simpleid-ldap-1.0.0/0000755000175000017500000000000011752045466013520 5ustar danieldanielsimpleid-ldap-1.0.0/ldap-filesystem.store.inc0000644000175000017500000003550411752045466020457 0ustar danieldaniel $store_time) ? $identity_time : $store_time; } else { return NULL; } } /** * Verifies a set of credentials for a specified user. * * A set of credentials comprises: * * - A user name * - Some kind of verifying information, such as a plaintext password, a hashed * password (e.g. digest) or some other kind of identifying information. * * The user name is passed to this function using the $uid parameter. The user * name may or may not exist. If the user name does not exist, this function * must return false. * * The credentials are supplied as an array using the $credentials parameter. * Typically this array will be a subset of the $_POST superglobal passed to the * {@link user_login()} function. Thus it will generally contain the keys 'pass' and * 'digest'. * * This function must check whether the credentials supplied matches the credentials * for the specified user in the store. If for any reason that credentials * do not match, this function must return false. * * @param string $uid the name of the user to verify * @param array $credentials the credentials supplied by the browser * @return bool whether the credentials supplied matches those for the specified * user */ function store_user_verify_credentials($uid, $credentials) { $allowed_algorithms = array('md5', 'sha1'); $test_user = user_load($uid); if ($test_user == NULL) return false; if(!isset($test_user['auth_method']) || $test_user['auth_method'] == "STATIC") { return filesystem_user_verify_static_password($test_user, $credentials); } if($test_user['auth_method'] == "LDAP") { return filesystem_user_verify_ldap($uid, $test_user, $credentials); } return false; } /** * Verifies a user who relies on a statically defined password * in the identity file * @param array $test_user the user * @param array $credentials the credentials supplied by the browser */ function filesystem_user_verify_static_password($test_user, $credentials) { $hash_function_salt = explode(':', $test_user['pass'], 3); $hash = $hash_function_salt[0]; $function = (isset($hash_function_salt[1])) ? $hash_function_salt[1] : 'md5'; if (!in_array($function, $allowed_algorithms)) $function = 'md5'; $salt_suffix = (isset($hash_function_salt[2])) ? ':' . $hash_function_salt[2] : ''; if (call_user_func($function, $credentials['pass'] . $salt_suffix) != $hash) { return false; } return true; } /** * Verifies a user who uses LDAP for their password authentication * @param string $uid the user id * @param array $test_user the user * @param array $credentials the credentials supplied by the browser */ function filesystem_user_verify_ldap($uid, $test_user, $credentials) { /* We could try and look for the user by uid or by the mail attribute in LDAP. It depends on whether the uid entered in the login form contains the '@' symbol */ $ldap_attr = 'uid'; if(strpos($uid, '@')) { $ldap_attr = 'mail'; } if(LDAP_HOST == '' || LDAP_PORT == '' || LDAP_BASE_DN == '') { error_log('Missing an essential LDAP_ parameter'); return false; } $ldap_cfg = array ( 'host' => LDAP_HOST, 'port' => LDAP_PORT, 'version' => 3, 'starttls' => false, 'basedn' => LDAP_BASE_DN ); $ldap = Net_LDAP2::connect($ldap_cfg); // Testing for connection error if (PEAR::isError($ldap)) { error_log('Could not connect to LDAP-server: '.$ldap->getMessage()); return false; } $filter = Net_LDAP2_Filter::create($ldap_attr, 'equals', $uid); $requested_attributes = array('dn'); $ldap_res = $ldap->search(null, $filter, array('attributes' => $requested_attributes)); if (Net_LDAP2::isError($ldap_res)) { error_log('LDAP search failed: '.$search->getMessage()); $ldap->done(); return false; } if($ldap_res->count() == 0) { $error_msg = "Denied, No match found for $ldap_attr = $uid"; } else if($ldap_res->count() > 1) { $error_msg = "Denied, Multiple matches found for $ldap_attr = $uid"; } if($ldap_res->count() != 1) { error_log($error_msg); $ldap_res->done(); $ldap->done(); return false; } $ldap_entry = $ldap_res->shiftEntry(); $ldap_dn = $ldap_entry->dn(); if (Net_LDAP2::isError($ldap_dn)) { error_log('Could not retrieve dn from search result entry'); $ldap_res->done(); $ldap->done(); return false; } $authenticated = true; $ldap_rebind = $ldap->bind($ldap_dn, $credentials['pass']); if (Net_LDAP2::isError($ldap_rebind)) { $authenticated = false; error_log("bind failure".$ldap_rebind->getMessage()); } $ldap_res->done(); $ldap->done(); return $authenticated; } /** * Finds the user name from a specified OpenID Identity URI. * * @param string $identity the Identity URI of the user to load * @return string the user name for the Identity URI, or NULL if no user has * the specified Identity URI */ function store_get_uid($identity) { $uid = cache_get('identity', $identity); if ($uid !== NULL) return $uid; $r = NULL; $dir = opendir(SIMPLEID_IDENTITIES_DIR); while (($file = readdir($dir)) !== false) { $filename = SIMPLEID_IDENTITIES_DIR . '/' . $file; if ((filetype($filename) != "file") || (!preg_match('/^(.+)\.identity$/', $file, $matches))) continue; $uid = $matches[1]; $test_user = store_user_load($uid); cache_set('identity', $test_user['identity'], $uid); if ($test_user['identity'] == $identity) { $r = $uid; } } closedir($dir); return $r; } /** * Finds the user name from a specified client SSL certificate string. * * The client SSL certificate string comprises the certificate's serial number * (in capitals hex notation) and the distinguished name of the certificate's issuer * (with components joined using slashes), joined using a semi-colon. * * * @param string $identity the client SSL certificate string of the user to load * @return string the user name matching the client SSL certificate string, or NULL if no user has * client SSL certificate string */ function store_get_uid_from_cert($cert) { $uid = cache_get('cert', $cert); if ($uid !== NULL) return $uid; $r = NULL; $dir = opendir(SIMPLEID_IDENTITIES_DIR); while (($file = readdir($dir)) !== false) { $filename = SIMPLEID_IDENTITIES_DIR . '/' . $file; if ((filetype($filename) != "file") || (!preg_match('/^(.+)\.identity$/', $file, $matches))) continue; $uid = $matches[1]; $test_user = store_user_load($uid); if (isset($test_user['cert'])) { if (is_array($test_user['cert'])) { foreach ($test_user['cert'] as $test_cert) { if (trim($test_cert) != '') cache_set('cert', $test_cert, $uid); } foreach ($test_user['cert'] as $test_cert) { if ((trim($test_cert) != '') && ($test_cert == $cert)) $r = $uid; } } else { if (trim($test_cert) != '') { cache_set('cert', $test_user['cert'], $uid); if ($test_user['cert'] == $cert) $r = $uid; } } } } closedir($dir); return $r; } /** * Saves user data for a specific user name. * * This data is stored in the user store file. * * @param string $uid the name of the user * @param array $data the data to save * @param array $exclude an array of keys to exclude from the user store file. * These are generally keys which are stored in the identity file. * * @since 0.7 */ function store_user_save($uid, $data, $exclude = array()) { foreach ($exclude as $key) { if (isset($data[$key])) unset($data[$key]); } if (!_store_is_valid_name($uid)) { trigger_error("Invalid user name for filesystem store", E_USER_ERROR); return; } $store_file = SIMPLEID_STORE_DIR . "/$uid.usrstore"; $file = fopen($store_file, 'w'); fwrite($file, serialize($data)); fclose($file); } /** * Loads an application setting. * * @param string $name the name of the setting to return * @param mixed $default the default value to use if this variable has never been set * @return mixed the value of the setting * */ function store_get($name, $default = NULL) { global $simpleid_settings; if (!_store_is_valid_name($name)) return $default; if (!isset($simpleid_settings[$name])) { $setting_file = SIMPLEID_STORE_DIR . "/$name.setting"; if (file_exists($setting_file)) { $simpleid_settings[$name] = unserialize(file_get_contents($setting_file)); } else { return $default; } } return $simpleid_settings[$name]; } /** * Saves an application setting. * * @param string $name the name of the setting to save * @param mixed $value the value of the setting * */ function store_set($name, $value) { global $simpleid_settings; if (!_store_is_valid_name($name)) { trigger_error("Invalid setting name for filesystem store", E_USER_ERROR); return; } $simpleid_settings[$name] = $value; $setting_file = SIMPLEID_STORE_DIR . "/$name.setting"; $file = fopen($setting_file, 'w'); fwrite($file, serialize($value)); fclose($file); } /** * Deletes an application setting. * * @param string $name the name of the setting to delete * */ function store_del($name) { global $simpleid_settings; if (!_store_is_valid_name($name)) { trigger_error("Invalid setting name for filesystem store", E_USER_ERROR); return; } if (isset($simpleid_settings[$name])) unset($simpleid_settings[$name]); $setting_file = SIMPLEID_STORE_DIR . "/$name.setting"; if (file_exists($setting_file)) unlink($setting_file); } /** * Determines whether a name is a valid name for use with this store. * * For file system storage, a name is not valid if it contains either a * directory separator (i.e. / or \). * * @param string $name the name to check * @return boolean whether the name is valid for use with this store * */ function _store_is_valid_name($name) { return preg_match('!\A[^/\\\\]*\z!', $name); } ?> simpleid-ldap-1.0.0/ldap-filesystem.store.config.php-sample0000644000175000017500000000061311752045466023211 0ustar danieldaniel simpleid-ldap-1.0.0/README0000644000175000017500000000415211752045466014402 0ustar danieldaniel Installation ------------ a) copy the two files to your simpleID PHP directory (wherever the other simpleID *.inc files are kept) b) rename the config file mv ldap-filesystem.store.config.php-sample ldap-filesystem.store.config.php c) edit the config file, specify the LDAP server name and LDAP_BASE_DN d) modify the main simpleID config file, config.inc, and change the store parameter like so: define('SIMPLEID_STORE', 'ldap-filesystem'); e) for each user, create a normal identity file, but add this extra line in the file somewhere: auth_method="LDAP" If the module sees this auth_method, it will authenticate against LDAP. If no auth_method is specified, or if you specify auth_method="STATIC", it will just use the password hash within the identity file. How it works ------------ - the module makes an anonymous bind to the LDAP server - it looks at the username from the login form, - if it contains an @ symbol, it will search the LDAP server for a user with the `mail' attribute matching the login name - otherwise, it will search for a user with the matching `uid' attribute - if more than one LDAP entry is found, access is denied - it attempts to re-bind to the LDAP server using the DN of the matched LDAP entry, and using the password supplied in the login form - if the re-bind is successful, access is granted Copyright and license --------------------- Copyright 2012 Daniel Pocock This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see .