4.13 Updating the security descriptor


4.13 Updating the security descriptor

Now that the security descriptors can be read from protected entities via WMI or ADSI, their components, such as the Control Flags, can be updated; ACEs can be added and removed from DACL or SACL, but security descriptors must be saved back to the protected entities to make the security change effective. Because the security descriptor access methods differ if they come from a file, Active Directory, or a CIM repository namespace, the object model used to save security descriptors will be the same as the one used to read the security descriptor. Of course, even if the object model remains the same to save the security descriptor, the invoked method will be different. In the next sections, we will see how the security descriptor can be saved back to a protected entity in regard to its origin and the object model used.

4.13.1 Updating file and folder security descriptors

In section 4.7.1 ("Retrieving file and folder security descriptor"), both object models offered an access method to read a security descriptor. To save the security descriptor back to the file system, both object models will be considered in the same way.

4.13.1.1 Updating file and folder security descriptors with WMI

In Chapter 2, when we worked with the CIM_LogicalFile class supported by the Win32 provider, although we didn't use all methods, we discussed the methods exposed by this class (see Table 2.17, "The CIM_LogicalFile Methods") to change the security permissions. We had:

  • The ChangeSecurityPermissions or ChangeSecurityPermissionsEx methods: These methods change the security permissions for the logical file specified in the object path. If the logical file is a folder, then ChangeSecurityPermissions will act recursively, changing the security permissions of all files and subfolders the folder contains.

  • The TakeOwnerShip or TakeOwnerShipEx methods: These methods obtain ownership of the logical file specified in the object path. If the logical file is actually a directory, then TakeOwnerShip acts recursively, taking ownership of all the files and subdirectories the directory contains. We already demonstrated the TakeOwnerShipEx method in Chapter 2, with Sample 2.36.

On the other hand, the Win32_LogicalFileSecuritySetting class, supported by the Security provider, exposes two methods to retrieve and update the security descriptor:

  • GetSecurityDescriptor method: Retrieves a structural representation of the object's security descriptor.

  • SetSecurityDescriptor method: Replaces a structural representation of the object's security descriptor.

Although the methods from the Win32_LogicalFileSecuritySetting and CIM_LogicalFile classes seem to be redundant, they are not! The CIM_LogicalFile ChangeSecurityPermissions method is able to change one or several security descriptor subcomponents (owner, group, Discretionary ACL, or System ACL) recursively in a File System directory tree. On the other hand, the Win32_LogicalFileSecuritySetting SetSecurityDescriptor method replaces the complete structural representation of a security descriptor of a file or a directory object represented by a Win32_LogicalFileSecuritySetting instance (see Sample 4.51).

Sample 4.51: Updating file and folder security descriptors with WMI (Part I)

start example

  .:  .:  .:  8:' ------------------------------------------------------------------------------------------  9:Function SetSecurityDescriptor (objConnection, objSD, strSource, intSDType) ..: 21:    SetSecurityDescriptor = False 22: 23:    Select Case intSDType 24:' +----------------------------------------------------------------------------------------+ 25:' | File or Folder                                                                     | 26:' +----------------------------------------------------------------------------------------+ 27:           Case cFileViaWMI 28:' WMI update technique --------------------------------------------------------------------- 29: 30:' Here objSD contains a security descriptor in the WMI object model. 31: 32:                WScript.Echo "Setting File or Folder security descriptor via WMI to '" & _ 33:                             strSource & "'." 34: 35:                ' Set objWMIInstance = objConnection.Get("CIM_LogicalFile='" & strSource & "'") ..: 38:                ' intRC = objWMIInstance.ChangeSecurityPermissionsEx (objSD, _ 39:                '                                                     13, 40:                '                                                     Null, _ 41:                '                                                     Null, _ 42:                '                                                     True) 43: 44:                Set objWMIInstance = objConnection.Get("Win32_LogicalFileSecuritySetting='" & 45:                                     strSource & "'") ..: 48:                intRC = objWMIInstance.SetSecurityDescriptor (objSD) 49: 50:                If intRC Then 51:                   WScript.Echo vbCRLF & "Failed to set File or Folder security " & _ 52:                                "descriptor to '" & strSource & "' (" & intRC & ")." 53:                Else 54:                   SetSecurityDescriptor = True 55:                End If ..: ..: ..: 

