Using PHP with Active Directory

I l @ ve RuBoard

Now that you have an idea of what Active Directory is, let's look at how you can make use of content within it.

The following examples use a simple structure for Active Directory (see Figure 11.3). It contains one domain called a-coda.com (the root of Active Directory is not shown in Figure 11.3, but assume that one is present) and under it an OU called myplace.

Figure 11.3. A sample Active Directory structure.

graphics/11fig03.gif

In the following examples you will build a simple web application to list members in, add members to, and delete members from both the a-coda.com domain and the myplace OU.

Using the PHP LDAP Extension

PHP has an LDAP extension that you can use to query X.500 directories.

Before you can make use of the LDAP extension, you must uncomment the following line in your PHP.ini file:

 extension=php_ldap.dll 

You can use the LDAP extension as shown in Listing 11.1.

Listing 11.1 Using PHP's LDAP Extension to Query Active Directory
 <html>  <body>  <p><font size="4">Active Directory Members</font></p>  <table width="100%" border="1" cellspacing="0" cellpadding="0">  <?php  //connect to LDAP server  if(!($ldap = ldap_connect("localhost"))) { die ("ldap server can not be reached");  } else { $oudc = "ou=myplace,dc=a-coda,dc=com";  $dn2 = "cn=terry, " . $oudc;  $password = "terry";       //look up OU       if (!($res = @ldap_bind($ldap, $dn2, $password))) {      print(ldap_error($ldap) . "<BR>");       die ("Could not bind to $dn");       } else {           //set search critia for OU            $filter="cn=*";                      //search OU                      $sr=ldap_search($ldap,$oudc,$filter);                      if (!$sr) {                                    die("search failed\n");                      } else {                          //get fields from search                           $info = ldap_get_entries($ldap, $sr);                           for ($i=0; $i<$info["count"]; $i++) {                                    //display fields                                print("<TR");                                     print("<TD width=15%>" .  $info[$i]["cn"][0] . " " . $info[$i]["sn"][0] . "</TD>");                                     print("<TD width=85%>" .  $info[$i]["mail"][0] . "</TD>");                                     print("</TR>");                           }                      }                 }  //disconnect from LDAP server  ldap_unbind($ldap);  }  ?>  </table>   </body>  </html> 

