2 // PukiWiki - Yet another WikiWikiWeb clone
4 // Copyright 2003-2018 PukiWiki Development Team
5 // License: GPL v2 or (at your option) any later version
7 // Authentication related functions
9 define('PKWK_PASSPHRASE_LIMIT_LENGTH', 512);
11 /////////////////////////////////////////////////
14 define('AUTH_TYPE_NONE', 0);
15 define('AUTH_TYPE_BASIC', 1);
16 define('AUTH_TYPE_EXTERNAL', 2);
17 define('AUTH_TYPE_FORM', 3);
19 define('AUTH_TYPE_EXTERNAL_REMOTE_USER', 4);
20 define('AUTH_TYPE_EXTERNAL_X_FORWARDED_USER', 5);
21 define('AUTH_TYPE_SAML', 6);
24 // Passwd-auth related ----
26 function pkwk_login($pass = '')
30 if (! PKWK_READONLY && isset($adminpass) &&
31 pkwk_hash_compute($pass, $adminpass) === $adminpass) {
34 sleep(2); // Blocking brute force attack
39 // Compute RFC2307 'userPassword' value, like slappasswd (OpenLDAP)
40 // $phrase : Pass-phrase
41 // $scheme : Specify '{scheme}' or '{scheme}salt'
42 // $prefix : Output with a scheme-prefix or not
43 // $canonical : Correct or Preserve $scheme prefix
44 function pkwk_hash_compute($phrase = '', $scheme = '{x-php-md5}', $prefix = TRUE, $canonical = FALSE)
46 if (! is_string($phrase) || ! is_string($scheme)) return FALSE;
48 if (strlen($phrase) > PKWK_PASSPHRASE_LIMIT_LENGTH)
49 die('pkwk_hash_compute(): malicious message length');
51 // With a {scheme}salt or not
53 if (preg_match('/^(\{.+\})(.*)$/', $scheme, $matches)) {
54 $scheme = $matches[1];
56 } else if ($scheme != '') {
57 $scheme = ''; // Cleartext
61 // Compute and add a scheme-prefix
62 switch (strtolower($scheme)) {
65 case '{x-php-crypt}' :
66 $hash = ($prefix ? ($canonical ? '{x-php-crypt}' : $scheme) : '') .
67 ($salt != '' ? crypt($phrase, $salt) : crypt($phrase));
72 $hash = ($prefix ? ($canonical ? '{x-php-md5}' : $scheme) : '') .
78 $hash = ($prefix ? ($canonical ? '{x-php-sha1}' : $scheme) : '') .
83 case '{x-php-sha256}' :
84 $hash = ($prefix ? ($canonical ? '{x-php-sha256}' : $scheme) : '') .
85 hash('sha256', $phrase);
89 case '{x-php-sha384}' :
90 $hash = ($prefix ? ($canonical ? '{x-php-sha384}' : $scheme) : '') .
91 hash('sha384', $phrase);
95 case '{x-php-sha512}' :
96 $hash = ($prefix ? ($canonical ? '{x-php-sha512}' : $scheme) : '') .
97 hash('sha512', $phrase);
102 $hash = ($prefix ? ($canonical ? '{CRYPT}' : $scheme) : '') .
103 ($salt != '' ? crypt($phrase, $salt) : crypt($phrase));
108 $hash = ($prefix ? ($canonical ? '{MD5}' : $scheme) : '') .
109 base64_encode(pkwk_hex2bin(md5($phrase)));
114 // MD5 Key length = 128bits = 16bytes
115 $salt = ($salt != '' ? substr(base64_decode($salt), 16) : substr(crypt(''), -8));
116 $hash = ($prefix ? ($canonical ? '{SMD5}' : $scheme) : '') .
117 base64_encode(pkwk_hex2bin(md5($phrase . $salt)) . $salt);
122 $hash = ($prefix ? ($canonical ? '{SHA}' : $scheme) : '') .
123 base64_encode(pkwk_hex2bin(sha1($phrase)));
128 // SHA-1 Key length = 160bits = 20bytes
129 $salt = ($salt != '' ? substr(base64_decode($salt), 20) : substr(crypt(''), -8));
130 $hash = ($prefix ? ($canonical ? '{SSHA}' : $scheme) : '') .
131 base64_encode(pkwk_hex2bin(sha1($phrase . $salt)) . $salt);
136 $hash = ($prefix ? ($canonical ? '{SHA256}' : $scheme) : '') .
137 base64_encode(hash('sha256', $phrase, TRUE));
142 // SHA-2 SHA-256 Key length = 256bits = 32bytes
143 $salt = ($salt != '' ? substr(base64_decode($salt), 32) : substr(crypt(''), -8));
144 $hash = ($prefix ? ($canonical ? '{SSHA256}' : $scheme) : '') .
145 base64_encode(hash('sha256', $phrase . $salt, TRUE) . $salt);
150 $hash = ($prefix ? ($canonical ? '{SHA384}' : $scheme) : '') .
151 base64_encode(hash('sha384', $phrase, TRUE));
156 // SHA-2 SHA-384 Key length = 384bits = 48bytes
157 $salt = ($salt != '' ? substr(base64_decode($salt), 48) : substr(crypt(''), -8));
158 $hash = ($prefix ? ($canonical ? '{SSHA384}' : $scheme) : '') .
159 base64_encode(hash('sha384', $phrase . $salt, TRUE) . $salt);
164 $hash = ($prefix ? ($canonical ? '{SHA512}' : $scheme) : '') .
165 base64_encode(hash('sha512', $phrase, TRUE));
170 // SHA-2 SHA-512 Key length = 512bits = 64bytes
171 $salt = ($salt != '' ? substr(base64_decode($salt), 64) : substr(crypt(''), -8));
172 $hash = ($prefix ? ($canonical ? '{SSHA512}' : $scheme) : '') .
173 base64_encode(hash('sha512', $phrase . $salt, TRUE) . $salt);
176 // LDAP CLEARTEXT and just cleartext
177 case '{cleartext}' : /* FALLTHROUGH */
179 $hash = ($prefix ? ($canonical ? '{CLEARTEXT}' : $scheme) : '') .
192 // LDAP related functions
194 function _pkwk_ldap_escape_callback($matches) {
195 return sprintf('\\%02x', ord($matches[0]));
198 function pkwk_ldap_escape_filter($value) {
199 if (function_exists('ldap_escape')) {
200 return ldap_escape($value, false, LDAP_ESCAPE_FILTER);
202 return preg_replace_callback('/[\\\\*()\0]/',
203 '_pkwk_ldap_escape_callback', $value);
206 function pkwk_ldap_escape_dn($value) {
207 if (function_exists('ldap_escape')) {
208 return ldap_escape($value, false, LDAP_ESCAPE_DN);
210 return preg_replace_callback('/[\\\\,=+<>;"#]/',
211 '_pkwk_ldap_escape_callback', $value);
215 // Basic-auth related ----
217 // Check edit-permission
218 function check_editable($page, $auth_enabled = TRUE, $exit_on_fail = TRUE)
220 global $_title_cannotedit, $_msg_unfreeze;
222 if (edit_auth($page, $auth_enabled, $exit_on_fail) && is_editable($page)) {
227 if ($exit_on_fail === FALSE) {
228 return FALSE; // Without exit
231 $body = $title = str_replace('$1',
232 htmlsc(strip_bracket($page)), $_title_cannotedit);
233 if (is_freeze($page))
234 $body .= '(<a href="' . get_base_uri() . '?cmd=unfreeze&page=' .
235 rawurlencode($page) . '">' . $_msg_unfreeze . '</a>)';
236 $page = str_replace('$1', make_search($page), $_title_cannotedit);
237 catbody($title, $page, $body);
244 * Whether the page is readable from current user or not.
246 function is_page_readable($page) {
247 global $read_auth_pages;
248 return _is_page_accessible($page, $read_auth_pages);
252 * Whether the page is writable from current user or not.
254 function is_page_writable($page) {
255 global $edit_auth_pages;
256 return _is_page_accessible($page, $edit_auth_pages);
260 * Get whether a current auth user can access the page
262 * @param $page page name
263 * @param $auth_pages pagepattern -> groups map
264 * @return true if a current user can access the page
266 function _is_page_accessible($page, $auth_pages) {
267 global $auth_method_type, $auth_user_groups, $auth_user;
271 if ($auth_method_type == 'pagename') {
272 $target_str = $page; // Page name
273 } else if ($auth_method_type == 'contents') {
274 $target_str = join('', get_source($page)); // Its contents
276 $user_list = array();
277 foreach($auth_pages as $key=>$val) {
278 if (preg_match($key, $target_str)) {
279 $user_list = array_merge($user_list, explode(',', $val));
282 if (empty($user_list)) return TRUE; // No limit
284 // Current user doesen't yet log in.
287 if (count(array_intersect($auth_user_groups, $user_list)) === 0) {
294 * Ensure the page is readable, or show Login UI.
297 function ensure_page_readable($page) {
298 global $read_auth, $read_auth_pages, $_title_cannotread;
302 return basic_auth($page, true, true,
303 $read_auth_pages, $_title_cannotread);
307 * Ensure the page is writable, or show Login UI.
310 function ensure_page_writable($page) {
311 global $edit_auth, $edit_auth_pages, $_title_cannotedit;
315 return basic_auth($page, true, true,
316 $edit_auth_pages, $_title_cannotedit);
320 * Check a page is readable or not, show Auth UI in some cases.
322 * @param $page page name
323 * @param $auth_enabled true if auth is available (Normally true)
324 * @param $exit_on_fail (Normally true)
325 * @return true if the page is readable
327 function check_readable($page, $auth_enabled = TRUE, $exit_on_fail = TRUE)
329 return read_auth($page, $auth_enabled, $exit_on_fail);
332 function edit_auth($page, $auth_enabled = TRUE, $exit_on_fail = TRUE)
334 global $edit_auth, $edit_auth_pages, $_title_cannotedit;
335 return $edit_auth ? basic_auth($page, $auth_enabled, $exit_on_fail,
336 $edit_auth_pages, $_title_cannotedit) : TRUE;
339 function read_auth($page, $auth_enabled = TRUE, $exit_on_fail = TRUE)
341 global $read_auth, $read_auth_pages, $_title_cannotread;
342 return $read_auth ? basic_auth($page, $auth_enabled, $exit_on_fail,
343 $read_auth_pages, $_title_cannotread) : TRUE;
349 * @param $page page name
350 * @param $auth_enabled true if auth is available
351 * @param $exit_on_fail Show forbidden message and stop all following processes
352 * @param $auth_pages accessible users -> pages pattern map
353 * @param $title_cannot forbidden message
355 function basic_auth($page, $auth_enabled, $exit_on_fail, $auth_pages, $title_cannot)
357 global $auth_users, $_msg_auth, $auth_user;
358 global $auth_type, $g_query_string;
359 $is_accessible = _is_page_accessible($page, $auth_pages);
360 if ($is_accessible) {
364 pkwk_common_headers();
365 if ($auth_enabled && !$auth_user) {
366 if (AUTH_TYPE_BASIC === $auth_type) {
367 header('WWW-Authenticate: Basic realm="' . $_msg_auth . '"');
368 header('HTTP/1.0 401 Unauthorized');
369 } elseif (AUTH_TYPE_FORM === $auth_type) {
370 if (is_null($g_query_string)) {
371 $url_after_login = get_base_uri();
373 $url_after_login = get_base_uri() . '?' . $g_query_string;
375 $loginurl = get_base_uri() . '?plugin=loginform'
376 . '&page=' . rawurlencode($page)
377 . '&url_after_login=' . rawurlencode($url_after_login);
378 header('HTTP/1.0 302 Found');
379 header('Location: ' . $loginurl);
380 } elseif (AUTH_TYPE_EXTERNAL === $auth_type ||
381 AUTH_TYPE_SAML === $auth_type) {
382 if (is_null($g_query_string)) {
383 $url_after_login = get_base_uri(PKWK_URI_ABSOLUTE);
385 $url_after_login = get_base_uri(PKWK_URI_ABSOLUTE) . '?' . $g_query_string;
387 $loginurl = get_auth_external_login_url($page, $url_after_login);
388 header('HTTP/1.0 302 Found');
389 header('Location: ' . $loginurl);
393 $body = $title = str_replace('$1',
394 htmlsc(strip_bracket($page)), $title_cannot);
395 $page = str_replace('$1', make_search($page), $title_cannot);
396 catbody($title, $page, $body);
404 * Send 401 if client send a invalid credentials
406 * @return true if valid, false if invalid credentials
408 function ensure_valid_auth_user()
410 global $auth_type, $auth_users, $_msg_auth, $auth_user, $auth_groups;
411 global $auth_user_groups, $auth_user_fullname;
412 global $ldap_user_account;
413 global $read_auth, $edit_auth;
414 if ($read_auth || $edit_auth) {
415 switch ($auth_type) {
416 case AUTH_TYPE_BASIC:
418 case AUTH_TYPE_EXTERNAL:
419 case AUTH_TYPE_EXTERNAL_REMOTE_USER:
420 case AUTH_TYPE_EXTERNAL_X_FORWARDED_USER:
424 // $auth_type is not valid, Set form auth as default
425 $auth_type = AUTH_TYPE_FORM;
428 $auth_dynamic_groups = null;
429 switch ($auth_type) {
430 case AUTH_TYPE_BASIC:
432 if (isset($_SERVER['PHP_AUTH_USER'])) {
433 $user = $_SERVER['PHP_AUTH_USER'];
434 if (in_array($user, array_keys($auth_users))) {
435 if (pkwk_hash_compute(
436 $_SERVER['PHP_AUTH_PW'],
437 $auth_users[$user]) === $auth_users[$user]) {
439 $auth_user_fullname = $auth_user;
440 $auth_user_groups = get_groups_from_username($user);
444 header('WWW-Authenticate: Basic realm="' . $_msg_auth . '"');
445 header('HTTP/1.0 401 Unauthorized');
448 $auth_user_groups = array();
449 return true; // no auth input
452 case AUTH_TYPE_EXTERNAL:
458 $dynamic_groups = array();
459 if (isset($_SESSION['authenticated_user'])) {
460 $user = $_SESSION['authenticated_user'];
461 if (isset($_SESSION['authenticated_user_fullname'])) {
462 $fullname = $_SESSION['authenticated_user_fullname'];
463 $dynamic_groups = $_SESSION['dynamic_member_groups'];
466 if (($auth_type === AUTH_TYPE_EXTERNAL || $auth_type === AUTH_TYPE_SAML) &&
467 $ldap_user_account) {
468 $ldap_user_info = ldap_get_simple_user_info($user);
469 if ($ldap_user_info) {
470 $fullname = $ldap_user_info['fullname'];
471 $dynamic_groups = $ldap_user_info['dynamic_member_groups'];
474 $_SESSION['authenticated_user_fullname'] = $fullname;
475 $_SESSION['dynamic_member_groups'] = $dynamic_groups;
479 $auth_user_fullname = $fullname;
480 $auth_dynamic_groups = $dynamic_groups;
483 case AUTH_TYPE_EXTERNAL_REMOTE_USER:
484 $auth_user = $_SERVER['REMOTE_USER'];
485 $auth_user_fullname = $auth_user;
487 case AUTH_TYPE_EXTERNAL_X_FORWARDED_USER:
488 $auth_user = $_SERVER['HTTP_X_FORWARDED_USER'];
489 $auth_user_fullname = $auth_user;
491 default: // AUTH_TYPE_NONE
493 $auth_user_fullname = '';
496 $auth_user_groups = get_groups_from_username($auth_user);
497 if ($auth_dynamic_groups && is_array($auth_dynamic_groups)) {
498 $auth_user_groups = array_values(array_merge($auth_user_groups, $auth_dynamic_groups));
500 return true; // is not basic auth
504 * Return group name array whose group contains the user
506 * Result array contains reserved 'valid-user' group for all authenticated user
507 * @global array $auth_groups
508 * @param string $user
511 function get_groups_from_username($user)
516 foreach ($auth_groups as $group=>$users) {
517 $sp = explode(',', $users);
518 if (in_array($user, $sp)) {
522 // Implicit group that has same name as user itself
524 // 'valid-user' group for
525 $valid_user = 'valid-user';
526 if (!in_array($valid_user, $groups)) {
527 $groups[] = $valid_user;
535 * Get authenticated user name.
537 * @global type $auth_user
540 function get_auth_user()
547 * Sign in with username and password
549 * @param String username
550 * @param String password
551 * @return true is sign in is OK
553 function form_auth($username, $password)
555 global $ldap_user_account, $auth_users;
557 if ($ldap_user_account) {
559 return ldap_auth($username, $password);
561 // Defined users in pukiwiki.ini.php
562 if (in_array($user, array_keys($auth_users))) {
563 if (pkwk_hash_compute(
565 $auth_users[$user]) === $auth_users[$user]) {
567 session_regenerate_id(true); // require: PHP5.1+
568 $_SESSION['authenticated_user'] = $user;
569 $_SESSION['authenticated_user_fullname'] = $user;
577 function ldap_auth($username, $password)
579 global $ldap_server, $ldap_base_dn, $ldap_bind_dn, $ldap_bind_password;
580 $ldapconn = ldap_connect($ldap_server);
582 ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
583 ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
584 if (preg_match('#\$login\b#', $ldap_bind_dn)) {
585 // Bind by user credential
586 $username_esc = pkwk_ldap_escape_dn($username);
587 $bind_dn_user = preg_replace('#\$login\b#', $username_esc, $ldap_bind_dn);
588 $ldap_bind_user = ldap_bind($ldapconn, $bind_dn_user, $password);
589 if ($ldap_bind_user) {
590 $user_info = get_ldap_user_info($ldapconn, $username, $ldap_base_dn);
592 $ldap_groups = get_ldap_groups_with_user($ldapconn, $username, $user_info['is_ad']);
593 session_regenerate_id(true); // require: PHP5.1+
594 $_SESSION['authenticated_user'] = $user_info['uid'];
595 $_SESSION['authenticated_user_fullname'] = $user_info['fullname'];
596 $_SESSION['dynamic_member_groups'] = $ldap_groups;
602 $ldap_bind = ldap_bind($ldapconn, $ldap_bind_dn, $ldap_bind_password);
604 $user_info = get_ldap_user_info($ldapconn, $username, $ldap_base_dn);
606 $ldap_bind_user2 = ldap_bind($ldapconn, $user_info['dn'], $password);
607 if ($ldap_bind_user2) {
608 $ldap_groups = get_ldap_groups_with_user($ldapconn, $username, $user_info['is_ad']);
609 session_regenerate_id(true); // require: PHP5.1+
610 $_SESSION['authenticated_user'] = $user_info['uid'];
611 $_SESSION['authenticated_user_fullname'] = $user_info['fullname'];
612 $_SESSION['dynamic_member_groups'] = $ldap_groups;
622 // Get LDAP user info via bind DN
623 function ldap_get_simple_user_info($username)
625 global $ldap_server, $ldap_base_dn, $ldap_bind_dn, $ldap_bind_password;
626 $ldapconn = ldap_connect($ldap_server);
628 ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
629 ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
631 $ldap_bind = ldap_bind($ldapconn, $ldap_bind_dn, $ldap_bind_password);
633 $user_info = get_ldap_user_info($ldapconn, $username, $ldap_base_dn);
635 $ldap_groups = get_ldap_groups_with_user($ldapconn,
636 $username, $user_info['is_ad']);
637 $user_info['dynamic_member_groups'] = $ldap_groups;
646 * Search user and get 'dn', 'uid', 'fullname' and 'mail'
647 * @param type $ldapconn
648 * @param type $username
649 * @param type $base_dn
652 function get_ldap_user_info($ldapconn, $username, $base_dn) {
653 $username_esc = pkwk_ldap_escape_filter($username);
654 $filter = "(|(uid=$username_esc)(sAMAccountName=$username_esc))";
655 $result1 = ldap_search($ldapconn, $base_dn, $filter, array('dn', 'uid', 'cn', 'samaccountname', 'displayname', 'mail'));
656 $entries = ldap_get_entries($ldapconn, $result1);
657 if (!isset($entries[0])) {
661 if (isset($info['dn'])) {
662 $user_dn = $info['dn'];
663 $cano_username = $username;
664 $is_active_directory = false;
665 if (isset($info['uid'][0])) {
666 $cano_username = $info['uid'][0];
667 } elseif (isset($info['samaccountname'][0])) {
668 $cano_username = $info['samaccountname'][0];
669 $is_active_directory = true;
671 $cano_fullname = $username;
672 if (isset($info['displayname'][0])) {
673 $cano_fullname = $info['displayname'][0];
674 } elseif (isset($info['cn'][0])) {
675 $cano_fullname = $info['cn'][0];
679 'uid' => $cano_username,
680 'fullname' => $cano_fullname,
681 'mail' => $info['mail'][0],
682 'is_ad' => $is_active_directory,
689 * Redirect after login. Need to assing location or page
691 * @param type $location
694 function form_auth_redirect($location, $page)
696 header('HTTP/1.0 302 Found');
698 header('Location: ' . $location);
700 $url = get_page_uri($page, PKWK_URI_ROOT);
701 header('Location: ' . $url);
706 * Get External Auth log-in URL
708 function get_auth_external_login_url($page, $url_after_login) {
709 global $auth_external_login_url_base;
711 if (strpos($auth_external_login_url_base, '?') === FALSE) {
714 $url = $auth_external_login_url_base . $sep
715 . 'page=' . rawurlencode($page)
716 . '&url_after_login=' . rawurlencode($url_after_login);
720 function get_auth_user_prefix() {
721 global $ldap_user_account, $auth_type;
722 global $auth_provider_user_prefix_default;
723 global $auth_provider_user_prefix_ldap;
724 global $auth_provider_user_prefix_external;
725 global $auth_provider_user_prefix_saml;
727 switch ($auth_type) {
728 case AUTH_TYPE_BASIC:
729 $user_prefix = $auth_provider_user_prefix_default;
731 case AUTH_TYPE_EXTERNAL:
732 case AUTH_TYPE_EXTERNAL_REMOTE_USER:
733 case AUTH_TYPE_EXTERNAL_X_FORWARDED_USER:
734 $user_prefix = $auth_provider_user_prefix_external;
737 $user_prefix = $auth_provider_user_prefix_saml;
740 if ($ldap_user_account) {
741 $user_prefix = $auth_provider_user_prefix_ldap;
743 $user_prefix = $auth_provider_user_prefix_default;
750 function get_ldap_related_groups() {
751 global $read_auth_pages, $edit_auth_pages;
752 global $auth_provider_user_prefix_ldap;
753 $ldap_groups = array();
754 foreach ($read_auth_pages as $pattern=>$groups) {
755 $sp_groups = explode(',', $groups);
756 foreach ($sp_groups as $group) {
757 if (strpos($group, $auth_provider_user_prefix_ldap) === 0) {
758 $ldap_groups[] = $group;
762 foreach ($edit_auth_pages as $pattern=>$groups) {
763 $sp_groups = explode(',', $groups);
764 foreach ($sp_groups as $group) {
765 if (strpos($group, $auth_provider_user_prefix_ldap) === 0) {
766 $ldap_groups[] = $group;
770 $ldap_groups_unique = array_values(array_unique($ldap_groups));
771 return $ldap_groups_unique;
775 * Get LDAP groups user belongs to
777 * @param Resource $ldapconn
778 * @param String $user
782 function get_ldap_groups_with_user($ldapconn, $user, $is_ad) {
783 global $auth_provider_user_prefix_ldap;
784 global $ldap_base_dn;
785 $related_groups = get_ldap_related_groups();
786 if (count($related_groups) == 0) {
790 foreach ($related_groups as $group_full) {
791 $g = substr($group_full, strlen($auth_provider_user_prefix_ldap));
792 $gfilter .= sprintf('(cn=%s)', pkwk_ldap_escape_filter($g));
794 $gfilter .= sprintf('(sAMAccountName=%s)', pkwk_ldap_escape_filter($g));
798 $result_g = ldap_search($ldapconn, $ldap_base_dn, $gfilter,
799 array('dn', 'uid', 'cn', 'samaccountname'));
800 $entries = ldap_get_entries($ldapconn, $result_g);
801 if (!isset($entries[0])) {
807 $entry_count = $entries['count'];
808 $group_list = array();
809 for ($i = 0; $i < $entry_count; $i++) {
810 $group_name = $entries[$i]['cn'][0];
812 $group_name = $entries[$i]['samaccountname'][0];
814 $group_list[] = array(
815 'name' => $group_name,
816 'dn' => $entries[$i]['dn']
819 $groups_member = array();
820 $groups_nonmember = array();
821 foreach ($group_list as $gp) {
822 $fmt = '(&(uid=%s)(memberOf=%s))';
824 // LDAP_MATCHING_RULE_IN_CHAIN: Active Directory specific rule
825 $fmt = '(&(sAMAccountName=%s)(memberOf:1.2.840.113556.1.4.1941:=%s))';
827 $user_gfilter = sprintf($fmt,
828 pkwk_ldap_escape_filter($user),
829 pkwk_ldap_escape_filter($gp['dn']));
830 $result_e = ldap_search($ldapconn, $ldap_base_dn, $user_gfilter,
832 $user_e = ldap_get_entries($ldapconn, $result_e);
833 if (isset($user_e['count']) && $user_e['count'] > 0) {
834 $groups_member[] = $gp['name'];
836 $groups_nonmember[] = $gp['name'];
839 $groups_full = array();
840 foreach ($groups_member as $g) {
841 $groups_full[] = $auth_provider_user_prefix_ldap . $g;