DAViCal
drivers_ldap.php
1 <?php
14 require_once("auth-functions.php");
15 
20 {
28  var $connect;
29 
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  //Set LDAP protocol version
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 we are given a URI (or multiple) to connect to, use them. This allows support for LDAPS connections
58  // as well as redundant ldap servers to connect to
59  // Otherwise default to host and port
60  if (isset($config['uri']))
61  $this->connect=ldap_connect($config['uri']);
62  elseif ($port)
63  $this->connect=ldap_connect($host, $port);
64  else
65  $this->connect=ldap_connect($host);
66 
67  if (! $this->connect){
68  if (isset($config['uri']))
69  $c->messages[] = sprintf(translate( 'drivers_ldap : Unable to connect to LDAP with URI: %s'), $config['uri'] );
70  else
71  $c->messages[] = sprintf(translate( 'drivers_ldap : Unable to connect to LDAP with port %s on host %s'), $port, $host );
72  $this->valid=false;
73  return ;
74  }
75 
76  dbg_error_log( "LDAP", "drivers_ldap : Connected to LDAP server %s",$host );
77 
78  // Start TLS if desired (requires protocol version 3)
79  if (isset($config['startTLS'])) {
80  if (!ldap_set_option($this->connect, LDAP_OPT_PROTOCOL_VERSION, 3)) {
81  $c->messages[] = i18n('drivers_ldap : Failed to set LDAP to use protocol version 3, TLS not supported');
82  $this->valid=false;
83  return;
84  }
85  if (!ldap_start_tls($this->connect)) {
86  $c->messages[] = i18n('drivers_ldap : Could not start TLS: ldap_start_tls() failed');
87  $this->valid=false;
88  return;
89  }
90  }
91 
92  //Set the search scope to be used, default to subtree. This sets the functions to be called later.
93  if (!isset($config['scope'])) $config['scope'] = 'subtree';
94  switch (strtolower($config['scope'])) {
95  case "base":
96  $this->ldap_query_one = 'ldap_read';
97  $this->ldap_query_all = 'ldap_read';
98  break;
99  case "onelevel":
100  $this->ldap_query_one = 'ldap_list';
101  $this->ldap_query_all = 'ldap_search';
102  break;
103  default:
104  $this->ldap_query_one = 'ldap_search';
105  $this->ldap_query_all = 'ldap_search';
106  break;
107  }
108 
109  //connect as root
110  if (!ldap_bind($this->connect, (isset($config['bindDN']) ? $config['bindDN'] : null), (isset($config['passDN']) ? $config['passDN'] : null) ) ){
111  $bindDN = isset($config['bindDN']) ? $config['bindDN'] : 'anonymous';
112  $passDN = isset($config['passDN']) ? $config['passDN'] : 'anonymous';
113  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 );
114  $c->messages[] = i18n( 'drivers_ldap : Unable to bind to LDAP - check your configuration for bindDN and passDN, and that your LDAP server is reachable');
115  $this->valid=false;
116  return ;
117  }
118  $this->valid = true;
119  //root to start search
120  $this->baseDNUsers = is_string($config['baseDNUsers']) ? array($config['baseDNUsers']) : $config['baseDNUsers'];
121  $this->filterUsers = (isset($config['filterUsers']) ? $config['filterUsers'] : null);
122  $this->baseDNGroups = (isset($config['baseDNGroups']) ? (is_string($config['baseDNGroups']) ? array($config['baseDNGroups']) : $config['baseDNGroups']) : null);
123  $this->filterGroups = (isset($config['filterGroups']) ? $config['filterGroups'] : null);
124  }
125 
129  function getAllUsers($attributes){
130  global $c;
131 
132  $query = $this->ldap_query_all;
133  $ret = array();
134 
135  foreach($this->baseDNUsers as $baseDNUsers) {
136  $entry = $query($this->connect,$baseDNUsers,$this->filterUsers,$attributes);
137 
138  if (!ldap_first_entry($this->connect,$entry)) {
139  $c->messages[] = sprintf(translate('Error NoUserFound with filter >%s<, attributes >%s< , dn >%s<'),
140  $this->filterUsers,
141  join(', ', $attributes),
142  $baseDNUsers);
143  }
144  $row = array();
145  for($i = ldap_first_entry($this->connect,$entry);
146  $i && $arr = ldap_get_attributes($this->connect,$i);
147  $i = ldap_next_entry($this->connect,$i) ) {
148  $row = array();
149  for ($j=0; $j < $arr['count']; $j++) {
150  $row[$arr[$j]] = $arr[$arr[$j]][0];
151  }
152  $ret[]=$row;
153  }
154  }
155  return $ret;
156  }
157 
161  function getAllGroups($attributes){
162  global $c;
163 
164  $query = $this->ldap_query_all;
165  $ret = array();
166 
167  foreach($this->baseDNGroups as $baseDNGroups) {
168  $entry = $query($this->connect,$baseDNGroups,$this->filterGroups,$attributes);
169 
170  if (!ldap_first_entry($this->connect,$entry)) {
171  $c->messages[] = sprintf(translate('Error NoGroupFound with filter >%s<, attributes >%s< , dn >%s<'),
172  $this->filterGroups,
173  join(', ', $attributes),
174  $baseDNGroups);
175  }
176  $row = array();
177  for($i = ldap_first_entry($this->connect,$entry);
178  $i && $arr = ldap_get_attributes($this->connect,$i);
179  $i = ldap_next_entry($this->connect,$i) ) {
180  for ($j=0; $j < $arr['count']; $j++) {
181  $row[$arr[$j]] = count($arr[$arr[$j]])>2?$arr[$arr[$j]]:$arr[$arr[$j]][0];
182  }
183  $ret[]=$row;
184  unset($row);
185  }
186  }
187  return $ret;
188  }
189 
200  function requestUser( $filter, $attributes, $username, $passwd) {
201  global $c;
202 
203  $entry=NULL;
204  // We get the DN of the USER
205  $query = $this->ldap_query_one;
206  # ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7);
207 
208  foreach($this->baseDNUsers as $baseDNUsers) {
209  $entry = $query($this->connect, $baseDNUsers, $filter, $attributes);
210 
211  if (ldap_first_entry($this->connect,$entry) )
212  break;
213 
214  dbg_error_log( "LDAP", "drivers_ldap : Failed to find user with baseDN: %s", $baseDNUsers );
215  }
216 
217  if ( !ldap_first_entry($this->connect, $entry) ){
218  dbg_error_log( "ERROR", "drivers_ldap : Unable to find the user with filter %s",$filter );
219  return false;
220  } else {
221  dbg_error_log( "LDAP", "drivers_ldap : Found a user using filter %s",$filter );
222  }
223 
224  $dnUser = ldap_get_dn($this->connect, ldap_first_entry($this->connect,$entry));
225 
226  if ( isset($c->authenticate_hook['config']['i_use_mode_kerberos']) && $c->authenticate_hook['config']['i_use_mode_kerberos'] == "i_know_what_i_am_doing") {
227  if (isset($_SERVER["REMOTE_USER"])) {
228  dbg_error_log( "LOG", "drivers_ldap : Skipping password Check for user %s which should be the same as %s",$username , $_SERVER["REMOTE_USER"]);
229  if ($username != $_SERVER["REMOTE_USER"]) {
230  return false;
231  }
232  } else {
233  dbg_error_log( "LOG", "drivers_ldap : Skipping password Check for user %s which should be the same as %s",$username , $_SERVER["REDIRECT_REMOTE_USER"]);
234  if ($username != $_SERVER["REDIRECT_REMOTE_USER"]) {
235  return false;
236  }
237  }
238  }
239  else if ( empty($passwd) || preg_match('/[\x00-\x19]/',$passwd) ) {
240  // See http://www.php.net/manual/en/function.ldap-bind.php#73718 for more background
241  dbg_error_log( 'LDAP', 'drivers_ldap : user %s supplied empty or invalid password: login rejected', $dnUser );
242  return false;
243  }
244  else {
245  if ( !@ldap_bind($this->connect, $dnUser, $passwd) ) {
246  dbg_error_log( "LDAP", "drivers_ldap : Failed to bind to user %s ", $dnUser );
247  return false;
248  }
249  }
250 
251  dbg_error_log( "LDAP", "drivers_ldap : Bound to user %s using password %s", $dnUser,
252  (isset($c->dbg['password']) && $c->dbg['password'] ? $passwd : 'another delicious password for the debugging monster!') );
253 
254  $i = ldap_first_entry($this->connect,$entry);
255  $arr = ldap_get_attributes($this->connect,$i);
256  for( $i=0; $i<$arr['count']; $i++ ) {
257  $ret[$arr[$i]]=$arr[$arr[$i]][0];
258  }
259  return $ret;
260 
261  }
262 }
263 
264 
268 function getStaticLdap() {
269  global $c;
270  // Declare a static variable to hold the object instance
271  static $instance;
272 
273  // If the instance is not there, create one
274  if(!isset($instance)) {
275  $ldapDriver = new ldapDriver($c->authenticate_hook['config']);
276 
277  if ($ldapDriver->valid) {
278  $instance = $ldapDriver;
279  }
280  }
281  else {
282  $ldapDriver = $instance;
283  }
284  return $ldapDriver;
285 }
286 
287 
292 function sync_user_from_LDAP( Principal &$principal, $mapping, $ldap_values ) {
293  global $c;
294 
295  dbg_error_log( "LDAP", "Going to sync the user from LDAP" );
296 
297  $fields_to_set = array();
298  $updateable_fields = Principal::updateableFields();
299  foreach( $updateable_fields AS $field ) {
300  if ( isset($mapping[$field]) ) {
301  $tab_part_fields = explode(',',$mapping[$field]);
302  foreach( $tab_part_fields as $part_field ) {
303  if ( isset($ldap_values[$part_field]) ) {
304  if (isset($fields_to_set[$field]) ) {
305  $fields_to_set[$field] .= ' '.$ldap_values[$part_field];
306  }
307  else {
308  $fields_to_set[$field] = $ldap_values[$part_field];
309  }
310  }
311  }
312  dbg_error_log( "LDAP", "Setting usr->%s to %s from LDAP field %s", $field, $fields_to_set[$field], $mapping[$field] );
313  }
314  else if ( isset($c->authenticate_hook['config']['default_value']) && is_array($c->authenticate_hook['config']['default_value'])
315  && isset($c->authenticate_hook['config']['default_value'][$field] ) ) {
316  $fields_to_set[$field] = $c->authenticate_hook['config']['default_value'][$field];
317  dbg_error_log( "LDAP", "Setting usr->%s to %s from configured defaults", $field, $c->authenticate_hook['config']['default_value'][$field] );
318  }
319  }
320 
321  if ( $principal->Exists() ) {
322  $principal->Update($fields_to_set);
323  }
324  else {
325  $principal->Create($fields_to_set);
326  CreateHomeCollections($principal->username());
327  CreateDefaultRelationships($principal->username());
328  }
329 }
330 
334 function array_values_mapping($mapping){
335  $attributes=array();
336  foreach ( $mapping as $field ) {
337  $tab_part_field = explode(",",$field);
338  foreach( $tab_part_field as $part_field ) {
339  $attributes[] = $part_field;
340  }
341  }
342  return $attributes;
343 }
344 
348 function LDAP_check($username, $password ){
349  global $c;
350 
351  $ldapDriver = getStaticLdap();
352  if ( !$ldapDriver->valid ) {
353  sleep(1); // Sleep very briefly to try and survive intermittent issues
354  $ldapDriver = getStaticLdap();
355  if ( !$ldapDriver->valid ) {
356  dbg_error_log( "ERROR", "Couldn't contact LDAP server for authentication" );
357  foreach($c->messages as $msg) {
358  dbg_error_log( "ERROR", "-> ".$msg );
359  }
360  header( sprintf("HTTP/1.1 %d %s", 503, translate("Authentication server unavailable.")) );
361  exit(0);
362  }
363  }
364 
365  $mapping = $c->authenticate_hook['config']['mapping_field'];
366  if ( isset($mapping['active']) && !isset($mapping['user_active']) ) {
367  // Backward compatibility: now 'user_active'
368  $mapping['user_active'] = $mapping['active'];
369  unset($mapping['active']);
370  }
371  if ( isset($mapping['updated']) && !isset($mapping['modified']) ) {
372  // Backward compatibility: now 'modified'
373  $mapping['modified'] = $mapping['updated'];
374  unset($mapping['updated']);
375  }
376  $attributes = array_values_mapping($mapping);
377 
382  $filter_munge = "";
383  if ( preg_match( '/^\(/', $ldapDriver->filterUsers ) ) {
384  $filter_munge = $ldapDriver->filterUsers;
385  }
386  else if ( isset($ldapDriver->filterUsers) && $ldapDriver->filterUsers != '' ) {
387  $filter_munge = "($ldapDriver->filterUsers)";
388  }
389 
390  $filter = "(&$filter_munge(".$mapping['username']."=$username))";
391  $valid = $ldapDriver->requestUser( $filter, $attributes, $username, $password );
392 
393  // is a valid user or not
394  if ( !$valid ) {
395  dbg_error_log( "LDAP", "user %s is not a valid user",$username );
396  return false;
397  }
398 
399  if ( $mapping['modified'] != "" && array_key_exists($mapping['modified'], $valid)) {
400  $ldap_timestamp = $valid[$mapping['modified']];
401  } else {
402  $ldap_timestamp = '19700101000000';
403  }
404 
408  foreach($c->authenticate_hook['config']['format_updated'] as $k => $v)
409  $$k = substr($ldap_timestamp,$v[0],$v[1]);
410 
411  $ldap_timestamp = "$Y"."$m"."$d"."$H"."$M"."$S";
412  if ($mapping['modified'] != "" && array_key_exists($mapping['modified'], $valid)) {
413  $valid[$mapping['modified']] = "$Y-$m-$d $H:$M:$S";
414  }
415 
416  $principal = new Principal('username',$username);
417  if ( $principal->Exists() ) {
418  // should we update it ?
419  $db_timestamp = $principal->modified;
420  $db_timestamp = substr(strtr($db_timestamp, array(':' => '',' '=>'','-'=>'')),0,14);
421  if( $ldap_timestamp <= $db_timestamp ) {
422  return $principal; // no need to update
423  }
424  // we will need to update the user record
425  }
426  else {
427  dbg_error_log( "LDAP", "user %s doesn't exist in local DB, we need to create it",$username );
428  }
429  $principal->setUsername($username);
430 
431  // The local cached user doesn't exist, or is older, so we create/update their details
432  sync_user_from_LDAP( $principal, $mapping, $valid );
433 
434  return $principal;
435 
436 }
437 
441 function fix_unique_member($list) {
442  $fixed_list = array();
443  foreach ( $list as $member ){
444  array_unshift( $fixed_list, ldap_explode_dn($member,1)[0]);
445  }
446  return $fixed_list;
447 }
448 
452 function sync_LDAP_groups(){
453  global $c;
454  $ldapDriver = getStaticLdap();
455  if ( ! $ldapDriver->valid ) return;
456 
457  $mapping = $c->authenticate_hook['config']['group_mapping_field'];
458  //$attributes = array('cn','modifyTimestamp','memberUid');
459  $attributes = array_values_mapping($mapping);
460  $ldap_groups_tmp = $ldapDriver->getAllGroups($attributes);
461 
462  if ( sizeof($ldap_groups_tmp) == 0 ) return;
463 
464  $member_field = $mapping['members'];
465  $dnfix = isset($c->authenticate_hook['config']['group_member_dnfix']) && $c->authenticate_hook['config']['group_member_dnfix'];
466 
467  foreach($ldap_groups_tmp as $key => $ldap_group){
468  $group_mapping = $ldap_group[$mapping['username']];
469  $ldap_groups_info[$group_mapping] = $ldap_group;
470  if ( is_array($ldap_groups_info[$group_mapping][$member_field]) ) {
471  unset( $ldap_groups_info[$group_mapping][$member_field]['count'] );
472  }
473  else {
474  $ldap_groups_info[$group_mapping][$member_field] = array($ldap_groups_info[$group_mapping][$member_field]);
475  }
476  unset($ldap_groups_tmp[$key]);
477  }
478  $db_groups = array();
479  $db_group_members = array();
480  $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");
481  $qry->Exec('sync_LDAP',__LINE__,__FILE__);
482  while($db_group = $qry->Fetch()) {
483  $db_groups[$db_group->group_name] = $db_group->group_name;
484  $db_group_members[$db_group->group_name][] = $db_group->member_name;
485  }
486 
487  $ldap_groups = array_keys($ldap_groups_info);
488 
489  // users only in ldap
490  $groups_to_create = array_diff($ldap_groups,$db_groups);
491 
492  // users only in db
493  $groups_to_deactivate = array_diff($db_groups,$ldap_groups);
494 
495  // users present in ldap and in the db
496  $groups_to_update = array_intersect($db_groups,$ldap_groups);
497 
498  // groups where nothing was done
499  $groups_nothing_done[] = null;
500 
501  if ( sizeof ( $groups_to_create ) ){
502  $validUserFields = awl_get_fields('usr');
503  foreach ( $groups_to_create as $k => $group ){
504  if ( isset($c->do_not_sync_group_from_ldap) && isset($c->do_not_sync_group_from_ldap[$group]) ){
505  unset($groups_to_create[$k]);
506  $groups_nothing_done[] = $group;
507  continue;
508  }
509 
510  $user = (object) array();
511 
512  if ( isset($c->authenticate_hook['config']['default_value']) && is_array($c->authenticate_hook['config']['default_value']) ) {
513  foreach ( $c->authenticate_hook['config']['default_value'] as $field => $value ) {
514  if ( isset($validUserFields[$field]) ) {
515  $user->{$field} = $value;
516  dbg_error_log( "LDAP", "Setting usr->%s to %s from configured defaults", $field, $value );
517  }
518  }
519  }
520  $user->user_no = 0;
521  $ldap_values = $ldap_groups_info[$group];
522  foreach ( $mapping as $field => $value ) {
523  dbg_error_log( "LDAP", "Considering copying %s", $field );
524  if ( isset($validUserFields[$field]) ) {
525  $user->{$field} = $ldap_values[$value];
526  dbg_error_log( "LDAP", "Setting usr->%s to %s from LDAP field %s", $field, $ldap_values[$value], $value );
527  }
528  }
529  if ($user->fullname=="") {
530  $user->fullname = $group;
531  }
532  if ($user->displayname=="") {
533  $user->displayname = $group;
534  }
535  $user->username = $group;
536  $user->updated = "now";
538  $principal = new Principal('username',$group);
539  if ( $principal->Exists() ) {
540  $principal->Update($user);
541  }
542  else {
543  $principal->Create($user);
544  }
545 
546  $qry = new AwlQuery( "UPDATE dav_principal set type_id = 3 WHERE username=:group ",array(':group'=>$group) );
547  $qry->Exec('sync_LDAP',__LINE__,__FILE__);
548  Principal::cacheDelete('username', $group);
549  // mark group for updating, so users get synced
550  $groups_to_update[] = $group;
551  }
552  $c->messages[] = sprintf( i18n('- creating groups : %s'), join(', ',$groups_to_create) );
553  }
554 
555  if ( sizeof ( $groups_to_update ) ){
556  $c->messages[] = sprintf(i18n('- updating groups : %s'),join(', ',$groups_to_update));
557  foreach ( $groups_to_update as $group ){
558  $db_members = array_values ( $db_group_members[$group] );
559  $ldap_members = array_values ( $ldap_groups_info[$group][$member_field] );
560  if ( $member_field == 'uniqueMember' || $dnfix ) {
561  $ldap_members = fix_unique_member( $ldap_members );
562  }
563  $add_users = array_diff ( $ldap_members, $db_members );
564  if ( sizeof ( $add_users ) ){
565  $c->messages[] = sprintf(i18n('- adding %s to group : %s'),join(', ', $add_users ), $group);
566  foreach ( $add_users as $member ){
567  $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) );
568  $qry->Exec('sync_LDAP_groups',__LINE__,__FILE__);
569  Principal::cacheDelete('username', $member);
570  }
571  }
572  $remove_users = @array_flip( @array_flip( array_diff( $db_members, $ldap_members ) ));
573  if ( sizeof ( $remove_users ) ){
574  $c->messages[] = sprintf(i18n('- removing %s from group : %s'),join(', ', $remove_users ), $group);
575  foreach ( $remove_users as $member ){
576  $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) );
577  $qry->Exec('sync_LDAP_groups',__LINE__,__FILE__);
578  Principal::cacheDelete('username', $member);
579  }
580  }
581  }
582  }
583 
584  if ( sizeof ( $groups_to_deactivate ) ){
585  foreach ( $groups_to_deactivate as $k => $group ){
586  if ( isset($c->do_not_sync_group_from_ldap) && isset($c->do_not_sync_group_from_ldap[$group]) ){
587  unset($groups_to_deactivate[$k]);
588  $groups_nothing_done[] = $group;
589  } else {
590  $qry = new AwlQuery( 'UPDATE dav_principal SET user_active=FALSE WHERE username=:group AND type_id = 3',array(':group'=>$group) );
591  $qry->Exec('sync_LDAP',__LINE__,__FILE__);
592  Principal::cacheFlush('username=:group AND type_id = 3', array(':group'=>$group) );
593  }
594  }
595  if ( sizeof($groups_to_deactivate) )
596  $c->messages[] = sprintf(i18n('- deactivated groups : %s'), join(', ',$groups_to_deactivate));
597  }
598  if ( sizeof($groups_nothing_done) )
599  $c->messages[] = sprintf( i18n('- nothing done on : %s'), join(', ',$groups_nothing_done) );
600 
601 }
602 
606 function sync_LDAP(){
607  global $c;
608  $ldapDriver = getStaticLdap();
609  if ( ! $ldapDriver->valid ) return;
610 
611  $mapping = $c->authenticate_hook['config']['mapping_field'];
612  $attributes = array_values_mapping($mapping);
613  $ldap_users_tmp = $ldapDriver->getAllUsers($attributes);
614 
615  if ( sizeof($ldap_users_tmp) == 0 ) return;
616 
617  foreach($ldap_users_tmp as $key => $ldap_user){
618  if(!isset($ldap_user[$mapping['username']])) continue;
619  $ldap_users_info[$ldap_user[$mapping['username']]] = $ldap_user;
620  unset($ldap_users_tmp[$key]);
621  }
622  $qry = new AwlQuery( "SELECT username, user_no, modified as updated , user_active FROM dav_principal where type_id=1");
623  $qry->Exec('sync_LDAP',__LINE__,__FILE__);
624  while($db_user = $qry->Fetch()) {
625  $db_users[] = $db_user->username;
626  $db_users_info[$db_user->username] = array('user_no' => $db_user->user_no, 'updated' => $db_user->updated, 'user_active' => $db_user->user_active);
627  }
628 
629  // all users from ldap
630  $ldap_users = array_keys($ldap_users_info);
631  // users only in ldap
632  $users_to_create = array_diff($ldap_users,$db_users);
633  // users only in db
634  $users_to_deactivate = array_diff($db_users,$ldap_users);
635  // users present in ldap and in the db
636  $users_to_update = array_intersect($db_users,$ldap_users);
637 
638  // creation of all users;
639  if ( sizeof($users_to_create) ) {
640  foreach( $users_to_create as $k => $username ) {
641  if ( isset($c->do_not_sync_from_ldap) && isset($c->do_not_sync_from_ldap[$username]) ) {
642  unset( $users_to_create[$k] );
643  $users_nothing_done[] = $username;
644  continue;
645  }
646  $principal = new Principal( 'username', $username );
647  $valid = $ldap_users_info[$username];
648  if ( $mapping['modified'] != "" && array_key_exists($mapping['modified'], $valid)) {
649  $ldap_timestamp = $valid[$mapping['modified']];
650  } else {
651  $ldap_timestamp = '19700101000000';
652  }
653 
654  if ( !empty($c->authenticate_hook['config']['format_updated']) ) {
658  foreach($c->authenticate_hook['config']['format_updated'] as $k => $v)
659  $$k = substr($ldap_timestamp,$v[0],$v[1]);
660  $ldap_timestamp = $Y.$m.$d.$H.$M.$S;
661  }
662  else if ( preg_match('{^(\d{8})(\d{6})(Z)?$', $ldap_timestamp, $matches ) ) {
663  $ldap_timestamp = $matches[1].'T'.$matches[2].$matches[3];
664  }
665  else if ( empty($ldap_timestamp) ) {
666  $ldap_timestamp = date('c');
667  }
668  if ( $mapping['modified'] != "" && array_key_exists($mapping['modified'], $valid)) {
669  $valid[$mapping['modified']] = $ldap_timestamp;
670  }
671 
672  sync_user_from_LDAP( $principal, $mapping, $valid );
673  }
674  $c->messages[] = sprintf( i18n('- creating record for users : %s'), join(', ',$users_to_create) );
675  }
676 
677  // deactivating all users
678  $params = array();
679  $i = 0;
680  $paramstring = '';
681  foreach( $users_to_deactivate as $k => $v ) {
682  if ( isset($c->do_not_sync_from_ldap) && isset($c->do_not_sync_from_ldap[$v]) ) {
683  unset($users_to_deactivate[$k]);
684  $users_nothing_done[] = $v;
685  continue;
686  }
687  if ( $i > 0 ) $paramstring .= ',';
688  $paramstring .= ':u'.$i.'::text';
689  $params[':u'.$i++] = strtolower($v);
690  }
691  if ( count($params) > 0 ) {
692  $c->messages[] = sprintf(i18n('- deactivating users : %s'),join(', ',$users_to_deactivate));
693  $qry = new AwlQuery( 'UPDATE usr SET active = FALSE WHERE lower(username) IN ('.$paramstring.')', $params);
694  $qry->Exec('sync_LDAP',__LINE__,__FILE__);
695 
696  Principal::cacheFlush('lower(username) IN ('.$paramstring.')', $params);
697  }
698 
699  // updating all users
700  if ( sizeof($users_to_update) ) {
701  foreach ( $users_to_update as $key=> $username ) {
702  $principal = new Principal( 'username', $username );
703  $valid=$ldap_users_info[$username];
704  if ( $mapping['modified'] != "" && array_key_exists($mapping['modified'], $valid)) {
705  $ldap_timestamp = $valid[$mapping['modified']];
706  } else {
707  $ldap_timestamp = '19700101000000';
708  }
709 
710  $valid['user_no'] = $db_users_info[$username]['user_no'];
711  $mapping['user_no'] = 'user_no';
712 
716  foreach($c->authenticate_hook['config']['format_updated'] as $k => $v) {
717  $$k = substr($ldap_timestamp,$v[0],$v[1]);
718  }
719  $ldap_timestamp = $Y.$m.$d.$H.$M.$S;
720  $valid[$mapping['modified']] = "$Y-$m-$d $H:$M:$S";
721 
722  $db_timestamp = substr(strtr($db_users_info[$username]['updated'], array(':' => '',' '=>'','-'=>'')),0,14);
723  if ( $ldap_timestamp > $db_timestamp || !$db_users_info[$username]['user_active']) {
724  $principal->user_active = true;
725  sync_user_from_LDAP($principal, $mapping, $valid);
726  }
727  else {
728  unset($users_to_update[$key]);
729  $users_nothing_done[] = $username;
730  }
731  }
732  if ( sizeof($users_to_update) )
733  $c->messages[] = sprintf(i18n('- updating user records : %s'),join(', ',$users_to_update));
734  }
735  if ( sizeof($users_nothing_done) )
736  $c->messages[] = sprintf( i18n('- nothing done on : %s'), join(', ',$users_nothing_done) );
737 
738  // check for remaining admins
739  $admins = 0;
740  $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'");
741  $qry->Exec('sync_LDAP',__LINE__,__FILE__);
742  while ( $db_user = $qry->Fetch() ) {
743  $admins = $db_user->admins;
744  }
745  if ( $admins == 0 ) {
746  $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.'));
747  }
748 }
getAllGroups($attributes)
__construct($config)
getAllUsers($attributes)
requestUser( $filter, $attributes, $username, $passwd)
setUsername($new_username)
Definition: Principal.php:344