We have seen situations where the security descriptor is not directly retrieved in the WMI or in the ADSI object model. Sometimes, the security descriptor is represented as a binary array, which does not represent a usable form from a script. In such a case, it is necessary to convert the binary security descriptor to a usable object model. We mentioned that ADSI represents a good alternative to convert the binary security descriptor into the ADSI object model compared with the low-level programming that Win32 APIs require. Moreover, this approach is much simpler than digging into the low-level API programming. As a reminder, this conversion to get an ADSI security descriptor is necessary for:
Sample 4.18, "Retrieving Active Directory object security descriptors with WMI (Part V)"
Sample 4.20, "Retrieving Exchange 2000 mailbox security descriptors with WMI (Part VII)"
Sample 4.24, "Retrieving CIM repository namespace security descriptors with WMI (Part XI)"
We will see further that a conversion is also necessary to update the security descriptor for:
Sample 4.55, "Updating Active Directory object security descriptors with WMI (Part V)"
Sample 4.57, "Updating Exchange 2000 mailbox security descriptors with WMI (Part VII)"
Sample 4.61, "Updating CIM repository namespace security descriptors with WMI (Part XI)"
For the variable type conversion facility, the security descriptor conversion is encapsulated into a COM object called ADSIHelper. This ActiveX DLL object is written in Visual BASIC v6.0 (VB6), which allows the use of type definitions for variables. This comes from the fact that the ADSI technique used for the conversion requires a precise type as input parameter. Since scripting languages do not have explicit type definitions (Variant), this makes VB6 a good candidate for such programming while maintaining simplicity of use. The ADSIHelper object exposes two methods:
ConvertRawSDToAdsiSD, which converts the binary security descriptor to an ADSI representation. The code is shown in Sample 4.26.
Sample 4.26: Converting the binary security descriptor to an ADSI representation
1:Option Explicit 2: 3:Public Function ConvertRawSDToAdsiSD(ByVal arrayBytes As Variant) As IADsSecurityDescriptor 4: 5:' Windows Server 2003 only 6:Dim objADsSecurity As New ADsSecurityUtility 7: 8:' Windows 2000 only 9:' Dim objPropertyValue As New PropertyValue 10: 11:Dim objADsSD As IADsSecurityDescriptor 12:Dim byteSD() As Byte 13:Dim intIndice As Integer 14: 15: On Error Resume Next 16: 17: ' We must convert the variant array to a byte array. 18: ' Otherwise, doesn't work ... (type conversion problem) 19: ReDim byteSD(UBound(arrayBytes)) 20: 21: For intIndice = 0 To UBound(arrayBytes) 22: byteSD(intIndice) = arrayBytes(intIndice) 23: Next 24: 25: ' Windows Server 2003 only ------------------------------------------------------- 26: objADsSecurity.SecurityMask = ADS_SECURITY_INFO_OWNER Or _ 27: ADS_SECURITY_INFO_GROUP Or _ 28: ADS_SECURITY_INFO_DACL Or _ 29: ADS_SECURITY_INFO_SACL 30: 31: Set objADsSD = objADsSecurity.ConvertSecurityDescriptor(byteSD, _ 32: ADS_SD_FORMAT_RAW, _ 33: ADS_SD_FORMAT_IID) 34: 35: ' Windows 2000 only -------------------------------------------------------------- 36: ' objPropertyValue.PutObjectProperty ADSTYPE_OCTET_STRING, (byteSD) 37: ' Set objADsSD = objPropertyValue.GetObjectProperty(ADSTYPE_NT_SECURITY_DESCRIPTOR) 38: 39: If Err.Number Then 40: ErrorHandler "ConvertRawSDToAdsiSD", _ 41: "Unable to convert raw Security Descriptor to an ADSI Security Descriptor", 42: Err, _ 43: True ..: 45: Exit Function 46: End If 47: 48: Set ConvertRawSDToAdsiSD = objADsSD 49: 50:End Function 51: ..: ..: ..:
ConvertAdsiSDToRawSD, which converts the ADSI security descriptor to a binary format. The code is shown in Sample 4.27.
Sample 4.27: Converting the ADSI security descriptor to a binary format
..: ..: ..: 51: 52:Public Function ConvertAdsiSDToRawSD(objVariantADsSD As Variant) As Variant() 53: 54:' Windows Server 2003 only 55:Dim objADsSecurity As New ADsSecurityUtility 56: 57:' Windows 2000 only 58:' Dim objPropertyValue As New PropertyValue 59: 60:Dim arrayBytes() As Variant 61:Dim byteSD() As Byte 62:Dim intIndice As Integer 63: 64: On Error Resume Next 65: 66: ' Windows Server 2003 only -------------------------------------------------------- 67: objADsSecurity.SecurityMask = ADS_SECURITY_INFO_OWNER Or _ 68: ADS_SECURITY_INFO_GROUP Or _ 69: ADS_SECURITY_INFO_DACL Or _ 70: ADS_SECURITY_INFO_SACL 71: 72: byteSD = objADsSecurity.ConvertSecurityDescriptor(objVariantADsSD, _ 73: ADS_SD_FORMAT_IID, _ 74: ADS_SD_FORMAT_RAW) 75: 76: ' Windows 2000 only ------------------------------------------------------------- -- 77: ' objPropertyValue.PutObjectProperty ADSTYPE_NT_SECURITY_DESCRIPTOR, (objVariantADsSD) 78: ' byteSD = objPropertyValue.GetObjectProperty(ADSTYPE_OCTET_STRING) 79: 80: If Err.Number Then 81: ErrorHandler "ConvertAdsiSDToRawSD", _ 82: "Unable to convert ADSI Security Descriptor to a raw Security Descriptor", 83: Err, _ 84: True 85: ConvertAdsiSDToRawSD = Null 86: Exit Function 87: End If 88: 89: ' We must convert the byte array to a variant array. 90: ' Otherwise, doesn't work ... (type conversion problem) 91: ReDim arrayBytes(UBound(byteSD)) 92: 93: For intIndice = 0 To UBound(byteSD) 94: arrayBytes(intIndice) = byteSD(intIndice) 95: Next 96: 97: ConvertAdsiSDToRawSD = arrayBytes 98: 99:End Function 100: ...: ...: ...:
Here again, we must determine if we are running under Windows Server 2003 (or Windows XP) or Windows 2000 (or Windows NT). Under Windows Server 2003 (or Windows XP), the ADSIHelper ActiveX DLL uses the ADsSecurityUtility object to convert the security descriptor (lines 25 through 33). It uses the ConvertSecurityDescriptor method exposed by the ADsSecurityUtility object. This method can convert a binary security descriptor to an ADSI security descriptor and vice versa (Sample 4.26, lines 31 through 33, and Sample 4.27, lines 72 through 74). The method uses the values defined in Table 4.7 ("The ADsSecurityUtility constants"). Because the values required by these conversion techniques must use a formal type, it makes it easier to program this logic under VB6 than a script, which only uses the Variant type.
Under Windows 2000 (or Windows NT), the ADSIHelper ActiveX DLL uses the PropertyValue ADSI object exposed by the ADSI IADsPropertyValue interface (lines 36 and 37). The ActiveX DLL creates the PropertyValue object (line 9) and uses its PutObjectProperty method to assign the binary security descriptor as value (line 36). With the help of the ADSI cache and the ADSI property conversion mechanisms, the ActiveX DLL reads the assigned value by requesting an ADSI security descriptor format (line 37). The end result is that an ADSI security descriptor is returned from the ActiveX DLL. Note that this technique is also applicable under Windows Server 2003 (or Windows XP). Here, the ADsSecurityUtility object is only used to demonstrate some of the new ADSI capabilities provided by Windows Server 2003 and Windows XP.
The conversion of an ADSI security descriptor to a binary security descriptor follows the exact same logic (see Sample 4.27). Only the conversion types requested are inverted when compared with Sample 4.26.