From b5242101f9ee393cbc332a8bbeed102f2561be26 Mon Sep 17 00:00:00 2001 From: Neil Blakey-Milner Date: Tue, 22 Aug 2006 13:15:23 +0000 Subject: [PATCH] Add auto-signup for LDAP/ActiveDirectory authentication provider (including auto-creating AD groups). --- lib/groups/Group.inc | 9 +++++++++ plugins/ktstandard/ldap/ldapbaseauthenticationprovider.inc.php | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+), 0 deletions(-) diff --git a/lib/groups/Group.inc b/lib/groups/Group.inc index e286127..a3ed1c9 100644 --- a/lib/groups/Group.inc +++ b/lib/groups/Group.inc @@ -367,6 +367,15 @@ class Group extends KTEntity { ), $aOptions); } + function getByAuthenticationSourceAndDetails($oSource, $sDetails, $aOptions = null) { + $iSourceId = KTUtil::getId($oSource); + return KTEntityUtil::getByDict('Group', array( + 'authentication_source_id' => $iSourceId, + 'authentication_details_s1' => $sDetails, + ), $aOptions); + } + + function &createFromArray($aOptions) { return KTEntityUtil::createFromArray('Group', $aOptions); } } diff --git a/plugins/ktstandard/ldap/ldapbaseauthenticationprovider.inc.php b/plugins/ktstandard/ldap/ldapbaseauthenticationprovider.inc.php index da3948c..ee1bdab 100644 --- a/plugins/ktstandard/ldap/ldapbaseauthenticationprovider.inc.php +++ b/plugins/ktstandard/ldap/ldapbaseauthenticationprovider.inc.php @@ -32,6 +32,7 @@ class KTLDAPBaseAuthenticationProvider extends KTAuthenticationProvider { var $sNamespace = "ktstandard.authentication.ldapprovider"; var $aAttributes = array ("cn", "uid", "givenname", "sn", "mail", "mobile"); + var $aMembershipAttributes = array ("memberOf"); // {{{ KTLDAPBaseAuthenticationProvider function KTLDAPBaseAuthenticationProvider() { @@ -480,6 +481,83 @@ class KTLDAPBaseAuthenticationProvider extends KTAuthenticationProvider { exit(0); } // }}} + + // {{{ autoSignup + function autoSignup($sUsername, $sPassword, $aExtra, $oSource) { + $oAuthenticator =& $this->getAuthenticator($oSource); + $dn = $oAuthenticator->checkSignupPassword($sUsername, $sPassword); + + if (PEAR::isError($dn)) { + return; + } + if (!is_string($dn)) { + return; + } + + if (empty($dn)) { + return; + } + + $aResults = $oAuthenticator->getUser($dn); + $sUserName = $aResults[$this->aAttributes[1]]; + $sName = $aResults[$this->aAttributes[0]]; + $sEmailAddress = $aResults[$this->aAttributes[4]]; + $sMobileNumber = $aResults[$this->aAttributes[5]]; + + $oUser = User::createFromArray(array( + "Username" => $sUserName, + "Name" => $sName, + "Email" => $sEmailAddress, + "EmailNotification" => true, + "SmsNotification" => false, // FIXME do we auto-act if the user has a mobile? + "MaxSessions" => 3, + "authenticationsourceid" => $oSource->getId(), + "authenticationdetails" => $dn, + "authenticationdetails2" => $sUserName, + "password" => "", + )); + + if (PEAR::isError($oUser)) { + return; + } + + if (!is_a($oUser, 'User')) { + return; + } + + $this->_createSignupGroups($dn, $oSource); + + return $oUser; + } + + function _createSignupGroups($dn, $oSource) { + $oAuthenticator =& $this->getAuthenticator($oSource); + $aGroupDNs = $oAuthenticator->getGroups($dn); + foreach ($aGroupDNs as $sGroupDN) { + $oGroup = Group::getByAuthenticationSourceAndDetails($oSource, $sGroupDN); + if (PEAR::isError($oGroup)) { + $oGroup = $this->_createGroup($sGroupDN, $oSource); + if (PEAR::isError($oGroup)) { + continue; + } + } + $oAuthenticator->synchroniseGroup($oGroup); + } + } + + function _createGroup($dn, $oSource) { + $oAuthenticator =& $this->getAuthenticator($oSource); + $aGroupDetails = $oAuthenticator->getGroup($dn); + $name = $aGroupDetails['cn']; + $oGroup =& Group::createFromArray(array( + "name" => $name, + "isunitadmin" => false, + "issysadmin" => false, + "authenticationdetails" => $dn, + "authenticationsourceid" => $oSource->getId(), + )); + return $oGroup; + } } class KTLDAPBaseAuthenticator extends Authenticator { @@ -544,6 +622,40 @@ class KTLDAPBaseAuthenticator extends Authenticator { return $res; } + function checkSignupPassword($sUsername, $sPassword) { + $aUsers = $this->findUser($sUsername); + if (empty($aUsers)) { + return false; + } + if (count($aUsers) !== 1) { + return false; + } + $dn = $aUsers[0]['dn']; + $config = array( + 'host' => $this->sLdapServer, + 'base' => $this->sBaseDN, + ); + $oLdap =& Net_LDAP::connect($config); + $res = $oLdap->reBind($dn, $sPassword); + if ($res === true) { + return $dn; + } + return $res; + } + + function getGroups($dn) { + if (PEAR::isError($this->oLdap)) { + return $this->oLdap; + } + + $oEntry = $this->oLdap->getEntry($dn, array('memberOf')); + if (PEAR::isError($oEntry)) { + return $oEntry; + } + $aAttr = $oEntry->attributes(); + return $aAttr['memberOf']; + } + /** * Searched the directory for a specific user @@ -619,6 +731,43 @@ class KTLDAPBaseAuthenticator extends Authenticator { return $aRet; } + function findUser($sUsername) { + global $default; + if (PEAR::isError($this->oLdap)) { + return $this->oLdap; + } + + $aParams = array( + 'scope' => 'sub', + 'attributes' => array('cn', 'dn', 'samaccountname'), + ); + $rootDn = $this->sBaseDN; + if (is_array($rootDn)) { + $rootDn = join(",", $rootDn); + } + $sObjectClasses = "|"; + foreach ($this->aObjectClasses as $sObjectClass) { + $sObjectClasses .= sprintf('(objectClass=%s)', trim($sObjectClass)); + } + $sSearchAttributes = "|"; + foreach ($this->aSearchAttributes as $sSearchAttribute) { + $sSearchAttributes .= sprintf('(%s=%s)', trim($sSearchAttribute), $sUsername); + } + $sFilter = sprintf('(&(%s)(%s))', $sObjectClasses, $sSearchAttributes); + $default->log->debug("Search filter is: " . $sFilter); + $oResult = $this->oLdap->search($rootDn, $sFilter, $aParams); + if (PEAR::isError($oResult)) { + return $oResult; + } + $aRet = array(); + foreach($oResult->entries() as $oEntry) { + $aAttr = $oEntry->attributes(); + $aAttr['dn'] = $oEntry->dn(); + $aRet[] = $aAttr; + } + return $aRet; + } + function searchGroups($sSearch) { if (PEAR::isError($this->oLdap)) { return $this->oLdap; -- libgit2 0.21.4