OSDN Git Service

BugTrack2/384 Support LDAP Group - Security Group of Active Directory
[pukiwiki/pukiwiki.git] / lib / auth.php
1 <?php
2 // PukiWiki - Yet another WikiWikiWeb clone
3 // $Id: auth.php,v 1.22 2011/01/25 15:01:01 henoheno Exp $
4 // Copyright (C) 2003-2005, 2007 PukiWiki Developers Team
5 // License: GPL v2 or (at your option) any later version
6 //
7 // Authentication related functions
8
9 define('PKWK_PASSPHRASE_LIMIT_LENGTH', 512);
10
11 /////////////////////////////////////////////////
12 // Auth type
13
14 define('AUTH_TYPE_NONE', 0);
15 define('AUTH_TYPE_BASIC', 1);
16 define('AUTH_TYPE_EXTERNAL', 2);
17 define('AUTH_TYPE_FORM', 3);
18
19 define('AUTH_TYPE_EXTERNAL_REMOTE_USER', 4);
20 define('AUTH_TYPE_EXTERNAL_X_FORWARDED_USER', 5);
21
22
23 // Passwd-auth related ----
24
25 function pkwk_login($pass = '')
26 {
27         global $adminpass;
28
29         if (! PKWK_READONLY && isset($adminpass) &&
30                 pkwk_hash_compute($pass, $adminpass) === $adminpass) {
31                 return TRUE;
32         } else {
33                 sleep(2);       // Blocking brute force attack
34                 return FALSE;
35         }
36 }
37
38 // Compute RFC2307 'userPassword' value, like slappasswd (OpenLDAP)
39 // $phrase : Pass-phrase
40 // $scheme : Specify '{scheme}' or '{scheme}salt'
41 // $prefix : Output with a scheme-prefix or not
42 // $canonical : Correct or Preserve $scheme prefix
43 function pkwk_hash_compute($phrase = '', $scheme = '{x-php-md5}', $prefix = TRUE, $canonical = FALSE)
44 {
45         if (! is_string($phrase) || ! is_string($scheme)) return FALSE;
46
47         if (strlen($phrase) > PKWK_PASSPHRASE_LIMIT_LENGTH)
48                 die('pkwk_hash_compute(): malicious message length');
49
50         // With a {scheme}salt or not
51         $matches = array();
52         if (preg_match('/^(\{.+\})(.*)$/', $scheme, $matches)) {
53                 $scheme = & $matches[1];
54                 $salt   = & $matches[2];
55         } else if ($scheme != '') {
56                 $scheme  = ''; // Cleartext
57                 $salt    = '';
58         }
59
60         // Compute and add a scheme-prefix
61         switch (strtolower($scheme)) {
62
63         // PHP crypt()
64         case '{x-php-crypt}' :
65                 $hash = ($prefix ? ($canonical ? '{x-php-crypt}' : $scheme) : '') .
66                         ($salt != '' ? crypt($phrase, $salt) : crypt($phrase));
67                 break;
68
69         // PHP md5()
70         case '{x-php-md5}'   :
71                 $hash = ($prefix ? ($canonical ? '{x-php-md5}' : $scheme) : '') .
72                         md5($phrase);
73                 break;
74
75         // PHP sha1()
76         case '{x-php-sha1}'  :
77                 $hash = ($prefix ? ($canonical ? '{x-php-sha1}' : $scheme) : '') .
78                         sha1($phrase);
79                 break;
80
81         // LDAP CRYPT
82         case '{crypt}'       :
83                 $hash = ($prefix ? ($canonical ? '{CRYPT}' : $scheme) : '') .
84                         ($salt != '' ? crypt($phrase, $salt) : crypt($phrase));
85                 break;
86
87         // LDAP MD5
88         case '{md5}'         :
89                 $hash = ($prefix ? ($canonical ? '{MD5}' : $scheme) : '') .
90                         base64_encode(pkwk_hex2bin(md5($phrase)));
91                 break;
92
93         // LDAP SMD5
94         case '{smd5}'        :
95                 // MD5 Key length = 128bits = 16bytes
96                 $salt = ($salt != '' ? substr(base64_decode($salt), 16) : substr(crypt(''), -8));
97                 $hash = ($prefix ? ($canonical ? '{SMD5}' : $scheme) : '') .
98                         base64_encode(pkwk_hex2bin(md5($phrase . $salt)) . $salt);
99                 break;
100
101         // LDAP SHA
102         case '{sha}'         :
103                 $hash = ($prefix ? ($canonical ? '{SHA}' : $scheme) : '') .
104                         base64_encode(pkwk_hex2bin(sha1($phrase)));
105                 break;
106
107         // LDAP SSHA
108         case '{ssha}'        :
109                 // SHA-1 Key length = 160bits = 20bytes
110                 $salt = ($salt != '' ? substr(base64_decode($salt), 20) : substr(crypt(''), -8));
111                 $hash = ($prefix ? ($canonical ? '{SSHA}' : $scheme) : '') .
112                         base64_encode(pkwk_hex2bin(sha1($phrase . $salt)) . $salt);
113                 break;
114
115         // LDAP CLEARTEXT and just cleartext
116         case '{cleartext}'   : /* FALLTHROUGH */
117         case ''              :
118                 $hash = ($prefix ? ($canonical ? '{CLEARTEXT}' : $scheme) : '') .
119                         $phrase;
120                 break;
121
122         // Invalid scheme
123         default:
124                 $hash = FALSE;
125                 break;
126         }
127
128         return $hash;
129 }
130
131 // LDAP related functions
132
133 function _pkwk_ldap_escape_callback($matches) {
134         return sprintf('\\%02x', ord($matches[0]));
135 }
136
137 function pkwk_ldap_escape_filter($value) {
138         if (function_exists('ldap_escape')) {
139                 return ldap_escape($value, false, LDAP_ESCAPE_FILTER);
140         }
141         return preg_replace_callback('/[\\\\*()\0]/',
142                 '_pkwk_ldap_escape_callback', $value);
143 }
144
145 function pkwk_ldap_escape_dn($value) {
146         if (function_exists('ldap_escape')) {
147                 return ldap_escape($value, false, LDAP_ESCAPE_DN);
148         }
149         return preg_replace_callback('/[\\\\,=+<>;"#]/',
150                 '_pkwk_ldap_escape_callback', $value);
151 }
152
153
154 // Basic-auth related ----
155
156 // Check edit-permission
157 function check_editable($page, $auth_flag = TRUE, $exit_flag = TRUE)
158 {
159         global $script, $_title_cannotedit, $_msg_unfreeze;
160
161         if (edit_auth($page, $auth_flag, $exit_flag) && is_editable($page)) {
162                 // Editable
163                 return TRUE;
164         } else {
165                 // Not editable
166                 if ($exit_flag === FALSE) {
167                         return FALSE; // Without exit
168                 } else {
169                         // With exit
170                         $body = $title = str_replace('$1',
171                                 htmlsc(strip_bracket($page)), $_title_cannotedit);
172                         if (is_freeze($page))
173                                 $body .= '(<a href="' . $script . '?cmd=unfreeze&amp;page=' .
174                                         rawurlencode($page) . '">' . $_msg_unfreeze . '</a>)';
175                         $page = str_replace('$1', make_search($page), $_title_cannotedit);
176                         catbody($title, $page, $body);
177                         exit;
178                 }
179         }
180 }
181
182 // Check read-permission
183 function check_readable($page, $auth_flag = TRUE, $exit_flag = TRUE)
184 {
185         return read_auth($page, $auth_flag, $exit_flag);
186 }
187
188 function edit_auth($page, $auth_flag = TRUE, $exit_flag = TRUE)
189 {
190         global $edit_auth, $edit_auth_pages, $_title_cannotedit;
191         return $edit_auth ?  basic_auth($page, $auth_flag, $exit_flag,
192                 $edit_auth_pages, $_title_cannotedit) : TRUE;
193 }
194
195 function read_auth($page, $auth_flag = TRUE, $exit_flag = TRUE)
196 {
197         global $read_auth, $read_auth_pages, $_title_cannotread;
198         return $read_auth ?  basic_auth($page, $auth_flag, $exit_flag,
199                 $read_auth_pages, $_title_cannotread) : TRUE;
200 }
201
202 // Basic authentication
203 function basic_auth($page, $auth_flag, $exit_flag, $auth_pages, $title_cannot)
204 {
205         global $auth_method_type, $auth_users, $_msg_auth, $auth_user, $auth_groups;
206         global $auth_user_groups, $auth_type, $g_query_string;
207         // Checked by:
208         $target_str = '';
209         if ($auth_method_type == 'pagename') {
210                 $target_str = $page; // Page name
211         } else if ($auth_method_type == 'contents') {
212                 $target_str = join('', get_source($page)); // Its contents
213         }
214
215         $user_list = array();
216         foreach($auth_pages as $key=>$val)
217                 if (preg_match($key, $target_str))
218                         $user_list = array_merge($user_list, explode(',', $val));
219
220         if (empty($user_list)) return TRUE; // No limit
221
222         $matches = array();
223         if (PKWK_READONLY ||
224                 ! $auth_user ||
225                 count(array_intersect($auth_user_groups, $user_list)) === 0)
226         {
227                 // Auth failed
228                 pkwk_common_headers();
229                 if ($auth_flag && !$auth_user) {
230                         if (AUTH_TYPE_BASIC === $auth_type) {
231                                 header('WWW-Authenticate: Basic realm="' . $_msg_auth . '"');
232                                 header('HTTP/1.0 401 Unauthorized');
233                         } elseif (AUTH_TYPE_FORM === $auth_type) {
234                                 $url_after_login = get_script_uri() . '?' . $g_query_string;
235                                 $loginurl = get_script_uri() . '?plugin=loginform'
236                                         . '&page=' . rawurlencode($page)
237                                         . '&url_after_login=' . rawurlencode($url_after_login);
238                                 header('HTTP/1.0 302 Found');
239                                 header('Location: ' . $loginurl);
240                         } elseif (AUTH_TYPE_EXTERNAL === $auth_type) {
241                                 $url_after_login = get_script_uri() . '?' . $g_query_string;
242                                 $loginurl = get_auth_external_login_url($page, $url_after_login);
243                                 header('HTTP/1.0 302 Found');
244                                 header('Location: ' . $loginurl);
245                         }
246                 }
247                 if ($exit_flag) {
248                         $body = $title = str_replace('$1',
249                                 htmlsc(strip_bracket($page)), $title_cannot);
250                         $page = str_replace('$1', make_search($page), $title_cannot);
251                         catbody($title, $page, $body);
252                         exit;
253                 }
254                 return FALSE;
255         } else {
256                 return TRUE;
257         }
258 }
259
260 /**
261  * Send 401 if client send a invalid credentials
262  *
263  * @return true if valid, false if invalid credentials
264  */
265 function ensure_valid_auth_user()
266 {
267         global $auth_type, $auth_users, $_msg_auth, $auth_user, $auth_groups;
268         global $auth_user_groups, $auth_user_fullname;
269         global $ldap_user_account;
270         global $read_auth, $edit_auth;
271         if ($read_auth || $edit_auth) {
272                 switch ($auth_type) {
273                         case AUTH_TYPE_BASIC:
274                         case AUTH_TYPE_FORM:
275                         case AUTH_TYPE_EXTERNAL:
276                         case AUTH_TYPE_EXTERNAL_REMOTE_USER:
277                         case AUTH_TYPE_EXTERNAL_X_FORWARDED_USER:
278                                 break;
279                         default:
280                                 // $auth_type is not valid, Set form auth as default
281                                 $auth_type = AUTH_TYPE_FORM;
282                 }
283         }
284         $auth_dynamic_groups = null;
285         switch ($auth_type) {
286                 case AUTH_TYPE_BASIC:
287                 {
288                         if (isset($_SERVER['PHP_AUTH_USER'])) {
289                                 $user = $_SERVER['PHP_AUTH_USER'];
290                                 if (in_array($user, array_keys($auth_users))) {
291                                         if (pkwk_hash_compute(
292                                                 $_SERVER['PHP_AUTH_PW'],
293                                                 $auth_users[$user]) === $auth_users[$user]) {
294                                                 $auth_user = $user;
295                                                 $auth_user_fullname = $auth_user;
296                                                 $auth_user_groups = get_groups_from_username($user);
297                                                 return true;
298                                         }
299                                 }
300                                 header('WWW-Authenticate: Basic realm="' . $_msg_auth . '"');
301                                 header('HTTP/1.0 401 Unauthorized');
302                         }
303                         $auth_user = '';
304                         $auth_user_groups = get_groups_from_username($user);
305                         return true; // no auth input
306                 }
307                 case AUTH_TYPE_FORM:
308                 case AUTH_TYPE_EXTERNAL:
309                 {
310                         session_start();
311                         $user = '';
312                         $fullname = '';
313                         $dynamic_groups = array();
314                         if (isset($_SESSION['authenticated_user'])) {
315                                 $user = $_SESSION['authenticated_user'];
316                                 if (isset($_SESSION['authenticated_user_fullname'])) {
317                                         $fullname = $_SESSION['authenticated_user_fullname'];
318                                         $dynamic_groups = $_SESSION['dynamic_member_groups'];
319                                 } else {
320                                         $fullname = $user;
321                                         if ($auth_type === AUTH_TYPE_EXTERNAL && $ldap_user_account) {
322                                                 $ldap_user_info = ldap_get_simple_user_info($user);
323                                                 if ($ldap_user_info) {
324                                                         $fullname = $ldap_user_info['fullname'];
325                                                         $dynamic_groups = $ldap_user_info['dynamic_member_groups'];
326                                                 }
327                                         }
328                                         $_SESSION['authenticated_user_fullname'] = $fullname;
329                                         $_SESSION['dynamic_member_groups'] = $dynamic_groups;
330                                 }
331                         }
332                         $auth_user = $user;
333                         $auth_user_fullname = $fullname;
334                         $auth_dynamic_groups = $dynamic_groups;
335                         break;
336                 }
337                 case AUTH_TYPE_EXTERNAL_REMOTE_USER:
338                         $auth_user = $_SERVER['REMOTE_USER'];
339                         $auth_user_fullname = $auth_user;
340                         break;
341                 case AUTH_TYPE_EXTERNAL_X_FORWARDED_USER:
342                         $auth_user =  $_SERVER['HTTP_X_FORWARDED_USER'];
343                         $auth_user_fullname = $auth_user;
344                         break;
345                 default: // AUTH_TYPE_NONE
346                         $auth_user = '';
347                         $auth_user_fullname = '';
348                         break;
349         }
350         $auth_user_groups = get_groups_from_username($auth_user);
351         if ($auth_dynamic_groups && is_array($auth_dynamic_groups)) {
352                 $auth_user_groups = array_values(array_merge($auth_user_groups, $auth_dynamic_groups));
353         }
354         return true; // is not basic auth
355 }
356
357 /**
358  * Return group name array whose group contains the user
359  *
360  * Result array contains reserved 'valid-user' group for all authenticated user
361  * @global array $auth_groups
362  * @param string $user
363  * @return array
364  */
365 function get_groups_from_username($user)
366 {
367         global $auth_groups;
368         if ($user !== '') {
369                 $groups = array();
370                 foreach ($auth_groups as $group=>$users) {
371                         $sp = explode(',', $users);
372                         if (in_array($user, $sp)) {
373                                 $groups[] = $group;
374                         }
375                 }
376                 // Implicit group that has same name as user itself
377                 $groups[] = $user;
378                 // 'valid-user' group for
379                 $valid_user = 'valid-user';
380                 if (!in_array($valid_user, $groups)) {
381                         $groups[] = $valid_user;
382                 }
383                 return $groups;
384         }
385         return array();
386 }
387
388 /**
389  * Get authenticated user name.
390  *
391  * @global type $auth_user
392  * @return type
393  */
394 function get_auth_user()
395 {
396         global $auth_user;
397         return $auth_user;
398 }
399
400 /**
401  * Sign in with username and password
402  *
403  * @param String username
404  * @param String password
405  * @return true is sign in is OK
406  */
407 function form_auth($username, $password)
408 {
409         global $ldap_user_account, $auth_users;
410         $user = $username;
411         if ($ldap_user_account) {
412                 // LDAP account
413                 return ldap_auth($username, $password);
414         } else {
415                 // Defined users in pukiwiki.ini.php
416                 if (in_array($user, array_keys($auth_users))) {
417                         if (pkwk_hash_compute(
418                                 $password,
419                                 $auth_users[$user]) === $auth_users[$user]) {
420                                 session_start();
421                                 session_regenerate_id(true); // require: PHP5.1+
422                                 $_SESSION['authenticated_user'] = $user;
423                                 $_SESSION['authenticated_user_fullname'] = $user;
424                                 return true;
425                         }
426                 }
427         }
428         return false;
429 }
430
431 function ldap_auth($username, $password)
432 {
433         global $ldap_server, $ldap_base_dn, $ldap_bind_dn, $ldap_bind_password;
434         $ldapconn = ldap_connect($ldap_server);
435         if ($ldapconn) {
436                 ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
437                 ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
438                 if (preg_match('#\$login\b#', $ldap_bind_dn)) {
439                         // Bind by user credential
440                         $username_esc = pkwk_ldap_escape_dn($username);
441                         $bind_dn_user = preg_replace('#\$login\b#', $username_esc, $ldap_bind_dn);
442                         $ldap_bind_user = ldap_bind($ldapconn, $bind_dn_user, $password);
443                         if ($ldap_bind_user) {
444                                 $user_info = get_ldap_user_info($ldapconn, $username, $ldap_base_dn);
445                                 if ($user_info) {
446                                         $ldap_groups = get_ldap_groups_with_user($ldapconn, $username, $user_info['is_ad']);
447                                         session_regenerate_id(true); // require: PHP5.1+
448                                         $_SESSION['authenticated_user'] = $user_info['uid'];
449                                         $_SESSION['authenticated_user_fullname'] = $user_info['fullname'];
450                                         $_SESSION['dynamic_member_groups'] = $ldap_groups;
451                                         return true;
452                                 }
453                         }
454                 } else {
455                         // Bind by bind dn
456                         $ldap_bind = ldap_bind($ldapconn, $ldap_bind_dn, $ldap_bind_password);
457                         if ($ldap_bind) {
458                                 $user_info = get_ldap_user_info($ldapconn, $username, $ldap_base_dn);
459                                 if ($user_info) {
460                                         $ldap_bind_user2 = ldap_bind($ldapconn, $user_info['dn'], $password);
461                                         if ($ldap_bind_user2) {
462                                                 $ldap_groups = get_ldap_groups_with_user($ldapconn, $username, $user_info['is_ad']);
463                                                 session_regenerate_id(true); // require: PHP5.1+
464                                                 $_SESSION['authenticated_user'] = $user_info['uid'];
465                                                 $_SESSION['authenticated_user_fullname'] = $user_info['fullname'];
466                                                 $_SESSION['dynamic_member_groups'] = $ldap_groups;
467                                                 return true;
468                                         }
469                                 }
470                         }
471                 }
472         }
473         return false;
474 }
475
476 // Get LDAP user info via bind DN
477 function ldap_get_simple_user_info($username)
478 {
479         global $ldap_server, $ldap_base_dn, $ldap_bind_dn, $ldap_bind_password;
480         $ldapconn = ldap_connect($ldap_server);
481         if ($ldapconn) {
482                 ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
483                 ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
484                 // Bind by bind dn
485                 $ldap_bind = ldap_bind($ldapconn, $ldap_bind_dn, $ldap_bind_password);
486                 if ($ldap_bind) {
487                         $user_info = get_ldap_user_info($ldapconn, $username, $ldap_base_dn);
488                         if ($user_info) {
489                                 $ldap_groups = get_ldap_groups_with_user($ldapconn,
490                                         $username, $user_info['is_ad']);
491                                 $user_info['dynamic_member_groups'] = $ldap_groups;
492                                 return $user_info;
493                         }
494                 }
495         }
496         return false;
497 }
498
499 /**
500  * Search user and get 'dn', 'uid', 'fullname' and 'mail'
501  * @param type $ldapconn
502  * @param type $username
503  * @param type $base_dn
504  * @return boolean
505  */
506 function get_ldap_user_info($ldapconn, $username, $base_dn) {
507         $username_esc = pkwk_ldap_escape_filter($username);
508         $filter = "(|(uid=$username_esc)(sAMAccountName=$username_esc))";
509         $result1 = ldap_search($ldapconn, $base_dn, $filter, array('dn', 'uid', 'cn', 'samaccountname', 'displayname', 'mail'));
510         $entries = ldap_get_entries($ldapconn, $result1);
511         if (!isset($entries[0])) {
512                 return false;
513         }
514         $info = $entries[0];
515         if (isset($info['dn'])) {
516                 $user_dn = $info['dn'];
517                 $cano_username = $username;
518                 $is_active_directory = false;
519                 if (isset($info['uid'][0])) {
520                         $cano_username = $info['uid'][0];
521                 } elseif (isset($info['samaccountname'][0])) {
522                         $cano_username = $info['samaccountname'][0];
523                         $is_active_directory = true;
524                 }
525                 $cano_fullname = $username;
526                 if (isset($info['displayname'][0])) {
527                         $cano_fullname = $info['displayname'][0];
528                 } elseif (isset($info['cn'][0])) {
529                         $cano_fullname = $info['cn'][0];
530                 }
531                 return array(
532                         'dn' => $user_dn,
533                         'uid' => $cano_username,
534                         'fullname' => $cano_fullname,
535                         'mail' => $info['mail'][0],
536                         'is_ad' => $is_active_directory,
537                 );
538         }
539         return false;
540 }
541
542 /**
543  * Redirect after login. Need to assing location or page
544  *
545  * @param type $location
546  * @param type $page
547  */
548 function form_auth_redirect($location, $page)
549 {
550         header('HTTP/1.0 302 Found');
551         if ($location) {
552                 header('Location: ' . $location);
553         } else {
554                 $url = get_script_uri() . '?' . $page;
555                 header('Location: ' . $url);
556         }
557 }
558
559 /**
560  * Get External Auth log-in URL
561  */
562 function get_auth_external_login_url($page, $url_after_login) {
563         global $auth_external_login_url_base;
564         $sep = '&';
565         if (strpos($auth_external_login_url_base, '?') === FALSE) {
566                 $sep = '?';
567         }
568         $url = $auth_external_login_url_base . $sep
569                 . 'page=' . rawurlencode($page)
570                 . '&url_after_login=' . rawurlencode($url_after_login);
571         return $url;
572 }
573
574 function get_auth_user_prefix() {
575         global $ldap_user_account, $auth_type;
576         global $auth_provider_user_prefix_default;
577         global $auth_provider_user_prefix_ldap;
578         global $auth_provider_user_prefix_external;
579         $user_prefix = '';
580         switch ($auth_type) {
581                 case AUTH_TYPE_BASIC:
582                         $user_prefix = $auth_provider_user_prefix_default;
583                         break;
584                 case AUTH_TYPE_EXTERNAL:
585                 case AUTH_TYPE_EXTERNAL_REMOTE_USER:
586                 case AUTH_TYPE_EXTERNAL_X_FORWARDED_USER:
587                         $user_prefix = $auth_provider_user_prefix_external;
588                         break;
589                 case AUTH_TYPE_FORM:
590                         if ($ldap_user_account) {
591                                 $user_prefix = $auth_provider_user_prefix_ldap;
592                         } else {
593                                 $user_prefix = $auth_provider_user_prefix_default;
594                         }
595                         break;
596         }
597         return $user_prefix;
598 }
599
600 function get_ldap_related_groups() {
601         global $read_auth_pages, $edit_auth_pages;
602         global $auth_provider_user_prefix_ldap;
603         $ldap_groups = array();
604         foreach ($read_auth_pages as $pattern=>$groups) {
605                 $sp_groups = explode(',', $groups);
606                 foreach ($sp_groups as $group) {
607                         if (strpos($group, $auth_provider_user_prefix_ldap) === 0) {
608                                 $ldap_groups[] = $group;
609                         }
610                 }
611         }
612         foreach ($edit_auth_pages as $pattern=>$groups) {
613                 $sp_groups = explode(',', $groups);
614                 foreach ($sp_groups as $group) {
615                         if (strpos($group, $auth_provider_user_prefix_ldap) === 0) {
616                                 $ldap_groups[] = $group;
617                         }
618                 }
619         }
620         $ldap_groups_unique = array_values(array_unique($ldap_groups));
621         return $ldap_groups_unique;
622 }
623
624 /**
625  * Get LDAP groups user belongs to
626  *
627  * @param Resource $ldapconn
628  * @param String $user
629  * @param bool $is_ad
630  * @return Array
631  */
632 function get_ldap_groups_with_user($ldapconn, $user, $is_ad) {
633         global $auth_provider_user_prefix_ldap;
634         global $ldap_base_dn;
635         $related_groups = get_ldap_related_groups();
636         if (count($related_groups) == 0) {
637                 return array();
638         }
639         $gfilter = '(|';
640         foreach ($related_groups as $group_full) {
641                 $g = substr($group_full, strlen($auth_provider_user_prefix_ldap));
642                 $gfilter .= sprintf('(cn=%s)', pkwk_ldap_escape_filter($g));
643                 if ($is_ad) {
644                         $gfilter .= sprintf('(sAMAccountName=%s)', pkwk_ldap_escape_filter($g));
645                 }
646         }
647         $gfilter .= ')';
648         $result_g = ldap_search($ldapconn, $ldap_base_dn, $gfilter,
649                 array('dn', 'uid', 'cn', 'samaccountname'));
650         $entries = ldap_get_entries($ldapconn, $result_g);
651         if (!isset($entries[0])) {
652                 return false;
653         }
654         if (!$entries) {
655                 return array();
656         }
657         $entry_count = $entries['count'];
658         $group_list = array();
659         for ($i = 0; $i < $entry_count; $i++) {
660                 $group_name = $entries[$i]['cn'][0];
661                 if ($is_ad) {
662                         $group_name = $entries[$i]['samaccountname'][0];
663                 }
664                 $group_list[] = array(
665                         'name' => $group_name,
666                         'dn' => $entries[$i]['dn']
667                 );
668         }
669         $groups_member = array();
670         $groups_nonmember = array();
671         foreach ($group_list as $gp) {
672                 $fmt = '(&(uid=%s)(memberOf=%s))';
673                 if ($is_ad) {
674                         // LDAP_MATCHING_RULE_IN_CHAIN: Active Directory specific rule
675                         $fmt = '(&(sAMAccountName=%s)(memberOf:1.2.840.113556.1.4.1941:=%s))';
676                 }
677                 $user_gfilter = sprintf($fmt,
678                         pkwk_ldap_escape_filter($user),
679                         pkwk_ldap_escape_filter($gp['dn']));
680                 $result_e = ldap_search($ldapconn, $ldap_base_dn, $user_gfilter,
681                         array('dn'), 0, 1);
682                 $user_e = ldap_get_entries($ldapconn, $result_e);
683                 if (isset($user_e['count']) && $user_e['count'] > 0) {
684                         $groups_member[] = $gp['name'];
685                 } else {
686                         $groups_nonmember[] = $gp['name'];
687                 }
688         }
689         $groups_full = array();
690         foreach ($groups_member as $g) {
691                 $groups_full[] = $auth_provider_user_prefix_ldap . $g;
692         }
693         return $groups_full;
694 }