end example

By default, the code replaces the structural representation of the security descriptor (lines 44 through 48). However, the commented out lines 35 through 42 show the coding technique to use if you do want to make a recursive replacement with the ChangeSecurityPermissionsEx method of the CIM_LogicalFile class. Note that the ChangeSecurityPermissionsEx method does not necessarily replace the whole security descriptor. A set of flags, listed in Table 4.26, determines which part of the security descriptor needs to be replaced.

Table 4.26: The ChangeSecurityPermissionsEx Method Flags for the Security Descriptor Recursive Update

ChangeSecurityPermissionsEx flags

Bit

Value

Change_Owner_Security_Information

0

1

Change_Group_Security_Information

1

2

Change_Dad_Security_Information

2

4

Change_Sad_Security_Information

3

8

Nothing forces you to use the ChangeSecurityPermissionsEx method. By default, the script makes use of the SetSecurityDescriptor method exposed by the Win32_LogicalFileSecuritySetting class. Eventually, the script can process the recursion itself. Of course, this logic must be developed in the script code, but the Microsoft Knowledge Base article Q266461 shows an example for the File System security descriptor. In its current version, the SetSecurityDescriptor() function does not support the recursive application of a security descriptor, but the script can easily be expanded.

4.13.1.2 Updating file and folder security descriptors with ADSI

Through ADSI, under Windows Server 2003 (or Windows XP), the script makes use of the IADsSecurityUtility interface. This interface was already used in section 4.7.1.2 ("Retrieving file and folder security descriptors with ADSI") and follows the same logic to save the security descriptor back to the File System. Of course, a different method must be used, as shown in Sample 4.52 (lines 73 through 76). Under Windows 2000 (or Windows NT 4.0), the ADsSecurity object is used to save the security descriptor (line 79).

Sample 4.52: Updating file and folder security descriptors with ADSI (Part II)

start example

 ..: ..: ..: 58: 59:           Case cFileViaADSI 60:' ADSI update technique -------------------------------------------------------------------- 61: 62:' Here objSD contains a security descriptor in the ADSI object model. 63: 64:                WScript.Echo "Setting File or Folder security descriptor via ADSI to '" & _ 65:                             strSource & "'." 66: 67:                ' Windows Server 2003 only ------------------------------------------------- 68:                objADsSecurity.SecurityMask = ADS_SECURITY_INFO_OWNER Or _ 69:                                              ADS_SECURITY_INFO_GROUP Or _ 70:                                              ADS_SECURITY_INFO_DACL ' Or _ 71:                                              ' ADS_SECURITY_INFO_SACL 72: 73:                objADsSecurity.SetSecurityDescriptor strSource, _ 74:                                                     ADS_PATH_FILE, _ 75:                                                     objSD, _ 76:                                                     ADS_SD_FORMAT_IID 77: 78:                ' Windows 2000 only -------------------------------------------------------- 79:                ' objADsSecurity.SetSecurityDescriptor objSD, "FILE://" & strSource 80: 81:                If Err.Number Then 82:                   Err.Clear 83:                   WScript.Echo vbCRLF & "Failed to set File or Folder security " & _ 84:                                "descriptor to '" & strSource & "' (" & intRC & ")." 85:               Else 86:                  SetSecurityDescriptor = True 87:               End If 88: 

end example

The ADSI techniques do not expose functionality to recursively save the security descriptor, although WMI does with the ChangeSecurityPermissionsEx method. To accomplish this, it is necessary to recursively browse the File System hierarchy, as described in the Microsoft Knowledge Base article Q266461.

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, then it will be impossible to save the updated SACL security descriptor back to the file system.

4.13.2 Updating File System share security descriptors

When a File System share security descriptor is read (see section 4.7.2, "Retrieving file system share security descriptor"), it is not always certain that a security descriptor is available from the share. In such a case, when no security descriptor is available, a default security descriptor is created based on the "Everyone" trustee. To save the security descriptor back to the File System share, we will see that some care must be taken.

4.13.2.1 Updating share security descriptors with WMI

With the WMI object model it is necessary to retrieve an instance of the File System share in an SWBemObject to update the security descriptor (see Sample 4.53).

