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 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
96 if (defined $forward_to_gosa) {
97 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
98 }
100 # return message
101 return &create_xml_string($out_hash);
102 }
105 sub krb5_create_principal {
106 my ($msg, $msg_hash) = @_;
107 my $header = @{$msg_hash->{'header'}}[0];
108 my $source = @{$msg_hash->{'source'}}[0];
109 my $target = @{$msg_hash->{'target'}}[0];
110 my $session_id = @{$msg_hash->{'session_id'}}[0];
112 # build return message with twisted target and source
113 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
114 &add_content2xml_hash($out_hash, "session_id", $session_id);
116 # Sanity check
117 if (not defined @{$msg_hash->{'principal'}}[0]){
118 &add_content2xml_hash($out_hash, "error", "No principal specified");
119 return &create_xml_string($out_hash);
120 }
122 # Authenticate
123 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
124 my $principal;
125 if (not defined $kadm5){
126 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
127 } else {
128 $principal= Authen::Krb5::parse_name(@{$msg_hash->{'principal'}}[0]);
129 if(not defined $principal) {
130 &add_content2xml_hash($out_hash, "error", "Illegal principal name");
131 } else {
132 if ( $kadm5->get_principal($principal)){
133 &add_content2xml_hash($out_hash, "error", "Principal exists");
134 return &create_xml_string($out_hash);
135 }
137 my $princ= Authen::Krb5::Admin::Principal->new;
138 foreach ('mask', 'attributes', 'aux_attributes', 'max_life', 'max_renewable_life',
139 'policy', 'princ_expire_time', 'pw_expiration'){
141 if (defined @{$msg_hash->{$_}}[0]){
142 $princ->$_(@{$msg_hash->{$_}}[0]);
143 }
144 }
146 $princ->principal($principal);
147 $kadm5->create_principal($princ, join '', map { chr rand(255) + 1 } 1..256) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
149 # Directly randomize key
150 $kadm5->randkey_principal($princ);
151 }
152 }
154 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
155 if (defined $forward_to_gosa) {
156 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
157 }
159 # return message
160 return &create_xml_string($out_hash);
161 }
164 sub krb5_modify_principal {
165 my ($msg, $msg_hash) = @_;
166 my $header = @{$msg_hash->{'header'}}[0];
167 my $source = @{$msg_hash->{'source'}}[0];
168 my $target = @{$msg_hash->{'target'}}[0];
169 my $session_id = @{$msg_hash->{'session_id'}}[0];
171 # build return message with twisted target and source
172 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
173 &add_content2xml_hash($out_hash, "session_id", $session_id);
175 # Sanity check
176 if (not defined @{$msg_hash->{'principal'}}[0]){
177 &add_content2xml_hash($out_hash, "error", "No principal specified");
178 return &create_xml_string($out_hash);
179 }
181 # Authenticate
182 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
183 my $principal;
184 if (not defined $kadm5){
185 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
186 } else {
187 $principal= Authen::Krb5::parse_name(@{$msg_hash->{'principal'}}[0]);
188 if(not defined $principal) {
189 &add_content2xml_hash($out_hash, "error", "Illegal principal name");
190 } else {
191 if (not $kadm5->get_principal($principal)){
192 &add_content2xml_hash($out_hash, "error", "Principal does not exists");
193 return &create_xml_string($out_hash);
194 }
196 my $princ= Authen::Krb5::Admin::Principal->new;
197 foreach ('mask', 'attributes', 'aux_attributes', 'max_life', 'max_renewable_life',
198 'policy', 'princ_expire_time', 'pw_expiration'){
200 if (defined @{$msg_hash->{$_}}[0]){
201 $princ->$_(@{$msg_hash->{$_}}[0]);
202 }
203 }
205 $princ->principal($principal);
206 $kadm5->modify_principal($princ) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
207 }
208 }
210 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
211 if (defined $forward_to_gosa) {
212 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
213 }
215 # return message
216 return &create_xml_string($out_hash);
217 }
220 sub krb5_get_principal {
221 my ($msg, $msg_hash) = @_;
222 my $header = @{$msg_hash->{'header'}}[0];
223 my $source = @{$msg_hash->{'source'}}[0];
224 my $target = @{$msg_hash->{'target'}}[0];
225 my $session_id = @{$msg_hash->{'session_id'}}[0];
227 # build return message with twisted target and source
228 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
229 &add_content2xml_hash($out_hash, "session_id", $session_id);
231 # Sanity check
232 if (not defined @{$msg_hash->{'principal'}}[0]){
233 &add_content2xml_hash($out_hash, "error", "No principal specified");
234 return &create_xml_string($out_hash);
235 }
237 # Authenticate
238 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
239 my $principal;
240 if (not defined $kadm5){
241 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
242 } else {
243 $principal= Authen::Krb5::parse_name(@{$msg_hash->{'principal'}}[0]);
244 if(not defined $principal) {
245 &add_content2xml_hash($out_hash, "error", "Illegal principal name");
246 } else {
247 my $data= $kadm5->get_principal($principal) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
248 &add_content2xml_hash($out_hash, "principal", @{$msg_hash->{'principal'}}[0]);
249 &add_content2xml_hash($out_hash, "mask", $data->mask);
250 &add_content2xml_hash($out_hash, "attributes", $data->attributes);
251 &add_content2xml_hash($out_hash, "kvno", $data->kvno);
252 &add_content2xml_hash($out_hash, "max_life", $data->max_life);
253 &add_content2xml_hash($out_hash, "max_renewable_life", $data->max_renewable_life);
254 &add_content2xml_hash($out_hash, "aux_attributes", $data->aux_attributes);
255 &add_content2xml_hash($out_hash, "policy", $data->policy);
256 &add_content2xml_hash($out_hash, "fail_auth_count", $data->fail_auth_count);
257 &add_content2xml_hash($out_hash, "last_failed", $data->last_failed);
258 &add_content2xml_hash($out_hash, "last_pwd_change", $data->last_pwd_change);
259 &add_content2xml_hash($out_hash, "last_success", $data->last_success);
260 &add_content2xml_hash($out_hash, "mod_date", $data->mod_date);
261 &add_content2xml_hash($out_hash, "princ_expire_time", $data->princ_expire_time);
262 &add_content2xml_hash($out_hash, "pw_expiration", $data->pw_expiration);
263 }
264 }
266 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
267 if (defined $forward_to_gosa) {
268 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
269 }
271 # return message
272 return &create_xml_string($out_hash);
273 }
276 sub krb5_del_principal {
277 my ($msg, $msg_hash) = @_;
278 my $header = @{$msg_hash->{'header'}}[0];
279 my $source = @{$msg_hash->{'source'}}[0];
280 my $target = @{$msg_hash->{'target'}}[0];
281 my $session_id = @{$msg_hash->{'session_id'}}[0];
283 # build return message with twisted target and source
284 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
285 &add_content2xml_hash($out_hash, "session_id", $session_id);
287 # Sanity check
288 if (not defined @{$msg_hash->{'principal'}}[0]){
289 &add_content2xml_hash($out_hash, "error", "No principal specified");
290 return &create_xml_string($out_hash);
291 }
293 # Authenticate
294 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
295 my $principal;
296 if (not defined $kadm5){
297 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
298 } else {
299 $principal= Authen::Krb5::parse_name(@{$msg_hash->{'principal'}}[0]);
300 if(not defined $principal) {
301 &add_content2xml_hash($out_hash, "error", "Illegal principal name");
302 } else {
303 $kadm5->delete_principal($principal) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
304 }
305 }
307 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
308 if (defined $forward_to_gosa) {
309 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
310 }
312 # return message
313 return &create_xml_string($out_hash);
314 }
317 sub krb5_list_policies {
318 my ($msg, $msg_hash) = @_;
319 my $header = @{$msg_hash->{'header'}}[0];
320 my $source = @{$msg_hash->{'source'}}[0];
321 my $target = @{$msg_hash->{'target'}}[0];
322 my $session_id = @{$msg_hash->{'session_id'}}[0];
324 # build return message with twisted target and source
325 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
326 &add_content2xml_hash($out_hash, "session_id", $session_id);
328 # Authenticate
329 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
330 if (not defined $kadm5){
331 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
332 } else {
333 my @policies= $kadm5->get_policies() or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
334 for my $policy (@policies) {
335 &add_content2xml_hash($out_hash, "policy", $policy);
336 }
337 }
339 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
340 if (defined $forward_to_gosa) {
341 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
342 }
344 # return message
345 return &create_xml_string($out_hash);
346 }
349 sub krb5_get_policy {
350 my ($msg, $msg_hash) = @_;
351 my $header = @{$msg_hash->{'header'}}[0];
352 my $source = @{$msg_hash->{'source'}}[0];
353 my $target = @{$msg_hash->{'target'}}[0];
354 my $session_id = @{$msg_hash->{'session_id'}}[0];
356 # build return message with twisted target and source
357 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
358 &add_content2xml_hash($out_hash, "session_id", $session_id);
360 # Sanity check
361 if (not defined @{$msg_hash->{'policy'}}[0]){
362 &add_content2xml_hash($out_hash, "error", "No policy specified");
363 return &create_xml_string($out_hash);
364 }
366 # Authenticate
367 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
368 my $principal;
369 if (not defined $kadm5){
370 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
371 } else {
372 my $data= $kadm5->get_policy(@{$msg_hash->{'policy'}}[0]) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
373 &add_content2xml_hash($out_hash, "name", $data->name);
374 &add_content2xml_hash($out_hash, "mask", $data->mask);
375 &add_content2xml_hash($out_hash, "pw_history_num", $data->pw_history_num);
376 &add_content2xml_hash($out_hash, "pw_max_life", $data->pw_max_life);
377 &add_content2xml_hash($out_hash, "pw_min_classes", $data->pw_min_classes);
378 &add_content2xml_hash($out_hash, "pw_min_length", $data->pw_min_length);
379 &add_content2xml_hash($out_hash, "pw_min_life", $data->pw_min_life);
380 &add_content2xml_hash($out_hash, "policy_refcnt", $data->policy_refcnt);
381 }
383 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
384 if (defined $forward_to_gosa) {
385 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
386 }
388 # return message
389 return &create_xml_string($out_hash);
390 }
393 sub krb5_create_policy {
394 my ($msg, $msg_hash) = @_;
395 my $header = @{$msg_hash->{'header'}}[0];
396 my $source = @{$msg_hash->{'source'}}[0];
397 my $target = @{$msg_hash->{'target'}}[0];
398 my $session_id = @{$msg_hash->{'session_id'}}[0];
400 # Build return message
401 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
402 &add_content2xml_hash($out_hash, "session_id", $session_id);
404 # Sanity check
405 if (not defined @{$msg_hash->{'policy'}}[0]){
406 &add_content2xml_hash($out_hash, "error", "No policy specified");
407 return &create_xml_string($out_hash);
408 }
409 &add_content2xml_hash($msg_hash, "name", @{$msg_hash->{'policy'}}[0]);
411 # Authenticate
412 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
413 if (not defined $kadm5){
414 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
415 } else {
416 if ( $kadm5->get_policy(@{$msg_hash->{'policy'}}[0])) {
417 &add_content2xml_hash($out_hash, "error", "Policy exists");
418 return &create_xml_string($out_hash);
419 }
421 my $pol = Authen::Krb5::Admin::Policy->new;
423 # Move information from xml message to modifyer
424 foreach ('name', 'mask', 'pw_history_num', 'pw_max_life', 'pw_min_classes',
425 'pw_min_length', 'pw_min_life'){
427 if (defined @{$msg_hash->{$_}}[0]){
428 $pol->$_(@{$msg_hash->{$_}}[0]);
429 }
430 }
432 # Create info
433 $kadm5->create_policy($pol) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
434 }
436 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
437 if (defined $forward_to_gosa) {
438 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
439 }
441 # build return message with twisted target and source
442 my $out_msg = &create_xml_string($out_hash);
444 # return message
445 return $out_msg;
446 }
449 sub krb5_modify_policy {
450 my ($msg, $msg_hash) = @_;
451 my $header = @{$msg_hash->{'header'}}[0];
452 my $source = @{$msg_hash->{'source'}}[0];
453 my $target = @{$msg_hash->{'target'}}[0];
454 my $session_id = @{$msg_hash->{'session_id'}}[0];
456 # Build return message
457 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
458 &add_content2xml_hash($out_hash, "session_id", $session_id);
460 # Sanity check
461 if (not defined @{$msg_hash->{'policy'}}[0]){
462 &add_content2xml_hash($out_hash, "error", "No policy specified");
463 return &create_xml_string($out_hash);
464 }
465 &add_content2xml_hash($msg_hash, "name", @{$msg_hash->{'policy'}}[0]);
467 # Authenticate
468 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
469 if (not defined $kadm5){
470 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
471 } else {
472 my $pol = Authen::Krb5::Admin::Policy->new;
474 # Move information from xml message to modifyer
475 foreach ('name', 'mask', 'pw_history_num', 'pw_max_life', 'pw_min_classes',
476 'pw_min_length', 'pw_min_life'){
478 if (defined @{$msg_hash->{$_}}[0]){
479 $pol->$_(@{$msg_hash->{$_}}[0]);
480 }
481 }
483 # Create info
484 $kadm5->modify_policy($pol) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
485 }
487 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
488 if (defined $forward_to_gosa) {
489 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
490 }
492 # build return message with twisted target and source
493 my $out_msg = &create_xml_string($out_hash);
495 # return message
496 return $out_msg;
497 }
500 sub krb5_del_policy {
501 my ($msg, $msg_hash) = @_;
502 my $header = @{$msg_hash->{'header'}}[0];
503 my $source = @{$msg_hash->{'source'}}[0];
504 my $target = @{$msg_hash->{'target'}}[0];
505 my $session_id = @{$msg_hash->{'session_id'}}[0];
507 # build return message with twisted target and source
508 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
509 &add_content2xml_hash($out_hash, "session_id", $session_id);
511 # Sanity check
512 if (not defined @{$msg_hash->{'policy'}}[0]){
513 &add_content2xml_hash($out_hash, "error", "No policy specified");
514 return &create_xml_string($out_hash);
515 }
517 # Authenticate
518 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
519 my $policy= @{$msg_hash->{'policy'}}[0];
520 if (not defined $kadm5){
521 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
522 } else {
523 $kadm5->delete_policy($policy) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
524 }
526 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
527 if (defined $forward_to_gosa) {
528 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
529 }
531 # return message
532 return &create_xml_string($out_hash);
533 }
535 sub krb5_set_password {
536 my ($msg, $msg_hash) = @_;
537 my $header = @{$msg_hash->{'header'}}[0];
538 my $source = @{$msg_hash->{'source'}}[0];
539 my $target = @{$msg_hash->{'target'}}[0];
540 my $session_id = @{$msg_hash->{'session_id'}}[0];
542 # build return message with twisted target and source
543 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
544 &add_content2xml_hash($out_hash, "session_id", $session_id);
546 # Sanity check
547 if (not defined @{$msg_hash->{'principal'}}[0]){
548 &add_content2xml_hash($out_hash, "error", "No principal specified");
549 return &create_xml_string($out_hash);
550 }
551 if (not defined @{$msg_hash->{'password'}}[0]){
552 &add_content2xml_hash($out_hash, "error", "No password specified");
553 return &create_xml_string($out_hash);
554 }
556 # Authenticate
557 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
558 my $principal;
559 if (not defined $kadm5){
560 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
561 }
563 $principal= Authen::Krb5::parse_name(@{$msg_hash->{'principal'}}[0]);
564 if(not defined $principal) {
565 &add_content2xml_hash($out_hash, "error", "Illegal principal name");
566 } else {
567 $kadm5->chpass_principal($principal, @{$msg_hash->{'password'}}[0]) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
568 }
570 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
571 if (defined $forward_to_gosa) {
572 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
573 }
575 # return message
576 return &create_xml_string($out_hash);
577 }
578 1;