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;
42   var $objectclasses = array("top","sudoRole");
43   var $attributes    = array("cn","description","sudoUser","sudoCommand","sudoHost","sudoRunAs","accessTo","trustModel");
45   var $is_account = TRUE;
46   var $is_default = FALSE;
47   var $dialog;
49   /*! \brief  Returns to the base department for sudo roles.
50               This department is then used to store new roles.
51       @param  Object  GOsa configuration object.
52       @return String sudo store department
53    */
54   public static function get_sudoers_ou($config)
55   {
56     /***
57       GET sudo base
58      ***/
59     $base ="";
60     if(empty($base)){
61       /* Default is ou=sudoers,BASE */
62       $base = "ou=sudoers,".$config->current['BASE'];
63     }else{
65       /* Append base to given sudoers ou if missing */
66       if(!preg_match("/".normalizePreg($config->current['BASE'])."$/i",$base)){
67         if(!preg_match("/,$/",$base)){
68           $base = $base.",".$config->current['BASE'];
69         }else{
70           $base = $base.$config->current['BASE'];
71         }
72       }
73     }
74     return($base);
75   }
77   /*! \brief  Initializes this sudo class, with all required attributes.
78       @param  Object $config  GOsa configuration object.
79       @param  String $db      "new" or the sudo role dn.
80       @return .
81    */
82   function sudo(&$config, $dn= NULL)
83   {
84     plugin::plugin ($config, $dn);
86     if($this->initially_was_account){
87       foreach(array("sudoUser","sudoCommand","sudoHost","sudoRunAs") as $attr){
88         $this->$attr = array();
89         if(isset($this->attrs[$attr])){
90           $tmp = array();
91           for($i = 0 ; $i < $this->attrs[$attr]['count']; $i++){
92             $tmp[] = $this->attrs[$attr][$i];
93           }
94           $this->$attr = $tmp;
95         }
96       }
98       /* Is this account a trustAccount? */
99       if ($this->is_account && isset($this->attrs['trustModel'])){
100         $this->trustModel= $this->attrs['trustModel'][0];
101         $this->was_trust_account= TRUE;
102       } else {
103         $this->was_trust_account= FALSE;
104         $this->trustModel= "";
105       }
107       $this->accessTo = array();
108       if ($this->is_account && isset($this->attrs['accessTo'])){
109         for ($i= 0; $i<$this->attrs['accessTo']['count']; $i++){
110           $tmp= $this->attrs['accessTo'][$i];
111           $this->accessTo[$tmp]= $tmp;
112         }
113       }
115     }
117     if(preg_match("/^default$/i",$this->cn)){
118       $this->is_default = TRUE;
119     }
121     /* Get global filter config */
122     if (!session::is_set("sysfilter")){
123       $ui= get_userinfo();
124       $base= get_base_from_people($ui->dn);
125       $sysfilter= array( "depselect"       => $base,
126           "regex"           => "*");
127       session::set("sysfilter", $sysfilter);
128     }
129   }
132   /*! \brief  Creates the sudo generic ui. 
133       @return String  The generated HTML content for this plugin. 
134    */
135   function execute()
136   {
137     /* Call parent execute */
138     plugin::execute();
140     /*********************
141        Access control list / trust mode 
142      *********************/ 
144     /* Add user workstation? */
145     if (isset($_POST["add_ws"])){
146       $this->show_ws_dialog= TRUE;
147       $this->dialog= TRUE;
148     }
150     /* Add user workstation? */
151     if (isset($_POST["add_ws_finish"]) && isset($_POST['wslist'])){
152       foreach($_POST['wslist'] as $ws){
153         $this->accessTo[$ws]= $ws;
154       }
155       ksort($this->accessTo);
156       $this->is_modified= TRUE;
157     }
159     /* Remove user workstations? */
160     if (isset($_POST["delete_ws"]) && isset($_POST['workstation_list'])){
161       foreach($_POST['workstation_list'] as $name){
162         unset ($this->accessTo[$name]);
163       }
164       $this->is_modified= TRUE;
165     }
167     /* Add user workstation finished? */
168     if (isset($_POST["add_ws_finish"]) || isset($_POST["add_ws_cancel"])){
169       $this->show_ws_dialog= FALSE;
170       $this->dialog= FALSE;
171     }
173     /* Show ws dialog */
174     if ($this->show_ws_dialog){
175       return($this->display_trust_add_dialog());
176     }
179     /*********************
180        Add users 
181      *********************/ 
182   
183     if(isset($_POST['list_sudoUser']) && !is_object($this->dialog) && $this->acl_is_writeable("sudoUser")){
184       $used = array();
185       foreach($this->sudoUser as $name){
186         $used[] = preg_replace("/^!/","",$name);
187       }
188       $this->dialog =new target_list_users($this->config,$used);
189     }
190    
191     /* Add selected hosts  to the sudoUser list */ 
192     if(isset($_POST['SaveMultiSelectWindow']) && $this->dialog instanceof target_list_users){
193       if($this->acl_is_writeable("sudoUser")){
194         foreach($this->dialog->save() as $entry){
195           $cn = trim($entry['uid'][0]);
196           if(!in_array($cn,$this->sudoUser) && !in_array("!".$cn,$this->sudoUser)){
197             $this->sudoUser[] = $cn;
198           }
199         }   
200       }
201       unset($this->dialog);
202       $this->dialog = NULL;
203     }    
206     /*********************
207        Add systems 
208      *********************/ 
209   
210     if(isset($_POST['list_sudoHost']) && !is_object($this->dialog) && $this->acl_is_writeable("sudoHost")){
211       $used = array();
212       foreach($this->sudoHost as $name){
213         $used[] = preg_replace("/^!/","",$name);
214       }
215       $this->dialog =new target_list_systems($this->config,$used);
216     }
217    
218     /* Add selected hosts  to the sudoHost list */ 
219     if(isset($_POST['SaveMultiSelectWindow']) && $this->dialog instanceof target_list_systems){
220       if($this->acl_is_writeable("sudoHost")){
221         foreach($this->dialog->save() as $entry){
222           $cn = trim($entry['cn'][0]);
223           if(!in_array($cn,$this->sudoHost) && !in_array("!".$cn,$this->sudoHost)){
224             $this->sudoHost[] = $cn;
225           }
226         }   
227       }   
228       unset($this->dialog);
229       $this->dialog = NULL;
230     }    
233     /*********************
234        Dialog handling / display / close  
235      *********************/ 
236   
237     if(isset($_POST['CloseMultiSelectWindow']) && is_object($this->dialog)){
238       unset($this->dialog);
239       $this->dialog = NULL;
240     }    
242     if(is_object($this->dialog)){
243       return($this->dialog->execute());
244     }
246  
247     /*********************
248        NEGATE values 
249      *********************/ 
250     foreach($_POST as $name => $value){
251       if(preg_match("/^neg_/",$name)){
252         $attr = preg_replace("/^neg_([^_]*)_.*$/","\\1",$name);
253         $value= preg_replace("/^neg_[^_]*_([0-9]*)_.*$/","\\1",$name);
254  
255         if($this->acl_is_writeable($attr)){
256           $attrs = $this->$attr;
257           if(isset( $attrs[$value])){
258             $v =  $attrs[$value];
259             if(preg_match("/^!/",$v)){
260               $attrs[$value] = preg_replace("/^!/","",$v);
261             }else{
262               $attrs[$value] = "!".$v;
263             }
264             $this->$attr = $attrs;  
265           }
266         }
267         break; // Do it once, image inputs will be posted twice
268       }
269     }
270   
271     /*********************
272        Delete values 
273      *********************/ 
274     foreach($_POST as $name => $value){
275       if(preg_match("/^del_/",$name)){
276         $attr = preg_replace("/^del_([^_]*)_.*$/","\\1",$name);
277         $value= preg_replace("/^del_[^_]*_([0-9]*)_.*$/","\\1",$name);
278         if($this->acl_is_writeable($attr)){
279           $attrs = $this->$attr;
280           if(isset( $attrs[$value])){
281             unset($attrs[$value]);
282             $this->$attr = $attrs;  
283           }
284         }
285         break; // Do it once, image inputs will be posted twice
286       }
287     }
290     /*********************
291        ADD values 
292      *********************/
294     /* User / Host / Runas */ 
295     foreach(array("sudoUser","sudoHost","sudoRunAs") as $attr){
296       if($this->acl_is_writeable($attr) && 
297           isset($_POST["add_".$attr]) && 
298           isset($_POST['new_'.$attr]) && 
299           !empty($_POST['new_'.$attr])){
300         if(preg_match("/^[a-z\.0-9]*$/i",$_POST['new_'.$attr])){
301           $attrs = $this->$attr;
302           $attrs[] =  trim($_POST['new_'.$attr]); 
303           $this->$attr = $attrs;
304         }else{
305           msg_dialog::display(_("Error"),msgPool::invalid($attr,$_POST['new_'.$attr],"/[a-z0-9]/"));
306         }
307       }
308     }
310     /* Command */
311     foreach(array("sudoCommand") as $attr){
312       if($this->acl_is_writeable($attr) && isset($_POST["add_".$attr]) && isset($_POST['new_'.$attr])){
313         $attrs = $this->$attr;
314         $attrs[] =  trim($_POST['new_'.$attr]); 
315         $this->$attr = $attrs;
316       }
317     }
319     
320     /*********************
321        SMARTY assignments 
322      *********************/
324     $smarty = get_smarty();
325     $smarty->assign("is_default",$this->is_default);
326     foreach($this->attributes as $attr){
327       $smarty->assign($attr,$this->$attr);
328       $smarty->assign($attr."ACL",$this->getacl($attr));
329     }
331     /* Work on trust modes */
332     $smarty->assign("trusthide", " disabled ");
333     if ($this->trustModel == "fullaccess"){
334       $trustmode= 1;
335     } elseif ($this->trustModel == "byhost"){
336       $trustmode= 2;
337       $smarty->assign("trusthide", "");
338     } else {
339       $trustmode= 0;
340     }
341     $smarty->assign("trustmode", $trustmode);
342     $smarty->assign("trustmodes", array( 
343           0 => _("disabled"), 
344           1 => _("full access"),
345           2 => _("allow access to these hosts")));
347     if((count($this->accessTo))==0){
348       $smarty->assign("emptyArrAccess",true);
349     }else{
350       $smarty->assign("emptyArrAccess",false);
351     }
352     $smarty->assign("workstations", $this->accessTo);
353     
354     /* Create lists 
355      */
356     $divlist_sudoUser = new divSelectBox("divlist_sudoUser");
357     $divlist_sudoUser->SetHeight("90");
358     $divlist_sudoHost = new divSelectBox("divlist_sudoHost");
359     $divlist_sudoHost->Setheight("90");
360     $divlist_sudoRunAs = new divSelectBox("divlist_sudoRunAs");
361     $divlist_sudoRunAs->Setheight("90");
362     $divlist_sudoCommand = new divSelectBox("divlist_sudoCommand");
363     $divlist_sudoCommand->Setheight("90");
365     /* Fill divlists
366      */
367     $neg_img= "<img src='images/negate.png' alt='!' class='center'>"; 
368     $option = "<input type='image' src='images/negate.png'     name='neg_%ATTR%_%KEY%' class='center'>"; 
369     $option.= "<input type='image' src='images/edittrash.png'  name='del_%ATTR%_%KEY%' class='center'>"; 
370     foreach(array("sudoUser","sudoCommand","sudoHost","sudoRunAs") as $attr){
371       if($this->acl_is_readable($attr)){
372         foreach($this->$attr as $key => $entry){
373           $entry = preg_replace("/^!/",$neg_img,$entry);
374           $list_name = "divlist_".$attr;
375           $$list_name->AddEntry(
376               array(
377                 array("string" => $entry),
378                 array("string" => preg_replace(array("/%KEY%/","/%ATTR%/"),array($key,$attr),$option),
379                   "attach" => "style='width:40px; border-right: 0px;'")));
380         }
381       }
382     }
384     /* Tell smarty about our divlists 
385      */
386     $smarty->assign("divlist_sudoUser",   $divlist_sudoUser->DrawList());
387     $smarty->assign("divlist_sudoHost",   $divlist_sudoHost->DrawList());
388     $smarty->assign("divlist_sudoRunAs",  $divlist_sudoRunAs->DrawList());
389     $smarty->assign("divlist_sudoCommand",$divlist_sudoCommand->DrawList());
390     return($smarty->fetch(get_template_path('generic.tpl', TRUE)));
391   }
394   /*! \brief  Remove this sudo role from the ldap server 
395    */
396   function remove_from_parent()
397   {
398     plugin::remove_from_parent();
400     $ldap = $this->config->get_ldap_link();
401     $ldap->cd($this->dn);
402     $ldap->rmdir($this->dn);
404     /* Send signal to the world that we've done */
405     $this->handle_post_events("remove");
406   }
409   /*! \brief  Save all relevant HTML posts. 
410    */
411   function save_object()
412   {
413     plugin::save_object();
415     if(is_object($this->dialog)){
416       $this->dialog->save_object();
417     }
419     /* Trust mode - special handling */
420     if($this->acl_is_writeable("trustModel")){
421       if (isset($_POST['trustmode'])){
422         $saved= $this->trustModel;
423         if ($_POST['trustmode'] == "1"){
424           $this->trustModel= "fullaccess";
425         } elseif ($_POST['trustmode'] == "2"){
426           $this->trustModel= "byhost";
427         } else {
428           $this->trustModel= "";
429         }
430         if ($this->trustModel != $saved){
431           $this->is_modified= TRUE;
432         }
433       }
434     }
435   }
438   /*! \brief  Save changes into the ldap database.
439    */
440   function save()
441   {
442     plugin::save();
443    /* Trust accounts */
444     $objectclasses= array();
445     foreach ($this->attrs['objectClass'] as $key => $class){
446       if (preg_match('/trustAccount/i', $class)){
447         continue;
448       }
449       $objectclasses[]= $this->attrs['objectClass'][$key];
450     }
452     $this->attrs['objectClass']= $objectclasses;
453     if ($this->trustModel != ""){
454       $this->attrs['objectClass'][]= "trustAccount";
455       $this->attrs['trustModel']= $this->trustModel;
456       $this->attrs['accessTo']= array();
457       if ($this->trustModel == "byhost"){
458         foreach ($this->accessTo as $host){
459           $this->attrs['accessTo'][]= $host;
460         }
461       }
462     } else {
463       if ($this->was_trust_account){
464         $this->attrs['accessTo']= array();
465         $this->attrs['trustModel']= array();
466       }
467     }
470     /* Ensure a correct array index 
471      */ 
472     $this->attrs['sudoHost']    = array_values($this->attrs['sudoHost']);
473     $this->attrs['sudoRunAs']   = array_values($this->attrs['sudoRunAs']);
474     $this->attrs['sudoUser']    = array_values($this->attrs['sudoUser']);
475     $this->attrs['sudoCommand'] = array_values($this->attrs['sudoCommand']);
476     $this->cleanup();
478     $ldap = $this->config->get_ldap_link();
479     $ldap->cd($this->config->current['BASE']);
480     if($this->is_new){
481       $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $this->dn));
482       $ldap->cd($this->dn);
483       $ldap->add($this->attrs);
485       /* Send signal to the world that we've done */
486       $this->handle_post_events("create");
487     }else{
488       $ldap->cd($this->dn);
489       $ldap->modify($this->attrs);;
491       /* Send signal to the world that we've done */
492       $this->handle_post_events("modify");
493     }
495     if (!$ldap->success()){
496       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
497     }
498   }
501   /*! \brief  Check the given input.
502       @return Array   All error messages in an array();
503    */
504   function check()
505   {
506     $message = plugin::check();
508     /* Is a name given? */
509     if(empty($this->cn)){
510       $message[] = msgPool::required(_("Name"));
511     }
513     /* Check name */
514     if(!preg_match("/^[a-z]*$/i",$this->cn)){
515       $message[] = msgPool::invalid(_("Name"),$this->cn,"/[a-z]/i");
516     }
518     /* Check if this entry will cause duplicated ldap entries */
519     $ldap = $this->config->get_ldap_link();
520     $ldap->cd($this->get_sudoers_ou($this->config));
521     $ldap->search("(&(objectClass=sudoRole)(cn=".$this->cn."))");
522     while($attrs = $ldap->fetch()){
523       if($attrs['dn'] != $this->dn){
524         $message[] = msgPool::duplicated(_("Name"));
525       }
526     }
528     return ($message);
529   }
532   /*! \brief  Display the System Trust Add Workstation dialog 
533     @return String  HTML dialog to add a system to the trust list.
535    */
536   private function display_trust_add_dialog()
537   {
538     $smarty = get_smarty();
540     /* Save data */
541     $sysfilter= session::get("sysfilter");
542     foreach( array("depselect", "regex") as $type){
543       if (isset($_POST[$type])){
544         $sysfilter[$type]= $_POST[$type];
545       }
546     }
547     if (isset($_GET['search'])){
548       $s= mb_substr($_GET['search'], 0, 1, "UTF8")."*";
549       if ($s == "**"){
550         $s= "*";
551       }
552       $sysfilter['regex']= $s;
553     }
554     session::set("sysfilter", $sysfilter);
556     /* Get workstation list */
557     $exclude= "";
558     foreach($this->accessTo as $ws){
559       $exclude.= "(cn=$ws)";
560     }
561     if ($exclude != ""){
562       $exclude= "(!(|$exclude))";
563     }
564     $regex= $sysfilter['regex'];
565     $filter= "(&(|(objectClass=goServer)(objectClass=gotoWorkstation)(objectClass=gotoTerminal))$exclude(cn=*)(cn=$regex))";
567     $res = array();
568     $res= array_merge($res,get_sub_list($filter, array("terminal"), get_ou("terminalou"),
569         get_ou("systemsou").$sysfilter['depselect'],          array("cn"), GL_SUBSEARCH | GL_SIZELIMIT));
570     $res= array_merge($res,get_sub_list($filter, array("server"), get_ou("serverou"), 
571         get_ou("systemsou").$sysfilter['depselect'],          array("cn"), GL_SUBSEARCH | GL_SIZELIMIT));
572     $res= array_merge($res,get_sub_list($filter, array("workstation"), get_ou("workstationou"),
573         get_ou("systemsou").$sysfilter['depselect'],          array("cn"), GL_SUBSEARCH | GL_SIZELIMIT));
575     $wslist= array();
576     foreach ($res as $attrs){
577       $wslist[]= preg_replace('/\$/', '', $attrs['cn'][0]);
578     }
579     asort($wslist);
580     foreach( array("depselect","regex") as $type){
581       $smarty->assign("$type", $sysfilter[$type]);
582     }
583     $smarty->assign("search_image", get_template_path('images/search.png'));
584     $smarty->assign("launchimage",  get_template_path('images/small_filter.png'));
585     $smarty->assign("tree_image",   get_template_path('images/tree.png'));
586     $smarty->assign("deplist",      $this->config->idepartments);
587     $smarty->assign("alphabet",     generate_alphabet());
588     $smarty->assign("hint",         print_sizelimit_warning());
589     $smarty->assign("wslist",       $wslist);
590     $smarty->assign("apply",        apply_filter());
591     $display= $smarty->fetch (get_template_path('trust_machines.tpl', TRUE, dirname(__FILE__)));
592     return ($display);
593   }
596   /*! \brief  Add ACL object
597       @return Returns the ACL object.
598    */
599   static function plInfo()
600   {
601     return (array(  
602           "plShortName" => _("Sudo"),
603           "plDescription" => _("Sudo role"),
604           "plSelfModify"  => FALSE,
605           "plDepends"     => array(),
606           "plPriority"    => 0,
607           "plSection"     => array("admin"),
608           "plCategory"    => array("sudo" => array("objectClass" => "sudoRole", "description" => _("Sudo role"))),
610           "plProvidedAcls"    => array(
611             "cn"                => _("Name"),
612             "description"       => _("Description"),
613             "sudoUser"          => _("Users"),
614             "sudoHost"          => _("Host"),
615             "sudoCommand"       => _("Command"),
616             "sudoRunAs"         => _("Run as user"),
617             "trustModel"        => _("Access control list"))
618         ));
619   }
621 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
622 ?>