Sample 4.53: Updating share security descriptors with WMI (Part III)

start example

 ..: ..: ..: 88: 89:' +----------------------------------------------------------------------------------------+ 90:' | Share                                                                                 | 91:' +----------------------------------------------------------------------------------------+ 92:           Case cShareViaWMI 93:' WMI update technique --------------------------------------------------------------------- 94: 95:' Here objSD contains a security descriptor in the WMI object model. 96: 97:                WScript.Echo "Setting Share security descriptor " & _ 98:                             "via WMI to '" & strSource & "'." 99: 100:               Set objWMIInstance = objConnection.Get("Win32_LogicalShareSecuritySetting='" & 101:                                    strSource & "'") 102:               If Err.Number = wbemErrNotFound Then 103:                  Err.Clear 104:                  Set objWMIInstance = objConnection.Get("Win32_Share='" & strSource & "'") ...: 107:                  intRC = objWMIInstance.SetShareInfo (0, "", objSD) 108:                  If intRC Then 109:                     WScript.Echo vbCRLF & "Failed to set Share security descriptor to '" & _ 110:                                  strSource & "' (" & intRC & ")." 111:                  Else 112:                     SetSecurityDescriptor = True 113:                  End If 114:               Else 115:                  If Err.Number Then ErrorHandler (Err) 116: 117:                  intRC = objWMIInstance.SetSecurityDescriptor (objSD) 118:                  If intRC Then 119:                     WScript.Echo vbCRLF & "Failed to set Share security descriptor to '" & _ 120:                                  strSource & "' (" & intRC & ")." 121:                  Else 122:                     SetSecurityDescriptor = True 123:                  End If 124:               End If ...: ...: ...: 

end example

The Win32_LogicalShareSecuritySetting class can be used to retrieve an instance of the File System share but with the condition that the share has a security descriptor set (lines 100 and 101). If no security descriptor exists, a wbemErrNotFound error will be returned, even if the share is well defined (line 102). In such a case the SetSecurityDescriptor method of the Win32_LogicalShareSecuritySetting class can't be used to save the security descriptor. At that time, the script must retrieve an instance of the File System share by using another class: the Win32_Share class (line 104) discussed in Chapter 2 with Sample 2.65. This class exposes the SetShareInfo method (line 107). The third input parameter of this method requires a structural WMI representation of the security descriptor (made from the Win32_SecurityDescriptor class). This technique saves to the File System share the updated or created security descriptor (see Sample 4.25, "Create a default security descriptor for a share").

4.13.2.2 Updating share security descriptors with ADSI

To update the File System share security descriptor with ADSI, it is mandatory to run under Windows Server 2003 (or Windows XP) and make use of the IADsSecurityUtility interface, as shown in Sample 4.54. Under Windows 2000 (or Windows NT 4.0), there is no way to update a File System share security descriptor with ADSI.

Sample 4.54: Updating share security descriptors with ADSI (Part IV)

start example

 ...: ...: ...: 127: 128:           Case cShareViaADSI 129:' ADSI update technique -------------------------------------------------------------------- 130: 131:' Here objSD contains a security descriptor in the ADSI object model. 132: 133:                WScript.Echo "Setting Share security descriptor via ADSI to '" & _ 134:                             strSource & "'." 135: 136:                ' Windows Server 2003 only ------------------------------------------------- 137:                objADsSecurity.SetSecurityDescriptor strSource, _ 138:                                                     ADS_PATH_FILESHARE, _ 139:                                                     objSD, _ 140:                                                     ADS_SD_FORMAT_IID 141: 142:                If Err.Number Then 143:                   Err.Clear 144:                      WScript.Echo vbCRLF & "Failed to set Share security descriptor to '" & _ 145:                                   strSource & "' (" & intRC & ")." 146:                Else 147:                   SetSecurityDescriptor = True 148:                End If 149: ...: ...: ...: 

end example

However, things are easier with ADSI than they are with WMI, since it is not necessary in the ADSI object model to retrieve an instance of the share to update the security descriptor (lines 137 through 140). Only the SetSecurityDescriptor method of the IADsSecurityUtility interface needs to be used.

4.13.3 Updating Active Directory object security descriptors

In section 4.7.3 ("Retrieving Active Directory object security descriptors"), the script retrieves the security descriptor via WMI and ADSI. To update the security descriptor back to Active Directory the script will also use the WMI and ADSI techniques.

4.13.3.1 Updating Active Directory object security descriptors with WMI

Updating the security descriptor in Active Directory is little bit more complex than the previous security descriptor update mechanisms. This logic is implemented in Sample 4.55. First, the script must retrieve an instance of the Active Directory object secured by the security descriptor to update (lines 158 through 165). As with the security descriptor access in Sample 4.18 ("Retrieving Active Directory object security descriptors with WMI [Part V]"), the script invokes the ConvertStringInArray() function to split the Active Directory object class from the object distinguishedName (line 158).

Sample 4.55: Updating Active Directory object security descriptors with WMI (Part V)

start example

 ...: ...: ...: 149: 150:' +----------------------------------------------------------------------------------------+ 151:' | Active Directory object                                                               | 152:' +----------------------------------------------------------------------------------------+ 153:           Case cActiveDirectoryViaWMI 154:' WMI update technique --------------------------------------------------------------------- 155: 156:' Here objSD contains a security descriptor in the ADSI object model. 157: 158:                arrayADInfo = ConvertStringInArray (strSource, ";") 159:                WScript.Echo "Setting " & LCase(arrayADInfo(0)) & _ 160:                             " Active Directory object security descriptor " & _ 161:                             "via WMI to 'LDAP://" & arrayADInfo(1) & "'." 162: 163:                Set objWMIInstance = objConnection.Get("ds_" & LCase(arrayADInfo(0)) & _ 164:                                                       ".ADSIPath='LDAP://" & _ 165:                                                       arrayADInfo(1) & "'") ...: 168:                arrayBytes = objADSIHelper.ConvertAdsiSDToRawSD (objSD) ...: 171:                Set objTempSD = objWMIInstance.DS_nTSecurityDescriptor ...: 174:                objTempSD.Value = arrayBytes 175:                Set objWMIInstance.DS_nTSecurityDescriptor = objTempSD 176: 177:                objWMINamedValueSet.Add "__PUT_EXTENSIONS", True 178:                objWMINamedValueSet.Add "__PUT_EXT_CLIENT_REQUEST", True 179:                objWMINamedValueSet.Add "__PUT_EXT_PROPERTIES", _ 180:                                        Array ("DS_nTSecurityDescriptor") 181: 182:                objWMIInstance.Put_ wbemChangeFlagUpdateOnly Or wbemFlagReturnWhenComplete, _ 183:                                    objWMINamedValueSet 184:                If Err.Number Then 185:                   Err.Clear 186:                   WScript.Echo vbCRLF & "Failed to set Active Directory object " & _ 187:                                "security descriptor to 'LDAP://" & strSource & "'." 188:                Else 189:                   SetSecurityDescriptor = True 190:                End If ...: ...: ...: 

end example

Because the WMI security descriptor method retrieves a security descriptor in a raw form, the WMI security descriptor update method must set the security descriptor in the same format. This requires a conversion of the security descriptor from its ADSI form to a binary form. This conversion is made with the help of the ActiveX DLL (line 168) used during the read operation of the security descriptor. During the read operation of the security descriptor (see Sample 4.18), we saw that the security descriptor is contained in an SWBemNamedValue object assigned to the DS_nTSecurityDescriptor property of the SWBemObject representing the Active Directory object instance. Because the script saves the updated security descriptor back to the Active Directory, it sets the value of the SWBemNamedValue object (line 174) to the DS_nTSecurityDescriptor property (line 175). Now that the security descriptor of the SWBemObject object representing the Active Directory object is updated, this WMI instance must be updated back to the Active Directory. Here, the script uses a WMI partial update technique (lines 177 through 183). We already used the partial-instance update technique in Chapter 3 (section 3.6.1.1, "Creating and updating objects in Active Directory"). Actually, it is impossible to save the complete Active Directory object instance at once, because some of the Active Directory attributes defined in this instance can only be set by the system itself. This means that if we try to save the complete instance back to Active Directory without a partial-instance update, Active Directory will reject the update, since it will consider this update as a violation of the rules enforced by the directory schema (constraint violation). Therefore, the script uses the partial-instance update mechanism and specifies that only the ntSecurityDescriptor Active Directory attribute (lines 179 through 180), represented by the DS_nTSecurityDescriptor WMI property, must be updated.

