[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).
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 {
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 }
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 }
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);
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 }
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 }
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 }
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 }
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 ));
469 }
470 }
471 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
472 ?>