FusionDirectory
 All Data Structures Files Functions Variables
class_userinfo.inc
Go to the documentation of this file.
1 <?php
2 /*
3  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
4  Copyright (C) 2003-2010 Cajus Pollmeier
5  Copyright (C) 2011-2016 FusionDirectory
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21 
33 class userinfo
34 {
35  var $dn;
36  var $cn;
37  var $uid;
38  var $sn = '';
39  var $givenName = '';
40  var $gidNumber = -1;
41  var $language = "";
42  var $subtreeACL = array();
43  var $ACL = array();
44  var $groups = array();
45  var $roles = array();
46  var $result_cache = array();
47  var $ignoreACL = FALSE;
48 
49  var $ACLperPath = array();
50  var $ACLperPath_usesFilter = array();
51 
52  /* get acl's an put them into the userinfo object
53  attr subtreeACL (userdn:components, userdn:component1#sub1#sub2,component2,...) */
54  function __construct($userdn)
55  {
56  global $config;
57  $this->dn = $userdn;
58  $this->ignoreACL = ($config->get_cfg_value('ignoreAcl') == $this->dn);
59 
60  $this->loadLDAPInfo();
61 
62  /* Initialize ACL_CACHE */
63  $this->reset_acl_cache();
64  }
65 
67  function loadLDAPInfo()
68  {
69  global $config;
70  $ldap = $config->get_ldap_link();
71  $ldap->cat($this->dn, array('cn', 'sn', 'givenName', 'uid', 'gidNumber', 'preferredLanguage'));
72  $attrs = $ldap->fetch();
73 
74  $this->uid = $attrs['uid'][0];
75 
76  if (isset($attrs['cn'][0])) {
77  $this->cn = $attrs['cn'][0];
78  } elseif (isset($attrs['givenName'][0]) && isset($attrs['sn'][0])) {
79  $this->cn = $attrs['givenName'][0].' '.$attrs['sn'][0];
80  } else {
81  $this->cn = $attrs['uid'][0];
82  }
83  if (isset($attrs['gidNumber'][0])) {
84  $this->gidNumber = $attrs['gidNumber'][0];
85  }
86  if (isset($attrs['sn'][0])) {
87  $this->sn = $attrs['sn'][0];
88  }
89  if (isset($attrs['givenName'][0])) {
90  $this->givenName = $attrs['givenName'][0];
91  }
92 
93  /* Assign user language */
94  if (isset($attrs['preferredLanguage'][0])) {
95  $this->language = $attrs['preferredLanguage'][0];
96  }
97  }
98 
102  public function reset_acl_cache()
103  {
104  /* Initialize ACL_CACHE */
105  session::global_set('ACL_CACHE', array());
106  }
107 
111  function loadACL()
112  {
113  global $config;
114  $this->ACL = array();
115  $this->groups = array();
116  $this->roles = array();
117  $this->result_cache = array();
118  $this->reset_acl_cache();
119  $ldap = $config->get_ldap_link();
120  $ldap->cd($config->current['BASE']);
121 
122  /* Get member groups... */
123  $ldap->search('(&(objectClass=groupOfNames)(member='.ldap_escape_f($this->dn).'))', array('dn'));
124  while ($attrs = $ldap->fetch()) {
125  $this->groups[$attrs['dn']] = $attrs['dn'];
126  }
127 
128  /* Get member POSIX groups... */
129  $ldap->search('(&(objectClass=posixGroup)(memberUid='.ldap_escape_f($this->uid).'))', array('dn'));
130  while ($attrs = $ldap->fetch()) {
131  $this->groups[$attrs['dn']] = $attrs['dn'];
132  }
133 
134  /* Get member roles... */
135  $ldap->search('(&(objectClass=organizationalRole)(roleOccupant='.ldap_escape_f($this->dn).'))', array('dn'));
136  while ($attrs = $ldap->fetch()) {
137  $this->roles[$attrs['dn']] = $attrs['dn'];
138  }
139 
140  /* Crawl through ACLs and move relevant to the tree */
141  $ldap->search("(objectClass=gosaACL)", array('dn', 'gosaAclEntry'));
142  $aclp = array();
143  $aclc = array();
144  while ($attrs = $ldap->fetch()) {
145 
146  /* Insert links in ACL array */
147  $aclp[$attrs['dn']] = substr_count($attrs['dn'], ',');
148  $aclc[$attrs['dn']] = array();
149  $ol = array();
150  for ($i = 0; $i < $attrs['gosaAclEntry']['count']; $i++) {
151  $ol = array_merge($ol, acl::explodeAcl($attrs['gosaAclEntry'][$i]));
152  }
153  $aclc[$attrs['dn']] = $ol;
154  }
155 
156  /* Resolve roles here */
157  foreach ($aclc as $dn => $data) {
158  foreach ($data as $prio => $aclc_value) {
159  unset($aclc[$dn][$prio]);
160 
161  $ldap->cat($aclc_value['acl'], array("gosaAclTemplate"));
162  $attrs = $ldap->fetch();
163 
164  if (isset($attrs['gosaAclTemplate'])) {
165  $roleAcls = acl::explodeRole($attrs['gosaAclTemplate']);
166  foreach ($roleAcls as $roleAcl) {
167  $aclc[$dn][] = array(
168  'acl' => $roleAcl,
169  'type' => $aclc_value['type'],
170  'members' => $aclc_value['members'],
171  'filter' => $aclc_value['filter']
172  );
173  }
174  }
175  }
176  }
177 
178  /* ACL's read, sort for tree depth */
179  asort($aclp);
180 
181  /* Sort in tree order */
182  foreach ($aclp as $dn => $acl) {
183  /* Check if we need to keep this ACL */
184  foreach ($aclc[$dn] as $idx => $type) {
185  $interresting = FALSE;
186 
187  /* No members? This ACL rule is deactivated ... */
188  if (!count($type['members'])) {
189  $interresting = FALSE;
190  } else {
191  /* Inspect members... */
192  foreach (array_keys($type['members']) as $grp) {
193  /* Some group inside the members that is relevant for us? */
194  if (in_array_ics(preg_replace('/^G:/', '', $grp), $this->groups)) {
195  $interresting = TRUE;
196  }
197 
198  /* Some role inside the members that is relevant for us? */
199  if (in_array_ics(preg_replace('/^R:/', '', $grp), $this->roles)) {
200  $interresting = TRUE;
201  }
202 
203  /* User inside the members? */
204  if (mb_strtoupper(preg_replace('/^U:/', '', $grp)) == mb_strtoupper($this->dn)) {
205  $interresting = TRUE;
206  }
207 
208  /* Wildcard? */
209  if (preg_match('/^G:\*/', $grp)) {
210  $interresting = TRUE;
211  }
212  }
213  }
214 
215  if ($interresting) {
216  if (!isset($this->ACL[$dn])) {
217  $this->ACL[$dn] = array();
218  }
219  $this->ACL[$dn][$idx] = $type;
220  }
221  }
222  }
223 
224  /* Create an array which represent all relevant permissions settings
225  per dn.
226 
227  The array will look like this:
228 
229  . ['ou=base'] ['ou=base'] = array(ACLs);
230  .
231  . ['ou=dep1,ou=base']['ou=dep1,ou=base'] = array(ACLs);
232  . ['ou=base'] = array(ACLs);
233 
234 
235  For object located in 'ou=dep1,ou=base' we have to both ACLs,
236  for objects in 'ou=base' we only have to apply on ACL.
237  */
238  $without_self_acl = $all_acl = array();
239  foreach ($this->ACL as $dn => $acl) {
240  $sdn = $dn;
241  do {
242  if (isset($this->ACL[$dn])) {
243  $all_acl[$sdn][$dn] = $this->ACL[$dn];
244  $without_self_acl[$sdn][$dn] = $this->ACL[$dn];
245  foreach ($without_self_acl[$sdn][$dn] as $acl_id => $acl_set) {
246 
247  /* Remember which ACL set has speicial user filter */
248  if (isset($acl_set['filter']{1})) {
249  $this->ACLperPath_usesFilter[$sdn] = TRUE;
250  }
251 
252  /* Remove all acl entries which are especially for the current user (self acl) */
253  foreach ($acl_set['acl'] as $object => $object_acls) {
254  if (isset($object_acls[0]) && (strpos($object_acls[0], "s") !== FALSE)) {
255  unset($without_self_acl[$sdn][$dn][$acl_id]['acl'][$object]);
256  }
257  }
258  }
259  }
260  $dn = preg_replace("/^[^,]*+,/", "", $dn);
261  } while (strpos($dn, ',') !== FALSE);
262  }
263  $this->ACLperPath = $without_self_acl;
264 
265  /* Append Self entry */
266  $dn = $this->dn;
267  while (strpos($dn, ",") && !isset($all_acl[$dn])) {
268  $dn = preg_replace("/^[^,]*+,/", "", $dn);
269  }
270  if (isset($all_acl[$dn])) {
271  $this->ACLperPath[$this->dn] = $all_acl[$dn];
272  }
273  }
274 
281  {
282  return array_keys($this->ACLperPath);
283  }
284 
294  function get_category_permissions($dn, $category)
295  {
296  return @$this->get_permissions($dn, $category.'/0', '');
297  }
298 
299 
309  function is_copyable($dn, $object)
310  {
311  return (strpos($this->get_complete_category_acls($dn, $object), 'r') !== FALSE);
312  }
313 
314 
326  function is_cutable($dn, $object, $class)
327  {
328  $remove = (strpos($this->get_permissions($dn, $object.'/'.$class), 'd') !== FALSE);
329  $read = (strpos($this->get_complete_category_acls($dn, $object), 'r') !== FALSE);
330  return ($remove && $read);
331  }
332 
333 
343  function is_pasteable($dn, $object)
344  {
345  return (strpos($this->get_complete_category_acls($dn, $object), 'w') !== FALSE);
346  }
347 
348 
358  function allow_snapshot_restore($dn, $object)
359  {
360  if (!is_array($object)) {
361  $object = array($object);
362  }
363  $r = $w = TRUE;
364  foreach ($object as $category) {
365  $w &= (strpos($this->get_complete_category_acls($dn, $category), 'w') !== FALSE);
366  $r &= (strpos($this->get_complete_category_acls($dn, $category), 'r') !== FALSE);
367  }
368  return ($r && $w);
369  }
370 
371 
381  function allow_snapshot_create($dn, $object)
382  {
383  if (!is_array($object)) {
384  $object = array($object);
385  }
386  foreach ($object as $category) {
387  if (strpos($this->get_complete_category_acls($dn, $category), 'r') === FALSE) {
388  return FALSE;
389  }
390  }
391  return TRUE;
392  }
393 
406  function get_permissions($dn, $object, $attribute = "", $skip_write = FALSE)
407  {
408  global $config;
409  /* If we are forced to skip ACLs checks for the current user
410  then return all permissions.
411  */
412  if ($this->ignore_acl_for_current_user()) {
413  if ($skip_write) {
414  return 'r';
415  }
416  return 'rwcdm';
417  }
418 
419  /* Push cache answer? */
420  $ACL_CACHE = &session::global_get_ref('ACL_CACHE');
421  if (isset($ACL_CACHE["$dn+$object+$attribute"])) {
422  $ret = $ACL_CACHE["$dn+$object+$attribute"];
423  if ($skip_write) {
424  $ret = str_replace(array('w','c','d','m'), '', $ret);
425  }
426  return $ret;
427  }
428 
429  /* Detect the set of ACLs we have to check for this object
430  */
431  $adn = $dn;
432  while (!isset($this->ACLperPath[$adn]) && (strpos($adn, ',') !== FALSE)) {
433  $adn = preg_replace("/^[^,]*+,/", "", $adn);
434  }
435  if (isset($this->ACLperPath[$adn])) {
436  $ACL = $this->ACLperPath[$adn];
437  } else {
438  $ACL_CACHE["$dn+$object+$attribute"] = '';
439  return '';
440  }
441 
442  /* If we do not need to respect any user-filter settings
443  we can skip the per object ACL checks.
444  */
445  $orig_dn = $dn;
446  if (!isset($this->ACLperPath_usesFilter[$adn])) {
447  $dn = $adn;
448  if (isset($ACL_CACHE["$dn+$object+$attribute"])) {
449  $ret = $ACL_CACHE["$dn+$object+$attribute"];
450  if (!isset($ACL_CACHE["$orig_dn+$object+$attribute"])) {
451  $ACL_CACHE["$orig_dn+$object+$attribute"] = $ret;
452  }
453  if ($skip_write) {
454  $ret = str_replace(array('w','c','d','m'), '', $ret);
455  }
456  return $ret;
457  }
458  }
459 
460  /* Get ldap object, for later filter checks */
461  $ldap = $config->get_ldap_link();
462 
463  $acl = array('r' => '', 'w' => '', 'c' => '', 'd' => '', 'm' => '', 'a' => '');
464 
465  /* Build dn array */
466  $path = explode(',', $dn);
467  $path = array_reverse($path);
468 
469  /* Walk along the path to evaluate the acl */
470  $cpath = '';
471  foreach ($path as $element) {
472 
473  /* Clean potential ACLs for each level */
474  if (isset($config->idepartments[$cpath])) {
475  $acl = $this->cleanACL($acl);
476  }
477 
478  if ($cpath == "") {
479  $cpath = $element;
480  } else {
481  $cpath = $element.','.$cpath;
482  }
483 
484  if (isset($ACL[$cpath])) {
485 
486  /* Inspect this ACL, place the result into ACL */
487  foreach ($ACL[$cpath] as $subacl) {
488 
489  /* Reset? Just clean the ACL and turn over to the next one... */
490  if ($subacl['type'] == 'reset') {
491  $acl = $this->cleanACL($acl, TRUE);
492  continue;
493  }
494 
495  /* With user filter */
496  if (isset($subacl['filter']) && !empty($subacl['filter'])) {
497  $id = $dn."-".$subacl['filter'];
498  if (!isset($ACL_CACHE['FILTER'][$id])) {
499  $ACL_CACHE['FILTER'][$id] = $ldap->object_match_filter($dn, $subacl['filter']);
500  }
501  if (!$ACL_CACHE['FILTER'][$id]) {
502  continue;
503  }
504  }
505 
506  /* Self ACLs? */
507  if (($dn != $this->dn) && isset($subacl['acl'][$object][0]) && (strpos($subacl['acl'][$object][0], "s") !== FALSE)) {
508  continue;
509  }
510 
511  /* If attribute is "", we want to know, if we've *any* permissions here...
512  Merge global class ACLs [0] with attributes specific ACLs [attribute].
513  */
514  if (($attribute == '') && isset($subacl['acl'][$object])) {
515  foreach ($subacl['acl'][$object] as $attr => $dummy) {
516  $acl = $this->mergeACL($acl, $subacl['type'], $subacl['acl'][$object][$attr]);
517  }
518  continue;
519  }
520 
521  /* Per attribute ACL? */
522  if (isset($subacl['acl'][$object][$attribute])) {
523  $acl = $this->mergeACL($acl, $subacl['type'], $subacl['acl'][$object][$attribute]);
524  continue;
525  }
526 
527  /* Per object ACL? */
528  if (isset($subacl['acl'][$object][0])) {
529  $acl = $this->mergeACL($acl, $subacl['type'], $subacl['acl'][$object][0]);
530  continue;
531  }
532 
533  /* Global ACL? */
534  if (isset($subacl['acl']['all'][0])) {
535  $acl = $this->mergeACL($acl, $subacl['type'], $subacl['acl']['all'][0]);
536  continue;
537  }
538 
539  /* Category ACLs (e.g. $object = "user/0")
540  */
541  if (strstr($object, '/0')) {
542  $ocs = preg_replace("/\/0$/", "", $object);
543  if (isset($config->data['CATEGORIES'][$ocs])) {
544 
545  /* if $attribute is "", then check every single attribute for this object.
546  if it is 0, then just check the object category ACL.
547  */
548  if ($attribute == "") {
549  foreach ($config->data['CATEGORIES'][$ocs]['classes'] as $oc) {
550  if (isset($subacl['acl'][$ocs.'/'.$oc])) {
551  // Skip ACLs wich are defined for ourselfs only - if not checking against ($ui->dn)
552  if (isset($subacl['acl'][$ocs.'/'.$oc][0]) &&
553  ($dn != $this->dn) &&
554  (strpos($subacl['acl'][$ocs.'/'.$oc][0], "s") !== FALSE)) {
555  continue;
556  }
557 
558  foreach ($subacl['acl'][$ocs.'/'.$oc] as $attr => $dummy) {
559  $acl = $this->mergeACL($acl, $subacl['type'], $subacl['acl'][$ocs.'/'.$oc][$attr]);
560  }
561  continue;
562  }
563  }
564  } else {
565  if (isset($subacl['acl'][$ocs.'/'.$oc][0])) {
566  if (($dn != $this->dn) && (strpos($subacl['acl'][$ocs.'/'.$oc][0], "s") !== FALSE)) {
567  continue;
568  }
569  $acl = $this->mergeACL($acl, $subacl['type'], $subacl['acl'][$ocs.'/'.$oc][0]);
570  }
571  }
572  }
573  continue;
574  }
575  }
576  }
577  }
578 
579  /* If the requested ACL is for a container object, then alter
580  ACLs by applying cleanACL a last time.
581  */
582  if (isset($config->idepartments[$dn])) {
583  $acl = $this->cleanACL($acl);
584  }
585 
586  /* Assemble string */
587  $ret = "";
588  foreach ($acl as $key => $value) {
589  if ($value !== "") {
590  $ret .= $key;
591  }
592  }
593 
594  $ACL_CACHE["$dn+$object+$attribute"] = $ret;
595  $ACL_CACHE["$orig_dn+$object+$attribute"] = $ret;
596 
597  /* Remove write if needed */
598  if ($skip_write) {
599  $ret = str_replace(array('w','c','d','m'), '', $ret);
600  }
601  return $ret;
602  }
603 
616  function get_module_departments($module, $skip_self_acls = FALSE )
617  {
618  global $config;
619  /* If we are forced to skip ACLs checks for the current user
620  then return all departments as valid.
621  */
622  if ($this->ignore_acl_for_current_user()) {
623  return array_keys($config->idepartments);
624  }
625 
626  /* Use cached results if possilbe */
627  $ACL_CACHE = &session::global_get_ref('ACL_CACHE');
628 
629  if (!is_array($module)) {
630  $module = array($module);
631  }
632 
633  $res = array();
634  foreach ($module as $mod) {
635  if (isset($ACL_CACHE['MODULE_DEPARTMENTS'][$mod])) {
636  $res = array_merge($res, $ACL_CACHE['MODULE_DEPARTMENTS'][$mod]);
637  continue;
638  }
639 
640  $deps = array();
641 
642  /* Search for per object ACLs */
643  foreach ($this->ACL as $dn => $infos) {
644  foreach ($infos as $info) {
645  $found = FALSE;
646  foreach ($info['acl'] as $cat => $data) {
647  /* Skip self acls? */
648  if ($skip_self_acls && isset($data['0']) && (strpos($data['0'], "s") !== FALSE)) {
649  continue;
650  }
651  if (preg_match("/^".preg_quote($mod, '/')."/", $cat)) {
652  $found = TRUE;
653  break;
654  }
655  }
656 
657  if ($found && !isset($config->idepartments[$dn])) {
658  while (!isset($config->idepartments[$dn]) && strpos($dn, ",")) {
659  $dn = preg_replace("/^[^,]+,/", "", $dn);
660  }
661  if (isset($config->idepartments[$dn])) {
662  $deps[$dn] = $dn;
663  }
664  }
665  }
666  }
667 
668  /* For all gosaDepartments */
669  foreach ($config->departments as $dn) {
670  if (isset($deps[$dn])) {
671  continue;
672  }
673  $acl = '';
674  if (strpos($mod, '/')) {
675  $acl .= $this->get_permissions($dn, $mod);
676  } else {
677  $acl .= $this->get_category_permissions($dn, $mod);
678  }
679  if (!empty($acl)) {
680  $deps[$dn] = $dn;
681  }
682  }
683 
684  $ACL_CACHE['MODULE_DEPARTMENTS'][$mod] = $deps;
685  $res = array_merge($res, $deps);
686  }
687 
688  return array_values($res);
689  }
690 
700  function mergeACL($acl, $type, $newACL)
701  {
702  $at = array("subtree" => "s", "one" => "1");
703 
704  if ((strpos($newACL, 'w') !== FALSE) && (strpos($newACL, 'r') === FALSE)) {
705  $newACL .= "r";
706  }
707 
708  /* Ignore invalid characters */
709  $newACL = preg_replace('/[^rwcdm]/', '', $newACL);
710 
711  foreach (str_split($newACL) as $char) {
712  /* Skip "self" ACLs without combination of rwcdm, they have no effect.
713  -self flag without read/write/create/...
714  */
715  if (empty($char)) {
716  continue;
717  }
718 
719  /* Skip subtree entries */
720  if ($acl[$char] == 's') {
721  continue;
722  }
723 
724  if ($type == "base" && $acl[$char] != 1) {
725  $acl[$char] = 0;
726  } else {
727  $acl[$char] = $at[$type];
728  }
729  }
730 
731  return $acl;
732  }
733 
741  function cleanACL($acl, $reset = FALSE)
742  {
743  foreach ($acl as $key => $value) {
744  /* Continue, if value is empty or subtree */
745  if (($value == "") || ($value == "s")) {
746  continue;
747  }
748 
749  /* Reset removes everything but 'p' */
750  if ($reset && $value != 'p') {
751  $acl[$key] = "";
752  continue;
753  }
754 
755  /* Decrease tree level */
756  if (is_int($value)) {
757  if ($value) {
758  $acl[$key]--;
759  } else {
760  $acl[$key] = "";
761  }
762  }
763  }
764 
765  return $acl;
766  }
767 
784  function get_complete_category_acls($dn, $category)
785  {
786  global $config;
787 
788  if (!is_string($category)) {
789  trigger_error('category must be string');
790  return '';
791  } else {
792  if (isset($this->result_cache['get_complete_category_acls'][$dn][$category])) {
793  return $this->result_cache['get_complete_category_acls'][$dn][$category];
794  }
795  $acl = 'rwcdm';
796  if (isset($config->data['CATEGORIES'][$category])) {
797  foreach ($config->data['CATEGORIES'][$category]['classes'] as $oc) {
798  if ($oc == '0') {
799  /* Skip objectClass '0' (e.g. user/0) */
800  continue;
801  }
802  $tmp = $this->get_permissions($dn, $category.'/'.$oc);
803  $types = $acl;
804  for ($i = 0, $l = strlen($types); $i < $l; $i++) {
805  if (strpos($tmp, $types[$i]) === FALSE) {
806  $acl = str_replace($types[$i], '', $acl);
807  }
808  }
809  }
810  } else {
811  $acl = '';
812  }
813  $this->result_cache['get_complete_category_acls'][$dn][$category] = $acl;
814  return $acl;
815  }
816  }
817 
818 
826  {
827  return $this->ignoreACL;
828  }
829 
853  function expired_status ()
854  {
855  global $config;
856  // Skip this for the admin account, we do not want to lock him out.
857  if ($this->is_user_admin()) {
858  return 0;
859  }
860 
861  $ldap = $config->get_ldap_link();
862  $ldap->cd($config->current['BASE']);
863  $ldap->cat($this->dn);
864  $attrs = $ldap->fetch();
865  $current = floor(date("U") / 60 / 60 / 24);
866 
867  // Fetch required attributes
868  foreach (array('shadowExpire','shadowLastChange','shadowMax','shadowMin',
869  'shadowInactive','shadowWarning','sambaKickoffTime') as $attr) {
870  $$attr = (isset($attrs[$attr][0]) ? $attrs[$attr][0] : NULL);
871  }
872 
873  // Check if the account has reached its kick off limitations.
874  // ----------------------------------------------------------
875  // Once the accout reaches the kick off limit it has expired.
876  if ($sambaKickoffTime !== NULL) {
877  if (time() >= $sambaKickoffTime) {
878  return POSIX_ACCOUNT_EXPIRED;
879  }
880  }
881 
882  // Check if the account has expired.
883  // ---------------------------------
884  // An account is locked/expired once its expiration date has reached (shadowExpire).
885  // If the optional attribute (shadowInactive) is set, we've to postpone
886  // the account expiration by the amount of days specified in (shadowInactive).
887  if (($shadowExpire != NULL) && ($shadowExpire <= $current)) {
888 
889  // The account seems to be expired, but we've to check 'shadowInactive' additionally.
890  // ShadowInactive specifies an amount of days we've to reprieve the user.
891  // It some kind of x days' grace.
892  if (($shadowInactive == NULL) || $current > $shadowExpire + $shadowInactive) {
893 
894  // Finally we've detect that the account is deactivated.
895  return POSIX_ACCOUNT_EXPIRED;
896  }
897  }
898 
899  // The users password is going to expire.
900  // --------------------------------------
901  // We've to warn the user in the case of an expiring account.
902  // An account is going to expire when it reaches its expiration date (shadowExpire).
903  // The user has to be warned, if the days left till expiration, match the
904  // configured warning period (shadowWarning)
905  // --> shadowWarning: Warn x days before account expiration.
906  if (($shadowExpire != NULL) && ($shadowWarning != NULL)) {
907 
908  // Check if the account is still active and not already expired.
909  if ($shadowExpire >= $current) {
910 
911  // Check if we've to warn the user by comparing the remaining
912  // number of days till expiration with the configured amount
913  // of days in shadowWarning.
914  if (($shadowExpire - $current) <= $shadowWarning) {
915  return POSIX_WARN_ABOUT_EXPIRATION;
916  }
917  }
918  }
919 
920  // -- I guess this is the correct detection, isn't it?
921  if (($shadowLastChange != NULL) && ($shadowWarning != NULL) && ($shadowMax != NULL)) {
922  $daysRemaining = ($shadowLastChange + $shadowMax) - $current;
923  if ($daysRemaining > 0 && $daysRemaining <= $shadowWarning) {
924  return POSIX_WARN_ABOUT_EXPIRATION;
925  }
926  }
927 
928  // Check if we've to force the user to change his password.
929  // --------------------------------------------------------
930  // A password change is enforced when the password is older than
931  // the configured amount of days (shadowMax).
932  // The age of the current password (shadowLastChange) plus the maximum
933  // amount amount of days (shadowMax) has to be smaller than the
934  // current timestamp.
935  if (($shadowLastChange != NULL) && ($shadowMax != NULL)) {
936  // Check if we've an outdated password.
937  if ($current >= ($shadowLastChange + $shadowMax)) {
938  return POSIX_FORCE_PASSWORD_CHANGE;
939  }
940  }
941 
942  // Check if we've to freeze the users password.
943  // --------------------------------------------
944  // Once a user has changed his password, he cannot change it again
945  // for a given amount of days (shadowMin).
946  // We should not allow to change the password within FusionDirectory too.
947  if (($shadowLastChange != NULL) && ($shadowMin != NULL)) {
948  // Check if we've an outdated password.
949  if (($shadowLastChange + $shadowMin) >= $current) {
950  return POSIX_DISALLOW_PASSWORD_CHANGE;
951  }
952  }
953 
954  return 0;
955  }
956 
957  /* \brief Check if a user is a 'user admin'
958  */
959  function is_user_admin()
960  {
961  global $config;
962  if (empty($this->ACLperPath)) {
963  $this->loadACL();
964  }
965  return ($this->get_permissions($config->current['BASE'], 'user/user') == 'rwcdm');
966  }
967 
968  /* \brief Test if a plugin is blacklisted for this user (does not show up in the menu)
969  */
970  function isBlacklisted($plugin)
971  {
972  global $config;
973  $blacklist = $config->get_cfg_value('PluginsMenuBlacklist', array());
974  foreach ($blacklist as $item) {
975  list ($group, $p) = explode('|', $item, 2);
976  if ($plugin == $p) {
977  if (in_array($group, $this->groups) || in_array($group, $this->roles)) {
978  return TRUE;
979  }
980  }
981  }
982 
983  return FALSE;
984  }
985 
986  /* \brief Search which ACL category should be used for this attribute and this object type, if any
987  *
988  * \return The ACL catogory or FALSE if not found
989  */
990  function getAttributeCategory($type, $attribute)
991  {
992  global $config;
993  $infos = objects::infos($type);
994  $classes = $config->data['CATEGORIES'][$infos['aclCategory']]['classes'];
995  foreach ($classes as $class) {
996  if ($class == '0') {
997  continue;
998  }
999  $acls = pluglist::pluginInfos($class)['plProvidedAcls'];
1000  if (isset($acls[$attribute])) {
1001  return $infos['aclCategory'].'/'.$class;
1002  }
1003  }
1004  return FALSE;
1005  }
1006 }
1007 ?>
in_array_ics($value, array $items)
Check if a value exists in an array (case-insensitive)
Definition: functions.inc:1677
get_category_permissions($dn, $category)
Get permissions by category.
get_complete_category_acls($dn, $category)
Return combined acls for a given category.
reset_acl_cache()
Reset acl cache.
ignore_acl_for_current_user()
Ignore acl for the current user.
mergeACL($acl, $type, $newACL)
Merge acls.
is_copyable($dn, $object)
Check if the given object (dn) is copyable.
loadLDAPInfo()
Loads user information from LDAP.
expired_status()
Checks the posixAccount status by comparing the shadow attributes.
static global_set($name, $value)
Set a value in a session.
loadACL()
Load an acl.
is_cutable($dn, $object, $class)
Check if the given object (dn) is cutable.
allow_snapshot_restore($dn, $object)
Checks if we are allowed to restore a snapshot for the given dn.
Class userinfo This class contains all informations and functions about user.
static explodeRole($role)
Explode a role.
Definition: class_acl.inc:78
get_module_departments($module, $skip_self_acls=FALSE)
Extract all departments that are accessible.
get_acl_target_objects()
Returns an array containing all target objects we've permissions on.
get_permissions($dn, $object, $attribute="", $skip_write=FALSE)
Get the permissions for a specified dn.
static & global_get_ref($name)
Accessor of a session var by reference.
allow_snapshot_create($dn, $object)
Checks if we are allowed to create a snapshot of the given dn.
cleanACL($acl, $reset=FALSE)
Clean acls.
is_pasteable($dn, $object)
Checks if we are allowed to paste an object to the given destination ($dn)