1 package krb5;
2 use Exporter;
3 @ISA = qw(Exporter);
4 my @events = (
5 "get_events",
6 "krb5_list_principals",
7 "krb5_list_policies",
8 "krb5_get_principal",
9 "krb5_create_principal",
10 "krb5_modify_principal",
11 "krb5_del_principal",
12 "krb5_get_policy",
13 "krb5_create_policy",
14 "krb5_modify_policy",
15 "krb5_del_policy",
16 "krb5_set_password",
17 );
18 @EXPORT = @events;
20 use strict;
21 use warnings;
22 use Data::Dumper;
23 use GOSA::GosaSupportDaemon;
24 use Authen::Krb5;
25 use Authen::Krb5::Admin qw(:constants);
27 BEGIN {}
29 END {}
31 ### Start ######################################################################
33 Authen::Krb5::init_context;
34 Authen::Krb5::init_ets;
36 my $krb_admin;
37 my $krb_password;
39 my %cfg_defaults = (
40 "krb5" => {
41 "admin" => [\$krb_admin, ""],
42 "password" => [\$krb_password, ""],
43 },
44 );
45 &read_configfile($main::cfg_file, %cfg_defaults);
48 sub read_configfile {
49 my ($cfg_file, %cfg_defaults) = @_;
50 my $cfg;
52 if( defined( $cfg_file) && ( (-s $cfg_file) > 0 )) {
53 if( -r $cfg_file ) {
54 $cfg = Config::IniFiles->new( -file => $cfg_file );
55 } else {
56 &main::daemon_log("ERROR: krb5.pm couldn't read config file!", 1);
57 }
58 } else {
59 $cfg = Config::IniFiles->new() ;
60 }
61 foreach my $section (keys %cfg_defaults) {
62 foreach my $param (keys %{$cfg_defaults{ $section }}) {
63 my $pinfo = $cfg_defaults{ $section }{ $param };
64 ${@$pinfo[0]} = $cfg->val( $section, $param, @$pinfo[1] );
65 }
66 }
67 }
70 sub get_events { return \@events; }
73 sub krb5_list_principals {
74 my ($msg, $msg_hash) = @_;
75 my $header = @{$msg_hash->{'header'}}[0];
76 my $source = @{$msg_hash->{'source'}}[0];
77 my $target = @{$msg_hash->{'target'}}[0];
78 my $session_id = @{$msg_hash->{'session_id'}}[0];
80 # build return message with twisted target and source
81 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
82 &add_content2xml_hash($out_hash, "session_id", $session_id);
84 # Authenticate
85 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
86 if (not defined $kadm5){
87 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
88 } else {
89 my @principals= $kadm5->get_principals() or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
90 for my $principal (@principals) {
91 &add_content2xml_hash($out_hash, "principal", $principal);
92 }
93 }
95 # return message
96 return &create_xml_string($out_hash);
97 }
100 sub krb5_create_principal {
101 my ($msg, $msg_hash) = @_;
102 my $header = @{$msg_hash->{'header'}}[0];
103 my $source = @{$msg_hash->{'source'}}[0];
104 my $target = @{$msg_hash->{'target'}}[0];
105 my $session_id = @{$msg_hash->{'session_id'}}[0];
107 # build return message with twisted target and source
108 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
109 &add_content2xml_hash($out_hash, "session_id", $session_id);
111 # Sanity check
112 if (not defined @{$msg_hash->{'principal'}}[0]){
113 &add_content2xml_hash($out_hash, "error", "No principal specified");
114 return &create_xml_string($out_hash);
115 }
117 # Authenticate
118 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
119 my $principal;
120 if (not defined $kadm5){
121 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
122 } else {
123 $principal= Authen::Krb5::parse_name(@{$msg_hash->{'principal'}}[0]);
124 if(not defined $principal) {
125 &add_content2xml_hash($out_hash, "error", "Illegal principal name");
126 } else {
127 if ( $kadm5->get_principal($principal)){
128 &add_content2xml_hash($out_hash, "error", "Principal exists");
129 return &create_xml_string($out_hash);
130 }
132 my $princ= Authen::Krb5::Admin::Principal->new;
133 foreach ('mask', 'attributes', 'aux_attributes', 'max_life', 'max_renewable_life',
134 'policy', 'princ_expire_time', 'pw_expiration'){
136 if (defined @{$msg_hash->{$_}}[0]){
137 $princ->$_(@{$msg_hash->{$_}}[0]);
138 }
139 }
141 $princ->principal($principal);
142 $kadm5->create_principal($princ, join '', map { chr rand(255) + 1 } 1..256) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
144 # Directly randomize key
145 $kadm5->randkey_principal($princ);
146 }
147 }
149 # return message
150 return &create_xml_string($out_hash);
151 }
154 sub krb5_modify_principal {
155 my ($msg, $msg_hash) = @_;
156 my $header = @{$msg_hash->{'header'}}[0];
157 my $source = @{$msg_hash->{'source'}}[0];
158 my $target = @{$msg_hash->{'target'}}[0];
159 my $session_id = @{$msg_hash->{'session_id'}}[0];
161 # build return message with twisted target and source
162 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
163 &add_content2xml_hash($out_hash, "session_id", $session_id);
165 # Sanity check
166 if (not defined @{$msg_hash->{'principal'}}[0]){
167 &add_content2xml_hash($out_hash, "error", "No principal specified");
168 return &create_xml_string($out_hash);
169 }
171 # Authenticate
172 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
173 my $principal;
174 if (not defined $kadm5){
175 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
176 } else {
177 $principal= Authen::Krb5::parse_name(@{$msg_hash->{'principal'}}[0]);
178 if(not defined $principal) {
179 &add_content2xml_hash($out_hash, "error", "Illegal principal name");
180 } else {
181 if (not $kadm5->get_principal($principal)){
182 &add_content2xml_hash($out_hash, "error", "Principal does not exists");
183 return &create_xml_string($out_hash);
184 }
186 my $princ= Authen::Krb5::Admin::Principal->new;
187 foreach ('mask', 'attributes', 'aux_attributes', 'max_life', 'max_renewable_life',
188 'policy', 'princ_expire_time', 'pw_expiration'){
190 if (defined @{$msg_hash->{$_}}[0]){
191 $princ->$_(@{$msg_hash->{$_}}[0]);
192 }
193 }
195 $princ->principal($principal);
196 $kadm5->modify_principal($princ) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
197 }
198 }
200 # return message
201 return &create_xml_string($out_hash);
202 }
205 sub krb5_get_principal {
206 my ($msg, $msg_hash) = @_;
207 my $header = @{$msg_hash->{'header'}}[0];
208 my $source = @{$msg_hash->{'source'}}[0];
209 my $target = @{$msg_hash->{'target'}}[0];
210 my $session_id = @{$msg_hash->{'session_id'}}[0];
212 # build return message with twisted target and source
213 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
214 &add_content2xml_hash($out_hash, "session_id", $session_id);
216 # Sanity check
217 if (not defined @{$msg_hash->{'principal'}}[0]){
218 &add_content2xml_hash($out_hash, "error", "No principal specified");
219 return &create_xml_string($out_hash);
220 }
222 # Authenticate
223 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
224 my $principal;
225 if (not defined $kadm5){
226 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
227 } else {
228 $principal= Authen::Krb5::parse_name(@{$msg_hash->{'principal'}}[0]);
229 if(not defined $principal) {
230 &add_content2xml_hash($out_hash, "error", "Illegal principal name");
231 } else {
232 my $data= $kadm5->get_principal($principal) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
233 &add_content2xml_hash($out_hash, "principal", @{$msg_hash->{'principal'}}[0]);
234 &add_content2xml_hash($out_hash, "mask", $data->mask);
235 &add_content2xml_hash($out_hash, "attributes", $data->attributes);
236 &add_content2xml_hash($out_hash, "kvno", $data->kvno);
237 &add_content2xml_hash($out_hash, "max_life", $data->max_life);
238 &add_content2xml_hash($out_hash, "max_renewable_life", $data->max_renewable_life);
239 &add_content2xml_hash($out_hash, "aux_attributes", $data->aux_attributes);
240 &add_content2xml_hash($out_hash, "policy", $data->policy);
241 &add_content2xml_hash($out_hash, "fail_auth_count", $data->fail_auth_count);
242 &add_content2xml_hash($out_hash, "last_failed", $data->last_failed);
243 &add_content2xml_hash($out_hash, "last_pwd_change", $data->last_pwd_change);
244 &add_content2xml_hash($out_hash, "last_success", $data->last_success);
245 &add_content2xml_hash($out_hash, "mod_date", $data->mod_date);
246 &add_content2xml_hash($out_hash, "princ_expire_time", $data->princ_expire_time);
247 &add_content2xml_hash($out_hash, "pw_expiration", $data->pw_expiration);
248 }
249 }
251 # return message
252 return &create_xml_string($out_hash);
253 }
256 sub krb5_del_principal {
257 my ($msg, $msg_hash) = @_;
258 my $header = @{$msg_hash->{'header'}}[0];
259 my $source = @{$msg_hash->{'source'}}[0];
260 my $target = @{$msg_hash->{'target'}}[0];
261 my $session_id = @{$msg_hash->{'session_id'}}[0];
263 # build return message with twisted target and source
264 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
265 &add_content2xml_hash($out_hash, "session_id", $session_id);
267 # Sanity check
268 if (not defined @{$msg_hash->{'principal'}}[0]){
269 &add_content2xml_hash($out_hash, "error", "No principal specified");
270 return &create_xml_string($out_hash);
271 }
273 # Authenticate
274 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
275 my $principal;
276 if (not defined $kadm5){
277 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
278 } else {
279 $principal= Authen::Krb5::parse_name(@{$msg_hash->{'principal'}}[0]);
280 if(not defined $principal) {
281 &add_content2xml_hash($out_hash, "error", "Illegal principal name");
282 } else {
283 $kadm5->delete_principal($principal) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
284 }
285 }
287 # return message
288 return &create_xml_string($out_hash);
289 }
292 sub krb5_list_policies {
293 my ($msg, $msg_hash) = @_;
294 my $header = @{$msg_hash->{'header'}}[0];
295 my $source = @{$msg_hash->{'source'}}[0];
296 my $target = @{$msg_hash->{'target'}}[0];
297 my $session_id = @{$msg_hash->{'session_id'}}[0];
299 # build return message with twisted target and source
300 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
301 &add_content2xml_hash($out_hash, "session_id", $session_id);
303 # Authenticate
304 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
305 if (not defined $kadm5){
306 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
307 } else {
308 my @policies= $kadm5->get_policies() or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
309 for my $policy (@policies) {
310 &add_content2xml_hash($out_hash, "policy", $policy);
311 }
312 }
314 # return message
315 return &create_xml_string($out_hash);
316 }
319 sub krb5_get_policy {
320 my ($msg, $msg_hash) = @_;
321 my $header = @{$msg_hash->{'header'}}[0];
322 my $source = @{$msg_hash->{'source'}}[0];
323 my $target = @{$msg_hash->{'target'}}[0];
324 my $session_id = @{$msg_hash->{'session_id'}}[0];
326 # build return message with twisted target and source
327 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
328 &add_content2xml_hash($out_hash, "session_id", $session_id);
330 # Sanity check
331 if (not defined @{$msg_hash->{'policy'}}[0]){
332 &add_content2xml_hash($out_hash, "error", "No policy specified");
333 return &create_xml_string($out_hash);
334 }
336 # Authenticate
337 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
338 my $principal;
339 if (not defined $kadm5){
340 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
341 } else {
342 my $data= $kadm5->get_policy(@{$msg_hash->{'policy'}}[0]) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
343 &add_content2xml_hash($out_hash, "name", $data->name);
344 &add_content2xml_hash($out_hash, "mask", $data->mask);
345 &add_content2xml_hash($out_hash, "pw_history_num", $data->pw_history_num);
346 &add_content2xml_hash($out_hash, "pw_max_life", $data->pw_max_life);
347 &add_content2xml_hash($out_hash, "pw_min_classes", $data->pw_min_classes);
348 &add_content2xml_hash($out_hash, "pw_min_length", $data->pw_min_length);
349 &add_content2xml_hash($out_hash, "pw_min_life", $data->pw_min_life);
350 &add_content2xml_hash($out_hash, "policy_refcnt", $data->policy_refcnt);
351 }
353 # return message
354 return &create_xml_string($out_hash);
355 }
358 sub krb5_create_policy {
359 my ($msg, $msg_hash) = @_;
360 my $header = @{$msg_hash->{'header'}}[0];
361 my $source = @{$msg_hash->{'source'}}[0];
362 my $target = @{$msg_hash->{'target'}}[0];
363 my $session_id = @{$msg_hash->{'session_id'}}[0];
365 # Build return message
366 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
367 &add_content2xml_hash($out_hash, "session_id", $session_id);
369 # Sanity check
370 if (not defined @{$msg_hash->{'policy'}}[0]){
371 &add_content2xml_hash($out_hash, "error", "No policy specified");
372 return &create_xml_string($out_hash);
373 }
374 &add_content2xml_hash($msg_hash, "name", @{$msg_hash->{'policy'}}[0]);
376 # Authenticate
377 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
378 if (not defined $kadm5){
379 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
380 } else {
381 if ( $kadm5->get_policy(@{$msg_hash->{'policy'}}[0])) {
382 &add_content2xml_hash($out_hash, "error", "Policy exists");
383 return &create_xml_string($out_hash);
384 }
386 my $pol = Authen::Krb5::Admin::Policy->new;
388 # Move information from xml message to modifyer
389 foreach ('name', 'mask', 'pw_history_num', 'pw_max_life', 'pw_min_classes',
390 'pw_min_length', 'pw_min_life'){
392 if (defined @{$msg_hash->{$_}}[0]){
393 $pol->$_(@{$msg_hash->{$_}}[0]);
394 }
395 }
397 # Create info
398 $kadm5->create_policy($pol) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
399 }
401 # build return message with twisted target and source
402 my $out_msg = &create_xml_string($out_hash);
404 # return message
405 return $out_msg;
406 }
409 sub krb5_modify_policy {
410 my ($msg, $msg_hash) = @_;
411 my $header = @{$msg_hash->{'header'}}[0];
412 my $source = @{$msg_hash->{'source'}}[0];
413 my $target = @{$msg_hash->{'target'}}[0];
414 my $session_id = @{$msg_hash->{'session_id'}}[0];
416 # Build return message
417 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
418 &add_content2xml_hash($out_hash, "session_id", $session_id);
420 # Sanity check
421 if (not defined @{$msg_hash->{'policy'}}[0]){
422 &add_content2xml_hash($out_hash, "error", "No policy specified");
423 return &create_xml_string($out_hash);
424 }
425 &add_content2xml_hash($msg_hash, "name", @{$msg_hash->{'policy'}}[0]);
427 # Authenticate
428 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
429 if (not defined $kadm5){
430 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
431 } else {
432 my $pol = Authen::Krb5::Admin::Policy->new;
434 # Move information from xml message to modifyer
435 foreach ('name', 'mask', 'pw_history_num', 'pw_max_life', 'pw_min_classes',
436 'pw_min_length', 'pw_min_life'){
438 if (defined @{$msg_hash->{$_}}[0]){
439 $pol->$_(@{$msg_hash->{$_}}[0]);
440 }
441 }
443 # Create info
444 $kadm5->modify_policy($pol) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
445 }
447 # build return message with twisted target and source
448 my $out_msg = &create_xml_string($out_hash);
450 # return message
451 return $out_msg;
452 }
455 sub krb5_del_policy {
456 my ($msg, $msg_hash) = @_;
457 my $header = @{$msg_hash->{'header'}}[0];
458 my $source = @{$msg_hash->{'source'}}[0];
459 my $target = @{$msg_hash->{'target'}}[0];
460 my $session_id = @{$msg_hash->{'session_id'}}[0];
462 # build return message with twisted target and source
463 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
464 &add_content2xml_hash($out_hash, "session_id", $session_id);
466 # Sanity check
467 if (not defined @{$msg_hash->{'policy'}}[0]){
468 &add_content2xml_hash($out_hash, "error", "No policy specified");
469 return &create_xml_string($out_hash);
470 }
472 # Authenticate
473 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
474 my $policy= @{$msg_hash->{'policy'}}[0];
475 if (not defined $kadm5){
476 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
477 } else {
478 $kadm5->delete_policy($policy) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
479 }
481 # return message
482 return &create_xml_string($out_hash);
483 }
485 sub krb5_set_password {
486 my ($msg, $msg_hash) = @_;
487 my $header = @{$msg_hash->{'header'}}[0];
488 my $source = @{$msg_hash->{'source'}}[0];
489 my $target = @{$msg_hash->{'target'}}[0];
490 my $session_id = @{$msg_hash->{'session_id'}}[0];
492 # build return message with twisted target and source
493 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
494 &add_content2xml_hash($out_hash, "session_id", $session_id);
496 # Sanity check
497 if (not defined @{$msg_hash->{'principal'}}[0]){
498 &add_content2xml_hash($out_hash, "error", "No principal specified");
499 return &create_xml_string($out_hash);
500 }
501 if (not defined @{$msg_hash->{'password'}}[0]){
502 &add_content2xml_hash($out_hash, "error", "No password specified");
503 return &create_xml_string($out_hash);
504 }
506 # Authenticate
507 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
508 my $principal;
509 if (not defined $kadm5){
510 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
511 }
513 $principal= Authen::Krb5::parse_name(@{$msg_hash->{'principal'}}[0]);
514 if(not defined $principal) {
515 &add_content2xml_hash($out_hash, "error", "Illegal principal name");
516 } else {
517 $kadm5->chpass_principal($principal, @{$msg_hash->{'password'}}[0]) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
518 }
520 # return message
521 return &create_xml_string($out_hash);
522 }
523 1;