Code

cb241e439588030a5d8c2ac2fe74394eb7984e79
[gosa.git] / gosa-plugins / sudo / admin / sudo / class_sudoGeneric.inc
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: class_sudo.inc 9975 2008-03-25 14:09:30Z hickert $$
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  */
24 /*! \brief Sudo generic class. Allow setting User/Host/Command/Runas
25            for a sudo role object.
26  */
27 class sudo extends plugin
28 {
30   protected $cn= "";
31   protected $description= "";
33   protected $sudoUser   = array("ALL");
34   protected $sudoCommand= array();
35   protected $sudoHost   = array("ALL");
36   protected $sudoRunAs  = array("ALL");
37   protected $accessTo         = array();
38   protected $trustModel       = "";
40   private $is_default = FALSE;
41   private $was_trust_account= FALSE;
43   public $objectclasses = array("top","sudoRole");
44   public $attributes    = array("cn","description","sudoUser","sudoCommand","sudoHost","sudoRunAs","accessTo","trustModel");
46   public $ignore_account = TRUE;
48   public $orig_dn;
50   protected $trustSelect;
52   /*! \brief  Returns to the base department for sudo roles.
53               This department is then used to store new roles.
54       @param  Object  GOsa configuration object.
55       @return String sudo store department
56    */
57   public static function get_sudoers_ou($config)
58   {
59     return(get_ou("sudoRDN").$config->current['BASE']);
60   }
62   /*! \brief  Initializes this sudo class, with all required attributes.
63       @param  Object $config  GOsa configuration object.
64       @param  String $db      "new" or the sudo role dn.
65       @return .
66    */
67   function sudo(&$config, $dn= NULL)
68   {
69     plugin::plugin ($config, $dn);
71     if($this->initially_was_account){
72       foreach(array("sudoUser","sudoCommand","sudoHost","sudoRunAs") as $attr){
73         $this->$attr = array();
74         if(isset($this->attrs[$attr])){
75           $tmp = array();
76           for($i = 0 ; $i < $this->attrs[$attr]['count']; $i++){
77             $tmp[] = $this->attrs[$attr][$i];
78           }
79           $this->$attr = $tmp;
80         }
81       }
83       /* Is this account a trustAccount? */
84       if (isset($this->attrs['trustModel'])){
85         $this->trustModel= $this->attrs['trustModel'][0];
86         $this->was_trust_account= TRUE;
87       } else {
88         $this->was_trust_account= FALSE;
89         $this->trustModel= "";
90       }
92       $this->accessTo = array();
93       if (isset($this->attrs['accessTo'])){
94         for ($i= 0; $i<$this->attrs['accessTo']['count']; $i++){
95           $tmp= $this->attrs['accessTo'][$i];
96           $this->accessTo[$tmp]= $tmp;
97         }
98       }
100     }
102     if(preg_match("/^defaults$/i",$this->cn)){
103       $this->is_default = TRUE;
104     }
106     /* Get global filter config */
107     if (!session::is_set("sysfilter")){
108       $ui= get_userinfo();
109       $base= get_base_from_people($ui->dn);
110       $sysfilter= array( "depselect"       => $base,
111           "regex"           => "*");
112       session::set("sysfilter", $sysfilter);
113     }
115     $this->orig_dn = $this->dn;
116   }
119   /*! \brief  Creates the sudo generic ui. 
120       @return String  The generated HTML content for this plugin. 
121    */
122   function execute()
123   {
124     /* Call parent execute */
125     plugin::execute();
127     /*********************
128        Access control list / trust mode 
129      *********************/ 
131     /* Add user workstation? */
132     if (isset($_POST["add_ws"])){
133       $this->trustSelect= new trustSelect($this->config,get_userinfo());
134       $this->dialog= TRUE;
135     }
137     // Add selected machines to trusted ones.
138     if (isset($_POST["add_ws_finish"]) &&  $this->trustSelect){
139       $trusts = $this->trustSelect->detectPostActions();
140       if(isset($trusts['targets'])){
142         $headpage = $this->trustSelect->getHeadpage();
143         foreach($trusts['targets'] as $id){
144           $attrs = $headpage->getEntry($id);
145           $this->accessTo[$attrs['cn'][0]]= $attrs['cn'][0];
146         }
147         ksort($this->accessTo);
148         $this->is_modified= TRUE;
149       }
150       $this->trustSelect= NULL;
151       $this->dialog= FALSE;
152     }
155     /* Remove user workstations? */
156     if (isset($_POST["delete_ws"]) && isset($_POST['workstation_list'])){
157       foreach($_POST['workstation_list'] as $name){
158         unset ($this->accessTo[$name]);
159       }
160       $this->is_modified= TRUE;
161     }
163     /* Add user workstation finished? */
164     if (isset($_POST["add_ws_finish"]) || isset($_POST["add_ws_cancel"])){
165       $this->trustSelect= NULL;
166       $this->dialog= FALSE;
167     }
169     /* Show ws dialog */
170     if ($this->trustSelect){
172       // Build up blocklist
173       session::set('filterBlacklist', array('cn' => array_values($this->accessTo)));
174       return($this->trustSelect->execute());
175     }
178     /*********************
179        Add users 
180      *********************/ 
181  
182     if(isset($_POST['list_sudoUser']) && !is_object($this->dialog) && $this->acl_is_writeable("sudoUser")){
183       $this->dialog =new userGroupSelect($this->config,get_userinfo());
184     }
185    
186     /* Add selected hosts  to the sudoUser list */ 
187     if(isset($_POST['userGroupSelect_save']) && $this->dialog instanceof userGroupSelect){
188       if($this->acl_is_writeable("sudoUser")){
189         foreach($this->dialog->save() as $entry){
190           if(in_array("posixGroup",$entry['objectClass'])){
191             $name = trim("%".$entry['cn'][0]);
192           }elseif(isset($entry['uid'][0])){
193             $name = trim($entry['uid'][0]);
194           }
195           if(!in_array($name,$this->sudoUser) && !in_array("!".$name,$this->sudoUser)){
196             $this->sudoUser[] = $name;
197           }
198         }   
199       }
200       unset($this->dialog);
201       $this->dialog = NULL;
202     }    
204     if(isset($_POST['userGroupSelect_cancel']) && $this->dialog instanceOf userGroupSelect){
205       unset($this->dialog);
206       $this->dialog = NULL;
207     }    
209     if($this->dialog instanceOf userGroupSelect){
210       $used = array();
211       foreach($this->sudoUser as $name){
212         $str = preg_replace("/^!/","",$name);
213         if(preg_match("/^%/", $str)){
214           $used['cn'][] = preg_replace("/^%/","",$str);
215         }else{
216           $used['uid'][] = $str;
217         }
218       }
220       // Build up blocklist
221       session::set('filterBlacklist', $used);
222       return($this->dialog->execute());
223     }
224  
227     /*********************
228        Add systems 
229      *********************/ 
230   
231     if(isset($_POST['list_sudoHost']) && !is_object($this->dialog) && $this->acl_is_writeable("sudoHost")){
232       $this->dialog =new systemSelect($this->config,get_userinfo());
233     }
234    
235     /* Add selected hosts  to the sudoHost list */ 
236     if(isset($_POST['systemSelect_save']) && $this->dialog instanceof systemSelect){
237       if($this->acl_is_writeable("sudoHost")){
238         foreach($this->dialog->save() as $entry){
239           $cn = trim($entry['cn'][0]);
240           if(!in_array($cn,$this->sudoHost) && !in_array("!".$cn,$this->sudoHost)){
241             $this->sudoHost[] = $cn;
242           }
243         }   
244       }   
245       unset($this->dialog);
246       $this->dialog = NULL;
247     }    
249     if(isset($_POST['systemSelect_cancel']) && $this->dialog instanceOf systemSelect){
250       unset($this->dialog);
251       $this->dialog = NULL;
252     }    
254     if($this->dialog instanceOf systemSelect){
255       $used = array();
256       foreach($this->sudoHost as $name){
257         $used['cn'][] = preg_replace("/^!/","",$name);
258       }
260       // Build up blocklist
261       session::set('filterBlacklist', $used);
262       return($this->dialog->execute());
263     }
264   
265     /*********************
266        Dialog handling / display / close  
267      *********************/ 
268   
269     if(is_object($this->dialog)){
270       return($this->dialog->execute());
271     }
273  
274     /*********************
275        NEGATE values 
276      *********************/ 
277     foreach($_POST as $name => $value){
278       if(preg_match("/^neg_/",$name)){
279         $attr = preg_replace("/^neg_([^_]*)_.*$/","\\1",$name);
280         $value= preg_replace("/^neg_[^_]*_([0-9]*)_.*$/","\\1",$name);
281  
282         if($this->acl_is_writeable($attr)){
283           $attrs = $this->$attr;
284           if(isset( $attrs[$value])){
285             $v =  $attrs[$value];
286             if(preg_match("/^!/",$v)){
287               $attrs[$value] = preg_replace("/^!/","",$v);
288             }else{
289               $attrs[$value] = "!".$v;
290             }
291             $this->$attr = $attrs;  
292           }
293         }
294         break; // Do it once, image inputs will be posted twice
295       }
296     }
297   
298     /*********************
299        Delete values 
300      *********************/ 
301     foreach($_POST as $name => $value){
302       if(preg_match("/^del_/",$name)){
303         $attr = preg_replace("/^del_([^_]*)_.*$/","\\1",$name);
304         $value= preg_replace("/^del_[^_]*_([0-9]*)_.*$/","\\1",$name);
305         if($this->acl_is_writeable($attr)){
306           $attrs = $this->$attr;
307           if(isset( $attrs[$value])){
308             unset($attrs[$value]);
309             $this->$attr = $attrs;  
310           }
311         }
312         break; // Do it once, image inputs will be posted twice
313       }
314     }
317     /*********************
318        ADD values 
319      *********************/
321     /* User / Host / Runas */ 
322     foreach(array("sudoUser","sudoHost","sudoRunAs") as $attr){
323         if($this->acl_is_writeable($attr) && 
324                 isset($_POST["add_".$attr]) && 
325                 isset($_POST['new_'.$attr]) && 
326                 !empty($_POST['new_'.$attr])){
328             $c = preg_quote(' *+-?_|!\'"()','/');
329             if(preg_match("/^[a-z0-9{$c}]*$/i",$_POST['new_'.$attr])){
330                 $attrs = $this->$attr;
331                 $attrs[] =  trim($_POST['new_'.$attr]);
332                 $this->$attr = $attrs;
333             }else{
334                 msg_dialog::display(_("Error"),msgPool::invalid($attr,$_POST['new_'.$attr],"/[a-z0-9{$c}]/i"));
335             }
336         }
337     }
339     /* Command */
340     foreach(array("sudoCommand") as $attr){
341       if($this->acl_is_writeable($attr) && isset($_POST["add_".$attr]) && isset($_POST['new_'.$attr])){
342         $attrs = $this->$attr;
343         $attrs[] =  trim($_POST['new_'.$attr]); 
344         $this->$attr = $attrs;
345       }
346     }
348     
349     /*********************
350        SMARTY assignments 
351      *********************/
353     $smarty = get_smarty();
354     $smarty->assign("is_default",$this->is_default);
355     foreach($this->attributes as $attr){
356       if(is_string($this->$attr)){
357         $smarty->assign($attr,htmlentities($this->$attr));
358       }else{
359         $smarty->assign($attr,$this->$attr);
360       }
361       $smarty->assign($attr."ACL",$this->getacl($attr));
362     }
364     /* Work on trust modes */
365     $smarty->assign("trusthide", " disabled ");
366     if ($this->trustModel == "fullaccess"){
367       $trustmode= 1;
368     } elseif ($this->trustModel == "byhost"){
369       $trustmode= 2;
370       $smarty->assign("trusthide", "");
371     } else {
372       $trustmode= 0;
373     }
374     $smarty->assign("trustmode", $trustmode);
375     $smarty->assign("trustmodes", array( 
376           0 => _("disabled"), 
377           1 => _("full access"),
378           2 => _("allow access to these hosts")));
380     if((count($this->accessTo))==0){
381       $smarty->assign("emptyArrAccess",true);
382     }else{
383       $smarty->assign("emptyArrAccess",false);
384     }
385     $smarty->assign("workstations", $this->accessTo);
386     
387     /* Create lists 
388      */
389     $divlist_sudoUser = new divSelectBox("divlist_sudoUser");
390     $divlist_sudoUser->SetHeight("90");
391     $divlist_sudoHost = new divSelectBox("divlist_sudoHost");
392     $divlist_sudoHost->Setheight("90");
393     $divlist_sudoRunAs = new divSelectBox("divlist_sudoRunAs");
394     $divlist_sudoRunAs->Setheight("90");
395     $divlist_sudoCommand = new divSelectBox("divlist_sudoCommand");
396     $divlist_sudoCommand->Setheight("90");
398     /* Fill divlists
399      */
400     $neg_img= "<img src='plugins/sudo/images/negate.png' alt='!' class='center'>"; 
401     $option = "<input type='image' src='plugins/sudo/images/negate.png'     name='neg_%ATTR%_%KEY%' class='center'>"; 
402     $option.= "<input type='image' src='images/lists/trash.png'  name='del_%ATTR%_%KEY%' class='center'>"; 
403     foreach(array("sudoCommand","sudoHost","sudoRunAs") as $attr){
404       if($this->acl_is_readable($attr)){
405         foreach($this->$attr as $key => $entry){
406           $neg = "";
407           if(preg_match("/^!/",$entry)){
408             $neg = $neg_img;
409           }
410           $entry = preg_replace("/^!/","",$entry);
411           $list_name = "divlist_".$attr;
412           $$list_name->AddEntry(
413               array(
414                 array("string" => $neg,"attach" => "style='width:18px;'"),
415                 array("string" => $entry),
416                 array("string" => preg_replace(array("/%KEY%/","/%ATTR%/"),array($key,$attr),$option),
417                   "attach" => "style='width:40px; border-right: 0px;'")));
418         }
419       }
420     }
422     foreach(array("sudoUser") as $attr){
423       $img1 = "<img src='plugins/users/images/select_user.png'   alt='"._("User")."' class='center'>";
424       $img2 = "<img src='plugins/groups/images/groups.png' alt='"._("Group")."' class='center'>";
425       if($this->acl_is_readable($attr)){
426         foreach($this->$attr as $key => $entry){
427           $neg = "";
428           if(preg_match("/^!/",$entry)){
429             $neg = $neg_img;
430           }
431           $entry = preg_replace("/^!/","",$entry);
433           $img = $img1;
434           if(preg_match("/^%/",$entry)){
435             $img = $img2;
436           }
437           $entry = preg_replace("/^%/","",$entry);
438   
439           $list_name = "divlist_".$attr;
440           $$list_name->AddEntry(
441               array(
442                 array("string" => $neg,"attach" => "style='width:18px;'"),
443                 array("string" => $img,"attach" => "style='width:18px;'"),
444                 array("string" => $entry),
445                 array("string" => preg_replace(array("/%KEY%/","/%ATTR%/"),array($key,$attr),$option),
446                   "attach" => "style='width:40px; border-right: 0px;'")));
447         }
448       }
449     }
454     /* Tell smarty about our divlists 
455      */
456     $smarty->assign("divlist_sudoUser",   $divlist_sudoUser->DrawList());
457     $smarty->assign("divlist_sudoHost",   $divlist_sudoHost->DrawList());
458     $smarty->assign("divlist_sudoRunAs",  $divlist_sudoRunAs->DrawList());
459     $smarty->assign("divlist_sudoCommand",$divlist_sudoCommand->DrawList());
460     return($smarty->fetch(get_template_path('generic.tpl', TRUE)));
461   }
464   /*! \brief  Remove this sudo role from the ldap server 
465    */
466   function remove_from_parent()
467   {
468     plugin::remove_from_parent();
470     $ldap = $this->config->get_ldap_link();
471     $ldap->cd($this->dn);
472     $ldap->rmdir($this->dn);
474     /* Send signal to the world that we've done */
475     $this->handle_post_events("remove");
476   }
479   /*! \brief  Save all relevant HTML posts. 
480    */
481   function save_object()
482   {
483     plugin::save_object();
484     
485     if($this->is_default){
486       $this->cn = "defaults";
487     }  
489     /* Trust mode - special handling */
490     if($this->acl_is_writeable("trustModel")){
491       if (isset($_POST['trustmode'])){
492         $saved= $this->trustModel;
493         if ($_POST['trustmode'] == "1"){
494           $this->trustModel= "fullaccess";
495         } elseif ($_POST['trustmode'] == "2"){
496           $this->trustModel= "byhost";
497         } else {
498           $this->trustModel= "";
499         }
500         if ($this->trustModel != $saved){
501           $this->is_modified= TRUE;
502         }
503       }
504     }
505   }
508   /*! \brief  Save changes into the ldap database.
509    */
510   function save()
511   {
512     plugin::save();
513    /* Trust accounts */
514     $objectclasses= array();
515     foreach ($this->attrs['objectClass'] as $key => $class){
516       if (preg_match('/trustAccount/i', $class)){
517         continue;
518       }
519       $objectclasses[]= $this->attrs['objectClass'][$key];
520     }
522     $this->attrs['objectClass']= $objectclasses;
523     if ($this->trustModel != ""){
524       $this->attrs['objectClass'][]= "trustAccount";
525       $this->attrs['trustModel']= $this->trustModel;
526       $this->attrs['accessTo']= array();
527       if ($this->trustModel == "byhost"){
528         foreach ($this->accessTo as $host){
529           $this->attrs['accessTo'][]= $host;
530         }
531       }
532     } else {
533       if ($this->was_trust_account){
534         $this->attrs['accessTo']= array();
535         $this->attrs['trustModel']= array();
536       }
537     }
540     /* Ensure a correct array index 
541      */ 
542     $this->attrs['sudoHost']    = array_values($this->attrs['sudoHost']);
543     $this->attrs['sudoRunAs']   = array_values($this->attrs['sudoRunAs']);
544     $this->attrs['sudoUser']    = array_values($this->attrs['sudoUser']);
545     $this->attrs['sudoCommand'] = array_values($this->attrs['sudoCommand']);
547     $this->cleanup();
549     $ldap = $this->config->get_ldap_link();
550     $ldap->cd($this->config->current['BASE']);
552     if($this->is_new){
553       $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $this->dn));
554       $ldap->cd($this->dn);
555       $ldap->add($this->attrs);
557       /* Send signal to the world that we've done */
558       $this->handle_post_events("create");
559     }else{
560       $ldap->cd($this->dn);
561       $ldap->modify($this->attrs);;
563       /* Send signal to the world that we've done */
564       $this->handle_post_events("modify");
565     }
567     if (!$ldap->success()){
568       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
569     }
570   }
573   /*! \brief  Check the given input.
574       @return Array   All error messages in an array();
575    */
576   function check()
577   {
578     $message = plugin::check();
580     /* Is a name given? */
581     if($this->cn == ""){
582       $message[] = msgPool::required(_("Name"));
583     }
585     /* Check if name is reserved */
586     if(!$this->is_default && preg_match("/^defaults$/i",$this->cn)){
587       $message[] = msgPool::reserved(_("Name"));
588     }
590     /* Check name */
591     if(!preg_match("/^[0-9a-z\@]*$/i",$this->cn)){
592       $message[] = msgPool::invalid(_("Name"),$this->cn,"/[0-9a-z\@]/i");
593     }
595     /* Check if this entry will cause duplicated ldap entries */
596     $ldap = $this->config->get_ldap_link();
597     $ldap->cd($this->get_sudoers_ou($this->config));
598     $ldap->search("(&(objectClass=sudoRole)(cn=".$this->cn."))");
599     while($attrs = $ldap->fetch()){
600       if($attrs['dn'] != $this->dn){
601         $message[] = msgPool::duplicated(_("Name"));
602       }
603     }
605     /* Check if we are allowed to create or move this object
606      */
607     if($this->orig_dn == "new" && !$this->acl_is_createable($this->get_sudoers_ou($this->config))){
608       $message[] = msgPool::permCreate();
609     }
611     return ($message);
612   }
615   /*! \brief Force this entry to be handled and saved as 'default'
616       @param  BOOL  TRUE -force defaults   FALSE -normal
617    */
618   public function set_default($state)
619   {
620     $this->is_default = TRUE;
621     $this->cn = "defaults";
622   }
625   /*! \brief  Add ACL object
626       @return Returns the ACL object.
627    */
628   static function plInfo()
629   {
630     return (array(  
631           "plShortName" => _("Sudo"),
632           "plDescription" => _("Sudo role"),
633           "plSelfModify"  => FALSE,
634           "plDepends"     => array(),
635           "plPriority"    => 0,
636           "plSection"     => array("administration"),
637           "plCategory"    => array("sudo" => array("objectClass" => "sudoRole", "description" => _("Sudo role"))),
639           "plProvidedAcls"    => array(
640             "cn"                => _("Name"),
641             "description"       => _("Description"),
642             "sudoUser"          => _("Users"),
643             "sudoHost"          => _("Host"),
644             "sudoCommand"       => _("Command"),
645             "sudoRunAs"         => _("Run as user"),
646             "trustModel"        => _("Access control list"))
647         ));
648   }
651   /*! \brief  This function will be called if an object gets copied.
652               This function adapts attributes from the source object.
653       @param  Array The source object.
654    */
655   function PrepareForCopyPaste($source)
656   {
657     plugin::PrepareForCopyPaste($source);
658     foreach(array("sudoUser","sudoCommand","sudoHost","sudoRunAs") as $attr){
659       $this->$attr = array();
660       if(isset($source[$attr])){
661         $tmp = array();
662         for($i = 0 ; $i < $source[$attr]['count']; $i++){
663           $tmp[] = $source[$attr][$i];
664         }
665         $this->$attr = $tmp;
666       }
667     }
669     /* Is this account a trustAccount? */
670     if (isset($source['trustModel'])){
671       $this->trustModel= $source['trustModel'][0];
672       $this->was_trust_account= TRUE;
673     } else {
674       $this->was_trust_account= FALSE;
675       $this->trustModel= "";
676     }
678     $this->accessTo = array();
679     if (isset($source['accessTo'])){
680       for ($i= 0; $i<$source['accessTo']['count']; $i++){
681         $tmp= $source['accessTo'][$i];
682         $this->accessTo[$tmp]= $tmp;
683       }
684     }
685   }
688   /*! \brief  Used for copy & paste.
689               Returns a HTML input mask, which allows to change the cn of this entry.
690       @param  Array   Array containing current status && a HTML template.              
691    */
692   function getCopyDialog()
693   {
694     $vars = array("cn");
695     $smarty = get_smarty();
696     $smarty->assign("cn", htmlentities($this->cn));
697     $str = $smarty->fetch(get_template_path("paste_generic.tpl",TRUE));
698     $ret = array();
699     $ret['string'] = $str;
700     $ret['status'] = "";
701     return($ret);
702   }
705   public function get_cn()
706   {
707     return($this->cn);
708   }
711   /*! \brief  Used for copy & paste.
712               Some entries must be renamed to avaoid duplicate entries.
713    */
714   function saveCopyDialog()
715   {
716     if(isset($_POST['cn'])){
717       $this->cn = get_post('cn');
718     }
719   }
721 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
722 ?>