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 *********************/
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 }
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 *********************/
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 }
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 *********************/
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 }
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);
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 }
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 }
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);
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 }
620 }
621 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
622 ?>