1 <?php
2 /*
3 * This code is part of GOsa (http://www.gosa-project.org)
4 * Copyright (C) 2003-2008 GONICUS GmbH
5 *
6 * ID: $$Id$$
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
23 /*!
24 \brief posixAccount plugin
25 \author Cajus Pollmeier <pollmeier@gonicus.de>
26 \version 2.00
27 \date 24.07.2003
29 This class provides the functionality to read and write all attributes
30 relevant for posixAccounts and shadowAccounts from/to the LDAP. It
31 does syntax checking and displays the formulars required.
32 */
34 class posixAccount extends plugin
35 {
36 /* Definitions */
37 var $plHeadline= "UNIX";
38 var $plDescription= "Edit users POSIX settings";
40 /* Plugin specific values */
41 var $homeDirectory= "";
42 var $loginShell= "/bin/bash";
43 var $uidNumber= "";
44 var $gidNumber= "";
45 var $gecos= "";
46 var $shadowMin= "0";
47 var $shadowMax= "0";
48 var $shadowWarning= "0";
49 var $shadowLastChange= "0";
50 var $shadowInactive= "0";
51 var $shadowExpire= "0";
52 var $gosaDefaultPrinter= "";
53 var $accessTo= array();
54 var $trustModel= "";
56 var $glist=array();
57 var $status= "";
58 var $loginShellList= array();
59 var $groupMembership= array();
60 var $savedGroupMembership= array();
61 var $savedUidNumber= "";
62 var $savedGidNumber= "";
63 var $activate_shadowMin= "0";
64 var $activate_shadowMax= "0";
65 var $activate_shadowWarning= "0";
66 var $activate_shadowInactive= "0";
67 var $activate_shadowExpire= "0";
68 var $mustchangepassword= "0";
69 var $force_ids= 0;
70 var $group_dialog= FALSE;
71 var $show_ws_dialog= FALSE;
72 var $secondaryGroups= array();
73 var $primaryGroup= 0;
74 var $was_trust_account= FALSE;
75 var $memberGroup= array();
76 var $grouplist= array();
77 var $ui= array();
78 var $ssh= null;
80 var $GroupRegex= "*";
81 var $GroupUserRegex= "*";
82 var $SubSearch= false;
84 var $view_logged= false;
86 /* attribute list for save action */
87 var $CopyPasteVars =
88 array("grouplist","groupMembership","activate_shadowMin",
89 "activate_shadowMax","activate_shadowWarning","activate_shadowInactive","activate_shadowExpire",
90 "must_change_password","printerList","grouplist","savedGidNumber","savedUidNumber");
92 var $attributes = array("homeDirectory", "loginShell", "uidNumber", "gidNumber", "gecos",
93 "shadowMin", "shadowMax", "shadowWarning", "shadowInactive", "shadowLastChange",
94 "shadowExpire", "gosaDefaultPrinter", "uid","accessTo","trustModel");
96 var $objectclasses= array("posixAccount", "shadowAccount");
98 var $uid= "";
99 var $multiple_support = TRUE;
100 var $groupMembership_some = array();
102 /* constructor, if 'dn' is set, the node loads the given
103 'dn' from LDAP */
104 function posixAccount (&$config, $dn= NULL)
105 {
106 global $class_mapping;
108 /* Configuration is fine, allways */
109 $this->config= $config;
111 /* Load bases attributes */
112 plugin::plugin($config, $dn);
114 /* Setting uid to default */
115 if(isset($this->attrs['uid'][0])){
116 $this->uid = $this->attrs['uid'][0];
117 }
119 $ldap= $this->config->get_ldap_link();
121 if ($dn !== NULL){
123 /* Correct is_account. shadowAccount is not required. */
124 if (isset($this->attrs['objectClass']) &&
125 in_array ('posixAccount', $this->attrs['objectClass'])){
127 $this->is_account= TRUE;
128 }
130 /* Is this account a trustAccount? */
131 if ($this->is_account && isset($this->attrs['trustModel'])){
132 $this->trustModel= $this->attrs['trustModel'][0];
133 $this->was_trust_account= TRUE;
134 } else {
135 $this->was_trust_account= FALSE;
136 $this->trustModel= "";
137 }
139 $this->accessTo = array();
140 if ($this->is_account && isset($this->attrs['accessTo'])){
141 for ($i= 0; $i<$this->attrs['accessTo']['count']; $i++){
142 $tmp= $this->attrs['accessTo'][$i];
143 $this->accessTo[$tmp]= $tmp;
144 }
145 }
146 $this->initially_was_account= $this->is_account;
148 /* Fill group */
149 $this->primaryGroup= $this->gidNumber;
151 /* Generate status text */
152 $current= date("U");
154 $current= floor($current / 60 /60 / 24);
156 if (($current >= $this->shadowExpire) && $this->shadowExpire){
157 $this->status= _("expired");
158 if (($current - $this->shadowExpire) < $this->shadowInactive){
159 $this->status.= ", "._("grace time active");
160 }
161 } elseif (($this->shadowLastChange + $this->shadowMin) >= $current){
162 $this->status= _("active").", "._("password not changeable");
163 } elseif (($this->shadowLastChange + $this->shadowMax) >= $current){
164 $this->status= _("active").", "._("password expired");
165 } else {
166 $this->status= _("active");
167 }
169 /* Get group membership */
170 $ldap->cd($this->config->current['BASE']);
171 $ldap->search("(&(objectClass=posixGroup)(memberUid=".$this->uid."))", array("cn", "description"));
173 while ($attrs= $ldap->fetch()){
174 if (!isset($attrs["description"][0])){
175 $entry= $attrs["cn"][0];
176 } else {
177 $entry= $attrs["cn"][0]." [".$attrs["description"][0]."]";
178 }
179 $this->groupMembership[$ldap->getDN()]= $entry;
180 }
181 asort($this->groupMembership);
182 reset($this->groupMembership);
183 $this->savedGroupMembership= $this->groupMembership;
184 $this->savedUidNumber= $this->uidNumber;
185 $this->savedGidNumber= $this->gidNumber;
187 // Instanciate SSH object if available
188 if (isset($class_mapping["sshPublicKey"])){
189 $this->ssh= new sshPublicKey($this->config, $this->dn);
190 }
191 }
193 /* Adjust shadow checkboxes */
194 foreach (array("shadowMin", "shadowMax", "shadowWarning", "shadowInactive",
195 "shadowExpire") as $val){
197 if ($this->$val != 0){
198 $oval= "activate_".$val;
199 $this->$oval= "1";
200 }
201 }
203 /* Convert to seconds */
204 $this->shadowExpire= $this->convertToSeconds($this->shadowExpire);
206 /* Generate shell list from CONFIG_DIR./shells */
207 if (file_exists(CONFIG_DIR.'/shells')){
208 $shells = file (CONFIG_DIR.'/shells');
209 foreach ($shells as $line){
210 if (!preg_match ("/^#/", $line)){
211 $this->loginShellList[]= trim($line);
212 }
213 }
214 } else {
215 if ($this->loginShell == ""){
216 $this->loginShellList[]= _("unconfigured");
217 }
218 }
220 /* Insert possibly missing loginShell */
221 if ($this->loginShell != "" && !in_array($this->loginShell, $this->loginShellList)){
222 $this->loginShellList[]= $this->loginShell;
223 }
225 /* Generate group list */
226 $this->ui = get_userinfo();
227 $this->secondaryGroups[]= "- "._("automatic")." -";
228 $ldap->cd($this->config->current['BASE']);
229 $ldap->search("(objectClass=posixGroup)", array("cn", "gidNumber"));
230 while($attrs = $ldap->fetch()){
231 $this->secondaryGroups[$attrs['gidNumber'][0]]= $attrs['cn'][0];
232 }
233 asort ($this->secondaryGroups);
235 /* Get global filter config */
236 if (!session::is_set("sysfilter")){
237 $ui= get_userinfo();
238 $base= get_base_from_people($ui->dn);
239 $sysfilter= array( "depselect" => $base,
240 "regex" => "*");
241 session::set("sysfilter", $sysfilter);
242 }
243 $this->ui = get_userinfo();
244 }
247 /* execute generates the html output for this node */
248 function execute($isCopyPaste = false)
249 {
250 /* Call parent execute */
251 plugin::execute();
252 $display= "";
254 /* Log view */
255 if($this->is_account && !$this->view_logged){
256 $this->view_logged = TRUE;
257 new log("view","users/".get_class($this),$this->dn);
258 }
260 /* Department has changed? */
261 if(isset($_POST['depselect'])){
262 session::set('CurrentMainBase',validate($_POST['depselect']));
263 }
265 if($this->multiple_support_active){
266 $this->is_account = TRUE;
267 }
269 if(!$isCopyPaste && ! $this->multiple_support_active){
271 /* Do we need to flip is_account state? */
272 if(isset($_POST['modify_state'])){
273 if($this->is_account && $this->acl_is_removeable()){
274 $this->is_account= FALSE;
275 }elseif(!$this->is_account && $this->acl_is_createable()){
276 $this->is_account= TRUE;
277 }
278 }
280 /* Do we represent a valid posixAccount? */
281 if (!$this->is_account && $this->parent === NULL ){
282 $display= "<img alt=\"\" src=\"images/small-error.png\" align=\"middle\"> <b>".
283 msgPool::noValidExtension(_("POSIX"))."</b>";
284 $display.= back_to_main();
285 return ($display);
286 }
289 /* Show tab dialog headers */
290 if ($this->parent !== NULL){
291 if ($this->is_account){
292 if (isset($this->parent->by_object['sambaAccount'])){
293 $obj= $this->parent->by_object['sambaAccount'];
294 }
295 if (isset($obj) && $obj->is_account == TRUE &&
296 ((isset($this->parent->by_object['sambaAccount']))&&($this->parent->by_object['sambaAccount']->is_account))
297 ||(isset($this->parent->by_object['environment'] ))&&($this->parent->by_object['environment'] ->is_account)){
299 /* Samba3 dependency on posix accounts are enabled
300 in the moment, because I need to rely on unique
301 uidNumbers. There'll be a better solution later
302 on. */
303 $display= $this->show_disable_header(msgPool::removeFeaturesButton(_("POSIX")), msgPool::featuresEnabled(_("POSIX"), array(_("Samba"), _("Environment"))), TRUE);
304 } else {
305 $display= $this->show_disable_header(msgPool::removeFeaturesButton(_("POSIX")), msgPool::featuresEnabled(_("POSIX")));
306 }
307 } else {
308 $display= $this->show_enable_header(msgPool::addFeaturesButton(_("POSIX")), msgPool::featuresDisabled(_("POSIX")));
309 return($display);
310 }
311 }
312 }
314 /* Trigger group edit? */
315 if (isset($_POST['edit_groupmembership'])){
316 $this->group_dialog= TRUE;
317 $this->dialog= TRUE;
318 }
320 /* Cancel group edit? */
321 if (isset($_POST['add_groups_cancel']) ||
322 isset($_POST['add_groups_finish'])){
323 $this->group_dialog= FALSE;
324 $this->dialog= FALSE;
325 }
327 /* Add selected groups */
328 if (isset($_POST['add_groups_finish']) && isset($_POST['groups']) &&
329 count($_POST['groups'])){
331 $this->addGroup ($_POST['groups']);
332 }
334 /* Delete selected groups */
335 if (isset($_POST['delete_groupmembership']) &&
336 isset($_POST['group_list']) && count($_POST['group_list'])){
338 $this->delGroup ($_POST['group_list']);
339 }
341 /* Add user workstation? */
342 if (isset($_POST["add_ws"])){
343 $this->show_ws_dialog= TRUE;
344 $this->dialog= TRUE;
345 }
347 /* Add user workstation? */
348 if (isset($_POST["add_ws_finish"]) && isset($_POST['wslist'])){
349 foreach($_POST['wslist'] as $ws){
350 $this->accessTo[$ws]= $ws;
351 }
352 ksort($this->accessTo);
353 $this->is_modified= TRUE;
354 }
356 /* Remove user workstations? */
357 if (isset($_POST["delete_ws"]) && isset($_POST['workstation_list'])){
358 foreach($_POST['workstation_list'] as $name){
359 unset ($this->accessTo[$name]);
360 }
361 $this->is_modified= TRUE;
362 }
364 /* Add user workstation finished? */
365 if (isset($_POST["add_ws_finish"]) || isset($_POST["add_ws_cancel"])){
366 $this->show_ws_dialog= FALSE;
367 $this->dialog= FALSE;
368 }
370 /* Templates now! */
371 $smarty= get_smarty();
373 /* Show ws dialog */
374 if ($this->show_ws_dialog){
375 /* Save data */
376 $sysfilter= session::get("sysfilter");
377 foreach( array("depselect", "regex") as $type){
378 if (isset($_POST[$type])){
379 $sysfilter[$type]= $_POST[$type];
380 }
381 }
382 if (isset($_GET['search'])){
383 $s= mb_substr($_GET['search'], 0, 1, "UTF8")."*";
384 if ($s == "**"){
385 $s= "*";
386 }
387 $sysfilter['regex']= $s;
388 }
389 session::set("sysfilter", $sysfilter);
391 /* Get workstation list */
392 $exclude= "";
393 foreach($this->accessTo as $ws){
394 $exclude.= "(cn=$ws)";
395 }
396 if ($exclude != ""){
397 $exclude= "(!(|$exclude))";
398 }
399 $regex= $sysfilter['regex'];
401 $acls = array();
402 if(class_available("servgeneric")) $acls[] = "server";
403 if(class_available("workgeneric")) $acls[] = "worstation";
404 if(class_available("termgeneric")) $acls[] = "terminal";
406 $filter= "(&(|(objectClass=goServer)(objectClass=gotoWorkstation)(objectClass=gotoTerminal))$exclude(cn=*)(cn=$regex))";
408 $deps_a = array(get_ou("serverRDN"),
409 get_ou("terminalRDN"),
410 get_ou("workstationRDN"));
412 $res= get_sub_list($filter, $acls, $deps_a, get_ou("systemRDN").$sysfilter['depselect'], array("cn"), GL_SUBSEARCH | GL_SIZELIMIT);
413 $wslist= array();
414 foreach ($res as $attrs){
415 $wslist[]= preg_replace('/\$/', '', $attrs['cn'][0]);
416 }
417 asort($wslist);
418 $smarty->assign("search_image", get_template_path('images/lists/search.png'));
419 $smarty->assign("launchimage", get_template_path('images/lists/action.png'));
420 $smarty->assign("tree_image", get_template_path('images/lists/search-subtree.png'));
421 $smarty->assign("deplist", $this->config->idepartments);
422 $smarty->assign("alphabet", generate_alphabet());
423 foreach( array("depselect", "regex") as $type){
424 $smarty->assign("$type", $sysfilter[$type]);
425 }
426 $smarty->assign("hint", print_sizelimit_warning());
427 $smarty->assign("wslist", $wslist);
428 $smarty->assign("apply", apply_filter());
429 $display= $smarty->fetch (get_template_path('trust_machines.tpl', TRUE, dirname(__FILE__)));
430 return ($display);
431 }
433 /* Manage group add dialog */
434 if ($this->group_dialog){
436 /* Get global filter config */
437 $this->reload();
439 /* remove already assigned groups */
440 $glist= array();
441 foreach ($this->grouplist as $key => $value){
442 if (!isset($this->groupMembership[$key]) && obj_is_writable($key,"groups/group","memberUid")){
443 $glist[$key]= $value;
444 }
445 }
447 if($this->SubSearch){
448 $smarty->assign("SubSearchCHK"," checked ");
449 }else{
450 $smarty->assign("SubSearchCHK","");
451 }
453 $smarty->assign("regex",$this->GroupRegex);
454 $smarty->assign("guser",$this->GroupUserRegex);
455 $smarty->assign("groups", $glist);
456 $smarty->assign("search_image", get_template_path('images/lists/search.png'));
457 $smarty->assign("launchimage", get_template_path('images/lists/action.png'));
458 $smarty->assign("tree_image", get_template_path('images/lists/search-subtree.png'));
459 $smarty->assign("deplist", $this->config->idepartments);
460 $smarty->assign("alphabet", generate_alphabet());
461 $smarty->assign("depselect", session::get('CurrentMainBase'));
462 $smarty->assign("hint", print_sizelimit_warning());
463 $smarty->assign("apply", apply_filter());
465 $display.= $smarty->fetch (get_template_path('posix_groups.tpl', TRUE, dirname(__FILE__)));
466 return ($display);
467 }
469 // Handle ssh dialog?
470 if ($this->ssh && preg_match('/[rw]/', $this->getacl("sshPublicKey"))) {
471 if ($result= $this->ssh->execute()) {
472 $this->dialog= true;
473 return $result;
474 }
475 $this->dialog= false;
476 }
479 /* Show main page */
480 $smarty= get_smarty();
482 /* In 'MyAccount' mode, we must remove write acls if we are not in editing mode. */
483 $SkipWrite = (!isset($this->parent) || !$this->parent) && !session::is_set('edit');
485 $smarty->assign("sshPublicKeyACL", $this->getacl("sshPublicKey"));
487 /* Depending on pwmode, currently hardcoded because there are no other methods */
488 if ( 1 == 1 ){
489 $smarty->assign("pwmode", dirname(__FILE__)."/posix_shadow");
491 $shadowMinACL = $this->getacl("shadowMin",$SkipWrite);
492 $smarty->assign("shadowmins", sprintf(_("Password can't be changed up to %s days after last change"),
493 "<input name=\"shadowMin\" size=3 maxlength=4 value=\"".$this->shadowMin."\">"));
495 $shadowMaxACL = $this->getacl("shadowMax",$SkipWrite);
496 $smarty->assign("shadowmaxs", sprintf(_("Password must be changed after %s days"),
497 "<input name=\"shadowMax\" size=3 maxlength=4 value=\"".$this->shadowMax."\">"));
499 $shadowInactiveACL= $this->getacl("shadowInactive",$SkipWrite);
500 $smarty->assign("shadowinactives", sprintf(_("Disable account after %s days of inactivity after password expiry"),
501 "<input name=\"shadowInactive\" size=3 maxlength=4 value=\"".$this->shadowInactive."\">"));
503 $shadowWarningACL = $this->getacl("shadowWarning",$SkipWrite);
504 $smarty->assign("shadowwarnings", sprintf(_("Warn user %s days before password expiry"),
505 "<input name=\"shadowWarning\" size=3 maxlength=4 value=\"".$this->shadowWarning."\">"));
507 foreach( array("activate_shadowMin", "activate_shadowMax",
508 "activate_shadowExpire", "activate_shadowInactive","activate_shadowWarning") as $val){
509 if ($this->$val == 1){
510 $smarty->assign("$val", "checked");
511 } else {
512 $smarty->assign("$val", "");
513 }
514 $smarty->assign("$val"."ACL", $this->getacl($val,$SkipWrite));
515 }
517 $smarty->assign("mustchangepasswordACL", $this->getacl("mustchangepassword",$SkipWrite));
518 }
520 /* Fill calendar */
521 /* If this $this->shadowExpire is empty
522 use current date as base for calculating selectbox values.
523 (This attribute is empty if this is a new user )*/
524 if(empty($this->shadowExpire)){
525 $date= getdate(time());
526 }else{
527 $date= getdate($this->shadowExpire);
528 }
530 $days= array();
531 for($d= 1; $d<32; $d++){
532 $days[$d]= $d;
533 }
534 $years= array();
535 for($y= $date['year']-10; $y<$date['year']+10; $y++){
536 $years[]= $y;
537 }
538 $months= msgPool::months();
539 $smarty->assign("day", $date["mday"]);
540 $smarty->assign("days", $days);
541 $smarty->assign("months", $months);
542 $smarty->assign("month", $date["mon"]-1);
543 $smarty->assign("years", $years);
544 $smarty->assign("year", $date["year"]);
546 /* Fill arrays */
547 $smarty->assign("shells", $this->loginShellList);
548 $smarty->assign("secondaryGroups", $this->secondaryGroups);
549 $smarty->assign("primaryGroup", $this->primaryGroup);
550 if(!$this->multiple_support_active){
551 if (!count($this->groupMembership)){
552 $smarty->assign("groupMembership", array(" "));
553 } else {
554 $smarty->assign("groupMembership", $this->groupMembership);
555 }
556 }else{
557 $smarty->assign("groupMembership", $this->groupMembership);
558 $smarty->assign("groupMembership_some", $this->groupMembership_some);
559 }
560 if (count($this->groupMembership) > 16){
561 $smarty->assign("groups", "too_many_for_nfs");
562 } else {
563 $smarty->assign("groups", "");
564 }
566 /* Avoid "Undefined index: forceMode" */
567 $smarty->assign("forceMode", "");
569 /* Checkboxes */
570 if ($this->force_ids == 1){
571 $smarty->assign("force_ids", "checked");
572 if (session::get('js')){
573 $smarty->assign("forceMode", "");
574 }
575 } else {
576 if (session::get('js')){
577 $smarty->assign("forceMode", "disabled");
578 }
579 $smarty->assign("force_ids", "");
580 }
582 /* Create onClick="" action string for the "Force UID/GID" option
583 */
584 $onClickIDS ="";
585 if(preg_match("/w/",$this->getacl("uidNumber",$SkipWrite))){
586 $onClickIDS .= "changeState('uidNumber');";
587 }
588 if(preg_match("/w/",$this->getacl("gidNumber",$SkipWrite))){
589 $onClickIDS .= "changeState('gidNumber');";
590 }
591 $smarty->assign("onClickIDS", $onClickIDS);
592 $smarty->assign("force_idsACL", $this->getacl("uidNumber",$SkipWrite).$this->getacl("gidNumber",$SkipWrite));
594 foreach(array("primaryGroup","trustmode","activate_shadowWarning","activate_shadowInactive","activate_shadowMin","activate_shadowMax","activate_shadowExpire","mustchangepassword") as $val){
595 if(in_array($val,$this->multi_boxes)){
596 $smarty->assign("use_".$val,TRUE);
597 }else{
598 $smarty->assign("use_".$val,FALSE);
599 }
600 }
603 /* Load attributes and acl's */
604 foreach($this->attributes as $val){
605 if(in_array($val,$this->multi_boxes)){
606 $smarty->assign("use_".$val,TRUE);
607 }else{
608 $smarty->assign("use_".$val,FALSE);
609 }
611 if((session::get("js"))&&(($val=="uidNumber")||($val=="gidNumber")))
612 {
613 $smarty->assign("$val"."ACL",$this->getacl($val,$SkipWrite));
614 $smarty->assign("$val", $this->$val);
615 continue;
616 }
617 $smarty->assign("$val", $this->$val);
618 $smarty->assign("$val"."ACL", $this->getacl($val,$SkipWrite));
619 }
620 if($SkipWrite){
621 $smarty->assign("groupMembershipACL","r");
622 }else{
623 $smarty->assign("groupMembershipACL","rw");
624 }
625 $smarty->assign("status", $this->status);
627 /* Work on trust modes */
628 $smarty->assign("trusthide", " disabled ");
629 $smarty->assign("trustmodeACL", $this->getacl("trustModel",$SkipWrite));
630 if ($this->trustModel == "fullaccess"){
631 $trustmode= 1;
632 // pervent double disable tag in html code, this will disturb our clean w3c html
633 $smarty->assign("trustmode", $this->getacl("trustModel",$SkipWrite));
635 } elseif ($this->trustModel == "byhost"){
636 $trustmode= 2;
637 $smarty->assign("trusthide", "");
638 } else {
639 // pervent double disable tag in html code, this will disturb our clean w3c html
640 $smarty->assign("trustmode", $this->getacl("trustModel",$SkipWrite));
641 $trustmode= 0;
642 }
643 $smarty->assign("trustmode", $trustmode);
644 $smarty->assign("trustmodes", array( 0 => _("disabled"), 1 => _("full access"),
645 2 => _("allow access to these hosts")));
649 if((count($this->accessTo))==0)
650 $smarty->assign("emptyArrAccess",true);
651 else
652 $smarty->assign("emptyArrAccess",false);
654 if($this->mustchangepassword){
655 $smarty->assign("mustchangepassword", " checked ");
656 } else {
657 $smarty->assign("mustchangepassword", "");
658 }
660 $smarty->assign("workstations", $this->accessTo);
662 // Add SSH button if available
663 if ($this->ssh) {
664 $smarty->assign("sshPublicKey", 1);
665 }
667 $smarty->assign("apply", apply_filter());
668 $smarty->assign("multiple_support" , $this->multiple_support_active);
669 $display.= $smarty->fetch (get_template_path('generic.tpl', TRUE, dirname(__FILE__)));
670 return($display);
671 }
674 /* remove object from parent */
675 function remove_from_parent()
676 {
677 /* Cancel if there's nothing to do here */
678 if ((!$this->initially_was_account) || (!$this->acl_is_removeable())){
679 return;
680 }
683 /* Remove and write to LDAP */
684 plugin::remove_from_parent();
686 /* Zero out array */
687 $this->attrs['gosaHostACL']= array();
689 /* Keep uid, because we need it for authentification! */
690 unset($this->attrs['uid']);
691 unset($this->attrs['trustModel']);
693 @DEBUG (DEBUG_LDAP, __LINE__, __FUNCTION__, __FILE__,
694 /* include global link_info */
695 $this->attributes, "Save");
696 $ldap= $this->config->get_ldap_link();
697 $ldap->cd($this->dn);
698 $this->cleanup();
699 $ldap->modify ($this->attrs);
701 new log("remove","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
703 if (!$ldap->success()){
704 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
705 }
707 /* Delete group only if cn is uid and there are no other
708 members inside */
709 $ldap->cd ($this->config->current['BASE']);
710 $ldap->search ("(&(objectClass=posixGroup)(gidNumber=".$this->gidNumber."))", array("cn", "memberUid"));
711 if ($ldap->count() != 0){
712 $attrs= $ldap->fetch();
713 if ($attrs['cn'][0] == $this->uid &&
714 !isset($this->attrs['memberUid'])){
716 $ldap->rmDir($ldap->getDN());
717 }
718 }
720 /* Optionally execute a command after we're done */
721 $this->handle_post_events("remove",array("uid" => $this->uid));
722 }
725 function save_object()
726 {
727 if (isset($_POST['posixTab'])){
728 /* Save values to object */
729 plugin::save_object();
732 /* Save force GID checkbox */
733 if($this->acl_is_writeable("gidNumber") || $this->acl_is_writeable("uidNumber")){
734 if (isset ($_POST['force_ids'])){
735 $data= 1;
736 } else {
737 $data= 0;
738 }
739 if ($this->force_ids != $data){
740 $this->is_modified= TRUE;
741 }
742 $this->force_ids= $data;
743 }
745 /*Save primary group settings */
746 if($this->acl_is_writeable("primaryGroup") && isset($_POST['primaryGroup'])){
747 $data= $_POST['primaryGroup'];
748 if ($this->primaryGroup != $data){
749 $this->is_modified= TRUE;
750 }
751 $this->primaryGroup= $_POST['primaryGroup'];
752 }
754 /* Get seelcted shadow checkboxes */
755 foreach(array("shadowMin","shadowMax","shadowExpire","shadowInactive","shadowWarning") as $var) {
756 if($this->acl_is_writeable($var)){
757 $activate_var = "activate_".$var;
758 if(isset($_POST['activate_'.$var])){
759 $this->$activate_var = true;
760 $this->$var = $_POST[$var];
761 }else{
762 $this->$activate_var = false;
763 $this->$var = 0;
764 }
765 }
766 }
768 /* Force change password ? */
769 if(isset($_POST['mustchangepassword'])){
770 $this->mustchangepassword = TRUE;
771 }else{
772 $this->mustchangepassword = FALSE;
773 }
775 /* Trust mode - special handling */
776 if($this->acl_is_writeable("trustModel")){
777 if (isset($_POST['trustmode'])){
778 $saved= $this->trustModel;
779 if ($_POST['trustmode'] == "1"){
780 $this->trustModel= "fullaccess";
781 } elseif ($_POST['trustmode'] == "2"){
782 $this->trustModel= "byhost";
783 } else {
784 $this->trustModel= "";
785 }
786 if ($this->trustModel != $saved){
787 $this->is_modified= TRUE;
788 }
789 }
790 }
791 }
793 /* Get regex from alphabet */
794 if(isset($_GET['search'])){
795 $this->GroupRegex = $_GET['search']."*";
796 }
798 /* Check checkboxes and regexes */
799 if(isset($_POST["PosixGroupDialogPosted"])){
801 if(isset($_POST['SubSearch']) && ($_POST['SubSearch'])){
802 $this->SubSearch = true;
803 }else{
804 $this->SubSearch = false;
805 }
806 if(isset($_POST['guser'])){
807 $this->GroupUserRegex = $_POST['guser'];
808 }
809 if(isset($_POST['regex'])){
810 $this->GroupRegex = $_POST['regex'];
811 }
812 }
813 $this->GroupRegex = preg_replace("/\*\**/","*",$this->GroupRegex);
814 $this->GroupUserRegex = preg_replace("/\*\**/","*",$this->GroupUserRegex);
815 }
818 /* Save data to LDAP, depending on is_account we save or delete */
819 function save()
820 {
822 /* Adapt shadow values */
823 if (!$this->activate_shadowExpire){
824 $this->shadowExpire= "0";
825 } else {
826 /* Transform seconds to days here */
827 $this->shadowExpire= (int)($this->shadowExpire / (60 * 60 * 24)) ;
828 }
829 if (!$this->activate_shadowMax){
830 $this->shadowMax= "0";
831 }
832 if ($this->mustchangepassword){
833 $this->shadowLastChange= (int)(date("U") / 86400) - $this->shadowMax - 1;
834 } else {
835 $this->shadowLastChange= (int)(date("U") / 86400);
836 }
837 if (!$this->activate_shadowWarning){
838 $this->shadowWarning= "0";
839 }
841 /* Check what to do with ID's
842 Nothing forced, so we may have to generate our own IDs, if not done already.
843 */
844 if ($this->force_ids == 0){
846 /* Handle uidNumber.
847 * - use existing number if possible
848 * - if not, try to create a new uniqe one.
849 * */
850 if ($this->savedUidNumber != ""){
851 $this->uidNumber= $this->savedUidNumber;
852 } else {
854 /* Calculate new id's. We need to place a lock before calling get_next_id
855 to get real unique values.
856 */
857 $wait= 10;
858 while (get_lock("uidnumber") != ""){
859 sleep (1);
861 /* Oups - timed out */
862 if ($wait-- == 0){
863 msg_dialog::display(_("Warning"), _("Timeout while waiting for lock. Ignoring lock!"), WARNING_DIALOG);
864 break;
865 }
866 }
867 add_lock ("uidnumber", "gosa");
868 $this->uidNumber= $this->get_next_id("uidNumber", $this->dn);
869 }
870 }
873 /* Handle gidNumber
874 * - If we do not have a primary group selected (automatic), we will check if there
875 * is already a group with the same name and use this as primary.
876 * - .. if we couldn't find a group with the same name, we will create a new one,
877 * using the users uid as cn and a generated uniqe gidNumber.
878 * */
879 if ($this->primaryGroup == 0 || $this->force_ids){
881 /* Search for existing group */
882 $ldap = $this->config->get_ldap_link();
883 $ldap->cd($this->config->current['BASE']);
885 /* Are we forced to use a special gidNumber? */
886 if($this->force_ids){
887 $ldap->search("(&(objectClass=posixGroup)(gidNumber=".$this->gidNumber."))", array("cn","gidNumber"));
888 }else{
889 $ldap->search("(&(objectClass=posixGroup)(gidNumber=*)(cn=".$this->uid."))", array("cn","gidNumber"));
890 }
892 /* No primary group found, create a new one */
893 if ($ldap->count() == 0){
895 $groupcn = $this->uid;
896 $groupdn= preg_replace ('/^'.$this->config->get_cfg_value("accountPrimaryAttribute").'=[^,]+,'.get_people_ou().'/i',
897 'cn='.$groupcn.','.get_groups_ou(), $this->dn);
899 /* Request a new and uniqe gidNumber, if required */
900 if(!$this->force_ids){
901 $this->gidNumber= $this->get_next_id("gidNumber", $this->dn);
902 }else{
904 /* If forced gidNumber could not be found, then check if the given group name already exists
905 we do not want to modify the gidNumber of an existing group.
906 */
907 $cnt= 0;
908 while($ldap->dn_exists($groupdn)){
909 $cnt ++;
910 $groupcn = $this->uid."_".$cnt;
911 $groupdn= preg_replace ('/^'.$this->config->get_cfg_value("accountPrimaryAttribute").'=[^,]+,'.get_people_ou().'/i',
912 'cn='.$groupcn.','.get_groups_ou(), $this->dn);
913 }
914 }
916 /* Create new primary group and enforce the new gidNumber */
917 $g= new group($this->config, $groupdn);
918 $g->cn= $groupcn;
919 $g->force_gid= 1;
920 $g->gidNumber= $this->gidNumber;
921 $g->description= _("Group of user")." ".$this->givenName." ".$this->sn;
922 $g->save ();
924 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
925 sprintf("Primary group '%s' created, using gidNumber '%s'.",$groupcn,$this->gidNumber),"");
926 }else{
927 $attrs = $ldap->fetch();
928 $this->gidNumber = $attrs['gidNumber'][0];
929 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
930 "Found and used: <i>".$attrs['dn']."</i>",
931 sprintf("Primary group '%s' exists, gidNumber is '%s'.",$this->uid,$this->gidNumber));
932 }
933 }else{
935 /* Primary group was selected by user
936 */
937 $this->gidNumber = $this->primaryGroup;
938 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
939 sprintf("Primary group '%s' for user '%s' manually selected.",$this->gidNumber,$this->uid),"");
940 }
942 if ($this->activate_shadowMin != "1" ) {
943 $this->shadowMin = "";
944 }
946 if (($this->activate_shadowMax != "1") && ($this->mustchangepassword != "1")) {
947 $this->shadowMax = "";
948 }
950 if ($this->activate_shadowWarning != "1" ) {
951 $this->shadowWarning = "";
952 }
954 if ($this->activate_shadowInactive != "1" ) {
955 $this->shadowInactive = "";
956 }
958 if ($this->activate_shadowExpire != "1" ) {
959 $this->shadowExpire = "";
960 }
962 /* Fill gecos */
963 if (isset($this->parent) && $this->parent !== NULL){
964 $this->gecos= rewrite($this->parent->by_object['user']->cn);
965 if (!preg_match('/^[a-z0-9 -]+$/i', $this->gecos)){
966 $this->gecos= "";
967 }
968 }
970 foreach(array("shadowMin","shadowMax","shadowWarning","shadowInactive","shadowExpire") as $attr){
971 $this->$attr = (int) $this->$attr;
972 }
973 /* Call parents save to prepare $this->attrs */
974 plugin::save();
976 /* Trust accounts */
977 $objectclasses= array();
978 foreach ($this->attrs['objectClass'] as $key => $class){
979 if (preg_match('/trustAccount/i', $class)){
980 continue;
981 }
982 $objectclasses[]= $this->attrs['objectClass'][$key];
983 }
984 $this->attrs['objectClass']= $objectclasses;
985 if ($this->trustModel != ""){
986 $this->attrs['objectClass'][]= "trustAccount";
987 $this->attrs['trustModel']= $this->trustModel;
988 $this->attrs['accessTo']= array();
989 if ($this->trustModel == "byhost"){
990 foreach ($this->accessTo as $host){
991 $this->attrs['accessTo'][]= $host;
992 }
993 }
994 } else {
995 if ($this->was_trust_account){
996 $this->attrs['accessTo']= array();
997 $this->attrs['trustModel']= array();
998 }
999 }
1001 if(empty($this->attrs['gosaDefaultPrinter'])){
1002 $thid->attrs['gosaDefaultPrinter']=array();
1003 }
1006 /* include global link_info */
1007 $this->cleanup();
1009 /* This is just a test, we have had duplicated ids
1010 in the past when copy & paste was used.
1011 Normaly this should not happen.
1012 */
1013 if(isset($this->attrs['uidNumber']) && !$this->force_ids){
1014 $used = $this->get_used_uid_numbers();
1015 if(isset($used[$this->attrs['uidNumber']]) && $used[$this->attrs['uidNumber']] != $this->dn){
1016 msg_dialog::display(_("Warning"),_("A duplicated UID number was written for this user. If this was not intended please verify all used uidNumbers!"), WARNING_DIALOG);
1017 }
1018 }
1020 $ldap= $this->config->get_ldap_link();
1021 $ldap->cd($this->dn);
1022 unset($this->attrs['uid']);
1023 $ldap->modify ($this->attrs);
1025 /* Log last action */
1026 if($this->initially_was_account){
1027 new log("modify","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
1028 }else{
1029 new log("create","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
1030 }
1032 if (!$ldap->success()){
1033 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
1034 }
1036 /* Remove lock needed for unique id generation */
1037 del_lock ("uidnumber");
1039 // Save ssh stuff if needed
1040 if ($this->ssh) {
1041 $this->ssh->setDN($this->dn);
1042 $this->ssh->save();
1043 }
1045 /* Take care about groupMembership values: add to groups */
1046 foreach ($this->groupMembership as $key => $value){
1047 if (!isset($this->savedGroupMembership[$key])){
1048 $g= new grouptabs($this->config,$this->config->data['TABS']['GROUPTABS'], $key,"groups");
1049 $g->set_acl_base($key);
1050 $g->by_object['group']->addUser($this->uid);
1051 $g->save();
1052 }
1053 }
1055 /* Remove groups not listed in groupMembership */
1056 foreach ($this->savedGroupMembership as $key => $value){
1057 if (!isset($this->groupMembership[$key])){
1058 $g= new grouptabs($this->config,$this->config->data['TABS']['GROUPTABS'], $key,"groups");
1059 $g->set_acl_base($key);
1060 $g->by_object['group']->removeUser ($this->uid);
1061 $g->save();
1062 }
1063 }
1065 /* Optionally execute a command after we're done */
1066 if ($this->initially_was_account == $this->is_account){
1067 if ($this->is_modified){
1068 $this->handle_post_events("modify",array("uid" => $this->uid));
1069 }
1070 } else {
1071 $this->handle_post_events("add" ,array("uid"=> $this->uid));
1072 }
1073 }
1076 /* Check formular input */
1077 function check()
1078 {
1079 /* Include global link_info */
1080 $ldap= $this->config->get_ldap_link();
1082 /* Append groups as memberGroup: to check hook
1083 */
1084 $tmp_attributes = $this->attributes;
1085 $this->attributes[] = "memberGroup";
1086 $this->memberGroup = array();
1087 foreach($this->groupMembership as $dn => $name){
1088 $this->memberGroup[] = $name;
1089 }
1091 /* Call common method to give check the hook */
1092 $message= plugin::check();
1093 $this->attributes = $tmp_attributes;
1095 /* must: homeDirectory */
1096 if ($this->homeDirectory == ""){
1097 $message[]= msgPool::required(_("Home directory"));
1098 }
1099 if (!tests::is_path($this->homeDirectory)){
1100 $message[]= msgPool::invalid(_("Home directory"), "", "", "/home/yourname" );
1101 }
1103 /* Check ID's if they are forced by user */
1104 if ($this->force_ids == "1"){
1106 /* Valid uid/gid? */
1107 if (!tests::is_id($this->uidNumber)){
1108 $message[]= msgPool::invalid(_("UID"), $this->uidNumber, "/[0-9]/");
1109 } else {
1110 if ($this->uidNumber < $this->config->get_cfg_value("minId")){
1111 $message[]= msgPool::toosmall(_("UID"), $this->config->get_cfg_value("minId"));
1112 }
1113 }
1114 if (!tests::is_id($this->gidNumber)){
1115 $message[]= msgPool::invalid(_("GID"), $this->gidNumber, "/[0-9]/");
1116 } else {
1117 if ($this->gidNumber < $this->config->get_cfg_value("minId")){
1118 $message[]= msgPool::toosmall(_("GID"), $this->config->get_cfg_value("minId"));
1119 }
1120 }
1121 }
1123 /* Check shadow settings, well I like spaghetties... */
1124 if ($this->activate_shadowMin){
1125 if (!tests::is_id($this->shadowMin)){
1126 $message[]= msgPool::invalid(_("shadowMin"), $this->shadowMin, "/[0-9]/");
1127 }
1128 }
1129 if ($this->activate_shadowMax){
1130 if (!tests::is_id($this->shadowMax)){
1131 $message[]= msgPool::invalid(_("shadowMax"), $this->shadowMax, "/[0-9]/");
1132 }
1133 }
1134 if ($this->activate_shadowWarning){
1135 if (!tests::is_id($this->shadowWarning)){
1136 $message[]= msgPool::invalid(_("shadowWarning"), $this->shadowWarning, "/[0-9]/");
1137 }
1138 if (!$this->activate_shadowMax){
1139 $message[]= msgPool::depends("shadowWarning", "shadowMax");
1140 }
1141 if ($this->shadowWarning > $this->shadowMax){
1142 $message[]= msgPool::toobig("shadowWarning", "shadowMax");
1143 }
1144 if ($this->activate_shadowMin && $this->shadowWarning < $this->shadowMin){
1145 $message[]= msgPool::toosmall("shadowWarning", "shadowMin");
1146 }
1147 }
1148 if ($this->activate_shadowInactive){
1149 if (!tests::is_id($this->shadowInactive)){
1150 $message[]= msgPool::invalid(_("shadowInactive"), $this->shadowInactive, "/[0-9]/");
1151 }
1152 if (!$this->activate_shadowMax){
1153 $message[]= msgPool::depends("shadowInactive", "shadowMax");
1154 }
1155 }
1156 if ($this->activate_shadowMin && $this->activate_shadowMax){
1157 if ($this->shadowMin > $this->shadowMax){
1158 $message[]= msgPool::toobig("shadowMin", "shadowMax");
1159 }
1160 }
1162 return ($message);
1163 }
1166 function multiple_check()
1167 {
1168 $message = plugin::multiple_check();
1169 if ($this->homeDirectory == "" && in_array("homeDirectory",$this->multi_boxes)){
1170 $message[]= msgPool::required(_("Home directory"));
1171 }
1172 if (!tests::is_path($this->homeDirectory) && in_array("homeDirectory",$this->multi_boxes)){
1173 $message[]= msgPool::invalid(_("Home directory"), "", "", "/home/yourname" );
1174 }
1176 /* Check shadow settings, well I like spaghetties... */
1177 if ($this->activate_shadowMin && in_array("activate_shadowMin",$this->multi_boxes)){
1178 if (!tests::is_id($this->shadowMin)){
1179 $message[]= msgPool::invalid(_("shadowMin"), $this->shadowMin, "/[0-9]/");
1180 }
1181 }
1182 if ($this->activate_shadowMax && in_array("activate_shadowMax",$this->multi_boxes)){
1183 if (!tests::is_id($this->shadowMax)){
1184 $message[]= msgPool::invalid(_("shadowMax"), $this->shadowMax, "/[0-9]/");
1185 }
1186 }
1187 if ($this->activate_shadowWarning && in_array("activate_shadowWarning",$this->multi_boxes)){
1188 if (!tests::is_id($this->shadowWarning)){
1189 $message[]= msgPool::invalid(_("shadowWarning"), $this->shadowWarning, "/[0-9]/");
1190 }
1191 if (!$this->activate_shadowMax && in_array("activate_shadowMax",$this->multi_boxes)){
1192 $message[]= msgPool::depends("shadowWarning", "shadowMax");
1193 }
1194 if ($this->shadowWarning > $this->shadowMax && in_array("activate_shadowWarning",$this->multi_boxes)){
1195 $message[]= msgPool::toobig("shadowWarning", "shadowMax");
1196 }
1197 if ($this->activate_shadowMin && $this->shadowWarning < $this->shadowMin && in_array("activate_shadowMin",$this->multi_boxes)){
1198 $message[]= msgPool::tosmall("shadowWarning", "shadowMin");
1199 }
1200 }
1201 if ($this->activate_shadowInactive && in_array("activate_shadowInactive",$this->multi_boxes)){
1202 if (!tests::is_id($this->shadowInactive)){
1203 $message[]= msgPool::invalid(_("shadowInactive"), $this->shadowInactive, "/[0-9]/");
1204 }
1205 if (!$this->activate_shadowMax && in_array("activate_shadowMax",$this->multi_boxes)){
1206 $message[]= msgPool::depends("shadowInactive", "shadowMax");
1207 }
1208 }
1209 if ($this->activate_shadowMin && $this->activate_shadowMax && in_array("activate_shadowMin",$this->multi_boxes)){
1210 if ($this->shadowMin > $this->shadowMax){
1211 $message[]= msgPool::toobig("shadowMin", "shadowMax");
1212 }
1213 }
1215 return($message);
1216 }
1219 function addGroup ($groups)
1220 {
1221 /* include global link_info */
1222 $ldap= $this->config->get_ldap_link();
1224 /* Walk through groups and add the descriptive entry if not exists */
1225 foreach ($groups as $value){
1227 if (!array_key_exists($value, $this->groupMembership)){
1228 $ldap->cat($value, array('cn', 'description', 'dn'));
1229 $attrs= $ldap->fetch();
1230 error_reporting (0);
1231 if (!isset($attrs['description'][0])){
1232 $entry= $attrs["cn"][0];
1233 } else {
1234 $dsc= preg_replace ('/^Group of user/', _("Group of user"), $attrs["description"][0]);
1235 $entry= $attrs["cn"][0]." [$dsc]";
1236 }
1237 error_reporting (E_ALL | E_STRICT);
1239 if(obj_is_writable($attrs['dn'],"groups/group","memberUid")){
1240 $this->groupMembership[$attrs['dn']]= $entry;
1241 if($this->multiple_support_active && isset($this->groupMembership_some[$attrs['dn']])){
1242 unset($this->groupMembership_some[$attrs['dn']]);
1243 }
1244 }
1245 }
1246 }
1248 /* Sort groups */
1249 asort ($this->groupMembership);
1250 reset ($this->groupMembership);
1251 }
1254 /* Del posix user from some groups */
1255 function delGroup ($groups)
1256 {
1257 $dest= array();
1258 foreach($groups as $dn_to_del){
1259 if(isset($this->groupMembership[$dn_to_del]) && obj_is_writable($dn_to_del,"groups/group","memberUid")){
1260 unset($this->groupMembership[$dn_to_del]);
1261 }
1262 if($this->multiple_support_active){
1263 if(isset($this->groupMembership_some[$dn_to_del]) && obj_is_writable($dn_to_del,"groups/group","memberUid")){
1264 unset($this->groupMembership_some[$dn_to_del]);
1265 }
1266 }
1267 }
1268 }
1271 /* Adapt from template, using 'dn' */
1272 function adapt_from_template($dn, $skip= array())
1273 {
1274 /* Include global link_info */
1275 $ldap= $this->config->get_ldap_link();
1277 plugin::adapt_from_template($dn, $skip);
1278 $template= $this->attrs['uid'][0];
1280 /* Adapt group membership */
1281 $ldap->cd($this->config->current['BASE']);
1282 $ldap->search("(&(objectClass=posixGroup)(memberUid=".$this->attrs["uid"][0]."))", array("description", "cn"));
1284 while ($this->attrs= $ldap->fetch()){
1285 if (!isset($this->attrs["description"][0])){
1286 $entry= $this->attrs["cn"][0];
1287 } else {
1288 $entry= $this->attrs["cn"][0]." [".$this->attrs["description"][0]."]";
1289 }
1290 $this->groupMembership[$ldap->getDN()]= $entry;
1291 }
1293 /* Fix primary group settings */
1294 $ldap->cd($this->config->current['BASE']);
1295 $ldap->search("(&(objectClass=posixGroup)(cn=$template)(gidNumber=".$this->gidNumber."))", array("cn"));
1296 if ($ldap->count() != 1){
1297 $this->primaryGroup= $this->gidNumber;
1298 }
1300 $ldap->cd($this->config->current['BASE']);
1301 $ldap->search("(&(objectClass=gosaUserTemplate)(uid=".$template.")(accessTo=*))", array("cn","accessTo"));
1302 while($attr = $ldap->fetch()){
1303 $tmp = $attr['accessTo'];
1304 unset ($tmp['count']);
1305 $this->accessTo = $tmp;
1306 }
1308 /* Adjust shadow checkboxes */
1309 foreach (array("shadowMin", "shadowMax", "shadowWarning", "shadowInactive") as $val){
1310 if ($this->$val != 0){
1311 $oval= "activate_".$val;
1312 $this->$oval= "1";
1313 }
1314 }
1316 /* FIXME: NEED review of this section */
1317 /* Need to check shadowExpire separately */
1319 /*
1320 * If shadowExpire is not enabled in the template, it's a UNIX timestamp - so don't convert it to seconds.
1321 * The check is a hack - if difference between timestamp generated above and here is max 1 day.
1322 */
1323 if(abs($this->shadowExpire - time())>86400) {
1324 $this->shadowExpire= $this->convertToSeconds($this->shadowExpire);
1325 }
1327 /* Only enable checkbox, if shadowExpire is in the future */
1328 if($this->shadowExpire > time()) {
1329 $this->activate_shadowExpire= "1";
1330 }
1331 }
1333 function convertToSeconds($val)
1334 {
1335 if ($val != 0){
1336 $val*= 60 * 60 * 24;
1337 } else {
1338 $date= getdate();
1339 $val= floor($date[0] / (60*60*24)) * 60 * 60 * 24;
1340 }
1341 return($val);
1342 }
1345 function get_used_uid_numbers()
1346 {
1347 $ids= array();
1348 $ldap= $this->config->get_ldap_link();
1350 $ldap->cd ($this->config->current['BASE']);
1351 $ldap->search ("(&(objectClass=posixAccount)(uidNumber=*))", array("uidNumber"));
1353 /* Get list of ids */
1354 while ($attrs= $ldap->fetch()){
1355 $ids[$attrs['uidNumber'][0]] = $attrs['dn'];
1356 }
1357 return($ids);
1358 }
1361 function get_next_id($attrib, $dn)
1362 {
1363 $ids= array();
1364 $ldap= $this->config->get_ldap_link();
1366 $ldap->cd ($this->config->current['BASE']);
1367 if (preg_match('/gidNumber/i', $attrib)){
1368 $oc= "posixGroup";
1369 } else {
1370 $oc= "posixAccount";
1371 }
1372 $ldap->search ("(&(objectClass=$oc)($attrib=*))", array("$attrib"));
1374 /* Get list of ids */
1375 while ($attrs= $ldap->fetch()){
1376 $ids[]= (int)$attrs["$attrib"][0];
1377 }
1379 /* Add the nobody id */
1380 $ids[]= 65534;
1382 /* get the ranges */
1383 $tmp = array('0'=> 1000);
1384 if (preg_match('/posixAccount/', $oc) && $this->config->get_cfg_value("uidNumberBase") != ""){
1385 $tmp= split('-',$this->config->get_cfg_value("uidNumberBase"));
1386 } elseif($this->config->get_cfg_value("gidNumberBase") != ""){
1387 $tmp= split('-',$this->config->get_cfg_value("gidNumberBase"));
1388 }
1390 /* Set hwm to max if not set - for backward compatibility */
1391 $lwm= $tmp[0];
1392 if (isset($tmp[1])){
1393 $hwm= $tmp[1];
1394 } else {
1395 $hwm= pow(2,32);
1396 }
1398 /* Find out next free id near to UID_BASE */
1399 if ($this->config->get_cfg_value("baseIdHook") == ""){
1400 $base= $lwm;
1401 } else {
1402 /* Call base hook */
1403 $base= get_base_from_hook($dn, $attrib);
1404 }
1405 for ($id= $base; $id++; $id < pow(2,32)){
1406 if (!in_array($id, $ids)){
1407 return ($id);
1408 }
1409 }
1411 /* Should not happen */
1412 if ($id == $hwm){
1413 msg_dialog::display(_("Error"), _("Cannot allocate a free ID!"), ERROR_DIALOG);
1414 exit;
1415 }
1417 }
1419 function reload()
1420 {
1421 /* Set base for all searches */
1422 $base = session::get('CurrentMainBase');
1423 $base = $base;
1424 $ldap = $this->config->get_ldap_link();
1425 $attrs = array("cn", "description", "gidNumber");
1426 $Flags = GL_SIZELIMIT;
1428 /* Get groups */
1429 if ($this->GroupUserRegex == '*'){
1430 $filter = "(&(objectClass=posixGroup)(cn=".$this->GroupRegex."))";
1431 } else {
1432 $filter= "(&(objectClass=posixGroup)(cn=".$this->GroupRegex.")(memberUid=".$this->GroupUserRegex."))";
1433 }
1434 if($this->SubSearch){
1435 $Flags |= GL_SUBSEARCH;
1436 }else{
1437 $base = get_groups_ou().$base;
1438 }
1440 $res= get_list($filter, "groups", $base,$attrs, $Flags);
1442 /* check sizelimit */
1443 if (preg_match("/size limit/i", $ldap->get_error())){
1444 session::set('limit_exceeded',TRUE);
1445 }
1447 /* Create a list of users */
1448 $this->grouplist = array();
1449 foreach ($res as $value){
1450 $this->grouplist[$value['gidNumber'][0]]= $value;
1451 }
1453 $tmp=array();
1454 foreach($this->grouplist as $tkey => $val ){
1455 $tmp[strtolower($val['cn'][0]).$val['cn'][0]]=$val;
1456 }
1458 /* Sort index */
1459 ksort($tmp);
1461 /* Recreate index array[dn]=cn[description]*/
1462 $this->grouplist=array();
1463 foreach($tmp as $val){
1464 if(isset($val['description'])){
1465 $this->grouplist[$val['dn']]=$val['cn'][0]." [".$val['description'][0]."]";
1466 }else{
1467 $this->grouplist[$val['dn']]=$val['cn'][0];
1468 }
1469 }
1471 reset ($this->grouplist);
1472 }
1475 /* Get posts from copy & paste dialog */
1476 function saveCopyDialog()
1477 {
1478 if(isset($_POST['homeDirectory'])){
1479 $this->homeDirectory = $_POST['homeDirectory'];
1480 if (isset ($_POST['force_ids'])){
1481 $data= 1;
1482 $this->gidNumber = $_POST['gidNumber'];
1483 $this->uidNumber = $_POST['uidNumber'];
1484 } else {
1485 $data= 0;
1486 }
1487 if ($this->force_ids != $data){
1488 $this->is_modified= TRUE;
1489 }
1490 $this->force_ids= $data;
1491 $data= $_POST['primaryGroup'];
1492 if ($this->primaryGroup != $data){
1493 $this->is_modified= TRUE;
1494 }
1495 $this->primaryGroup= $_POST['primaryGroup'];
1496 }
1497 }
1500 /* Create the posix dialog part for copy & paste */
1501 function getCopyDialog()
1502 {
1503 /* Skip dialog creation if this is not a valid account*/
1504 if(!$this->is_account) return("");
1505 if ($this->force_ids == 1){
1506 $force_ids = "checked";
1507 if (session::get('js')){
1508 $forceMode = "";
1509 }
1510 } else {
1511 if (session::get('js')){
1512 if($this->acl != "#none#")
1513 $forceMode ="disabled";
1514 }
1515 $force_ids = "";
1516 }
1518 $sta = "";
1520 /* Open group add dialog */
1521 if(isset($_POST['edit_groupmembership'])){
1522 $this->group_dialog = TRUE;
1523 $sta = "SubDialog";
1524 }
1526 /* If the group-add dialog is closed, call execute
1527 to ensure that the membership is updatd */
1528 if(isset($_POST['add_groups_finish']) || isset($_POST['add_groups_cancel'])){
1529 $this->execute();
1530 $this->group_dialog =FALSE;
1531 }
1533 if($this->group_dialog){
1534 $str = $this->execute(true);
1535 $ret = array();
1536 $ret['string'] = $str;
1537 $ret['status'] = $sta;
1538 return($ret);
1539 }
1541 /* If a group member should be deleted, simply call execute */
1542 if(isset($_POST['delete_groupmembership'])){
1543 $this->execute();
1544 }
1546 /* Assigned informations to smarty */
1547 $smarty = get_smarty();
1548 $smarty->assign("homeDirectory",$this->homeDirectory);
1549 $smarty->assign("secondaryGroups",$this->secondaryGroups);
1550 $smarty->assign("primaryGroup",$this->primaryGroup);
1552 $smarty->assign("uidNumber",$this->uidNumber);
1553 $smarty->assign("gidNumber",$this->gidNumber);
1554 $smarty->assign("forceMode",$forceMode);
1555 $smarty->assign("force_ids",$force_ids);
1556 if (!count($this->groupMembership)){
1557 $smarty->assign("groupMembership", array(" "));
1558 } else {
1559 $smarty->assign("groupMembership", $this->groupMembership);
1560 }
1562 /* Display wars message if there are more than 16 group members */
1563 if (count($this->groupMembership) > 16){
1564 $smarty->assign("groups", "too_many_for_nfs");
1565 } else {
1566 $smarty->assign("groups", "");
1567 }
1568 $str = $smarty->fetch(get_template_path("paste_generic.tpl",TRUE,dirname(__FILE__)));
1570 $ret = array();
1571 $ret['string'] = $str;
1572 $ret['status'] = $sta;
1573 return($ret);
1574 }
1577 function PrepareForCopyPaste($source)
1578 {
1579 plugin::PrepareForCopyPaste($source);
1581 /* Avoid using the same gid/uid number as source user
1582 empty numbers to enforce new ones. */
1583 # $this->savedUidNumber = $this->get_next_id("uidNumber", $this->dn);
1584 $this->savedUidNumber = "";
1585 # $this->savedGidNumber = $this->get_next_id("gidNumber", $this->dn);
1586 $this->savedGidNumber = "";
1588 /* Fill group */
1589 if(isset($source['gidNumber'][0])){
1590 $this->primaryGroup= $source['gidNumber'][0];
1591 }
1593 }
1596 function multiple_execute()
1597 {
1598 return($this->execute());
1599 }
1602 static function plInfo()
1603 {
1604 return (array(
1605 "plDescription" => _("POSIX account"),
1606 "plSelfModify" => TRUE,
1607 "plDepends" => array("user"),
1608 "plPriority" => 2,
1609 "plSection" => array("personal" => _("My account")),
1610 "plCategory" => array("users"),
1611 "plOptions" => array(),
1613 "plProvidedAcls" => array(
1615 "homeDirectory" => _("Home directory"),
1616 "loginShell" => _("Shell"),
1617 "uidNumber" => _("User ID"),
1618 "gidNumber" => _("Group ID"),
1620 "mustchangepassword"=> _("Force password change on login"),
1621 "shadowMin" => _("Shadow min"),
1622 "shadowMax" => _("Shadow max"),
1623 "shadowWarning" => _("Shadow warning"),
1624 "shadowInactive" => _("Shadow inactive"),
1625 "shadowExpire" => _("Shadow expire"),
1626 "trustModel" => _("System trust model")))
1627 );
1628 }
1631 /* Return selected values for multiple edit */
1632 function get_multi_edit_values()
1633 {
1634 $ret = plugin::get_multi_edit_values();
1635 $ret['groupMembership'] = $this->groupMembership;
1636 $ret['groupMembership_some']= $this->groupMembership_some;
1638 if(in_array("primaryGroup",$this->multi_boxes)){
1639 $ret['primaryGroup'] = $this->primaryGroup;
1640 }
1641 if(in_array("trustmode",$this->multi_boxes)){
1642 $ret['trustModel'] = $this->trustModel;
1643 $ret['accessTo'] = $this->accessTo;
1644 }
1645 foreach(array("shadowWarning","shadowInactive","shadowMin","shadowMax", "shadowExpire") as $entry){
1646 $active = "activate_".$entry;
1647 if(in_array($active,$this->multi_boxes)){
1648 $ret[$entry] = $this->$entry;
1649 $ret[$active] = $this->$active;
1650 }
1651 }
1652 if(in_array("mustchangepassword",$this->multi_boxes)){
1653 $ret['mustchangepassword'] = $this->mustchangepassword;
1654 }
1655 return($ret);
1656 }
1659 /* Save posts for multiple edit
1660 */
1661 function multiple_save_object()
1662 {
1663 if(isset($_POST['posix_mulitple_edit'])){
1665 /* Backup expire value */
1666 $expire_tmp = $this->shadowExpire;
1668 /* Update all values */
1669 plugin::multiple_save_object();
1671 /* Get selected checkboxes */
1672 foreach(array("primaryGroup","trustmode","mustchangepassword","activate_shadowWarning","activate_shadowInactive","activate_shadowMin", "activate_shadowMax","activate_shadowExpire") as $val){
1673 if(isset($_POST["use_".$val])){
1674 $this->multi_boxes[] = $val;
1675 }
1676 }
1678 /* Update special values, checkboxes for posixShadow */
1679 foreach(array("shadowMin","shadowMax","shadowExpire","shadowInactive","shadowWarning") as $var) {
1680 if($this->acl_is_writeable($var)){
1681 $activate_var = "activate_".$var;
1682 if(in_array($activate_var, $this->multi_boxes)){
1683 if(isset($_POST['activate_'.$var])){
1684 $this->$activate_var = true;
1685 $this->$var = $_POST[$var];
1686 }else{
1687 $this->$activate_var = false;
1688 $this->$var = 0;
1689 }
1690 }
1691 }
1692 }
1694 /* Restore shadow value, if the shadow attribute isn't used */
1695 if(!in_array("activate_shadowExpire",$this->multi_boxes)){
1696 $this->shadowExpire = $expire_tmp;
1697 }
1699 /* Force change password ? */
1700 if(isset($_POST['mustchangepassword'])){
1701 $this->mustchangepassword = TRUE;
1702 }else{
1703 $this->mustchangepassword = FALSE;
1704 }
1706 /* Trust mode - special handling */
1707 if($this->acl_is_writeable("trustModel")){
1708 if (isset($_POST['trustmode'])){
1709 $saved= $this->trustModel;
1710 if ($_POST['trustmode'] == "1"){
1711 $this->trustModel= "fullaccess";
1712 } elseif ($_POST['trustmode'] == "2"){
1713 $this->trustModel= "byhost";
1714 } else {
1715 $this->trustModel= "";
1716 }
1717 if ($this->trustModel != $saved){
1718 $this->is_modified= TRUE;
1719 }
1720 }
1721 }
1723 /* Save primary group settings */
1724 if($this->acl_is_writeable("primaryGroup") && isset($_POST['primaryGroup'])){
1725 $data= $_POST['primaryGroup'];
1726 if ($this->primaryGroup != $data){
1727 $this->is_modified= TRUE;
1728 }
1729 $this->primaryGroup= $_POST['primaryGroup'];
1730 }
1731 }
1732 }
1735 /* Initialize plugin with given atribute arrays
1736 */
1737 function init_multiple_support($attrs,$all)
1738 {
1739 plugin::init_multiple_support($attrs,$all);
1741 /* Some dummy values */
1742 $groups_some = array();
1743 $groups_all = array();
1744 $groups_uid = array();
1745 $uids = array();
1746 $first = TRUE;
1748 /* Get all groups used by currently edited users */
1749 $uid_filter="";
1750 for($i =0; $i < $this->multi_attrs_all['uid']['count'] ; $i ++){
1751 $uid = $this->multi_attrs_all['uid'][$i];
1752 $uids[] = $uid;
1753 $uid_filter.= "(memberUid=".$uid.")";
1754 }
1755 $uid_filter = "(&(objectClass=posixGroup)(|".$uid_filter."))";
1756 $ldap = $this->config->get_ldap_link();
1757 $ldap->cd($this->config->current['BASE']);
1758 $ldap->search($uid_filter,array("dn","cn","memberUid"));
1759 while($group = $ldap->fetch()){
1760 $groups_some[$group['dn']] = $group['cn'][0];
1761 for($i = 0 ; $i < $group['memberUid']['count'] ; $i++){
1762 $groups_uid[$group['dn']][] = $group['memberUid'][$i];
1763 }
1764 }
1766 /* Create an array, containing all used groups */
1767 $groups_all = $groups_some;
1768 foreach($groups_all as $id => $group){
1769 foreach($uids as $uid){
1770 if(!in_array($uid,$groups_uid[$id])){
1771 unset($groups_all[$id]);
1772 break;
1773 }
1774 }
1775 }
1777 /* Assign group array */
1778 $this->groupMembership = $groups_all;
1780 /* Create an array of all grouops used by all users */
1781 foreach( $groups_all as $dn => $cn){
1782 if(isset($groups_some[$dn])){
1783 unset($groups_some[$dn]);
1784 }
1785 }
1786 $this->groupMembership_some = $groups_some;
1787 $this->primaryGroup = $this->gidNumber;
1789 /* Is this account a trustAccount? */
1790 if (isset($this->multi_attrs['trustModel'])){
1791 $this->trustModel= $this->multi_attrs['trustModel'][0];
1792 $this->was_trust_account= TRUE;
1793 $this->multi_boxes[] = "trustmode";
1794 } else {
1795 $this->was_trust_account= FALSE;
1796 $this->trustModel= "";
1797 }
1799 /* Create access informations */
1800 $this->accessTo = array();
1801 if (isset($this->multi_attrs['accessTo'])){
1802 for ($i= 0; $i<$this->multi_attrs['accessTo']['count']; $i++){
1803 $tmp= $this->multi_attrs['accessTo'][$i];
1804 $this->accessTo[$tmp]= $tmp;
1805 }
1806 }
1808 /* Adjust shadow checkboxes */
1809 foreach (array("shadowMin", "shadowMax", "shadowWarning", "shadowInactive",
1810 "shadowExpire") as $val){
1811 if ($this->$val != 0){
1812 $oval= "activate_".$val;
1813 $this->$oval= "1";
1814 }
1815 }
1817 /* Convert to seconds */
1818 if(isset($this->multi_attrs['shadowExpire'])){
1819 $this->shadowExpire = $this->convertToSeconds($this->multi_attrs['shadowExpire'][0]);
1820 }else{
1821 $this->activate_shadowExpire = FALSE;
1822 }
1823 }
1826 function set_multi_edit_values($attrs)
1827 {
1828 $groups = array();
1830 /* Update groupMembership, keep optinal group */
1831 foreach($attrs['groupMembership_some'] as $dn => $cn){
1832 if(isset($this->groupMembership[$dn])){
1833 $groups[$dn] = $cn;
1834 }
1835 }
1836 /* Update groupMembership, add forced groups */
1837 foreach($attrs['groupMembership'] as $dn => $cn){
1838 $groups[$dn] = $cn;
1839 }
1840 plugin::set_multi_edit_values($attrs);
1841 $this->groupMembership = $groups;
1842 }
1843 }
1845 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1846 ?>