4.7 Accessing the security descriptor set on manageable entities


4.7 Accessing the security descriptor set on manageable entities

Now that we have a connection to the manageable entity, we are in a position to retrieve its associated security descriptor. Of course, since the access methods vary, the techniques to read the security descriptor also vary. Moreover, its encoded form, once retrieved, may also vary. This totally relies on the Microsoft ADSI and WMI capabilities. In this section, we will examine the coding techniques used with their conditions of use. The goals of Samples 4.14 through 4.24, which implement the GetSecurityDescriptor() function, are to always return a security descriptor in a manageable form, which means returning an ADSI or a WMI representation of the retrieved security descriptor.

4.7.1 Retrieving file and folder security descriptors

4.7.1.1 Retrieving file and folder security descriptors with WMI

To retrieve the structural representation of a security descriptor from a file or a folder, the Win32_LogicalFileSecuritySetting GetSecurityDescriptor method must be used.

It is important to note that the GetEffectivePermission method available from the CIM_DataFile class (but defined on the parent class, called CIM_ LogicalFile) determines whether the caller has the aggregated permissions specified by the permission argument, not only on the file system object but also on the share the file or directory resides on. At no time does this method retrieve a structural representation of the security descriptor.

The use of the Win32_LogicalFileSecuritySetting GetSecurityDescriptor method requires a WMI connection to the Root\CIMv2 namespace. This connection is already executed in Sample 4.3 ("Connecting to files and folders with WMI [Part I]"), which calls the GetSecurityDescriptor() function.

In the case of a WMI security descriptor access method, the parameters of the GetSecurityDescriptor() function represent (Sample 4.14, line 9):

  • An SWBemServices object representing the WMI connection to the Root\CIMv2 namespace (contained in the objConnection variable).

  • A string containing the file or folder path (contained in the strSource variable).

  • A value representing the security descriptor access method type (contained in the intSDType variable), which determines the security descriptor retrieval technique through a Select Case statement (line 21). This value is defined in the SecurityInclude.vbs included at line 155 of Sample 4.2 ("The WMIManageSD.Wsf framework to manage security descriptors from the command line"). The Select Case statement determines the execution of lines 26 through 42 for a WMI security descriptor access method for a file or a folder.

Sample 4.14: Retrieving file and folder security descriptors with WMI (Part I)

start example

   .:   .:   .:   8:'--------------------------------------------------------------------------------   9:Function GetSecurityDescriptor (objConnection, strSource, intSDType) ..: 21:     Select Case intSDType 22:' +----------------------------------------------------------------------------------------+ 23:' | File or Folder                                                                      | 24:' +----------------------------------------------------------------------------------------+ 25:           Case cFileViaWMI 26:' WMI retrieval technique ------------------------------------------------------------------ 27:                WScript.Echo "Reading File or Folder security descriptor via WMI from '" & _ 28:                             strSource & "'." 29:                Set objWMIInstance = objConnection.Get("Win32_LogicalFileSecuritySetting='" & _ 30:                                                       strSource & "'") ..: 33:                intRC = objWMIInstance.GetSecurityDescriptor (objSD) 34:                If intRC Then 35:                   WScript.Echo vbCRLF & "Failed to get File or Folder " & _ 36:                                "security descriptor from '" & strSource & "'." 37:                   WScript.Quit (1) 38:                End If ..: 42:' Here objSD contains a security descriptor in the WMI object model. 43: ...: 291:           Case Else 292: 293:    End Select 294: 295:    Set GetSecurityDescriptor = objSD ...: 299:End Function 

end example

With the SWBemServices object, the script retrieves an SWBemObject object representing an instance of the file specified by the file path name (lines 29 and 30). Next, the script invokes the GetSecurityDescriptor method of the Win32_LogicalFileSecuritySetting class to retrieve the security descriptor (line 33). Since the retrieved security descriptor is represented in a Win32_SecurityDescriptor instance, no further processing is necessary. The GetSecurityDescriptor() function ends its execution by returning the SWBemObject object representing the security descriptor instance (line 295).

4.7.1.2 Retrieving file and folder security descriptors with ADSI

To retrieve a file or folder security descriptor with ADSI (see Sample 4.15), we must distinguish if the script runs under Windows Server 2003, Windows XP, Windows 2000, or Windows NT. As mentioned in section 4.6.1.2 ("Connecting to files and folders with ADSI"), under Windows Server 2003 or Windows XP, the script uses the ADsSecurityUtility object. The SecurityMask property of this object specifies which component of the security descriptor must be retrieved with the GetSecurityDescriptor method invoked at line 55. The SecurityMask property requires a bitwise value, as defined in Table 4.7. By default, only the owner, the group, and the DACL components are retrieved. Because the ADsSecurityUtility GetSecurityDescriptor method can retrieve a security descriptor from a file, a file system share, or a registry key, this method requires parameters to:

Sample 4.15: Retrieving file and folder security descriptors with ADSI (Part II)

start example

 ..: ..: ..: 43: 44:           Case cFileViaADSI 45:' ADSI retrieval technique ----------------------------------------------------------------- 46:                WScript.Echo "Reading File or Folder security descriptor via ADSI from '" & _ 47:                             strSource & "'." 48: 49:                ' Windows Server 2003 only ------------------------------------------------- 50:                objADsSecurity.SecurityMask = ADS_SECURITY_INFO_OWNER Or _ 51:                                              ADS_SECURITY_INFO_GROUP Or _ 52:                                              ADS_SECURITY_INFO_DACL ' Or _ 53:                                              ' ADS_SECURITY_INFO_SACL 54: 55:                Set objSD = objADsSecurity.GetSecurityDescriptor(strSource, _ 56:                                                                 ADS_PATH_FILE, _ 57:                                                                 ADS_SD_FORMAT_IID) 58: 59:                ' Windows 2000 only -------------------------------------------------------- 60:                ' Set objSD = objADsSecurity.GetSecurityDescriptor("FILE://" & strSource) 61: 62:                If Err.Number Then 63:                   WScript.Echo vbCRLF & "Failed to get File or Folder " & _ 64:                                "security descriptor from '" & strSource & "'." 65:                   WScript.Quit (1) 66:                End If 67: 68:'  Here objSD contains a security descriptor in the ADSI object model. 69: ...: 291:           Case Else 292: 293:    End Select 294: 295:    Set GetSecurityDescriptor = objSD ...: 299:End Function 

end example

Table 4.7: The ADsSecurityUtility Constants

Security Descriptor Info

Name

Value

ADS_SECURITY_INFO_OWNER

0x1

ADS_SECURITY_INFO_GROUP

0x2

ADS_SECURITY_INFO_DACL

0x4

ADS_SECURITY_INFO_SACL

0x5

Security Descriptor format

Name

Value

ADS_SD_FORMAT_IID

1

ADS_SD_FORMAT_RAW

2

ADS_SD_FORMAT_HEXSTRING

3

Security Descriptor path

Name

Value

ADS PATH FILE

1

ADS_PATH_FILESHARE

2

ADS PATH REGISTRY

3

  • Specify the path of the entity to retrieve the security descriptor (line 55).

  • A constant (as defined in Table 4.7) to determine the nature of the specified path to retrieve (line 56).

  • A constant (as defined in Table 4.7) to determine the format of the retrieved security descriptor (line 57).

Under Windows 2000 (or Windows NT), the script uses the ADsSecurity object implemented by the ADsSecurity.DLL. This object also exposes a GetSecurityDescriptor method. However, the method requires one single parameter, which is the path of the entity to retrieve the security descriptor. The method uses a "FILE://" pointer to determine that the given path is a file or folder path (line 60). The ADsSecurity object does not retrieve the SACL component of a security descriptor and does not expose any Security-Mask property (or equivalent) to do so. Because both ADsSecurityUtility and ADsSecurity objects do not require a connection to the examined file or folder, this parameter is set to Null when calling the GetSecurityDescriptor() function (see Sample 4.4, line 587).

Once completed, the retrieved security descriptor is represented in the ADSI object model, as opposed to the WMI security descriptor access method, which returns a security descriptor in the WMI object model (see Sample 4.14, "Retrieving file and folder security descriptor with WMI [Part I]"). We take advantage of the variant variable type used in scripts to return different types of objects from the same function.

Note

