simpleid-ldap-1.0.0/ 0000755 0001750 0001750 00000000000 11752045466 013520 5 ustar daniel daniel simpleid-ldap-1.0.0/ldap-filesystem.store.inc 0000644 0001750 0001750 00000035504 11752045466 020457 0 ustar daniel daniel $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-sample 0000644 0001750 0001750 00000000613 11752045466 023211 0 ustar daniel daniel
/**
* The LDAP server name and TCP port.
*
* LDAP_HOST can also contain a full LDAP URL, which is necessary
* when specifying that LDAPS should be used, e.g.
*
* define('LDAP_HOST', 'ldaps://ldap.example.org:636');
*
*/
define('LDAP_HOST', 'ldap.example.org');
define('LDAP_PORT', 389);
/**
* The LDAP base DN for the search
*/
define('LDAP_BASE_DN', 'dc=example,dc=org');
?>
simpleid-ldap-1.0.0/README 0000644 0001750 0001750 00000004152 11752045466 014402 0 ustar daniel daniel
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 .