Active Directory with LDAP some thoughts and code

Creating and modifying plugins.
Post Reply
daFool
Regular
Posts: 15
Joined: Mon Jul 05, 2004 12:47 pm
Contact:

Active Directory with LDAP some thoughts and code

Post by daFool »

I tried to authenticate against Microsoft Server 2003 AD domain and as I am not a guru either in LDAP or in AD I ended up modifying code to get it work. :shock:

I added one new configuration option user_base which is used as starting point for searching user object and added choice of "AD" to the type select.

Then I added a branch that uses ldap_search instead of ldap_read to find the user object when type is AD. I also modified filter to be (&(objectclass=*)(sAMAccountName={$addData['username']})).

I am not the lord of our AD so I have no access to the schema and can not add serendipity_userlevel to it. I found that requesting an attribute that does not exist causes the whole search to fail. I lazily :twisted: remedied that by removing the whole attributes thing from the search. After these modifications I was able to log in using my AD account.

Without the serendipity_userlevel attribute the control of who can log in with AD account is controlled only by user_base.

If anyone is interested here are two patch files:

Code: Select all

*** serendipity_event_externalauth.php	2008-09-05 16:32:06.000000000 +0300
--- safe/serendipity_event_externalauth.php	2008-09-05 16:13:29.000000000 +0300
***************
*** 37,49 ****
          ));
          $propbag->add('configuration', array('enable_ldap', 'enable_logging',
  					     'host', 'port', 'rdn', 'source', 'userlevel', 'ldap_userlevel_attr',
! 					     'ldap_tls', 'firstlogin', 'auth_query', 'bind_user', 'bind_password', 'user_wysiwyg'));
          $propbag->add('groups', array('BACKEND_USERMANAGEMENT'));
      }
  
      function introspect_config_item($name, &$propbag)
      {
          switch($name) {
              case 'enable_ldap':
                  $propbag->add('type',        'boolean');
                  $propbag->add('name',        PLUGIN_EVENT_EXTERNALAUTH_ENABLE_LDAP);
--- 37,56 ----
          ));
          $propbag->add('configuration', array('enable_ldap', 'enable_logging',
  					     'host', 'port', 'rdn', 'source', 'userlevel', 'ldap_userlevel_attr',
! 					     'ldap_tls', 'firstlogin', 'auth_query', 'bind_user', 'bind_password', 'user_wysiwyg', 'user_base'));
          $propbag->add('groups', array('BACKEND_USERMANAGEMENT'));
      }
  
      function introspect_config_item($name, &$propbag)
      {
          switch($name) {
+ 	case 'user_base':
+ 	  $propbag->add('type','string');
+ 	  $propbag->add('name', PLUGIN_EVENT_EXTERNALAUTH_USERBASE);
+ 	  $propbag->add('description', PLUGIN_EVENT_EXTERNALAUTH_USERBASE_DESC);
+ 	  $propbag->add('default', 'OU=internal,OU=Users,OU=ourcorp,DC=root,DC=local');
+ 	  break;
+ 
              case 'enable_ldap':
                  $propbag->add('type',        'boolean');
                  $propbag->add('name',        PLUGIN_EVENT_EXTERNALAUTH_ENABLE_LDAP);
***************
*** 98,104 ****
                  $propbag->add('name',        PLUGIN_EVENT_EXTERNALAUTH_SOURCE);
                  $propbag->add('description', PLUGIN_EVENT_EXTERNALAUTH_SOURCE_DESC);
                  $propbag->add('default',     'LDAP');
!                 $propbag->add('select_values', array('LDAP' => 'LDAP'));
                  break;
  
              case 'userlevel':
--- 105,111 ----
                  $propbag->add('name',        PLUGIN_EVENT_EXTERNALAUTH_SOURCE);
                  $propbag->add('description', PLUGIN_EVENT_EXTERNALAUTH_SOURCE_DESC);
                  $propbag->add('default',     'LDAP');
!                 $propbag->add('select_values', array('LDAP' => 'LDAP', 'AD' => 'AD'));
                  break;
  
              case 'userlevel':
***************
*** 298,315 ****
  						     );
  				  $this->debugmsg('LDAP bind call: ' . $rdn);
  				  if ($valid = @ldap_bind($ds, $rdn, $addData['password'])) {
                                      $srch="(objectclass=*)";
                                      $attributes=array("objectclass","mail",$this->get_config('ldap_userlevel_attr'));
!                                     if ($res = @ldap_read($ds,$rdn,$srch,$attributes)) {
  				      $e = ldap_first_entry($ds,$res);
  				      $attr = ldap_get_attributes($ds,$e);
  				      $userlevel_attr = $this->get_config('ldap_userlevel_attr');
  				      if ($attr[$userlevel_attr] > -1) {
  					$valid_userlevel = $attr[$userlevel_attr][0];
  				      } else {
  					$valid_userlevel = $this->get_config('userlevel');
  				      }
!                                     }
  				  }
  				} else { // LDAP with protected access and messy schema
  				  $password = $addData['password'];
--- 305,338 ----
  						     );
  				  $this->debugmsg('LDAP bind call: ' . $rdn);
  				  if ($valid = @ldap_bind($ds, $rdn, $addData['password'])) {
+ 				    $this->debugmsg('Valid bind');
                                      $srch="(objectclass=*)";
                                      $attributes=array("objectclass","mail",$this->get_config('ldap_userlevel_attr'));
! 				    if($this->get_config('source')=="AD") {
! 				      $user_tree=$this->get_config('user_base');
! 				      $srch="(&(objectclass=*)(sAMAccountName={$addData['username']}))";
! 				      $this->debugmsg("Search $srch");
! 				      $res = @ldap_search($ds,$user_tree,$srch);
! 				    } else {
! 				      $user_tree=$rdn;
! 				      $res = @ldap_read($ds,$user_tree,$srch,$attributes); 
! 				    }
! 				  if ($res) {
! 				      $this->debugmsg('Read succeeded');
  				      $e = ldap_first_entry($ds,$res);
  				      $attr = ldap_get_attributes($ds,$e);
+ 				      $this->debugmsg(print_r($attr,true));
  				      $userlevel_attr = $this->get_config('ldap_userlevel_attr');
  				      if ($attr[$userlevel_attr] > -1) {
  					$valid_userlevel = $attr[$userlevel_attr][0];
  				      } else {
  					$valid_userlevel = $this->get_config('userlevel');
  				      }
!                                     } else {
! 				      $this->debugmsg('Read failed');
! 				    }
! 				  } else {
! 				    $this->debugmsg('Bind failed');
  				  }
  				} else { // LDAP with protected access and messy schema
  				  $password = $addData['password'];
And

Code: Select all

*** lang_en.inc.php	2008-09-05 16:30:40.000000000 +0300
--- safe/lang_en.inc.php	2008-09-05 15:08:50.000000000 +0300
***************
*** 39,41 ****
--- 39,43 ----
  
  @define('PLUGIN_EVENT_EXTERNALAUTH_USER_WYSIWYG', 'Wysiwyg enabled by default?');
  @define('PLUGIN_EVENT_EXTERNALAUTH_USER_WYSIWYG_DESC', 'Does new accounts are created with the "Use WYSIWYG editor on" by default?');
+ @define('PLUGIN_EVENT_EXTERNALAUTH_USERBASE','User tree base for AD-authentication.');
+ @define('PLUGIN_EVENT_EXTERNALAUTH_USERBASE_DESC','Where the users are located on your Active Directory.');

garvinhicking
Core Developer
Posts: 30022
Joined: Tue Sep 16, 2003 9:45 pm
Location: Cologne, Germany
Contact:

Re: Active Directory with LDAP some thoughts and code

Post by garvinhicking »

Hi!

Thanks a lot for sharing this here with us. I've never worked with AD at all, so I don't really understand that whole LDAP stuff. But with your help I guess that more people might get this to work :)

Regards,
Garvin
# Garvin Hicking (s9y Developer)
# Did I help you? Consider making me happy: http://wishes.garv.in/
# or use my PayPal account "paypal {at} supergarv (dot) de"
# My "other" hobby: http://flickr.garv.in/
Post Reply