/plugins/auth/ldap/LDAPAuthPlugin.inc.php
PHP | 388 lines | 226 code | 33 blank | 129 comment | 49 complexity | 87466667168ca82854fab656841e9df1 MD5 | raw file
Possible License(s): GPL-2.0
- <?php
- /**
- * @file LDAPAuthPlugin.inc.php
- *
- * Copyright (c) 2000-2012 John Willinsky
- * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
- *
- * @class LDAPAuthPlugin
- * @ingroup plugins_auth_ldap
- *
- * @brief LDAP authentication plugin.
- */
- import('classes.plugins.AuthPlugin');
- class LDAPAuthPlugin extends AuthPlugin {
- /**
- * Called as a plugin is registered to the registry
- * @param $category String Name of category plugin was registered to
- * @return boolean True iff plugin initialized successfully; if false,
- * the plugin will not be registered.
- */
- function register($category, $path) {
- $success = parent::register($category, $path);
- $this->addLocaleData();
- return $success;
- }
- // LDAP-specific configuration settings:
- // - hostname
- // - port
- // - basedn
- // - managerdn
- // - managerpwd
- // - pwhash
- // - SASL: sasl, saslmech, saslrealm, saslauthzid, saslprop
- /** @var $conn resource the LDAP connection */
- var $conn;
- /**
- * Return the name of this plugin.
- * @return string
- */
- function getName() {
- return 'ldap';
- }
- /**
- * Return the localized name of this plugin.
- * @return string
- */
- function getDisplayName() {
- return __('plugins.auth.ldap.displayName');
- }
- /**
- * Return the localized description of this plugin.
- * @return string
- */
- function getDescription() {
- return __('plugins.auth.ldap.description');
- }
- //
- // Core Plugin Functions
- // (Must be implemented by every authentication plugin)
- //
- /**
- * Returns an instance of the authentication plugin
- * @param $settings array settings specific to this instance.
- * @param $authId int identifier for this instance
- * @return LDAPuthPlugin
- */
- function &getInstance($settings, $authId) {
- $returner = new LDAPAuthPlugin($settings, $authId);
- return $returner;
- }
- /**
- * Authenticate a username and password.
- * @param $username string
- * @param $password string
- * @return boolean true if authentication is successful
- */
- function authenticate($username, $password) {
- $valid = false;
- if ($this->open()) {
- if ($entry = $this->getUserEntry($username)) {
- $userdn = ldap_get_dn($this->conn, $entry);
- if ($this->bind($userdn, $password)) {
- $valid = true;
- }
- }
- $this->close();
- }
- return $valid;
- }
- //
- // Optional Plugin Functions
- //
- /**
- * Check if a username exists.
- * @param $username string
- * @return boolean
- */
- function userExists($username) {
- $exists = true;
- if ($this->open()) {
- if ($this->bind()) {
- $result = ldap_search($this->conn, $this->settings['basedn'], $this->settings['uid'] . '=' . $username);
- $exists = (ldap_count_entries($this->conn, $result) != 0);
- }
- $this->close();
- }
- return $exists;
- }
- /**
- * Retrieve user profile information from the LDAP server.
- * @param $user User to update
- * @return boolean true if successful
- */
- function getUserInfo(&$user) {
- $valid = false;
- if ($this->open()) {
- if ($entry = $this->getUserEntry($user->getUsername())) {
- $valid = true;
- $attr = ldap_get_attributes($this->conn, $entry);
- $this->userFromAttr($user, $attr);
- }
- $this->close();
- }
- return $valid;
- }
- /**
- * Store user profile information on the LDAP server.
- * @param $user User to store
- * @return boolean true if successful
- */
- function setUserInfo(&$user) {
- $valid = false;
- if ($this->open()) {
- if ($entry = $this->getUserEntry($user->getUsername())) {
- $userdn = ldap_get_dn($this->conn, $entry);
- if ($this->bind($this->settings['managerdn'], $this->settings['managerpwd'])) {
- $attr = array();
- $this->userToAttr($user, $attr);
- $valid = ldap_modify($this->conn, $userdn, $attr);
- }
- }
- $this->close();
- }
- return $valid;
- }
- /**
- * Change a user's password on the LDAP server.
- * @param $username string user to update
- * @param $password string the new password
- * @return boolean true if successful
- */
- function setUserPassword($username, $password) {
- if ($this->open()) {
- if ($entry = $this->getUserEntry($username)) {
- $userdn = ldap_get_dn($this->conn, $entry);
- if ($this->bind($this->settings['managerdn'], $this->settings['managerpwd'])) {
- $attr = array('userPassword' => $this->encodePassword($password));
- $valid = ldap_modify($this->conn, $userdn, $attr);
- }
- }
- $this->close();
- }
- }
- /**
- * Create a user on the LDAP server.
- * @param $user User to create
- * @return boolean true if successful
- */
- function createUser(&$user) {
- $valid = false;
- if ($this->open()) {
- if (!($entry = $this->getUserEntry($user->getUsername()))) {
- if ($this->bind($this->settings['managerdn'], $this->settings['managerpwd'])) {
- $userdn = $this->settings['uid'] . '=' . $user->getUsername() . ',' . $this->settings['basedn'];
- $attr = array(
- 'objectclass' => array('top', 'person', 'organizationalPerson', 'inetorgperson'),
- $this->settings['uid'] => $user->getUsername(),
- 'userPassword' => $this->encodePassword($user->getPassword())
- );
- $this->userToAttr($user, $attr);
- $valid = ldap_add($this->conn, $userdn, $attr);
- }
- }
- $this->close();
- }
- return $valid;
- }
- /**
- * Delete a user from the LDAP server.
- * @param $username string user to delete
- * @return boolean true if successful
- */
- function deleteUser($username) {
- $valid = false;
- if ($this->open()) {
- if ($entry = $this->getUserEntry($username)) {
- $userdn = ldap_get_dn($this->conn, $entry);
- if ($this->bind($this->settings['managerdn'], $this->settings['managerpwd'])) {
- $valid = ldap_delete($this->conn, $userdn);
- }
- }
- $this->close();
- }
- return $valid;
- }
- //
- // LDAP Helper Functions
- //
- /**
- * Open connection to the server.
- */
- function open() {
- $this->conn = ldap_connect($this->settings['hostname'], (int)$this->settings['port']);
- ldap_set_option($this->conn, LDAP_OPT_PROTOCOL_VERSION, 3);
- return $this->conn;
- }
- /**
- * Close connection.
- */
- function close() {
- ldap_close($this->conn);
- $this->conn = null;
- }
- /**
- * Bind to a directory.
- * $binddn string directory to bind (optional)
- * $password string (optional)
- */
- function bind($binddn = null, $password = null) {
- if (isset($this->settings['sasl'])) {
- // FIXME ldap_sasl_bind requires PHP5, haven't tested this
- return @ldap_sasl_bind($this->conn, $binddn, $password, $this->settings['saslmech'], $this->settings['saslrealm'], $this->settings['saslauthzid'], $this->settings['saslprop']);
- }
- return @ldap_bind($this->conn, $binddn, $password);
- }
- /**
- * Lookup a user entry in the directory.
- * @param $username string
- */
- function getUserEntry($username) {
- $entry = false;
- if ($this->bind($this->settings['managerdn'], $this->settings['managerpwd'])) {
- $result = ldap_search($this->conn, $this->settings['basedn'], $this->settings['uid'] . '=' . $username);
- if (ldap_count_entries($this->conn, $result) == 1) {
- $entry = ldap_first_entry($this->conn, $result);
- }
- }
- return $entry;
- }
- /**
- * Update User object from entry attributes.
- * TODO Abstract this to allow arbitrary LDAP <-> OJS schema mappings.
- * For now must be subclassed for other schemas.
- * TODO How to deal with deleted fields.
- * @param $user User
- * @param $uattr array
- */
- function userFromAttr(&$user, &$uattr) {
- $attr = array_change_key_case($uattr, CASE_LOWER); // Note: array_change_key_case requires PHP >= 4.2.0
- $firstName = @$attr['givenname'][0];
- $middleName = null;
- $initials = null;
- $lastName = @$attr['sn'][0];
- if (!isset($lastName))
- $lastName = @$attr['surname'][0];
- $affiliation = @$attr['o'][0];
- if (!isset($affiliation))
- $affiliation = @$attr['organizationname'][0];
- $email = @$attr['mail'][0];
- if (!isset($email))
- $email = @$attr['email'][0];
- $phone = @$attr['telephonenumber'][0];
- $fax = @$attr['facsimiletelephonenumber'][0];
- if (!isset($fax))
- $fax = @$attr['fax'][0];
- $mailingAddress = @$attr['postaladdress'][0];
- if (!isset($mailingAddress))
- $mailingAddress = @$attr['registeredAddress'][0];
- $biography = null;
- $interests = null;
- // Only update fields that exist
- if (isset($firstName))
- $user->setFirstName($firstName);
- if (isset($middleName))
- $user->setMiddleName($middleName);
- if (isset($initials))
- $user->setInitials($initials);
- if (isset($lastName))
- $user->setLastName($lastName);
- if (isset($affiliation))
- $user->setAffiliation($affiliation, AppLocale::getLocale());
- if (isset($email))
- $user->setEmail($email);
- if (isset($phone))
- $user->setPhone($phone);
- if (isset($fax))
- $user->setFax($fax);
- if (isset($mailingAddress))
- $user->setMailingAddress($mailingAddress);
- if (isset($biography))
- $user->setBiography($biography, AppLocale::getLocale());
- if (isset($interests))
- $user->setInterests($interests, AppLocale::getLocale());
- }
- /**
- * Update entry attributes from User object.
- * TODO How to deal with deleted fields.
- * @param $user User
- * @param $attr array
- */
- function userToAttr(&$user, &$attr) {
- // FIXME empty strings for unset fields?
- if ($user->getFullName())
- $attr['cn'] = $user->getFullName();
- if ($user->getFirstName())
- $attr['givenName'] = $user->getFirstName();
- if ($user->getLastName())
- $attr['sn'] = $user->getLastName();
- if ($a = $user->getLocalizedAffiliation())
- $attr['organizationName'] = $a;
- if ($user->getEmail())
- $attr['mail'] = $user->getEmail();
- if ($user->getPhone())
- $attr['telephoneNumber'] = $user->getPhone();
- if ($user->getFax())
- $attr['facsimileTelephoneNumber'] = $user->getFax();
- if ($user->getMailingAddress())
- $attr['postalAddress'] = $user->getMailingAddress();
- }
- /**
- * Encode password for the 'userPassword' field using the specified hash.
- * @param $password string
- * @return string hashed string (with prefix).
- */
- function encodePassword($password) {
- switch ($this->settings['pwhash']) {
- case 'md5':
- return '{MD5}' . base64_encode(pack('H*', md5($password)));
- case 'smd5':
- $salt = pack('C*', mt_rand(), mt_rand(), mt_rand(), mt_rand(), mt_rand(), mt_rand());
- return '{SMD5}' . base64_encode(pack('H*', md5($password . $salt)) . $salt);
- case 'sha':
- return '{SHA}' . base64_encode(pack('H*', sha1($password))); // Note: sha1 requres PHP >= 4.3.0
- case 'ssha':
- $salt = pack('C*', mt_rand(), mt_rand(), mt_rand(), mt_rand(), mt_rand(), mt_rand());
- return '{SSHA}' . base64_encode(pack('H*', sha1($password . $salt)) . $salt);
- case 'crypt':
- return '{CRYPT}' . crypt($password);
- default:
- //return '{CLEARTEXT}'. $password;
- return $password;
- }
- }
- }
- ?>