I am experiementing with integrating Active Directory into an intranet web application. I have read a bunch of tutorials on how to do this. Just wanted to ask if my logic is correct or if their is a better way to skin this cat.

My platform is:

MS Server 2003 Standard
Apache 1.3.31
Php 4.3.9
Mysql 4.0.21

I have set up php as a module and have installed and tested the PHP LDAP package (including the two dll required libeay32.dll & ssleay32.dll)

I am also going to use the LDAP module for apache.

My intent is to restrict the web application directory to a group of users via an .htaccess file using LDAP restriction.

I also want to populate the username and Display name from the authenticated user into the web page using environment variables to strip out the logged in username. I.E. the person visiting the intranet site will have logged into the active directory domain. I am a bit confused about how to retrieve this person's user name and then look it up in the active directory. I understand the look up process using LDAP to access the active directory and then performing a search based on the username to grab the Display Name etc from the ad directory entry, but I am not sure how to grab the logged in username of the person accessing the site. I know I can use the .htaccess to restrict the access based on their domain credentials but how to grab the actual username is confusing to me.

The other piece is I will then populate a list with users of a group based on active directory using a bound connection to the ad server with domain admin credentials. This is so the user can be switched. I will be restricting this to certain groups of persons.

My confusion lies in the explanation of the LDAP settings for the search and the original connection.

the base_dn string baffles me a bit as well as the use of things like ou (organizational unit?) and some of the other search qualifiers. I would also like a idiot definition of the DN string used for the initial connection. Anyway I have the groups i question set up in Active Directory.

Any pointers or suggestions would be appreciated. I will post code that works here once I muddle my way through.

I am looking at this point for a logical analysis of steps in the process or validation of my intended method as well as some explanation of the use of ldap functions.

Thanks Ahead,

