Securing Files


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 15.4 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 15.4 isn’t complete—it only contains the material not discussed in other areas and lacks the Win32 API function declarataions. (You can find the complete source code for this example in the \Chapter 15\C#\FileSecurity and \Chapter 15\VB\FileSecurity folders of the source code located on the Sybex Web site.)

Listing 15.4 One Technique for Accessing File Security Information

start example
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))    {       // Get the last error.       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))    {       // Get the last error.       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 // code appears in this area. See Listing 14.2 for an example of how to // convert a SID to a name. }
end example

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. 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 information.

Remember 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. Other functions such as GetSecurityDescriptorDacl() and GetSecurityDescriptorGroup() work 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 determines 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 you 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, you have a SID and can use the LookupAccountSid() function to retrieve the applicable information. Figure 15.3 shows the output from this example.


Figure 15.3: The example application will tell you who owns a particular file.




.Net Development Security Solutions
.NET Development Security Solutions
ISBN: 0782142664
EAN: 2147483647
Year: 2003
Pages: 168

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net