By design, with the ADsSecurityUtility object it is possible to retrieve the security descriptor with its SACL component on the condition that the statement of line 53 is specified (ADS_SECURITY_INFO_SACL flag). Another requirement to retrieve the SACL of a security descriptor is that the SE_SECURITY_NAME privilege (also called SeSecurityPrivilege or the "Manage auditing and security log" privilege in the GPO) must be granted to the thread/process requesting access to the SACL. Despite the fact that you could run the script as a member of the Administrators group (which has the SE_SECURITY_NAME privilege enabled by default at the account level—see http://msdn.microsoft.com/library/en-us/security/security/sacl_access_right.asp), it is not granted by default at the thread/process level. Therefore, it is necessary for the thread/process to explicity enable this privilege as well. Unfortunately, at writing time, a bug located in the ADsSecurityUtility object of Windows Server 2003 and Windows XP does not allow the retrieval of the SACL component, even if the object has been designed for this purpose and even if the statement of line 53 is specified. If you execute the script with the ADS_SECURITY_INFO_SACL flag, the following error message will be returned:

 A required privilege is not held by the client. 

Actually, the ADsSecurityUtility object retrieving the security descriptor does not grant the ADS_SECURITY_INFO_SACL privilege. Therefore, it makes it impossible to retrieve the SACL component of the security descriptor.

Due to the timing issues, it is more than likely that Microsoft won't fix this bug for the release code of Windows Server 2003. However, it is possible to use a work-around by developing a small fix. I shared this issue with my colleague, Andr Larbi re from HP Belgium/Luxembourg, and after thinking about different approaches he developed a COM object that could be invoked during the script execution to enable the missing SE_SECURITY_NAME privilege. We won't enter into the details of the COM object development here, but we will see how it can be used from the WMIManageSD.Wsf script to work around this problem. Actually, its use is pretty simple. It requires three modifications. The first modification concerns the Sample 4.2 header, where the instantiation of the object enabling the SE_SECURITY_NAME privilege is added at line 195 (User-Right.Control object):

 ...: ...: ...: 186:     <reference object="ADs" version="1.0"/> 187: 188:     <!-- ***** Windows Server 2003 only ***** --> 189:     <object prog /> 190: 191:     <!-- ***** Windows 2000 only ***** --> 192:     <!-- <object prog /> --> 193: 194:     <object prog /> 195:     <object prog /> 196:     <object prog  reference="true"/> 197:     <object prog  /> 198: 199:     <!-- ***** Windows Server 2003 only ***** --> 200:     <object prog  /> 201: 202:     <!-- ***** Windows 2000 only *****--> 203:     <!-- <object prog  /> --> 204: 205:     <script language="VBscript"> 206:     <![CDATA[ ...: ...: ...: 

Next, we must make use of the UserRight.Control object in the WMIManageSD.Wsf script to enable the required privilege. The method exposed by this object to enable the privilege is only used where the ADsSecurityUtility object is referenced. This concerns several portions of the script code:

  • Sample 4.15 ("Retrieving file and folder security descriptor with ADSI [Part II]") and Sample 4.23 ("Retrieving registry keys security descriptor with ADSI [Part X]"), both located in the GetSecurityDescriptor() function.

  • Sample 4.52 ("Updating file and folder security descriptor with ADSI [Part II]") and Sample 4.60 ("Updating registry keys security descriptor with ADSI [Part X]"), both located in the SetSecurityDescriptor() function.

All samples are subject to the same modification. The following code shows how the script is modified based on Sample 4.15 ("Retrieving file and folder security descriptor with ADSI [Part II]"). The original code is as follows:

 ..: ..: ..: 48: 49:                ' Windows Server 2003 only ------------------------------------------------- 50:                objADsSecurity.SecurityMask = ADS_SECURITY_INFO_OWNER Or _ 51:                                              ADS_SECURITY_INFO_GROUP Or _ 52:                                              ADS_SECURITY_INFO_DACL ' Or _ 53:                                              ' ADS_SECURITY_INFO_SACL 54: 55:                Set objSD = objADsSecurity.GetSecurityDescriptor(strSource, _ 56:                                                                 ADS_PATH_FILE, _ 57:                                                                 ADS_SD_FORMAT_IID) 58: ..: ..: ..: 

and must be changed to (lines 54 and 58 in bold):

 ..: ..: ..: 48: 49:                ' Windows Server 2003 only ------------------------------------------------- 50:                objADsSecurity.SecurityMask = ADS_SECURITY_INFO_OWNER Or _ 51:                                         ADS_SECURITY_INFO_GROUP Or _ 52:                                         ADS_SECURITY_INFO_DACL ' Or _ 53:                                         ADS_SECURITY_INFO_SACL 54:                objADSIPriv.Enable "SeSecurityPrivilege" 55:                Set objSD = objADsSecurity.GetSecurityDescriptor(strSource, _ 56:                                                            ADS_PATH_FILE, _ 57:                                                            ADS_SD_FORMAT_IID) 58:                objADSIPriv.Disable "SeSecurityPrivilege" ..: ..: ..: 

Basically, this object is performing the exact same thing as the WMI wbemPrivilegeSecurity constant: It grants the SE_SECURITY_NAME privilege (also called SeSecurityPrivilege) to the process/thread. Note that the privilege is enabled before reading the security descriptor and disabled once it has been read.

If you don't plan to use this work-around (i.e., because you don't need to retrieve the SACL), to avoid this problem line 53 must be commented out. In such a case, only the WMI technique is able to retrieve the SACL of a file or folder security descriptor. If you do not need to retrieve the SACL of a file or a folder security descriptor, the native ADSI method is perfectly applicable without this work-around.

4.7.2 Retrieving file system share security descriptors

4.7.2.1 Retrieving file system share security descriptors with WMI

Regarding the file system shares, the Win32_Share class exposes (only under Windows Server 2003 or Windows XP) the GetAccessMask method to gather information about the share security settings. The GetAccessMask method returns the access rights of the share held by the user or group on whose behalf the instance is created. Unfortunately, this method does not return a structural representation of the share security descriptor.

On the other hand, the Win32_LogicalShareSecuritySetting class exposes an equivalent method as the GetSecurityDescriptor method of the Win32_LogicalFileSecuritySetting class. This method retrieves a structural representation of the share security descriptor. Sample 4.16 illustrates this logic. The script retrieves an instance of the Win32_LogicalShareSecuritySetting class in an SWBemObject object (lines 77 and 78). When a share is created, it is not necessarily created with a security descriptor. In such a case, the share always has a default security setting, even if no security descriptor exists. The default security grants everyone full control. Note that it is the default behavior under Windows NT 4.0 and Windows 2000. However, under Windows XP and Windows Server 2003, the default is everyone read-only. Because the Win32_LogicalShareSecuritySetting instance can only be retrieved with the condition that a security descriptor is set, the script manages the situation by testing the error return code of the instance retrieval (lines 79 and 80).

Sample 4.16: Retrieving file system share security descriptors with WMI (Part III)

start example

 ..: ..: ..: 69: 70:' +----------------------------------------------------------------------------------------+ 71:' | Share                                                                              | 72:' +----------------------------------------------------------------------------------------+ 73:           Case cShareViaWMI 74:' WMI retrieval technique ------------------------------------------------------------------ 75:                WScript.Echo "Reading Share security descriptor via WMI from '" & _ 76:                             strSource & "'." 77:                Set objWMIInstance = objConnection.Get("Win32_LogicalShareSecuritySetting='" & 78:                                                       strSource & "'") 79:                If Err.Number = wbemErrNotFound Then 80:                   Err.Clear 81:                   Set objSD = CreateDefaultSD (objConnection, intSDType) 82:                Else 83:                   If Err.Number Then ErrorHandler (Err) 84: 85:                   intRC = objWMIInstance.GetSecurityDescriptor (objSD) 86:                   If intRC Then 87:                      WScript.Echo vbCRLF & "Failed to get Share security descriptor from '" & 88:                                   strSource & "'." 89:                      WScript.Quit (1) 90:                   End If 91:                End If ..: 95:' Here objSD contains a security descriptor in the WMI object model. 96: ...: 291:           Case Else 292: 293:    End Select 294: 295:    Set GetSecurityDescriptor = objSD ...: 299:End Function 

end example

If no instance of this class can be retrieved, it likely means that no specific security is set, which implies the creation of a default security descriptor (line 80) by calling the CreateDefaultSD() function. This function will be examined later in section 4.8 ("Creating a default security descriptor"). If the file system share has a security descriptor set, the script invokes the GetSecurityDescriptor method and retrieves the security descriptor in a Win32_SecurityDescriptor instance (line 85). The end result is the representation of the file system share security descriptor in the WMI object model (line 295).

4.7.2.2 Retrieving file system share security descriptors with ADSI

To retrieve a security descriptor from a file system share via ADSI, the overall logic is basically the same. However, in the details, we must consider some peculiarities:

  • It is only possible to retrieve a share security descriptor under Windows Server 2003 (or Windows XP), since these platforms implement the ADSI ADsSecurityUtility object.

  • Managing the owner, the group, and the SACL components is not applicable to a share.

Once these restrictions are clearly identified, the script logic is pretty simple (see Sample 4.17). With the GetSecurityDescriptor method (line 103) and its correct parameters (as defined in Table 4.7), the script will retrieve the security descriptor in the ADSI object model. If there is no security descriptor set on the share because it uses the default security, then the script creates a default ADSI security descriptor (line 109). Once completed, the GetSecurityDescriptor() function returns the ADSI security descriptor (line 295).

Sample 4.17: Retrieving file system share security descriptors with ADSI (Part IV)

start example

 ..: ..: ..: 96: 97:           Case cShareViaADSI 98:' ADSI retrieval technique ----------------------------------------------------------------- 99:                WScript.Echo "Reading Share security descriptor via ADSI from '" & _ 100:                            strSource & "'." 101: 102:               ' Windows Server 2003 only ------------------------------------------------- 103:               Set objSD = objADsSecurity.GetSecurityDescriptor(strSource, _ 104:                                                                ADS_PATH_FILESHARE, _ 105:                                                                ADS_SD_FORMAT_IID) 106: 107:               If Err.Number Then 108:                  Err.Clear 109:                  Set objSD = CreateDefaultSD (vbNull, intSDType) 110:               End If 111: 112:' Here objSD contains a security descriptor in the ADSI object model. 113: ...: 291:           Case Else 292: 293:    End Select 294: 295:    Set GetSecurityDescriptor = objSD ...: 299:End Function 

end example

4.7.3 Retrieving Active Directory object security descriptors

4.7.3.1 Retrieving Active Directory object security descriptors with WMI

The access to a security descriptor of an Active Directory object with WMI is a little bit more challenging. The GetSecurityDescriptor() function requires an SWBemServices object, which represents a connection to the CIM repository namespace giving access to Active Directory. As we have seen before, this connection is performed in Sample 4.7 ("Connecting to Active Directory objects with WMI [Part V]"). Next, the distinguishedName of the desired object must be correctly parsed. As a reminder, the script command-line parameters executing this portion of the code would be as follows:

 C:\>WMIManageSD.Wsf /ADObject:"user;CN=MyUser,CN=Users,DC=LissWare, DC=Net" 

At line 119, the script invokes the ConvertStringInArray() function to split the Active Directory object class from the object distinguishedName. Once complete, the returned array contains the Active Directory object class in element 0 and the distinguishedName in element 1. With this information, the script retrieves an instance of the specified Active Directory object (lines 132 through 134). For instance, the previous command line will create the following WMI path:

 ds_user.ADSIPath='LDAP://CN=MyUser,CN=Users,DC=LissWare,DC=Net'") 

Once the Active Directory object instance is retrieved in an SWBemObject object, the script gets access to all attributes of the Active Directory object as represented by WMI. The security descriptor of an Active Directory object is contained in the nTSecurityDescriptor attribute. Doing so, the script reads the value of the DS_nTSecurityDescriptor property exposed by WMI. Unfortunately, things are not so easy, because the security descriptor contained in this SWBemObject object property is in the form of an SWBemNamedValue object. This SWBemNamedValue object exposes a property called Value, which contains the security descriptor in a binary array (line 144). To get the security descriptor in a usable form, the script invokes the ConvertRawSDToAdsiSD method exposed by the ADSIHelper object (line 144). The ADSIHelper object is instantiated in Sample 4.2 at line 194. We will come back to the ADSIHelper object in section 4.9 ("The security descriptor conversion"). The end result is a security descriptor represented in the ADSI object model. In this particular case, we have a mixed situation, since the script uses a WMI access method, which, in the end, returns an ADSI security descriptor (line 295).

Sample 4.18: Retrieving Active Directory object security descriptors with WMI (Part V)

start example

 ...: ...: ...: 113: 114:' +----------------------------------------------------------------------------------------+ 115:' | Active Directory object | 116:' +----------------------------------------------------------------------------------------+ 117:           Case cActiveDirectoryViaWMI 118:' WMI retrieval technique ------------------------------------------------------------------ 119:                arrayADInfo = ConvertStringInArray (strSource, ";") 120:                If Ubound(arrayADInfo) <> 1 Then 121:                   WScript.Echo "The Active Directory class and object distinguished name " & _ 122:                                "must be specified as follow:" & vbCRLF & vbCRLF & _ 123:                                "/ADObject:""Objectclass;CN=MyObject," & _ 124:                                "CN=Users,DC=LissWare,DC=Net""" 125:                   WScript.Quit (1) 126:                End If 127: 128:                WScript.Echo "Reading " & LCase(arrayADInfo(0)) & " Active Directory " & _ 129:                             "object security descriptor via WMI from 'LDAP://" & _ 130:                             arrayADInfo(1) & "'." 131: 132:                Set objWMIInstance = objConnection.Get("ds_" & LCase(arrayADInfo(0)) & _ 133:                                                       ".ADSIPath='LDAP://" &_ 134:                                                       arrayADInfo(1) & "'") ...: 137:                Set objSD = objWMIInstance.DS_nTSecurityDescriptor 138:                If Err.Number Then 139:                   Err.Clear 140:                   WScript.Echo vbCRLF & "Failed to get Active Directory object " & _ 141:                                "security descriptor from 'LDAP://" & strSource & "'." 142:                   WScript.Quit (1) 143:                Else 144:                   Set objSD = objADSIHelper.ConvertRawSDToAdsiSD (objSD.Value) 145:                   If Err.Number Then ErrorHandler (Err) 146:                End If ...: 150:' Here objSD contains a security descriptor in the ADSI object model. 151: ...: 291:           Case Else 292: 293:    End Select 294: 295:    Set GetSecurityDescriptor = objSD ...: 299:End Function 

end example

4.7.3.2 Retrieving Active Directory object security descriptors with ADSI

Retrieving a security descriptor from an Active Directory object with ADSI is, of course, a more natural technique, since ADSI is especially designed for Active Directory accesses. Despite this fact, there are some things we must still take into consideration. Sample 4.19 illustrates this technique. Although the script uses ADSI, it is required to have a connection to the Active Directory object (called an object binding in the LDAP world). This object binding is established in Sample 4.8 ("Connecting to Active Directory objects with ADSI [Part VI]") and passed in the objConnection variable to the GetSecurityDescriptor() function. Basically, this object represents the Active Directory object in the ADSI object model. From this object, the script retrieves the ntSecurityDescriptor attribute (line 161). To retrieve the SACL component, the script must initialize the SetOption property of this object (lines 156 through 159). The SetOption property works in the same way as the SecurityMask property of the ADsSecurityUtility object. There is no difference between the two properties, but the SetOption property is exposed by the ADSI representation of the Active Directory object. Once completed, the GetSecurityDescriptor() function returns an ADSI representation of the Active Directory object security descriptor (line 295).

Sample 4.19: Retrieving Active Directory object security descriptors with ADSI (Part VI)

start example

 ...: ...: ...: 151: 152:           Case cActiveDirectoryViaADSI 153:' ADSI retrieval technique ----------------------------------------------------------------- 154:                WScript.Echo "Reading Active Directory object security descriptor " & _ 155:                             "via ADSI from 'LDAP://" & strSource & "'." 156:                objConnection.SetOption ADS_OPTION_SECURITY_MASK, ADS_SECURITY_INFO_OWNER Or _ 157:                                                                  ADS_SECURITY_INFO_GROUP Or _ 158:                                                                  ADS_SECURITY_INFO_DACL Or _ 159:                                                                  ADS_SECURITY_INFO_SACL 160: 161:                Set objSD = objConnection.Get("ntSecurityDescriptor") 162:                If Err.Number Then 163:                   Err.Clear 164:                   WScript.Echo vbCRLF & "Failed to get Active Directory object " & _ 165:                                "security descriptor from 'LDAP://" & strSource & "'." 166:                   WScript.Quit (1) 167:                End If 168: 169:' Here objSD contains a security descriptor in the ADSI object model. 170: ...: 291:           Case Else 292: 293:    End Select 294: 295:    Set GetSecurityDescriptor = objSD ...: 299:End Function 

end example

4.7.4 Retrieving Exchange 2000 mailbox security descriptors

4.7.4.1 Retrieving Exchange 2000 mailbox security descriptors with WMI

Retrieving the Exchange 2000 mailbox security descriptor with WMI (Sample 4.20) follows the same logic as retrieving an Active Directory object security descriptor (Sample 4.18). However, only user objects are accessed, and, instead of reading the DS_nTSecurityDescriptor property of the SWBemObject object representing the Active Directory object instance, the script must read the DS_msExchMailboxSecurityDescriptor property (line 182). As in Sample 4.18 ("Retrieving Active Directory object security descriptors with WMI [Part V]"), the security descriptor is finally retrieved in a binary array and must be converted with the help of the ConvertRawSDToAdsiSD method exposed by the ADSIHelper object (line 189). Once completed, the GetSecurityDescriptor() function returns an ADSI security descriptor representation accessed by WMI (line 295).

Sample 4.20: Retrieving Exchange 2000 mailbox security descriptors with WMI (Part VII)

start example

 ...: ...: ...: 170: 171:' +----------------------------------------------------------------------------------------+ 172:' | Exchange 2000 mailbox | 173:' +----------------------------------------------------------------------------------------+ 174:           Case cExchange2000MailboxViaWMI 175:' WMI retrieval technique ------------------------------------------------------------------ 176:                WScript.Echo "Reading Exchange 2000 mailbox security descriptor " & _ 177:                             "via WMI from 'LDAP://" & strSource & "'." 178:                Set objWMIInstance = objConnection.Get("ds_user.ADSIPath='LDAP://" & _ 179:                                                       strSource & "'") ...: 182:                Set objSD = objWMIInstance.DS_msExchMailboxSecurityDescriptor 183:                If Err.Number Then 184:                   Err.Clear 185:                   WScript.Echo vbCRLF & "Failed to get Exchange 2000 mailbox " & _ 186:                                         "security descriptor from 'LDAP://" & strSource & "'." 187:                   WScript.Quit (1) 188:                Else 189:                   Set objSD = objADSIHelper.ConvertRawSDToAdsiSD (objSD.Value) 190:                   If Err.Number Then ErrorHandler (Err) 191:                End If ...: 195:' Here objSD contains a security descriptor in the ADSI object model. 196: ...: 291:           Case Else 292: 293:    End Select 294: 295:    Set GetSecurityDescriptor = objSD ...: 299:End Function 

end example

4.7.4.2 Retrieving Exchange 2000 mailbox security descriptors with ADSI

Retrieving an Exchange 2000 mailbox security descriptor with ADSI is as simple as retrieving an Active Directory object security descriptor. Instead of accessing the ntSecurityDescriptor attribute, the script must retrieve the msExchMailboxSecurityDescriptor attribute (Sample 4.21, line 206). To ensure that all components of the security descriptor are retrieved, the script initializes the SetOption property of the Active Directory object (lines 201 through 204).

Sample 4.21: Retrieving Exchange 2000 mailbox security descriptors with ADSI (Part VIII)

start example

 ...: ...: ...: 196: 197:           Case cExchange2000MailboxViaADSI 198:' ADSI retrieval technique ----------------------------------------------------------------- 199:                WScript.Echo "Reading Exchange 2000 mailbox security descriptor " & _ 200:                             "via ADSI from 'LDAP://" & strSource & "'." 201:                objConnection.SetOption ADS_OPTION_SECURITY_MASK, ADS_SECURITY_INFO_OWNER Or _ 202:                                                                  ADS_SECURITY_INFO_GROUP Or _ 203:                                                                  ADS_SECURITY_INFO_DACL Or _ 204:                                                                  ADS_SECURITY_INFO_SACL 205: 206:                Set objSD = objConnection.Get("msExchMailboxSecurityDescriptor") 207:                If Err.Number Then 208:                   Err.Clear 209:                   WScript.Echo vbCRLF & "Failed to get Exchange 2000 mailbox " & _ 210:                                "security descriptor from 'LDAP://" & strSource & "'." 211:                   WScript.Quit (1) 212:                End If 213: 214:' Here objSD contains a security descriptor in the ADSI object model. 215: ...: 291:           Case Else 292: 293:    End Select 294: 295:    Set GetSecurityDescriptor = objSD ...: 299:End Function 

end example

4.7.4.3 Retrieving Exchange 2000 mailbox security descriptors with CDOEXM

If Exchange 2000 Service Pack 2 is installed, it is possible to retrieve the Exchange 2000 mailbox security descriptors with CDOEXM. Since CDOEXM acts as an extension for ADSI, the coding technique is very similar to the ADSI coding in Sample 4.21. However, instead of accessing the security descriptor stored in the Active Directory, the CDOEXM method accesses the security descriptor stored in the Exchange store. Actually, both security descriptors are the same, but the Active Directory security descriptor is the mirror of the one in the Exchange store. This will be very important when updating the Exchange 2000 mailbox security descriptors (see section 4.13.4.3, "Updating Exchange 2000 mailbox security descriptors with CDOEXM").

To get the mailbox security descriptor, the script reads the MailboxRights property exposed by the IExchangeMailbox CDOEXM interface (line 220). The end result is a security descriptor in the ADSI object model (line 295).

Sample 4.22: Retrieving Exchange 2000 mailbox security descriptors with CDOEXM (Part IX)

start example

 ...: ...: ...: 215: 216:           Case cExchange2000MailboxViaCDOEXM 217:' CDOEXM retrieval technique --------------------------------------------------------------- 218:                WScript.Echo "Reading Exchange 2000 mailbox security descriptor " & _ 219:                             "via CDOEXM from 'LDAP://" & strSource & "'." 220:                Set objSD = objConnection.MailboxRights 221:                If Err.Number Then 222:                   Err.Clear 223:                   WScript.Echo vbCRLF & "Failed to get Exchange 2000 mailbox " & _ 224:                                "security descriptor from 'LDAP://" & strSource & "'." 225:                   WScript.Quit (1) 226:                End If 227: 228:' Here objSD contains a security descriptor in the ADSI object model. 229: ...: 291:           Case Else 292: 293:    End Select 294: 295:    Set GetSecurityDescriptor = objSD ...: 299:End Function 

end example

4.7.5 Retrieving registry key security descriptors with ADSI

In Chapter 3 (section 3.3.3, "Registry providers"), we saw that WMI implements a WMI Registry provider to support the StdRegProv class. Unfortunately, this class does not implement a method to retrieve a structural representation of a security descriptor. The only method that gives information about the registry key security is the CheckAccess method. This method verifies that the user invoking the method possesses the specified permissions. Although useful, this WMI method does not suit the needs of the WMIManageSD.Wsf script. We must use an alternate tactic implemented by ADSI to retrieve the desired information.

To retrieve a registry key security descriptor with ADSI (see Sample 4.23), we must determine if the script runs under Windows XP, Windows Server 2003, Windows 2000, or Windows NT. The selected platform determines the use of the ADsSecurityUtility object of Windows XP and Windows Server 2003 (lines 243 through 251) or the ADsSecurity object of Windows 2000 and Windows NT 4.0 (line 254). Under Windows Server 2003, to retrieve the SACL component of the security descriptor, the SecurityMask property of the ADsSecurityUtility must be initialized (lines 244 through 247). Once complete, the script retrieves the registry key security descriptor by invoking the GetSecurityDescriptor method of the ADsSecurityUtility object (lines 249 through 251). The method uses the required parameters, as specified in Table 4.7 ("The ADsSecurityUtility Constants").

Sample 4.23: Retrieving registry key security descriptors with ADSI (Part X)

start example

 ...: ...: ...: 229: 230:' +----------------------------------------------------------------------------------------+ 231:' | Registry key | 232:' +----------------------------------------------------------------------------------------+ 233:           Case cRegistryViaWMI 234:' WMI retrieval technique ------------------------------------------------------------------ 235: 236:' Here we can't retrieve a security descriptor via this access method. 237: 238:           Case cRegistryViaADSI 239:' ADSI retrieval technique ----------------------------------------------------------------- 240:                WScript.Echo "Reading registry security descriptor " & _ 241:                             "via ADSI from '" & strSource & "'." 242: 243:                ' Windows Server 2003 only ------------------------------------------------ 244:                objADsSecurity.SecurityMask = ADS_SECURITY_INFO_OWNER Or _ 245:                                              ADS_SECURITY_INFO_GROUP Or _ 246:                                              ADS_SECURITY_INFO_DACL ' Or _ 247:                                              ' ADS_SECURITY_INFO_SACL 248: 249:                Set objSD = objADsSecurity.GetSecurityDescriptor(strSource, _ 250:                                                                 ADS_PATH_REGISTRY, _ 251:                                                                 ADS_SD_FORMAT_IID) 252: 253:                ' Windows 2000 only -------------------------------------------------------- 254:                ' Set objSD = objADsSecurity.GetSecurityDescriptor("RGY://" & strSource) 255: 256:                If Err.Number Then 257:                   WScript.Echo vbCRLF & "Failed to get registry security descriptor " & _ 258:                                "from '" & strSource & "'." 259:                   WScript.Quit (1) 260:                End If 261: 262:' Here objSD contains a security descriptor in the ADSI object model. 263: ...: 291:           Case Else 292: 293:    End Select 294: 295:    Set GetSecurityDescriptor = objSD 299:End Function 

end example

Since the ADsSecurityUtility object is subject to a bug under Windows Server 2003 and Windows XP, don't forget to refer to section 4.7.1.2 ("Retrieving file and folder security descriptors with ADSI"). If the work-around explained in that section is not used, and since the WMI technique is not able to retrieve a structural representation of a registry key security decriptor, there will be no way to retrieve the SACL of registry key security descriptors from the scripting world with the current ADSI COM objects.

Under Windows 2000 (or Windows NT), the GetSecurityDescriptor method of the ADsSecurity object is invoked (line 254). As mentioned before, no SACL component can be retrieved with this object. Once finished, the GetSecurityDescriptor() function returns the registry key security descriptor in the ADSI object model (line 295).

4.7.6 Retrieving CIM repository namespace security descriptors with WMI

To retrieve the security descriptor of a CIM repository namespace, the script must refer to a WMI system class called __SystemSecurity. As usual, to get access to an instance of a class, the script must connect to its corresponding CIM repository namespace. In this case, the script will be connected to the namespace from which we must retrieve the security descriptor. This connection is made in Sample 4.13 ("Connecting to CIM repository namespaces with WMI [Part XI]"), which provides an SWBemServices object to the GetSecurityDescriptor() function. From this connection, Sample 4.24 retrieves an instance of the __SystemSecurity class (line 271). Note that the __SystemSecurity class is a singleton class, which makes sense, since WMI implements one security descriptor per namespace. To get the namespace security descriptor, the __SystemSecurity class exposes the GetSD method (line 274). Unfortunately, things are not straightforward. The retrieved security descriptor has the format of a binary array, which forces the script to convert it to an ADSI security descriptor with the help of the ADSIHelper object (line 280). As a reminder, the ADSIHelper object is instantiated in Sample 4.2 at line 194. We will come back to the ADSIHelper object in section 4.9 ("The security descriptor conversion"). Once completed, the GetSecurityDescriptor() function returns a CIM repository namespace security descriptor retrieved with WMI but formatted as an ADSI security descriptor (line 295).

Sample 4.24: Retrieving CIM repository namespace security descriptors with WMI (Part XI)

start example

 ...: ...: ...: 263: 264:' +----------------------------------------------------------------------------------------+ 265:' | CIM repository namespace | 266:' +----------------------------------------------------------------------------------------+ 267:           Case cWMINameSpaceViaWMI 268:' WMI retrieval technique ------------------------------------------------------------------ 269:              WScript.Echo "Reading CIM repository namespace security descriptor via WMI from '" & _ 270:                            strSource & "'." 271:                Set objWMIInstance = objConnection.Get ("__SysetmSecurity=@") ...: 274:                intRC = objWMIInstance.GetSD (arrayBytes) 275:                If intRC Then 276:                   WScript.Echo vbCRLF & "Failed to get CIM repository namespace security " & _ 277:                                "descriptor from '" & strSource & "'." 278:                   WScript.Quit (1) 279:                Else 280:                   Set objSD = objADSIHelper.ConvertRawSDToAdsiSD (arrayBytes) 281:                   If Err.Number Then ErrorHandler (Err) 282:                End If 283: 284:' Here objSD contains a security descriptor in the ADSI object model. 285: 286:           Case cWMINameSpaceViaADSI 287:' ADSI retrieval technique ----------------------------------------------------------------- 288: 289:' Here we can't retrieve a security descriptor via this access method. 290: 291:           Case Else 292: 293:    End Select 294: 295:    Set GetSecurityDescriptor = objSD ...: 299:End Function 

end example




Leveraging WMI Scripting
Leveraging WMI Scripting: Using Windows Management Instrumentation to Solve Windows Management Problems (HP Technologies)
ISBN: 1555582990
EAN: 2147483647
Year: 2003
Pages: 82
Authors: Alain Lissoir

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