502 lines
28 KiB
HTML
502 lines
28 KiB
HTML
<html>
|
||
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||
<title>Active Directory Service Interfaces - Advanced Topic</title>
|
||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||
</head>
|
||
|
||
<body topmargin="0" leftmargin="0">
|
||
|
||
<table border="0" height="86" cellpadding="0" cellspacing="0">
|
||
<tr>
|
||
<td width="77%" valign="top" height="58"><map name="FPMap2">
|
||
<area href="http://www.microsoft.com/windows2000/library/howitworks/activedirectory/adsilinks.asp" shape="rect" coords="4, 6, 248, 57"></map><img src="banner.gif"
|
||
border="0" alt="http://www.microsoft.com/windows2000/library/howitworks/activedirectory/adsilinks.asp" width="250" height="60" usemap="#FPMap2"></td>
|
||
<td width="3%" height="58"></td>
|
||
<td width="21%" height="58" valign="bottom"><p align="right"><map name="FPMap3">
|
||
<area href="http://www.microsoft.com" shape="rect" coords="7, 6, 108, 39"></map><img src="mslogo.gif"
|
||
border="0" alt="http://www.microsoft.com" width="112" height="40" usemap="#FPMap3"></td>
|
||
</tr>
|
||
<tr>
|
||
<td valign="top" align="left" height="28"><map name="FPMap0">
|
||
<area href="rtk.htm" shape="rect" coords="420, 1, 515, 18" ALT="rtk.htm">
|
||
<area href="interopt.htm" shape="rect" coords="350, 1, 415, 19" ALT="interopt.htm">
|
||
<area href="ad.htm" shape="rect" coords="233, 1, 345, 19" ALT="ad.htm">
|
||
<area href="winnt.htm" shape="rect" coords="165, 1, 223, 19" ALT="winnt.htm">
|
||
<area href="dev.htm" shape="rect" coords="67, 1, 165, 19" ALT="dev.htm">
|
||
<area href="../default.htm" shape="rect" coords="13, 1, 65, 20" ALT = "../default.htm"></map>
|
||
<img rectangle="(233,1) (345, 19) ad.htm" rectangle="(165,1) (223, 19) winnt.htm" rectangle="(67,1) (165, 19) dev.htm" rectangle="(13,1) (65, 20) ../default.htm" src="router.gif" alt="router.gif (3874 bytes)" border="0" usemap="#FPMap0" width="536" height="26"></td>
|
||
<td width="3%" height="28"></td>
|
||
<td width="21%" height="28"></td>
|
||
</tr>
|
||
</table>
|
||
|
||
<table border="0" width="100%" cellspacing="0" cellpadding="0" height="40">
|
||
<tr>
|
||
<td width="2%" height="19"></td>
|
||
<td width="98%" height="19">
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td width="2%" height="21"></td>
|
||
<td width="98%" height="21"><img border="0" src="advanced.gif" width="209" height="123"></td>
|
||
</tr>
|
||
<tr>
|
||
<td width="2%" height="21"></td>
|
||
<td width="98%" height="21" valign="top"> <table border="0" width="100%" cellspacing="0"
|
||
cellpadding="0">
|
||
<tr>
|
||
<td width="43%"></td>
|
||
</tr>
|
||
<tr>
|
||
<td width="43%"><font face="Verdana" size="2" color="#0080C0"><b><a name="top"></a>General</b></font>
|
||
<ul>
|
||
<li><a href="#GetInfoEx"><font face="Verdana" size="2">GetInfoEx</font></a></li>
|
||
<li><a href="#Filter"><font face="Verdana" size="2">Filtering</font></a></li>
|
||
<li><a href="#PropertyCache"><font face="Verdana" size="2">Property
|
||
Caching</font></a></li>
|
||
<li><a href="#GetEx"><font face="Verdana" size="2">GetEx</font></a></li>
|
||
</ul>
|
||
<p><font size="2" color="#0080C0" face="Verdana"><b>WinNT</b></font></p>
|
||
<ul>
|
||
<li><a href="#ntBinding"><font face="Verdana" size="2">WinNT
|
||
Binding</font></a></li>
|
||
<li><a href="#ntDC"><font face="Verdana" size="2">Communicating
|
||
to a specific domain controller</font></a></li>
|
||
<li><a href="#ntReadOnly"><font face="Verdana" size="2">Including
|
||
backup domain controllers as part of selection </font></a></li>
|
||
</ul>
|
||
<p><font size="2" color="#0080C0" face="Verdana"><b>Active Directory</b></font></p>
|
||
<ul>
|
||
<li><a href="#adTree"><font face="Verdana" size="2">Searching
|
||
the entire tree</font></a></li>
|
||
<li><a href="#ObjectCategory"><font face="Verdana" size="2">Object
|
||
Class vs Object Category</font></a></li>
|
||
<li><a href="#fastBind"><font face="Verdana" size="2">Fast
|
||
Bind</font></a></li>
|
||
<li><a href="#operationalAttribute"><font face="Verdana" size="2">Operational
|
||
Attributes</font></a></li>
|
||
<li><font face="Verdana" size="2"><a href="#pageSize">Specifying
|
||
Page Size</a> </font></li>
|
||
<li><a href="#guid"><font face="Verdana" size="2">GUID
|
||
searching</font></a></li>
|
||
<li><a href="#mandatoryAttr"><font face="Verdana" size="2">Listing
|
||
Mandatory and Optional Attributes</font></a></li>
|
||
<li><a href="#adSecurity"><font face="Verdana" size="2">Active
|
||
Directory Security</font></a></li>
|
||
</ul>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td width="43%">
|
||
<hr color="#0080C0">
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td width="43%"><font face="Verdana" size="2" color="#0080C0"><a name="GetInfoEx"></a><b>GetInfoEx</b></font>
|
||
<p><font face="Verdana" size="2">When the first Get issue on an
|
||
object, ADSI ,implicitly,brings all attributes which have 1) value 2)
|
||
user has a read permission into ADSI cache. This is designed for
|
||
optimizing network traffic, server load for most cases and ease of
|
||
use- one big round trip is normally better than chatty traffics.
|
||
However, in some cases, you like to get only a small set of
|
||
attributes. GetInfoEx does exactly this. It allows you to specify only
|
||
attributes you're interested in.<br>
|
||
<br>
|
||
Example,<br>
|
||
Set o = GetObject("LDAP://CN=Jsmith, DC=ArcadiaBay, DC=COM")<br>
|
||
o.GetInfoEx
|
||
Array("sn","givenName","telephoneNumber"),
|
||
0<br>
|
||
Debug.Print o.Get("sn")<br>
|
||
Debug.Pritn o.Get("givenName")<br>
|
||
<br>
|
||
Back to <a href="#top">top</a></font></p>
|
||
<p><font face="Verdana" size="2" color="#0080C0"><a name="Filter"></a><b>Filtering</b></font></p>
|
||
<p><font face="Verdana" size="2">Often time you would like to
|
||
enumerate only certain types of class in a container. It's more efficient
|
||
to filter first, instead of doing comparision during the enumeration.<br>
|
||
<br>
|
||
Example, instead of doing this<br>
|
||
'--- Print all users in a domain<br>
|
||
Set cont = GetObject("WinNT://ARCADIABAY")<br>
|
||
For each obj in cont<br>
|
||
if obj.Class = "User" then<br>
|
||
Debug.Print obj.Name<br>
|
||
End if <br>
|
||
Next<br>
|
||
<br>
|
||
Instead, you should do this:</font></p>
|
||
<p><font face="Verdana" size="2">'--- Print all users in a domain<br>
|
||
Set cont = GetObject("WinNT://ARCADIABAY")<br>
|
||
con.Filter = Array("user")<br>
|
||
For each usr in cont<br>
|
||
Debug.Print usr.Name<br>
|
||
Next</font></p>
|
||
<p><font face="Verdana" size="2">Back to <a href="#top">top</a><br>
|
||
<br>
|
||
</font><font face="Verdana" size="2" color="#0080C0"><a name="GetEx"></a><b>GetEx</b></font></p>
|
||
<p><font face="Verdana" size="2">If you want to read a property but don't know whether
|
||
it is single-valued or multi-valued, GetEx comes in handy. Regardless how
|
||
many values in an attribute, you can rely on GetEx for value
|
||
enumeration.<br>
|
||
<br>
|
||
Example,<br>
|
||
Set usr = GetObject("LDAP://CN=Jsmith, DC=Fabrikam,
|
||
DC=COM")<br>
|
||
<br>
|
||
phone = usr.GetEx("telephoneNumber") 'single-valued property<br>
|
||
For Each pnumber In phone<br>
|
||
Debug.Print pnumber<br>
|
||
Next <br>
|
||
<br>
|
||
phone = usr.GetEx("otherTelephone") 'multi-valued property<br>
|
||
For Each pnumber In phone<br>
|
||
Debug.Print pnumber<br>
|
||
Next</font></p>
|
||
<p><font face="Verdana" size="2">Back to <a href="#top">top</a></font></p>
|
||
<p><font face="Verdana" size="2" color="#0080C0"><a name="PropertyCache"></a><b>Property
|
||
Caching</b></font></p>
|
||
<font face="Verdana" size="2">With IADsPropertyList, IADsPropertyEntry
|
||
and IADsPropertyValue, you will be able to manipulate ADSI caches.<br>
|
||
<br>
|
||
Example,<br>
|
||
<br>
|
||
Set oObject = GetObject("LDAP://CN=Andrew Anderson,OU=Sales,DC=Antipodes,DC=com")<br>
|
||
WScript.Echo "User: " & oObject.cn<br>
|
||
<br>
|
||
oObject.GetInfo 'Load into ADSI's caches<br>
|
||
WScript.Echo "Property Count: " & oObject.PropertyCount<br>
|
||
For i = 0 to oObject.PropertyCount -1<br>
|
||
Set X = oObject.Item(i+1) <br>
|
||
For Each Y In X.Values<br>
|
||
WScript.Echo "Attribute: " & X.Name & " " & " (" & CStr(aProperty(Y.ADsType+1)) & ")"<br>
|
||
Select Case Y.ADsType + 1<br>
|
||
Case ADSTYPE_DN_STRING<br>
|
||
|
||
WScript.Echo "Value: " & Y.DNString<br>
|
||
Case ADSTYPE_CASE_EXACT_STRING<br>
|
||
|
||
WScript.Echo "Value: " & Y.CaseExactString <br>
|
||
Case ADSTYPE_CASE_IGNORE_STRING<br>
|
||
|
||
WScript.Echo "Value: " & Y.CaseIgnoreString<br>
|
||
Case ADSTYPE_PRINTABLE_STRING<br>
|
||
|
||
WScript.Echo "Value: " & Y.PrintableString<br>
|
||
Case ADSTYPE_NUMERIC_STRING<br>
|
||
|
||
WScript.Echo "Value: " & Y.NumericString<br>
|
||
Case ADSTYPE_BOOLEAN<br>
|
||
|
||
WScript.Echo "Value: " & Y.Boolean<br>
|
||
Case ADSTYPE_INTEGER<br>
|
||
|
||
WScript.Echo "Value: " & Y.Integer<br>
|
||
//... and
|
||
more here.... <br>
|
||
Next<br>
|
||
Next<br>
|
||
<br>
|
||
</font><font face="Verdana" size="2">Back to <a href="#top">top</a></font>
|
||
<hr color="#0080C0">
|
||
<p><font face="Verdana" color="#0080C0" size="2"><b><a name="ntBinding"></a>WinNT:
|
||
Binding</b></font></p>
|
||
<p><font size="2" face="Verdana">In WinNT, you will be able to specify
|
||
the object's class as part of the ADsPath. This will speed up the bind
|
||
in most cases. Examples: "WinNT://ARCADIABAY/jsmith<b>,user</b>"
|
||
, "WinNT://ARCADIABAY/marketing<b>,group</b>" </font></p>
|
||
<p><font face="Verdana" size="2">Back to <a href="#top">top</a></font></p>
|
||
<p> </p>
|
||
<p><font size="2" color="#0080C0" face="Verdana"><b><a name="ntDC"></a>WinNT:
|
||
Communicating to a specific domain controller</b></font></p>
|
||
<p><font size="2" face="Verdana">If you specify bind to a domain or
|
||
objects in a domain, ADSI, by default, communicates to Primary Domain
|
||
Controller. In ADSI, there is a way, to select to a specific domain
|
||
controller. Specify the computer name with ',computer' as part of
|
||
ADsPath.<br>
|
||
Example: "WinNT://bdc02,computer" </font></p>
|
||
<p><font size="2" face="Verdana">Note: if the domain controller is a
|
||
backup domain controller, all the write operations will fail.</font></p>
|
||
<p><font face="Verdana" size="2">Back to <a href="#top">top</a></font></p>
|
||
<p><br>
|
||
<font face="Verdana" size="2" color="#0080C0"><b><a name="ntReadOnly"></a>WinNT:
|
||
Including backup domain controllers as part of selection</b></font></p>
|
||
<p><font face="Verdana" size="2">ADSI introduces a new flag (ADS_READONLY_SERVER)
|
||
for including back up domain controllers as part of selection criteria
|
||
when bind to a domain. ADSI may select either PDC or BDC. <br>
|
||
<br>
|
||
Example,<br>
|
||
Set dso = GetObject("WinNT:")<br>
|
||
Set obj = dso.OpenDSObject("WinNT://ARCADIABAY/jsmith,user",
|
||
"Administrator", "secret", ADS_READONLY_SERVER )<br>
|
||
<br>
|
||
</font><font size="2" face="Verdana">Note: if the domain controller is
|
||
a backup domain controller, all the write operations will fail.</font></p>
|
||
<p><font face="Verdana" size="2">Back to <a href="#top">top</a></font></p>
|
||
<hr color="#0080C0">
|
||
<p><font size="2" color="#0080C0" face="Verdana"><b><a name="adTree"></a>Active
|
||
Directory: Searching the entire domain tree</b></font></p>
|
||
<p><font size="2" face="Verdana">Although it's very possible, chasing
|
||
referral is discouraged for a domain tree search. The client may have
|
||
to connect n number of domain controllers before getting the complete
|
||
result set. Global catalog is designed for enterprise, tree search.
|
||
Since not all attributes are replicated to Global Catalog, you may
|
||
want to rebind to the targeted object once you retreive its
|
||
distinguished name.</font></p>
|
||
<p><font size="2" face="Verdana">example,<br>
|
||
Set gc = GetObject("GC://DC=Central, DC=ArcadiaBay, DC=COM")<br>
|
||
//... do ADO search here...</font></p>
|
||
<p><font face="Verdana" size="2">Back to <a href="#top">top</a></font></p>
|
||
<p><font size="2" color="#0080C0" face="Verdana"><b><a name="ObjectCategory"></a>Active
|
||
Directory: Object Class vs Object Category</b></font></p>
|
||
<p><font size="2" face="Verdana">Object class is a multi-valued
|
||
attribute. Active Directory does not index this attribute for many
|
||
reasons. Active Directory introduces a similar concept -
|
||
objectCategory, is an indexed, single value attributes. Include
|
||
objectCategory to search a certain type of class.<br>
|
||
<br>
|
||
Note: With the exception of (objectClass=*), you should always include
|
||
objectCategory for efficient searches. </font></p>
|
||
<p><font size="2" face="Verdana">Example,<br>
|
||
<br>
|
||
-Find all users<br>
|
||
(&(objectCategory=Person)(objectClass=user))</font></p>
|
||
<p><font size="2" face="Verdana">-Find all groups<br>
|
||
(objectCategory=Group)<br>
|
||
<br>
|
||
-Find all computers<br>
|
||
(objectCategory=Computer)<br>
|
||
<br>
|
||
-Find all object<br>
|
||
(objectClass=*)</font></p>
|
||
<p><font face="Verdana" size="2">Back to <a href="#top">top</a></font></p>
|
||
<p><font size="2" color="#0080C0" face="Verdana"><b><a name="fastBind"></a>LDAP:
|
||
Fast Bind</b></font></p>
|
||
<p><font size="2" face="Verdana">When you request an LDAP bind using
|
||
ADSI, one of things ADSI will do is to do a quick base search on that
|
||
object itself. This is done for the following reasons: 1) to make sure
|
||
the object exists 2) to get the object class so that ADSI will be able
|
||
to load the appropriate ADSI extensions and interfaces. By specifying
|
||
ADS_FAST_BIND, ADSI will skip this base search. This means that ADSI
|
||
does not check if object's existence, and ADSI only supports IADs
|
||
interface for this bound object. <br>
|
||
<br>
|
||
One scenario is updating attributes on objects found in a result set.
|
||
Since the objects are included in the result set, they are highly
|
||
likely exist in the directory. <br>
|
||
<br>
|
||
example, <br>
|
||
Set dso = GetObject("LDAP:")<br>
|
||
... do Search....<br>
|
||
while rs.EOF <br>
|
||
adsPath = rs.Fields("ADsPath")<br>
|
||
Set obj = dso.OpenDSObject(adsPath, vbNullString,
|
||
vbNullString, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND )<br>
|
||
rs.MoveNext<br>
|
||
wend<br>
|
||
<br>
|
||
Back to <a href="#top">top</a></font></p>
|
||
<p><font size="2" color="#0080C0" face="Verdana"><b><a name="operationalAttribute"></a>Active
|
||
Directory: Operational Attributes</b></font></p>
|
||
<p><font face="Verdana" size="2">Active Directory defines several
|
||
operational attributes. An operational attribute is an artifact
|
||
attribute. When one sets an operational attribute value, it, normally,
|
||
triggers some actions on the server. On the other hand, when one gets
|
||
an operational attribute value, the value itself, usually, is
|
||
calculated on the server. Like a normal attribute, an
|
||
operational attribute can be either multivalue or single value. The
|
||
operational attribute may be in read-only, write-only or read and
|
||
write mode.</font></p>
|
||
<p><font size="2" face="Verdana">Active Directory defines several
|
||
operational attributes,for examples: <i>canonicalName</i>, <i>allowedChildClassesEffective,
|
||
allowedAttributes, possibleInferirors, lowestUncommitedUSN</i>, and
|
||
many more.</font></p>
|
||
<p><font face="Verdana" size="2">To retrieve or set an operational
|
||
attribute value, you must use IDirectoryObject, or IADs::GetInfoEx<br>
|
||
<br>
|
||
'--- Retrieve a canonical name (every object in Active Directory has a
|
||
canonicalName)<br>
|
||
Set obj = GetObject("LDAP://CN=Cert Publishers,CN=Users,DC=Arcadiabay,DC=com")<br>
|
||
obj.GetInfoEx Array("canonicalName"), 0<br>
|
||
Debug.Print obj.Get("canonicalName") '---it should be:
|
||
arcadiabay.com/Users/Cert Publishers</font></p>
|
||
<p><font face="Tahoma" size="2">//----- Find all allowed attributes
|
||
for a given object in the current user security context -------</font></p>
|
||
<p><small><font face="Tahoma"> IIDirectoryObject *pObject;<br>
|
||
<br>
|
||
hr = ADsGetObject(L"LDAP://DC=activeds,DC=ntdev,DC=Microsoft,DC=Com",<br>
|
||
IID_IDirectoryObject,
|
||
(void**) &pObject );<br>
|
||
<br>
|
||
if (!SUCCEEDED(hr) )<br>
|
||
{<br>
|
||
return hr;<br>
|
||
}<br>
|
||
<br>
|
||
<br>
|
||
<br>
|
||
LPWSTR szAttrs[] = {
|
||
L"allowedAttributesEffective" };<br>
|
||
PADS_ATTR_INFO pAttrEntry;<br>
|
||
DWORD dwReturn;<br>
|
||
hr = pObject->GetObjectAttributes( szAttrs, 1,
|
||
&pAttrEntry, &dwReturn );<br>
|
||
<br>
|
||
if ( !SUCCEEDED(hr) )<br>
|
||
{<br>
|
||
pObject->Release();<br>
|
||
return hr;<br>
|
||
}<br>
|
||
<br>
|
||
if ( pAttrEntry )<br>
|
||
{<br>
|
||
for( DWORD idx=0; idx <
|
||
pAttrEntry->dwNumValues; idx++ )<br>
|
||
{<br>
|
||
|
||
printf("%ws\n", pAttrEntry->pADsValues[idx].CaseIgnoreString
|
||
);<br>
|
||
}<br>
|
||
FreeADsMem( pAttrEntry );<br>
|
||
}<br>
|
||
<br>
|
||
pObject->Release();<br>
|
||
return hr;<br>
|
||
</font></small></p>
|
||
<p><font face="Verdana" size="2">Back to <a href="#top">top</a></font></p>
|
||
<p><font size="2" color="#0080C0" face="Verdana"><b><a name="guid"></a>Active
|
||
Directory: GUID searching</b></font></p>
|
||
<p><font face="Verdana" size="2">Every object in Active Directory
|
||
carries GUID which guarantees to be unique. GUID never changes even
|
||
the object is renamed or moved. ADSI support GUID binding in the form
|
||
of LDAP://<GUID=xxxxxx> or GC://<GUID=xxx><br>
|
||
<br>
|
||
For example of GUID binding please see <a href="ad.htm#BindGUID">Active
|
||
Directory GUID Binding</a></font></p>
|
||
<p><font face="Verdana" size="2">Back to <a href="#top">top</a></font></p>
|
||
<p><font size="2" color="#0080C0" face="Verdana"><b><a name="mandatoryAttr"></a>Active
|
||
Directory: Listing Mandatory and Optional Attributes</b></font></p>
|
||
<p><font face="Verdana" size="2">Both mandatory and operational
|
||
attributes can be obtained from IADsClass. To get the IADsClass
|
||
interface, first you must know the class name of an object. Secondly,
|
||
compose the ADSPath from the class name and schema path. Third, bind
|
||
this object and ask for IADsClass. The MandatoryProperties and
|
||
OptionalProperties attributes contain in this interface.</font></p>
|
||
<p><font face="Verdana"> </font></p>
|
||
<font color="#0000ff" size="2">
|
||
<p></font><font size="2"><font face="Verdana">Dim x As IADsClass<br>
|
||
Dim classNams As String<br>
|
||
Dim provider As String</font></p>
|
||
<p></font><font size="2" face="Verdana">className = "user"<br>
|
||
provider = "LDAP://schema/"<br>
|
||
<br>
|
||
Set x = GetObject( provider & className )</font><font size="2"></p>
|
||
<p></font><font size="2" face="Verdana">For Each attr In
|
||
x.MandatoryProperties<br>
|
||
Debug.Print attr<br>
|
||
Next</font><font size="2"></p>
|
||
<p></font><font size="2" face="Verdana">For Each attr In
|
||
x.OptionalProperties<br>
|
||
Debug.Print attr<br>
|
||
Next</font></p>
|
||
<p><font face="Verdana" size="2">Back to <a href="#top">top</a></font></p>
|
||
<p><font size="2" face="Verdana" color="#0080C0"><b><a name="pageSize"></a>Active
|
||
Directory: Specifying Page Size </b></font></p>
|
||
<p><font size="2" face="Verdana">On subtree search, it's recommended
|
||
to specify the page size. Even if you're not expecting to find many
|
||
objects with the search. Paging allows the search to timeout in a re-startable
|
||
way, so that you can resume the search where it left off. Without
|
||
paging, the search will simply fail when it hits a time limit. Paging
|
||
also promote scalability for both clients and servers. <br>
|
||
<br>
|
||
ADSI handles the page size transparently. No need additional
|
||
programming required, except specifying the page size in the search
|
||
preferences.</font></p>
|
||
<p><font size="2" face="Verdana"><br>
|
||
<i>VB Example,<br>
|
||
</i>Command.Properties("Page Size") = 500<br>
|
||
<br>
|
||
'--Execute and enumerate ...<br>
|
||
<br>
|
||
<i>VC Example,</i><br>
|
||
ADS_SEARCHPREF_INFO prefInfo[ MAX_SEARCH_PREF ];<br>
|
||
<br>
|
||
prefInfo[dwCountPref].dwSearchPref = ADS_SEARCHPREF_PAGESIZE; <br>
|
||
prefInfo[dwCountPref].vValue.dwType = ADSTYPE_INTEGER;<br>
|
||
prefInfo[dwCountPref].vValue.Integer = m_nPageSize;<br>
|
||
dwCountPref++;<br>
|
||
<br>
|
||
hr = m_pSearch->SetSearchPreference( prefInfo, dwCountPref )</font></p>
|
||
<p><font size="2" face="Verdana">Back to <a href="#top">top</a></font></p>
|
||
<p><font size="2" color="#0080C0" face="Verdana"><a name="adSecurity"></a><b>Active
|
||
Directory: Security</b></font></p>
|
||
<p><font size="2" face="Verdana">Active Directory Security covers in
|
||
detail in the <a href="http://msdn.microsoft.com/developer/windows2000/adsi/actdirguide.asp">Active
|
||
Directory Programmer's Guide</a>. <br>
|
||
Two common scenarios are presented here. - Organizational Unit
|
||
Delegation and Setting ACL on an attribute<br>
|
||
<br>
|
||
Example 1 - Organizational Unit Delegation</font></p>
|
||
<p><font size="2" face="Verdana">'---- Allow JSmith to create and
|
||
delete users in the sales organization ----------<br>
|
||
<br>
|
||
Dim ace As New AccessControlEntry<br>
|
||
Dim secDesc As IADsSecurityDescriptor<br>
|
||
Dim acl As IADsAccessControlList<br>
|
||
<br>
|
||
Set x = GetObject("LDAP://OU=Sales,DC=Arcadiay,DC=com")<br>
|
||
Set secDesc = x.Get("ntSecurityDescriptor")<br>
|
||
Set acl = secDesc.DiscretionaryAcl<br>
|
||
<br>
|
||
ace.ObjectType = "{BF967ABA-0DE6-11D0-A285-00AA003049E2}" '---
|
||
This is the User Class' schemaID GUID<br>
|
||
ace.AccessMask = ADS_RIGHT_DS_CREATE_CHILD Or ADS_RIGHT_DS_DELETE_CHILD<br>
|
||
ace.AceType = ADS_ACETYPE_ACCESS_ALLOWED_OBJECT<br>
|
||
ace.AceFlags = ADS_ACEFLAG_INHERIT_ACE<br>
|
||
ace.Flags = ADS_FLAG_OBJECT_TYPE_PRESENT<br>
|
||
ace.Trustee = "ARCADIABAY\JSmith"<br>
|
||
<br>
|
||
acl.AddAce ace<br>
|
||
secDesc.DiscretionaryAcl = acl<br>
|
||
x.Put "ntSecurityDescriptor", Array(secDesc)<br>
|
||
x.SetInfo<br>
|
||
<br>
|
||
<br>
|
||
Example 2 - Setting ACL on an attribute<br>
|
||
<br>
|
||
<20>-- Deny JSmith to write <20>Managed By<42> attributes<br>
|
||
</font><font size="2" face="Verdana">Dim ace As New AccessControlEntry<br>
|
||
Dim secDesc As IADsSecurityDescriptor<br>
|
||
Dim acl As IADsAccessControlList<br>
|
||
<br>
|
||
Set x = GetObject("LDAP://OU=Sales,DC=Arcadiay,DC=com")<br>
|
||
Set secDesc = x.Get("ntSecurityDescriptor")<br>
|
||
Set acl = secDesc.DiscretionaryAcl<br>
|
||
</font><font size="2" face="Verdana"><br>
|
||
ace.ObjectType = "{0296C120-40DA-11D1-A9C0-0000F80367C1}<7D> <20>Managed By<br>
|
||
ace.AccessMask = ADS_RIGHT_DS_WRITE_PROP<br>
|
||
ace.AceType = ADS_ACETYPE_ACCESS_DENIED_OBJECT<br>
|
||
ace.AceFlags = ADS_ACEFLAG_INHERIT_ACE<br>
|
||
ace.Flags = ADS_FLAG_OBJECT_TYPE_PRESENT<br>
|
||
ace.Trustee = "ARCADIABAY\JSmith"<br>
|
||
<br>
|
||
acl.AddAce ace<br>
|
||
secDesc.DiscretionaryAcl = acl<br>
|
||
x.Put "ntSecurityDescriptor", Array(secDesc)<br>
|
||
x.SetInfo<br>
|
||
</font></p>
|
||
<p><font face="Verdana" size="2">Back to <a href="#top">top</a></font></p>
|
||
<p><font face="Verdana" size="2" color="#0080C0"> </font></td>
|
||
</tr>
|
||
<tr>
|
||
<td width="43%"></td>
|
||
</tr>
|
||
</table>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</body>
|
||
</html>
|