1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
13:
14: require_once("auth-functions.php");
15:
16: 17: 18:
19: class ldapDriver
20: {
21: 22: 23:
24:
25: 26: 27:
28: var $connect;
29:
30:
31:
32:
33: 34: 35: 36: 37:
38: function __construct($config)
39: {
40: global $c;
41: $host=$config['host'];
42: $port=$config['port'];
43: if(!function_exists('ldap_connect')){
44: $c->messages[] = i18n("drivers_ldap : function ldap_connect not defined, check your php_ldap module");
45: $this->valid=false;
46: return ;
47: }
48:
49:
50: if (isset($config['protocolVersion']))
51: ldap_set_option($this->connect, LDAP_OPT_PROTOCOL_VERSION, $config['protocolVersion']);
52: if (isset($config['optReferrals']))
53: ldap_set_option($this->connect, LDAP_OPT_REFERRALS, $config['optReferrals']);
54: if (isset($config['networkTimeout']))
55: ldap_set_option($this->connect, LDAP_OPT_NETWORK_TIMEOUT, $config['networkTimeout']);
56:
57: if ($port)
58: $this->connect=ldap_connect($host, $port);
59: else
60: $this->connect=ldap_connect($host);
61:
62: if (! $this->connect){
63: $c->messages[] = sprintf(translate( 'drivers_ldap : Unable to connect to LDAP with port %s on host %s'), $port, $host );
64: $this->valid=false;
65: return ;
66: }
67:
68: dbg_error_log( "LDAP", "drivers_ldap : Connected to LDAP server %s",$host );
69:
70:
71: if (isset($config['startTLS'])) {
72: if (!ldap_set_option($this->connect, LDAP_OPT_PROTOCOL_VERSION, 3)) {
73: $c->messages[] = i18n('drivers_ldap : Failed to set LDAP to use protocol version 3, TLS not supported');
74: $this->valid=false;
75: return;
76: }
77: if (!ldap_start_tls($this->connect)) {
78: $c->messages[] = i18n('drivers_ldap : Could not start TLS: ldap_start_tls() failed');
79: $this->valid=false;
80: return;
81: }
82: }
83:
84:
85: if (!isset($config['scope'])) $config['scope'] = 'subtree';
86: switch (strtolower($config['scope'])) {
87: case "base":
88: $this->ldap_query_one = 'ldap_read';
89: $this->ldap_query_all = 'ldap_read';
90: break;
91: case "onelevel":
92: $this->ldap_query_one = 'ldap_list';
93: $this->ldap_query_all = 'ldap_search';
94: break;
95: default:
96: $this->ldap_query_one = 'ldap_search';
97: $this->ldap_query_all = 'ldap_search';
98: break;
99: }
100:
101:
102: if (!ldap_bind($this->connect, (isset($config['bindDN']) ? $config['bindDN'] : null), (isset($config['passDN']) ? $config['passDN'] : null) ) ){
103: $bindDN = isset($config['bindDN']) ? $config['bindDN'] : 'anonymous';
104: $passDN = isset($config['passDN']) ? $config['passDN'] : 'anonymous';
105: dbg_error_log( "LDAP", i18n('drivers_ldap : Failed to bind to host %1$s on port %2$s with bindDN of %3$s'), $host, $port, $bindDN );
106: $c->messages[] = i18n( 'drivers_ldap : Unable to bind to LDAP - check your configuration for bindDN and passDN, and that your LDAP server is reachable');
107: $this->valid=false;
108: return ;
109: }
110: $this->valid = true;
111:
112: $this->baseDNUsers = is_string($config['baseDNUsers']) ? array($config['baseDNUsers']) : $config['baseDNUsers'];
113: $this->filterUsers = (isset($config['filterUsers']) ? $config['filterUsers'] : null);
114: $this->baseDNGroups = is_string($config['baseDNGroups']) ? array($config['baseDNGroups']) : $config['baseDNGroups'];
115: $this->filterGroups = (isset($config['filterGroups']) ? $config['filterGroups'] : null);
116: }
117:
118: 119: 120:
121: function getAllUsers($attributes){
122: global $c;
123:
124: $query = $this->ldap_query_all;
125: $ret = array();
126:
127: foreach($this->baseDNUsers as $baseDNUsers) {
128: $entry = $query($this->connect,$baseDNUsers,$this->filterUsers,$attributes);
129:
130: if (!ldap_first_entry($this->connect,$entry)) {
131: $c->messages[] = sprintf(translate('Error NoUserFound with filter >%s<, attributes >%s< , dn >%s<'),
132: $this->filterUsers,
133: join(', ', $attributes),
134: $baseDNUsers);
135: }
136: $row = array();
137: for($i = ldap_first_entry($this->connect,$entry);
138: $i && $arr = ldap_get_attributes($this->connect,$i);
139: $i = ldap_next_entry($this->connect,$i) ) {
140: $row = array();
141: for ($j=0; $j < $arr['count']; $j++) {
142: $row[$arr[$j]] = $arr[$arr[$j]][0];
143: }
144: $ret[]=$row;
145: }
146: }
147: return $ret;
148: }
149:
150: 151: 152:
153: function getAllGroups($attributes){
154: global $c;
155:
156: $query = $this->ldap_query_all;
157: $ret = array();
158:
159: foreach($this->baseDNGroups as $baseDNGroups) {
160: $entry = $query($this->connect,$baseDNGroups,$this->filterGroups,$attributes);
161:
162: if (!ldap_first_entry($this->connect,$entry)) {
163: $c->messages[] = sprintf(translate('Error NoGroupFound with filter >%s<, attributes >%s< , dn >%s<'),
164: $this->filterGroups,
165: join(', ', $attributes),
166: $baseDNGroups);
167: }
168: $row = array();
169: for($i = ldap_first_entry($this->connect,$entry);
170: $i && $arr = ldap_get_attributes($this->connect,$i);
171: $i = ldap_next_entry($this->connect,$i) ) {
172: for ($j=0; $j < $arr['count']; $j++) {
173: $row[$arr[$j]] = count($arr[$arr[$j]])>2?$arr[$arr[$j]]:$arr[$arr[$j]][0];
174: }
175: $ret[]=$row;
176: unset($row);
177: }
178: }
179: return $ret;
180: }
181:
182: 183: 184: 185: 186: 187: 188: 189:
190: function requestUser( $filter, $attributes=NULL, $username, $passwd) {
191: global $c;
192:
193: $entry=NULL;
194:
195: $query = $this->ldap_query_one;
196:
197: foreach($this->baseDNUsers as $baseDNUsers) {
198: $entry = $query($this->connect, $baseDNUsers, $filter, $attributes);
199:
200: if (ldap_first_entry($this->connect,$entry) )
201: break;
202:
203: dbg_error_log( "LDAP", "drivers_ldap : Failed to find user with baseDN: %s", $baseDNUsers );
204: }
205:
206: if ( !ldap_first_entry($this->connect, $entry) ){
207: dbg_error_log( "ERROR", "drivers_ldap : Unable to find the user with filter %s",$filter );
208: return false;
209: } else {
210: dbg_error_log( "LDAP", "drivers_ldap : Found a user using filter %s",$filter );
211: }
212:
213: $dnUser = ldap_get_dn($this->connect, ldap_first_entry($this->connect,$entry));
214:
215: if ( isset($c->authenticate_hook['config']['i_use_mode_kerberos']) && $c->authenticate_hook['config']['i_use_mode_kerberos'] == "i_know_what_i_am_doing") {
216: if (isset($_SERVER["REMOTE_USER"])) {
217: dbg_error_log( "LOG", "drivers_ldap : Skipping password Check for user %s which should be the same as %s",$username , $_SERVER["REMOTE_USER"]);
218: if ($username != $_SERVER["REMOTE_USER"]) {
219: return false;
220: }
221: } else {
222: dbg_error_log( "LOG", "drivers_ldap : Skipping password Check for user %s which should be the same as %s",$username , $_SERVER["REDIRECT_REMOTE_USER"]);
223: if ($username != $_SERVER["REDIRECT_REMOTE_USER"]) {
224: return false;
225: }
226: }
227: }
228: else if ( empty($passwd) || preg_match('/[\x00-\x19]/',$passwd) ) {
229:
230: dbg_error_log( 'LDAP', 'drivers_ldap : user %s supplied empty or invalid password: login rejected', $dnUser );
231: return false;
232: }
233: else {
234: if ( !@ldap_bind($this->connect, $dnUser, $passwd) ) {
235: dbg_error_log( "LDAP", "drivers_ldap : Failed to bind to user %s ", $dnUser );
236: return false;
237: }
238: }
239:
240: dbg_error_log( "LDAP", "drivers_ldap : Bound to user %s using password %s", $dnUser,
241: (isset($c->dbg['password']) && $c->dbg['password'] ? $passwd : 'another delicious password for the debugging monster!') );
242:
243: $i = ldap_first_entry($this->connect,$entry);
244: $arr = ldap_get_attributes($this->connect,$i);
245: for( $i=0; $i<$arr['count']; $i++ ) {
246: $ret[$arr[$i]]=$arr[$arr[$i]][0];
247: }
248: return $ret;
249:
250: }
251: }
252:
253:
254: 255: 256:
257: function getStaticLdap() {
258: global $c;
259:
260: static $instance;
261:
262:
263: if(!isset($instance)) {
264: $ldapDriver = new ldapDriver($c->authenticate_hook['config']);
265:
266: if ($ldapDriver->valid) {
267: $instance = $ldapDriver;
268: }
269: }
270: else {
271: $ldapDriver = $instance;
272: }
273: return $ldapDriver;
274: }
275:
276:
277: 278: 279: 280:
281: function sync_user_from_LDAP( Principal &$principal, $mapping, $ldap_values ) {
282: global $c;
283:
284: dbg_error_log( "LDAP", "Going to sync the user from LDAP" );
285:
286: $fields_to_set = array();
287: $updateable_fields = Principal::updateableFields();
288: foreach( $updateable_fields AS $field ) {
289: if ( isset($mapping[$field]) ) {
290: $tab_part_fields = explode(',',$mapping[$field]);
291: foreach( $tab_part_fields as $part_field ) {
292: if ( isset($ldap_values[$part_field]) ) {
293: if (isset($fields_to_set[$field]) ) {
294: $fields_to_set[$field] .= ' '.$ldap_values[$part_field];
295: }
296: else {
297: $fields_to_set[$field] = $ldap_values[$part_field];
298: }
299: }
300: }
301: dbg_error_log( "LDAP", "Setting usr->%s to %s from LDAP field %s", $field, $fields_to_set[$field], $mapping[$field] );
302: }
303: else if ( isset($c->authenticate_hook['config']['default_value']) && is_array($c->authenticate_hook['config']['default_value'])
304: && isset($c->authenticate_hook['config']['default_value'][$field] ) ) {
305: $fields_to_set[$field] = $c->authenticate_hook['config']['default_value'][$field];
306: dbg_error_log( "LDAP", "Setting usr->%s to %s from configured defaults", $field, $c->authenticate_hook['config']['default_value'][$field] );
307: }
308: }
309:
310: if ( $principal->Exists() ) {
311: $principal->Update($fields_to_set);
312: }
313: else {
314: $principal->Create($fields_to_set);
315: CreateHomeCollections($principal->username(), $c->default_timezone);
316: CreateDefaultRelationships($principal->username());
317: }
318: }
319:
320: 321: 322:
323: function array_values_mapping($mapping){
324: $attributes=array();
325: foreach ( $mapping as $field ) {
326: $tab_part_field = explode(",",$field);
327: foreach( $tab_part_field as $part_field ) {
328: $attributes[] = $part_field;
329: }
330: }
331: return $attributes;
332: }
333:
334: 335: 336:
337: function LDAP_check($username, $password ){
338: global $c;
339:
340: $ldapDriver = getStaticLdap();
341: if ( !$ldapDriver->valid ) {
342: sleep(1);
343: $ldapDriver = getStaticLdap();
344: if ( !$ldapDriver->valid ) {
345: dbg_error_log( "ERROR", "Couldn't contact LDAP server for authentication" );
346: foreach($c->messages as $msg) {
347: dbg_error_log( "ERROR", "-> ".$msg );
348: }
349: header( sprintf("HTTP/1.1 %d %s", 503, translate("Authentication server unavailable.")) );
350: exit(0);
351: }
352: }
353:
354: $mapping = $c->authenticate_hook['config']['mapping_field'];
355: if ( isset($mapping['active']) && !isset($mapping['user_active']) ) {
356:
357: $mapping['user_active'] = $mapping['active'];
358: unset($mapping['active']);
359: }
360: if ( isset($mapping['updated']) && !isset($mapping['modified']) ) {
361:
362: $mapping['modified'] = $mapping['updated'];
363: unset($mapping['updated']);
364: }
365: $attributes = array_values_mapping($mapping);
366:
367: 368: 369: 370:
371: $filter_munge = "";
372: if ( preg_match( '/^\(/', $ldapDriver->filterUsers ) ) {
373: $filter_munge = $ldapDriver->filterUsers;
374: }
375: else if ( isset($ldapDriver->filterUsers) && $ldapDriver->filterUsers != '' ) {
376: $filter_munge = "($ldapDriver->filterUsers)";
377: }
378:
379: $filter = "(&$filter_munge(".$mapping['username']."=$username))";
380: $valid = $ldapDriver->requestUser( $filter, $attributes, $username, $password );
381:
382:
383: if ( !$valid ) {
384: dbg_error_log( "LDAP", "user %s is not a valid user",$username );
385: return false;
386: }
387:
388: if ( $mapping['modified'] != "" && array_key_exists($mapping['modified'], $valid)) {
389: $ldap_timestamp = $valid[$mapping['modified']];
390: } else {
391: $ldap_timestamp = '19700101000000';
392: }
393:
394: 395: 396:
397: foreach($c->authenticate_hook['config']['format_updated'] as $k => $v)
398: $$k = substr($ldap_timestamp,$v[0],$v[1]);
399:
400: $ldap_timestamp = "$Y"."$m"."$d"."$H"."$M"."$S";
401: if ($mapping['modified'] != "" && array_key_exists($mapping['modified'], $valid)) {
402: $valid[$mapping['modified']] = "$Y-$m-$d $H:$M:$S";
403: }
404:
405: $principal = new Principal('username',$username);
406: if ( $principal->Exists() ) {
407:
408: $db_timestamp = $principal->modified;
409: $db_timestamp = substr(strtr($db_timestamp, array(':' => '',' '=>'','-'=>'')),0,14);
410: if( $ldap_timestamp <= $db_timestamp ) {
411: return $principal;
412: }
413:
414: }
415: else {
416: dbg_error_log( "LDAP", "user %s doesn't exist in local DB, we need to create it",$username );
417: }
418: $principal->setUsername($username);
419:
420:
421: sync_user_from_LDAP( $principal, $mapping, $valid );
422:
423: return $principal;
424:
425: }
426:
427: 428: 429:
430: function fix_unique_member($list) {
431: $fixed_list = array();
432: foreach ( $list as $member ){
433: list( $mem, $rest ) = explode(",", $member );
434: $member = str_replace( 'uid=', '', $mem );
435: array_unshift( $fixed_list, $member );
436: }
437: return $fixed_list;
438: }
439:
440: 441: 442:
443: function sync_LDAP_groups(){
444: global $c;
445: $ldapDriver = getStaticLdap();
446: if ( ! $ldapDriver->valid ) return;
447:
448: $mapping = $c->authenticate_hook['config']['group_mapping_field'];
449:
450: $attributes = array_values_mapping($mapping);
451: $ldap_groups_tmp = $ldapDriver->getAllGroups($attributes);
452:
453: if ( sizeof($ldap_groups_tmp) == 0 ) return;
454:
455: $member_field = $mapping['members'];
456: $dnfix = isset($c->authenticate_hook['config']['group_member_dnfix']) && $c->authenticate_hook['config']['group_member_dnfix'];
457:
458: foreach($ldap_groups_tmp as $key => $ldap_group){
459: $group_mapping = $ldap_group[$mapping['username']];
460: $ldap_groups_info[$group_mapping] = $ldap_group;
461: if ( is_array($ldap_groups_info[$group_mapping][$member_field]) ) {
462: unset( $ldap_groups_info[$group_mapping][$member_field]['count'] );
463: }
464: else {
465: $ldap_groups_info[$group_mapping][$member_field] = array($ldap_groups_info[$group_mapping][$member_field]);
466: }
467: unset($ldap_groups_tmp[$key]);
468: }
469: $db_groups = array();
470: $db_group_members = array();
471: $qry = new AwlQuery( "SELECT g.username AS group_name, member.username AS member_name FROM dav_principal g LEFT JOIN group_member ON (g.principal_id=group_member.group_id) LEFT JOIN dav_principal member ON (member.principal_id=group_member.member_id) WHERE g.type_id = 3");
472: $qry->Exec('sync_LDAP',__LINE__,__FILE__);
473: while($db_group = $qry->Fetch()) {
474: $db_groups[$db_group->group_name] = $db_group->group_name;
475: $db_group_members[$db_group->group_name][] = $db_group->member_name;
476: }
477:
478: $ldap_groups = array_keys($ldap_groups_info);
479:
480: $groups_to_create = array_diff($ldap_groups,$db_groups);
481:
482: $groups_to_deactivate = array_diff($db_groups,$ldap_groups);
483:
484: $groups_to_update = array_intersect($db_groups,$ldap_groups);
485:
486: if ( sizeof ( $groups_to_create ) ){
487: $c->messages[] = sprintf(i18n('- creating groups : %s'),join(', ',$groups_to_create));
488: $validUserFields = awl_get_fields('usr');
489: foreach ( $groups_to_create as $k => $group ){
490: $user = (object) array();
491:
492: if ( isset($c->authenticate_hook['config']['default_value']) && is_array($c->authenticate_hook['config']['default_value']) ) {
493: foreach ( $c->authenticate_hook['config']['default_value'] as $field => $value ) {
494: if ( isset($validUserFields[$field]) ) {
495: $user->{$field} = $value;
496: dbg_error_log( "LDAP", "Setting usr->%s to %s from configured defaults", $field, $value );
497: }
498: }
499: }
500: $user->user_no = 0;
501: $ldap_values = $ldap_groups_info[$group];
502: foreach ( $mapping as $field => $value ) {
503: dbg_error_log( "LDAP", "Considering copying %s", $field );
504: if ( isset($validUserFields[$field]) ) {
505: $user->{$field} = $ldap_values[$value];
506: dbg_error_log( "LDAP", "Setting usr->%s to %s from LDAP field %s", $field, $ldap_values[$value], $value );
507: }
508: }
509: if ($user->fullname=="") {
510: $user->fullname = $group;
511: }
512: if ($user->displayname=="") {
513: $user->displayname = $group;
514: }
515: $user->username = $group;
516: $user->updated = "now";
517:
518: $principal = new Principal('username',$group);
519: if ( $principal->Exists() ) {
520: $principal->Update($user);
521: }
522: else {
523: $principal->Create($user);
524: }
525:
526: $qry = new AwlQuery( "UPDATE dav_principal set type_id = 3 WHERE username=:group ",array(':group'=>$group) );
527: $qry->Exec('sync_LDAP',__LINE__,__FILE__);
528: Principal::cacheDelete('username', $group);
529: $c->messages[] = sprintf(i18n('- adding users %s to group : %s'),join(',',$ldap_groups_info[$group][$mapping['members']]),$group);
530: foreach ( $ldap_groups_info[$group][$mapping['members']] as $member ){
531: if ( $member_field == 'uniqueMember' || $dnfix ) {
532: list( $mem, $rest ) = explode(",", $member );
533: $member = str_replace( 'uid=', '', $mem );
534: }
535: $qry = new AwlQuery( "INSERT INTO group_member SELECT g.principal_id AS group_id,u.principal_id AS member_id FROM dav_principal g, dav_principal u WHERE g.username=:group AND u.username=:member;",array (':group'=>$group,':member'=>$member) );
536: $qry->Exec('sync_LDAP_groups',__LINE__,__FILE__);
537: Principal::cacheDelete('username', $member);
538: }
539: }
540: }
541:
542: if ( sizeof ( $groups_to_update ) ){
543: $c->messages[] = sprintf(i18n('- updating groups : %s'),join(', ',$groups_to_update));
544: foreach ( $groups_to_update as $group ){
545: $db_members = array_values ( $db_group_members[$group] );
546: $ldap_members = array_values ( $ldap_groups_info[$group][$member_field] );
547: if ( $member_field == 'uniqueMember' || $dnfix ) {
548: $ldap_members = fix_unique_member( $ldap_members );
549: }
550: $add_users = array_diff ( $ldap_members, $db_members );
551: if ( sizeof ( $add_users ) ){
552: $c->messages[] = sprintf(i18n('- adding %s to group : %s'),join(', ', $add_users ), $group);
553: foreach ( $add_users as $member ){
554: $qry = new AwlQuery( "INSERT INTO group_member SELECT g.principal_id AS group_id,u.principal_id AS member_id FROM dav_principal g, dav_principal u WHERE g.username=:group AND u.username=:member",array (':group'=>$group,':member'=>$member) );
555: $qry->Exec('sync_LDAP_groups',__LINE__,__FILE__);
556: Principal::cacheDelete('username', $member);
557: }
558: }
559: $remove_users = @array_flip( @array_flip( array_diff( $db_members, $ldap_members ) ));
560: if ( sizeof ( $remove_users ) ){
561: $c->messages[] = sprintf(i18n('- removing %s from group : %s'),join(', ', $remove_users ), $group);
562: foreach ( $remove_users as $member ){
563: $qry = new AwlQuery( "DELETE FROM group_member USING dav_principal g,dav_principal m WHERE group_id=g.principal_id AND member_id=m.principal_id AND g.username=:group AND m.username=:member",array (':group'=>$group,':member'=>$member) );
564: $qry->Exec('sync_LDAP_groups',__LINE__,__FILE__);
565: Principal::cacheDelete('username', $member);
566: }
567: }
568: }
569: }
570:
571: if ( sizeof ( $groups_to_deactivate ) ){
572: $c->messages[] = sprintf(i18n('- deactivate groups : %s'),join(', ',$groups_to_deactivate));
573: foreach ( $groups_to_deactivate as $group ){
574: $qry = new AwlQuery( 'UPDATE dav_principal SET user_active=FALSE WHERE username=:group AND type_id = 3',array(':group'=>$group) );
575: $qry->Exec('sync_LDAP',__LINE__,__FILE__);
576: Principal::cacheFlush('username=:group AND type_id = 3', array(':group'=>$group) );
577: }
578: }
579:
580: }
581:
582: 583: 584:
585: function sync_LDAP(){
586: global $c;
587: $ldapDriver = getStaticLdap();
588: if ( ! $ldapDriver->valid ) return;
589:
590: $mapping = $c->authenticate_hook['config']['mapping_field'];
591: $attributes = array_values_mapping($mapping);
592: $ldap_users_tmp = $ldapDriver->getAllUsers($attributes);
593:
594: if ( sizeof($ldap_users_tmp) == 0 ) return;
595:
596: foreach($ldap_users_tmp as $key => $ldap_user){
597: $ldap_users_info[$ldap_user[$mapping['username']]] = $ldap_user;
598: unset($ldap_users_tmp[$key]);
599: }
600: $qry = new AwlQuery( "SELECT username, user_no, modified as updated FROM dav_principal where type_id=1");
601: $qry->Exec('sync_LDAP',__LINE__,__FILE__);
602: while($db_user = $qry->Fetch()) {
603: $db_users[] = $db_user->username;
604: $db_users_info[$db_user->username] = array('user_no' => $db_user->user_no, 'updated' => $db_user->updated);
605: }
606:
607:
608: $ldap_users = array_keys($ldap_users_info);
609:
610: $users_to_create = array_diff($ldap_users,$db_users);
611:
612: $users_to_deactivate = array_diff($db_users,$ldap_users);
613:
614: $users_to_update = array_intersect($db_users,$ldap_users);
615:
616:
617: if ( sizeof($users_to_create) ) {
618: $c->messages[] = sprintf(i18n('- creating record for users : %s'),join(', ',$users_to_create));
619:
620: foreach( $users_to_create as $username ) {
621: $principal = new Principal( 'username', $username );
622: $valid = $ldap_users_info[$username];
623: if ( $mapping['modified'] != "" && array_key_exists($mapping['modified'], $valid)) {
624: $ldap_timestamp = $valid[$mapping['modified']];
625: } else {
626: $ldap_timestamp = '19700101000000';
627: }
628:
629: if ( !empty($c->authenticate_hook['config']['format_updated']) ) {
630: 631: 632:
633: foreach($c->authenticate_hook['config']['format_updated'] as $k => $v)
634: $$k = substr($ldap_timestamp,$v[0],$v[1]);
635: $ldap_timestamp = $Y.$m.$d.$H.$M.$S;
636: }
637: else if ( preg_match('{^(\d{8})(\d{6})(Z)?$', $ldap_timestamp, $matches ) ) {
638: $ldap_timestamp = $matches[1].'T'.$matches[2].$matches[3];
639: }
640: else if ( empty($ldap_timestamp) ) {
641: $ldap_timestamp = date('c');
642: }
643: if ( $mapping['modified'] != "" && array_key_exists($mapping['modified'], $valid)) {
644: $valid[$mapping['modified']] = $ldap_timestamp;
645: }
646:
647: sync_user_from_LDAP( $principal, $mapping, $valid );
648: }
649: }
650:
651:
652: $params = array();
653: $i = 0;
654: $paramstring = '';
655: foreach( $users_to_deactivate AS $v ) {
656: if ( isset($c->do_not_sync_from_ldap) && isset($c->do_not_sync_from_ldap[$v]) ) continue;
657: if ( $i > 0 ) $paramstring .= ',';
658: $paramstring .= ':u'.$i.'::text';
659: $params[':u'.$i++] = strtolower($v);
660: }
661: if ( count($params) > 0 ) {
662: $c->messages[] = sprintf(i18n('- deactivating users : %s'),join(', ',$users_to_deactivate));
663: $qry = new AwlQuery( 'UPDATE usr SET active = FALSE WHERE lower(username) IN ('.$paramstring.')', $params);
664: $qry->Exec('sync_LDAP',__LINE__,__FILE__);
665:
666: Principal::cacheFlush('lower(username) IN ('.$paramstring.')', $params);
667: }
668:
669:
670: if ( sizeof($users_to_update) ) {
671: foreach ( $users_to_update as $key=> $username ) {
672: $principal = new Principal( 'username', $username );
673: $valid=$ldap_users_info[$username];
674: if ( $mapping['modified'] != "" && array_key_exists($mapping['modified'], $valid)) {
675: $ldap_timestamp = $valid[$mapping['modified']];
676: } else {
677: $ldap_timestamp = '19700101000000';
678: }
679:
680: $valid['user_no'] = $db_users_info[$username]['user_no'];
681: $mapping['user_no'] = 'user_no';
682:
683: 684: 685:
686: foreach($c->authenticate_hook['config']['format_updated'] as $k => $v) {
687: $$k = substr($ldap_timestamp,$v[0],$v[1]);
688: }
689: $ldap_timestamp = $Y.$m.$d.$H.$M.$S;
690: $valid[$mapping['modified']] = "$Y-$m-$d $H:$M:$S";
691:
692: $db_timestamp = substr(strtr($db_users_info[$username]['updated'], array(':' => '',' '=>'','-'=>'')),0,14);
693: if ( $ldap_timestamp > $db_timestamp ) {
694: sync_user_from_LDAP($principal, $mapping, $valid );
695: }
696: else {
697: unset($users_to_update[$key]);
698: $users_nothing_done[] = $username;
699: }
700: }
701: if ( sizeof($users_to_update) )
702: $c->messages[] = sprintf(i18n('- updating user records : %s'),join(', ',$users_to_update));
703: if ( sizeof($users_nothing_done) )
704: $c->messages[] = sprintf(i18n('- nothing done on : %s'),join(', ', $users_nothing_done));
705: }
706:
707: $admins = 0;
708: $qry = new AwlQuery( "SELECT count(*) AS admins FROM usr JOIN role_member USING ( user_no ) JOIN roles USING (role_no) WHERE usr.active=TRUE AND role_name='Admin'");
709: $qry->Exec('sync_LDAP',__LINE__,__FILE__);
710: while ( $db_user = $qry->Fetch() ) {
711: $admins = $db_user->admins;
712: }
713: if ( $admins == 0 ) {
714: $c->messages[] = sprintf(i18n('Warning: there are no active admin users! You should fix this before logging out. Consider using the $c->do_not_sync_from_ldap configuration setting.'));
715: }
716: }
717: