[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 }
117 /* Get a list of all kerberos servers, defined in ldap
118 and get a list of principals they are providing.
119 */
120 $ldap = $this->config->get_ldap_link();
121 $ldap->cd($this->config->current['BASE']);
122 $ldap->search("(&(objectClass=goServer)(objectClass=goKrbServer))",array("goKrbRealm","cn","description","macAddress"));
123 $this->server_list = array();
124 while($attrs = $ldap->fetch()){
125 if(!isset($attrs['macAddress'][0])) continue;
126 if(!isset($attrs['description'][0])) $attrs['description'][0] ="";
128 $principals = $this->load_principals_for_server($attrs['macAddress'][0]);
130 /* Create Realm/Server/Principal mapping.
131 */
132 foreach($principals as $principal){
133 $this->map["PRINCIPAL_SERVER"][$principal] = $attrs['cn'][0];
134 $this->map["PRINCIPAL_REALM"] [$principal] = $attrs['goKrbRealm'][0];
135 }
136 $this->map["SERVER_REALM"][$attrs['cn'][0]] = $attrs['goKrbRealm'][0];
137 $this->map["REALM_SERVER"][$attrs['goKrbRealm'][0]] = $attrs['cn'][0];
139 /* Set first realm as selected.
140 */
141 if($this->goKrbRealm == ""){
142 $this->goKrbRealm = $attrs['goKrbRealm'][0];
143 }
145 /* Create Server list
146 */
147 $this->server_list[$attrs['cn'][0]] = array("macAddress" => $attrs['macAddress'][0],
148 "description"=> $attrs['description'][0],
149 "dn" => $attrs['dn'],
150 "principals" => $principals,
151 "goKrbRealm" => $attrs['goKrbRealm'][0],
152 "cn" => $attrs['cn'][0]);
153 }
155 /* Load object data from ldap && initialize this class
156 */
157 $this->is_new = TRUE;
158 if($dn != "new" && $dn != ""){
159 $ldap = $this->config->get_ldap_link();
160 $ldap->cd($dn);
161 $ldap->cat($dn);
162 $this->attrs = $ldap->fetch();
163 if(isset($this->attrs['userPassword']) && preg_match("/".$this->get_hash_name()."/",$this->attrs['userPassword'][0])){
165 $p_name = preg_replace("/^\{".$this->get_hash_name()."\}/","",$this->attrs['userPassword'][0]);
167 /* Try to detect server our principal is configured on
168 */
169 if($this->map['PRINCIPAL_SERVER'][$p_name]){
170 $server= $this->map['PRINCIPAL_SERVER'][$p_name];
171 $this->goKrbRealm = $this->map['SERVER_REALM'][$server];
172 $this->principal = $p_name;
174 /* Load policies */
175 $server_name = $this->map['REALM_SERVER'][$this->goKrbRealm];
176 $server_mac = $this->server_list[$server_name]['macAddress'];
177 $this->POLICIES = $this->load_policies_for_server($server_mac);
179 /* Load principal */
180 $this->load_principal($this->server_list[$server]['macAddress'],$p_name);
181 $this->is_new = FALSE;
182 }
183 }
184 }
185 }
188 /*! \brief Load this plugin with the values of the given principal
189 @param String The macAddress of the kerberos server.
190 @param String The name of the principal to load.
191 */
192 public function load_principal($server,$name)
193 {
194 $o = new gosaSupportDaemon();
195 $tmp = array();
196 $tmp = $o->krb5_get_principal($server,$name);
197 if($o->is_error()){
199 $this->si_error = TRUE;
200 $this->si_error_msg = $o->get_error();
201 msg_dialog::display(_("Service infrastructure"),msgPool::siError($o->get_error()),ERROR_DIALOG);
202 }else{
204 /* Load flags
205 */
206 if(isset($tmp['ATTRIBUTES'])){
207 foreach($this->flags as $flag){
208 if(in_array($flag,$tmp['ATTRIBUTES'])){
209 $this->$flag = TRUE;
210 }
211 }
212 }
214 /* Load readonly attributes
215 */
216 foreach($this->readonly as $attr){
217 if(isset($tmp[$attr])){
218 $this->$flag = $tmp[$attr];
219 }
220 }
222 /* Load modifyable attributes
223 */
224 foreach($this->values as $attr){
225 if(isset($tmp[$attr])){
226 $this->$flag = $tmp[$attr];
227 }
228 }
229 }
230 }
233 /*! \brief get list of all configured principals
234 for a given server.
235 The results will cached.
236 */
237 public function load_principals_for_server($server)
238 {
239 if(!session::is_set("MIT_PRINCIPAL_CACHE")){
240 session::set("MIT_PRINCIPAL_CACHE",array());
241 }
242 $cache = session::get("MIT_PRINCIPAL_CACHE");
243 if(!isset($cache[$server])){
244 $o = new gosaSupportDaemon();
245 $tmp = $o->krb5_list_principals($server);
246 if($o->is_error()){
247 $this->si_error = TRUE;
248 $this->si_error_msg = $o->get_error();
249 msg_dialog::display(_("Service infrastructure"),msgPool::siError($o->get_error()),ERROR_DIALOG);
250 }else{
251 $cache[$server] = $tmp;
252 }
253 session::set("MIT_PRINCIPAL_CACHE",$cache);
254 }
255 return($cache[$server]);
256 }
259 /*! \brief get list of all configured policies
260 for a given server.
261 The results will cached.
262 */
263 public function load_policies_for_server($server)
264 {
265 if(!session::is_set("MIT_POLICY_CACHE")){
266 session::set("MIT_POLICY_CACHE",array());
267 }
268 $cache = session::get("MIT_POLICY_CACHE");
269 if(!isset($cache[$server])){
270 $o = new gosaSupportDaemon();
271 $tmp = $o->krb5_list_policies($server);
272 if($o->is_error()){
273 $this->si_error = TRUE;
274 $this->si_error_msg = $o->get_error();
275 msg_dialog::display(_("Service infrastructure"),msgPool::siError($o->get_error()),ERROR_DIALOG);
276 }else{
277 $cache[$server] = array();
278 $cache[$server]["_none_"] = _("none");
279 foreach($tmp as $policy){
280 $cache[$server][$policy] = $policy;
281 }
282 ksort($cache[$server]);
283 }
284 session::set("MIT_POLICY_CACHE",$cache);
285 }
286 return($cache[$server]);
287 }
290 /*! \brief Check if this password method is useable.
291 This is the case if there is a si server running and at least one server configured.
292 kerberos support.
293 */
294 function is_available()
295 {
296 $o = new gosaSupportDaemon(FALSE);
297 if(count($this->server_list) && $o->connect()){
298 return TRUE;
299 }
300 return(FALSE);
301 }
304 function generate_hash($pwd)
305 {
306 $mode= "kerberos";
307 if (isset($this->config->current['KRBSASL']) && preg_match('/^true$/i', $this->config->current['KRBSASL'])){
308 $mode= "sasl";
309 }
310 return "{".$mode."}".$this->attrs['uid'][0]."@".$this->goKrbRealm;
311 }
314 function remove_from_parent()
315 {
316 if(!empty($this->principal) && $this->goKrbRealm){
317 $server = $this->map['REALM_SERVER'][$this->goKrbRealm];
318 $o = new gosaSupportDaemon();
319 if(!$o->krb5_del_principal($this->server_list[$server]['macAddress'],$this->principal)){
320 $this->si_error = TRUE;
321 $this->si_error_msg = $o->get_error();
322 msg_dialog::display(_("Service infrastructure"),msgPool::siError($o->get_error()),ERROR_DIALOG);
323 }
324 }
325 }
328 function set_password($password)
329 {
330 if(!empty($this->principal) && $this->goKrbRealm){
331 $server = $this->map['REALM_SERVER'][$this->goKrbRealm];
332 $o = new gosaSupportDaemon();
334 echo "Not implemented yet";
335 $attrs = array("password" => $password);
337 # if(!$o->krb5_set_principal($this->server_list[$server]['macAddress'],$this->principal,$attrs)){
338 # msg_dialog::display(_("Service infrastructure"),msgPool::siError($o->get_error()),ERROR_DIALOG);
339 # }
340 }
341 }
344 function get_hash_name()
345 {
346 $mode= "kerberos";
347 if (isset($this->config->current['KRBSASL']) && preg_match('/^true$/i', $this->config->current['KRBSASL'])){
348 $mode= "sasl";
349 }
350 return "$mode";
351 }
354 function is_configurable()
355 {
356 return TRUE;
357 }
360 function configure()
361 {
362 $this->save_object();
364 $years = array();
365 $start = date("Y")-1;
366 for($i = $start; $i < ($start +20) ; $i++){
367 $years[$i] = $i;
368 }
369 $month= array();
370 for($i = 1; $i <= 12 ; $i++){
371 $month[str_pad($i,2,"0",STR_PAD_LEFT)] = $i;
372 }
373 $days= array();
374 for($i = 1; $i <= 31 ; $i++){
375 $days[str_pad($i,2,"0",STR_PAD_LEFT)] = $i;
376 }
377 $hours= array();
378 for($i = 0; $i <= 23 ; $i++){
379 $hours[str_pad($i,2,"0",STR_PAD_LEFT)] = $i;
380 }
381 $minutes= array();
382 for($i = 0; $i <= 59 ; $i++){
383 $minutes[str_pad($i,2,"0",STR_PAD_LEFT)] = $i;
384 }
387 /* Cancel heimdal options */
388 if (isset($_POST['pw_abort']) || $this->display == FALSE){
389 $this->display = FALSE;
390 return("");
391 }
393 /* Cancel heimdal options */
394 if (isset($_POST['pw_save'])){
395 $msgs = $this->check();
396 if(count($msgs)){
397 foreach($msgs as $msg){
398 msg_dialog::display(_("Heimdal"),$msg,WARNING_DIALOG);
399 }
400 }else{
401 $this->display = FALSE;
402 return "";
403 }
404 }
407 $smarty = get_smarty();
409 $smarty->assign("si_error",$this->si_error);
410 $smarty->assign("si_error_msg",$this->si_error_msg);
412 $smarty->assign("years",$years);
413 $smarty->assign("month",$month);
414 $smarty->assign("days",$days);
415 $smarty->assign("hours",$hours);
416 $smarty->assign("minutes",$minutes);
418 $smarty->assign("server_list",$this->server_list);
419 $smarty->assign("POLICY" ,$this->POLICY);
420 $smarty->assign("goKrbRealm" , $this->goKrbRealm);
422 $server_name = $this->map['REALM_SERVER'][$this->goKrbRealm];
423 $server_mac = $this->server_list[$server_name]['macAddress'];
424 $this->POLICIES = $this->load_policies_for_server($server_mac);
425 $smarty->assign("POLICIES" ,$this->POLICIES);
427 foreach($this->values as $attr){
428 $smarty->assign($attr ,$this->$attr);
429 }
430 foreach($this->readonly as $attr){
431 $smarty->assign($attr ,$this->$attr);
432 }
433 foreach($this->flags as $attr){
434 $smarty->assign($attr,$this->$attr);
435 }
437 $date_values = array("PRINC_EXPIRE_TIME","PW_EXPIRATION");
438 foreach($date_values as $date_val){
439 $clear = $date_val."_clear";
440 $smarty->assign($date_val."_clear",$this->$clear);
441 $smarty->assign($date_val."_y",substr($this->$date_val,0,4));
442 $smarty->assign($date_val."_m",substr($this->$date_val,4,2));
443 $smarty->assign($date_val."_d",substr($this->$date_val,6,2));
444 $smarty->assign($date_val."_h",substr($this->$date_val,8,2));
445 $smarty->assign($date_val."_i",substr($this->$date_val,10,2));
446 }
449 return($smarty->fetch(get_template_path("pwd_kerberos_mit.tpl")));
450 }
453 function save_object()
454 {
455 /* If the communication with the si server failed,
456 you are able to retry to connect to the server.
457 Here we hanlde those requests.
458 */
459 if(isset($_POST['retry_si'])){
460 $this->si_error= FALSE;
461 $this->si_error_msg= "";
462 session::un_set("MIT_PRINCIPAL_CACHE");
463 session::un_set("MIT_POLICY_CACHE");
464 $this->__construct($this->config,$this->parent_dn);
465 }
467 /* Only handle posts for this plugin, it its content was posted
468 */
469 if(isset($_POST['pwd_heimdal_posted'])){
471 if(isset($_POST['goKrbRealm'])){
472 $this->goKrbRealm = get_post("goKrbRealm");
473 }
475 foreach($this->flags as $attr){
476 $this->$attr = isset($_POST[$attr]);
477 }
479 foreach(array("MAX_LIFE","MAX_RENEWABLE_LIFE","POLICY") as $attr){
480 if(isset($_POST[$attr])){
481 $this->$attr = get_post($attr);
482 }
483 }
485 $date_values = array("PW_EXPIRATION","PRINC_EXPIRE_TIME");
486 foreach($date_values as $date_value){
487 $clear = $date_value."_clear";
488 if(isset($_POST[$date_value."_clear"])){
489 $this->$clear = TRUE;
490 }else{
491 $this->$clear = FALSE;
492 $str = "";
493 foreach(array("y","m","d","h","i") as $val){
494 if(isset($_POST[$date_value."_".$val])){
495 $str .= $_POST[$date_value."_".$val];
496 }
497 }
498 $this->$date_value = $str."Z";
499 }
500 }
501 }
502 }
504 function check()
505 {
506 $message = array();
507 echo "Checks missing";
508 return($message);
509 }
512 function chk_times($str)
513 {
514 if(preg_match("/^([0-9]){12,12}[a-z]$/i",$str)){
515 return(true);
516 }
517 return(false);
518 }
521 function save($dn)
522 {
523 $realm = $this->config->data['SERVERS']['KERBEROS']['REALM'];
525 $ldap = $this->config->get_ldap_link();
526 $ldap->cd($dn);
527 $ldap->cat($dn,array('uid'));
528 $attrs = $ldap->fetch();
529 if(isset($attrs['uid'][0])){
531 /* Get servers mac */
532 $server_name = $this->map['REALM_SERVER'][$this->goKrbRealm];
533 $server_mac = $this->server_list[$server_name]['macAddress'];
535 $uid = $attrs['uid'][0];
536 $principal = $uid."@".strtoupper($this->goKrbRealm);
537 $policy = $this->POLICY;
539 /* Collect flags */
540 $flags = array();
541 $entry = array();
542 foreach($this->flags as $flag){
543 if($this->$flag){
544 $flags[] = $flag;
545 }
546 }
547 if(count($flags)){
548 $entry['ATTRIBUTES'] = $flags;
549 }
551 /* Append other values */
552 foreach($this->values as $attr){
553 if($attr == "POLICY") continue;
554 $entry[$attr] = $this->$attr;
555 }
557 /* Prepare entry to be saved */
558 if($policy != "_none_"){
559 $entry['POLICY'] = $policy;
560 }
562 /* Save principal changes */
563 $o = new gosaSupportDaemon();
564 if($this->is_new){
565 $o->krb5_add_principal($server_mac,$principal,$entry);
566 }else{
567 $o->krb5_set_principal($server_mac,$principal,$entry);
568 }
569 if($o->is_error()){
570 $this->si_error = TRUE;
571 $this->si_error_msg = $o->get_error();
572 msg_dialog::display(_("Service infrastructure"),msgPool::siError($o->get_error()),ERROR_DIALOG);
573 }
574 }
575 }
576 }
577 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
578 ?>