Code

Updated sudo
[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 {
29   /* Group attributes */
30   var $cn= "";
31   var $description= "";
33   var $sudoUser   = array("ALL");
34   var $sudoCommand= array();
35   var $sudoHost   = array("ALL");
36   var $sudoRunAs  = array("ALL");
38   var $accessTo         = array();
39   var $trustModel       = "";
40   var $show_ws_dialog   = FALSE;
41   var $was_trust_account= FALSE;
43   var $objectclasses = array("top","sudoRole");
44   var $attributes    = array("cn","description","sudoUser","sudoCommand","sudoHost","sudoRunAs","accessTo","trustModel");
46   var $is_account = TRUE;
47   var $is_default = FALSE;
48   var $dialog;
50   /*! \brief  Returns to the base department for sudo roles.
51               This department is then used to store new roles.
52       @param  Object  GOsa configuration object.
53       @return String sudo store department
54    */
55   public static function get_sudoers_ou($config)
56   {
57     /***
58       GET sudo base
59      ***/
60     $base ="";
61     if(empty($base)){
62       /* Default is ou=sudoers,BASE */
63       $base = "ou=sudoers,".$config->current['BASE'];
64     }else{
66       /* Append base to given sudoers ou if missing */
67       if(!preg_match("/".normalizePreg($config->current['BASE'])."$/i",$base)){
68         if(!preg_match("/,$/",$base)){
69           $base = $base.",".$config->current['BASE'];
70         }else{
71           $base = $base.$config->current['BASE'];
72         }
73       }
74     }
75     return($base);
76   }
78   /*! \brief  Initializes this sudo class, with all required attributes.
79       @param  Object $config  GOsa configuration object.
80       @param  String $db      "new" or the sudo role dn.
81       @return .
82    */
83   function sudo(&$config, $dn= NULL)
84   {
85     plugin::plugin ($config, $dn);
87     if($this->initially_was_account){
88       foreach(array("sudoUser","sudoCommand","sudoHost","sudoRunAs") as $attr){
89         $this->$attr = array();
90         if(isset($this->attrs[$attr])){
91           $tmp = array();
92           for($i = 0 ; $i < $this->attrs[$attr]['count']; $i++){
93             $tmp[] = $this->attrs[$attr][$i];
94           }
95           $this->$attr = $tmp;
96         }
97       }
99       /* Is this account a trustAccount? */
100       if ($this->is_account && isset($this->attrs['trustModel'])){
101         $this->trustModel= $this->attrs['trustModel'][0];
102         $this->was_trust_account= TRUE;
103       } else {
104         $this->was_trust_account= FALSE;
105         $this->trustModel= "";
106       }
108       $this->accessTo = array();
109       if ($this->is_account && isset($this->attrs['accessTo'])){
110         for ($i= 0; $i<$this->attrs['accessTo']['count']; $i++){
111           $tmp= $this->attrs['accessTo'][$i];
112           $this->accessTo[$tmp]= $tmp;
113         }
114       }
116     }
118     if(preg_match("/^defaults$/i",$this->cn)){
119       $this->is_default = TRUE;
120     }
122     /* Get global filter config */
123     if (!session::is_set("sysfilter")){
124       $ui= get_userinfo();
125       $base= get_base_from_people($ui->dn);
126       $sysfilter= array( "depselect"       => $base,
127           "regex"           => "*");
128       session::set("sysfilter", $sysfilter);
129     }
130   }
133   /*! \brief  Creates the sudo generic ui. 
134       @return String  The generated HTML content for this plugin. 
135    */
136   function execute()
137   {
138     /* Call parent execute */
139     plugin::execute();
141     /*********************
142        Access control list / trust mode 
143      *********************/ 
145     /* Add user workstation? */
146     if (isset($_POST["add_ws"])){
147       $this->show_ws_dialog= TRUE;
148       $this->dialog= TRUE;
149     }
151     /* Add user workstation? */
152     if (isset($_POST["add_ws_finish"]) && isset($_POST['wslist'])){
153       foreach($_POST['wslist'] as $ws){
154         $this->accessTo[$ws]= $ws;
155       }
156       ksort($this->accessTo);
157       $this->is_modified= TRUE;
158     }
160     /* Remove user workstations? */
161     if (isset($_POST["delete_ws"]) && isset($_POST['workstation_list'])){
162       foreach($_POST['workstation_list'] as $name){
163         unset ($this->accessTo[$name]);
164       }
165       $this->is_modified= TRUE;
166     }
168     /* Add user workstation finished? */
169     if (isset($_POST["add_ws_finish"]) || isset($_POST["add_ws_cancel"])){
170       $this->show_ws_dialog= FALSE;
171       $this->dialog= FALSE;
172     }
174     /* Show ws dialog */
175     if ($this->show_ws_dialog){
176       return($this->display_trust_add_dialog());
177     }
180     /*********************
181        Add users 
182      *********************/ 
183   
184     if(isset($_POST['list_sudoUser']) && !is_object($this->dialog) && $this->acl_is_writeable("sudoUser")){
185       $used = array();
186       foreach($this->sudoUser as $name){
187         $used[] = preg_replace("/^!/","",$name);
188       }
189       $this->dialog =new target_list_users($this->config,$used);
190     }
191    
192     /* Add selected hosts  to the sudoUser list */ 
193     if(isset($_POST['SaveMultiSelectWindow']) && $this->dialog instanceof target_list_users){
194       if($this->acl_is_writeable("sudoUser")){
195         foreach($this->dialog->save() as $entry){
196           if(in_array("posixGroup",$entry['objectClass'])){
197             $name = trim("%".$entry['cn'][0]);
198           }else{
199             $name = trim($entry['uid'][0]);
200           }
201           if(!in_array($name,$this->sudoUser) && !in_array("!".$name,$this->sudoUser)){
202             $this->sudoUser[] = $name;
203           }
204         }   
205       }
206       unset($this->dialog);
207       $this->dialog = NULL;
208     }    
211     /*********************
212        Add systems 
213      *********************/ 
214   
215     if(isset($_POST['list_sudoHost']) && !is_object($this->dialog) && $this->acl_is_writeable("sudoHost")){
216       $used = array();
217       foreach($this->sudoHost as $name){
218         $used[] = preg_replace("/^!/","",$name);
219       }
220       $this->dialog =new target_list_systems($this->config,$used);
221     }
222    
223     /* Add selected hosts  to the sudoHost list */ 
224     if(isset($_POST['SaveMultiSelectWindow']) && $this->dialog instanceof target_list_systems){
225       if($this->acl_is_writeable("sudoHost")){
226         foreach($this->dialog->save() as $entry){
227           $cn = trim($entry['cn'][0]);
228           if(!in_array($cn,$this->sudoHost) && !in_array("!".$cn,$this->sudoHost)){
229             $this->sudoHost[] = $cn;
230           }
231         }   
232       }   
233       unset($this->dialog);
234       $this->dialog = NULL;
235     }    
238     /*********************
239        Dialog handling / display / close  
240      *********************/ 
241   
242     if(isset($_POST['CloseMultiSelectWindow']) && is_object($this->dialog)){
243       unset($this->dialog);
244       $this->dialog = NULL;
245     }    
247     if(is_object($this->dialog)){
248       return($this->dialog->execute());
249     }
251  
252     /*********************
253        NEGATE values 
254      *********************/ 
255     foreach($_POST as $name => $value){
256       if(preg_match("/^neg_/",$name)){
257         $attr = preg_replace("/^neg_([^_]*)_.*$/","\\1",$name);
258         $value= preg_replace("/^neg_[^_]*_([0-9]*)_.*$/","\\1",$name);
259  
260         if($this->acl_is_writeable($attr)){
261           $attrs = $this->$attr;
262           if(isset( $attrs[$value])){
263             $v =  $attrs[$value];
264             if(preg_match("/^!/",$v)){
265               $attrs[$value] = preg_replace("/^!/","",$v);
266             }else{
267               $attrs[$value] = "!".$v;
268             }
269             $this->$attr = $attrs;  
270           }
271         }
272         break; // Do it once, image inputs will be posted twice
273       }
274     }
275   
276     /*********************
277        Delete values 
278      *********************/ 
279     foreach($_POST as $name => $value){
280       if(preg_match("/^del_/",$name)){
281         $attr = preg_replace("/^del_([^_]*)_.*$/","\\1",$name);
282         $value= preg_replace("/^del_[^_]*_([0-9]*)_.*$/","\\1",$name);
283         if($this->acl_is_writeable($attr)){
284           $attrs = $this->$attr;
285           if(isset( $attrs[$value])){
286             unset($attrs[$value]);
287             $this->$attr = $attrs;  
288           }
289         }
290         break; // Do it once, image inputs will be posted twice
291       }
292     }
295     /*********************
296        ADD values 
297      *********************/
299     /* User / Host / Runas */ 
300     foreach(array("sudoUser","sudoHost","sudoRunAs") as $attr){
301       if($this->acl_is_writeable($attr) && 
302           isset($_POST["add_".$attr]) && 
303           isset($_POST['new_'.$attr]) && 
304           !empty($_POST['new_'.$attr])){
305         if(preg_match("/^[a-z\.0-9]*$/i",$_POST['new_'.$attr])){
306           $attrs = $this->$attr;
307           $attrs[] =  trim($_POST['new_'.$attr]); 
308           $this->$attr = $attrs;
309         }else{
310           msg_dialog::display(_("Error"),msgPool::invalid($attr,$_POST['new_'.$attr],"/[a-z0-9]/"));
311         }
312       }
313     }
315     /* Command */
316     foreach(array("sudoCommand") as $attr){
317       if($this->acl_is_writeable($attr) && isset($_POST["add_".$attr]) && isset($_POST['new_'.$attr])){
318         $attrs = $this->$attr;
319         $attrs[] =  trim($_POST['new_'.$attr]); 
320         $this->$attr = $attrs;
321       }
322     }
324     
325     /*********************
326        SMARTY assignments 
327      *********************/
329     $smarty = get_smarty();
330     $smarty->assign("is_default",$this->is_default);
331     foreach($this->attributes as $attr){
332       if(is_string($this->$attr)){
333         $smarty->assign($attr,htmlentities($this->$attr));
334       }else{
335         $smarty->assign($attr,$this->$attr);
336       }
337       $smarty->assign($attr."ACL",$this->getacl($attr));
338     }
340     /* Work on trust modes */
341     $smarty->assign("trusthide", " disabled ");
342     if ($this->trustModel == "fullaccess"){
343       $trustmode= 1;
344     } elseif ($this->trustModel == "byhost"){
345       $trustmode= 2;
346       $smarty->assign("trusthide", "");
347     } else {
348       $trustmode= 0;
349     }
350     $smarty->assign("trustmode", $trustmode);
351     $smarty->assign("trustmodes", array( 
352           0 => _("disabled"), 
353           1 => _("full access"),
354           2 => _("allow access to these hosts")));
356     if((count($this->accessTo))==0){
357       $smarty->assign("emptyArrAccess",true);
358     }else{
359       $smarty->assign("emptyArrAccess",false);
360     }
361     $smarty->assign("workstations", $this->accessTo);
362     
363     /* Create lists 
364      */
365     $divlist_sudoUser = new divSelectBox("divlist_sudoUser");
366     $divlist_sudoUser->SetHeight("90");
367     $divlist_sudoHost = new divSelectBox("divlist_sudoHost");
368     $divlist_sudoHost->Setheight("90");
369     $divlist_sudoRunAs = new divSelectBox("divlist_sudoRunAs");
370     $divlist_sudoRunAs->Setheight("90");
371     $divlist_sudoCommand = new divSelectBox("divlist_sudoCommand");
372     $divlist_sudoCommand->Setheight("90");
374     /* Fill divlists
375      */
376     $neg_img= "<img src='images/negate.png' alt='!' class='center'>"; 
377     $option = "<input type='image' src='images/negate.png'     name='neg_%ATTR%_%KEY%' class='center'>"; 
378     $option.= "<input type='image' src='images/edittrash.png'  name='del_%ATTR%_%KEY%' class='center'>"; 
379     foreach(array("sudoCommand","sudoHost","sudoRunAs") as $attr){
380       if($this->acl_is_readable($attr)){
381         foreach($this->$attr as $key => $entry){
382           $neg = "";
383           if(preg_match("/^!/",$entry)){
384             $neg = $neg_img;
385           }
386           $entry = preg_replace("/^!/","",$entry);
387           $list_name = "divlist_".$attr;
388           $$list_name->AddEntry(
389               array(
390                 array("string" => $neg,"attach" => "style='width:18px;'"),
391                 array("string" => $entry),
392                 array("string" => preg_replace(array("/%KEY%/","/%ATTR%/"),array($key,$attr),$option),
393                   "attach" => "style='width:40px; border-right: 0px;'")));
394         }
395       }
396     }
398     foreach(array("sudoUser") as $attr){
399       $img1 = "<img src='images/select_user.png'   alt='"._("User")."' class='center'>";
400       $img2 = "<img src='images/select_groups.png' alt='"._("Group")."' class='center'>";
401       if($this->acl_is_readable($attr)){
402         foreach($this->$attr as $key => $entry){
403           $neg = "";
404           if(preg_match("/^!/",$entry)){
405             $neg = $neg_img;
406           }
407           $entry = preg_replace("/^!/","",$entry);
409           $img = $img1;
410           if(preg_match("/^%/",$entry)){
411             $img = $img2;
412           }
413           $entry = preg_replace("/^%/","",$entry);
414   
415           $list_name = "divlist_".$attr;
416           $$list_name->AddEntry(
417               array(
418                 array("string" => $neg,"attach" => "style='width:18px;'"),
419                 array("string" => $img,"attach" => "style='width:18px;'"),
420                 array("string" => $entry),
421                 array("string" => preg_replace(array("/%KEY%/","/%ATTR%/"),array($key,$attr),$option),
422                   "attach" => "style='width:40px; border-right: 0px;'")));
423         }
424       }
425     }
430     /* Tell smarty about our divlists 
431      */
432     $smarty->assign("divlist_sudoUser",   $divlist_sudoUser->DrawList());
433     $smarty->assign("divlist_sudoHost",   $divlist_sudoHost->DrawList());
434     $smarty->assign("divlist_sudoRunAs",  $divlist_sudoRunAs->DrawList());
435     $smarty->assign("divlist_sudoCommand",$divlist_sudoCommand->DrawList());
436     return($smarty->fetch(get_template_path('generic.tpl', TRUE)));
437   }
440   /*! \brief  Remove this sudo role from the ldap server 
441    */
442   function remove_from_parent()
443   {
444     plugin::remove_from_parent();
446     $ldap = $this->config->get_ldap_link();
447     $ldap->cd($this->dn);
448     $ldap->rmdir($this->dn);
450     /* Send signal to the world that we've done */
451     $this->handle_post_events("remove");
452   }
455   /*! \brief  Save all relevant HTML posts. 
456    */
457   function save_object()
458   {
459     plugin::save_object();
460     
461     if($this->is_default){
462       $this->cn = "defaults";
463     }  
465     if(is_object($this->dialog)){
466       $this->dialog->save_object();
467     }
469     /* Trust mode - special handling */
470     if($this->acl_is_writeable("trustModel")){
471       if (isset($_POST['trustmode'])){
472         $saved= $this->trustModel;
473         if ($_POST['trustmode'] == "1"){
474           $this->trustModel= "fullaccess";
475         } elseif ($_POST['trustmode'] == "2"){
476           $this->trustModel= "byhost";
477         } else {
478           $this->trustModel= "";
479         }
480         if ($this->trustModel != $saved){
481           $this->is_modified= TRUE;
482         }
483       }
484     }
485   }
488   /*! \brief  Save changes into the ldap database.
489    */
490   function save()
491   {
492     plugin::save();
493    /* Trust accounts */
494     $objectclasses= array();
495     foreach ($this->attrs['objectClass'] as $key => $class){
496       if (preg_match('/trustAccount/i', $class)){
497         continue;
498       }
499       $objectclasses[]= $this->attrs['objectClass'][$key];
500     }
502     $this->attrs['objectClass']= $objectclasses;
503     if ($this->trustModel != ""){
504       $this->attrs['objectClass'][]= "trustAccount";
505       $this->attrs['trustModel']= $this->trustModel;
506       $this->attrs['accessTo']= array();
507       if ($this->trustModel == "byhost"){
508         foreach ($this->accessTo as $host){
509           $this->attrs['accessTo'][]= $host;
510         }
511       }
512     } else {
513       if ($this->was_trust_account){
514         $this->attrs['accessTo']= array();
515         $this->attrs['trustModel']= array();
516       }
517     }
520     /* Ensure a correct array index 
521      */ 
522     $this->attrs['sudoHost']    = array_values($this->attrs['sudoHost']);
523     $this->attrs['sudoRunAs']   = array_values($this->attrs['sudoRunAs']);
524     $this->attrs['sudoUser']    = array_values($this->attrs['sudoUser']);
525     $this->attrs['sudoCommand'] = array_values($this->attrs['sudoCommand']);
527     $this->cleanup();
529     $ldap = $this->config->get_ldap_link();
530     $ldap->cd($this->config->current['BASE']);
531     if($this->is_new){
532       $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $this->dn));
533       $ldap->cd($this->dn);
534       $ldap->add($this->attrs);
536       /* Send signal to the world that we've done */
537       $this->handle_post_events("create");
538     }else{
539       $ldap->cd($this->dn);
540       $ldap->modify($this->attrs);;
542       /* Send signal to the world that we've done */
543       $this->handle_post_events("modify");
544     }
546     if (!$ldap->success()){
547       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
548     }
549   }
552   /*! \brief  Check the given input.
553       @return Array   All error messages in an array();
554    */
555   function check()
556   {
557     $message = plugin::check();
559     /* Is a name given? */
560     if(empty($this->cn)){
561       $message[] = msgPool::required(_("Name"));
562     }
564     /* Check if name is reserved */
565     if(!$this->is_default && preg_match("/^defaults$/i",$this->cn)){
566       $message[] = msgPool::reserved(_("Name"));
567     }
569     /* Check name */
570     if(!preg_match("/^[a-z\@]*$/i",$this->cn)){
571       $message[] = msgPool::invalid(_("Name"),$this->cn,"/[a-z\@]/i");
572     }
574     /* Check if this entry will cause duplicated ldap entries */
575     $ldap = $this->config->get_ldap_link();
576     $ldap->cd($this->get_sudoers_ou($this->config));
577     $ldap->search("(&(objectClass=sudoRole)(cn=".$this->cn."))");
578     while($attrs = $ldap->fetch()){
579       if($attrs['dn'] != $this->dn){
580         $message[] = msgPool::duplicated(_("Name"));
581       }
582     }
584     return ($message);
585   }
588   /*! \brief  Display the System Trust Add Workstation dialog 
589     @return String  HTML dialog to add a system to the trust list.
591    */
592   private function display_trust_add_dialog()
593   {
594     $smarty = get_smarty();
596     /* Save data */
597     $sysfilter= session::get("sysfilter");
598     foreach( array("depselect", "regex") as $type){
599       if (isset($_POST[$type])){
600         $sysfilter[$type]= $_POST[$type];
601       }
602     }
603     if (isset($_GET['search'])){
604       $s= mb_substr($_GET['search'], 0, 1, "UTF8")."*";
605       if ($s == "**"){
606         $s= "*";
607       }
608       $sysfilter['regex']= $s;
609     }
610     session::set("sysfilter", $sysfilter);
612     /* Get workstation list */
613     $exclude= "";
614     foreach($this->accessTo as $ws){
615       $exclude.= "(cn=$ws)";
616     }
617     if ($exclude != ""){
618       $exclude= "(!(|$exclude))";
619     }
620     $regex= $sysfilter['regex'];
621     $filter= "(&(|(objectClass=goServer)(objectClass=gotoWorkstation)(objectClass=gotoTerminal))$exclude(cn=*)(cn=$regex))";
623     $res = array();
624     $res= array_merge($res,get_sub_list($filter, array("terminal"), get_ou("terminalou"),
625         get_ou("systemsou").$sysfilter['depselect'],          array("cn"), GL_SUBSEARCH | GL_SIZELIMIT));
626     $res= array_merge($res,get_sub_list($filter, array("server"), get_ou("serverou"), 
627         get_ou("systemsou").$sysfilter['depselect'],          array("cn"), GL_SUBSEARCH | GL_SIZELIMIT));
628     $res= array_merge($res,get_sub_list($filter, array("workstation"), get_ou("workstationou"),
629         get_ou("systemsou").$sysfilter['depselect'],          array("cn"), GL_SUBSEARCH | GL_SIZELIMIT));
631     $wslist= array();
632     foreach ($res as $attrs){
633       $wslist[]= preg_replace('/\$/', '', $attrs['cn'][0]);
634     }
635     asort($wslist);
636     foreach( array("depselect","regex") as $type){
637       $smarty->assign("$type", $sysfilter[$type]);
638     }
639     $smarty->assign("search_image", get_template_path('images/search.png'));
640     $smarty->assign("launchimage",  get_template_path('images/small_filter.png'));
641     $smarty->assign("tree_image",   get_template_path('images/tree.png'));
642     $smarty->assign("deplist",      $this->config->idepartments);
643     $smarty->assign("alphabet",     generate_alphabet());
644     $smarty->assign("hint",         print_sizelimit_warning());
645     $smarty->assign("wslist",       $wslist);
646     $smarty->assign("apply",        apply_filter());
647     $display= $smarty->fetch (get_template_path('trust_machines.tpl', TRUE, dirname(__FILE__)));
648     return ($display);
649   }
652   /*! \brief Force this entry to be handled and saved as 'default'
653       @param  BOOL  TRUE -force defaults   FALSE -normal
654    */
655   public function set_default($state)
656   {
657     $this->is_default = TRUE;
658     $this->cn = "defaults";
659   }
662   /*! \brief  Add ACL object
663       @return Returns the ACL object.
664    */
665   static function plInfo()
666   {
667     return (array(  
668           "plShortName" => _("Sudo"),
669           "plDescription" => _("Sudo role"),
670           "plSelfModify"  => FALSE,
671           "plDepends"     => array(),
672           "plPriority"    => 0,
673           "plSection"     => array("admin"),
674           "plCategory"    => array("sudo" => array("objectClass" => "sudoRole", "description" => _("Sudo role"))),
676           "plProvidedAcls"    => array(
677             "cn"                => _("Name"),
678             "description"       => _("Description"),
679             "sudoUser"          => _("Users"),
680             "sudoHost"          => _("Host"),
681             "sudoCommand"       => _("Command"),
682             "sudoRunAs"         => _("Run as user"),
683             "trustModel"        => _("Access control list"))
684         ));
685   }
687 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
688 ?>