4.13.3.2 Updating Active Directory object security descriptors with ADSI

Updating an Active Directory security descriptor with ADSI is much simpler than the WMI technique (see Sample 4.56). To ensure that all security descriptor components are saved (i.e., DACL, SACL), the SetOption property is initialized accordingly (lines 201 through 204). Next, the security descriptor is placed back into the nTSecurityDescriptor attribute (line 206) and committed back to the Active Directory (line 209).

Sample 4.56: Updating Active Directory object security descriptors with ADSI (Part VI)

start example

 ...: ...: ...: 193: 194:           Case cActiveDirectoryViaADSI 195:' ADSI update technique -------------------------------------------------------------------- 196: 197:' Here objSD contains a security descriptor in the ADSI object model. 198: 199:                WScript.Echo "Setting Active Directory object security " & _ 200:                             "descriptor via ADSI to '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:                objConnection.Put "ntSecurityDescriptor", objSD ...: 209:                objConnection.SetInfo 210:                If Err.Number Then 211:                   Err.Clear 212:                   WScript.Echo vbCRLF & "Failed to set Active Directory object " & _ 213:                                "security descriptor to 'LDAP://" & strSource & "'." 214:                Else 215:                   SetSecurityDescriptor = True 216:                End If 217: ...: ...: ...: 

end example

4.13.4 Updating Exchange 2000 mailbox security descriptors

Updating the Exchange 2000 mailbox security descriptor requires some specific considerations. With the initial release of Exchange 2000 and with Service Pack 1, the use of ADSI and CDOEXM to manage the mailbox security descriptor was quite limited. All of the information required to create an Exchange 2000 mailbox is initially stored in the Active Directory. By initializing a specific set of attributes associated with a user object, it is possible to create a mailbox using ADSI. Although not officially supported by Microsoft, this is technically possible (at least until Exchange 2000 Service Pack 3). The supported Microsoft solution is to use the CDOEXM extension to create the mailbox. Basically, CDOEXM abstracts the set of attributes required via the CreateMailbox method exposed by the IMailboxStore CDOEXM interface. This gives the guarantee of a reliable code, even if Microsoft changes the underlying logic of the mailbox creation in the future. Put simply, the ADSI technique can be seen as a raw mailbox creation process, while the CDOEXM technique can be seen as a logic encapsulated in a COM object.

Despite this nice abstraction layer, until Exchange 2000 Service Pack 2, the original CDOEXM version does not expose any attributes or methods to update mailbox security. Instead, CDOEXM configures a default security for the mailbox, which is not always the one required by Administrators. One possible solution is to use ADSI and access the msExchMailboxSecurityDescriptor attribute to initialize the Exchange 2000 mailbox security descriptor as required. But this technique has its limitations, since it only works well for new mailboxes, not existing mailboxes. Why? When an Exchange 2000 mailbox is created, the information required for the definition of the mailbox is stored in the Active Directory. Actually, the physical mailbox, the one in the Exchange 2000 Store, is not created immediately. This "physical" mailbox is created only when the user connects to the new mailbox or when mail is delivered to it. At that time, the mailbox is really created in the Exchange Store, and its security is set from the msExchMailboxSecurityDescriptor attribute in the Exchange 2000 Store.

The Active Directory msExchMailboxSecurityDescriptor becomes a copy of the real security descriptor set in the store and it only mirrors its value. In this case, ADSI can't be used anymore to change the mailbox security, since it does not provide access to the security descriptor in the store. Any change to the msExchMailboxSecurityDescriptor attribute will not be reflected in the Store. So, this solution only works for brand new mailboxes before they are "physically" created in the Exchange Store. Actually, the msExchMailboxSecurityDescriptor has two purposes:

  • The attribute is a placeholder used to store the security information that will be written to the mailbox security descriptor in the Exchange store when the "physical" mailbox is created.

  • Since the attribute is replicated in the Exchange organization, it allows the mailbox permissions to be accessible to all Exchange servers that are connected to different GCs. The evaluation of the "Send as" permission (Extended Right) requires the mailbox permissions to be accessible by all Exchange servers.