Geoffrey

    Here is where I am at so far. Anyone care to help or critique:

    Base Class File: wldap.class.php

    Full Name: wrapper ldap class

    <?php
    
    //  Define Installed Class
    define('INSTALLED_WLDAP', 1);
    
    //  Check Dependancies
    if( !(defined('LDAP_USER')) ) define('LDAP_USER', '');
    if( !(defined('LDAP_PASS')) ) define('LDAP_PASS', '');
    if( !(defined('LDAP_DOMAIN')) ) define('LDAP_DOMAIN', '');
    if( !(defined('LDAP_PROTOCOL')) ) define('LDAP_PROTOCOL', 3);
    if( !(isset($path_root)) ) $path_root = "./../";
    if( !(defined('INSTALLED_REDIRECTION')) ) require_once("$path_root/common/redirection.php");
    
    
    //  Class wrapper for base dn
    class wBASEDN {
    
    var $ou;
    var $cn;
    var $dc;
    var $dom;
    
    function wBASEDN(){
    	$this->dc = array();
    	$this->ou = array();
    	$this->cn = array();
    }
    
    function add_element($type, $element){
    
    	switch($type) {
    		case "dc":
    			$this->dc[count($this->dc)] = $element;
    		break;
    		case "ou":
    			$this->ou[count($this->ou)] = $element;
    		break;
    		case "cn":
    			$this->cn[count($this->cn)] = $element;
    		break;
    		default:
    			redirect_user("Invalid Distinguished Name element element.", "error");
    
    	}
    }
    
    function _get(){
    
    	$base_dn = "";
    	for($i=0; $i<count($this->dc); $i++){
    		if(($i) > 0) $base_dn += ",";
    		$base_dn += "dc=$this->dc[$i]";
    	}
    	for($j=0; $j<count($this->cn); $j++){
    		if(($i+$j) > 0) $base_dn += ",";
    		$base_dn += "ou=$this->ou[$j]";
    	}
    	for($k=0; $k<count($this->cn); $k++){
    		if(($i+$j+$k) > 0) $base_dn += ",";
    		$base_dn += "cn=$this->cn[$i]";
    	}
    
    	return $base_dn;
    
    }
    
    }
    
    //  LDAP Wrapper Class and functionality
    class wLDAP {
    
    var $queue;
    var $top;
    var $bottom;
    
    var $rlink;
    
    var $is_open;
    
    var $base_dn;
    var $filter;
    var $columns;
    
    function wLDAP() {
    
    	$this->is_open = false;
    	$this->base_dn = new wBASEDN();
    	$this->filter = new wBASEDN();
    	$this->columns = array();
    
    }
    
    function &get_array_from_group($group) {
    
    	if( !($this->is_open) ) $this->_connect();
    
    	if( !($search = ldap_search($this->rlink, $this->base_dn->_get(), $this->filter->_get(), $this->columns)) ){
    		redirect_user("Unable to search LDAP Server.", "error");
    	}
    
    	if( !($group_array = ldap_get_entries($this->rlink, $search)) ){
    		redirect_user("Unable to get entries from LDAP search", "error");
    	}
    
    	return $group_array;
    
    }
    
    function _connect($ldap_domain=LDAP_DOMAIN, $ldap_protocol=LDAP_PROTOCOL, $ldap_user=LDAP_USER, $ldap_pass=LDAP_PASS){
    
    	if( !($resource_link = ldap_connect(LDAP_DOMAIN)) )
    		redirect_user("Unable to connect to LDAP Server.", "error");
    
    	if( !(ldap_set_option($resource_link, LDAP_OPT_PROTOCOL_VERSION, LDAP_PROTOCOL)) )
    		redirect_user("Unable to set LDAP Protocol Version.", "error");
    
    	if( !(ldap_bind($resource_link, LDAP_USER, LDAP_PASS)) )
    		redirect_user("Unable to bind to LDAP Server.", "error");
    
    	$this->rlink = $resource_link;
    
    }
    
    function _disconnect(){
    
    	ldap_unbind($this->rlink);
    
    }
    }
    
    ?>
    

    testing file: ldap_test.php

    <?php
    
    ob_start();
    
    $path_root = "./..";
    
    require_once('wldap.class.php');
    
    $ldap = new wLDAP();
    
    $ldap->base_dn->add_element('dc', 'com');
    $ldap->base_dn->add_element('dc', 'mysite');
    $ldap->base_dn->add_element('dc', 'subdomain');
    $ldap->base_dn->add_element('ou', 'Security Groups');
    
    $ldap->_connect();
    
    $ldap_return =& $ldap->get_array_from_group("All Homeland");
    
    echo (count($ldap_return) . " entries in array<br>\n");
    
    $ldap->_disconnect();
    
    ob_end_flush();
    
    
    ?>
    

    Both Files are stored in a sub directory of root application called common (just for reference if you see the $path_root variable.

    redirection function use headers to redirect to main index.php file where error message is displayed

    I found a primer that explains base_dn (base distinguished name) for active directory which helped.

    http://www.windowsnetworking.com/kbase/WindowsTips/Windows2000/AdminTips/ActiveDirectory/ActiveDirectoryNamingStandard.html

    Anyway I can't get the get entries to work so I think I have to bind to the active directory server with domain credentials and not anonymously. Is there an SSL consideration here? Am I missing anything huge.

    BTW the output buffer is needed to allow redirection as the warning messages generated by the failed ldap_get_entries would cause headers to be sent to the browser before the redirection function moves the user with the error message (graceful death)

    Thanks Ahead,
    Geoffrey

      if anyone is following this thread here is the latest classes. I worked out the DN questions : Base DN = Base distiguished name = the distinguished name identifier for the entry point into the ldap tree. ie if you were using active directory on a ldap server in the domain: mysubdomain.domain.com and you wanted to enter at a sub container of the root object (rootgroup) called (subgroup) you would use:

      "OU=subgroup,OU=rootgroup,DC=mysubdomain,DC=domain,DC=com"

      Anyway that confused the mess out of me and when i used and finally was able to connect via the free ldapbrowser I got a DN string that wasn't valid for the security group containers and had to figure that out through trial and error:

      current code needs a fix or class for filters and attribute returns in search string and will be augmented as I go:

      ############################################################
      ############################################################
      ##  Class:  wDName
      ##			wrapper class for distingushed name creation
      ##
      ##  A distingushed name is a way to uniquely describe a
      ##  ldap object.
      ##
      ##	cn - Common Name
      ##  ou - Organizational Unit
      ##  dc - domain component
      ##
      ##  when adding elements to the Distinguished Name order is
      ##  very important.
      ##	
      ##  * wDName stores information in FILO (First In Last Out)
      ##    form
      ##
      ##  EXAMPLES:
      ##  
      ##  A domain component (DC) of the type
      ##
      ##    mysubdomain.mydomain.com
      ##
      ##  would be entered using the add element like:
      ##  
      ##    require_once('wldap.class.php');
      ##    myDName = new wDName();
      ##    myDName->add_element('dc', 'mysubdomain');
      ##    myDName->add_element('dc', 'mydomain');
      ##    myDName->add_element('dc', 'com');
      ##
      ##  An Organizational Unit (OU) in active directory where
      ##  the root node or container was called
      ##    All Groups
      ##  and contained a Sub Group that was to be the beginning
      ##  of the LDAP search or entry into the LDAP directory
      ##  (Searches are performed downward) named
      ##     Sub Group
      ##
      ##    require_once('wldap.class.php');
      ##    myDName = new wDName();
      ##    myDName->add_element('ou', 'Sub Group');
      ##    myDName->add_element('ou', 'All Groups');
      ##
      ############################################################
      ############################################################
      
      class wDName {
      
      var $ou;
      var $cn;
      var $dc;
      var $dom;
      
      function wDName(){
      	$this->dc = array();
      	$this->ou = array();
      	$this->cn = array();
      }
      
      function add_element($type, $element){
      
      	switch($type) {
      		case "ou":
      			$this->ou[count($this->ou)] = $element;
      		break;
      		case "cn":
      			$this->cn[count($this->cn)] = $element;
      		break;
      		case "dc":
      			$this->dc[count($this->dc)] = $element;
      		break;
      		default:
      			redirect_user("Invalid Distinguished Name element element.", "error");
      
      	}
      }
      
      function _get(){
      
      	$base_dn = "";
      
      	for($i=0; $i<count($this->cn); $i++){
      		if(($i) > 0) 
      			$base_dn .= ",";
      		$base_dn .= "CN=";
      		$base_dn .= $this->cn[$i];
      	}
      	for($j=0; $j<count($this->ou); $j++){
      		if(($i+$j) > 0) 
      			$base_dn .= ",";
      		$base_dn .= "OU=";
      		$base_dn .= $this->ou[$j];
      	}
      	for($k=0; $k<count($this->dc); $k++){
      		if(($i+$j+$k) > 0) $base_dn .= ",";
      		$base_dn .= "DC=";
      		$base_dn .= $this->dc[$k];
      	}
      
      	return $base_dn;
      
      }
      
      }
      
      //  LDAP Wrapper Class and functionality
      class wLDAP {
      
      var $queue;
      var $top;
      var $bottom;
      
      var $rlink;
      
      var $is_open;
      
      var $base_dn;
      var $filter;
      var $columns;
      
      function wLDAP() {
      
      	$this->is_open = false;
      	$this->base_dn = new wDName();
      	$this->filter = new wDName();
      	$this->columns = array();
      
      }
      
      function &get_array_from_group($group) {
      
      	if( !($this->is_open) ) $this->_connect();
      
      	if( !($search = ldap_search($this->rlink, $this->base_dn->_get(), $this->filter->_get(), array("ou", "sn", "mail") )) ){
      		echo "Search";
      		//  redirect_user("Unable to search LDAP Server.", "error");
      	}
      
      	if( !($group_array = ldap_get_entries($this->rlink, $search)) ){
      		echo "Ldap entries";
      		// redirect_user("Unable to get entries from LDAP search", "error");
      	}
      
      	return $group_array;
      
      }
      
      function _connect($ldap_domain=LDAP_DOMAIN, $ldap_protocol=LDAP_PROTOCOL, $ldap_user=LDAP_USER, $ldap_pass=LDAP_PASS){
      
      	if( !($resource_link = ldap_connect(LDAP_DOMAIN, 389)) )
      		redirect_user("Unable to connect to LDAP Server.", "error");
      
      	$this->is_open = true;
      
      	if( !(ldap_set_option($resource_link, LDAP_OPT_PROTOCOL_VERSION, LDAP_PROTOCOL)) )
      		redirect_user("Unable to set LDAP Protocol Version.", "error");
      
      	if( !(ldap_bind($resource_link, LDAP_USER, LDAP_PASS)) )
      		echo ldap_error( $resource_link);
      		// redirect_user("Unable to bind to LDAP Server.", "error");
      
      
      	$this->rlink = $resource_link;
      
      }
      
      function _disconnect(){
      
      	ldap_unbind($this->rlink);
      
      }
      }
      

      -Geoffrey

        Write a Reply...