Code

Created trunk inside of 2.6-lhm
[gosa.git] / trunk / gosa-plugins / mit-krb5 / admin / systems / services / kerberos / class_krb_host_keys.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_gosaSupportDaemon.inc 10788 2008-05-06 11:15:57Z 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   Allows the creation of service and host principals.
25               e.g.  host/server.intranet.company.de@COMPANY.DE
26               e.g.  ldap/server.intranet.company.de@COMPANY.DE
27              The is specified by the third parameter of the constructor, the   
28               hostname is specified by the parent object. ($parent->cn).
29     
30              The keys can be created and removed.
31              A running "GOsa support Daemon" with a krb5 module is required.
32 */
33 class krbHostKeys extends plugin 
34 {
36   public  $config;
37   private $object;
38   private $o_queue;
39   private $goKrbRealm = "disabled";
40   private $kerberos_support= FALSE;
42   private $pwd_handle   = NULL;
43   private $server_list  = array(); 
44   private $last_list    = array(); // The last array created for the smarty template
46   private $init_namingAttr  = "";
47   private $namingAttr       = "";
48   private $is_service_key   = FALSE;
49   private $confirm_box      = NULL;
51   /*! \brief  Initalizes the kerberos host/service key generation. 
52                 (See class comment for more information)
53       @param  Object  The GOsa configuration class. 
54       @param  Object  The parent class (e.g. servgeneric) // $parent->cn MUST be set. 
55    */
56   public function __construct($config,&$object)
57   {
58   
59     /* Initialize this plugin 
60      */
61     plugin::plugin($config, NULL);
62     $this->object = $object;
64     $this->acl_category = &$this->object->acl_category;
65     $this->acl_base = &$this->object->acl_base;
67     /* Instantiate si class, to be able to communicate with the support daemon.
68      */
69     $this->o_queue = new gosaSupportDaemon();
71     /*  Create principal name, to detect whether there is a valid host key or not
72      */
73     if(!isset($this->object->cn)){
74       trigger_error("Cannot initialize kerberos key service, invalid parent object given (Paramter 2).".
75           " Should be of class 'plugin' with accessible class member variable 'cn'.");
76     }else{
77       $this->init_namingAttr = $this->namingAttr = $this->object->cn;
78       $this->init();
79     }
80   }
82  
83   /*! \brief  Reloads the list of available principals. 
84    */ 
85   public function reload_principals()
86   {
87     if($this->kerberos_support){
88       foreach($this->server_list as $mac => $data){
89         $principals = $this->pwd_handle->load_principals_for_server($mac);
90         $this->server_list[$mac]['PRINCIPALS'] = $principals;
91       }
92     }
93   }
96   /*! \brief  Load/reload all key settings for the current host ($this->object).
97               This reloads the list of all kerberos realms and which keys 
98                are set for the current host.
99    */
100   private function init()
101   {
102     /* Check if the SI based kerberos method is available 
103      */
104     $this->kerberos_support = FALSE;
105     if(class_available("passwordMethodMIT")){
107       /* Update the naming attribute.
108        */
109       $this->namingAttr = $this->object->cn;
111       /* Create password handle, it has already a working principal parsing 
112        */
113       $this->pwd_handle = new passwordMethodMIT($this->config);
114       if(!$this->pwd_handle->is_available()){
115         return;
116       }
117   
118       /* Check class initialation */
119       if(!($this->pwd_handle instanceOf passwordMethodMIT)){
120         trigger_error("Could not initialize kerberos password method 'passwordMethodMIT'.");
121         return;
122       }
123       $this->pwd_handle->clear_cache();
125       /* Get a list of all kerberos servers, defined in ldap
126          and get a list of principals they are providing.
127        */
128       $ldap = $this->config->get_ldap_link();
129       $ldap->cd($this->config->current['BASE']);
130       $ldap->search("(&(objectClass=goServer)(objectClass=goKrbServer))",array("goKrbRealm","cn","description","macAddress"));
131       $this->server_list = array();
132       while($attrs = $ldap->fetch()){
133         if(!isset($attrs['macAddress'][0])) continue;
134         if(!isset($attrs['description'][0])) $attrs['description'][0] ="";
136         /* Get all required informations for each realm 
137          */
138         $mac        = $attrs['macAddress'][0];
139         $realm      = $attrs['goKrbRealm'][0];
140         $cn         = $attrs['cn'][0];
141         $principals = $this->pwd_handle->load_principals_for_server($mac);
142     
143         /* Create a list of all realms and their attributes.
144          */ 
145         $this->server_list[$mac]['CN']          = $cn;
146         $this->server_list[$mac]['MAC']         = $mac;
147         $this->server_list[$mac]['REALM']       = $realm;
148         $this->server_list[$mac]['PRINCIPALS']  = $principals;
150         /* Set first realm as selected.
151          */
152         if($this->goKrbRealm == ""){
153           $this->goKrbRealm = $attrs['goKrbRealm'][0];
154         }
155       }
156   
157       if(isset($this->server_list) && count($this->server_list) && $this->o_queue->is_connected()){
158         $this->kerberos_support = TRUE;
159       }
160     }
161   }
164   /*! \brief  Create the HTML output used in the host generic dialogs 
165                or in server-services.
166               It also checks if the host cn has changed and asks the user 
167                if he want to update the keys to the current host name.
168   */
169   public function execute_by_prefix($prefix, $service_plugin =FALSE)
170   {
171     /* Skip if there is no kerberos support available 
172      */
173     if(!$this->kerberos_support || !$this->acl_is_readable("0")) return("");
175     /* Check if naming context has changed,
176        in this case ask user if he wants to update the keys. 
177      */
178     if($this->object->cn != $this->namingAttr){
180       /* The confirm dialog was shown. Check if OK was pressed. 
181        */
182       if(is_object($this->confirm_box) && $this->confirm_box instanceof msg_dialog){
183         if($this->confirm_box->is_confirmed()){
185           /* Walk through each server and check which keys have to be updated.
186            */
187           foreach($this->server_list as $server => $data){
188             foreach($data['PRINCIPALS'] as $p_name){
189               if(preg_match("/\/".preg_quote($this->namingAttr, '/')."\@/",$p_name)){
190                 $pre = preg_replace("/\/.*$/","/",$p_name);
191                 $this->delete_key($server, $pre.$this->namingAttr."@".$data['REALM']);
192                 $this->create_key($server, $pre.$this->object->cn."@".$data['REALM']);
193               }
194             }
195           }
196         }
197         $this->init();
198         $this->confirm_box = NULL;
199       }else{
201         /* The host name has changed, check if there are kerberos key which have to be updated 
202          */
203         $found = array();
204         $this->reload_principals();
205         foreach($this->server_list as $server => $data){
206           foreach($data['PRINCIPALS'] as $p_name){
208             /* Collect all principals for the current host. 
209              */
210             if(preg_match("/\/".preg_quote($this->namingAttr, '/')."\@/",$p_name)){
211               $pre = preg_replace("/\/.*$/","/",$p_name);
212               $found[] = "<b>".$pre.$this->namingAttr."@".$data['REALM']."</b> ".
213                 _("updated to").
214                 " <b>".$pre.$this->object->cn."@".$data['REALM']."</b>";
215             }
216           }
217         }
219         /* If there is at leat one key that have to updated, then display a confirm dialog. 
220          */
221         if(count($found)){
222           $this->confirm_box = new msg_dialog(_("Kerberos"),sprintf(_("The principal name of this system has changed. Do you want to update your principals? The affected principals are listed below: %s"),"<br>".msgPool::buildList($found)),OK_CANCEL_DIALOG); 
223         }else{
224           $this->init();
225         }
226       }
227     }
229     /* Create a divlist to list all key settings. 
230      */
231     $divlist = new divSelectBox("Kerberos_Host/Service_Keys");
232     $divlist->SetHeight(100);
233     $princ_id = 0; // Used in posts
235     $this->last_list[$prefix] = array();
237     /* Create actions */
238     $new = "<input type='image' class='center' name='create_%ID%'
239       alt='"._("Create key")."' 
240       title='"._("Create key")."' src='images/lists/new.png'>
241       <img src='images/empty.png' alt=' ' class='center'>
242       <img src='images/empty.png' alt=' ' class='center'>";
243     $rec ="
244       <img src='images/empty.png' alt=' ' class='center'>
245       <input type='image' class='center' name='recreate_%ID%'
246       alt='"._("Recreate key")."' title='"._("Recreate key")."' src='images/lists/reload.png'>
247       <input type='image' class='center' name='remove_%ID%'
248       alt='"._("Remove key")."' title='"._("Remove key")."' src='images/lists/trash.png'>";
250     /* Check ACLs */
251     if(!$this->acl_is_writeable("0")){
252       $new = $rec = "";
253     }
254     
256     foreach($this->server_list as $mac => $server){
258       /* Recreate/Remove actions */
259       $realm = $server['REALM'];
261       /* Check if the given prefix is configured for a realm
262          If it is configured display the recreate and remove button 
263          if not display the create button. 
264        */
265       $found        = FALSE;
267       // The master principal is specified by the $prefix parameter of this function.
268       $master_princ = $prefix.$this->namingAttr."@".$realm;
270       foreach($server['PRINCIPALS'] as $id => $princ){
271         if(preg_match("/^".preg_quote($master_princ, '/')."$/i",$princ)){
272           $found = TRUE;
273           break;
274         }
275       }      
277       /* Display buttons to "create" or to "remove/recreate" wheteher the prefix esists or not 
278        */
279       $princ_id ++;
280       $this->last_list[$prefix][$princ_id]['REALM']  = $realm;
281       $this->last_list[$prefix][$princ_id]['MAC']    = $mac;
282       $this->last_list[$prefix][$princ_id]['NAME']   = $master_princ;
284       $field1 = array('string' => $realm );
285       $field2 = array('string' => $master_princ);
286       if($found){
287         $field3 = array('string' => _("installed"));
288         $field4 = array('string' => preg_replace("/%ID%/",$princ_id,$rec),"attach" => "style='border:0px;'");
289         $this->last_list[$prefix][$princ_id]['USED'] = TRUE;
290       }else{
291         $field3 = array('string' => "-");
292         $field4 = array('string' => preg_replace("/%ID%/",$princ_id,$new),"attach" => "style='border:0px;'");
293         $this->last_list[$prefix][$princ_id]['USED'] = FALSE;
294       }
296       $divlist->AddEntry(array($field1,$field2,$field3,$field4));
298       /* Get all additionally configured service host keys, this are all keys that 
299          do not match the master_princ.
300        */
301       if(!$service_plugin){
302         foreach($server['PRINCIPALS'] as $id => $princ){
303           if(preg_match("/".preg_quote("/".$this->namingAttr."@", '/')."/i",$princ) &&
304               !preg_match("/^".preg_quote($prefix, '/')."/",$princ)){
306             /* Display buttons to "create" or to "remove/recreate" wheteher the prefix esists or not 
307              */
308             $princ_id ++;
310             $this->last_list[$prefix][$princ_id]['USED']  = TRUE;
311             $this->last_list[$prefix][$princ_id]['REALM'] = $realm;
312             $this->last_list[$prefix][$princ_id]['MAC']   = $mac;
313             $this->last_list[$prefix][$princ_id]['NAME']  = $princ;
315             $field1 = array('string' => $realm );
316             $field2 = array('string' => $princ);
317             $field3 = array('string' => _("installed"));
318             $field4 = array('string' => preg_replace("/%ID%/",$princ_id,$rec),"attach" => "style='border:0px;'");
319             $divlist->AddEntry(array($field1,$field2,$field3,$field4));
320           } 
321         }
322       }
323     }
324     
325     $smarty = get_smarty(); 
326     $smarty->assign("list",$divlist->DrawList());
327     $smarty->assign("server_list" ,$this->server_list);
328     $smarty->assign("service_plugin" ,$service_plugin);
329     $smarty->assign("is_service_key" , $this->is_service_key);
330     return($smarty->fetch (get_template_path('krb_host_keys.tpl', TRUE,dirname(__FILE__))));
331   }
334   /*! \brief  This function creates a new host/service key for the given server and principal name 
335       @param  String  The servers mac address. (Must be available in $this->server_list)
336       @param  $name   The new principal name. (e.g. ldap/some.host@REALM.FASEL)
337       @retrun Boolean TRUE on success else FALSE.
338    */
339   public function create_key($id,$name)
340   {
341     $this->o_queue->krb5_add_principal($id,$name,array());
342     if($this->o_queue->is_error()){
343       msg_dialog::display(_("Service infrastructure"),msgPool::siError($this->o_queue->get_error()),ERROR_DIALOG);
344       return(FALSE);
345     }
346     return(TRUE);
347   }  
350   /*! \brief  This function recreates a host/service key for the given server and principal name.
351               It remove the old key first and then tries to create a new one.
352       @param  String  The servers mac address. (Must be available in $this->server_list)
353       @param  $name   The new principal name. (e.g. ldap/some.host@REALM.FASEL)
354       @retrun Boolean TRUE on success else FALSE.
355    */
356   public function recreate_key($id,$name)
357   {
358     if($this->delete_key($id,$name)){
359       if($this->create_key($id,$name)){
360         return(TRUE);
361       }
362     }
363     return(FALSE);
364   }  
367   /*! \brief  This function removes a host/service key for the given server and principal name.
368       @param  String  The servers mac address. (Must be available in $this->server_list)
369       @param  $name   The new principal name. (e.g. ldap/some.host@REALM.FASEL)
370       @retrun Boolean TRUE on success else FALSE.
371    */
372   public function delete_key($id,$name)
373   {
374     $this->o_queue->krb5_del_principal($id,  $name);
375     if($this->o_queue->is_error()){
376       msg_dialog::display(_("Service infrastructure"),msgPool::siError($this->o_queue->get_error()),ERROR_DIALOG);
377       return(FALSE);
378     }
379     return(TRUE);
380   }  
383   /*! \brief  This function acts on the HTML posts and ensures that our 
384                 delete/create/recreate are executed. 
385     */
386   public function save_object_by_prefix($prefix)
387   {
388     if(!isset($this->last_list[$prefix])) return; // No posts for us 
390     if(!$this->acl_is_writeable("0")) return; // No permissions to change anything
392     foreach($_POST as $name => $value){
393       if(preg_match("/^create_/",$name)){
394         $id = preg_replace("/^create_([0-9]*)_.*$/","\\1",$name);
395         if(isset($this->last_list[$prefix][$id])){
396           $data = $this->last_list[$prefix][$id]; 
397           $this->create_key($data['MAC'],$data['NAME']);
398           $this->init();
399         }
400         break;
401       }
402       if(preg_match("/^recreate_/",$name)){
403         $id = preg_replace("/^recreate_([0-9]*)_.*$/","\\1",$name);
404         if(isset($this->last_list[$prefix][$id])){
405           $data = $this->last_list[$prefix][$id]; 
406           $this->recreate_key($data['MAC'],$data['NAME']);
407           $this->init();
408         }
409         break;
410       }
411       if(preg_match("/^remove_/",$name)){
412         $id = preg_replace("/^remove_([0-9]*)_.*$/","\\1",$name);
413         if(isset($this->last_list[$prefix][$id])){
414           $data = $this->last_list[$prefix][$id]; 
415           $this->delete_key($data['MAC'],$data['NAME']);
416           $this->init();
417         }
418         break;
419       }
420     }    
421   } 
423   
424   /*! \brief  Removes all key settings for the given host ($this->object->cn)
425    */
426   public function remove_from_parent_by_prefix($prefix)
427   {
428     if(!$this->kerberos_support)  return;
429     foreach($this->server_list as $server => $data){
430       foreach($data['PRINCIPALS'] as $p_name){
432         /* Detect all principals for the current host.
433          */
434         if(preg_match("/".preg_quote($prefix.$this->namingAttr, '/')."\@/",$p_name)){
435           $this->delete_key($server, $p_name);
436         }
437       }
438     }
439   }
442   /*! \brief  Ensures that a service plugin suitable HTML output is generated.
443       @param  Boolean TRUE enables servie plugin output, FALSE diables it. 
444    */
445   public function ServiceKey($bool = TRUE)
446   {
447     $this->is_service_key = $bool;
448   }
451   /*! \brief Return plugin informations for acl handling
452       @return Array   ACL infos.
453    */
454   static function plInfo()
455   {
456     return (array(
457           "plShortName"   => _("Kerberos key"),
458           "plDescription" => _("Kerberos host key"),
459           "plSelfModify"  => FALSE,
460           "plDepends"     => array(),
461           "plPriority"    => 2,
462           "plSection"     => array("administration"),
463           "plCategory"    => array("server","workstation","terminal"),
465           "plProvidedAcls"=> array()
466         ));
467         
469   }
471 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
472 ?>