Since the Exchange 2000 Service Pack 2, it is possible to update the mailbox security descriptor in the Exchange Store using a new property, called MailboxRights, which is exposed by the IMailboxStore CDOEXM interface. Since CDOEXM acts as an ADSI extension, this property is associated with the ADSI IADsUser interface.

Based on this technical explanation, we can conclude that the Exchange 2000 mailbox security descriptor can be read with any access method (WMI, ADSI, CDOEXM), but it can only be updated with:

  • WMI, if the mailbox is not physically created in the Exchange 2000 Store.

  • ADSI, if the mailbox is not physically created in the Exchange 2000 Store.

  • CDOEXM, if the mailbox is physically created or not in the Exchange 2000 Store. However, Exchange 2000 Service Pack 2 is required!

Now that the update conditions of the Exchange 2000 mailbox security descriptor are clear, let's see how this can be coded in a script.

4.13.4.1 Updating Exchange 2000 mailbox security descriptors with WMI

The Exchange 2000 mailbox security descriptor update follows the exact same logic as the update of an Active Directory object security descriptor. The only difference is in the attribute to be updated. For an Active Directory object, the script updated the DS_nTSecurityDescriptor of the SWBemObject representing the Active Directory object (see Sample 4.55). For the Exchange 2000 mailbox security descriptor, the script updates the DS_msExchMailboxSecurityDescriptor property of the SWBemObject representing the Active Directory user object (see Sample 4.57). For the rest, we use the same four steps:

  • Retrieval of the Active Directory user object instance (lines 228 and 229)

  • Conversion of the security descriptor to a binary format (line 232)

  • Assignment of the SWBemNamedValue object assigned to the DS_msExchMailboxSecurityDescriptor property (lines 235 to 239)

  • Partial update of the WMI instance representing the Active Directory user object (lines 241 through 247)

Sample 4.57: Updating Exchange 2000 mailbox security descriptors with WMI (Part VII)

start example

 ...: ...: ...: 217: 218:' +----------------------------------------------------------------------------------------+ 219:' | Exchange 2000 mailbox | 220:' +----------------------------------------------------------------------------------------+ 221:           Case cExchange2000MailboxViaWMI 222:' WMI update technique --------------------------------------------------------------------- 223: 224:' Here objSD contains a security descriptor in the ADSI object model. 225: 226:                WScript.Echo "Setting Exchange 2000 mailbox security " & _ 227:                             "descriptor via WMI to 'LDAP://" & strSource & "'." 228:                Set objWMIInstance = objConnection.Get("ds_user.ADSIPath='LDAP://" & _ 229:                                                       strSource & "'") ...: 232:                arrayBytes = objADSIHelper.ConvertAdsiSDToRawSD (objSD) ...: 235:                Set objTempSD = objWMIInstance.DS_msExchMailboxSecurityDescriptor ...: 238:                objTempSD.Value = arrayBytes 239:                Set objWMIInstance.DS_nTSecurityDescriptor = objTempSD 240: 241:                objWMINamedValueSet.Add "__PUT_EXTENSIONS", True 242:                objWMINamedValueSet.Add "__PUT_EXT_CLIENT_REQUEST", True 243:                objWMINamedValueSet.Add "__PUT_EXT_PROPERTIES", _ 244:                                        Array ("DS_msExchMailboxSecurityDescriptor") 245: 246:                objWMIInstance.Put_ wbemChangeFlagUpdateOnly Or wbemFlagReturnWhenComplete, _ 247:                                    objWMINamedValueSet 248:                If Err.Number Then 249:                   Err.Clear 250:                   WScript.Echo vbCRLF & "Failed to set Exchange 2000 mailbox " & _ 251:                                "security descriptor to 'LDAP://" & strSource & "'." 252:                Else 253:                   SetSecurityDescriptor = True 254:                End If ...: ...: ...: 

end example

4.13.4.2 Updating Exchange 2000 mailbox security descriptors with ADSI

As with the ADSI update technique of a security descriptor from an Active Directory object, the update of a security descriptor of an Exchange 2000 mailbox follows the same logic and coding technique. However, instead of updating the nTSecurityDescriptor attribute, Sample 4.58 updates the msExchMailboxSecurityDescriptor attribute (lines 270 and 273).

