title: How to PHP ldap_search() to get user OU if I don't know the OU for base DN
body: <p>I have an Active-Directory structure where User objects reside in OU for example, IT, Technical, HR, Accounts etc.. I want to write a PHP script that authenticates the user with AD and depending on their Group to provide the aproperiate web services.</p>
  
  <p>ldap_search() requires base DN.
  I tried to search with </p>
  
  <pre><code>ldap_search($ldap, "dc=country,dc=company,dc=co,dc=uk", "(samaccountname=$username)", array("memberof"));
  </code></pre>
  
  <p>but PHP gives "Operation Error". If instead i specify the OU</p>
  
  <pre><code>ldap_search($ldap, "ou=sales,dc=country,dc=company,dc=co,dc=uk", "(samaccountname=jake)", array("memberof"));
  </code></pre>
  
  <p>then the search is ok.</p>
  
  <p>Is there a wildcard I can use?</p>
  
  <p>On a side note, should user objects be in OU at all? Because I am the noob who moved them inside in the first place!</p>
  
  <p>EDIT:
  With credits to JPBlanc for guiding me in the right direction and <a href="http://blog.redbranch.net/?p=76">http://blog.redbranch.net/?p=76</a></p>
  
  <p>The solution is to add 2 lines between connect and bind.</p>
  
  <pre><code>ldap_connect(..)
  ldap_set_option ($ldap, LDAP_OPT_REFERRALS, 0);
  ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
  ldap_bind(..)
  </code></pre>
  
  <p>Thanks =)</p>
  
  <p>EDIT 2 - Fullcode:</p>
  
  <pre><code>&lt;?php
  
  namespace ldap;
  
  abstract class AuthStatus
  {
      const FAIL = "Authentication failed";
      const OK = "Authentication OK";
      const SERVER_FAIL = "Unable to connect to LDAP server";
      const ANONYMOUS = "Anonymous log on";
  }
  
  // The LDAP server
  class LDAP
  {
      private $server = "127.0.0.1";
      private $domain = "localhost";
      private $admin = "admin";
      private $password = "";
  
      public function __construct($server, $domain, $admin = "", $password = "")
      {
          $this-&gt;server = $server;
          $this-&gt;domain = $domain;
          $this-&gt;admin = $admin;
          $this-&gt;password = $password;
      }
  
      // Authenticate the against server the domain\username and password combination.
      public function authenticate($user)
      {
          $user-&gt;auth_status = AuthStatus::FAIL;
  
          $ldap = ldap_connect($this-&gt;server) or $user-&gt;auth_status = AuthStatus::SERVER_FAIL;
          ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
          ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
          $ldapbind = ldap_bind($ldap, $user-&gt;username."@".$this-&gt;domain, $user-&gt;password);
  
          if($ldapbind)
          {
              if(empty($user-&gt;password))
              {
                  $user-&gt;auth_status = AuthStatus::ANONYMOUS;
              }
              else
              {
                  $result = $user-&gt;auth_status = AuthStatus::OK;
  
                  $this-&gt;_get_user_info($ldap, $user);
              }
          }
          else
          {
              $result = $user-&gt;auth_status = AuthStatus::FAIL;
          }
  
          ldap_close($ldap);
      }
  
      // Get an array of users or return false on error
      public function get_users()
      {       
          if(!($ldap = ldap_connect($this-&gt;server))) return false;
  
          ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
          ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
          $ldapbind = ldap_bind($ldap, $this-&gt;admin."@".$this-&gt;domain, $this-&gt;password);
  
          $dc = explode(".", $this-&gt;domain);
          $base_dn = "";
          foreach($dc as $_dc) $base_dn .= "dc=".$_dc.",";
          $base_dn = substr($base_dn, 0, -1);
          $sr=ldap_search($ldap, $base_dn, "(&amp;(objectClass=user)(objectCategory=person)(|(mail=*)(telephonenumber=*))(!(userAccountControl:1.2.840.113556.1.4.803:=2)))", array("cn", "dn", "memberof", "mail", "telephonenumber", "othertelephone", "mobile", "ipphone", "department", "title"));
          $info = ldap_get_entries($ldap, $sr);
  
          for($i = 0; $i &lt; $info["count"]; $i++)
          {
              $users[$i]["name"] = $info[$i]["cn"][0];
              $users[$i]["mail"] = $info[$i]["mail"][0];
              $users[$i]["mobile"] = $info[$i]["mobile"][0];
              $users[$i]["skype"] = $info[$i]["ipphone"][0];
              $users[$i]["telephone"] = $info[$i]["telephonenumber"][0];
              $users[$i]["department"] = $info[$i]["department"][0];
              $users[$i]["title"] = $info[$i]["title"][0];
  
              for($t = 0; $t &lt; $info[$i]["othertelephone"]["count"]; $t++)
                  $users[$i]["othertelephone"][$t] = $info[$i]["othertelephone"][$t];
  
              // set to empty array
              if(!is_array($users[$i]["othertelephone"])) $users[$i]["othertelephone"] = Array();
          }
  
          return $users;
      }
  
      private function _get_user_info($ldap, $user)
      {
          $dc = explode(".", $this-&gt;domain);
  
          $base_dn = "";
          foreach($dc as $_dc) $base_dn .= "dc=".$_dc.",";
  
          $base_dn = substr($base_dn, 0, -1);
  
          $sr=ldap_search($ldap, $base_dn, "(&amp;(objectClass=user)(objectCategory=person)(samaccountname=".$user-&gt;username."))", array("cn", "dn", "memberof", "mail", "telephonenumber", "othertelephone", "mobile", "ipphone", "department", "title"));
          $info = ldap_get_entries($ldap, $sr);
  
          $user-&gt;groups = Array();
          for($i = 0; $i &lt; $info[0]["memberof"]["count"]; $i++)
              array_push($user-&gt;groups, $info[0]["memberof"][$i]);
  
          $user-&gt;name = $info[0]["cn"][0];
          $user-&gt;dn = $info[0]["dn"];
          $user-&gt;mail = $info[0]["mail"][0];
          $user-&gt;telephone = $info[0]["telephonenumber"][0];
          $user-&gt;mobile = $info[0]["mobile"][0];
          $user-&gt;skype = $info[0]["ipphone"][0];
          $user-&gt;department = $info[0]["department"][0];
          $user-&gt;title = $info[0]["title"][0];
  
          for($t = 0; $t &lt; $info[$i]["othertelephone"]["count"]; $t++)
                  $user-&gt;other_telephone[$t] = $info[$i]["othertelephone"][$t];
  
          if(!is_array($user-&gt;other_telephone[$t])) $user-&gt;other_telephone[$t] = Array();
      }
  }
  
  class User
  {
      var $auth_status = AuthStatus::FAIL;
      var $username = "Anonymous";
      var $password = "";
  
      var $groups = Array();
      var $dn = "";
      var $name = "";
      var $mail = "";
      var $telephone = "";
      var $other_telephone = Array();
      var $mobile = "";
      var $skype = "";
      var $department = "";
      var $title = "";
  
      public function __construct($username, $password)
      {       
          $this-&gt;auth_status = AuthStatus::FAIL;
          $this-&gt;username = $username;
          $this-&gt;password = $password;
      }
  
      public function get_auth_status()
      {
          return $this-&gt;auth_status;
      }
   }
  ?&gt;
  </code></pre>
  
  <p>Usage:</p>
  
  <pre><code>$ldap = new ldap\LDAP("192.168.1.123", "company.com", "admin", "mypassword");
  $users = $ldap-&gt;get_users();
  </code></pre>