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;
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 /* Get global filter config */
118 if (!session::is_set("sysfilter")){
119 $ui= get_userinfo();
120 $base= get_base_from_people($ui->dn);
121 $sysfilter= array( "depselect" => $base,
122 "regex" => "*");
123 session::set("sysfilter", $sysfilter);
124 }
125 }
128 /*! \brief Creates the sudo generic ui.
129 @return String The generated HTML content for this plugin.
130 */
131 function execute()
132 {
133 /* Call parent execute */
134 plugin::execute();
136 /*********************
137 Access control list / trust mode
138 *********************/
140 /* Add user workstation? */
141 if (isset($_POST["add_ws"])){
142 $this->show_ws_dialog= TRUE;
143 $this->dialog= TRUE;
144 }
146 /* Add user workstation? */
147 if (isset($_POST["add_ws_finish"]) && isset($_POST['wslist'])){
148 foreach($_POST['wslist'] as $ws){
149 $this->accessTo[$ws]= $ws;
150 }
151 ksort($this->accessTo);
152 $this->is_modified= TRUE;
153 }
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->show_ws_dialog= FALSE;
166 $this->dialog= FALSE;
167 }
169 /* Show ws dialog */
170 if ($this->show_ws_dialog){
171 return($this->display_trust_add_dialog());
172 }
175 /*********************
176 Add users
177 *********************/
179 if(isset($_POST['list_sudoUser']) && !is_object($this->dialog) && $this->acl_is_writeable("sudoUser")){
180 $used = array();
181 foreach($this->sudoUser as $name){
182 $used[] = preg_replace("/^!/","",$name);
183 }
184 $this->dialog =new target_list_users($this->config,$used);
185 }
187 /* Add selected hosts to the sudoUser list */
188 if(isset($_POST['SaveMultiSelectWindow']) && $this->dialog instanceof target_list_users){
189 if($this->acl_is_writeable("sudoUser")){
190 foreach($this->dialog->save() as $entry){
191 $cn = trim($entry['uid'][0]);
192 if(!in_array($cn,$this->sudoUser) && !in_array("!".$cn,$this->sudoUser)){
193 $this->sudoUser[] = $cn;
194 }
195 }
196 }
197 unset($this->dialog);
198 $this->dialog = NULL;
199 }
202 /*********************
203 Add systems
204 *********************/
206 if(isset($_POST['list_sudoHost']) && !is_object($this->dialog) && $this->acl_is_writeable("sudoHost")){
207 $used = array();
208 foreach($this->sudoHost as $name){
209 $used[] = preg_replace("/^!/","",$name);
210 }
211 $this->dialog =new target_list_systems($this->config,$used);
212 }
214 /* Add selected hosts to the sudoHost list */
215 if(isset($_POST['SaveMultiSelectWindow']) && $this->dialog instanceof target_list_systems){
216 if($this->acl_is_writeable("sudoHost")){
217 foreach($this->dialog->save() as $entry){
218 $cn = trim($entry['cn'][0]);
219 if(!in_array($cn,$this->sudoHost) && !in_array("!".$cn,$this->sudoHost)){
220 $this->sudoHost[] = $cn;
221 }
222 }
223 }
224 unset($this->dialog);
225 $this->dialog = NULL;
226 }
229 /*********************
230 Dialog handling / display / close
231 *********************/
233 if(isset($_POST['CloseMultiSelectWindow']) && is_object($this->dialog)){
234 unset($this->dialog);
235 $this->dialog = NULL;
236 }
238 if(is_object($this->dialog)){
239 return($this->dialog->execute());
240 }
243 /*********************
244 NEGATE values
245 *********************/
246 foreach($_POST as $name => $value){
247 if(preg_match("/^neg_/",$name)){
248 $attr = preg_replace("/^neg_([^_]*)_.*$/","\\1",$name);
249 $value= preg_replace("/^neg_[^_]*_([0-9]*)_.*$/","\\1",$name);
251 if($this->acl_is_writeable($attr)){
252 $attrs = $this->$attr;
253 if(isset( $attrs[$value])){
254 $v = $attrs[$value];
255 if(preg_match("/^!/",$v)){
256 $attrs[$value] = preg_replace("/^!/","",$v);
257 }else{
258 $attrs[$value] = "!".$v;
259 }
260 $this->$attr = $attrs;
261 }
262 }
263 break; // Do it once, image inputs will be posted twice
264 }
265 }
267 /*********************
268 Delete values
269 *********************/
270 foreach($_POST as $name => $value){
271 if(preg_match("/^del_/",$name)){
272 $attr = preg_replace("/^del_([^_]*)_.*$/","\\1",$name);
273 $value= preg_replace("/^del_[^_]*_([0-9]*)_.*$/","\\1",$name);
274 if($this->acl_is_writeable($attr)){
275 $attrs = $this->$attr;
276 if(isset( $attrs[$value])){
277 unset($attrs[$value]);
278 $this->$attr = $attrs;
279 }
280 }
281 break; // Do it once, image inputs will be posted twice
282 }
283 }
286 /*********************
287 ADD values
288 *********************/
290 /* User / Host / Runas */
291 foreach(array("sudoUser","sudoHost","sudoRunAs") as $attr){
292 if($this->acl_is_writeable($attr) &&
293 isset($_POST["add_".$attr]) &&
294 isset($_POST['new_'.$attr]) &&
295 !empty($_POST['new_'.$attr])){
296 if(preg_match("/^[a-z\.0-9]*$/i",$_POST['new_'.$attr])){
297 $attrs = $this->$attr;
298 $attrs[] = trim($_POST['new_'.$attr]);
299 $this->$attr = $attrs;
300 }else{
301 msg_dialog::display(_("Error"),msgPool::invalid($attr,$_POST['new_'.$attr],"/[a-z0-9]/"));
302 }
303 }
304 }
306 /* Command */
307 foreach(array("sudoCommand") as $attr){
308 if($this->acl_is_writeable($attr) && isset($_POST["add_".$attr]) && isset($_POST['new_'.$attr])){
309 $attrs = $this->$attr;
310 $attrs[] = trim($_POST['new_'.$attr]);
311 $this->$attr = $attrs;
312 }
313 }
316 /*********************
317 SMARTY assignments
318 *********************/
320 $smarty = get_smarty();
321 foreach($this->attributes as $attr){
322 $smarty->assign($attr,$this->$attr);
323 $smarty->assign($attr."ACL",$this->getacl($attr));
324 }
326 /* Work on trust modes */
327 $smarty->assign("trusthide", " disabled ");
328 if ($this->trustModel == "fullaccess"){
329 $trustmode= 1;
330 } elseif ($this->trustModel == "byhost"){
331 $trustmode= 2;
332 $smarty->assign("trusthide", "");
333 } else {
334 $trustmode= 0;
335 }
336 $smarty->assign("trustmode", $trustmode);
337 $smarty->assign("trustmodes", array(
338 0 => _("disabled"),
339 1 => _("full access"),
340 2 => _("allow access to these hosts")));
342 if((count($this->accessTo))==0){
343 $smarty->assign("emptyArrAccess",true);
344 }else{
345 $smarty->assign("emptyArrAccess",false);
346 }
347 $smarty->assign("workstations", $this->accessTo);
349 /* Create lists
350 */
351 $divlist_sudoUser = new divSelectBox("divlist_sudoUser");
352 $divlist_sudoUser->SetHeight("90");
353 $divlist_sudoHost = new divSelectBox("divlist_sudoHost");
354 $divlist_sudoHost->Setheight("90");
355 $divlist_sudoRunAs = new divSelectBox("divlist_sudoRunAs");
356 $divlist_sudoRunAs->Setheight("90");
357 $divlist_sudoCommand = new divSelectBox("divlist_sudoCommand");
358 $divlist_sudoCommand->Setheight("90");
360 /* Fill divlists
361 */
362 $neg_img= "<img src='images/negate.png' alt='!' class='center'>";
363 $option = "<input type='image' src='images/negate.png' name='neg_%ATTR%_%KEY%' class='center'>";
364 $option.= "<input type='image' src='images/edittrash.png' name='del_%ATTR%_%KEY%' class='center'>";
365 foreach(array("sudoUser","sudoCommand","sudoHost","sudoRunAs") as $attr){
366 if($this->acl_is_readable($attr)){
367 foreach($this->$attr as $key => $entry){
368 $entry = preg_replace("/^!/",$neg_img,$entry);
369 $list_name = "divlist_".$attr;
370 $$list_name->AddEntry(
371 array(
372 array("string" => $entry),
373 array("string" => preg_replace(array("/%KEY%/","/%ATTR%/"),array($key,$attr),$option),
374 "attach" => "style='width:40px; border-right: 0px;'")));
375 }
376 }
377 }
379 /* Tell smarty about our divlists
380 */
381 $smarty->assign("divlist_sudoUser", $divlist_sudoUser->DrawList());
382 $smarty->assign("divlist_sudoHost", $divlist_sudoHost->DrawList());
383 $smarty->assign("divlist_sudoRunAs", $divlist_sudoRunAs->DrawList());
384 $smarty->assign("divlist_sudoCommand",$divlist_sudoCommand->DrawList());
385 return($smarty->fetch(get_template_path('generic.tpl', TRUE)));
386 }
389 /*! \brief Remove this sudo role from the ldap server
390 */
391 function remove_from_parent()
392 {
393 plugin::remove_from_parent();
395 $ldap = $this->config->get_ldap_link();
396 $ldap->cd($this->dn);
397 $ldap->rmdir($this->dn);
399 /* Send signal to the world that we've done */
400 $this->handle_post_events("remove");
401 }
404 /*! \brief Save all relevant HTML posts.
405 */
406 function save_object()
407 {
408 plugin::save_object();
410 if(is_object($this->dialog)){
411 $this->dialog->save_object();
412 }
414 /* Trust mode - special handling */
415 if($this->acl_is_writeable("trustModel")){
416 if (isset($_POST['trustmode'])){
417 $saved= $this->trustModel;
418 if ($_POST['trustmode'] == "1"){
419 $this->trustModel= "fullaccess";
420 } elseif ($_POST['trustmode'] == "2"){
421 $this->trustModel= "byhost";
422 } else {
423 $this->trustModel= "";
424 }
425 if ($this->trustModel != $saved){
426 $this->is_modified= TRUE;
427 }
428 }
429 }
430 }
433 /*! \brief Save changes into the ldap database.
434 */
435 function save()
436 {
437 plugin::save();
438 /* Trust accounts */
439 $objectclasses= array();
440 foreach ($this->attrs['objectClass'] as $key => $class){
441 if (preg_match('/trustAccount/i', $class)){
442 continue;
443 }
444 $objectclasses[]= $this->attrs['objectClass'][$key];
445 }
447 $this->attrs['objectClass']= $objectclasses;
448 if ($this->trustModel != ""){
449 $this->attrs['objectClass'][]= "trustAccount";
450 $this->attrs['trustModel']= $this->trustModel;
451 $this->attrs['accessTo']= array();
452 if ($this->trustModel == "byhost"){
453 foreach ($this->accessTo as $host){
454 $this->attrs['accessTo'][]= $host;
455 }
456 }
457 } else {
458 if ($this->was_trust_account){
459 $this->attrs['accessTo']= array();
460 $this->attrs['trustModel']= array();
461 }
462 }
465 /* Ensure a correct array index
466 */
467 $this->attrs['sudoHost'] = array_values($this->attrs['sudoHost']);
468 $this->attrs['sudoRunAs'] = array_values($this->attrs['sudoRunAs']);
469 $this->attrs['sudoUser'] = array_values($this->attrs['sudoUser']);
470 $this->attrs['sudoCommand'] = array_values($this->attrs['sudoCommand']);
471 $this->cleanup();
473 $ldap = $this->config->get_ldap_link();
474 $ldap->cd($this->config->current['BASE']);
475 if($this->is_new){
476 $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $this->dn));
477 $ldap->cd($this->dn);
478 $ldap->add($this->attrs);
480 /* Send signal to the world that we've done */
481 $this->handle_post_events("create");
482 }else{
483 $ldap->cd($this->dn);
484 $ldap->modify($this->attrs);;
486 /* Send signal to the world that we've done */
487 $this->handle_post_events("modify");
488 }
490 if (!$ldap->success()){
491 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
492 }
493 }
496 /*! \brief Check the given input.
497 @return Array All error messages in an array();
498 */
499 function check()
500 {
501 $message = plugin::check();
502 return ($message);
503 }
506 /*! \brief Display the System Trust Add Workstation dialog
507 @return String HTML dialog to add a system to the trust list.
509 */
510 private function display_trust_add_dialog()
511 {
512 $smarty = get_smarty();
514 /* Save data */
515 $sysfilter= session::get("sysfilter");
516 foreach( array("depselect", "regex") as $type){
517 if (isset($_POST[$type])){
518 $sysfilter[$type]= $_POST[$type];
519 }
520 }
521 if (isset($_GET['search'])){
522 $s= mb_substr($_GET['search'], 0, 1, "UTF8")."*";
523 if ($s == "**"){
524 $s= "*";
525 }
526 $sysfilter['regex']= $s;
527 }
528 session::set("sysfilter", $sysfilter);
530 /* Get workstation list */
531 $exclude= "";
532 foreach($this->accessTo as $ws){
533 $exclude.= "(cn=$ws)";
534 }
535 if ($exclude != ""){
536 $exclude= "(!(|$exclude))";
537 }
538 $regex= $sysfilter['regex'];
539 $filter= "(&(|(objectClass=goServer)(objectClass=gotoWorkstation)(objectClass=gotoTerminal))$exclude(cn=*)(cn=$regex))";
541 $res = array();
542 $res= array_merge($res,get_sub_list($filter, array("terminal"), get_ou("terminalou"),
543 get_ou("systemsou").$sysfilter['depselect'], array("cn"), GL_SUBSEARCH | GL_SIZELIMIT));
544 $res= array_merge($res,get_sub_list($filter, array("server"), get_ou("serverou"),
545 get_ou("systemsou").$sysfilter['depselect'], array("cn"), GL_SUBSEARCH | GL_SIZELIMIT));
546 $res= array_merge($res,get_sub_list($filter, array("workstation"), get_ou("workstationou"),
547 get_ou("systemsou").$sysfilter['depselect'], array("cn"), GL_SUBSEARCH | GL_SIZELIMIT));
549 $wslist= array();
550 foreach ($res as $attrs){
551 $wslist[]= preg_replace('/\$/', '', $attrs['cn'][0]);
552 }
553 asort($wslist);
554 foreach( array("depselect","regex") as $type){
555 $smarty->assign("$type", $sysfilter[$type]);
556 }
557 $smarty->assign("search_image", get_template_path('images/search.png'));
558 $smarty->assign("launchimage", get_template_path('images/small_filter.png'));
559 $smarty->assign("tree_image", get_template_path('images/tree.png'));
560 $smarty->assign("deplist", $this->config->idepartments);
561 $smarty->assign("alphabet", generate_alphabet());
562 $smarty->assign("hint", print_sizelimit_warning());
563 $smarty->assign("wslist", $wslist);
564 $smarty->assign("apply", apply_filter());
565 $display= $smarty->fetch (get_template_path('trust_machines.tpl', TRUE, dirname(__FILE__)));
566 return ($display);
567 }
570 /*! \brief Add ACL object
571 @return Returns the ACL object.
572 */
573 static function plInfo()
574 {
575 return (array(
576 "plShortName" => _("Sudo"),
577 "plDescription" => _("Sudo role"),
578 "plSelfModify" => FALSE,
579 "plDepends" => array(),
580 "plPriority" => 0,
581 "plSection" => array("admin"),
582 "plCategory" => array("sudo" => array("objectClass" => "sudoRole", "description" => _("Sudo role"))),
584 "plProvidedAcls" => array(
585 "cn" => _("Name"),
586 "description" => _("Description"),
587 "sudoUser" => _("Users"),
588 "sudoHost" => _("Host"),
589 "sudoCommand" => _("Command"),
590 "sudoRunAs" => _("Run as user"),
591 "trustModel" => _("Access control list"))
592 ));
593 }
594 }
595 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
596 ?>