Code

Updated sudo
[gosa.git] / gosa-plugins / sudo / admin / sudo / class_sudoOption.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 option class.
25             Allows setting flags/options for a sudo role.
26  */
27 class sudoOption extends plugin
28 {
29   /* Group attributes */
30   var $sudoOption = array();
31   var $attributes    = array("sudoOption");
32   var $is_account = TRUE;
33   var $options = array();
35   /*! \brief  Initializes this class
36         @param  Object $config  The GOsa configuration object.
37         @param  String $dn      The object dn.
38    */
39   function sudoOption(&$config, $dn= NULL)
40   {
41     plugin::plugin ($config, $dn);
43     /****
44       Create a list of known options
45      ****/
46     $options = array();
47     $option['long_otp_prompt']= array('NAME' =>'long_otp_prompt' ,   'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
48     $option['ignore_dot']=  array('NAME' =>'ignore_dot' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
49     $option['mail_always']= array('NAME' =>'mail_always' ,   'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
50     $option['mail_badpass']=  array('NAME' =>'mail_badpass' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
51     $option['mail_no_user']=  array('NAME' =>'mail_no_user' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
52     $option['mail_no_host']=  array('NAME' =>'mail_no_host' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
53     $option['mail_no_perms']= array('NAME' =>'mail_no_perms' ,   'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
54     $option['tty_tickets']= array('NAME' =>'tty_tickets' ,   'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
55     $option['authenticate']=  array('NAME' =>'authenticate' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
56     $option['root_sudo']= array('NAME' =>'root_sudo' ,   'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
57     $option['log_host']=  array('NAME' =>'log_host' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
58     $option['log_year']=  array('NAME' =>'log_year' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
59     $option['shell_noargs']=  array('NAME' =>'shell_noargs' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
60     $option['set_home']=  array('NAME' =>'set_home' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
61     $option['always_set_home']= array('NAME' =>'always_set_home' ,   'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
62     $option['path_info']= array('NAME' =>'path_info' ,   'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
63     $option['preserve_groups']= array('NAME' =>'preserve_groups' ,   'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
64     $option['fqdn']=  array('NAME' =>'fqdn' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
65     $option['insults']= array('NAME' =>'insults' ,   'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
66     $option['requiretty']=  array('NAME' =>'requiretty' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
67     $option['env_editor']=  array('NAME' =>'env_editor' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
68     $option['rootpw']=  array('NAME' =>'rootpw' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
69     $option['runaspw']= array('NAME' =>'runaspw' ,   'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
70     $option['targetpw']=  array('NAME' =>'targetpw' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
71     $option['set_logname']= array('NAME' =>'set_logname' ,   'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
72     $option['stay_setuid']= array('NAME' =>'stay_setuid' ,   'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
73     $option['env_reset']= array('NAME' =>'env_reset' ,   'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
74     $option['use_loginclass']=  array('NAME' =>'use_loginclass' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
75     $option['noexec']=  array('NAME' =>'noexec' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
76     $option['ignore_local_sudoers']=  array('NAME' =>'ignore_local_sudoers' ,  'TYPE' => 'BOOLEAN' ,   'DEFAULT' => 'TRUE');
77     $option['passwd_tries']=  array('NAME' =>'passwd_tries' ,  'TYPE' => 'INTEGER' ,   'DEFAULT' => 0);
78     $option['loglinelen']=  array('NAME' =>'loglinelen' ,  'TYPE' => 'BOOL_INTEGER' ,  'DEFAULT' => 0);
79     $option['timestamp_timeout']= array('NAME' =>'timestamp_timeout' ,   'TYPE' => 'BOOL_INTEGER' ,  'DEFAULT' => 0);
80     $option['passwd_timeout']=  array('NAME' =>'passwd_timeout' ,  'TYPE' => 'BOOL_INTEGER' ,  'DEFAULT' => 0);
81     $option['umask']= array('NAME' =>'umask' ,   'TYPE' => 'BOOL_INTEGER' ,  'DEFAULT' => 0);
82     $option['mailsub']= array('NAME' =>'mailsub' ,   'TYPE' => 'STRING' ,   'DEFAULT' => '');
83     $option['badpass_message']= array('NAME' =>'badpass_message' ,   'TYPE' => 'STRING' ,   'DEFAULT' => '');
84     $option['timestampdir']=  array('NAME' =>'timestampdir' ,  'TYPE' => 'STRING' ,   'DEFAULT' => '');
85     $option['timestampowner']=  array('NAME' =>'timestampowner' ,  'TYPE' => 'STRING' ,   'DEFAULT' => '');
86     $option['passprompt']=  array('NAME' =>'passprompt' ,  'TYPE' => 'STRING' ,   'DEFAULT' => '');
87     $option['runas_default']= array('NAME' =>'runas_default' ,   'TYPE' => 'STRING' ,   'DEFAULT' => '');
88     $option['syslog_goodpri']=  array('NAME' =>'syslog_goodpri' ,  'TYPE' => 'STRING' ,   'DEFAULT' => '');
89     $option['syslog_badpri']= array('NAME' =>'syslog_badpri' ,   'TYPE' => 'STRING' ,   'DEFAULT' => '');
90     $option['editor']=  array('NAME' =>'editor' ,  'TYPE' => 'STRING' ,   'DEFAULT' => '');
91     $option['noexec_file']= array('NAME' =>'noexec_file' ,   'TYPE' => 'STRING' ,   'DEFAULT' => '');
92     $option['lecture']= array('NAME' =>'lecture' ,   'TYPE' => 'STRING_BOOL' ,   'DEFAULT' => '');
93     $option['lecture_file']=  array('NAME' =>'lecture_file' ,  'TYPE' => 'STRING_BOOL' ,   'DEFAULT' => '');
94     $option['logfile']= array('NAME' =>'logfile' ,   'TYPE' => 'STRING_BOOL' ,   'DEFAULT' => '');
95     $option['syslog']=  array('NAME' =>'syslog' ,  'TYPE' => 'STRING_BOOL' ,   'DEFAULT' => '');
96     $option['mailerpath']=  array('NAME' =>'mailerpath' ,  'TYPE' => 'STRING_BOOL' ,   'DEFAULT' => '');
97     $option['mailerflags']= array('NAME' =>'mailerflags' ,   'TYPE' => 'STRING_BOOL' ,   'DEFAULT' => '');
98     $option['mailto']=  array('NAME' =>'mailto' ,  'TYPE' => 'STRING_BOOL' ,   'DEFAULT' => '');
99     $option['exempt_group']=  array('NAME' =>'exempt_group' ,  'TYPE' => 'STRING_BOOL' ,   'DEFAULT' => '');
100     $option['verifypw']=  array('NAME' =>'verifypw' ,  'TYPE' => 'STRING_BOOL' ,   'DEFAULT' => '');
101     $option['listpw']=  array('NAME' =>'listpw' ,  'TYPE' => 'STRING_BOOL' ,   'DEFAULT' => '');
102     $option['env_check']= array('NAME' =>'env_check' ,   'TYPE' => 'LISTS' ,   'DEFAULT' => '');
103     $option['env_delete']=  array('NAME' =>'env_delete' ,  'TYPE' => 'LISTS' ,   'DEFAULT' => '');
104     $option['env_keep']=  array('NAME' =>'env_keep' ,  'TYPE' => 'LISTS' ,   'DEFAULT' => '');
105     ksort($option);
106     $this->options = $option;
108     /****
109       Parse given sudoOption attributes 
110      ****/
111     $this->sudoOption = array();
112     if(isset($this->attrs['sudoOption'])){
113       for($i = 0 ; $i < $this->attrs['sudoOption']['count']; $i++){
115         /****
116           Detect attribute name/value/negation
117          ****/
118         $opt = $this->attrs['sudoOption'][$i];
120         /* Get negation */ 
121         $negation = FALSE;
122         if(preg_match("/^!/",$opt)){
123           $negation = TRUE; 
124           $opt = preg_replace("/^!/","",$opt);
125         }
127         /* Get value / name*/
128         $value    = "";
129         if(preg_match("/=/",$opt)){
130           $value  = preg_replace("/^[^=]*+=/","",$opt);
131           $opt    = preg_replace("/=.*$/","",$opt);
132         }
134         /* Special chars are escaped, remove escape char now.
135             \\ => \
136             \: => :
137             \, => ,
138             \= => = 
139          */
140         $value = preg_replace(array("/\\\\\\\\/","/\\\\,/","/\\\\:/","/\\\\=/"),
141                               array("\\",",",":","="),$value);
143         /* Check if the given value is part of our options list.
144            If it is not, add it as type STRING and display a warning.  
145         */
146         if(!isset($this->options[$opt])){
147           $this->options[$opt]=array('NAME'=>$opt,'TYPE'=>'STRING','DEFAULT' => '');
148           msg_dialog::display(_("Unknown option"),
149               sprintf(_("The sudo option '%s' is invalid!"),
150                 $opt),WARNING_DIALOG);
151         }
153         /* Create internal sudoOption object */
154         $option = array();
155         $option['NAME']   = $opt;
156         $option['VALUE']  = $value;
157         $option['NEGATE'] = $negation;
159         /*  Special handling for mixed flag types. 
160             Some attributes like (BOOL_INTEGER) can be TRUE/FALSE and INTEGER.
161             This means, if the value is empty it is BOOL and $negation defines its boolean value.
162          */
163         if(in_array($this->options[$opt]['TYPE'],array("BOOL_INTEGER","STRING_BOOL"))){
164           if(empty($value)){
165             $option['NEGATE'] = FALSE;
166             if($negation){
167               $option['VALUE'] = "FALSE";
168             }else{
169               $option['VALUE'] = "TRUE";
170             }
171           }
172         }
174         /* Special handling for BOOLEAN values */
175         if(in_array($this->options[$opt]['TYPE'],array("BOOLEAN"))){
176           $option['NEGATE'] = FALSE;
177           if($negation){
178             $option['VALUE'] = "FALSE";
179           }else{
180             $option['VALUE'] = "TRUE";
181           }
182         }
184         /* Append values */
185         $this->sudoOption[$opt][] = $option;
186       }
187     }
188   }
191   /*! \brief  Create HTML output for this plugin 
192       @return String  HTML output for this plugin.
193     */
194   function execute()
195   {
196     /* Call parent execute */
197     plugin::execute();
199     /*****
200       Handle Posts 
201      *****/
202     foreach($_POST as $name => $value){
204       if(preg_match("/^negOption_/",$name)){
206         $opt = preg_replace("/^negOption_/","",$name);
207         $opt = preg_replace("/_[^_]*$/","",$opt);
208         $id  = preg_replace("/^.*_([0-9])*$/","\\1",$opt);
209         $opt = preg_replace("/_[0-9]*$/","",$opt);
211         if(isset($this->sudoOption[$opt][$id])){
212           $val = $this->sudoOption[$opt][$id]["VALUE"];
214           /*****
215             Negate STRING_BOOL && BOOL_INTEGER
216            *****/
217           if(in_array($this->options[$opt]['TYPE'],array('STRING_BOOL','BOOL_INTEGER'))){
218             if(in_array($val, array("TRUE","FALSE"))){
219               if($val == "TRUE"){
220                 $this->sudoOption[$opt][$id]["VALUE"] = "FALSE";
221               }else{
222                 $this->sudoOption[$opt][$id]["VALUE"] = "TRUE";
223               }
224             }else{
225                $this->sudoOption[$opt][$id]['NEGATE'] = !$this->sudoOption[$opt][$id]['NEGATE']; 
226             }
227           }
229           /*****
230             Negate STRING / INTEGER
231            *****/
232           if(in_array($this->options[$opt]['TYPE'],array('STRING','INTEGER','LISTS'))){
233             $this->sudoOption[$opt][$id]['NEGATE'] = !$this->sudoOption[$opt][$id]['NEGATE']; 
234           }
236           /*****
237             Negate BOOLEAN
238            *****/
239           if(in_array($this->options[$opt]['TYPE'],array('BOOLEAN'))){
240             if($val == "TRUE"){
241               $this->sudoOption[$opt][$id]["VALUE"] = "FALSE";
242             }else{
243               $this->sudoOption[$opt][$id]["VALUE"] = "TRUE";
244             }
245           }
246         }
247         break;
248       }
250       /*****
251         Remove options
252        *****/
253       if(preg_match("/^delOption/",$name)){
254         $opt = preg_replace("/^delOption_/","",$name);
255         $opt = preg_replace("/_[^_]*$/","",$opt);
256         $id  = preg_replace("/^.*_([0-9])*$/","\\1",$opt);
257         $opt = preg_replace("/_[0-9]*$/","",$opt);
259         if(isset($this->sudoOption[$opt][$id])){
260           unset($this->sudoOption[$opt][$id]);
261         }
262         if(!count($this->sudoOption[$opt])){
263           unset($this->sudoOption[$opt]);
264         }
265         break;
266       }
267     }
269  
270     $smarty = get_smarty();
271     $smarty->assign("map",  array("STRING" => _("string"), "BOOLEAN" => _("bool"),
272       "INTEGER" => _("integer") , "BOOL_INTEGER" => _("integer")."-"._("bool") ,
273       "STRING_BOOL" => _("string")."-"._("bool"),"LISTS" => _("list")));
274     $smarty->assign("sudoOption",$this->sudoOption);
275     $smarty->assign("options",$this->options);
276     return($smarty->fetch(get_template_path('options.tpl', TRUE)));
277   }
280   /*! \brief  Removes this plugin 
281    */
282   function remove_from_parent()
283   {
284   }
287   /*! \brief  Saves all relevant HTML post values for this plugin 
288    */
289   function save_object()
290   {
291     plugin::save_object();
293     if(isset($_POST['add_option']) && isset($_POST['option'])){
294       $opt = get_post("option");
296       /* Append attribute only once, lists are handled below */
297       if(isset($this->options[$opt])){
298         $type = $this->options[$opt]['TYPE'];
299         $val  = $this->options[$opt]['DEFAULT'];
300         $option = array("NAME" => $opt, "VALUE" => $val , "NEGATE" => FALSE);
301         $this->sudoOption[$opt][] = $option;
302       }
303     }
305     foreach($this->sudoOption as $name => $opts){
306       foreach($opts as $id => $opt){
308         /****
309           Get posted value for BOOLEAN
310          ****/
311         if(in_array($this->options[$name]['TYPE'],array("BOOLEAN"))){
312           if(isset($_POST['option_value__'.$name.'_'.$id])){
313             $this->sudoOption[$name][$id]["VALUE"] = get_post('option_value__'.$name.'_'.$id);
314           }
315         }
317         /****
318           Get posted value for STRING / INTEGER
319          ****/
320         if(in_array($this->options[$name]['TYPE'],array("STRING","INTEGER"))){
321           if(isset($_POST['option_value__'.$name.'_'.$id])){
322             $this->sudoOption[$name][$id]["VALUE"] = get_post('option_value__'.$name.'_'.$id);
323           }
324         }
326         /****
327           Get posted value for STRING_BOOL / BOOL_INTEGER
328          ****/
329         if(in_array($this->options[$name]['TYPE'],array("BOOL_INTEGER","STRING_BOOL"))){
330           if(isset($_POST['option_selection__'.$name.'_'.$id])){
331             $sel = get_post('option_selection__'.$name.'_'.$id);
332             $val = "";
333             if(isset($_POST['option_value__'.$name.'_'.$id])){
334               $val = get_post('option_value__'.$name.'_'.$id);
335             }
337             if($sel == "FALSE" || $sel == "TRUE"){
338               $this->sudoOption[$name][$id]['VALUE'] = $sel;
339               $this->sudoOption[$name][$id]['NEGATE'] = FALSE;
340             }else{
341               $this->sudoOption[$name][$id]['VALUE'] = $val;
342             }
343           }
344         }
346         /****
347           Get posted value for LISTS
348          ****/
349         if(in_array($this->options[$name]['TYPE'],array("LISTS"))){
350           foreach($this->sudoOption[$name] as $entry_key => $entry){
351             if(isset($_POST['list_value__'.$name.'_'.$entry_key])){
352               $val = get_post('list_value__'.$name.'_'.$entry_key);
353               $this->sudoOption[$name][$entry_key]["VALUE"] = $val;
354             }
355           } 
356         }
357       }
358     }
359   }
362   /*! \brief  Save changes to ldap 
363    */
364   function save()
365   {
366     plugin::save(); 
368     $this->attrs['sudoOption'] = array();
369     foreach($this->sudoOption as $name => $opts){
370       foreach($opts as $id => $opt){
372         $type   = $this->options[$name]['TYPE'];
373         $neg    = $opt['NEGATE'];
374         $value  = $opt['VALUE'];
375         $option = "";
377         /* Escape special chars */
378         $value = addcslashes($value,"\\:,:=");
380         /****
381           Save LISTS 
382          ****/
383         if($type=="LISTS"){
384           if($value == ""){
385             $option = $name;
386           }else{
387             $option = $name."=".$value;
388           }
389           if($neg){
390             $option = "!".$option;
391           }
392         }
394         /****
395           Save BOOLEAN
396          ****/
397         if(in_array($type,array("BOOLEAN"))){ 
398           $option = $name;
399           if($value == "FALSE"){
400             $option = "!".$option;
401           }
402         }
404         /****
405           Save STRING / INTEGER
406          ****/
407         if(in_array($type,array("STRING","INTEGER"))){ 
408           if($value != ""){
409             $option = $name."=".$value;
410           }else{
411             $option = $name; 
412           }
413           if($neg){
414             $option = "!".$option;
415           }
416         }
418         /****
419           Save STRING_BOOL / BOOL_INTEGER
420          ****/
421         if(in_array($type,array("STRING_BOOL","BOOL_INTEGER"))){
422           if($value == "FALSE"){
423             $option = "!".$name;
424           }elseif($value == "TRUE"){
425             $option = $name;
426           }else{
427             if($value != ""){
428               $option = $name."=".$value;
429             }else{
430               $option = $name; 
431             }
432             if($neg){
433               $option = "!".$option;
434             }
435           }
436         }
438         $this->attrs['sudoOption'][] = $option;
439       }
440     }
441     $this->cleanup();
442     $ldap = $this->config->get_ldap_link();
443     $ldap->cd($this->dn);
444     $ldap->modify($this->attrs);;
445   }
447   
448   /*! \brief  Checks input validity
449    */
450   function check()
451   {
452     $message = plugin::check();
454     foreach($this->sudoOption as $name => $options){
455       foreach($options as $id => $option){
456         switch($this->options[$name]['TYPE']){
458           /* Check for a valid integer value */
459           case 'INTEGER' : 
460             {
461               if(!preg_match("/^[0-9]*$/",$option['VALUE'])){
462                 $message[] = msgPool::invalid($name,$option['VALUE'],"/[0-9]/");
463               }
464             } break;
466         }
467       }
468     }
470     return ($message);
471   }
473 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
474 ?>