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);
143 }
144 }
146 # return message
147 return &create_xml_string($out_hash);
148 }
151 sub krb5_modify_principal {
152 my ($msg, $msg_hash) = @_;
153 my $header = @{$msg_hash->{'header'}}[0];
154 my $source = @{$msg_hash->{'source'}}[0];
155 my $target = @{$msg_hash->{'target'}}[0];
156 my $session_id = @{$msg_hash->{'session_id'}}[0];
158 # build return message with twisted target and source
159 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
160 &add_content2xml_hash($out_hash, "session_id", $session_id);
162 # Sanity check
163 if (not defined @{$msg_hash->{'principal'}}[0]){
164 &add_content2xml_hash($out_hash, "error", "No principal specified");
165 return &create_xml_string($out_hash);
166 }
168 # Authenticate
169 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
170 my $principal;
171 if (not defined $kadm5){
172 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
173 } else {
174 $principal= Authen::Krb5::parse_name(@{$msg_hash->{'principal'}}[0]);
175 if(not defined $principal) {
176 &add_content2xml_hash($out_hash, "error", "Illegal principal name");
177 } else {
178 if (not $kadm5->get_principal($principal)){
179 &add_content2xml_hash($out_hash, "error", "Principal does not exists");
180 return &create_xml_string($out_hash);
181 }
183 my $princ= Authen::Krb5::Admin::Principal->new;
184 foreach ('mask', 'attributes', 'aux_attributes', 'max_life', 'max_renewable_life',
185 'policy', 'princ_expire_time', 'pw_expiration'){
187 if (defined @{$msg_hash->{$_}}[0]){
188 $princ->$_(@{$msg_hash->{$_}}[0]);
189 }
190 }
192 $princ->principal($principal);
193 $kadm5->modify_principal($princ) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
194 }
195 }
197 # return message
198 return &create_xml_string($out_hash);
199 }
202 sub krb5_get_principal {
203 my ($msg, $msg_hash) = @_;
204 my $header = @{$msg_hash->{'header'}}[0];
205 my $source = @{$msg_hash->{'source'}}[0];
206 my $target = @{$msg_hash->{'target'}}[0];
207 my $session_id = @{$msg_hash->{'session_id'}}[0];
209 # build return message with twisted target and source
210 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
211 &add_content2xml_hash($out_hash, "session_id", $session_id);
213 # Sanity check
214 if (not defined @{$msg_hash->{'principal'}}[0]){
215 &add_content2xml_hash($out_hash, "error", "No principal specified");
216 return &create_xml_string($out_hash);
217 }
219 # Authenticate
220 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
221 my $principal;
222 if (not defined $kadm5){
223 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
224 } else {
225 $principal= Authen::Krb5::parse_name(@{$msg_hash->{'principal'}}[0]);
226 if(not defined $principal) {
227 &add_content2xml_hash($out_hash, "error", "Illegal principal name");
228 } else {
229 my $data= $kadm5->get_principal($principal) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
230 &add_content2xml_hash($out_hash, "principal", @{$msg_hash->{'principal'}}[0]);
231 &add_content2xml_hash($out_hash, "mask", $data->mask);
232 &add_content2xml_hash($out_hash, "attributes", $data->attributes);
233 &add_content2xml_hash($out_hash, "kvno", $data->kvno);
234 &add_content2xml_hash($out_hash, "max_life", $data->max_life);
235 &add_content2xml_hash($out_hash, "max_renewable_life", $data->max_renewable_life);
236 &add_content2xml_hash($out_hash, "aux_attributes", $data->aux_attributes);
237 &add_content2xml_hash($out_hash, "policy", $data->policy);
238 &add_content2xml_hash($out_hash, "fail_auth_count", $data->fail_auth_count);
239 &add_content2xml_hash($out_hash, "last_failed", $data->last_failed);
240 &add_content2xml_hash($out_hash, "last_pwd_change", $data->last_pwd_change);
241 &add_content2xml_hash($out_hash, "last_success", $data->last_success);
242 &add_content2xml_hash($out_hash, "mod_date", $data->mod_date);
243 &add_content2xml_hash($out_hash, "princ_expire_time", $data->princ_expire_time);
244 &add_content2xml_hash($out_hash, "pw_expiration", $data->pw_expiration);
245 }
246 }
248 # return message
249 return &create_xml_string($out_hash);
250 }
253 sub krb5_del_principal {
254 my ($msg, $msg_hash) = @_;
255 my $header = @{$msg_hash->{'header'}}[0];
256 my $source = @{$msg_hash->{'source'}}[0];
257 my $target = @{$msg_hash->{'target'}}[0];
258 my $session_id = @{$msg_hash->{'session_id'}}[0];
260 # build return message with twisted target and source
261 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
262 &add_content2xml_hash($out_hash, "session_id", $session_id);
264 # Sanity check
265 if (not defined @{$msg_hash->{'principal'}}[0]){
266 &add_content2xml_hash($out_hash, "error", "No principal specified");
267 return &create_xml_string($out_hash);
268 }
270 # Authenticate
271 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
272 my $principal;
273 if (not defined $kadm5){
274 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
275 } else {
276 $principal= Authen::Krb5::parse_name(@{$msg_hash->{'principal'}}[0]);
277 if(not defined $principal) {
278 &add_content2xml_hash($out_hash, "error", "Illegal principal name");
279 } else {
280 $kadm5->delete_principal($principal) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
281 }
282 }
284 # return message
285 return &create_xml_string($out_hash);
286 }
289 sub krb5_list_policies {
290 my ($msg, $msg_hash) = @_;
291 my $header = @{$msg_hash->{'header'}}[0];
292 my $source = @{$msg_hash->{'source'}}[0];
293 my $target = @{$msg_hash->{'target'}}[0];
294 my $session_id = @{$msg_hash->{'session_id'}}[0];
296 # build return message with twisted target and source
297 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
298 &add_content2xml_hash($out_hash, "session_id", $session_id);
300 # Authenticate
301 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
302 if (not defined $kadm5){
303 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
304 } else {
305 my @policies= $kadm5->get_policies() or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
306 for my $policy (@policies) {
307 &add_content2xml_hash($out_hash, "policy", $policy);
308 }
309 }
311 # return message
312 return &create_xml_string($out_hash);
313 }
316 sub krb5_get_policy {
317 my ($msg, $msg_hash) = @_;
318 my $header = @{$msg_hash->{'header'}}[0];
319 my $source = @{$msg_hash->{'source'}}[0];
320 my $target = @{$msg_hash->{'target'}}[0];
321 my $session_id = @{$msg_hash->{'session_id'}}[0];
323 # build return message with twisted target and source
324 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
325 &add_content2xml_hash($out_hash, "session_id", $session_id);
327 # Sanity check
328 if (not defined @{$msg_hash->{'policy'}}[0]){
329 &add_content2xml_hash($out_hash, "error", "No policy specified");
330 return &create_xml_string($out_hash);
331 }
333 # Authenticate
334 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
335 my $principal;
336 if (not defined $kadm5){
337 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
338 } else {
339 my $data= $kadm5->get_policy(@{$msg_hash->{'policy'}}[0]) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
340 &add_content2xml_hash($out_hash, "name", $data->name);
341 &add_content2xml_hash($out_hash, "mask", $data->mask);
342 &add_content2xml_hash($out_hash, "pw_history_num", $data->pw_history_num);
343 &add_content2xml_hash($out_hash, "pw_max_life", $data->pw_max_life);
344 &add_content2xml_hash($out_hash, "pw_min_classes", $data->pw_min_classes);
345 &add_content2xml_hash($out_hash, "pw_min_length", $data->pw_min_length);
346 &add_content2xml_hash($out_hash, "pw_min_life", $data->pw_min_life);
347 &add_content2xml_hash($out_hash, "policy_refcnt", $data->policy_refcnt);
348 }
350 # return message
351 return &create_xml_string($out_hash);
352 }
355 sub krb5_create_policy {
356 my ($msg, $msg_hash) = @_;
357 my $header = @{$msg_hash->{'header'}}[0];
358 my $source = @{$msg_hash->{'source'}}[0];
359 my $target = @{$msg_hash->{'target'}}[0];
360 my $session_id = @{$msg_hash->{'session_id'}}[0];
362 # Build return message
363 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
364 &add_content2xml_hash($out_hash, "session_id", $session_id);
366 # Sanity check
367 if (not defined @{$msg_hash->{'policy'}}[0]){
368 &add_content2xml_hash($out_hash, "error", "No policy specified");
369 return &create_xml_string($out_hash);
370 }
371 &add_content2xml_hash($msg_hash, "name", @{$msg_hash->{'policy'}}[0]);
373 # Authenticate
374 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
375 if (not defined $kadm5){
376 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
377 } else {
378 if ( $kadm5->get_policy(@{$msg_hash->{'policy'}}[0])) {
379 &add_content2xml_hash($out_hash, "error", "Policy exists");
380 return &create_xml_string($out_hash);
381 }
383 my $pol = Authen::Krb5::Admin::Policy->new;
385 # Move information from xml message to modifyer
386 foreach ('name', 'mask', 'pw_history_num', 'pw_max_life', 'pw_min_classes',
387 'pw_min_length', 'pw_min_life'){
389 if (defined @{$msg_hash->{$_}}[0]){
390 $pol->$_(@{$msg_hash->{$_}}[0]);
391 }
392 }
394 # Create info
395 $kadm5->create_policy($pol) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
396 }
398 # build return message with twisted target and source
399 my $out_msg = &create_xml_string($out_hash);
401 # return message
402 return $out_msg;
403 }
406 sub krb5_modify_policy {
407 my ($msg, $msg_hash) = @_;
408 my $header = @{$msg_hash->{'header'}}[0];
409 my $source = @{$msg_hash->{'source'}}[0];
410 my $target = @{$msg_hash->{'target'}}[0];
411 my $session_id = @{$msg_hash->{'session_id'}}[0];
413 # Build return message
414 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
415 &add_content2xml_hash($out_hash, "session_id", $session_id);
417 # Sanity check
418 if (not defined @{$msg_hash->{'policy'}}[0]){
419 &add_content2xml_hash($out_hash, "error", "No policy specified");
420 return &create_xml_string($out_hash);
421 }
422 &add_content2xml_hash($msg_hash, "name", @{$msg_hash->{'policy'}}[0]);
424 # Authenticate
425 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
426 if (not defined $kadm5){
427 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
428 } else {
429 my $pol = Authen::Krb5::Admin::Policy->new;
431 # Move information from xml message to modifyer
432 foreach ('name', 'mask', 'pw_history_num', 'pw_max_life', 'pw_min_classes',
433 'pw_min_length', 'pw_min_life'){
435 if (defined @{$msg_hash->{$_}}[0]){
436 $pol->$_(@{$msg_hash->{$_}}[0]);
437 }
438 }
440 # Create info
441 $kadm5->modify_policy($pol) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
442 }
444 # build return message with twisted target and source
445 my $out_msg = &create_xml_string($out_hash);
447 # return message
448 return $out_msg;
449 }
452 sub krb5_del_policy {
453 my ($msg, $msg_hash) = @_;
454 my $header = @{$msg_hash->{'header'}}[0];
455 my $source = @{$msg_hash->{'source'}}[0];
456 my $target = @{$msg_hash->{'target'}}[0];
457 my $session_id = @{$msg_hash->{'session_id'}}[0];
459 # build return message with twisted target and source
460 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
461 &add_content2xml_hash($out_hash, "session_id", $session_id);
463 # Sanity check
464 if (not defined @{$msg_hash->{'policy'}}[0]){
465 &add_content2xml_hash($out_hash, "error", "No policy specified");
466 return &create_xml_string($out_hash);
467 }
469 # Authenticate
470 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
471 my $policy= @{$msg_hash->{'policy'}}[0];
472 if (not defined $kadm5){
473 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
474 } else {
475 $kadm5->delete_policy($policy) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
476 }
478 # return message
479 return &create_xml_string($out_hash);
480 }
482 sub krb5_set_password {
483 my ($msg, $msg_hash) = @_;
484 my $header = @{$msg_hash->{'header'}}[0];
485 my $source = @{$msg_hash->{'source'}}[0];
486 my $target = @{$msg_hash->{'target'}}[0];
487 my $session_id = @{$msg_hash->{'session_id'}}[0];
489 # build return message with twisted target and source
490 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
491 &add_content2xml_hash($out_hash, "session_id", $session_id);
493 # Sanity check
494 if (not defined @{$msg_hash->{'principal'}}[0]){
495 &add_content2xml_hash($out_hash, "error", "No principal specified");
496 return &create_xml_string($out_hash);
497 }
498 if (not defined @{$msg_hash->{'password'}}[0]){
499 &add_content2xml_hash($out_hash, "error", "No password specified");
500 return &create_xml_string($out_hash);
501 }
503 # Authenticate
504 my $kadm5 = Authen::Krb5::Admin->init_with_password($krb_admin, $krb_password);
505 my $principal;
506 if (not defined $kadm5){
507 &add_content2xml_hash($out_hash, "error", "Cannot connect to kadmin server");
508 }
510 $principal= Authen::Krb5::parse_name(@{$msg_hash->{'principal'}}[0]);
511 if(not defined $principal) {
512 &add_content2xml_hash($out_hash, "error", "Illegal principal name");
513 } else {
514 $kadm5->chpass_principal($principal, @{$msg_hash->{'password'}}[0]) or &add_content2xml_hash($out_hash, "error", Authen::Krb5::Admin::error);
515 }
517 # return message
518 return &create_xml_string($out_hash);
519 }
520 1;