Using the ldap_connect function, you first connect to the Windows 2000 server that is hosting your Active Directory. (In this case, it is localhost, but you can also use a computer's name or IP address if it is known in that Windows 2000 domain.)

 if(!($ldap = ldap_connect("localhost"))) { 

Next you look up the LDAP server's OU using the ldap_bind function:

 $oudc = "ou=myplace,dc=a-coda,dc=com";  $dn2 = "cn=terry, " . $oudc;  $password = "terry";  if (!($res = @ldap_bind($ldap, $dn2, $password))) { 

The ldap_bind method requires that you know the OU's name and which domain it is in. In most cases, the ldap_bind function also requires a username and password. However, this is optional. The ldap_bind function will still work if no username and password are required and you want to connect anonymously. Active Directory keeps users visible on a global level, but LDAP lets you query only the contents of an OU, not globally (whereas as ADSI does). For security reasons, Active Directory only lets you query an OU using a user contained within that OU. Your OU, myplace, has the user Terry, so you use his username and password.

Next, using the ldap_search function, you search the OU for the details you want to extract from the OU:

 $filter="cn=*";  $sr=ldap_search($ldap,$oudc,$filter); 

Here you look up the common name (cn) of all the users in the myplace OU.

Next, using the ldap_get_entries function, you obtain the results of the search:

 $info = ldap_get_entries($ldap, $sr); 

Next you iterate through the results and display them:

 for ($i=0; $i<$info["count"]; $i++) { print("<TR");  print("<TD width=15%>" . $info[$i]["cn"][0] . " " . $info[$i]["sn"][0] .  "</TD>");  print("<TD width=85%>" . $info[$i]["mail"][0] . "</TD>");  print("</TR>");  } 

The results are returned as an array. You iterate through the array using a for loop:

 for ($i=0; $i<$info["count"]; $i++) { 

As you iterate through the array, you display each value in the array in turn :

 print("<TD width=15%" . $info[$i]["cn"][0] . " " . $info[$i]["sn"][0] .  "</TD>");  print("<TD width=85%>" . $info[$i]["mail"][0] . "</TD>"); 

To display each value in the array, you use the iterating value from the for loop (in this case, $i ) and the Active Directory resource property you want to display. (Because you are using LDAP, you must use LDAP syntax to access Active Directory resources. In this case, this means cn, or common name, and mail, or the email address.) The results returned by ldap_get_entries are all Active Directory properties (even those that don't hold any data).

As soon as your loop is complete, use the ldap_unbind function to disconnect from the Active Directory to free up system resources:

 ldap_unbind($ldap); 

If you run the script, you can see the contents of the myplace OU, as shown in Figure 11.4. As I mentioned, all the Active Directory properties are returned by the ldap_get_entries method, even those that don't hold data. You can see this in Figure 11.4, where the terry vasey user has an email address but the Mary Vasey user does not.

Figure 11.4. The results of the Active Directory myplace OU returned using the PHP LDAP extension.

graphics/11fig04.gif

Using PHP, COM, and ADSI

To make use of ADSI in PHP, you must make use of COM. Here you will see how to use COM, ADSI, and PHP to query and administer Active Directory.

ADSI's API is wrapped in a COM object (called the Active DS Type Library); however, PHP's COM methods do not support many of the data types the ADSI COM object returns. To overcome this, you will create an ADSI wrapper COM object in Visual Basic to expose some of the functionality of the ADSI COM object and to provide return types that you can use in PHP.

The ADSI Wrapper COM Object

Open Visual Basic and create a new ActiveX DLL. I have named my ActiveX DLL chapter11 and my ClassModule AD, but you can use any names you want as long as you reflect them in your PHP code. You also need to add a reference to the Active DS type library, as shown in Figure 11.5.

Figure 11.5. Adding a reference to the Active DS type library.

graphics/11fig05.gif

Using the ADSI Wrapper COM Object

The next stage is to add functions such as list, add, and delete to your ADSI COM wrapper object.

Using ADSI to List Global Users Within Active Directory

Remember that Active Directory sees users on a global scale and that using ADSI means access to this global scale. Therefore, this method lists all users, whether they are within an OU or not. Here you first add the function that does this to your COM object and then create the PHP code that makes use of this function.

You start by adding the function to your COM object. You add the following to your class's general declarations:

 Public MemberCount As Variant 

This is a global variable (it can be used across all your functions) that you use to keep track of how many users are in Active Directory. Next you add the function shown in Listing 11.2.

Listing 11.2 A Function to List Members Via ADSI
 Public Function ListMembers(ByRef adserver As String)       'array of users in AD       Dim MemberArray(100)       'AD type for AD user       Dim User As IADsUser       'AD type for AD container       Dim Container As IADsContainer       'variable of how many users in AD       Dim Count       'connect to AD       Set Container = GetObject("WinNT://" & adserver)            'select only users            Container.Filter = Array("User")            'iterate through users            For Each User In Container            'count users            Count = Count + 1            'add user's name to array            MemberArray(Count) = User.Name            Next            'add count to global user count            MemberCount = Count            'return array            ListMembers = MemberArray       Set Container = Nothing  End Function 

The function takes the name of a Windows 2000 server as its reference and returns all the global users within the Active Directory of that server as an array. To start, you declare some variables . Here you declare the size of the array you will use to store usernames and return from the function:

 Dim MemberArray(100) 

Next you declare an Active Directory reference, IADsUser . This variable type is a COM object associated with an Active Directory user:

 Dim User As IADsUser 

Next you declare an Active Directory reference, IADsContainer . This variable type is a COM object associated with an Active Directory reference:

 Dim Container As IADsContainer 

To complete your variable declaration, you declare the variable that counts how many users are in Active Directory:

 Dim Count 

Next you connect to Active Directory using the reference to the server you passed to the function:

 Set Container = GetObject("WinNT://" & adserver) 

Remember that Active Directory can contain many resources, including users, computers, and printers. Because you are only interested in users, you filter Active Directory to return only users:

 Container.Filter = Array("User") 

Next you iterate through each user in Active Directory:

 For Each User In Container 

As you iterate, you count each user. Using the count value as a reference, you add each name to the users array:

 Count = Count + 1  MemberArray(Count) = User.Name 

As soon as the array is populated , you add the value of your users count to the global users count and return the array to your function:

 MemberCount = Count  ListMembers = MemberArray 

To make use of the array your function returns, you must get at the value of your users count (because you used this value as the reference in your array). To do this, you use another function:

 Public Function GetMemberCount()       GetMemberCount = MemberCount  End Function 

This simple function returns the global count value.

Using the ADSI COM wrapper object in PHP is very straightforward. You can use the two functions shown in Listing 11.3.

Listing 11.3 PHP Code That Uses the ListMembers Function to List Members Within Active Directory
 <?php  //load the ADSI COM wrapper object  $adsicom = new COM("chapter11.AD");  //users in Active Directory  $members = $adsicom->ListMembers("emma");  //count of users in Active Directory  $membercount = $adsicom->GetMemberCount();  //iterate through users in Active Directory  for ($i = 1; $i <= $membercount; $i++)  {      print("<TR>");       print("<TD width=15%>$members[$i]</TD>");       print("<TD width=85%><A  HREF=ListMembers.php?delmem=yes&mem=$members[$i]>Delete Member</A></TD>");       print("</TR>");  }  ?> 

First you add a reference to your ADSI COM wrapper object:

 $adsicom = new COM("chapter11.AD"); 

Next you call on your ListMembers function, adding a reference to the target Windows 2000 server (and thus Active Directory). You receive the array of users in Active Directory of that Windows 2000 server:

 $members = $adsicom->ListMembers("emma"); 

Next you call on the GetMemberCount function to see how many users are in the array:

 $membercount = $adsicom->GetMemberCount(); 

Then you iterate through your array using the value from the GetMemberCount function to discover when you have reached the final value in the array:

 for ($i = 1; $i <= $membercount; $i++) 

Finally, as you iterate through the array, you display each value within the array:

 print("<TD width=15%>$members[$i]</TD>"); 

If you run this script, you see all the users within Active Directory, as shown in Figure 11.6. Using ADSI means that users are seen globally, so your users (Terry and Mary) from the myplace OU are displayed here.

Figure 11.6. Global users of Active Directory returned using the ADSI COM wrapper object and PHP.

graphics/11fig06.gif

Using ADSI to Delete Global Users Within Active Directory

You can also delete members from Active Directory. Listing 11.4 adds the function that does this to your COM object and then creates the PHP code that uses this function.

Listing 11.4 A Function to Delete Members from Active Directory Using ADSI
 Public Function RemoveMemberADSI(ByRef adserver As String, ByRef usertogo As String)       'AD type for AD container       Dim Container As IADsContainer       'connect to AD       Set Container = GetObject("WinNT://" & adserver)            'delete user            Container.Delete "User", usertogo            RemoveMemberADSI = True       Set Container = Nothing  End Function 

As a reference, this function takes the name of the Windows 2000 server (and thus Active Directory) and the name of the user to delete. Within the function, you first declare your variables ”in this case, Active Directory COM type IADsContainer :

 Dim Container As IADsContainer 

Next you connect to Active Directory using the reference to the server you passed to the function:

 Set Container = GetObject("WinNT://" & adserver) 

Finally you delete the user, using the name you passed to the function:

 Container.Delete "User", usertogo 

In order for this function to work, the name you pass to the function and the name listed in Active Directory must match. A possible upgrade to this function that you could make is to search for the user, confirm that the user exists, and then delete the user (returning an error message if the user cannot be found).

To use this function, you add a link to allow users to be deleted:

 print("<TD width=85%><A HREF=ListMembers.php?delmem=yes&mem=$members[$i]>Delete Member</ graphics/ccc.gif A></TD>"); 

Here you link back to your PHP script, passing a flag (to indicate you want to delete) and the name of the user to delete. In your PHP, you see if the delete flag has been raised. You call the delete function of the ADSI COM wrapper if it has:

 $adsicom = new COM("chapter11.AD");  if ($_REQUEST['delmem'] == "yes") {      $adsicom->RemoveMemberADSI("emma", $mem);  } 

In your script, you first load your ADSI COM wrapper object:

 $adsicom = new COM("chapter11.AD"); 

Next you check to see if the delete flag has been raised:

 if ($_REQUEST['delmem'] == "yes") { 

If it has, you call the RemoveMemberADSI function to delete the user. You must also pass the user's name to the function:

 $adsicom->RemoveMemberADSI("emma", $mem); 

If you look back at the running script (refer to Figure 11.6), you can see that as usernames are displayed, so is the option to delete the user. If you click the delete link, the user is deleted from Active Directory. (Note that Windows 2000 protects some users from deletion.) A possible upgrade to the script would be to catch such messages. (As the script currently stands, it displays an ugly error message.)

Using ADSI to Add Global Users to Active Directory

The final ADSI function to add to your ADSI COM wrapper is the capability to add users to Active Directory. Here you use a simple HTML form to post user details to the PHP script. Next you add the function that adds the user in your COM object and then creates the PHP code that joins the HTML to form the COM object.

The HTML form you will use is a simple form that adds the user's username, password, and full name. It is shown in Listing 11.5.

Listing 11.5 An HTML Form to Add Users to Active Directory
 <html>  <head>  <title>Untitled Document</title>  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">  </head>  <body bgcolor="#FFFFFF" text="#000000">  <p><font size="4">Add an Active Directory Member </font></p>  <form method="post" action="ListMembers.php?postdata=yes">    <table width="100%" border="0" cellspacing="0" cellpadding="0">      <tr>        <td width="10%">User Name</td>        <td width="90%">          <input type="text" name="uname">        </td>      </tr>      <tr>        <td width="10%">Password</td>        <td width="90%">          <input type="password" name="pword">        </td>      </tr>      <tr>        <td width="10%">Full Name</td>        <td width="90%">          <input type="text" name="fname">        </td>      </tr>    </table>    <p>      <input type="submit" name="Submit" value="Submit">      <input type="reset" value="Reset">    </p>  </form>  </body>  </html> 

You post the form values back to your PHP script, as well as a flag to indicate that you are adding users:

 <form method="post" action="ListMembers.php?postdata=yes"> 

Now that your HTML form has been created, you can create a function in your COM object to add the users to Active Directory. See Listing 11.6.

Listing 11.6 A Function to Add Users to Active Directory Using ADSI
 Public Function AddMemberADSI(ByRef adserver As String, ByRef uname As String, ByRef graphics/ccc.gif pword As String, ByRef fname As String)       'AD type for AD user       Dim User As IADsUser       'AD type for AD container       Dim Container As IADsContainer        'connect to AD       Set Container = GetObject("WinNT://" & adserver)       'create user       Set User = Container.Create("User", uname)            'set password            User.SetPassword (pword)            'set full name            User.FullName = fname            'save user to AD            User.SetInfo            AddMemberADSI = True       Set User = Nothing       Set Container = Nothing  End Function 

As a reference, this function takes the name of the Windows 2000 server (and thus Active Directory), the username, the user's password, and the user's full name. To start, you declare some variables. Here you declare an Active Directory reference, IADsUser . This variable type is a COM object associated with an Active Directory user.

 Dim User As IADsUser 

Next you declare an Active Directory reference, IADsContainer . This type is a COM object associated with an Active Directory reference:

 Dim Container As IADsContainer 

Next you connect to Active Directory using the reference to the server you passed to the function:

 Set Container = GetObject("WinNT://" & adserver) 

Next you create your user using the reference to the username you passed to the function:

 Set User = Container.Create("User", uname) 

The Container.Create method can create various Active Directory objects, including computers and users. Thus, you must explicitly declare that you are creating a user when using this method.

Next you set the user's password and full name using the references you passed to the function:

 User.SetPassword (pword)  User.FullName = fname 

Finally, you save the user to the Active Directory:

 User.SetInfo 

To tie together your HTML form and the AddMemberADSI function of your ADSI COM wrapper object, you modify your PHP script as follows :

 if($_REQUEST['postdata'] == "yes") {      $adsicom = new COM("chapter11.AD");       $adsicom->AddMemberADSI("emma", $uname, $pword, $fname);  } 

You first see if the HTML form was posted to the PHP script by catching the flag from your HTML form:

 if($_REQUEST['postdata'] == "yes") { 

If the HTML form was posted to your script, you first load your ADSI COM wrapper object:

 $adsicom = new COM("chapter11.AD"); 

Finally, you call your AddMemberADSI function, passing the username, password, and full name values from your HTML form:

 $adsicom->AddMemberADSI("emma", $uname, $pword, $fname); 

If you load the HTML form and add a new user, you see that a new user has been added.

Using PHP, COM, and LDAP Over ADSI

As I mentioned, you can also use LDAP with ADSI. To do this, you use the ADSI COM wrapper object once more, but you add new functions to list and add and delete users via LDAP over ADSI.

Using LDAP Over ADSI to List Users Within an Active Directory OU

Remember that with LDAP, you see only users with a specified OU, so you must specify the OU in the script. Note that I have hard-coded the OU login username and password into the script. Normally you need some kind of login and password form. (Also remember that you should use secure logins utilizing SSL.)

Visual Basic Code

To the general declarations of your class, you add the following:

 Public LDAPMemberCount As Variant 

This is a global variable (usable across all your functions) that you use to keep track of how many users are in the OU. Next you add the function shown in Listing 11.7.

Listing 11.7 A Function to List Members of an OU Within Active Directory Using LDAP Over ADSI
 Public Function ListMembersLDAP(ByRef host As String, ByRef parent As String, ByRef ounit graphics/ccc.gif As String, ByRef LDAPLogInName As String, ByRef LDAPLogInPassword As String)      'variable of how many users in OU      Dim LDAPMemberArray(100)      'AD type for AD container      Dim Container2 As IADsContainer      'AD type for LDAP      Dim dso As IADsOpenDSObject      Dim parent_length, parent_one, parent_two, ldap_connect, child      'number of characters in parent variable e.g. a-coda.com = 10      parent_length = Len(parent)      'split front portion of parent variable e.g. a-coda      parent_one = Left(parent, parent_length - 4)      'split back portion of parent variable e.g. com      parent_two = Right(parent, 3)      'make up LDAP connection string using variables passed to function and      'parent one and parent two      ldap_connect = "LDAP://" & host & "/ou=" & ounit & ",dc=" & parent_one & ",dc=" & graphics/ccc.gif parent_two      'create ADSI LDAP object      Set dso = GetObject("LDAP:")      'connect to AD using LDAP      Set Container2 = dso.OpenDSObject(ldap_connect, LDAPLogInName, LDAPLogInPassword, 0)          'filter only users          Container2.Filter = "User"          'iterate through users          For Each child In Container2              'count users              LDAPMemberCount = LDAPMemberCount + 1              'add users to array              LDAPMemberArray(LDAPMemberCount) = Mid(child.Name, 4,  Len(child.Name))          Next      'return array      ListMembersLDAP = LDAPMemberArray  End Function 

The function takes the name of a Windows 2000 server (and thus Active Directory), the domain name, the OU, and the OU login username and password as its reference. It then returns all the users within the specified OU of that server as an array. To start, you declare some variables. Here you declare the size of the array you will use to store usernames and return from the function:

 Dim LDAPMemberArray(100) 

Next you declare an Active Directory reference, IADsContainer . This variable type is a COM object associated with an Active Directory reference:

 Dim Container2 As IADsContainer 

Next you declare an Active Directory reference, IADsOpenDSObject . This variable type is a COM object associated with an LDAP object:

 Dim dso As IADsOpenDSObject 

Next you split the domain name into two component parts (for example, a-coda.com becomes a-coda and com):

 parent_length = Len(parent)  parent_one = Left(parent, parent_length - 4)  parent_two = Right(parent, 3) 

Next you create the LDAP connection string:

 ldap_connect = "LDAP://" & host & "/ou=" & ounit & ",dc=" & parent_one &  ",dc=" & parent_two 

Next you create an LDAP object and, using that object and the connection string, connect to Active Directory:

 Set dso = GetObject("LDAP:")  Set Container2 = dso.OpenDSObject(ldap_connect, LDAPLogInName,  LDAPLogInPassword 

Remember that Active Directory can contain many resources, from users to computers and printers. Because you are only interested in users, you filter Active Directory to return users only:

 Container2.Filter = "User" 

Next you iterate through each user in Active Directory:

 For Each child In Container2 

As you iterate, you count each user. Using the global count value as a reference, you add each name to your users array:

 LDAPMemberCount = LDAPMemberCount + 1  LDAPMemberArray(LDAPMemberCount) = Mid(child.Name, 4, Len(child.Name)) 

After your array is populated, you return the array to your function:

 ListMembersLDAP = LDAPMemberArray 

To make use of the array your function returns, you must get at the value of the users count (because you used this value as the reference in your array). To do this, you use another function:

 Public Function GetLDAPMemberCount()      GetLDAPMemberCount = LDAPMemberCount  End Function 

This simple function returns the global count value.

PHP Code

Using the ADSI COM wrapper object in PHP is very straightforward. You can use the two functions shown in Listing 11.8.

Listing 11.8 PHP Code That Uses the ListMembersLDAP Function to List Members of an OU Within Active Directory
 <?  //no OU found  if ($_REQUEST['ou'] == "") { print "Error: No organizational unit";  } else {     //load ADSI COM wrapper object      $adsicom = new COM("chapter11.AD");      //get users in OU      $members = $adsicom->ListMembersLDAP("emma", "acoda.com", $ou, "terry", "terry");      //get count of users in OU      $membercount = $adsicom->GetLDAPMemberCount();      //iterate through users      for ($i = 1; $i <= $membercount; $i++)      {         print("<TR>");          print("<TD width=15%>$members[$i]</TD>");          print("<TD width=85%>          <A HREF=ListMembers_LDAP.php?ou=$ou&delmem=yes&mem=$members[$i]>Delete Member</ graphics/ccc.gif A></TD>");          print("</TR>");      }  }  ?> 

First you check to see if an OU has been specified in the URL to your PHP script:

 if ($_REQUEST['ou'] == "") { 

To ensure that your ADSI COM wrapper object does not raise any errors if no OU is specified, you instead display an error message, as shown in Figure 11.7.

Figure 11.7. Error message diplayed if no OU is specified.

graphics/11fig07.gif

Accessing an OU with the ADSI COM Wrapper Object with No OU Specified

If you do specify an OU, your script continues. Here you first load the ADSI COM wrapper object:

 $adsicom = new COM("chapter11.AD"); 

Next you call the ListMembersLDAP function, passing the Windows 2000 (and hence Active Directory) server name, the domain name, the OU (remember that you pass it in your script's URL), and the username and password for a user within the specified OU. From this function, you get back the array of users in the specified OU.

 $members = $adsicom->ListMembersLDAP("emma", "acoda.com", $ou, "terry",  "terry"); 

Next you call the GetMemberCount function so that you know how many users are in the array:

 $membercount = $adsicom->GetLDAPMemberCount(); 

Next you iterate through the array using the value from the GetMemberCount function to discover when you have reached the final value in the array:

 for ($i = 1; $i <= $membercount; $i++) 

Finally, as you iterate through the array, you display each value in the array:

 print("<TD width=15%>$members[$i]</TD>"); 

If you run this script using the myplace OU you used earlier in the chapter, you will see all the users in that OU, as shown in Figure 11.8.

Figure 11.8. Accessing an OU with the ADSI COM wrapper object.

graphics/11fig08.gif

Using LDAP Over ADSI to Delete Users Within an Active Directory OU

You can delete members from an Active Directory OU as described in the following sections.

Visual Basic Code

The Visual Basic code is shown in Listing 11.9.

Listing 11.9 A Function to Delete Users Within an Active Directory OU Using LDAP Over ADSI
 Public Function RemoveMemberLDAP(ByRef host As String, ByRef parent As String, ByRef graphics/ccc.gif ounit As String, ByRef LDAPLogInName As String, ByRef LDAPLogInPassword As String, ByRef graphics/ccc.gif usertogo As String)      'AD type for AD container      Dim Container2 As IADsContainer      'AD type for LDAP      Dim dso As IADsOpenDSObject      Dim parent_length, parent_one, parent_two, ldap_connect, DelUser      'number of characters in parent variable e.g. a-coda.com = 10      parent_length = Len(parent)      'split front portion of parent variable e.g. a-coda      parent_one = Left(parent, parent_length - 4)      'split back portion of parent variable e.g. com      parent_two = Right(parent, 3)      'make up LDAP connection string using variables passed to function and      'parent one and parent two      ldap_connect = "LDAP://" & host & "/ou=" & ounit & ",dc=" & parent_one & ",dc=" & graphics/ccc.gif parent_two      'create ADSI LDAP object      Set dso = GetObject("LDAP:")      'connect to AD using LDAP      Set Container2 = dso.OpenDSObject(ldap_connect, LDAPLogInName,      LDAPLogInPassword, 0)          'format user string          DelUser = "CN=" & usertogo          'delete user          Container2.Delete "User", DelUser          RemoveMemberLDAP = True      Set dso = Nothing      Set Container2 = Nothing  End Function 

The function takes the name of a Windows 2000 server (and thus Active Directory), the domain name, the OU, the OU login username and password, and the username that you will delete from the OU as its reference. It then deletes the specified user from the specified OU. To start, you declare some variables. Here you declare an Active Directory reference, IADsContainer . This variable type is a COM object associated with an Active Directory reference.

 Dim Container2 As IADsContainer 

Next you declare an Active Directory reference, IADsOpenDSObject . This variable type is a COM object associated with an LDAP object.

 Dim dso As IADsOpenDSObject 

Next you split the domain name into two component parts (for example, a-coda.com becomes a-coda and com):

 parent_length = Len(parent)  parent_one = Left(parent, parent_length - 4)  parent_two = Right(parent, 3) 

Note that for four-letter top levels (such as a-coda.co.uk), your code is as follows:

 parent_length = Len(parent)  parent_one = Left(parent, parent_length - 4)  parent_two = Right(parent, 4) 

Next you create the LDAP connection string:

 ldap_connect = "LDAP://" & host & "/ou=" & ounit & ",dc=" & parent_one & ",dc=" & graphics/ccc.gif parent_two 

Next you create an LDAP object. You use that object and the connection string to connect to Active Directory:

 Set dso = GetObject("LDAP:")  Set Container2 = dso.OpenDSObject(ldap_connect, LDAPLogInName,  LDAPLogInPassword 

Next you format the username so that it follows LDAP conventions to indicate that the username is a user's common name:

 DelUser = "CN=" & usertogo 

Finally, you delete the user, using the formatted username:

 Container2.Delete "User", DelUser 

Note that for this function to work, the name you pass to the function and the name listed within the OU must match. A possible upgrade to this function that you could make is to first search for the user, confirm that the user exists (returning an error message if he doesn't), and then delete the user.

PHP Code

To use this function, you add a link to allow users to be deleted when they are listed:

 print("<TD width=85%> <A graphics/ccc.gif HREF=ListMembers_LDAP.php?ou=$ou&delmem=yes&mem=$members[$i]>Delete Member</A></TD>"); 

Here you link back to your PHP script, passing a flag (to indicate that you want to delete) and the name of the user to delete. In your PHP, you see if the delete flag has been raised. You call the delete function of the ADSI COM wrapper if it has.

 $adsicom = new COM("chapter11.AD");  if ($_REQUEST['delmem'] == "yes") { $adsicom->RemoveMemberLDAP("emma", "acoda.com", $ou, "terry", "terry", $mem);  } 

In the script, you first load your ADSI COM wrapper object:

 $adsicom = new COM("chapter11.AD"); 

Next you check to see if the delete flag has been raised:

 if ($_REQUEST['delmem'] == "yes") { 

If it has, you call the RemoveMemberLDAP function to delete the user. You must also pass the Windows 2000 (and hence Active Directory) server name, the domain name, the OU (remember that you pass this in your script's URL), the username and password for a user in the specified OU, and the username of the user you want to delete:

 $adsicom->RemoveMemberLDAP("emma", "acoda.com", $ou, "terry", "terry", $mem); 

If you look at the running script (refer to Figure 11.8), you can see that as the usernames are displayed, so too is the option to delete the user. If you click the delete link, the user is deleted from the specified OU. (Note that Windows 2000 protects some users from deletion.) A possible upgrade to the script would be to catch such messages. (As the script currently stands, it displays an ugly error message.)

Using LDAP Over ADSI to Add Users to an Active Directory OU

The final LDAP-over-ADSI function to add to your ADSI COM wrapper is the capability to add users to an Active Directory OU. Here you use a simple HTML form to post user details to the PHP script, add the user, and display the user in your OU.

HTML Code

The HTML form you will use is a simple form that adds the user's first name, last name, and password. It is shown in Listing 11.10.

Listing 11.10 An HTML Form to Add Users to an Active Directory OU
 <html>  <head>  <title>Untitled Document</title>  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">  </head>  <body bgcolor="#FFFFFF" text="#000000">  <p><font size="4">Add an Active Directory Member </font></p>  <form name="form1" method="post" action="ListMembers_LDAP.php?postdata=yes&ou=<?php print graphics/ccc.gif $ou ?>">    <table width="100%" border="0" cellspacing="0" cellpadding="0">      <tr>        <td width="10%">First Name</td>        <td width="90%">          <input type="text" name="fname">        </td>      </tr>      <tr>        <td width="10%">Last Name</td>        <td width="90%">          <input type="text" name="lname">        </td>      </tr>        <tr>        <td width="10%">Password</td>        <td width="90%">          <input type="password" name="pword">        </td>      </tr>    </table>    <p>      <input type="submit" name="Submit" value="Submit">      <input type="reset" name="Submit2" value="Reset">    </p>  </form>  <p>&nbsp; </p>  </body>  </html> 

The form also needs to maintain that the name of your OU is passed back to your script. If it isn't, your script returns the OU not found error message. To do this, I have wrapped the HTML into a PHP script and used a simple PHP script to take the OU from the form's URL and add it to the form's action command:

 <form name="form1" method="post" action="ListMembers_LDAP.php?postdata=yes&ou=<?php print graphics/ccc.gif $ou ?>"> 
Visual Basic Code

After your HTML is created, you can create the function with your COM object to add users to an Active Directory OU, as shown in Listing 11.11.

Listing 11.11 A Function to Add Users to an Active Directory OU Using LDAP Over ADSI
 Public Function AddMemberLDAP(ByRef host As String, ByRef parent As String, ByRef ounit graphics/ccc.gif As String, ByRef LDAPLogInName As String, ByRef LDAPLogInPassword As String, ByRef Name graphics/ccc.gif As Variant, ByRef LastName As Variant, ByRef Password As String)      'AD type for AD container      Dim Container2 As IADsContainer      'AD type for LDAP      Dim dso As IADsOpenDSObject      Dim parent_length, parent_one, parent_two, ldap_connect, DelUser      'number of characters in parent variable e.g. a-coda.com = 10      parent_length = Len(parent)      'split front portion of parent variable e.g. a-coda      parent_one = Left(parent, parent_length - 4)      'split back portion of parent variable e.g. com      parent_two = Right(parent, 3)      'make up LDAP connection string using variables passed to function and      'parent one and parent two      ldap_connect = "LDAP://" & host & "/ou=" & ounit & ",dc=" & parent_one & ",dc=" & graphics/ccc.gif parent_two      'create ADSI LDAP object      Set dso = GetObject("LDAP:")      'connect to AD using LDAP      Set Container2 = dso.OpenDSObject(ldap_connect, LDAPLogInName,      LDAPLogInPassword, 0)          'create user          Set usr = Container2.Create("user", "cn=" & Name)          'add user information          usr.Put "samAccountName", Name & LastName           usr.Put "givenName", Name          usr.Put "sn", LastName          usr.Put "displayName", Name          usr.Put "userPrincipalName", Name          'save user to AD          usr.SetInfo          'set user password          usr.SetPassword Password          'enable user          usr.AccountDisabled = False          'update user to AD          usr.SetInfo      Set dso = Nothing      Set Container2 = Nothing  AddMemberLDAP = True  End Function 

The function takes the name of a Windows 2000 server (and thus Active Directory), the domain name, the OU, and the OU login username and password, as well as the first name, last name, and password of the user you will add. It then adds the specified user to the specified OU. To start, you declare some variables. Here you declare an Active Directory reference, IADsContainer . This variable type is a COM object associated with an Active Directory reference:

 Dim Container2 As IADsContainer 

Next you declare an Active Directory reference, IADsOpenDSObject . This variable type is a COM object associated with an LDAP object:

 Dim dso As IADsOpenDSObject 

Next you split the domain name into two component parts (for example, a-coda.com becomes a-coda and com).

 parent_length = Len(parent)  parent_one = Left(parent, parent_length - 4)  parent_two = Right(parent, 3) 

Note that for four-letter top levels (such as a-coda.co.uk), your code is as follows:

 parent_length = Len(parent)  parent_one = Left(parent, parent_length - 4)  parent_two = Right(parent, 4) 

Next you create the LDAP connection string:

 ldap_connect = "LDAP://" & host & "/ou=" & ounit & ",dc=" & parent_one & ",dc=" & graphics/ccc.gif parent_two 

Next you create an LDAP object. You use that object and the connection string to connect to Active Directory:

 Set dso = GetObject("LDAP:")  Set Container2 = dso.OpenDSObject(ldap_connect, LDAPLogInName,  LDAPLogInPassword 

Next you create the user:

 Set usr = Container2.Create("user", "cn=" & Name) 

Next you add some resource properties to the user and save the user to Active Directory:

 usr.Put "samAccountName", Name & LastName  usr.Put "givenName", Name  usr.Put "sn", LastName  usr.Put "displayName", Name  usr.Put "userPrincipalName", Name  usr.SetInfo 

ADSI reflects resource properties in its IADsUser COM object (which you create when you use the create method of an IADsContainer COM object ” in this case, Container2.Create ) differently from the way in which Active Directory does. The LDAP syntax mapping to resource properties and ADSI mapping are different. This means that when you use the IADsUser COM object, you must be aware of this change of syntax. (For further information, see http://msdn.microsoft.com/library/en-us/netdir/adsi/mapping_between_iadsuser_properties_and_active_directory_properties.asp.)

Next you set the password for the user:

 usr.SetPassword Password 

You must create and save the user to Active Directory before you create the password. If you try to set the password before saving the user, you will receive an error.

Next you enable the user:

 usr.AccountDisabled = False 

By default, users you create using LDAP over ADSI are disabled. As was done here, you can enable the new user in your code or by using Active Directory GUI tools.

Finally, you save the new information for your user to Active Directory:

 usr.SetInfo 
PHP Code

To tie together your HTML form and the AddMemberLDAP function of your ADSI COM wrapper object, you modify your PHP script as shown in Listing 11.12.

Listing 11.12 PHP Code That Uses the HTML Form and the AddMemberLDAP Function to Add Users to an Active Directory OU
 //if add user flag raised  if($_REQUEST['postdata'] == "yes") { //load ADSI COM wrapper object  $adsicom = new COM("chapter11.AD");  //add new user to OU  $adsicom->AddMemberLDAP("emma", "acoda.com", $ou, "terry", "terry", $fname, $lname, graphics/ccc.gif $pword);  } 

Here you see if the HTML form was posted to the PHP script by catching the flag from your HTML form:

 if($_REQUEST['postdata'] == "yes") { 

If the HTML form was posted to your script, you first load your ADSI COM wrapper object:

 $adsicom = new COM("chapter11.AD"); 

Finally, you call your AddMemberLDAP function, passing the name of a Windows 2000 server (and thus Active Directory), the domain name, the OU, and the OU login username and password, as well as the first name, last name, and password values from your HTML form.

 $adsicom->AddMemberLDAP("emma", "acoda.com", $ou, "terry", "terry", $fname, $lname, graphics/ccc.gif $pword); 

If you load the HTML form and add a new user, you will see that a new user has been added.

I l @ ve RuBoard


PHP Programming for Windows
PHP Programming for Windows (Landmark (New Riders))
ISBN: 0735711690
EAN: 2147483647
Year: 2002
Pages: 99

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net