Sample 4.58: Updating Exchange 2000 mailbox security descriptors with ADSI (Part VIII)

start example

 ...: ...: ...: 257: 258:           Case cExchange2000MailboxViaADSI 259:' ADSI update technique -------------------------------------------------------------------- 260: 261:' Here objSD contains a security descriptor in the ADSI object model. 262: 263:                WScript.Echo "Setting Exchange 2000 mailbox security " & _ 264:                             "descriptor via ADSI to 'LDAP://" & strSource & "'." 265:                objConnection.SetOption ADS_OPTION_SECURITY_MASK, ADS_SECURITY_INFO_OWNER Or _ 266:                                                                  ADS_SECURITY_INFO_GROUP Or _ 267:                                                                  ADS_SECURITY_INFO_DACL Or _ 268:                                                                  ADS_SECURITY_INFO_SACL 269: 270:                objConnection.Put "msExchMailboxSecurityDescriptor", objSD ...: 273:                objConnection.SetInfo 274:                If Err.Number Then 275:                   Err.Clear 276:                   WScript.Echo vbCRLF & "Failed to set Exchange 2000 mailbox " & _ 277:                                "security descriptor to 'LDAP://" & strSource & "'." 278:                      Else 279:                          SetSecurityDescriptor = True 280:                      End If 281: ...: ...: ...: 

end example

4.13.4.3 Updating Exchange 2000 mailbox security descriptors with CDOEXM

The CDOEXM mailbox security descriptor update technique is the only one able to update the security descriptor when the Exchange 2000 mailbox is physically created in the Exchange 2000 Store. As mentioned before, the Exchange 2000 Service Pack 2 is required. Basically, instead of directly updating the msExchMailboxSecurityDescriptor attribute (see Sample 4.58) with the line:

 objConnection.Put "msExchMailboxSecurityDescriptor", objSD 

the CDOEXM property, acting as an extension for ADSI, is assigned with the updated security descriptor as follows:

 objConnection.MailboxRights = Array (objSD) 

Behind the scenes, the logic encapsulated in the CDOEXM object will update the security descriptor in the Active Directory and at the same time in the Exchange 2000 Store. Sample 4.59 shows the complete code in the context of the script. As we can see, the code modification to support the CDOEXM is very small and the overall logic looks like the ADSI update method. This facility comes mainly from the fact that CDOEXM acts as an extension for ADSI.

Sample 4.59: Updating Exchange 2000 mailbox security descriptors with CDOEXM (Part IX)

start example

 ...: ...: ...: 281: 282:           Case cExchange2000MailboxViaCDOEXM 283:' CDOEXM update technique ------------------------------------------------------------------ 284: 285:' Here objSD contains a security descriptor in the ADSI object model. 286: 287:                WScript.Echo "Setting Exchange 2000 mailbox security " & _ 288:                             "descriptor via CDOEXM to 'LDAP://" & strSource & "'." 289:                objConnection.MailboxRights = Array (objSD) 290: 291:                objConnection.SetInfo 292:                If Err.Number Then 293:                   Err.Clear 294:                   WScript.Echo vbCRLF & "Failed to set Exchange 2000 mailbox " & _ 295:                                "security descriptor to 'LDAP://" & strSource & "'." 296:                      Else 297:                         SetSecurityDescriptor = True 298:                      End If 299: ...: ...: ...: 

end example

4.13.5 Updating registry key security descriptors with ADSI

To read a registry key security descriptor, we must determine if we are running under Windows NT 4.0, Windows 2000, Windows XP, or Windows Server 2003 (see section 4.7.5, "Retrieving registry key security descriptors with ADSI"). As we have seen, under Windows 2000 (or Windows NT 4.0), we can use the ADsSecurity.DLL ActiveX to read a registry security descriptor. Under Windows XP or Windows Server 2003, we should use the IADsSecurityUtility interface to read the security descriptor from the registry. To update the security descriptor to a registry key, the logic follows the same rule. By default, Sample 4.60 implements the Windows XP/Windows Server 2003 logic (lines 316 through 325), but the commented out lines can be swapped to run the script under Windows NT 4.0/Windows 2000 (line 328). Under Windows XP/Windows Server 2003, the SecurityMask is set up to ensure that all components of the security descriptor are saved back to the registry (lines 317 through 320).

