Revision | c3cf8aafd4eb0da0d2f02fe854075440d2d39c1e (tree) |
---|---|
Time | 2016-02-20 00:05:20 |
Author | ![]() |
Commiter | umorigu |
BugTrack2/384 Support LDAP Group - Security Group of Active Directory
Use LDAP_MATCHING_RULE_IN_CHAIN rule of Active Directory LDAP,
that enables nested group check.
For other systems, standard 'memberof' check is used.
@@ -281,6 +281,7 @@ function ensure_valid_auth_user() | ||
281 | 281 | $auth_type = AUTH_TYPE_FORM; |
282 | 282 | } |
283 | 283 | } |
284 | + $auth_dynamic_groups = null; | |
284 | 285 | switch ($auth_type) { |
285 | 286 | case AUTH_TYPE_BASIC: |
286 | 287 | { |
@@ -309,23 +310,28 @@ function ensure_valid_auth_user() | ||
309 | 310 | session_start(); |
310 | 311 | $user = ''; |
311 | 312 | $fullname = ''; |
313 | + $dynamic_groups = array(); | |
312 | 314 | if (isset($_SESSION['authenticated_user'])) { |
313 | 315 | $user = $_SESSION['authenticated_user']; |
314 | 316 | if (isset($_SESSION['authenticated_user_fullname'])) { |
315 | 317 | $fullname = $_SESSION['authenticated_user_fullname']; |
318 | + $dynamic_groups = $_SESSION['dynamic_member_groups']; | |
316 | 319 | } else { |
317 | 320 | $fullname = $user; |
318 | 321 | if ($auth_type === AUTH_TYPE_EXTERNAL && $ldap_user_account) { |
319 | 322 | $ldap_user_info = ldap_get_simple_user_info($user); |
320 | 323 | if ($ldap_user_info) { |
321 | 324 | $fullname = $ldap_user_info['fullname']; |
325 | + $dynamic_groups = $ldap_user_info['dynamic_member_groups']; | |
322 | 326 | } |
323 | 327 | } |
324 | 328 | $_SESSION['authenticated_user_fullname'] = $fullname; |
329 | + $_SESSION['dynamic_member_groups'] = $dynamic_groups; | |
325 | 330 | } |
326 | 331 | } |
327 | 332 | $auth_user = $user; |
328 | 333 | $auth_user_fullname = $fullname; |
334 | + $auth_dynamic_groups = $dynamic_groups; | |
329 | 335 | break; |
330 | 336 | } |
331 | 337 | case AUTH_TYPE_EXTERNAL_REMOTE_USER: |
@@ -342,6 +348,9 @@ function ensure_valid_auth_user() | ||
342 | 348 | break; |
343 | 349 | } |
344 | 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 | + } | |
345 | 354 | return true; // is not basic auth |
346 | 355 | } |
347 | 356 |
@@ -434,9 +443,11 @@ function ldap_auth($username, $password) | ||
434 | 443 | if ($ldap_bind_user) { |
435 | 444 | $user_info = get_ldap_user_info($ldapconn, $username, $ldap_base_dn); |
436 | 445 | if ($user_info) { |
446 | + $ldap_groups = get_ldap_groups_with_user($ldapconn, $username, $user_info['is_ad']); | |
437 | 447 | session_regenerate_id(true); // require: PHP5.1+ |
438 | 448 | $_SESSION['authenticated_user'] = $user_info['uid']; |
439 | 449 | $_SESSION['authenticated_user_fullname'] = $user_info['fullname']; |
450 | + $_SESSION['dynamic_member_groups'] = $ldap_groups; | |
440 | 451 | return true; |
441 | 452 | } |
442 | 453 | } |
@@ -448,9 +459,11 @@ function ldap_auth($username, $password) | ||
448 | 459 | if ($user_info) { |
449 | 460 | $ldap_bind_user2 = ldap_bind($ldapconn, $user_info['dn'], $password); |
450 | 461 | if ($ldap_bind_user2) { |
462 | + $ldap_groups = get_ldap_groups_with_user($ldapconn, $username, $user_info['is_ad']); | |
451 | 463 | session_regenerate_id(true); // require: PHP5.1+ |
452 | 464 | $_SESSION['authenticated_user'] = $user_info['uid']; |
453 | 465 | $_SESSION['authenticated_user_fullname'] = $user_info['fullname']; |
466 | + $_SESSION['dynamic_member_groups'] = $ldap_groups; | |
454 | 467 | return true; |
455 | 468 | } |
456 | 469 | } |
@@ -473,6 +486,9 @@ function ldap_get_simple_user_info($username) | ||
473 | 486 | if ($ldap_bind) { |
474 | 487 | $user_info = get_ldap_user_info($ldapconn, $username, $ldap_base_dn); |
475 | 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; | |
476 | 492 | return $user_info; |
477 | 493 | } |
478 | 494 | } |
@@ -499,10 +515,12 @@ function get_ldap_user_info($ldapconn, $username, $base_dn) { | ||
499 | 515 | if (isset($info['dn'])) { |
500 | 516 | $user_dn = $info['dn']; |
501 | 517 | $cano_username = $username; |
518 | + $is_active_directory = false; | |
502 | 519 | if (isset($info['uid'][0])) { |
503 | 520 | $cano_username = $info['uid'][0]; |
504 | 521 | } elseif (isset($info['samaccountname'][0])) { |
505 | 522 | $cano_username = $info['samaccountname'][0]; |
523 | + $is_active_directory = true; | |
506 | 524 | } |
507 | 525 | $cano_fullname = $username; |
508 | 526 | if (isset($info['displayname'][0])) { |
@@ -514,7 +532,8 @@ function get_ldap_user_info($ldapconn, $username, $base_dn) { | ||
514 | 532 | 'dn' => $user_dn, |
515 | 533 | 'uid' => $cano_username, |
516 | 534 | 'fullname' => $cano_fullname, |
517 | - 'mail' => $info['mail'][0] | |
535 | + 'mail' => $info['mail'][0], | |
536 | + 'is_ad' => $is_active_directory, | |
518 | 537 | ); |
519 | 538 | } |
520 | 539 | return false; |
@@ -551,3 +570,125 @@ function get_auth_external_login_url($page, $url_after_login) { | ||
551 | 570 | . '&url_after_login=' . rawurlencode($url_after_login); |
552 | 571 | return $url; |
553 | 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 | +} |
@@ -169,10 +169,7 @@ function make_str_rules($source) | ||
169 | 169 | |
170 | 170 | function add_author_info($wikitext) |
171 | 171 | { |
172 | - global $auth_user, $auth_user_fullname, $auth_type, $ldap_user_account; | |
173 | - global $auth_provider_user_prefix_default; | |
174 | - global $auth_provider_user_prefix_ldap; | |
175 | - global $auth_provider_user_prefix_external; | |
172 | + global $auth_user, $auth_user_fullname; | |
176 | 173 | $author = preg_replace('/"/', '', $auth_user); |
177 | 174 | $fullname = $auth_user_fullname; |
178 | 175 | if (!$fullname && $author) { |
@@ -180,24 +177,7 @@ function add_author_info($wikitext) | ||
180 | 177 | $fullname = preg_replace('/^[^:]*:/', '', $author); |
181 | 178 | } |
182 | 179 | $displayname = preg_replace('/"/', '', $fullname); |
183 | - $user_prefix = ''; | |
184 | - switch ($auth_type) { | |
185 | - case AUTH_TYPE_BASIC: | |
186 | - $user_prefix = $auth_provider_user_prefix_default; | |
187 | - break; | |
188 | - case AUTH_TYPE_EXTERNAL: | |
189 | - case AUTH_TYPE_EXTERNAL_REMOTE_USER: | |
190 | - case AUTH_TYPE_EXTERNAL_X_FORWARDED_USER: | |
191 | - $user_prefix = $auth_provider_user_prefix_external; | |
192 | - break; | |
193 | - case AUTH_TYPE_FORM: | |
194 | - if ($ldap_user_account) { | |
195 | - $user_prefix = $auth_provider_user_prefix_ldap; | |
196 | - } else { | |
197 | - $user_prefix = $auth_provider_user_prefix_default; | |
198 | - } | |
199 | - break; | |
200 | - } | |
180 | + $user_prefix = get_auth_user_prefix(); | |
201 | 181 | $author_text = sprintf('#author("%s","%s","%s")', |
202 | 182 | get_date_atom(UTIME + LOCALZONE), |
203 | 183 | ($author ? $user_prefix . $author : ''), |