Code

Updated principal handling
[gosa.git] / gosa-plugins / heimdal / admin / systems / services / kerberos / class_password-methods-MIT.inc
1 <?php
2 /*
3    This code is part of GOsa (https://gosa.gonicus.de)
4    Copyright (C) 2008 Fabian Hickert
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
21 class passwordMethodMIT extends passwordMethod
22 {
24   var $dn          = "new";     // DN of the current object
25   var $parent_dn   = "new";     // parents DN
26   var $is_account  = FALSE;     // This is TRUE if this object already has a krb extension
27   var $server_list = array();   // A list with all configured servers
28   var $map         = array();   // Mapping array, maps SERVER-REALM, REALM-SERVER ...
30   var $goKrbRealm  = "";        // The realm name this principal belongs to
31   var $principal   = "";        // The principals name (e.g. user@MY-DOMAIN.SYS)
32   var $is_new      = TRUE;      // Is TRUE if principal is new 
34   var $si_error        = FALSE;
35   var $si_error_msg    = "";
37   var $values = array(
38       "PRINC_EXPIRE_TIME",      // Expiry date of this principal
39       "PW_EXPIRATION",          // Password expiration 
40       "MAX_LIFE",               // Ticket lifetime
41       "MASK",                   // I'dont know 
42       "MAX_RENEWABLE_LIFE",     // Max ticket lifetime when renewed
43       "POLICY");                // The policy used by this principal
45   var $flags = array(
46       "DISALLOW_POSTDATED"  ,   // Pohibit postdated tickets
47       "DISALLOW_FORWARDABLE",   // Prohibit forwardable tickets
48       "DISALLOW_RENEWABLE"  ,   // Prohibit renewable tickets
49       "DISALLOW_PROXIABLE"  ,   // Disallow proxiable tickets
50       "DISALLOW_DUP_SKEY"   ,   // Disallow user to user authentification
51       "REQUIRES_PRE_AUTH"   ,   // Preauthentication required
52       "REQUIRES_HW_AUTH"    ,   // Hardware preauthentication
53       "DISALLOW_SVR"        ,   // Prohibit issuance of service tickets
54       "DISALLOW_TGT_BASED"  ,   // Disallow Ticket-Granting Service
55       "DISALLOW_ALL_TIX"    ,   // Forbid ticket issuance
56       "REQUIRES_PWCHANGE"   ,   // Force a password change
57       "PWCHANGE_SERVICE"    );  // Password change service 
59   var $readonly = array(
60       "FAIL_AUTH_COUNT",        // The number of failed logins 
61       "KVNO",                   // Key version number
62       "LAST_FAILED",            // Last failed login time
63       "LAST_PWD_CHANGE",        // Password last change time
64       "LAST_SUCCESS",           // Last successful login 
65       "MOD_DATE");              // Last modification time
68   var $POLICY                   = "";
69   var $POLICIES                 = array(); // Policies provided by the corrently selected realm/server
71   var $PRINC_EXPIRE_TIME        = 0;
72   var $PW_EXPIRATION            = 0;
73   var $PRINC_EXPIRE_TIME_clear  = TRUE;
74   var $PW_EXPIRATION_clear      = TRUE;
75   var $MAX_LIFE                 = 0;
76   var $MAX_RENEWABLE_LIFE       = 0;
77   var $MASK                     = "";
79   var $DISALLOW_POSTDATED       = FALSE;
80   var $DISALLOW_FORWARDABLE     = FALSE;
81   var $DISALLOW_RENEWABLE       = FALSE;
82   var $DISALLOW_PROXIABLE       = FALSE;
83   var $DISALLOW_DUP_SKEY        = FALSE;
84   var $REQUIRES_PRE_AUTH        = FALSE;
85   var $REQUIRES_HW_AUTH         = FALSE;
86   var $DISALLOW_SVR             = FALSE;
87   var $DISALLOW_TGT_BASED       = FALSE;
88   var $DISALLOW_ALL_TIX         = FALSE;
89   var $REQUIRES_PWCHANGE        = FALSE;
90   var $PWCHANGE_SERVICE         = FALSE;
92   var $FAIL_AUTH_COUNT          = 0;
93   var $KVNO                     = "";
94   var $LAST_FAILED              = 0;
95   var $LAST_PWD_CHANGE          = 0;
96   var $LAST_SUCCESS             = 0;
97   var $MOD_DATE                 = 0;
99   function __construct(&$config,$dn = "new")  
100   {
101     $this->config= $config;
102     $this->parent_dn = $dn;
104     /* No config object given, this may be the case 
105        if there is only a is_available() request triggered.
106      */
107     if(!is_object($config)){
108       return;
109     }  
111     /* Keep cache until we try to configure a principal 
112      */
113     if($dn != "new" && $dn != ""){
114       session::un_set("MIT_CACHE");
115       session::un_set("MIT_PRINCIPAL_CACHE");
116       session::un_set("MIT_POLICY_CACHE");
117     }
119     /* Get a list of all kerberos servers, defined in ldap
120        and get a list of principals they are providing. 
121      */
122     $ldap = $this->config->get_ldap_link();
123     $ldap->cd($this->config->current['BASE']);
124     $ldap->search("(&(objectClass=goServer)(objectClass=goKrbServer))",array("goKrbRealm","cn","description","macAddress"));
125     $this->server_list = array();
126     while($attrs = $ldap->fetch()){
127       if(!isset($attrs['macAddress'][0])) continue;
128       if(!isset($attrs['description'][0])) $attrs['description'][0] ="";
130       $principals = $this->load_principals_for_server($attrs['macAddress'][0]);
132       /* Create Realm/Server/Principal mapping.
133        */
134       foreach($principals as $principal){
135         $this->map["PRINCIPAL_SERVER"][$principal] = $attrs['cn'][0];
136         $this->map["PRINCIPAL_REALM"] [$principal] = $attrs['goKrbRealm'][0];
137       }
138       $this->map["SERVER_REALM"][$attrs['cn'][0]] = $attrs['goKrbRealm'][0];
139       $this->map["REALM_SERVER"][$attrs['goKrbRealm'][0]] = $attrs['cn'][0];
141       /* Set first realm as selected.  
142        */
143       if($this->goKrbRealm == ""){
144         $this->goKrbRealm = $attrs['goKrbRealm'][0];
145       }
147       /* Create Server list
148        */
149       $this->server_list[$attrs['cn'][0]] = array("macAddress" => $attrs['macAddress'][0],
150           "description"=> $attrs['description'][0],
151           "dn"         => $attrs['dn'],
152           "principals" => $principals,
153           "goKrbRealm" => $attrs['goKrbRealm'][0],
154           "cn"         => $attrs['cn'][0]);
155     }
157     /* Load object data from ldap && initialize this class  
158      */
159     $this->is_new = TRUE;
160     if($dn != "new" && $dn != ""){
161       $ldap = $this->config->get_ldap_link();
162       $ldap->cd($dn);
163       $ldap->cat($dn);
164       $this->attrs = $ldap->fetch();
165       if(isset($this->attrs['userPassword']) && preg_match("/^\{".$this->get_hash_name()."\}/",$this->attrs['userPassword'][0])){
167         /* Extract principal name out of userPassword attribute 
168          */
169         $p_name = preg_replace("/^\{".$this->get_hash_name()."\}/","",$this->attrs['userPassword'][0]);
171         /* Try to detect server our principal is configured on
172          */
173         if(isset($this->map['PRINCIPAL_SERVER'][$p_name])){
174           $server= $this->map['PRINCIPAL_SERVER'][$p_name];
175           $this->goKrbRealm = $this->map['SERVER_REALM'][$server];
176           $this->principal  = $p_name;
178           /* Load policies */
179           $server_name = $this->map['REALM_SERVER'][$this->goKrbRealm];
180           $server_mac  = $this->server_list[$server_name]['macAddress'];
181           $this->POLICIES = $this->load_policies_for_server($server_mac);
183           /* Load principal */
184           $this->load_principal($this->server_list[$server]['macAddress'],$p_name);
185           $this->is_new = FALSE;
186         }
187       }
188     }
189   }
192   /*! \brief  Load this plugin with the values of the given principal
193     @param  String  The macAddress of the kerberos server.
194     @param  String  The name of the principal to load.
195    */
196   public function load_principal($server,$name)
197   {
198     $o = new gosaSupportDaemon();
199     $tmp = array();
200     $tmp = $o->krb5_get_principal($server,$name);
201   
202     if($o->is_error()){
204       $this->si_error     = TRUE;
205       $this->si_error_msg = $o->get_error(); 
206       msg_dialog::display(_("Service infrastructure"),msgPool::siError($o->get_error()),ERROR_DIALOG);      
207     }else{
209       /* Load flags 
210        */
211 #     if(isset($tmp['ATTRIBUTES'])){
212 #       foreach($this->flags as $flag){
213 #         if(in_array($flag,$tmp['ATTRIBUTES'])){
214 #           $this->$flag = TRUE;
215 #         }
216 #       } 
217 #     }
219       /* Load readonly attributes 
220        */
221       foreach($this->readonly as $attr){
222         if(isset($tmp[$attr])){
223           $this->$attr = $tmp[$attr];
224         }
225       } 
227       /* Load modifyable attributes
228        */
229       foreach($this->values as $attr){
230         if(isset($tmp[$attr])){
231           $this->$attr = $tmp[$attr];
232         }
233       } 
235       /* Update time checkboxes 
236        */
237       $date_values = array("PW_EXPIRATION","PRINC_EXPIRE_TIME");
238       foreach($date_values as $value){
239         if(!empty($this->$value)){
240           $clear = $value."_clear";
241           $this->$clear = FALSE;
242         }
243       }
244     }
245   }
248   /*! \brief get list of all configured principals
249     for a given server. 
250     The results will cached.  
251    */
252   public function load_principals_for_server($server)
253   {
254     if(!session::is_set("MIT_PRINCIPAL_CACHE")){
255       session::set("MIT_PRINCIPAL_CACHE",array());
256     }
257     $cache = session::get("MIT_PRINCIPAL_CACHE");
258     if(!isset($cache[$server])){
259       $o = new gosaSupportDaemon();
260       $tmp = $o->krb5_list_principals($server);
261       if($o->is_error()){
262         $this->si_error     = TRUE;
263         $this->si_error_msg = $o->get_error(); 
264         msg_dialog::display(_("Service infrastructure"),msgPool::siError($o->get_error()),ERROR_DIALOG);
265         return(array());
266       }else{
267         $cache[$server] = $tmp;
268       }
269       session::set("MIT_PRINCIPAL_CACHE",$cache);
270     }
271     return($cache[$server]);
272   }
275   /*! \brief get list of all configured policies
276     for a given server. 
277     The results will cached.  
278    */
279   public function load_policies_for_server($server)
280   {
281     if(!session::is_set("MIT_POLICY_CACHE")){
282       session::set("MIT_POLICY_CACHE",array());
283     }
284     $cache = session::get("MIT_POLICY_CACHE");
285     if(!isset($cache[$server])){
286       $o = new gosaSupportDaemon();
287       $tmp = $o->krb5_list_policies($server);
288       if($o->is_error()){
289         $this->si_error     = TRUE;
290         $this->si_error_msg = $o->get_error();
291         msg_dialog::display(_("Service infrastructure"),msgPool::siError($o->get_error()),ERROR_DIALOG);
292         return(array());
293       }else{
294         $cache[$server] = array();
295         $cache[$server]["_none_"] = _("none"); 
296         foreach($tmp as $policy){
297           $cache[$server][$policy] = $policy;
298         }
299         ksort($cache[$server]);
300       }
301       session::set("MIT_POLICY_CACHE",$cache);
302     }
303     return($cache[$server]);
304   }
307   /*! \brief Check if this password method is useable. 
308     This is the case if there is a si server running and at least one server configured.
309     kerberos support. 
310    */ 
311   function is_available()
312   {
313     $o = new gosaSupportDaemon(FALSE);
314     if(count($this->server_list) && $o->connect()){
315       return TRUE; 
316     }
317     return(FALSE);  
318   }
321   function generate_hash($pwd)
322   {
323     $mode= "kerberos";
324     if (isset($this->config->current['KRBSASL']) && preg_match('/^true$/i', $this->config->current['KRBSASL'])){
325       $mode= "sasl";
326     }
327     return "{".$mode."}".$this->attrs['uid'][0]."@".$this->goKrbRealm;
328   }
331   function remove_from_parent()
332   {
333     if(!empty($this->principal) && $this->goKrbRealm){
334       $server = $this->map['REALM_SERVER'][$this->goKrbRealm];
335       $o = new gosaSupportDaemon();
336       if(!$o->krb5_del_principal($this->server_list[$server]['macAddress'],$this->principal)){
337         $this->si_error     = TRUE;
338         $this->si_error_msg = $o->get_error();
339         msg_dialog::display(_("Service infrastructure"),msgPool::siError($o->get_error()),ERROR_DIALOG);      
340       }
341     }
342   }
345   function set_password($password)
346   {
347     if(!empty($this->principal) && $this->goKrbRealm){
348       $server = $this->map['REALM_SERVER'][$this->goKrbRealm];
349       $o = new gosaSupportDaemon();
350       if(!$o->krb5_set_password($this->server_list[$server]['macAddress'],$this->principal,$password)){
351         msg_dialog::display(_("Service infrastructure"),msgPool::siError($o->get_error()),ERROR_DIALOG);      
352       }
353     }
354   }
357   function get_hash_name()
358   {
359     $mode= "kerberos";
360     if (isset($this->config->current['KRBSASL']) && preg_match('/^true$/i', $this->config->current['KRBSASL'])){
361       $mode= "sasl";
362     }
363     return "$mode";
364   }
367   function is_configurable()
368   {
369     return TRUE;
370   }
373   function configure()
374   {
375     $this->save_object();
377     $years = array();
378     $start = date("Y")-1;
379     for($i = $start; $i < ($start +20) ; $i++){
380       $years[$i] = $i;
381     }
382     $month= array();
383     for($i = 1; $i <= 12  ; $i++){
384       $month[str_pad($i,2,"0",STR_PAD_LEFT)] = $i;
385     }
386     $days= array();
387     for($i = 1; $i <= 31  ; $i++){
388       $days[str_pad($i,2,"0",STR_PAD_LEFT)] = $i;
389     }
390     $hours= array();
391     for($i = 0; $i <= 23  ; $i++){
392       $hours[str_pad($i,2,"0",STR_PAD_LEFT)] = $i;
393     }
394     $minutes= array();
395     for($i = 0; $i <= 59  ; $i++){
396       $minutes[str_pad($i,2,"0",STR_PAD_LEFT)] = $i;
397     }
400     /* Cancel heimdal options */
401     if (isset($_POST['pw_abort']) || $this->display == FALSE){
402       $this->display = FALSE;
403       return("");
404     }
406     /* Cancel heimdal options */
407     if (isset($_POST['pw_save'])){
408       $msgs = $this->check();
409       if(count($msgs)){
410         foreach($msgs as $msg){
411           msg_dialog::display(_("Heimdal"),$msg,WARNING_DIALOG);
412         }
413       }else{
414         $this->display = FALSE;
415         return "";
416       }
417     }
420     $smarty = get_smarty();
422     $smarty->assign("si_error",$this->si_error);
423     $smarty->assign("si_error_msg",$this->si_error_msg);
424   
425     $smarty->assign("years",$years);
426     $smarty->assign("month",$month);
427     $smarty->assign("days",$days);
428     $smarty->assign("hours",$hours);
429     $smarty->assign("minutes",$minutes);
431     $smarty->assign("server_list",$this->server_list);
432     $smarty->assign("POLICY"  ,$this->POLICY);
433     $smarty->assign("goKrbRealm" , $this->goKrbRealm);
435     $server_name = $this->map['REALM_SERVER'][$this->goKrbRealm];
436     $server_mac  = $this->server_list[$server_name]['macAddress'];
437     $this->POLICIES = $this->load_policies_for_server($server_mac);
438     $smarty->assign("POLICIES"  ,$this->POLICIES);
440     foreach($this->values as $attr){
441       $smarty->assign($attr ,$this->$attr);
442     }
443     foreach($this->readonly as $attr){
444       $smarty->assign($attr ,$this->$attr);
445     }
446     foreach($this->flags as $attr){
447       $smarty->assign($attr,$this->$attr);
448     }
450     $date_values = array("PRINC_EXPIRE_TIME","PW_EXPIRATION");
451     foreach($date_values as $date_val){
455       $clear = $date_val."_clear";
456       $smarty->assign($date_val."_clear",$this->$clear);
457       $smarty->assign($date_val."_y",date("Y",$this->$date_val));
458       $smarty->assign($date_val."_m",date("m",$this->$date_val));
459       $smarty->assign($date_val."_d",date("d",$this->$date_val));
460       $smarty->assign($date_val."_h",date("h",$this->$date_val));
461       $smarty->assign($date_val."_i",date("i",$this->$date_val));
462     }
465     return($smarty->fetch(get_template_path("pwd_kerberos_mit.tpl")));
466   }
469   function save_object()
470   {
471     /* If the communication with the si server failed, 
472         you are able to retry to connect to the server.
473        Here we hanlde those requests.
474      */
475     if(isset($_POST['retry_si'])){
476       $this->si_error= FALSE;
477       $this->si_error_msg= "";
478       session::un_set("MIT_PRINCIPAL_CACHE");
479       session::un_set("MIT_POLICY_CACHE");
480       $this->__construct($this->config,$this->parent_dn);
481     }
483     /* Only handle posts for this plugin, it its content was posted
484      */
485     if(isset($_POST['pwd_heimdal_posted'])){
487       if(isset($_POST['goKrbRealm'])){
488         $this->goKrbRealm = get_post("goKrbRealm");
489       }
491       foreach($this->flags as $attr){
492         $this->$attr = isset($_POST[$attr]);
493       }
495       foreach(array("MAX_LIFE","MAX_RENEWABLE_LIFE","POLICY") as $attr){
496         if(isset($_POST[$attr])){
497           $this->$attr = get_post($attr);
498         }
499       }
501       $date_values = array("PW_EXPIRATION","PRINC_EXPIRE_TIME");
502       foreach($date_values as $date_value){
503         $clear = $date_value."_clear";
504         if(isset($_POST[$date_value."_clear"])){
505           $this->$clear = TRUE;
506         }else{
507           $this->$clear = FALSE;
508           $this->$date_value = gmmktime(  
509               $_POST[$date_value."_h"],
510               $_POST[$date_value."_i"],
511               0,
512               $_POST[$date_value."_m"],
513               $_POST[$date_value."_d"],
514               $_POST[$date_value."_y"]);
515         }
516       }
517     }
518   }
521   function check()
522   {
523     $message = array();
524     echo "Checks missing";
525     return($message);
526   }
529   function chk_times($str)
530   {
531     if(preg_match("/^([0-9]){12,12}[a-z]$/i",$str)){
532       return(true);
533     }
534     return(false);
535   }
538   function save($dn)
539   {
540     $realm = $this->config->data['SERVERS']['KERBEROS']['REALM'];
542     $ldap = $this->config->get_ldap_link();
543     $ldap->cd($dn);
544     $ldap->cat($dn,array('uid'));
545     $attrs = $ldap->fetch();
546     if(isset($attrs['uid'][0])){
548       /* Get servers mac */
549       $server_name = $this->map['REALM_SERVER'][$this->goKrbRealm];
550       $server_mac  = $this->server_list[$server_name]['macAddress'];
552       $uid       = $attrs['uid'][0];
553       $principal = $uid."@".strtoupper($this->goKrbRealm); 
554       $policy    = $this->POLICY;
556       /* Collect flags */
557       $flags = array();
558       $entry = array();
559       foreach($this->flags as $flag){
560         if($this->$flag){
561           $flags[] = $flag;
562         }
563       }
564       if(count($flags)){
565         $entry['ATTRIBUTES'] = "23";
566       }
568       /* Append other values */
569       foreach($this->values as $attr){
570         if($attr == "POLICY") continue;
571         $entry[$attr] = $this->$attr;
572       }
574       /* Prepare entry to be saved */
575       if($policy != "_none_"){
576         $entry['POLICY'] = $policy;
577       }
579       /* Set date values 
580        */
581       $date_values = array("PW_EXPIRATION","PRINC_EXPIRE_TIME");
582       foreach($date_values as $value){
583         $clear = $value."_clear";
584         if($this->$clear){
585           $entry[$value] = 0;
586         }
587       }    
590       /* Save principal changes */
591       $o = new gosaSupportDaemon();
592       if(in_array($principal,$this->server_list[$server_name]['principals'])){
593         $this->is_new = FALSE;
594       }
596       if($this->is_new){
597         $o->krb5_add_principal($server_mac,$principal,$entry);
598       }else{
599         $o->krb5_set_principal($server_mac,$principal,$entry);
600       }
601       if($o->is_error()){
602         $this->si_error     = TRUE;
603         $this->si_error_msg = $o->get_error();
604         msg_dialog::display(_("Service infrastructure"),msgPool::siError($o->get_error()),ERROR_DIALOG);      
605       }
606     }
607   }
609 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
610 ?>