Sample 4.60: Updating registry key security descriptors with ADSI (Part X)

start example

 ...: ...: ...: 299: 300:' +----------------------------------------------------------------------------------------+ 301:' | Registry key                                                                       | 302:' +----------------------------------------------------------------------------------------+ 303:           Case cRegistryViaWMI 304:' WMI update technique --------------------------------------------------------------------- 305: 306:' Here we can't retrieve a security descriptor via this access method. 307: 308:           Case cRegistryViaADSI 309:' ADSI update technique -------------------------------------------------------------------- 310: 311:' Here objSD contains a security descriptor in the ADSI object model. 312: 313:                WScript.Echo "Setting registry security descriptor via ADSI to '" & _ 314:                             strSource & "'." 315: 316:                ' Windows Server 2003 only ------------------------------------------------- 317:                objADsSecurity.SecurityMask = ADS_SECURITY_INFO_OWNER Or _ 318:                                              ADS_SECURITY_INFO_GROUP Or _ 319:                                              ADS_SECURITY_INFO_DACL ' Or _ 320:                                              ' ADS_SECURITY_INFO_SACL 321: 322:                objADsSecurity.SetSecurityDescriptor strSource, _ 323:                                                     ADS_PATH_REGISTRY, _ 324:                                                     objSD, _ 325:                                                     ADS_SD_FORMAT_IID 326: 327:                ' Windows 2000 only -------------------------------------------------------- 328:                ' objADsSecurity.SetSecurityDescriptor objSD, "RGY://" & strSource 329: 330:                If Err.Number Then 331:                   Err.Clear 332:                   WScript.Echo vbCRLF & "Failed to set registry security descriptor to '" & _ 333:                                strSource & "'." 334:                Else 335:                   SetSecurityDescriptor = True 336:                End If 337: ...: ...: ...: 

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 update a structural representation of a registry key security decriptor, there will currently be no way to update the SACL of a registry key security descriptor from the scripting world with the current ADSI COM objects.

4.13.6 Updating CIM repository namespace security descriptors with WMI

When reading a CIM repository namespace security descriptor, we always retrieve the security descriptor in a raw format. Therefore, the script converts it into an ADSI structural representation (see section 4.7.6, "Retrieving CIM repository namespace security descriptors with WMI," Sample 4.24). To update the security descriptor back to a CIM repository namespace, the security descriptor must be converted back to a raw format from its ADSI structural representation. Sample 4.61 illustrates the logic.

Sample 4.61: Updating CIM repository namespace security descriptors with WMI (Part XI)

start example

 ...: ...: ...: 337: 338:' +----------------------------------------------------------------------------------------+ 339:' | CIM repository namespace                                                             | 340:' +----------------------------------------------------------------------------------------+ 341:           Case cWMINameSpaceViaWMI 342:' WMI update technique --------------------------------------------------------------------- 343: 344:' Here objSD contains a security descriptor in the ADSI object model. 345: 346:                WScript.Echo "Setting CIM repository namespace security descriptor via WMI to '" & _ 347:                             strSource & "'." 348:                Set objWMIInstance = objConnection.Get(" __SystemSecurity=@") ...: 351:                arrayBytes = objADSIHelper.ConvertAdsiSDToRawSD (objSD) ...: 354:                intRC = objWMIInstance.SetSD (arrayBytes) 355:                If intRC Then 356:                   WScript.Echo vbCRLF & "Failed to set CIM repository namespace security " & _ 357:                                "descriptor to '" & strSource & "'." 358:                Else 359:                   SetSecurityDescriptor = True 360:                End If 361: 362:           Case cWMINameSpaceViaADSI 363:' ADSI update technique -------------------------------------------------------------------- 364: 365:' Here we can't retrieve a security descriptor via this access method. 366: 367:           Case Else 368: 369:    End Select 370: 371:End Function 

end example

First, the script retrieves an instance of the __SystemSecurity singleton class (line 348). Next, it converts the ADSI security descriptor structural representation to a raw format (line 351) with the help of the ADSIHelper object (see section 4.9, "The security descriptor conversion"). Then it uses the SetSD method exposed by the __SystemSecurity class to update the security descriptor.




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