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 }
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 }
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 }
472 }
473 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
474 ?>