1 <?php
2 /*
3 This code is part of GOsa (https://gosa.gonicus.de)
4 Copyright (C) 2007 Cajus Pollmeier
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 */
22 class passwordMethodheimdal extends passwordMethod
23 {
25 var $krb5MaxLife = "";
26 var $krb5MaxRenew = "";
27 var $krb5ValidStart = "";
28 var $krb5ValidEnd = "";
29 var $krb5PasswordEnd = "";
30 var $krb5ValidStart_clear = TRUE;
31 var $krb5ValidEnd_clear = TRUE;
32 var $krb5PasswordEnd_clear = TRUE;
34 var $display = TRUE;
36 var $flag_list = array(
37 "0"=>"initial" ,
38 "1"=>"forwardable" ,
39 "2"=>"proxiable" ,
40 "3"=>"renewable" ,
41 "4"=>"postdate" ,
42 "5"=>"server" ,
43 "6"=>"client" ,
44 "7"=>"invalid" ,
45 "8"=>"require-preauth" ,
46 "9"=>"change-pw" ,
47 "10"=>"require-hwauth" ,
48 "11"=>"ok-as-delegate" ,
49 "12"=>"user-to-user" ,
50 "13"=>"immutable");
51 var $krb5KDCFlags = 123;
53 var $dn = "new";
54 var $parent_dn = "new";
55 var $attributes = array("krb5MaxLife","krb5MaxRenew","krb5KDCFlags",
56 "krb5ValidStart","krb5ValidEnd","krb5PasswordEnd");
57 var $attrs = array();
58 var $is_account = FALSE;
60 function passwordMethodheimdal(&$config,$dn = "new")
61 {
62 $this->config= $config;
63 $this->parent_dn = $dn;
65 $this->is_account = FALSE;
66 $this->krb5MaxLife = 86400;
67 $this->krb5MaxRenew = 604800;
68 $this->krb5ValidStart = date("Ymd",time())."0000Z";
69 $this->krb5ValidEnd = date("Ymd",time())."0000Z";
70 $this->krb5PasswordEnd= date("Ymd",time())."0000Z";
72 /* Load existing entries */
73 if($dn != "new"){
74 $ldap = $this->config->get_ldap_link();
75 $ldap->cd($dn);
76 $ldap->ls("objectClass=krb5Principal",$dn,array("*"));
77 if($ldap->count()==1){
78 $this->is_account = TRUE;
79 $this->attrs = $ldap->fetch();
80 $this->dn = $this->attrs['dn'];
81 foreach($this->attributes as $attr){
82 if(isset($this->attrs[$attr][0])){
83 $this->$attr = $this->attrs[$attr][0];
84 }else{
85 $this->$attr = "";
86 }
87 }
88 $date_values = array("krb5ValidStart","krb5ValidEnd","krb5PasswordEnd");
89 foreach($date_values as $date_val){
90 $clear = $date_val."_clear";
91 if(empty($this->$date_val)){
92 $this->$clear = TRUE;
93 }else{
94 $this->$clear = FALSE;
95 }
96 }
97 }elseif($ldap->count() >= 2){
98 new msg_dialog(_("Heimdal"),sprintf(_("Error loading heimdal configuration, more than one configuration entry was found for '%s'."),$this->parent_dn));
99 }
100 }
101 }
104 function is_available()
105 {
106 global $config;
107 $cmd = "";
108 if(isset($config->current['HEIMDAL_KEYGEN'])){
109 $cmd = $config->current['HEIMDAL_KEYGEN'];
110 if(!check_command($cmd)){
111 new msg_dialog(_("Heimdal"),sprintf(_("The configured HEIMDAL_KEYGEN '%s' is not a valid command."),$cmd),WARNING_DIALOG);
112 }
113 }
114 if(isset($this->config->data['MAIN']['HEIMDAL_KEYGEN'])){
115 $cmd = $this->config->data['MAIN']['HEIMDAL_KEYGEN'];
116 if(!check_command($cmd)){
117 new msg_dialog(_("Heimdal"),sprintf(_("The configured HEIMDAL_KEYGEN '%s' is not a valid command."),$cmd),WARNING_DIALOG);
118 }
119 }
120 if(isset($config->data['SERVERS']['KERBEROS']['REALM']) && check_command($cmd)){
121 return TRUE;
122 }else{
123 return FALSE;
124 }
125 }
128 function generate_hash($pwd)
129 {
130 $mode= "kerberos";
131 if (isset($this->config->current['KRBSASL']) && preg_match('/^true$/i', $this->config->current['KRBSASL'])){
132 $mode= "sasl";
133 }
135 return "{".$mode."}".$this->attrs['uid'][0]."@".$cfg= $this->config->data['SERVERS']['KERBEROS']['REALM'];
136 }
139 function remove_from_parent()
140 {
141 if($this->is_account && $this->dn != "new"){
142 $ldap = $this->config->get_ldap_link();
143 $ldap->cat($this->dn,array("dn"));
144 if($ldap->count()){
145 $ldap->rmdir($this->dn);
146 show_ldap_error($ldap->get_error(),_("Tried to remove heimdal extension."));
147 }
148 }
149 }
152 function set_password($password)
153 {
154 #TODO
155 # Add or modify kerberos entry below $this->dn
156 # See https://oss.gonicus.de/labs/gosa/ticket/223
157 # Order: create entries, then call the heimdal_keygen hook with the realm (returned by generate_hash)
158 # to let it add the missing kerberos keys.
160 global $config;
161 $cmd = "";
162 if(isset($config->current['HEIMDAL_KEYGEN'])){
163 $cmd = $config->current['HEIMDAL_KEYGEN'];
164 if(!check_command($cmd)){
165 new msg_dialog(_("Heimdal"),sprintf(_("The configured HEIMDAL_KEYGEN '%s' is not a valid command."),$cmd),WARNING_DIALOG);
166 }
167 }
168 if(isset($this->config->data['MAIN']['HEIMDAL_KEYGEN'])){
169 $cmd = $this->config->data['MAIN']['HEIMDAL_KEYGEN'];
170 if(!check_command($cmd)){
171 new msg_dialog(_("Heimdal"),sprintf(_("The configured HEIMDAL_KEYGEN '%s' is not a valid command."),$cmd),WARNING_DIALOG);
172 }
173 }
174 if ($cmd != ""){
176 /* Display in error message */
177 $cmdd = $cmd." '".$this->generate_hash($password)."' 'PASSWORD'";
179 /* Execute command and check return value */
180 $cmd = $cmd." '".$this->generate_hash($password)."' '".$password."'" ;
181 exec($cmd,$out,$res);
182 if($res != 0){
183 new msg_dialog(_("Heimdal"),sprintf(_("The configured HEIMDAL_KEYGEN '%s' wasn't successfully executed. Command does not return 0."),$cmdd),WARNING_DIALOG);
184 }
185 }
186 }
189 function get_hash_name()
190 {
191 $mode= "kerberos";
192 if (isset($this->config->current['KRBSASL']) && preg_match('/^true$/i', $this->config->current['KRBSASL'])){
193 $mode= "sasl";
194 }
195 return "$mode";
196 }
199 function is_configurable()
200 {
201 return TRUE;
202 }
205 function configure()
206 {
207 $this->save_object();
209 /* Cancel heimdal options */
210 if (isset($_POST['pw_abort'])){
211 return "";
212 }
214 /* Cancel heimdal options */
215 if (isset($_POST['pw_save'])){
216 $msgs = $this->check();
217 if(count($msgs)){
218 foreach($msgs as $msg){
219 msg_dialog::display(_("Heimdal"),$msg,WARNING_DIALOG);
220 }
221 }else{
222 $this->display = FALSE;
223 return "";
224 }
225 }
227 $years = array();
228 $start = date("Y")-1;
229 for($i = $start; $i < ($start +20) ; $i++){
230 $years[$i] = $i;
231 }
232 $month= array();
233 for($i = 1; $i <= 12 ; $i++){
234 $month[str_pad($i,2,"0",STR_PAD_LEFT)] = $i;
235 }
236 $days= array();
237 for($i = 1; $i <= 31 ; $i++){
238 $days[str_pad($i,2,"0",STR_PAD_LEFT)] = $i;
239 }
240 $hours= array();
241 for($i = 0; $i <= 23 ; $i++){
242 $hours[str_pad($i,2,"0",STR_PAD_LEFT)] = $i;
243 }
244 $minutes= array();
245 for($i = 0; $i <= 59 ; $i++){
246 $minutes[str_pad($i,2,"0",STR_PAD_LEFT)] = $i;
247 }
250 $smarty = get_smarty();
251 $smarty->assign("years",$years);
252 $smarty->assign("month",$month);
253 $smarty->assign("days",$days);
254 $smarty->assign("hours",$hours);
255 $smarty->assign("minutes",$minutes);
257 $date_values = array("krb5ValidStart","krb5ValidEnd","krb5PasswordEnd");
258 foreach($date_values as $date_val){
259 $clear = $date_val."_clear";
260 $smarty->assign($date_val."_clear",$this->$clear);
261 $smarty->assign($date_val."_y",substr($this->$date_val,0,4));
262 $smarty->assign($date_val."_m",substr($this->$date_val,4,2));
263 $smarty->assign($date_val."_d",substr($this->$date_val,6,2));
264 $smarty->assign($date_val."_h",substr($this->$date_val,8,2));
265 $smarty->assign($date_val."_i",substr($this->$date_val,10,2));
266 }
268 foreach($this->attributes as $attr){
269 $smarty->assign($attr ,$this->$attr);
270 }
271 foreach($this->flag_list as $key => $name){
272 $val = pow(2,$key);
273 if($this->krb5KDCFlags & $val){
274 $smarty->assign("krb5KDCFlags_".$key,TRUE);
275 }else{
276 $smarty->assign("krb5KDCFlags_".$key,FALSE);
277 }
278 }
280 return($smarty->fetch(get_template_path("pwd_heimdal.tpl")));
281 }
284 function save_object()
285 {
286 if(isset($_POST['pwd_heimdal_posted'])){
288 $date_values = array("krb5ValidStart","krb5ValidEnd","krb5PasswordEnd");
289 foreach($date_values as $date_value){
290 $clear = $date_value."_clear";
291 if(isset($_POST[$date_value."_clear"])){
292 $this->$clear = TRUE;
293 }else{
294 $this->$clear = FALSE;
295 $str = "";
296 foreach(array("y","m","d","h","i") as $val){
297 if(isset($_POST[$date_value."_".$val])){
298 $str .= $_POST[$date_value."_".$val];
299 }
300 }
301 $this->$date_value = $str."Z";
302 }
303 }
305 foreach($this->attributes as $attr){
306 if(isset($_POST[$attr])){
307 $this->$attr = get_post($attr);
308 }
309 }
311 $int = "";
312 foreach($this->flag_list as $key => $name){
313 $post = "krb5KDCFlags_".$key;
314 if(isset($_POST[$post])){
315 $int |= pow(2,$key);
316 }
317 }
318 $this->krb5KDCFlags = $int;
319 }
320 }
322 function check()
323 {
324 $message = array();
325 if(!is_numeric($this->krb5MaxLife) && !empty($this->krb5MaxLife)){
326 $message[] = sprintf(_("Please specify a numeric value for %s."),_("Max life"));
327 }
328 if(!is_numeric($this->krb5MaxRenew) && !empty($this->krb5MaxRenew)){
329 $message[] = sprintf(_("Please specify a numeric value for %s."),_("Max renew"));
330 }
331 if(!$this->krb5ValidStart_clear && !$this->chk_times($this->krb5ValidStart)){
332 $message[] = sprintf(_("Please specify a numeric value for %s."),_("Valid start"));
333 }
334 if(!$this->krb5ValidEnd_clear && !$this->chk_times($this->krb5ValidEnd)){
335 $message[] = sprintf(_("Please specify a numeric value for %s."),_("Valid end"));
336 }
337 if(!$this->krb5PasswordEnd_clear && !$this->chk_times($this->krb5PasswordEnd)){
338 $message[] = sprintf(_("Please specify a numeric value for %s."),_("Valid password"));
339 }
340 return($message);
341 }
344 function chk_times($str)
345 {
346 if(preg_match("/^([0-9]){12,12}[a-z]$/i",$str)){
347 return(true);
348 }
349 return(false);
350 }
353 function save($dn)
354 {
355 $realm = $this->config->data['SERVERS']['KERBEROS']['REALM'];
357 $ldap = $this->config->get_ldap_link();
358 $ldap->cd($dn);
359 $ldap->cat($dn,array('uid'));
360 $attrs = $ldap->fetch();
361 if(isset($attrs['uid'][0])){
363 $uid = $attrs['uid'][0];
364 $name = $uid."@".strtoupper($realm);
365 $dn = "krb5PrincipalName=".$name.",".$dn;
367 $data = array();
368 $data['krb5PrincipalName'] = $name;
369 $data['objectClass'] = array("top","account","krb5Principal","krb5KDCEntry");
370 $data['krb5PrincipalName'] =$name;
371 $data['uid'] = $uid;
372 $data['krb5KeyVersionNumber'] = rand(100000,99999999);
374 if($this->is_account){
375 foreach($this->attributes as $attr){
376 $data[$attr] = array();
377 }
378 }
380 /* Append Flags */
381 $data['krb5KDCFlags'] = $this->krb5KDCFlags;
382 if(!empty($this->krb5MaxLife)){
383 $data['krb5MaxLife'] = $this->krb5MaxLife;
384 }
385 if(!empty($this->krb5MaxRenew)){
386 $data['krb5MaxRenew'] = $this->krb5MaxRenew;
387 }
388 if(!$this->krb5ValidStart_clear){
389 $data['krb5ValidStart'] = $this->krb5ValidStart;
390 }
391 if(!$this->krb5ValidEnd_clear){
392 $data['krb5ValidEnd'] = $this->krb5ValidEnd;
393 }
394 if(!$this->krb5PasswordEnd_clear){
395 $data['krb5PasswordEnd']= $this->krb5PasswordEnd;
396 }
398 /* Add / Updated data */
399 $ldap->cd($dn);
400 if(!$this->is_account){
401 $ldap->add($data);
402 }else{
403 $ldap->modify($data);
404 }
405 show_ldap_error($ldap->get_error(),_("Could not add or update heimdal extensions."));
406 }
407 }
408 }
410 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
411 ?>