23.4 Creating Security Descriptors
If you are creating an
object from scratch, and you don't want it to get
the default DACL and SACL that due to inheritance would normally be
applied to objects created at that location in the tree, you can
write your own DACL and SACL for an object. As you would expect,
there are a number of properties associated with security descriptors
and ACLs that you need to set. SDs and ACLs can be manipulated with
the IADsAccessControlList (see Table 23-10) and IADsSecurityDescriptor
(see Table 23-11) interfaces. We'll
go through these briefly now and then move on to some more examples.
Table 23-10. IADsAccessControlList methods and properties
AddAce method
|
Adds an ACE to an ACL
|
RemoveAce method
|
Removes an ACE from an ACL
|
CopyAccessList method
|
Copies the current ACL
|
AclRevision property
|
Shows the revision of the ACL (always set to 4; see later text)
|
AceCount property
|
Indicates the number of ACEs in the ACL
|
The revision level is a static version number
for every ACE, ACL, and SD in Active Directory. It is defined in the
ADS_SD_REVISION_ENUM enumerated type, which contains a single
constant definition as follows:
Const ADS_SD_REVISION_DS = 4.
Having a revision allows Active Directory to know which elements of
an ACE could exist. Later, if new properties and concepts are added
to the ACE so that it has a more extended definition, the revision
would increment. Active Directory would then know that old revision-4
ACEs could not support the new extensions and could upgrade them or
support them with lesser functionality.
Table 23-11. IADsSecurityDescriptor methods and properties
CopySecurityDescriptor method
|
A copy of an existing SD.
|
Revision property
|
The revision of the SD (always set to 4, as noted earlier).
|
Control property
|
A set of flags indicating various aspects of the SD (see later text).
|
Owner property
|
The SID of the owner. If this field is null, no owner is set.
|
OwnerDefaulted property
|
A Boolean value indicating whether the owner is derived by the
default mechanism when created (i.e., assembled out of all the
inherited ACEs passed down by its parents) rather than explicitly set
by the person or application that created the SD in the first place.
|
Group property
|
The SID of the object's primary group if
appropriate. If this field is null, no primary group exists.
|
GroupDefaulted property
|
A Boolean value indicating that the group is derived by the default
mechanism rather than explicitly set by the person or application
that created the SD in the first place.
|
DiscretionaryAcl property
|
The discretionary ACL that holds permissions ACEs. The
SE_DACL_PRESENT flag must be set in the Control property if a DACL
exists. If the flag is set and yet this field is null, full access is
allowed to everyone.
|
DaclDefaulted property
|
A Boolean value indicating that the DACL is derived by the default
mechanism rather than explicitly set by the person or application
that created the SD in the first place. This is ignored unless
SE_DACL_PRESENT is set.
|
SystemAcl property
|
The system ACL that holds auditing ACEs. The SE_SACL_PRESENT flag
must be set in the Control property if a SACL exists.
|
SaclDefaulted property
|
A Boolean value indicating that the SACL is derived by the default
mechanism rather than explicitly set by the person or application
that created the SD in the first place. This is ignored unless
SE_SACL_PRESENT is set.
|
The Control property can take a number of
flags that help to define the properties of an SD. See Table 23-12 for a full description.
Table 23-12. Control constants
ADS_SD_CONTROL_SE_ OWNER_DEFAULTED
|
1
|
&H1
|
This Boolean flag, when set, indicates that the SID pointed to by the
Owner field was provided by the default mechanism rather than set by
the person or application that created the SD in the first place.
This may affect the treatment of the SID with respect to inheritance
of an owner.
|
ADS_SD_CONTROL_SE_ GROUP_DEFAULTED
|
2
|
&H2
|
This Boolean flag, when set, indicates that the SID in the Group
field was provided by the default mechanism rather than explicitly
set by the person or application that created the SD in the first
place. This may affect the treatment of the SID with respect to
inheritance of a primary group.
|
ADS_SD_CONTROL_SE_ DACL_PRESENT
|
4
|
&H4
|
This Boolean flag, when set, indicates that the security descriptor
contains a DACL. If this flag is set and the DiscretionaryAcl field
of the SD is null, an empty (but present) ACL is explicitly being
specified.
|
ADS_SD_CONTROL_SE_ DACL_DEFAULTED
|
8
|
&H8
|
This Boolean flag, when set, indicates that the
DiscretionaryAcl field was provided by the default
mechanism rather than explicitly set by the person or application
that created the SD in the first place. This may affect the treatment
of the ACL with respect to inheritance of an ACL. This flag is
ignored if the SE_DACL_PRESENT flag is not set.
|
ADS_SD_CONTROL_SE_ SACL_PRESENT
|
16
|
&H10
|
This Boolean flag, when set, indicates that the security descriptor
contains a SACL.
|
ADS_SD_CONTROL_SE_ SACL_DEFAULTED
|
32
|
&H20
|
This Boolean flag, when set, indicates that the ACL pointed to by the
SystemAcl field was provided by the default
mechanism rather than explicitly set by the person or application
that created the SD in the first place. This may affect the treatment
of the ACL with respect to inheritance of an ACL. This flag is
ignored if the SE_ SACL_PRESENT flag is not set.
|
ADS_SD_CONTROL_SE_ DACL_AUTO_INHERIT_ REQ
|
256
|
&H100
|
The DACL of the SD must be inherited.
|
ADS_SD_CONTROL_SE_ SACL_AUTO_INHERIT_ REQ
|
512
|
&H200
|
The SACL of the SD must be inherited.
|
ADS_SD_CONTROL_SE_ DACL_AUTO_INHERITED
|
1,024
|
&H400
|
The DACL of the SD supports auto-propagation of inheritable ACEs to
existing child objects.
|
ADS_SD_CONTROL_SE_ SACL_AUTO_INHERITED
|
2,048
|
&H800
|
The SACL of the SD supports auto-propagation of inheritable ACEs to
existing child objects.
|
ADS_SD_CONTROL_SE_ DACL_PROTECTED
|
4,096
|
&H1000
|
The DACL of the SD is protected and will not be modified when new
rights propagate through the tree.
|
ADS_SD_CONTROL_SE_ SACL_PROTECTED
|
8,192
|
&H2000
|
The SACL of the SD is protected and will not be modified when new
rights propagate through the tree.
|
ADS_SD_CONTROL_SE_ SELF_RELATIVE
|
32,768
|
&H8000
|
The SD is held in a contiguous block of memory.
|
These values were taken from the ADSI documentation for
the ADS_SD_CONTROL_ENUM enumerated type available from the MSDN
Library under the section described at the beginning of the chapter.
|
In your ADSI code, it is possible to specify that the DACL or SACL is
either null or empty. While in both cases each ACL contains no ACEs,
there is a big difference between the effects of each setting.
Specifically, any ACL that has been set to null (vbNull) grants full
permissions to everyone while an ACL that exists but contains no ACEs
(i.e., is empty) grants no permissions to anyone at all.
|
|
Now we have enough information to be able to create our own SD. Example 23-3 does exactly that. While we have defined all
of the SD constants, to save space we have defined only the ACE
constants that we are using. Also note that this code is not 100%
complete; the object creation code is not included.
Example 23-3. Creating your own security descriptor
'**************************************************************************
'AccessMask constants
'**************************************************************************
Const ADS_RIGHT_DS_LIST_OBJECT = &H80
'**************************************************************************
'AceType constants
'**************************************************************************
Const ADS_ACETYPE_ACCESS_DENIED = &H1
'**************************************************************************
'AceFlags constants
'**************************************************************************
Const ADS_ACEFLAG_INHERIT_ACE = &H2
'**************************************************************************
'Security Descriptor constants
'**************************************************************************
Const ADS_SD_CONTROL_SE_OWNER_DEFAULTED = &H1
Const ADS_SD_CONTROL_SE_GROUP_DEFAULTED = &H2
Const ADS_SD_CONTROL_SE_DACL_PRESENT = &H4
Const ADS_SD_CONTROL_SE_DACL_DEFAULTED = &H8
Const ADS_SD_CONTROL_SE_SACL_PRESENT = &H10
Const ADS_SD_CONTROL_SE_SACL_DEFAULTED = &H20
Const ADS_SD_CONTROL_SE_DACL_AUTO_INHERIT_REQ = &H100
Const ADS_SD_CONTROL_SE_SACL_AUTO_INHERIT_REQ = &H200
Const ADS_SD_CONTROL_SE_DACL_AUTO_INHERITED = &H400
Const ADS_SD_CONTROL_SE_SACL_AUTO_INHERITED = &H800
Const ADS_SD_CONTROL_SE_DACL_PROTECTED = &H1000
Const ADS_SD_CONTROL_SE_SACL_PROTECTED = &H2000
'**************************************************************************
'Security Descriptor Revision
'**************************************************************************
Const ADS_SD_REVISION_DS = 4
'**************************************************************************
'Declare general variables
'**************************************************************************
Dim objObject 'The object to bind to
Dim objSecDesc 'SecurityDescriptor
Dim objDACL 'AccessControlList object containing permission ACEs
Dim objSACL 'AccessControlList object containing audit ACEs
Dim objNewACE 'AccessControlEntry
Dim objAttributeSchemaObject 'An object representing an attribute in the schema
'**************************************************************************
'Create the objObject first [this code is not included here]
'**************************************************************************
'**************************************************************************
'Set no permission to view the object for members of DenyGroup
'**************************************************************************
Set objNewACE = CreateObject("AccessControlEntry")
AdsACE.Trustee = "cn=VickyLaunders,cn=Users,dc=amer,dc=mycorp,dc=com"
objNewACE.AccessMask = ADS_RIGHT_DS_LIST_OBJECT
objNewACE.AceType = ADS_ACETYPE_ACCESS_DENIED
objNewACE.AceFlags = ADS_ACEFLAG_INHERIT_ACE
'**************************************************************************
'Create a new DACL and add the ACE as the sole entry
'**************************************************************************
Set objDACL = CreateObject("AccessControlList")
ObjDACL.AceCount = 1
ObjDACL.AclRevision = ADS_SD_REVISION_DS
ObjDACL.AddAce objNewACE
Set objNewACE = Nothing
'**************************************************************************
'Create the SD for the object. Set the SD to use the DACL supplied rather
'than the default one. Set the SD to use the default SACL that will be
'generated from all the inherited ACEs from parents further up the hierarchy.
'**************************************************************************
Set objSecDesc = CreateObject("SecurityDescriptor")
objSecDes.Revision = ADS_SD_REVISION_DS
objSecDes.Control = ADS_SD_CONTROL_SE_SACL_PRESENT _
+ ADS_SD_CONTROL_SE_SACL_PRESENT + ADS_SD_CONTROL_SE_SACL_DEFAULTED _
+ SE_OWNER_DEFAULTED + SE_GROUP_DEFAULTED
objSecDes.OwnerDefaulted = True
objSecDes.GroupDefaulted = True
objSecDes.DiscretionaryAcl = objDACL
objSecDes.DaclDefaulted = False
objSecDes.SaclDefaulted = True
'**************************************************************************
'Assign the SD to the existing object
'**************************************************************************
objObject.Put "ntSecurityDescriptor", objSecDes
obj Object.SetInfo
|