Using the Get FileSecurity Function Example

One of the problems that many developers have noted with the .NET Framework security is a lack of access to file (and other object) security information. For example, it's hard to tell who owns a file without using the Win32 API calls. That's where the GetFileSecurity() function comes into play. It enables you to retrieve file security information in the form of a security descriptor. From the theoretical discussion earlier in the chapter, you know that the security descriptor contains just about every piece of security information that Windows can supply. The example shown in Listing 8.2 shows how to obtain the owner identification for a file. However, the same techniques can help you obtain the SACL, DACL, and other security elements. The source in Listing 8.2 isn't complete—it contains only the material we haven't discussed in other areas. See the source code in the \Chapter 08\C#\FileSecurity and \Chapter 08\VB\FileSecurity folders of the CD for details.

Listing 8.2: One Technique for Accessing File Security Information

// This function retrieves the security information for a file. [DllImport("AdvAPI3 2.DLL", CharSet=CharSet.Auto, SetLastError=true )] public static extern bool GetFileSecurity( String lpFileName,

SECURITY_INFORMATION RequestedInformation,

IntPtr pSecurityDescriptor,

Int32 nLength, ref Int32 lpnLengthNeeded);

// This enumeration tells what type of information we want to retrieve // about the file's security.

public enum SECURITY_INFORMATION : uint {

OWNER_SECURITY_INFORMATION GROUP_SECURITY_INFORMATION DACL_SECURITY_INFORMATION SACL_SECURITY_INFORMATION PROTECTED_DACL_SECURITY_INFORMATION PROTECTED_SACL_SECURITY_INFORMATION UNPROTECTED_DACL_SECURITY_INFORMATION UNPROTECTED_SACL_SECURITY_INFORMATION

0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x80000000, 0x40000000, 0x20000000, 0x10000000

// This function retrieves the security descriptor for the // file owner.

[DllImport("AdvAPI3 2.DLL", CharSet=CharSet.Auto, SetLastError=true public static extern bool GetSecurityDescriptorOwner( IntPtr pSecurityDescriptor, out IntPtr pOwner, ref Boolean lpbOwnerDefaulted);

private void btnTest_Click(object sender, {

System.EventArgs e)

private void btnTest_Click(object sender, {

System.EventArgs e)

IntPtr

SecurityDescriptor;

//

File security information.

Int32

SDSize;

//

Security descriptor size.

Int32

SDSizeNeeded;

//

Required security desc. size

int

LastError;

//

Last Win32 API error.

IntPtr

OwnerSID;

//

SID of the owner account.

Boolean

IsDefault;

//

Is this a defaulted account?

Int32

NameSize;

//

Size of the account name.

Int32

DomainSize;

//

Size of the domain name.

StringBuilder

Name;

//

Account name.

StringBuilder

Domain;

//

Domain name.

SID NAME USE

Use;

//

Account use.

// Determine the size of the security descriptor. SecurityDescriptor = new IntPtr(0); SDSizeNeeded = 0; GetFileSecurity(@txtFile.Text,

SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION, SecurityDescriptor, 0, ref SDSizeNeeded);

// Allocate the memory required for the security descriptor. SecurityDescriptor = Marshal.AllocHGlobal(SDSizeNeeded); SDSize = SDSizeNeeded;

// Get the security descriptor.

if (!GetFileSecurity(@txtFile.Text,

SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION, SecurityDescriptor, SDSize, ref SDSizeNeeded))

LastError = Marshal.GetLastWin32Error();

// Display an error message and exit if not successful. MessageBox.Show("Error obtaining the security descriptor." + "\r\nLast Error: " + LastError.ToString(), "Application Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

// Free the memory we allocated. Marshal.FreeHGlobal(SecurityDescriptor);

// Exit the routine. return;

// Obtain the owner SID for the file. IsDefault = false;

if (!GetSecurityDescriptorOwner(SecurityDescriptor, out OwnerSID, ref IsDefault))

LastError = Marshal.GetLastWin32Error();

// Display an error message and exit if not successful. MessageBox.Show("Error obtaining the owner SID." +

"\r\nLast Error: " + LastError.ToString(), "Application Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

// Free the memory we allocated. Marshal.FreeHGlobal(SecurityDescriptor);

// Exit the routine. return;

// Code to obtain the user information from the SID and some display

The GetFileSecurity() function retrieves a security descriptor for the file requested by lpFileName. However, the function doesn't retrieve a complete security descriptor. It instead asks you to supply a SECURITY_INFORMATION enumeration value that chooses one of several pieces of a standard security descriptor. This means that the call must match the data you want to work with later. Notice that the SECURITY_INFORMATION enumeration contains all of the elements we discussed in the theoretical portion of the chapter. You must also provide a buffer pointer and the buffer length. The GetFileSecurity() function returns the security descriptor that you requested and the amount of buffer space needed to store the

Remember that we discussed the fact that you should never work with the security descriptor directly, but instead use the Win32 API-supplied functions. The GetSecurityDescriptorOwner() function will retrieve owner information from a security descriptor if such information exists. There are also other functions, such as GetSecurityDescriptorDacl() and GetSecurityDescriptorGroup(), for retrieving other elements of the security descriptor. The GetSecurityDescriptorOwner() function accepts a security descriptor as input and returns a SID containing the owner information.

The code actually calls the GetFileSecurity() function twice. The first call is used to determine the size of the buffer needed to hold the security descriptor. The second call retrieves the security descriptor if the buffer is large enough to hold the data. Notice that this code uses the Marshal.AllocHGlobal() function to allocate the buffer for the SecurityDescriptor buffer.

Once the code obtains a security descriptor, it uses the GetSecurityDescriptorOwner() function to retrieve the SID. Notice that this second function accepts the uninitialized OwnerSID as an out value. If you try to initialize OwnerSID and send it as we did for the GetFileSecurity() function, the function will fail with an invalid parameter error. The GetSecurityDescriptorOwner() function points out that you won't always interact with the Win32 API functions in the same way. Be prepared to send an initialized variable in one case and an uninitialized in other cases. At this point, we have a SID and can use the LookupAccountSid() function to retrieve the applicable information. Figure 8.7 shows the output from this example.

Getfilesecurity

igure 8.7: The example application will tell you who owns a particular file on the hard drive.

Was this article helpful?

+1 -1

Responses

  • jeffrey pauline
    How to use getfilesecurity?
    8 years ago
  • peter
    How to use c# and GetFileSecurity function?
    5 years ago

Post a comment