1 package gosaTriggered;
2 use Exporter;
3 @ISA = qw(Exporter);
4 my @events = (
5 "get_events",
6 "get_login_usr_for_client",
7 "get_client_for_login_usr",
8 "gen_smb_hash",
9 "trigger_reload_ldap_config",
10 "ping",
11 "network_completition",
12 "set_activated_for_installation",
13 "new_key_for_client",
14 "detect_hardware",
15 "get_login_usr",
16 "get_login_client",
17 "trigger_action_localboot",
18 "trigger_action_faireboot",
19 "trigger_action_reboot",
20 "trigger_action_activate",
21 "trigger_action_lock",
22 "trigger_action_halt",
23 "trigger_action_update",
24 "trigger_action_reinstall",
25 "trigger_action_memcheck",
26 "trigger_action_sysinfo",
27 "trigger_action_instant_update",
28 "trigger_action_rescan",
29 "trigger_action_wake",
30 "recreate_fai_server_db",
31 "recreate_fai_release_db",
32 "recreate_packages_list_db",
33 "send_user_msg",
34 "get_available_kernel",
35 "trigger_activate_new",
36 "get_dak_keyring",
37 "import_dak_key",
38 "remove_dak_key",
39 # "get_dak_queue",
40 );
41 @EXPORT = @events;
43 use strict;
44 use warnings;
45 use GOSA::GosaSupportDaemon;
46 use Data::Dumper;
47 use Crypt::SmbHash;
48 use Net::ARP;
49 use Net::Ping;
50 use Socket;
51 use Time::HiRes qw( usleep);
52 use MIME::Base64;
54 BEGIN {}
56 END {}
58 ### Start ######################################################################
60 #&main::read_configfile($main::cfg_file, %cfg_defaults);
62 sub get_events {
63 return \@events;
64 }
66 sub send_user_msg {
67 my ($msg, $msg_hash, $session_id) = @_ ;
68 my $header = @{$msg_hash->{'header'}}[0];
69 my $source = @{$msg_hash->{'source'}}[0];
70 my $target = @{$msg_hash->{'target'}}[0];
72 #my $subject = &decode_base64(@{$msg_hash->{'subject'}}[0]);
73 my $subject = @{$msg_hash->{'subject'}}[0];
74 my $from = @{$msg_hash->{'from'}}[0];
75 my @users = @{$msg_hash->{'users'}};
76 my @groups = @{$msg_hash->{'groups'}};
77 my $delivery_time = @{$msg_hash->{'delivery_time'}}[0];
78 #my $message = &decode_base64(@{$msg_hash->{'message'}}[0]);
79 my $message = @{$msg_hash->{'message'}}[0];
81 # keep job queue uptodate if necessary
82 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
83 if( defined $jobdb_id) {
84 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
85 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
86 my $res = $main::job_db->exec_statement($sql_statement);
87 }
89 # error handling
90 if (not $delivery_time =~ /^\d{14}$/) {
91 my $error_string = "delivery_time '$delivery_time' is not a valid timestamp, please use format 'yyyymmddhhmmss'";
92 &main::daemon_log("$session_id ERROR: $error_string", 1);
93 return &create_xml_string(&create_xml_hash($header, $target, $source, $error_string));
94 }
96 # add incoming message to messaging_db
97 my $new_msg_id = 1;
98 my $new_msg_id_sql = "SELECT MAX(CAST(id AS INTEGER)) FROM $main::messaging_tn";
99 my $new_msg_id_res = $main::messaging_db->exec_statement($new_msg_id_sql);
100 if (defined @{@{$new_msg_id_res}[0]}[0] ) {
101 $new_msg_id = int(@{@{$new_msg_id_res}[0]}[0]);
102 $new_msg_id += 1;
103 }
105 # highlight user name and group name
106 my @receiver_l;
107 @users = map(push(@receiver_l, "u_$_"), @users);
108 @groups = map(push(@receiver_l, "g_$_"), @groups);
110 my $func_dic = {table=>$main::messaging_tn,
111 primkey=>[],
112 id=>$new_msg_id,
113 subject=>$subject,
114 message_from=>$from,
115 message_to=>join(",", @receiver_l),
116 flag=>"n",
117 direction=>"in",
118 delivery_time=>$delivery_time,
119 message=>$message,
120 timestamp=>&get_time(),
121 };
122 my $res = $main::messaging_db->add_dbentry($func_dic);
123 if (not $res == 0) {
124 &main::daemon_log("$session_id ERROR: gosaTriggered.pm: cannot add message to message_db: $res", 1);
125 } else {
126 &main::daemon_log("$session_id INFO: gosaTriggered.pm: message with subject '$subject' successfully added to message_db", 5);
127 }
129 return;
130 }
133 sub recreate_fai_server_db {
134 my ($msg, $msg_hash, $session_id) = @_ ;
135 my $out_msg;
137 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
138 if( defined $jobdb_id) {
139 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
140 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
141 my $res = $main::job_db->exec_statement($sql_statement);
142 }
144 $main::fai_server_db->create_table("new_fai_server", \@main::fai_server_col_names);
145 &main::create_fai_server_db("new_fai_server",undef,"dont", $session_id);
146 $main::fai_server_db->move_table("new_fai_server", $main::fai_server_tn);
148 my @out_msg_l = ( $out_msg );
149 return @out_msg_l;
150 }
153 sub recreate_fai_release_db {
154 my ($msg, $msg_hash, $session_id) = @_ ;
155 my $out_msg;
157 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
158 if( defined $jobdb_id) {
159 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
160 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
161 my $res = $main::job_db->exec_statement($sql_statement);
162 }
164 $main::fai_release_db->create_table("new_fai_release", \@main::fai_release_col_names);
165 &main::create_fai_release_db("new_fai_release", $session_id);
166 $main::fai_release_db->move_table("new_fai_release", $main::fai_release_tn);
168 my @out_msg_l = ( $out_msg );
169 return @out_msg_l;
170 }
173 sub recreate_packages_list_db {
174 my ($msg, $msg_hash, $session_id) = @_ ;
175 my $out_msg;
177 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
178 if( defined $jobdb_id) {
179 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
180 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
181 my $res = $main::job_db->exec_statement($sql_statement);
182 }
184 &main::create_packages_list_db;
186 my @out_msg_l = ( $out_msg );
187 return @out_msg_l;
188 }
191 sub get_login_usr_for_client {
192 my ($msg, $msg_hash, $session_id) = @_ ;
193 my $header = @{$msg_hash->{'header'}}[0];
194 my $source = @{$msg_hash->{'source'}}[0];
195 my $target = @{$msg_hash->{'target'}}[0];
196 my $client = @{$msg_hash->{'client'}}[0];
198 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
199 if( defined $jobdb_id) {
200 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
201 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
202 my $res = $main::job_db->exec_statement($sql_statement);
203 }
205 $header =~ s/^gosa_//;
207 my $sql_statement = "SELECT * FROM known_clients WHERE hostname='$client' OR macaddress LIKE '$client'";
208 my $res = $main::known_clients_db->select_dbentry($sql_statement);
210 my $out_msg = "<xml><header>$header</header><source>$target</source><target>$source</target>";
211 $out_msg .= &db_res2xml($res);
212 $out_msg .= "</xml>";
214 my @out_msg_l = ( $out_msg );
215 return @out_msg_l;
216 }
219 sub get_client_for_login_usr {
220 my ($msg, $msg_hash, $session_id) = @_ ;
221 my $header = @{$msg_hash->{'header'}}[0];
222 my $source = @{$msg_hash->{'source'}}[0];
223 my $target = @{$msg_hash->{'target'}}[0];
225 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
226 if( defined $jobdb_id) {
227 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
228 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
229 my $res = $main::job_db->exec_statement($sql_statement);
230 }
232 my $usr = @{$msg_hash->{'usr'}}[0];
233 $header =~ s/^gosa_//;
235 my $sql_statement = "SELECT * FROM known_clients WHERE login LIKE '%$usr%'";
236 my $res = $main::known_clients_db->select_dbentry($sql_statement);
238 my $out_msg = "<xml><header>$header</header><source>$target</source><target>$source</target>";
239 $out_msg .= &db_res2xml($res);
240 $out_msg .= "</xml>";
241 my @out_msg_l = ( $out_msg );
242 return @out_msg_l;
244 }
247 sub ping {
248 my ($msg, $msg_hash, $session_id) = @_ ;
249 my $header = @{$msg_hash->{header}}[0];
250 my $target = @{$msg_hash->{target}}[0];
251 my $source = @{$msg_hash->{source}}[0];
252 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
253 my $error = 0;
254 my $answer_msg;
255 my ($sql, $res);
257 if( defined $jobdb_id) {
258 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
259 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
260 my $res = $main::job_db->exec_statement($sql_statement);
261 }
263 # send message
264 $sql = "SELECT * FROM $main::known_clients_tn WHERE ((hostname='$target') || (macaddress LIKE '$target'))";
265 $res = $main::known_clients_db->exec_statement($sql);
267 # sanity check of db result
268 my ($host_name, $host_key);
269 if ((defined $res) && (@$res > 0) && @{@$res[0]} > 0) {
270 $host_name = @{@$res[0]}[0];
271 $host_key = @{@$res[0]}[2];
272 } else {
273 &main::daemon_log("$session_id ERROR: cannot determine host_name and host_key from known_clients_db at function ping\n$msg", 1);
274 my %data = ( 'answer_xml' => 'host not found in known_clients_db' );
275 $answer_msg = &build_msg("got_ping_error", $target, $source, \%data);
276 $error = 1;
277 }
279 if (not $error) {
280 my $client_hash = &create_xml_hash("ping", $main::server_address, $host_name);
281 &add_content2xml_hash($client_hash, 'session_id', $session_id);
282 my $client_msg = &create_xml_string($client_hash);
283 &main::send_msg_to_target($client_msg, $host_name, $host_key, $header, $session_id);
285 my $message_id;
286 my $i = 0;
287 while (1) {
288 $i++;
289 $sql = "SELECT * FROM $main::incoming_tn WHERE headertag='answer_$session_id'";
290 $res = $main::incoming_db->exec_statement($sql);
291 if (ref @$res[0] eq "ARRAY") {
292 $message_id = @{@$res[0]}[0];
293 last;
294 }
296 # do not run into a endless loop
297 if ($i > 100) { last; }
298 usleep(100000);
299 }
301 my $answer_xml = @{@$res[0]}[3];
302 my %data = ( 'answer_xml' => 'bin noch da' );
303 $answer_msg = &build_msg("got_ping", $target, $source, \%data);
304 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
305 if (defined $forward_to_gosa){
306 $answer_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
307 }
308 $sql = "DELETE FROM $main::incoming_tn WHERE id=$message_id";
309 $res = $main::incoming_db->exec_statement($sql);
310 }
312 return ( $answer_msg );
313 }
317 sub gen_smb_hash {
318 my ($msg, $msg_hash, $session_id) = @_ ;
319 my $source = @{$msg_hash->{source}}[0];
320 my $target = @{$msg_hash->{target}}[0];
321 my $password = @{$msg_hash->{password}}[0];
323 my %data= ('hash' => join(q[:], ntlmgen $password));
324 my $out_msg = &build_msg("gen_smb_hash", $target, $source, \%data );
325 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
326 if (defined $forward_to_gosa) {
327 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
328 }
330 return ( $out_msg );
331 }
334 sub network_completition {
335 my ($msg, $msg_hash, $session_id) = @_ ;
336 my $source = @{$msg_hash->{source}}[0];
337 my $target = @{$msg_hash->{target}}[0];
338 my $name = @{$msg_hash->{hostname}}[0];
340 # Can we resolv the name?
341 my %data;
342 if (inet_aton($name)){
343 my $address = inet_ntoa(inet_aton($name));
344 my $p = Net::Ping->new('tcp');
345 my $mac= "";
346 if ($p->ping($address, 1)){
347 $mac = Net::ARP::arp_lookup("", $address);
348 }
350 %data= ('ip' => $address, 'mac' => $mac);
351 } else {
352 %data= ('ip' => '', 'mac' => '');
353 }
355 my $out_msg = &build_msg("network_completition", $target, $source, \%data );
356 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
357 if (defined $forward_to_gosa) {
358 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
359 }
361 return ( $out_msg );
362 }
365 sub detect_hardware {
366 my ($msg, $msg_hash, $session_id) = @_ ;
367 # just forward msg to client, but dont forget to split off 'gosa_' in header
368 my $source = @{$msg_hash->{source}}[0];
369 my $target = @{$msg_hash->{target}}[0];
370 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
371 if( defined $jobdb_id) {
372 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
373 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
374 my $res = $main::job_db->exec_statement($sql_statement);
375 }
377 my $out_hash = &create_xml_hash("detect_hardware", $source, $target);
378 if( defined $jobdb_id ) {
379 &add_content2xml_hash($out_hash, 'jobdb_id', $jobdb_id);
380 }
381 my $out_msg = &create_xml_string($out_hash);
383 my @out_msg_l = ( $out_msg );
384 return @out_msg_l;
386 }
389 sub trigger_reload_ldap_config {
390 my ($msg, $msg_hash, $session_id) = @_ ;
391 my $target = @{$msg_hash->{target}}[0];
393 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
394 if( defined $jobdb_id) {
395 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
396 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
397 my $res = $main::job_db->exec_statement($sql_statement);
398 }
400 my $out_msg = &ClientPackages::new_ldap_config($target, $session_id);
401 my @out_msg_l = ( $out_msg );
403 return @out_msg_l;
404 }
407 sub set_activated_for_installation {
408 my ($msg, $msg_hash, $session_id) = @_;
409 my $header = @{$msg_hash->{header}}[0];
410 my $source = @{$msg_hash->{source}}[0];
411 my $target = @{$msg_hash->{target}}[0];
412 my @out_msg_l;
414 # update status of job
415 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
416 if( defined $jobdb_id) {
417 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
418 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
419 my $res = $main::job_db->exec_statement($sql_statement);
420 }
422 # create set_activated_for_installation message for delivery
423 my $out_hash = &create_xml_hash("set_activated_for_installation", $source, $target);
424 if( defined $jobdb_id ) {
425 &add_content2xml_hash($out_hash, 'jobdb_id', $jobdb_id);
426 }
427 my $out_msg = &create_xml_string($out_hash);
428 push(@out_msg_l, $out_msg);
430 return @out_msg_l;
431 }
434 sub trigger_action_faireboot {
435 my ($msg, $msg_hash, $session_id) = @_;
436 my $macaddress = @{$msg_hash->{macaddress}}[0];
437 my $source = @{$msg_hash->{source}}[0];
439 my @out_msg_l;
440 $msg =~ s/<header>gosa_trigger_action_faireboot<\/header>/<header>trigger_action_faireboot<\/header>/;
441 push(@out_msg_l, $msg);
443 &main::change_goto_state('locked', \@{$msg_hash->{macaddress}}, $session_id);
444 &main::change_fai_state('install', \@{$msg_hash->{macaddress}}, $session_id);
446 # delete all jobs from jobqueue which correspond to fai
447 my $sql_statement = "DELETE FROM $main::job_queue_tn WHERE (macaddress='$macaddress' AND ".
448 "status='processing')";
449 $main::job_db->del_dbentry($sql_statement );
451 return @out_msg_l;
452 }
455 sub trigger_action_lock {
456 my ($msg, $msg_hash, $session_id) = @_;
457 my $macaddress = @{$msg_hash->{macaddress}}[0];
458 my $source = @{$msg_hash->{source}}[0];
460 &main::change_goto_state('locked', \@{$msg_hash->{macaddress}}, $session_id);
461 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
462 if( defined $jobdb_id) {
463 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
464 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
465 my $res = $main::job_db->exec_statement($sql_statement);
466 }
468 my @out_msg_l;
469 return @out_msg_l;
470 }
473 sub trigger_action_activate {
474 my ($msg, $msg_hash, $session_id) = @_;
475 my $macaddress = @{$msg_hash->{macaddress}}[0];
476 my $source = @{$msg_hash->{source}}[0];
478 &main::change_goto_state('active', \@{$msg_hash->{macaddress}}, $session_id);
479 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
480 if( defined $jobdb_id) {
481 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
482 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
483 my $res = $main::job_db->exec_statement($sql_statement);
484 }
486 my $out_hash = &create_xml_hash("set_activated_for_installation", $source, $macaddress);
487 if( exists $msg_hash->{'jobdb_id'} ) {
488 &add_content2xml_hash($out_hash, 'jobdb_id', @{$msg_hash->{'jobdb_id'}}[0]);
489 }
490 my $out_msg = &create_xml_string($out_hash);
492 return ( $out_msg );
493 }
496 sub trigger_action_localboot {
497 my ($msg, $msg_hash, $session_id) = @_;
498 $msg =~ s/<header>gosa_trigger_action_localboot<\/header>/<header>trigger_action_localboot<\/header>/;
499 &main::change_fai_state('localboot', \@{$msg_hash->{macaddress}}, $session_id);
500 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
501 if( defined $jobdb_id) {
502 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
503 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
504 my $res = $main::job_db->exec_statement($sql_statement);
505 }
507 my @out_msg_l = ($msg);
508 return @out_msg_l;
509 }
512 sub trigger_action_halt {
513 my ($msg, $msg_hash, $session_id) = @_;
514 $msg =~ s/<header>gosa_trigger_action_halt<\/header>/<header>trigger_action_halt<\/header>/;
516 &main::change_fai_state('halt', \@{$msg_hash->{macaddress}}, $session_id);
517 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
518 if( defined $jobdb_id) {
519 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
520 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
521 my $res = $main::job_db->exec_statement($sql_statement);
522 }
524 my @out_msg_l = ($msg);
525 return @out_msg_l;
526 }
529 sub trigger_action_reboot {
530 my ($msg, $msg_hash, $session_id) = @_;
531 $msg =~ s/<header>gosa_trigger_action_reboot<\/header>/<header>trigger_action_reboot<\/header>/;
533 &main::change_fai_state('reboot', \@{$msg_hash->{macaddress}}, $session_id);
534 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
535 if( defined $jobdb_id) {
536 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
537 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
538 my $res = $main::job_db->exec_statement($sql_statement);
539 }
541 my @out_msg_l = ($msg);
542 return @out_msg_l;
543 }
546 sub trigger_action_memcheck {
547 my ($msg, $msg_hash, $session_id) = @_ ;
548 $msg =~ s/<header>gosa_trigger_action_memcheck<\/header>/<header>trigger_action_memcheck<\/header>/;
550 &main::change_fai_state('memcheck', \@{$msg_hash->{macaddress}}, $session_id);
551 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
552 if( defined $jobdb_id) {
553 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
554 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
555 my $res = $main::job_db->exec_statement($sql_statement);
556 }
558 my @out_msg_l = ($msg);
559 return @out_msg_l;
560 }
563 sub trigger_action_reinstall {
564 my ($msg, $msg_hash, $session_id) = @_;
565 $msg =~ s/<header>gosa_trigger_action_reinstall<\/header>/<header>trigger_action_reinstall<\/header>/;
567 &main::change_fai_state('reinstall', \@{$msg_hash->{macaddress}}, $session_id);
569 my %data = ( 'macAddress' => \@{$msg_hash->{macaddress}} );
570 my $wake_msg = &build_msg("trigger_wake", "GOSA", "KNOWN_SERVER", \%data);
571 my @out_msg_l = ($wake_msg, $msg);
572 return @out_msg_l;
573 }
576 sub trigger_action_update {
577 my ($msg, $msg_hash, $session_id) = @_;
578 $msg =~ s/<header>gosa_trigger_action_update<\/header>/<header>trigger_action_update<\/header>/;
580 &main::change_fai_state('update', \@{$msg_hash->{macaddress}}, $session_id);
582 my %data = ( 'macAddress' => \@{$msg_hash->{macaddress}} );
583 my $wake_msg = &build_msg("trigger_wake", "GOSA", "KNOWN_SERVER", \%data);
584 my @out_msg_l = ($wake_msg, $msg);
585 return @out_msg_l;
586 }
589 sub trigger_action_instant_update {
590 my ($msg, $msg_hash, $session_id) = @_;
591 $msg =~ s/<header>gosa_trigger_action_instant_update<\/header>/<header>trigger_action_instant_update<\/header>/;
593 &main::change_fai_state('update', \@{$msg_hash->{macaddress}}, $session_id);
595 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
596 if( defined $jobdb_id) {
597 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
598 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
599 my $res = $main::job_db->exec_statement($sql_statement);
600 }
602 my %data = ( 'macAddress' => \@{$msg_hash->{macaddress}} );
603 my $wake_msg = &build_msg("trigger_wake", "GOSA", "KNOWN_SERVER", \%data);
604 my @out_msg_l = ($wake_msg, $msg);
605 return @out_msg_l;
606 }
609 sub trigger_action_sysinfo {
610 my ($msg, $msg_hash, $session_id) = @_;
611 $msg =~ s/<header>gosa_trigger_action_sysinfo<\/header>/<header>trigger_action_sysinfo<\/header>/;
613 &main::change_fai_state('sysinfo', \@{$msg_hash->{macaddress}}, $session_id);
614 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
615 if( defined $jobdb_id) {
616 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
617 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
618 my $res = $main::job_db->exec_statement($sql_statement);
619 }
621 my @out_msg_l = ($msg);
622 return @out_msg_l;
623 }
626 sub new_key_for_client {
627 my ($msg, $msg_hash, $session_id) = @_;
629 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
630 if( defined $jobdb_id) {
631 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
632 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
633 my $res = $main::job_db->exec_statement($sql_statement);
634 }
636 $msg =~ s/<header>gosa_new_key_for_client<\/header>/<header>new_key<\/header>/;
637 my @out_msg_l = ($msg);
638 return @out_msg_l;
639 }
642 sub trigger_action_rescan {
643 my ($msg, $msg_hash, $session_id) = @_;
645 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
646 if( defined $jobdb_id) {
647 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
648 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
649 my $res = $main::job_db->exec_statement($sql_statement);
650 }
653 $msg =~ s/<header>gosa_trigger_action_rescan<\/header>/<header>trigger_action_rescan<\/header>/;
654 my @out_msg_l = ($msg);
655 return @out_msg_l;
656 }
659 sub trigger_action_wake {
660 my ($msg, $msg_hash, $session_id) = @_;
662 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
663 if( defined $jobdb_id) {
664 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
665 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
666 my $res = $main::job_db->exec_statement($sql_statement);
667 }
669 # build out message
670 my $out_hash = &create_xml_hash("trigger_wake", "GOSA", "KNOWN_SERVER");
671 &add_content2xml_hash($out_hash, 'macAddress', @{$msg_hash->{macaddress}}[0]);
672 my $out_msg = &create_xml_string($out_hash);
674 # invoke trigger wake for this gosa-si-server
675 &main::server_server_com::trigger_wake($out_msg, $out_hash, $session_id);
677 #my %data = ( 'macAddress' => \@{$msg_hash->{macaddress}} );
678 #my $out_msg = &build_msg("trigger_wake", "GOSA", "KNOWN_SERVER", \%data);
680 # send trigger wake to all other gosa-si-server
681 my @out_msg_l = ($out_msg);
682 return @out_msg_l;
683 }
686 sub get_available_kernel {
687 my ($msg, $msg_hash, $session_id) = @_;
689 my $source = @{$msg_hash->{'source'}}[0];
690 my $target = @{$msg_hash->{'target'}}[0];
691 my $release= @{$msg_hash->{'release'}}[0];
693 my @kernel;
694 # Get Kernel packages for release
695 my $sql_statement = "SELECT * FROM $main::packages_list_tn WHERE distribution='$release' AND package LIKE 'linux\-image\-%'";
696 my $res_hash = $main::packages_list_db->select_dbentry($sql_statement);
697 my %data;
698 my $i=1;
700 foreach my $package (keys %{$res_hash}) {
701 $data{"answer".$i++}= $data{"answer".$i++}= ${$res_hash}{$package}->{'package'};
702 }
703 $data{"answer".$i++}= "default";
705 my $out_msg = &build_msg("get_available_kernel", $target, $source, \%data);
706 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
707 if (defined $forward_to_gosa) {
708 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
709 }
711 return ( $out_msg );
712 }
715 sub trigger_activate_new {
716 my ($msg, $msg_hash, $session_id) = @_;
718 my $source = @{$msg_hash->{'source'}}[0];
719 my $target = @{$msg_hash->{'target'}}[0];
720 my $header= @{$msg_hash->{'header'}}[0];
721 my $mac= (defined($msg_hash->{'mac'}))?@{$msg_hash->{'mac'}}[0]:undef;
722 my $ogroup= (defined($msg_hash->{'ogroup'}))?@{$msg_hash->{'ogroup'}}[0]:undef;
723 my $timestamp= (defined($msg_hash->{'timestamp'}))?@{$msg_hash->{'timestamp'}}[0]:undef;
724 my $base= (defined($msg_hash->{'base'}))?@{$msg_hash->{'base'}}[0]:undef;
725 my $hostname= (defined($msg_hash->{'fqdn'}))?@{$msg_hash->{'fqdn'}}[0]:undef;
726 my $ip_address= (defined($msg_hash->{'ip'}))?@{$msg_hash->{'ip'}}[0]:undef;
727 my $dhcp_statement= (defined($msg_hash->{'dhcp'}))?@{$msg_hash->{'dhcp'}}[0]:undef;
728 my $jobdb_id= (defined($msg_hash->{'jobdb_id'}))?@{$msg_hash->{'jobdb_id'}}[0]:undef;
730 my $ldap_handle = &main::get_ldap_handle();
731 my $ldap_entry;
732 my $ogroup_entry;
733 my $changed_attributes_counter = 0;
735 eval {
737 my $ldap_mesg= $ldap_handle->search(
738 base => $main::ldap_base,
739 scope => 'sub',
740 filter => "(&(objectClass=gosaGroupOfnames)(cn=$ogroup))",
741 );
742 if($ldap_mesg->count == 1) {
743 $ogroup_entry= $ldap_mesg->pop_entry();
744 } elsif ($ldap_mesg->count == 0) {
745 &main::daemon_log("ERROR: A GosaGroupOfNames with cn '$ogroup' was not found in base '".$main::ldap_base."'!", 1);
746 } else {
747 &main::daemon_log("ERROR: More than one ObjectGroups with cn '$ogroup' was found in base '".$main::ldap_base."'!", 1);
748 }
750 # build the base, use optional base parameter or take it from ogroup
751 if(!(defined($base) && (length($base) > 0))) {
752 # Subtract the ObjectGroup cn
753 $base = $1 if $ogroup_entry->dn =~ /cn=$ogroup,ou=groups,(.*)$/;
754 }
756 # prepend ou=systems (configurable through config)
757 $base = $main::new_systems_ou.",".$base;
759 # Search for an existing entry (should be in ou=incoming)
760 $ldap_mesg= $ldap_handle->search(
761 base => $main::ldap_base,
762 scope => 'sub',
763 filter => "(&(objectClass=GOhard)(|(macAddress=$mac)(dhcpHWaddress=$mac)))",
764 );
766 # TODO: Find a way to guess an ip address for hosts with no ldap entry (MAC->ARP->IP)
768 if($ldap_mesg->count == 1) {
769 &main::daemon_log("DEBUG: One system with mac address '$mac' was found in base '".$main::ldap_base."'!", 6);
770 # Get the entry from LDAP
771 $ldap_entry= $ldap_mesg->pop_entry();
773 if(!($ldap_entry->dn() eq "cn=".$ldap_entry->get_value('cn').",$base")) {
774 # Move the entry to the new ou
775 $ldap_entry->changetype('moddn');
776 $ldap_entry->add(
777 newrdn => "cn=".$ldap_entry->get_value('cn'),
778 deleteoldrdn => 1,
779 newsuperior => $base,
780 );
781 }
783 }
785 $ldap_mesg= $ldap_handle->search(
786 base => $main::ldap_base,
787 scope => 'sub',
788 filter => "(&(objectClass=GOhard)(|(macAddress=$mac)(dhcpHWaddress=$mac)))",
789 );
791 # TODO: Find a way to guess an ip address for hosts with no ldap entry (MAC->ARP->IP)
793 if($ldap_mesg->count == 1) {
794 $ldap_entry= $ldap_mesg->pop_entry();
795 # Check for needed objectClasses
796 my $oclasses = $ldap_entry->get_value('objectClass', asref => 1);
797 foreach my $oclass ("FAIobject", "GOhard") {
798 if(!(scalar grep $_ eq $oclass, map {$_ => 1} @$oclasses)) {
799 &main::daemon_log("Adding objectClass $oclass", 1);
800 $ldap_entry->add(
801 objectClass => $oclass,
802 );
803 my $oclass_result = $ldap_entry->update($ldap_handle);
804 }
805 }
807 # Set FAIstate
808 if(defined($ldap_entry->get_value('FAIstate'))) {
809 if(!($ldap_entry->get_value('FAIstate') eq 'install')) {
810 $ldap_entry->replace(
811 'FAIstate' => 'install'
812 );
813 my $replace_result = $ldap_entry->update($ldap_handle);
814 }
815 } else {
816 $ldap_entry->add(
817 'FAIstate' => 'install'
818 );
819 my $add_result = $ldap_entry->update($ldap_handle);
820 }
823 } elsif ($ldap_mesg->count == 0) {
824 # TODO: Create a new entry
825 # $ldap_entry = Net::LDAP::Entry->new();
826 # $ldap_entry->dn("cn=$mac,$base");
827 &main::daemon_log("WARNING: No System with mac address '$mac' was found in base '".$main::ldap_base."'! Re-queuing job.", 4);
828 $main::job_db->exec_statement("UPDATE jobs SET status = 'waiting', timestamp = '".&get_time()."' WHERE id = $jobdb_id");
829 } else {
830 &main::daemon_log("ERROR: More than one system with mac address '$mac' was found in base '".$main::ldap_base."'!", 1);
831 }
833 # Add to ObjectGroup
834 if(!(scalar grep $_, map {$_ => 1} $ogroup_entry->get_value('member', asref => 1))) {
835 $ogroup_entry->add (
836 'member' => $ldap_entry->dn(),
837 );
838 my $ogroup_result = $ogroup_entry->update($ldap_handle);
839 if ($ogroup_result->code() != 0) {
840 &main::daemon_log("ERROR: Updating the ObjectGroup '$ogroup' failed (code '".$ogroup_result->code()."') with '".$ogroup_result->{'errorMessage'}."'!", 1);
841 }
842 }
844 # Finally set gotoMode to active
845 if(defined($ldap_entry->get_value('gotoMode'))) {
846 if(!($ldap_entry->get_value('gotoMode') eq 'active')) {
847 $ldap_entry->replace(
848 'gotoMode' => 'active'
849 );
850 my $activate_result = $ldap_entry->update($ldap_handle);
851 if ($activate_result->code() != 0) {
852 &main::daemon_log("ERROR: Activating system '".$ldap_entry->dn()."' failed (code '".$activate_result->code()."') with '".$activate_result->{'errorMessage'}."'!", 1);
853 }
854 }
855 } else {
856 $ldap_entry->add(
857 'gotoMode' => 'active'
858 );
859 my $activate_result = $ldap_entry->update($ldap_handle);
860 if ($activate_result->code() != 0) {
861 &main::daemon_log("ERROR: Activating system '".$ldap_entry->dn()."' failed (code '".$activate_result->code()."') with '".$activate_result->{'errorMessage'}."'!", 1);
862 }
863 }
864 };
865 if($@) {
866 &main::daemon_log("ERROR: activate_new failed with '$@'!", 1);
867 }
869 # Delete job
870 $main::job_db->exec_statement("DELETE FROM jobs WHERE id = $jobdb_id");
872 # create set_activated_for_installation message for delivery
873 my $out_hash = &create_xml_hash("set_activated_for_installation", $source, $target);
874 my $out_msg = &create_xml_string($out_hash);
875 my @out_msg_l = ($out_msg);
877 return @out_msg_l;
878 }
881 sub get_dak_keyring {
882 my ($msg, $msg_hash) = @_;
883 my $source = @{$msg_hash->{'source'}}[0];
884 my $target = @{$msg_hash->{'target'}}[0];
885 my $header= @{$msg_hash->{'header'}}[0];
886 my $session_id = @{$msg_hash->{'session_id'}}[0];
888 # build return message with twisted target and source
889 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
890 &add_content2xml_hash($out_hash, "session_id", $session_id);
892 my @keys;
893 my %data;
895 my $keyring = $main::dak_signing_keys_directory."/keyring.gpg";
897 my $gpg_cmd = `which gpg`; chomp $gpg_cmd;
898 my $gpg = "$gpg_cmd --no-default-keyring --no-random-seed --keyring $keyring";
900 # Check if the keyrings are in place and readable
901 if(
902 &run_as($main::dak_user, "test -r $keyring")->{'resultCode'} != 0
903 ) {
904 &add_content2xml_hash($out_hash, "error", "DAK Keyring is not readable");
905 } else {
906 my $command = "$gpg --list-keys";
907 my $output = &run_as($main::dak_user, $command);
908 &main::daemon_log("$session_id DEBUG: ".$output->{'command'}, 7);
910 my $i=0;
911 foreach (@{$output->{'output'}}) {
912 if ($_ =~ m/^pub\s.*$/) {
913 ($keys[$i]->{'pub'}->{'length'}, $keys[$i]->{'pub'}->{'uid'}, $keys[$i]->{'pub'}->{'created'}) = ($1, $2, $3)
914 if $_ =~ m/^pub\s*?(\w*?)\/(\w*?)\s(\d{4}-\d{2}-\d{2})/;
915 $keys[$i]->{'pub'}->{'expires'} = $1 if $_ =~ m/^pub\s*?\w*?\/\w*?\s\d{4}-\d{2}-\d{2}\s\[expires:\s(\d{4}-\d{2}-\d{2})\]/;
916 $keys[$i]->{'pub'}->{'expired'} = $1 if $_ =~ m/^pub\s*?\w*?\/\w*?\s\d{4}-\d{2}-\d{2}\s\[expired:\s(\d{4}-\d{2}-\d{2})\]/;
917 } elsif ($_ =~ m/^sub\s.*$/) {
918 ($keys[$i]->{'sub'}->{'length'}, $keys[$i]->{'sub'}->{'uid'}, $keys[$i]->{'sub'}->{'created'}) = ($1, $2, $3)
919 if $_ =~ m/^sub\s*?(\w*?)\/(\w*?)\s(\d{4}-\d{2}-\d{2})/;
920 $keys[$i]->{'sub'}->{'expires'} = $1 if $_ =~ m/^pub\s*?\w*?\/\w*?\s\d{4}-\d{2}-\d{2}\s\[expires:\s(\d{4}-\d{2}-\d{2})\]/;
921 $keys[$i]->{'sub'}->{'expired'} = $1 if $_ =~ m/^pub\s*?\w*?\/\w*?\s\d{4}-\d{2}-\d{2}\s\[expired:\s(\d{4}-\d{2}-\d{2})\]/;
922 } elsif ($_ =~ m/^uid\s.*$/) {
923 push @{$keys[$i]->{'uid'}}, $1 if $_ =~ m/^uid\s*?([^\s].*?)$/;
924 } elsif ($_ =~ m/^$/) {
925 $i++;
926 }
927 }
928 }
930 my $i=0;
931 foreach my $key (@keys) {
932 # &main::daemon_log(Dumper($key));
933 &add_content2xml_hash($out_hash, "answer".$i++, $key);
934 }
935 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
936 if (defined $forward_to_gosa) {
937 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
938 }
939 return &create_xml_string($out_hash);
940 }
943 sub import_dak_key {
944 my ($msg, $msg_hash) = @_;
945 my $source = @{$msg_hash->{'source'}}[0];
946 my $target = @{$msg_hash->{'target'}}[0];
947 my $header= @{$msg_hash->{'header'}}[0];
948 my $session_id = @{$msg_hash->{'session_id'}}[0];
949 my $key = &decode_base64(@{$msg_hash->{'key'}}[0]);
951 # build return message with twisted target and source
952 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
953 &add_content2xml_hash($out_hash, "session_id", $session_id);
955 my %data;
957 my $keyring = $main::dak_signing_keys_directory."/keyring.gpg";
959 my $gpg_cmd = `which gpg`; chomp $gpg_cmd;
960 my $gpg = "$gpg_cmd --no-default-keyring --no-random-seed --keyring $keyring";
962 # Check if the keyrings are in place and writable
963 if(
964 &run_as($main::dak_user, "test -w $keyring")->{'resultCode'} != 0
965 ) {
966 &add_content2xml_hash($out_hash, "error", "DAK Keyring is not writable");
967 } else {
968 my $keyfile;
969 open($keyfile, ">/tmp/gosa_si_tmp_dak_key");
970 print $keyfile $key;
971 close($keyfile);
972 my $command = "$gpg --import /tmp/gosa_si_tmp_dak_key";
973 my $output = &run_as($main::dak_user, $command);
974 &main::daemon_log("$session_id DEBUG: ".$output->{'command'}, 7);
975 unlink("/tmp/gosa_si_tmp_dak_key");
977 if($output->{'resultCode'} != 0) {
978 &add_content2xml_hash($out_hash, "error", "Import of DAK key failed! Output was '".$output->{'output'}."'");
979 } else {
980 &add_content2xml_hash($out_hash, "answer", "Import of DAK key successfull! Output was '".$output->{'output'}."'");
981 }
982 }
984 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
985 if (defined $forward_to_gosa) {
986 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
987 }
988 return &create_xml_string($out_hash);
989 }
992 sub remove_dak_key {
993 my ($msg, $msg_hash) = @_;
994 my $source = @{$msg_hash->{'source'}}[0];
995 my $target = @{$msg_hash->{'target'}}[0];
996 my $header= @{$msg_hash->{'header'}}[0];
997 my $session_id = @{$msg_hash->{'session_id'}}[0];
998 my $key = @{$msg_hash->{'keyid'}}[0];
999 # build return message with twisted target and source
1000 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
1001 &add_content2xml_hash($out_hash, "session_id", $session_id);
1003 my %data;
1005 my $keyring = $main::dak_signing_keys_directory."/keyring.gpg";
1007 my $gpg_cmd = `which gpg`; chomp $gpg_cmd;
1008 my $gpg = "$gpg_cmd --no-default-keyring --no-random-seed --homedir ".$main::dak_signing_keys_directory." --keyring $keyring";
1010 # Check if the keyrings are in place and writable
1011 if(
1012 &run_as($main::dak_user, "test -w $keyring")->{'resultCode'} != 0
1013 ) {
1014 &add_content2xml_hash($out_hash, "error", "DAK keyring is not writable");
1015 } else {
1016 # Check if the key is present in the keyring
1017 if(&run_as($main::dak_user, "$gpg --list-keys $key")->{'resultCode'} == 0) {
1018 my $command = "$gpg --batch --yes --delete-key $key";
1019 my $output = &run_as($main::dak_user, $command);
1020 &main::daemon_log("$session_id DEBUG: ".$output->{'command'}, 7);
1021 } else {
1022 &add_content2xml_hash($out_hash, "error", "DAK key with id '$key' was not found in keyring");
1023 }
1024 }
1026 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
1027 if (defined $forward_to_gosa) {
1028 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
1029 }
1030 return &create_xml_string($out_hash);
1031 }
1034 #sub get_dak_queue {
1035 # my ($msg, $msg_hash, $session_id) = @_;
1036 # my %data;
1037 # my $source = @{$msg_hash->{'source'}}[0];
1038 # my $target = @{$msg_hash->{'target'}}[0];
1039 # my $header= @{$msg_hash->{'header'}}[0];
1040 #
1041 # my %data;
1042 #
1043 # foreach my $dir ("unchecked", "new", "accepted") {
1044 # foreach my $file(<"$main::dak_queue_directory/$dir/*.changes">) {
1045 # }
1046 # }
1047 #
1048 # my $out_msg = &build_msg("get_dak_queue", $target, $source, \%data);
1049 # my @out_msg_l = ($out_msg);
1050 # return @out_msg_l;
1051 #}
1054 # vim:ts=4:shiftwidth:expandtab
1055 1;