ADSI Concepts
It is necessary to understand some terminology before delving into ADSI programming.
Component Object Model (COM) – A technology that allows the creation of binary compatible software components. This simply means that a COM component is a chunk of software that may be accessed anywhere a COM system is available. This is regardless of location, language or even operating system. It helps to think of this in a similar fashion to the Java system. Java may run wherever a Java Virtual Machine (JVM) is available. COM is accessible wherever a COM subsystem is available. But do not confuse the purposes of COM and Java. They are two very different technologies with different purposes.
Interface – A set of functions that are packaged and grouped together according to purpose. COM components provide a number of Interfaces that are available for use in applications. For example later in this article I will demonstrate using the IADsContainer interface (the leading I designates this as an interface) to access an LDAP directory.
Provider – A provider is the software that services requests to some external resource. The resource may be the Active Directory, an LDAP director or an application such as Internet Information Services.
Binding – Binding is the process of connecting a provider to a physical instance of a resource. Simply put, if I want to manipulate objects in my AD domain called Johnson, I would first bind to the Johnson domain. Then I could create, modify, update, search for or delete objects in the Johnson AD at will.
[forums/incl/ad_inline.htm]
Using ADSI
In order to manipulate anything in a namespace with ADSI, you must first bind to it. After binding, you may perform any operations on objects in the namespace you wish.
A typical ADSI application follows this format. Note that this is not real code and is for illustration purposes only:
- declare variables: var1, var2, etc
- bind to a resource: var1 = bind to AD(Johnson)
- manipulate the resource
- var1->createuser
- var1->delete another user
- var1->enumerate all users in the Johnson domain
- End
Notice how the process of binding returns an object that is stored in a variable. The object returned is actually an interface variable. This interface variable is used as the tool to do the actual manipulation of the bound resource. That's about all there is to it. If you can understand this simple example, you are well on your way to using ADSI.
ADSI Examples
LDAP Example
This is an example of connecting to a Sun One Directory Server and enumerating the users in a branch of the directory:
- option explicit
- dim Container ' as IADsContainer
- dim Entry 'as IADs
- dim Where 'as String
- dim Filter 'as Variant
- Where = "/ou=People"
- set Container = GetObject ("LDAP://192.168.1.105:59822/DC=NET/DC=COMCAST/DC=IL/DC=HSD1" & Where)
- for each entry in Container
- wscript.echo entry.name
- wscript.echo entry.get("mail")
- next
Line 1 turns on explicit variable declaration. This makes it easier to catch typos in variable names.
Lines 2-5 declare variables for use within the script. This script is written using VBScript (vbs) and therefore does not use typed variables. Every variable is a variant (can hold a value of any type). However, I show the variable type as a comment for documentation purposes. It is also useful when moving a script between vbs and its big brother Visual Basic.
Line 6 sets the Where variable to the location in the directory where enumeration will begin.
Line 7 is where the interesting stuff begins. Here is where the provider is bound to my test directory. Notice that the ldap port use is 59822 instead of 389. Also the contents of the Where variable is concatenated to the connection string to form the full LDAP URL. The GetObject function returns object of type IADsContainer, which is a collection of directory entries.
Lines 8 and 11 form a loop around two console output statements that print the desired directory information.
Line 9 is an example of a property of the interface variable. Each directory entry interface object has a name property that corresponds to the name of the entry in the ldap directory.
Line 10 is an example of a property on the directory entry itself, not the interface variable. These types of properties must be accessed via the get method on the interface variable. This example gets the mail property which is typically an rfc822 email address.
Executing this script against my test LDAP server produces the following output:
C:\scripts>SunOneDirServerUserDump uid=KJohnson johnkel2000@comcast.net uid=RJohnson jonnroc@sbcglobal.net uid=tadmin C:\scripts\SunOneDirServerUserDump.vbs(12, 2) Active Directory: The directory property cannot be found in the cache.
Notice the error message on the last lines. This is because the mail field is undefined for the tadmin user.
Active Directory Example 1
This example shows how to enumerate objects in the Active Directory. This script takes up to two arguments. The first argument is a starting location in the directory to use for enumeration. The second is a filter to limit the returned results to a particular object type. To run this script, simply type the name of the script into a command prompt. adexa1.vbs
- 'adexa1.vbs
- option explicit 'Always use explicit variable declaration!!!
- dim RootDSE 'as IAD
- dim Container 'as IADsContainer
- dim Entry 'as IADs
- dim Location 'as String
- dim Filter 'as string
- if(WScript.Arguments.Count > 0) then
- Location = WScript.Arguments(0)
- end if
- if(WScript.Arguments.Count > 1) then
- Filter = WScript.Arguments(1)
- end if
- set RootDSE = GetObject("LDAP://RootDSE")
- set Container = GetObject("LDAP://"& Location & "," & RootDSE.get("DefaultNamingContext"))
- if(Filter "") then
- Container.Filter = Array(Filter)
- end if
- For Each Entry in Container
- wscript.echo Entry.Name
- Next
- Wscript.Quit
Line 1 is a comment. It contains the name of the script.
Line 2 turns on explicit variable declaration.
Lines 3-7 declare variables for use within the script.
Lines 8 - 10 check to see if at least one command line argument was specified. If so, its value will be used as the starting directory location for enumeration.
Lines 11-13 check to see if at least two command line arguments were specified. If so, the second argument will be used as the value of the container filter. This filter will determine which object classes in the container will be available for manipulation.
Line 14 gets the RootDSE of the directory. This is a standard LDAP v3 object that contains information about the directory.
Line 15 is where binding occurs. However, this time the LDAP connection string is constructed by concatenating the container with the Default Naming Context (the name of the domain) obtained via the RootDSE object.
Lines 16-18 set the filter if one was supplied on the command line.
Lines 19-21 print each entry in the container.
Line 22 explicitly ends the script.
Running this script on one of my test Windows 2003 Server machines produces the following output:
C:\scripts>adexa1.vbs cn=users user CN=Administrator CN=Guest CN=IUSR_SERVER1 CN=IWAM_SERVER1 CN=krbtgt CN=SUPPORT_388945a0
Windows NT Example
Yes that's right, Windows NT. I know you still remember it. This is just to show you that it did work in Windows NT. Not that any NT 4 boxes still exist to actually test this out…
- Dim Container 'as IOleDsContainer
- Dim NewUser 'as IOleDsUser
- Set Container = GetObject("@WinNT!JOHNSON")
- Set NewUser = Container.Create("User", "JSomebody")
- NewUser.AccountRestrictions.SetPassword("password")
- NewUser.SetInfo
0 comments:
Post a Comment