[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);
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);
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 }
608 }
609 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
610 ?>