X-Git-Url: http://wagnertech.de/gitweb/gitweb.cgi/timetracker.git/blobdiff_plain/098a79f0819ebb89b7d48df4a6b154af4560f68e..9a23a8c0a51b7ec38a96f525484134f3cb85dc7e:/WEB-INF/lib/auth/Auth_ldap.class.php diff --git a/WEB-INF/lib/auth/Auth_ldap.class.php b/WEB-INF/lib/auth/Auth_ldap.class.php new file mode 100644 index 00000000..93fdebf4 --- /dev/null +++ b/WEB-INF/lib/auth/Auth_ldap.class.php @@ -0,0 +1,288 @@ + array()); is used in config.php. +// Note 2: search is likely to not work properly with OpenLDAP as well because of Windows specific filtering code in there +// (we are looking for matches for Windows-specific samaccountname property). Search needs to be redone during the next +// refactoring effort. + + +/** +* Auth_ldap class to authenticate users against an LDAP server (Windows AD, OpenLDAP, and others). +* @package TimeTracker +*/ +class Auth_ldap extends Auth { + var $params; + + function Auth_ldap($params) + { + $this->params = $params; + if (isset($GLOBALS['smarty'])) { + $GLOBALS['smarty']->assign('Auth_ldap_params', $this->params); + } + } + + function ldap_escape($str){ + $illegal = array("(", ")", "#"); + $legal = array(); + foreach ($illegal as $id => $char) { + $legal[$id] = "\\".$char; + } + $str = str_replace($illegal, $legal,$str); //replace them + return $str; + } + + /** + * Authenticate user against LDAP server. + * + * @param string $login + * @param string $password + * @return mixed + */ + function authenticate($login, $password) + { + if (!function_exists('ldap_bind')) { + die ('php_ldap extension not loaded!'); + } + + if (empty($this->params['server']) || empty($this->params['base_dn'])) { + die('You must set server and base_dn in AUTH_MODULE_PARAMS in config.php'); + } + + $member_of = @$this->params['member_of']; + + $lc = ldap_connect($this->params['server']); + + if (defined('AUTH_DEBUG') && isTrue(AUTH_DEBUG)) { + echo '
'; + echo '$lc='; var_dump($lc); echo '
'; + echo 'ldap_error()='; echo ldap_error($lc); echo '
'; + } + + if (!$lc) return false; + + ldap_set_option($lc, LDAP_OPT_PROTOCOL_VERSION, 3); + ldap_set_option($lc, LDAP_OPT_REFERRALS, 0); + if (defined('AUTH_DEBUG') && isTrue(AUTH_DEBUG)) { + ldap_set_option($lc, LDAP_OPT_DEBUG_LEVEL, 7); + } + + // We need to handle Windows AD and OpenLDAP differently. + if ($this->params['type'] != 'openldap') { + + // check if the user specified full login + if (strpos($login, '@') === false) { + // append default domain + $login .= '@' . $this->params['default_domain']; + } + + + if (defined('AUTH_DEBUG') && isTrue(AUTH_DEBUG)) { + echo '$login='; var_dump($login); echo '
'; + } + + $lb = @ldap_bind($lc, $login, $password); + + if (defined('AUTH_DEBUG') && isTrue(AUTH_DEBUG)) { + echo '$lb='; var_dump($lb); echo '
'; + echo 'ldap_error()='; echo ldap_error($lc); echo '
'; + } + + if (!$lb) { + ldap_unbind($lc); + return false; + } + + if ($member_of) { + // get groups + + $filter = 'samaccountname='.Auth_ldap::ldap_escape($login); + $fields = array('samaccountname', 'mail', 'memberof', 'department', 'displayname', 'telephonenumber', 'primarygroupid'); + $sr = @ldap_search($lc, $this->params['base_dn'], $filter, $fields); + + if (defined('AUTH_DEBUG') && isTrue(AUTH_DEBUG)) { + echo '$sr='; var_dump($sr); echo '
'; + echo 'ldap_error()='; echo ldap_error($lc); echo '
'; + } + + // if search failed it's likely that account is disabled + if (!$sr) { + ldap_unbind($lc); + return false; + } + + $entries = @ldap_get_entries($lc, $sr); + + if (defined('AUTH_DEBUG') && isTrue(AUTH_DEBUG)) { + echo '$entries='; var_dump($entries); echo '
'; + echo 'ldap_error()='; echo ldap_error($lc); echo '
'; + } + + if ($entries === false) { + ldap_unbind($lc); + return false; + } + + $groups = array(); + + // extract group names from + // assuming the groups are in format: CN=,... + for ($i = 0; $i < @$entries[0]['memberof']['count']; $i++) { + $grp = $entries[0]['memberof'][$i]; + $grp_fields = explode(',', $grp); + $groups[] = substr($grp_fields[0], 3); + } + + if (defined('AUTH_DEBUG') && isTrue(AUTH_DEBUG)) { + echo '$member_of'; var_dump($member_of); echo '
'; + }; + + // check for group membership + foreach ($member_of as $check_grp) { + if (!in_array($check_grp, $groups)) { + ldap_unbind($lc); + return false; + } + } + } + + ldap_unbind($lc); + + // handle special case - admin account, strip domain part + if (strpos($login, 'admin@') !== false) { + $login = substr($login, 0, 5); + } + + return array('login' => $login, 'data' => $entries, 'member_of' => $groups); + } else { + + // Assuming OpenLDAP server. + $login_oldap = 'uid='.$login.','.$this->params['base_dn']; + + if (defined('AUTH_DEBUG') && isTrue(AUTH_DEBUG)) { + echo '$login_oldap='; var_dump($login_oldap); echo '
'; + } + + // check if the user specified full login + if (strpos($login, '@') === false) { + // append default domain + $login .= '@' . $this->params['default_domain']; + } + + $lb = @ldap_bind($lc, $login_oldap, $password); + + if (defined('AUTH_DEBUG') && isTrue(AUTH_DEBUG)) { + echo '$lb='; var_dump($lb); echo '
'; + echo 'ldap_error()='; echo ldap_error($lc); echo '
'; + } + + if (!$lb) { + ldap_unbind($lc); + return false; + } + + if ($member_of) { + // get groups + + $filter = 'samaccountname='.Auth_ldap::ldap_escape($login_oldap); + $fields = array('samaccountname', 'mail', 'memberof', 'department', 'displayname', 'telephonenumber', 'primarygroupid'); + $sr = @ldap_search($lc, $this->params['base_dn'], $filter, $fields); + + if (defined('AUTH_DEBUG') && isTrue(AUTH_DEBUG)) { + echo '$sr='; var_dump($sr); echo '
'; + echo 'ldap_error()='; echo ldap_error($lc); echo '
'; + } + + // if search failed it's likely that account is disabled + if (!$sr) { + ldap_unbind($lc); + return false; + } + + $entries = @ldap_get_entries($lc, $sr); + + if (defined('AUTH_DEBUG') && isTrue(AUTH_DEBUG)) { + echo '$entries='; var_dump($entries); echo '
'; + echo 'ldap_error()='; echo ldap_error($lc); echo '
'; + } + + if ($entries === false) { + ldap_unbind($lc); + return false; + } + + $groups = array(); + + // extract group names from + // assuming the groups are in format: CN=,... + for ($i = 0; $i < @$entries[0]['memberof']['count']; $i++) { + $grp = $entries[0]['memberof'][$i]; + $grp_fields = explode(',', $grp); + $groups[] = substr($grp_fields[0], 3); + } + + if (defined('AUTH_DEBUG') && isTrue(AUTH_DEBUG)) { + echo '$member_of'; var_dump($member_of); echo '
'; + }; + + // check for group membership + foreach ($member_of as $check_grp) { + if (!in_array($check_grp, $groups)) { + ldap_unbind($lc); + return false; + } + } + } + + ldap_unbind($lc); + + // handle special case - admin account, strip domain part + if (strpos($login, 'admin@') !== false) { + $login = substr($login, 0, 5); + } + + return array('login' => $login, 'data' => $entries, 'member_of' => $groups); + } + } + + function isPasswordExternal() { + return true; + } +} \ No newline at end of file