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 = exists $msg_hash->{'users'} ? @{$msg_hash->{'users'}} : () ;
76 my @groups = exists $msg_hash->{'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 # if an answer to the question exists
302 if (defined $message_id) {
303 my $answer_xml = @{@$res[0]}[3];
304 my %data = ( 'answer_xml' => 'bin noch da' );
305 $answer_msg = &build_msg("got_ping", $target, $source, \%data);
306 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
307 if (defined $forward_to_gosa){
308 $answer_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
309 }
310 $sql = "DELETE FROM $main::incoming_tn WHERE id=$message_id";
311 $res = $main::incoming_db->exec_statement($sql);
312 }
314 }
316 return ( $answer_msg );
317 }
321 sub gen_smb_hash {
322 my ($msg, $msg_hash, $session_id) = @_ ;
323 my $source = @{$msg_hash->{source}}[0];
324 my $target = @{$msg_hash->{target}}[0];
325 my $password = @{$msg_hash->{password}}[0];
327 my %data= ('hash' => join(q[:], ntlmgen $password));
328 my $out_msg = &build_msg("gen_smb_hash", $target, $source, \%data );
329 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
330 if (defined $forward_to_gosa) {
331 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
332 }
334 return ( $out_msg );
335 }
338 sub network_completition {
339 my ($msg, $msg_hash, $session_id) = @_ ;
340 my $source = @{$msg_hash->{source}}[0];
341 my $target = @{$msg_hash->{target}}[0];
342 my $name = @{$msg_hash->{hostname}}[0];
344 # Can we resolv the name?
345 my %data;
346 if (inet_aton($name)){
347 my $address = inet_ntoa(inet_aton($name));
348 my $p = Net::Ping->new('tcp');
349 my $mac= "";
350 if ($p->ping($address, 1)){
351 $mac = Net::ARP::arp_lookup("", $address);
352 }
354 %data= ('ip' => $address, 'mac' => $mac);
355 } else {
356 %data= ('ip' => '', 'mac' => '');
357 }
359 my $out_msg = &build_msg("network_completition", $target, $source, \%data );
360 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
361 if (defined $forward_to_gosa) {
362 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
363 }
365 return ( $out_msg );
366 }
369 sub detect_hardware {
370 my ($msg, $msg_hash, $session_id) = @_ ;
371 # just forward msg to client, but dont forget to split off 'gosa_' in header
372 my $source = @{$msg_hash->{source}}[0];
373 my $target = @{$msg_hash->{target}}[0];
374 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
375 if( defined $jobdb_id) {
376 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
377 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
378 my $res = $main::job_db->exec_statement($sql_statement);
379 }
381 my $out_hash = &create_xml_hash("detect_hardware", $source, $target);
382 if( defined $jobdb_id ) {
383 &add_content2xml_hash($out_hash, 'jobdb_id', $jobdb_id);
384 }
385 my $out_msg = &create_xml_string($out_hash);
387 my @out_msg_l = ( $out_msg );
388 return @out_msg_l;
390 }
393 sub trigger_reload_ldap_config {
394 my ($msg, $msg_hash, $session_id) = @_ ;
395 my $target = @{$msg_hash->{target}}[0];
397 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
398 if( defined $jobdb_id) {
399 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
400 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
401 my $res = $main::job_db->exec_statement($sql_statement);
402 }
404 my $out_msg = &ClientPackages::new_ldap_config($target, $session_id);
405 my @out_msg_l = ( $out_msg );
407 return @out_msg_l;
408 }
411 sub set_activated_for_installation {
412 my ($msg, $msg_hash, $session_id) = @_;
413 my $header = @{$msg_hash->{header}}[0];
414 my $source = @{$msg_hash->{source}}[0];
415 my $target = @{$msg_hash->{target}}[0];
416 my @out_msg_l;
418 # update status of job
419 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
420 if( defined $jobdb_id) {
421 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
422 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
423 my $res = $main::job_db->exec_statement($sql_statement);
424 }
426 # create set_activated_for_installation message for delivery
427 my $out_hash = &create_xml_hash("set_activated_for_installation", $source, $target);
428 if( defined $jobdb_id ) {
429 &add_content2xml_hash($out_hash, 'jobdb_id', $jobdb_id);
430 }
431 my $out_msg = &create_xml_string($out_hash);
432 push(@out_msg_l, $out_msg);
434 return @out_msg_l;
435 }
438 sub trigger_action_faireboot {
439 my ($msg, $msg_hash, $session_id) = @_;
440 my $macaddress = @{$msg_hash->{macaddress}}[0];
441 my $source = @{$msg_hash->{source}}[0];
443 my @out_msg_l;
444 $msg =~ s/<header>gosa_trigger_action_faireboot<\/header>/<header>trigger_action_faireboot<\/header>/;
445 push(@out_msg_l, $msg);
447 &main::change_goto_state('locked', \@{$msg_hash->{macaddress}}, $session_id);
448 &main::change_fai_state('install', \@{$msg_hash->{macaddress}}, $session_id);
450 # set job to status 'done', job will be deleted automatically
451 my $sql_statement = "UPDATE $main::job_queue_tn ".
452 "SET status='done', modified='1'".
453 "WHERE (macaddress='$macaddress' AND status='processing')";
454 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
455 my $res = $main::job_db->update_dbentry( $sql_statement );
457 return @out_msg_l;
458 }
461 sub trigger_action_lock {
462 my ($msg, $msg_hash, $session_id) = @_;
463 my $macaddress = @{$msg_hash->{macaddress}}[0];
464 my $source = @{$msg_hash->{source}}[0];
466 &main::change_goto_state('locked', \@{$msg_hash->{macaddress}}, $session_id);
467 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
468 if( defined $jobdb_id) {
469 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
470 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
471 my $res = $main::job_db->exec_statement($sql_statement);
472 }
474 my @out_msg_l;
475 return @out_msg_l;
476 }
479 sub trigger_action_activate {
480 my ($msg, $msg_hash, $session_id) = @_;
481 my $macaddress = @{$msg_hash->{macaddress}}[0];
482 my $source = @{$msg_hash->{source}}[0];
484 &main::change_goto_state('active', \@{$msg_hash->{macaddress}}, $session_id);
485 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
486 if( defined $jobdb_id) {
487 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
488 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
489 my $res = $main::job_db->exec_statement($sql_statement);
490 }
492 my $out_hash = &create_xml_hash("set_activated_for_installation", $source, $macaddress);
493 if( exists $msg_hash->{'jobdb_id'} ) {
494 &add_content2xml_hash($out_hash, 'jobdb_id', @{$msg_hash->{'jobdb_id'}}[0]);
495 }
496 my $out_msg = &create_xml_string($out_hash);
498 return ( $out_msg );
499 }
502 sub trigger_action_localboot {
503 my ($msg, $msg_hash, $session_id) = @_;
504 $msg =~ s/<header>gosa_trigger_action_localboot<\/header>/<header>trigger_action_localboot<\/header>/;
505 &main::change_fai_state('localboot', \@{$msg_hash->{macaddress}}, $session_id);
506 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
507 if( defined $jobdb_id) {
508 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
509 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
510 my $res = $main::job_db->exec_statement($sql_statement);
511 }
513 my @out_msg_l = ($msg);
514 return @out_msg_l;
515 }
518 sub trigger_action_halt {
519 my ($msg, $msg_hash, $session_id) = @_;
520 $msg =~ s/<header>gosa_trigger_action_halt<\/header>/<header>trigger_action_halt<\/header>/;
522 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
523 if( defined $jobdb_id) {
524 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
525 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
526 my $res = $main::job_db->exec_statement($sql_statement);
527 }
529 my @out_msg_l = ($msg);
530 return @out_msg_l;
531 }
534 sub trigger_action_reboot {
535 my ($msg, $msg_hash, $session_id) = @_;
536 $msg =~ s/<header>gosa_trigger_action_reboot<\/header>/<header>trigger_action_reboot<\/header>/;
538 &main::change_fai_state('reboot', \@{$msg_hash->{macaddress}}, $session_id);
539 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
540 if( defined $jobdb_id) {
541 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
542 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
543 my $res = $main::job_db->exec_statement($sql_statement);
544 }
546 my @out_msg_l = ($msg);
547 return @out_msg_l;
548 }
551 sub trigger_action_memcheck {
552 my ($msg, $msg_hash, $session_id) = @_ ;
553 $msg =~ s/<header>gosa_trigger_action_memcheck<\/header>/<header>trigger_action_memcheck<\/header>/;
555 &main::change_fai_state('memcheck', \@{$msg_hash->{macaddress}}, $session_id);
556 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
557 if( defined $jobdb_id) {
558 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
559 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
560 my $res = $main::job_db->exec_statement($sql_statement);
561 }
563 my @out_msg_l = ($msg);
564 return @out_msg_l;
565 }
568 sub trigger_action_reinstall {
569 my ($msg, $msg_hash, $session_id) = @_;
570 $msg =~ s/<header>gosa_trigger_action_reinstall<\/header>/<header>trigger_action_reinstall<\/header>/;
572 &main::change_fai_state('reinstall', \@{$msg_hash->{macaddress}}, $session_id);
574 my %data = ( 'macAddress' => \@{$msg_hash->{macaddress}} );
575 my $wake_msg = &build_msg("trigger_wake", "GOSA", "KNOWN_SERVER", \%data);
576 my @out_msg_l = ($wake_msg, $msg);
577 return @out_msg_l;
578 }
581 sub trigger_action_update {
582 my ($msg, $msg_hash, $session_id) = @_;
583 $msg =~ s/<header>gosa_trigger_action_update<\/header>/<header>trigger_action_update<\/header>/;
585 &main::change_fai_state('update', \@{$msg_hash->{macaddress}}, $session_id);
587 my %data = ( 'macAddress' => \@{$msg_hash->{macaddress}} );
588 my $wake_msg = &build_msg("trigger_wake", "GOSA", "KNOWN_SERVER", \%data);
589 my @out_msg_l = ($wake_msg, $msg);
590 return @out_msg_l;
591 }
594 sub trigger_action_instant_update {
595 my ($msg, $msg_hash, $session_id) = @_;
596 $msg =~ s/<header>gosa_trigger_action_instant_update<\/header>/<header>trigger_action_instant_update<\/header>/;
598 &main::change_fai_state('update', \@{$msg_hash->{macaddress}}, $session_id);
600 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
601 if( defined $jobdb_id) {
602 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
603 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
604 my $res = $main::job_db->exec_statement($sql_statement);
605 }
607 my %data = ( 'macAddress' => \@{$msg_hash->{macaddress}} );
608 my $wake_msg = &build_msg("trigger_wake", "GOSA", "KNOWN_SERVER", \%data);
609 my @out_msg_l = ($wake_msg, $msg);
610 return @out_msg_l;
611 }
614 sub trigger_action_sysinfo {
615 my ($msg, $msg_hash, $session_id) = @_;
616 $msg =~ s/<header>gosa_trigger_action_sysinfo<\/header>/<header>trigger_action_sysinfo<\/header>/;
618 &main::change_fai_state('sysinfo', \@{$msg_hash->{macaddress}}, $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 my @out_msg_l = ($msg);
627 return @out_msg_l;
628 }
631 sub new_key_for_client {
632 my ($msg, $msg_hash, $session_id) = @_;
634 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
635 if( defined $jobdb_id) {
636 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
637 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
638 my $res = $main::job_db->exec_statement($sql_statement);
639 }
641 $msg =~ s/<header>gosa_new_key_for_client<\/header>/<header>new_key<\/header>/;
642 my @out_msg_l = ($msg);
643 return @out_msg_l;
644 }
647 sub trigger_action_rescan {
648 my ($msg, $msg_hash, $session_id) = @_;
650 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
651 if( defined $jobdb_id) {
652 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
653 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
654 my $res = $main::job_db->exec_statement($sql_statement);
655 }
658 $msg =~ s/<header>gosa_trigger_action_rescan<\/header>/<header>detect_hardware<header>/;
659 my @out_msg_l = ($msg);
660 return @out_msg_l;
661 }
664 sub trigger_action_wake {
665 my ($msg, $msg_hash, $session_id) = @_;
667 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
668 if( defined $jobdb_id) {
669 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
670 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
671 my $res = $main::job_db->exec_statement($sql_statement);
672 }
674 # build out message
675 my $out_hash = &create_xml_hash("trigger_wake", "GOSA", "KNOWN_SERVER");
676 foreach (@{$msg_hash->{target}}) {
677 &add_content2xml_hash($out_hash, 'macAddress', $_);
678 }
679 my $out_msg = &create_xml_string($out_hash);
681 # invoke trigger wake for this gosa-si-server
682 &main::server_server_com::trigger_wake($out_msg, $out_hash, $session_id);
684 # send trigger wake to all other gosa-si-server
685 my @out_msg_l = ($out_msg);
686 return @out_msg_l;
687 }
690 sub get_available_kernel {
691 my ($msg, $msg_hash, $session_id) = @_;
693 my $source = @{$msg_hash->{'source'}}[0];
694 my $target = @{$msg_hash->{'target'}}[0];
695 my $release= @{$msg_hash->{'release'}}[0];
697 my @kernel;
698 # Get Kernel packages for release
699 my $sql_statement = "SELECT * FROM $main::packages_list_tn WHERE distribution='$release' AND package LIKE 'linux\-image\-%'";
700 my $res_hash = $main::packages_list_db->select_dbentry($sql_statement);
701 my %data;
702 my $i=1;
704 foreach my $package (keys %{$res_hash}) {
705 $data{"answer".$i++}= $data{"answer".$i++}= ${$res_hash}{$package}->{'package'};
706 }
707 $data{"answer".$i++}= "default";
709 my $out_msg = &build_msg("get_available_kernel", $target, $source, \%data);
710 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
711 if (defined $forward_to_gosa) {
712 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
713 }
715 return ( $out_msg );
716 }
719 sub trigger_activate_new {
720 my ($msg, $msg_hash, $session_id) = @_;
722 my $source = @{$msg_hash->{'source'}}[0];
723 my $target = @{$msg_hash->{'target'}}[0];
724 my $header= @{$msg_hash->{'header'}}[0];
725 my $mac= (defined($msg_hash->{'mac'}))?@{$msg_hash->{'mac'}}[0]:undef;
726 my $ogroup= (defined($msg_hash->{'ogroup'}))?@{$msg_hash->{'ogroup'}}[0]:undef;
727 my $timestamp= (defined($msg_hash->{'timestamp'}))?@{$msg_hash->{'timestamp'}}[0]:undef;
728 my $base= (defined($msg_hash->{'base'}))?@{$msg_hash->{'base'}}[0]:undef;
729 my $hostname= (defined($msg_hash->{'fqdn'}))?@{$msg_hash->{'fqdn'}}[0]:undef;
730 my $ip_address= (defined($msg_hash->{'ip'}))?@{$msg_hash->{'ip'}}[0]:undef;
731 my $dhcp_statement= (defined($msg_hash->{'dhcp'}))?@{$msg_hash->{'dhcp'}}[0]:undef;
732 my $jobdb_id= (defined($msg_hash->{'jobdb_id'}))?@{$msg_hash->{'jobdb_id'}}[0]:undef;
734 my $ldap_handle = &main::get_ldap_handle();
735 my $ldap_entry;
736 my $ogroup_entry;
737 my $changed_attributes_counter = 0;
739 eval {
741 my $ldap_mesg= $ldap_handle->search(
742 base => $main::ldap_base,
743 scope => 'sub',
744 filter => "(&(objectClass=gosaGroupOfnames)(cn=$ogroup))",
745 );
746 if($ldap_mesg->count == 1) {
747 $ogroup_entry= $ldap_mesg->pop_entry();
748 } elsif ($ldap_mesg->count == 0) {
749 &main::daemon_log("ERROR: A GosaGroupOfNames with cn '$ogroup' was not found in base '".$main::ldap_base."'!", 1);
750 } else {
751 &main::daemon_log("ERROR: More than one ObjectGroups with cn '$ogroup' was found in base '".$main::ldap_base."'!", 1);
752 }
754 # build the base, use optional base parameter or take it from ogroup
755 if(!(defined($base) && (length($base) > 0))) {
756 # Subtract the ObjectGroup cn
757 $base = $1 if $ogroup_entry->dn =~ /cn=$ogroup,ou=groups,(.*)$/;
758 }
760 # prepend ou=systems (configurable through config)
761 $base = $main::new_systems_ou.",".$base;
763 # Search for an existing entry (should be in ou=incoming)
764 $ldap_mesg= $ldap_handle->search(
765 base => $main::ldap_base,
766 scope => 'sub',
767 filter => "(&(objectClass=GOhard)(|(macAddress=$mac)(dhcpHWaddress=$mac)))",
768 );
770 # TODO: Find a way to guess an ip address for hosts with no ldap entry (MAC->ARP->IP)
772 if($ldap_mesg->count == 1) {
773 &main::daemon_log("DEBUG: One system with mac address '$mac' was found in base '".$main::ldap_base."'!", 6);
774 # Get the entry from LDAP
775 $ldap_entry= $ldap_mesg->pop_entry();
777 if(!($ldap_entry->dn() eq "cn=".$ldap_entry->get_value('cn').",$base")) {
778 # Move the entry to the new ou
779 $ldap_entry->changetype('moddn');
780 $ldap_entry->add(
781 newrdn => "cn=".$ldap_entry->get_value('cn'),
782 deleteoldrdn => 1,
783 newsuperior => $base,
784 );
785 }
787 }
789 $ldap_mesg= $ldap_handle->search(
790 base => $main::ldap_base,
791 scope => 'sub',
792 filter => "(&(objectClass=GOhard)(|(macAddress=$mac)(dhcpHWaddress=$mac)))",
793 );
795 # TODO: Find a way to guess an ip address for hosts with no ldap entry (MAC->ARP->IP)
797 if($ldap_mesg->count == 1) {
798 $ldap_entry= $ldap_mesg->pop_entry();
799 # Check for needed objectClasses
800 my $oclasses = $ldap_entry->get_value('objectClass', asref => 1);
801 foreach my $oclass ("FAIobject", "GOhard") {
802 if(!(scalar grep $_ eq $oclass, map {$_ => 1} @$oclasses)) {
803 &main::daemon_log("Adding objectClass $oclass", 1);
804 $ldap_entry->add(
805 objectClass => $oclass,
806 );
807 my $oclass_result = $ldap_entry->update($ldap_handle);
808 }
809 }
811 # Set FAIstate
812 if(defined($ldap_entry->get_value('FAIstate'))) {
813 if(!($ldap_entry->get_value('FAIstate') eq 'install')) {
814 $ldap_entry->replace(
815 'FAIstate' => 'install'
816 );
817 my $replace_result = $ldap_entry->update($ldap_handle);
818 }
819 } else {
820 $ldap_entry->add(
821 'FAIstate' => 'install'
822 );
823 my $add_result = $ldap_entry->update($ldap_handle);
824 }
827 } elsif ($ldap_mesg->count == 0) {
828 # TODO: Create a new entry
829 # $ldap_entry = Net::LDAP::Entry->new();
830 # $ldap_entry->dn("cn=$mac,$base");
831 &main::daemon_log("WARNING: No System with mac address '$mac' was found in base '".$main::ldap_base."'! Re-queuing job.", 4);
832 $main::job_db->exec_statement("UPDATE jobs SET status = 'waiting', timestamp = '".&get_time()."' WHERE id = $jobdb_id");
833 } else {
834 &main::daemon_log("ERROR: More than one system with mac address '$mac' was found in base '".$main::ldap_base."'!", 1);
835 }
837 # Add to ObjectGroup
838 if(!(scalar grep $_, map {$_ => 1} $ogroup_entry->get_value('member', asref => 1))) {
839 $ogroup_entry->add (
840 'member' => $ldap_entry->dn(),
841 );
842 my $ogroup_result = $ogroup_entry->update($ldap_handle);
843 if ($ogroup_result->code() != 0) {
844 &main::daemon_log("ERROR: Updating the ObjectGroup '$ogroup' failed (code '".$ogroup_result->code()."') with '".$ogroup_result->{'errorMessage'}."'!", 1);
845 }
846 }
848 # Finally set gotoMode to active
849 if(defined($ldap_entry->get_value('gotoMode'))) {
850 if(!($ldap_entry->get_value('gotoMode') eq 'active')) {
851 $ldap_entry->replace(
852 'gotoMode' => 'active'
853 );
854 my $activate_result = $ldap_entry->update($ldap_handle);
855 if ($activate_result->code() != 0) {
856 &main::daemon_log("ERROR: Activating system '".$ldap_entry->dn()."' failed (code '".$activate_result->code()."') with '".$activate_result->{'errorMessage'}."'!", 1);
857 }
858 }
859 } else {
860 $ldap_entry->add(
861 'gotoMode' => 'active'
862 );
863 my $activate_result = $ldap_entry->update($ldap_handle);
864 if ($activate_result->code() != 0) {
865 &main::daemon_log("ERROR: Activating system '".$ldap_entry->dn()."' failed (code '".$activate_result->code()."') with '".$activate_result->{'errorMessage'}."'!", 1);
866 }
867 }
868 };
869 if($@) {
870 &main::daemon_log("ERROR: activate_new failed with '$@'!", 1);
871 }
873 # Delete job
874 $main::job_db->exec_statement("DELETE FROM jobs WHERE id = $jobdb_id");
876 # create set_activated_for_installation message for delivery
877 my $out_hash = &create_xml_hash("set_activated_for_installation", $source, $target);
878 my $out_msg = &create_xml_string($out_hash);
879 my @out_msg_l = ($out_msg);
881 return @out_msg_l;
882 }
885 sub get_dak_keyring {
886 my ($msg, $msg_hash) = @_;
887 my $source = @{$msg_hash->{'source'}}[0];
888 my $target = @{$msg_hash->{'target'}}[0];
889 my $header= @{$msg_hash->{'header'}}[0];
890 my $session_id = @{$msg_hash->{'session_id'}}[0];
892 # build return message with twisted target and source
893 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
894 &add_content2xml_hash($out_hash, "session_id", $session_id);
896 my @keys;
897 my %data;
899 my $keyring = $main::dak_signing_keys_directory."/keyring.gpg";
901 my $gpg_cmd = `which gpg`; chomp $gpg_cmd;
902 my $gpg = "$gpg_cmd --no-default-keyring --no-random-seed --keyring $keyring";
904 # Check if the keyrings are in place and readable
905 if(
906 &run_as($main::dak_user, "test -r $keyring")->{'resultCode'} != 0
907 ) {
908 &add_content2xml_hash($out_hash, "error", "DAK Keyring is not readable");
909 } else {
910 my $command = "$gpg --list-keys";
911 my $output = &run_as($main::dak_user, $command);
912 &main::daemon_log("$session_id DEBUG: ".$output->{'command'}, 7);
914 my $i=0;
915 foreach (@{$output->{'output'}}) {
916 if ($_ =~ m/^pub\s.*$/) {
917 ($keys[$i]->{'pub'}->{'length'}, $keys[$i]->{'pub'}->{'uid'}, $keys[$i]->{'pub'}->{'created'}) = ($1, $2, $3)
918 if $_ =~ m/^pub\s*?(\w*?)\/(\w*?)\s(\d{4}-\d{2}-\d{2})/;
919 $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})\]/;
920 $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})\]/;
921 } elsif ($_ =~ m/^sub\s.*$/) {
922 ($keys[$i]->{'sub'}->{'length'}, $keys[$i]->{'sub'}->{'uid'}, $keys[$i]->{'sub'}->{'created'}) = ($1, $2, $3)
923 if $_ =~ m/^sub\s*?(\w*?)\/(\w*?)\s(\d{4}-\d{2}-\d{2})/;
924 $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})\]/;
925 $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})\]/;
926 } elsif ($_ =~ m/^uid\s.*$/) {
927 push @{$keys[$i]->{'uid'}}, $1 if $_ =~ m/^uid\s*?([^\s].*?)$/;
928 } elsif ($_ =~ m/^$/) {
929 $i++;
930 }
931 }
932 }
934 my $i=0;
935 foreach my $key (@keys) {
936 # &main::daemon_log(Dumper($key));
937 &add_content2xml_hash($out_hash, "answer".$i++, $key);
938 }
939 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
940 if (defined $forward_to_gosa) {
941 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
942 }
943 return &create_xml_string($out_hash);
944 }
947 sub import_dak_key {
948 my ($msg, $msg_hash) = @_;
949 my $source = @{$msg_hash->{'source'}}[0];
950 my $target = @{$msg_hash->{'target'}}[0];
951 my $header= @{$msg_hash->{'header'}}[0];
952 my $session_id = @{$msg_hash->{'session_id'}}[0];
953 my $key = &decode_base64(@{$msg_hash->{'key'}}[0]);
955 # build return message with twisted target and source
956 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
957 &add_content2xml_hash($out_hash, "session_id", $session_id);
959 my %data;
961 my $keyring = $main::dak_signing_keys_directory."/keyring.gpg";
963 my $gpg_cmd = `which gpg`; chomp $gpg_cmd;
964 my $gpg = "$gpg_cmd --no-default-keyring --no-random-seed --keyring $keyring";
966 # Check if the keyrings are in place and writable
967 if(
968 &run_as($main::dak_user, "test -w $keyring")->{'resultCode'} != 0
969 ) {
970 &add_content2xml_hash($out_hash, "error", "DAK Keyring is not writable");
971 } else {
972 my $keyfile;
973 open($keyfile, ">/tmp/gosa_si_tmp_dak_key");
974 print $keyfile $key;
975 close($keyfile);
976 my $command = "$gpg --import /tmp/gosa_si_tmp_dak_key";
977 my $output = &run_as($main::dak_user, $command);
978 &main::daemon_log("$session_id DEBUG: ".$output->{'command'}, 7);
979 unlink("/tmp/gosa_si_tmp_dak_key");
981 if($output->{'resultCode'} != 0) {
982 &add_content2xml_hash($out_hash, "error", "Import of DAK key failed! Output was '".$output->{'output'}."'");
983 } else {
984 &add_content2xml_hash($out_hash, "answer", "Import of DAK key successfull! Output was '".$output->{'output'}."'");
985 }
986 }
988 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
989 if (defined $forward_to_gosa) {
990 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
991 }
992 return &create_xml_string($out_hash);
993 }
996 sub remove_dak_key {
997 my ($msg, $msg_hash) = @_;
998 my $source = @{$msg_hash->{'source'}}[0];
999 my $target = @{$msg_hash->{'target'}}[0];
1000 my $header= @{$msg_hash->{'header'}}[0];
1001 my $session_id = @{$msg_hash->{'session_id'}}[0];
1002 my $key = @{$msg_hash->{'keyid'}}[0];
1003 # build return message with twisted target and source
1004 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
1005 &add_content2xml_hash($out_hash, "session_id", $session_id);
1007 my %data;
1009 my $keyring = $main::dak_signing_keys_directory."/keyring.gpg";
1011 my $gpg_cmd = `which gpg`; chomp $gpg_cmd;
1012 my $gpg = "$gpg_cmd --no-default-keyring --no-random-seed --homedir ".$main::dak_signing_keys_directory." --keyring $keyring";
1014 # Check if the keyrings are in place and writable
1015 if(
1016 &run_as($main::dak_user, "test -w $keyring")->{'resultCode'} != 0
1017 ) {
1018 &add_content2xml_hash($out_hash, "error", "DAK keyring is not writable");
1019 } else {
1020 # Check if the key is present in the keyring
1021 if(&run_as($main::dak_user, "$gpg --list-keys $key")->{'resultCode'} == 0) {
1022 my $command = "$gpg --batch --yes --delete-key $key";
1023 my $output = &run_as($main::dak_user, $command);
1024 &main::daemon_log("$session_id DEBUG: ".$output->{'command'}, 7);
1025 } else {
1026 &add_content2xml_hash($out_hash, "error", "DAK key with id '$key' was not found in keyring");
1027 }
1028 }
1030 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
1031 if (defined $forward_to_gosa) {
1032 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
1033 }
1034 return &create_xml_string($out_hash);
1035 }
1038 #sub get_dak_queue {
1039 # my ($msg, $msg_hash, $session_id) = @_;
1040 # my %data;
1041 # my $source = @{$msg_hash->{'source'}}[0];
1042 # my $target = @{$msg_hash->{'target'}}[0];
1043 # my $header= @{$msg_hash->{'header'}}[0];
1044 #
1045 # my %data;
1046 #
1047 # foreach my $dir ("unchecked", "new", "accepted") {
1048 # foreach my $file(<"$main::dak_queue_directory/$dir/*.changes">) {
1049 # }
1050 # }
1051 #
1052 # my $out_msg = &build_msg("get_dak_queue", $target, $source, \%data);
1053 # my @out_msg_l = ($out_msg);
1054 # return @out_msg_l;
1055 #}
1058 # vim:ts=4:shiftwidth:expandtab
1059 1;