Accessing an ACE Directly


This example describes how to work with the ACEs that make up the SACL and the DACL. By working with an ACE, you also learn how to use the SACL and DACL. Because you’re most likely to work with the DACL, this example emphasizes access over auditing. However, working with the ACEs in either structure is about the same. Listing 14.3 contains the essential elements that show how you’d access the ACEs for a file—the listing doesn’t include items like the function declarations. (You can find the complete source code for this example in the \Chapter 14\C#\GetGroupAccess or \Chapter 14\VB\GetGroupAccess folders of the source code located on the Sybex Web site.)

Listing 14.3 Gaining Access to the ACEs Means Reading the ACL

start example
private void btnTest_Click(object sender, System.EventArgs e) {    Boolean           DACLPresent;   // Is the DACL present?    Boolean           Defaulted;     // Is the DACL defaulted?    IntPtr            DACL;          // Pointer to the DACL.    Int32             Result;        // Result of a call.    UInt32            ACECount;      // Number of ACEs in DACL.    EXPLICIT_ACCESS   []ACEList;     // An array of ACE entries.    // Obtain a security descriptor containing the DACL.    if (!GetFileSD(txtFile.Text,       SECURITY_INFORMATION.DACL_SECURITY_INFORMATION))       return;    // Obtain the DACL.    DACLPresent = false;    Defaulted = false;    if (!GetSecurityDescriptorDacl(SecurityDescriptor,                                   ref DACLPresent,                                   out DACL,                                   ref Defaulted))    {       // Display an error message.       MessageBox.Show("Unable to retrieve the DACL.",                       "Application Error",                       MessageBoxButtons.OK,                       MessageBoxIcon.Error);       // Free the memory we allocated.       Marshal.FreeHGlobal(SecurityDescriptor);       return;    }    // Make sure there is a DACL to display.    if (!DACLPresent)    {       // If not, tell the user there is no DACL.       MessageBox.Show("There is no DACL.",                       "Processing Report",                       MessageBoxButtons.OK,                       MessageBoxIcon.Information);       // Free the memory we allocated.       Marshal.FreeHGlobal(SecurityDescriptor);       return;    }    // Obtain the array of ACEs from the DACL.    ACECount = 0;    Result = GetExplicitEntriesFromAcl(DACL,                                       ref ACECount,                                       out ACEList);    // Check the results.    if (Result != ERROR_SUCCESS)    {       // Display an error message.       MessageBox.Show("Unable to retrieve the ACEs.",                       "Application Error",                       MessageBoxButtons.OK,                       MessageBoxIcon.Error);       // Free the memory we allocated.       Marshal.FreeHGlobal(SecurityDescriptor);       return;    }    // Display the number of ACEs.    MessageBox.Show("The file has " + ACECount.ToString() +                    " ACEs attached to it.",                    "Number of ACEs",                    MessageBoxButtons.OK,                    MessageBoxIcon.Information);    // Free the memory we allocated.    Marshal.FreeHGlobal(SecurityDescriptor); }
end example

The code begins with a simple define—a reminder that the various Win32 API functions return different values. In this case, the GetExplicitEntriesFromAcl() function returns a value of ERROR_SUCCESS if successful or an error value if unsuccessful. You compare the return value with constants to determine the cause of the error.

Notice that the GetExplicitEntriesFromAcl() function is also unique in that it requires an array as input. You don’t define a specific number of array elements—just the fact that the return value is an array. The call will still work, in this case, whether you provide an IntPtr or a single EXPLICIT_ACCESS structure value. The difference is that you won’t actually be able to use the return value if you don’t use an array.

The EXPLICIT_ACCESS structure is relatively complex. It includes both an enumerated value and another structure, TRUSTEE. The other two values are flags—you have to go through a complicated comparison routine to determine what the flag values mean.

While the TRUSTEE structure looks relatively simple, it can become complex because it also includes enumerated values that determine what each of the fields in the structure mean. For example, the ptstrName variable only has meaning if the TRUSTEE_FORM enumeration value is TRUSTEE_IS_NAME. Matters are further complicated by hidden rules. The MULTIPLE_TRUSTEE_OPERATION should always equal NO_MULTIPLE_TRUSTEE because Microsoft hasn’t implemented this feature yet, or at least they haven’t documented it.

The GetSecurityDescriptorDacl() obtains the DACL. You should never change the security descriptor directly because other applications might try to access it at the same time. This function has an odd return value until you consider that most parts of the security descriptor are optional. The lpbDaclPresent tells you if the DACL is present in the security descriptor. The call can succeed even if the security descriptor doesn’t contain a DACL, so you need to know this additional information.

In general, the btnTest_Click() method doesn’t contain too many surprises. Of course, the first major call is to GetSecurityDescriptorDacl() because we have to check the security descriptor created with the GetFileSD() function for a DACL. If there’s no DACL, the application hasn’t actually experienced an error—it’s simply found an unprotected file. Consequently, you need to handle the return as a type of legitimate return value. It simply might not be the return value you were expecting.

The next call is to GetExplicitEntriesFromAcl(). Theoretically, the ACECount variable could contain a 0 on return, so you should check it. Again, it’s not an actual application error—the DACL could simply be empty. It’s unlikely that you’ll ever see this happen unless the GetExplicitEntriesFromAcl() function experiences some type of error.




.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