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];
253 my ($sql, $res);
254 my $out_msg = $msg;
255 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
256 if( defined $jobdb_id) {
257 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
258 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
259 my $res = $main::job_db->exec_statement($sql_statement);
260 }
262 # send message
263 $sql = "SELECT * FROM $main::known_clients_tn WHERE ((hostname='$target') || (macaddress LIKE '$target'))";
264 $res = $main::known_clients_db->exec_statement($sql);
265 my $host_name = @{@$res[0]}[0];
266 my $host_key = @{@$res[0]}[2];
268 my $client_hash = &create_xml_hash("ping", $main::server_address, $host_name);
269 &add_content2xml_hash($client_hash, 'session_id', $session_id);
270 my $client_msg = &create_xml_string($client_hash);
271 my $error = &main::send_msg_to_target($client_msg, $host_name, $host_key, $header, $session_id);
272 #if ($error != 0) {}
274 my $message_id;
275 my $i = 0;
276 while (1) {
277 $i++;
278 $sql = "SELECT * FROM $main::incoming_tn WHERE headertag='answer_$session_id'";
279 $res = $main::incoming_db->exec_statement($sql);
280 if (ref @$res[0] eq "ARRAY") {
281 $message_id = @{@$res[0]}[0];
282 last;
283 }
285 # do not run into a endless loop
286 if ($i > 100) { last; }
287 usleep(100000);
288 }
290 my $answer_xml = @{@$res[0]}[3];
291 my %data = ( 'answer_xml' => 'bin noch da' );
292 my $answer_msg = &build_msg("got_ping", $target, $source, \%data);
293 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
294 if (defined $forward_to_gosa) {
295 $answer_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
296 }
298 $sql = "DELETE FROM $main::incoming_tn WHERE id=$message_id";
299 $res = $main::incoming_db->exec_statement($sql);
301 my @answer_msg_l = ( $answer_msg );
302 return @answer_msg_l;
303 }
307 sub gen_smb_hash {
308 my ($msg, $msg_hash, $session_id) = @_ ;
309 my $source = @{$msg_hash->{source}}[0];
310 my $target = @{$msg_hash->{target}}[0];
311 my $password = @{$msg_hash->{password}}[0];
313 my %data= ('hash' => join(q[:], ntlmgen $password));
314 my $out_msg = &build_msg("gen_smb_hash", $target, $source, \%data );
315 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
316 if (defined $forward_to_gosa) {
317 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
318 }
320 return ( $out_msg );
321 }
324 sub network_completition {
325 my ($msg, $msg_hash, $session_id) = @_ ;
326 my $source = @{$msg_hash->{source}}[0];
327 my $target = @{$msg_hash->{target}}[0];
328 my $name = @{$msg_hash->{hostname}}[0];
330 # Can we resolv the name?
331 my %data;
332 if (inet_aton($name)){
333 my $address = inet_ntoa(inet_aton($name));
334 my $p = Net::Ping->new('tcp');
335 my $mac= "";
336 if ($p->ping($address, 1)){
337 $mac = Net::ARP::arp_lookup("", $address);
338 }
340 %data= ('ip' => $address, 'mac' => $mac);
341 } else {
342 %data= ('ip' => '', 'mac' => '');
343 }
345 my $out_msg = &build_msg("network_completition", $target, $source, \%data );
346 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
347 if (defined $forward_to_gosa) {
348 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
349 }
351 return ( $out_msg );
352 }
355 sub detect_hardware {
356 my ($msg, $msg_hash, $session_id) = @_ ;
357 # just forward msg to client, but dont forget to split off 'gosa_' in header
358 my $source = @{$msg_hash->{source}}[0];
359 my $target = @{$msg_hash->{target}}[0];
360 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
361 if( defined $jobdb_id) {
362 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
363 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
364 my $res = $main::job_db->exec_statement($sql_statement);
365 }
367 my $out_hash = &create_xml_hash("detect_hardware", $source, $target);
368 if( defined $jobdb_id ) {
369 &add_content2xml_hash($out_hash, 'jobdb_id', $jobdb_id);
370 }
371 my $out_msg = &create_xml_string($out_hash);
373 my @out_msg_l = ( $out_msg );
374 return @out_msg_l;
376 }
379 sub trigger_reload_ldap_config {
380 my ($msg, $msg_hash, $session_id) = @_ ;
381 my $target = @{$msg_hash->{target}}[0];
383 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
384 if( defined $jobdb_id) {
385 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
386 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
387 my $res = $main::job_db->exec_statement($sql_statement);
388 }
390 my $out_msg = &ClientPackages::new_ldap_config($target, $session_id);
391 my @out_msg_l = ( $out_msg );
393 return @out_msg_l;
394 }
397 sub set_activated_for_installation {
398 my ($msg, $msg_hash, $session_id) = @_;
399 my $header = @{$msg_hash->{header}}[0];
400 my $source = @{$msg_hash->{source}}[0];
401 my $target = @{$msg_hash->{target}}[0];
402 my @out_msg_l;
404 # update status of job
405 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
406 if( defined $jobdb_id) {
407 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
408 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
409 my $res = $main::job_db->exec_statement($sql_statement);
410 }
412 # create set_activated_for_installation message for delivery
413 my $out_hash = &create_xml_hash("set_activated_for_installation", $source, $target);
414 if( defined $jobdb_id ) {
415 &add_content2xml_hash($out_hash, 'jobdb_id', $jobdb_id);
416 }
417 my $out_msg = &create_xml_string($out_hash);
418 push(@out_msg_l, $out_msg);
420 return @out_msg_l;
421 }
424 sub trigger_action_faireboot {
425 my ($msg, $msg_hash, $session_id) = @_;
426 my $macaddress = @{$msg_hash->{macaddress}}[0];
427 my $source = @{$msg_hash->{source}}[0];
429 my @out_msg_l;
430 $msg =~ s/<header>gosa_trigger_action_faireboot<\/header>/<header>trigger_action_faireboot<\/header>/;
431 push(@out_msg_l, $msg);
433 &main::change_goto_state('locked', \@{$msg_hash->{macaddress}}, $session_id);
434 &main::change_fai_state('install', \@{$msg_hash->{macaddress}}, $session_id);
436 # delete all jobs from jobqueue which correspond to fai
437 my $sql_statement = "DELETE FROM $main::job_queue_tn WHERE (macaddress='$macaddress' AND ".
438 "status='processing')";
439 $main::job_db->del_dbentry($sql_statement );
441 return @out_msg_l;
442 }
445 sub trigger_action_lock {
446 my ($msg, $msg_hash, $session_id) = @_;
447 my $macaddress = @{$msg_hash->{macaddress}}[0];
448 my $source = @{$msg_hash->{source}}[0];
450 &main::change_goto_state('locked', \@{$msg_hash->{macaddress}}, $session_id);
451 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
452 if( defined $jobdb_id) {
453 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
454 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
455 my $res = $main::job_db->exec_statement($sql_statement);
456 }
458 my @out_msg_l;
459 return @out_msg_l;
460 }
463 sub trigger_action_activate {
464 my ($msg, $msg_hash, $session_id) = @_;
465 my $macaddress = @{$msg_hash->{macaddress}}[0];
466 my $source = @{$msg_hash->{source}}[0];
468 &main::change_goto_state('active', \@{$msg_hash->{macaddress}}, $session_id);
469 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
470 if( defined $jobdb_id) {
471 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
472 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
473 my $res = $main::job_db->exec_statement($sql_statement);
474 }
476 my $out_hash = &create_xml_hash("set_activated_for_installation", $source, $macaddress);
477 if( exists $msg_hash->{'jobdb_id'} ) {
478 &add_content2xml_hash($out_hash, 'jobdb_id', @{$msg_hash->{'jobdb_id'}}[0]);
479 }
480 my $out_msg = &create_xml_string($out_hash);
482 return ( $out_msg );
483 }
486 sub trigger_action_localboot {
487 my ($msg, $msg_hash, $session_id) = @_;
488 $msg =~ s/<header>gosa_trigger_action_localboot<\/header>/<header>trigger_action_localboot<\/header>/;
489 &main::change_fai_state('localboot', \@{$msg_hash->{macaddress}}, $session_id);
490 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
491 if( defined $jobdb_id) {
492 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
493 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
494 my $res = $main::job_db->exec_statement($sql_statement);
495 }
497 my @out_msg_l = ($msg);
498 return @out_msg_l;
499 }
502 sub trigger_action_halt {
503 my ($msg, $msg_hash, $session_id) = @_;
504 $msg =~ s/<header>gosa_trigger_action_halt<\/header>/<header>trigger_action_halt<\/header>/;
506 &main::change_fai_state('halt', \@{$msg_hash->{macaddress}}, $session_id);
507 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
508 if( defined $jobdb_id) {
509 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
510 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
511 my $res = $main::job_db->exec_statement($sql_statement);
512 }
514 my @out_msg_l = ($msg);
515 return @out_msg_l;
516 }
519 sub trigger_action_reboot {
520 my ($msg, $msg_hash, $session_id) = @_;
521 $msg =~ s/<header>gosa_trigger_action_reboot<\/header>/<header>trigger_action_reboot<\/header>/;
523 &main::change_fai_state('reboot', \@{$msg_hash->{macaddress}}, $session_id);
524 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
525 if( defined $jobdb_id) {
526 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
527 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
528 my $res = $main::job_db->exec_statement($sql_statement);
529 }
531 my @out_msg_l = ($msg);
532 return @out_msg_l;
533 }
536 sub trigger_action_memcheck {
537 my ($msg, $msg_hash, $session_id) = @_ ;
538 $msg =~ s/<header>gosa_trigger_action_memcheck<\/header>/<header>trigger_action_memcheck<\/header>/;
540 &main::change_fai_state('memcheck', \@{$msg_hash->{macaddress}}, $session_id);
541 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
542 if( defined $jobdb_id) {
543 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
544 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
545 my $res = $main::job_db->exec_statement($sql_statement);
546 }
548 my @out_msg_l = ($msg);
549 return @out_msg_l;
550 }
553 sub trigger_action_reinstall {
554 my ($msg, $msg_hash, $session_id) = @_;
555 $msg =~ s/<header>gosa_trigger_action_reinstall<\/header>/<header>trigger_action_reinstall<\/header>/;
557 &main::change_fai_state('reinstall', \@{$msg_hash->{macaddress}}, $session_id);
559 my %data = ( 'macAddress' => \@{$msg_hash->{macaddress}} );
560 my $wake_msg = &build_msg("trigger_wake", "GOSA", "KNOWN_SERVER", \%data);
561 my @out_msg_l = ($wake_msg, $msg);
562 return @out_msg_l;
563 }
566 sub trigger_action_update {
567 my ($msg, $msg_hash, $session_id) = @_;
568 $msg =~ s/<header>gosa_trigger_action_update<\/header>/<header>trigger_action_update<\/header>/;
570 &main::change_fai_state('update', \@{$msg_hash->{macaddress}}, $session_id);
572 my %data = ( 'macAddress' => \@{$msg_hash->{macaddress}} );
573 my $wake_msg = &build_msg("trigger_wake", "GOSA", "KNOWN_SERVER", \%data);
574 my @out_msg_l = ($wake_msg, $msg);
575 return @out_msg_l;
576 }
579 sub trigger_action_instant_update {
580 my ($msg, $msg_hash, $session_id) = @_;
581 $msg =~ s/<header>gosa_trigger_action_instant_update<\/header>/<header>trigger_action_instant_update<\/header>/;
583 &main::change_fai_state('update', \@{$msg_hash->{macaddress}}, $session_id);
585 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
586 if( defined $jobdb_id) {
587 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
588 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
589 my $res = $main::job_db->exec_statement($sql_statement);
590 }
592 my %data = ( 'macAddress' => \@{$msg_hash->{macaddress}} );
593 my $wake_msg = &build_msg("trigger_wake", "GOSA", "KNOWN_SERVER", \%data);
594 my @out_msg_l = ($wake_msg, $msg);
595 return @out_msg_l;
596 }
599 sub trigger_action_sysinfo {
600 my ($msg, $msg_hash, $session_id) = @_;
601 $msg =~ s/<header>gosa_trigger_action_sysinfo<\/header>/<header>trigger_action_sysinfo<\/header>/;
603 &main::change_fai_state('sysinfo', \@{$msg_hash->{macaddress}}, $session_id);
604 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
605 if( defined $jobdb_id) {
606 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
607 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
608 my $res = $main::job_db->exec_statement($sql_statement);
609 }
611 my @out_msg_l = ($msg);
612 return @out_msg_l;
613 }
616 sub new_key_for_client {
617 my ($msg, $msg_hash, $session_id) = @_;
619 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
620 if( defined $jobdb_id) {
621 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
622 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
623 my $res = $main::job_db->exec_statement($sql_statement);
624 }
626 $msg =~ s/<header>gosa_new_key_for_client<\/header>/<header>new_key<\/header>/;
627 my @out_msg_l = ($msg);
628 return @out_msg_l;
629 }
632 sub trigger_action_rescan {
633 my ($msg, $msg_hash, $session_id) = @_;
635 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
636 if( defined $jobdb_id) {
637 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
638 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
639 my $res = $main::job_db->exec_statement($sql_statement);
640 }
643 $msg =~ s/<header>gosa_trigger_action_rescan<\/header>/<header>trigger_action_rescan<\/header>/;
644 my @out_msg_l = ($msg);
645 return @out_msg_l;
646 }
649 sub trigger_action_wake {
650 my ($msg, $msg_hash, $session_id) = @_;
652 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
653 if( defined $jobdb_id) {
654 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
655 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
656 my $res = $main::job_db->exec_statement($sql_statement);
657 }
660 my %data = ( 'macAddress' => \@{$msg_hash->{macaddress}} );
661 my $out_msg = &build_msg("trigger_wake", "GOSA", "KNOWN_SERVER", \%data);
662 my @out_msg_l = ($out_msg);
663 return @out_msg_l;
664 }
667 sub get_available_kernel {
668 my ($msg, $msg_hash, $session_id) = @_;
670 my $source = @{$msg_hash->{'source'}}[0];
671 my $target = @{$msg_hash->{'target'}}[0];
672 my $release= @{$msg_hash->{'release'}}[0];
674 my @kernel;
675 # Get Kernel packages for release
676 my $sql_statement = "SELECT * FROM $main::packages_list_tn WHERE distribution='$release' AND package LIKE 'linux\-image\-%'";
677 my $res_hash = $main::packages_list_db->select_dbentry($sql_statement);
678 my %data;
679 my $i=1;
681 foreach my $package (keys %{$res_hash}) {
682 $data{"answer".$i++}= $data{"answer".$i++}= ${$res_hash}{$package}->{'package'};
683 }
684 $data{"answer".$i++}= "default";
686 my $out_msg = &build_msg("get_available_kernel", $target, $source, \%data);
687 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
688 if (defined $forward_to_gosa) {
689 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
690 }
692 return ( $out_msg );
693 }
696 sub trigger_activate_new {
697 my ($msg, $msg_hash, $session_id) = @_;
699 my $source = @{$msg_hash->{'source'}}[0];
700 my $target = @{$msg_hash->{'target'}}[0];
701 my $header= @{$msg_hash->{'header'}}[0];
702 my $mac= (defined($msg_hash->{'mac'}))?@{$msg_hash->{'mac'}}[0]:undef;
703 my $ogroup= (defined($msg_hash->{'ogroup'}))?@{$msg_hash->{'ogroup'}}[0]:undef;
704 my $timestamp= (defined($msg_hash->{'timestamp'}))?@{$msg_hash->{'timestamp'}}[0]:undef;
705 my $base= (defined($msg_hash->{'base'}))?@{$msg_hash->{'base'}}[0]:undef;
706 my $hostname= (defined($msg_hash->{'fqdn'}))?@{$msg_hash->{'fqdn'}}[0]:undef;
707 my $ip_address= (defined($msg_hash->{'ip'}))?@{$msg_hash->{'ip'}}[0]:undef;
708 my $dhcp_statement= (defined($msg_hash->{'dhcp'}))?@{$msg_hash->{'dhcp'}}[0]:undef;
709 my $jobdb_id= (defined($msg_hash->{'jobdb_id'}))?@{$msg_hash->{'jobdb_id'}}[0]:undef;
711 my $ldap_handle = &main::get_ldap_handle();
712 my $ldap_entry;
713 my $ogroup_entry;
714 my $changed_attributes_counter = 0;
716 eval {
718 my $ldap_mesg= $ldap_handle->search(
719 base => $main::ldap_base,
720 scope => 'sub',
721 filter => "(&(objectClass=gosaGroupOfnames)(cn=$ogroup))",
722 );
723 if($ldap_mesg->count == 1) {
724 $ogroup_entry= $ldap_mesg->pop_entry();
725 } elsif ($ldap_mesg->count == 0) {
726 &main::daemon_log("ERROR: A GosaGroupOfNames with cn '$ogroup' was not found in base '".$main::ldap_base."'!", 1);
727 } else {
728 &main::daemon_log("ERROR: More than one ObjectGroups with cn '$ogroup' was found in base '".$main::ldap_base."'!", 1);
729 }
731 # build the base, use optional base parameter or take it from ogroup
732 if(!(defined($base) && (length($base) > 0))) {
733 # Subtract the ObjectGroup cn
734 $base = $1 if $ogroup_entry->dn =~ /cn=$ogroup,ou=groups,(.*)$/;
735 }
737 # prepend ou=systems (configurable through config)
738 $base = $main::new_systems_ou.",".$base;
740 # Search for an existing entry (should be in ou=incoming)
741 $ldap_mesg= $ldap_handle->search(
742 base => $main::ldap_base,
743 scope => 'sub',
744 filter => "(&(objectClass=GOhard)(|(macAddress=$mac)(dhcpHWaddress=$mac)))",
745 );
747 # TODO: Find a way to guess an ip address for hosts with no ldap entry (MAC->ARP->IP)
749 if($ldap_mesg->count == 1) {
750 &main::daemon_log("DEBUG: One system with mac address '$mac' was found in base '".$main::ldap_base."'!", 6);
751 # Get the entry from LDAP
752 $ldap_entry= $ldap_mesg->pop_entry();
754 if(!($ldap_entry->dn() eq "cn=".$ldap_entry->get_value('cn').",$base")) {
755 # Move the entry to the new ou
756 $ldap_entry->changetype('moddn');
757 $ldap_entry->add(
758 newrdn => "cn=".$ldap_entry->get_value('cn'),
759 deleteoldrdn => 1,
760 newsuperior => $base,
761 );
762 }
764 }
766 $ldap_mesg= $ldap_handle->search(
767 base => $main::ldap_base,
768 scope => 'sub',
769 filter => "(&(objectClass=GOhard)(|(macAddress=$mac)(dhcpHWaddress=$mac)))",
770 );
772 # TODO: Find a way to guess an ip address for hosts with no ldap entry (MAC->ARP->IP)
774 if($ldap_mesg->count == 1) {
775 $ldap_entry= $ldap_mesg->pop_entry();
776 # Check for needed objectClasses
777 my $oclasses = $ldap_entry->get_value('objectClass', asref => 1);
778 foreach my $oclass ("FAIobject", "GOhard") {
779 if(!(scalar grep $_ eq $oclass, map {$_ => 1} @$oclasses)) {
780 &main::daemon_log("Adding objectClass $oclass", 1);
781 $ldap_entry->add(
782 objectClass => $oclass,
783 );
784 my $oclass_result = $ldap_entry->update($ldap_handle);
785 }
786 }
788 # Set FAIstate
789 if(defined($ldap_entry->get_value('FAIstate'))) {
790 if(!($ldap_entry->get_value('FAIstate') eq 'install')) {
791 $ldap_entry->replace(
792 'FAIstate' => 'install'
793 );
794 my $replace_result = $ldap_entry->update($ldap_handle);
795 }
796 } else {
797 $ldap_entry->add(
798 'FAIstate' => 'install'
799 );
800 my $add_result = $ldap_entry->update($ldap_handle);
801 }
804 } elsif ($ldap_mesg->count == 0) {
805 # TODO: Create a new entry
806 # $ldap_entry = Net::LDAP::Entry->new();
807 # $ldap_entry->dn("cn=$mac,$base");
808 &main::daemon_log("WARNING: No System with mac address '$mac' was found in base '".$main::ldap_base."'! Re-queuing job.", 4);
809 $main::job_db->exec_statement("UPDATE jobs SET status = 'waiting', timestamp = '".&get_time()."' WHERE id = $jobdb_id");
810 } else {
811 &main::daemon_log("ERROR: More than one system with mac address '$mac' was found in base '".$main::ldap_base."'!", 1);
812 }
814 # Add to ObjectGroup
815 if(!(scalar grep $_, map {$_ => 1} $ogroup_entry->get_value('member', asref => 1))) {
816 $ogroup_entry->add (
817 'member' => $ldap_entry->dn(),
818 );
819 my $ogroup_result = $ogroup_entry->update($ldap_handle);
820 if ($ogroup_result->code() != 0) {
821 &main::daemon_log("ERROR: Updating the ObjectGroup '$ogroup' failed (code '".$ogroup_result->code()."') with '".$ogroup_result->{'errorMessage'}."'!", 1);
822 }
823 }
825 # Finally set gotoMode to active
826 if(defined($ldap_entry->get_value('gotoMode'))) {
827 if(!($ldap_entry->get_value('gotoMode') eq 'active')) {
828 $ldap_entry->replace(
829 'gotoMode' => 'active'
830 );
831 my $activate_result = $ldap_entry->update($ldap_handle);
832 if ($activate_result->code() != 0) {
833 &main::daemon_log("ERROR: Activating system '".$ldap_entry->dn()."' failed (code '".$activate_result->code()."') with '".$activate_result->{'errorMessage'}."'!", 1);
834 }
835 }
836 } else {
837 $ldap_entry->add(
838 'gotoMode' => 'active'
839 );
840 my $activate_result = $ldap_entry->update($ldap_handle);
841 if ($activate_result->code() != 0) {
842 &main::daemon_log("ERROR: Activating system '".$ldap_entry->dn()."' failed (code '".$activate_result->code()."') with '".$activate_result->{'errorMessage'}."'!", 1);
843 }
844 }
845 };
846 if($@) {
847 &main::daemon_log("ERROR: activate_new failed with '$@'!", 1);
848 }
850 # Delete job
851 $main::job_db->exec_statement("DELETE FROM jobs WHERE id = $jobdb_id");
853 # create set_activated_for_installation message for delivery
854 my $out_hash = &create_xml_hash("set_activated_for_installation", $source, $target);
855 my $out_msg = &create_xml_string($out_hash);
856 my @out_msg_l = ($out_msg);
858 return @out_msg_l;
859 }
862 sub get_dak_keyring {
863 my ($msg, $msg_hash) = @_;
864 my $source = @{$msg_hash->{'source'}}[0];
865 my $target = @{$msg_hash->{'target'}}[0];
866 my $header= @{$msg_hash->{'header'}}[0];
867 my $session_id = @{$msg_hash->{'session_id'}}[0];
869 # build return message with twisted target and source
870 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
871 &add_content2xml_hash($out_hash, "session_id", $session_id);
873 my @keys;
874 my %data;
876 my $keyring = $main::dak_signing_keys_directory."/keyring.gpg";
878 my $gpg_cmd = `which gpg`; chomp $gpg_cmd;
879 my $gpg = "$gpg_cmd --no-default-keyring --no-random-seed --keyring $keyring";
881 # Check if the keyrings are in place and readable
882 if(
883 &run_as($main::dak_user, "test -r $keyring")->{'resultCode'} != 0
884 ) {
885 &add_content2xml_hash($out_hash, "error", "DAK Keyring is not readable");
886 } else {
887 my $command = "$gpg --list-keys";
888 my $output = &run_as($main::dak_user, $command);
889 &main::daemon_log("$session_id DEBUG: ".$output->{'command'}, 7);
891 my $i=0;
892 foreach (@{$output->{'output'}}) {
893 if ($_ =~ m/^pub\s.*$/) {
894 ($keys[$i]->{'pub'}->{'length'}, $keys[$i]->{'pub'}->{'uid'}, $keys[$i]->{'pub'}->{'created'}) = ($1, $2, $3)
895 if $_ =~ m/^pub\s*?(\w*?)\/(\w*?)\s(\d{4}-\d{2}-\d{2})/;
896 $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})\]/;
897 $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})\]/;
898 } elsif ($_ =~ m/^sub\s.*$/) {
899 ($keys[$i]->{'sub'}->{'length'}, $keys[$i]->{'sub'}->{'uid'}, $keys[$i]->{'sub'}->{'created'}) = ($1, $2, $3)
900 if $_ =~ m/^sub\s*?(\w*?)\/(\w*?)\s(\d{4}-\d{2}-\d{2})/;
901 $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})\]/;
902 $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})\]/;
903 } elsif ($_ =~ m/^uid\s.*$/) {
904 push @{$keys[$i]->{'uid'}}, $1 if $_ =~ m/^uid\s*?([^\s].*?)$/;
905 } elsif ($_ =~ m/^$/) {
906 $i++;
907 }
908 }
909 }
911 my $i=0;
912 foreach my $key (@keys) {
913 # &main::daemon_log(Dumper($key));
914 &add_content2xml_hash($out_hash, "answer".$i++, $key);
915 }
916 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
917 if (defined $forward_to_gosa) {
918 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
919 }
920 return &create_xml_string($out_hash);
921 }
924 sub import_dak_key {
925 my ($msg, $msg_hash) = @_;
926 my $source = @{$msg_hash->{'source'}}[0];
927 my $target = @{$msg_hash->{'target'}}[0];
928 my $header= @{$msg_hash->{'header'}}[0];
929 my $session_id = @{$msg_hash->{'session_id'}}[0];
930 my $key = &decode_base64(@{$msg_hash->{'key'}}[0]);
932 # build return message with twisted target and source
933 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
934 &add_content2xml_hash($out_hash, "session_id", $session_id);
936 my %data;
938 my $keyring = $main::dak_signing_keys_directory."/keyring.gpg";
940 my $gpg_cmd = `which gpg`; chomp $gpg_cmd;
941 my $gpg = "$gpg_cmd --no-default-keyring --no-random-seed --keyring $keyring";
943 # Check if the keyrings are in place and writable
944 if(
945 &run_as($main::dak_user, "test -w $keyring")->{'resultCode'} != 0
946 ) {
947 &add_content2xml_hash($out_hash, "error", "DAK Keyring is not writable");
948 } else {
949 my $keyfile;
950 open($keyfile, ">/tmp/gosa_si_tmp_dak_key");
951 print $keyfile $key;
952 close($keyfile);
953 my $command = "$gpg --import /tmp/gosa_si_tmp_dak_key";
954 my $output = &run_as($main::dak_user, $command);
955 &main::daemon_log("$session_id DEBUG: ".$output->{'command'}, 7);
956 unlink("/tmp/gosa_si_tmp_dak_key");
958 if($output->{'resultCode'} != 0) {
959 &add_content2xml_hash($out_hash, "error", "Import of DAK key failed! Output was '".$output->{'output'}."'");
960 } else {
961 &add_content2xml_hash($out_hash, "answer", "Import of DAK key successfull! Output was '".$output->{'output'}."'");
962 }
963 }
965 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
966 if (defined $forward_to_gosa) {
967 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
968 }
969 return &create_xml_string($out_hash);
970 }
973 sub remove_dak_key {
974 my ($msg, $msg_hash) = @_;
975 my $source = @{$msg_hash->{'source'}}[0];
976 my $target = @{$msg_hash->{'target'}}[0];
977 my $header= @{$msg_hash->{'header'}}[0];
978 my $session_id = @{$msg_hash->{'session_id'}}[0];
979 my $key = @{$msg_hash->{'keyid'}}[0];
980 # build return message with twisted target and source
981 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
982 &add_content2xml_hash($out_hash, "session_id", $session_id);
984 my %data;
986 my $keyring = $main::dak_signing_keys_directory."/keyring.gpg";
988 my $gpg_cmd = `which gpg`; chomp $gpg_cmd;
989 my $gpg = "$gpg_cmd --no-default-keyring --no-random-seed --homedir ".$main::dak_signing_keys_directory." --keyring $keyring";
991 # Check if the keyrings are in place and writable
992 if(
993 &run_as($main::dak_user, "test -w $keyring")->{'resultCode'} != 0
994 ) {
995 &add_content2xml_hash($out_hash, "error", "DAK keyring is not writable");
996 } else {
997 # Check if the key is present in the keyring
998 if(&run_as($main::dak_user, "$gpg --list-keys $key")->{'resultCode'} == 0) {
999 my $command = "$gpg --batch --yes --delete-key $key";
1000 my $output = &run_as($main::dak_user, $command);
1001 &main::daemon_log("$session_id DEBUG: ".$output->{'command'}, 7);
1002 } else {
1003 &add_content2xml_hash($out_hash, "error", "DAK key with id '$key' was not found in keyring");
1004 }
1005 }
1007 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
1008 if (defined $forward_to_gosa) {
1009 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
1010 }
1011 return &create_xml_string($out_hash);
1012 }
1015 #sub get_dak_queue {
1016 # my ($msg, $msg_hash, $session_id) = @_;
1017 # my %data;
1018 # my $source = @{$msg_hash->{'source'}}[0];
1019 # my $target = @{$msg_hash->{'target'}}[0];
1020 # my $header= @{$msg_hash->{'header'}}[0];
1021 #
1022 # my %data;
1023 #
1024 # foreach my $dir ("unchecked", "new", "accepted") {
1025 # foreach my $file(<"$main::dak_queue_directory/$dir/*.changes">) {
1026 # }
1027 # }
1028 #
1029 # my $out_msg = &build_msg("get_dak_queue", $target, $source, \%data);
1030 # my @out_msg_l = ($out_msg);
1031 # return @out_msg_l;
1032 #}
1035 # vim:ts=4:shiftwidth:expandtab
1036 1;