X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=gosa-si%2Fgosa-si-client;h=d9bf2393d29dd576ce5850a5106a87a3e39ecf01;hb=1164b82972575c6389707407a1b11ccc066e2028;hp=6e4fdc38dc909059e5c44aadb94263d007d78759;hpb=651f27b4a03e89df0f9414568c9207bc9bf15430;p=gosa.git diff --git a/gosa-si/gosa-si-client b/gosa-si/gosa-si-client index 6e4fdc38d..d9bf2393d 100755 --- a/gosa-si/gosa-si-client +++ b/gosa-si/gosa-si-client @@ -20,13 +20,12 @@ use strict; use warnings; -use utf8; use Getopt::Long; use Config::IniFiles; use POSIX; use Time::HiRes qw( gettimeofday ); -use POE qw(Component::Server::TCP Wheel::FollowTail); +use POE qw(Component::Server::TCP Wheel::FollowTail Wheel::Run); use IO::Socket::INET; use NetAddr::IP; use Data::Dumper; @@ -37,6 +36,10 @@ use MIME::Base64; use XML::Simple; use Net::DNS; use File::Basename; +use File::Spec; + +# Workaround: need pure perl to make it work with UTF-8 :-( +$XML::Simple::PREFERRED_PARSER= "XML::SAX::PurePerl"; my $event_dir = "/usr/lib/gosa-si/client/events"; use lib "/usr/lib/gosa-si/client/events"; @@ -73,12 +76,15 @@ $gosa_si_client_fifo = "/var/run/gosa-si-client.socket"; # in function register_at_gosa_si_server, after which period of seconds a new registration should be tried if a registration was # not successful until now -my $delay_set_time = 5; +my $delay_set_time = 10; our $prg= basename($0); # all x seconds the client reports logged_in users to gosa-si-server my $trigger_logged_in_users_report_delay = 600; +# directory where all log files from installation are stored +my $fai_log_dir = "/tmp/fai"; + %cfg_defaults = ( "general" => {"log-file" => [\$log_file, "/var/run/".$prg.".log"], @@ -93,7 +99,7 @@ my $trigger_logged_in_users_report_delay = 600; "ldap" => [\$ldap_enabled, 1], "ldap-config" => [\$ldap_config, "/etc/ldap/ldap.conf"], "pam-config" => [\$pam_config, "/etc/pam_ldap.conf"], - "nss-config" => [\$nss_config, "/etc/libnss_ldap.conf"], + "nss-config" => [\$nss_config, "/etc/libnss-ldap.conf"], "fai-logpath" => [\$fai_logpath, "/var/log/fai/fai.log"], "force-hostname" => [\$client_force_hostname, "false"], }, @@ -144,7 +150,7 @@ sub check_cmdline_param () { sub read_configfile { my ($cfg_file, %cfg_defaults) = @_ ; my $cfg; - if( defined( $cfg_file) && ( length($cfg_file) > 0 )) { + if( defined( $cfg_file) && ( (-s $cfg_file) > 0 )) { if( -r $cfg_file ) { $cfg = Config::IniFiles->new( -file => $cfg_file ); } else { @@ -156,7 +162,7 @@ sub read_configfile { foreach my $section (keys %cfg_defaults) { foreach my $param (keys %{$cfg_defaults{ $section }}) { my $pinfo = $cfg_defaults{ $section }{ $param }; - ${@$pinfo[ 0 ]} = $cfg->val( $section, $param, @$pinfo[ 1 ] ); + ${@$pinfo[ 0 ]} = $cfg->val( $section, $param, @$pinfo[ 1 ] ); } } } @@ -213,9 +219,9 @@ sub check_pid { sub sig_int_handler { my ($signal) = @_; - - daemon_log("shutting down gosa-si-server", 1); - exit(1); + + daemon_log("shutting down gosa-si-client", 1); + system("kill `ps -C gosa-si-client -o pid=`"); } $SIG{INT} = \&sig_int_handler; @@ -607,18 +613,22 @@ sub send_msg_to_target { # encrypt xml msg my $crypted_msg = &encrypt_msg($msg, $encrypt_key); + # xxxxxxxxxxxxxx + + + # opensocket my $socket = &open_socket($address); if( !$socket ) { - daemon_log("cannot send ".$msg_header."msg to $address , host not reachable", 1); + daemon_log("ERROR: cannot send ".$msg_header."msg to $address , host not reachable", 1); $error++; } # send xml msg if( $error == 0 ) { print $socket $crypted_msg."\n"; - daemon_log("send ".$msg_header."msg to $address", 1); - daemon_log("message:\n$msg", 8); + daemon_log("INFO: send ".$msg_header."msg to $address", 5); + daemon_log("DEBUG: message:\n$msg", 8); } # close socket in any case @@ -647,9 +657,10 @@ sub write_to_file { chomp($string); - open(FILE, ">> $file"); - print FILE $string."\n"; - close(FILE); + if (open(FILE, ">> $file")){ + print FILE $string."\n"; + close(FILE); + } } return; @@ -684,85 +695,95 @@ sub open_socket { sub register_at_gosa_si_server { my ($kernel) = $_[KERNEL]; my $try_to_register = 0; + + # if client is already registered, stop registration process + if ($REGISTERED) { + $kernel->delay('register_at_gosa_si_server'); - if( not $REGISTERED ) { - # create new passwd and ciphering object for client-server communication - $server_key = &create_passwd(); - - my $events = join( ",", keys %{$event_hash} ); - while(1) { - - if( $try_to_register >= @servers ) { - last; - } - - # fetch first gosa-si-server from @servers - my $server = shift(@servers); - - # append shifted gosa-si-server at the end of @servers, so looking for servers never stop if - # a registration never occured - push( @servers, $server ); - - # Check if our ip is resolvable - if not: don't try to register - my $ip= &get_local_ip_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/)); - my $dnsname= gethostbyaddr(inet_aton($ip), AF_INET); - if(!defined($dnsname)) { - &write_to_file("goto-error-dns:$ip", $fai_logpath); - exit(1); - } - - # create registration msg - my $local_ip = &get_local_ip_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/)); - my $local_mac = &get_local_mac_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/)); - my $register_hash = &create_xml_hash("here_i_am", $local_ip.":".$client_port, $server); - &add_content2xml_hash($register_hash, "new_passwd", $server_key); - &add_content2xml_hash($register_hash, "mac_address", $local_mac); - &add_content2xml_hash($register_hash, "events", $events); - &add_content2xml_hash($register_hash, "gotoHardwareChecksum", $gotoHardwareChecksum); - - # Add $HOSTNAME from ENV if force-hostname is set - if( defined($client_force_hostname) && - $client_force_hostname eq "true") { - if(defined($ENV{HOSTNAME}) && - length($ENV{HOSTNAME}) >0 ) { - &add_content2xml_hash($register_hash, "force-hostname", $ENV{HOSTNAME}); - } else { - &main::daemon_log("force-hostname was set to true, but no \$HOSTNAME was found in Environment!",0); - } - } - - # send xml hash to server with general server passwd - my $res = &send_msg_hash_to_target($register_hash, $server, $default_server_key); - if($res == 0) { - # reset try_to_register - $try_to_register = 0; - - # Set fixed client address and mac address - $client_ip= &get_local_ip_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/)); - $client_address= "$client_ip:$client_port"; - $client_mac_address = $local_mac; - $client_dnsname = $dnsname; - - last; - } else { - $try_to_register++; - - # wait 1 sec until trying to register again - sleep(1); - next; - } - } + # client is not registered, start registration process + } else { + # clear all other triggered events and wait till registration was successful + $kernel->delay('trigger_new_key'); + + # create new passwd and ciphering object for client-server communication + $server_key = &create_passwd(); + + my $events = join( ",", keys %{$event_hash} ); + while(1) { + # fetch first gosa-si-server from @servers + my $server = shift(@servers); + + # append shifted gosa-si-server at the end of @servers, so looking for servers never stop if + # a registration never occured + push( @servers, $server ); + + # Check if our ip is resolvable - if not: don't try to register + my $ip= &get_local_ip_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/)); + my $dnsname= gethostbyaddr(inet_aton($ip), AF_INET); + if(!defined($dnsname)) { + &write_to_file("goto-error-dns:$ip", $fai_logpath); + exit(1); + } + + # create registration msg + my $local_ip = &get_local_ip_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/)); + my $local_mac = &get_local_mac_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/)); + my $register_hash = &create_xml_hash("here_i_am", $local_ip.":".$client_port, $server); + &add_content2xml_hash($register_hash, "new_passwd", $server_key); + &add_content2xml_hash($register_hash, "mac_address", $local_mac); + &add_content2xml_hash($register_hash, "events", $events); + &add_content2xml_hash($register_hash, "gotoHardwareChecksum", $gotoHardwareChecksum); + + # Add $HOSTNAME from ENV if force-hostname is set + if( defined($client_force_hostname) && $client_force_hostname eq "true") { + if(defined($ENV{HOSTNAME}) && length($ENV{HOSTNAME}) >0 ) { + &add_content2xml_hash($register_hash, "force-hostname", $ENV{HOSTNAME}); + } else { + &main::daemon_log("force-hostname was set to true, but no \$HOSTNAME was found in Environment!",0); + } + } + + # send xml hash to server with general server passwd + my $res = &send_msg_hash_to_target($register_hash, $server, $default_server_key); + + if( $try_to_register >= @servers ) { last; } + + # if delivery of registration msg succeed + if($res == 0) { + # reset try_to_register + $try_to_register = 0; + + # Set fixed client address and mac address + $client_ip= &get_local_ip_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/)); + $client_address= "$client_ip:$client_port"; + $client_mac_address = $local_mac; + $client_dnsname = $dnsname; + last; + + # delivery of registration msg failed + } else { + $try_to_register++; + # wait 1 sec until trying to register again + sleep(1); + next; + } + + } # end of while + + # one circle through all servers finished and no registration succeed + if ( $try_to_register >= @servers ) { + &write_to_file("gosa-si-no-server-available", $fai_logpath); + $kernel->delay_set('register_at_gosa_si_server', $delay_set_time); + + # delivery of registraion msg succeed, waiting for server response + } else { + daemon_log("INFO: waiting for msg 'register_at_gosa_si_server'",5); + $kernel->delay_set('register_at_gosa_si_server', $delay_set_time); + # clear old settings and set it again + $kernel->delay('trigger_new_key'); + $kernel->delay_set('trigger_new_key', $server_key_lifetime); + } - if( $try_to_register >= @servers ) { - &write_to_file("gosa-si-no-server-available", $fai_logpath); - $kernel->delay_set('register_at_gosa_si_server', $delay_set_time); - } - else { - daemon_log("INFO: waiting for msg 'register_at_gosa_si_server'",5); - $kernel->delay_set('register_at_gosa_si_server', $delay_set_time); - # clear old settings and set it again - $kernel->delay_set('trigger_new_key', $server_key_lifetime); - } } return; } @@ -899,7 +920,7 @@ sub import_events { eval{ require $event; }; if( $@ ) { daemon_log("ERROR: import of event module '$event' failed", 1); - daemon_log("$@", 8); + daemon_log("$@", 1); next; } @@ -933,36 +954,29 @@ sub trigger_logged_in_users_report { # just do if client is registered already if( $REGISTERED ) { - my $result = qx(/usr/bin/w -hs); - my @res_lines; - - if( defined $result ) { - chomp($result); - @res_lines = split("\n", $result); - } - - my @logged_in_user_list; - foreach my $line (@res_lines) { - chomp($line); - my @line_parts = split(/\s+/, $line); - push(@logged_in_user_list, $line_parts[0]); - } + my $result = qx(/usr/bin/users); + my @logged_in_user_list; + if( defined $result ) { + chomp($result); + @logged_in_user_list = split(/\s/, $result); + } + system("echo 'CURRENTLY_LOGGED_IN ".join(" ", @logged_in_user_list)."' > /var/run/gosa-si-client.socket"); $kernel->delay_set('trigger_logged_in_users_report', $trigger_logged_in_users_report_delay); } else { - # try it in 1 sec again - $kernel->delay_set('trigger_logged_in_users_report', 1); + # try it in 10 sec again + $kernel->delay_set('trigger_logged_in_users_report', 10); } } -sub generic_file_reset { - my ( $heap, $wheel_id ) = @_[ HEAP, ARG0 ]; - - my $service = $heap->{services}->{$wheel_id}; - daemon_log("INFO: '$service' watching reset", 5); - return; -} +#sub generic_file_reset { +# my ( $heap, $wheel_id ) = @_[ HEAP, ARG0 ]; +# +# my $service = $heap->{services}->{$wheel_id}; +# daemon_log("INFO: '$service' watching reset", 5); +# return; +#} sub generic_file_error { my ( $heap, $operation, $errno, $error_string, $wheel_id ) = @@ -977,10 +991,12 @@ sub generic_file_error { return; } + sub fifo_got_record { my $file_record = $_[ARG0]; my $header; my $content = ""; + daemon_log("DEBUG: fifo got record: $file_record", 7); $file_record =~ /^(\S+)[ ]?([\s\S]+)?$/; if( defined $1 ) { @@ -997,10 +1013,55 @@ sub fifo_got_record { &add_content2xml_hash($clmsg_hash, "macaddress", $client_mac_address); my $clmsg = &create_xml_string($clmsg_hash); &send_msg_to_target($clmsg, $server_address, $server_key, "CLMSG_$header"); + + # if installation finished, save all log files + if ($file_record eq "TASKBEGIN finish") { + &save_fai_log($fai_log_dir); + } + return; } +sub save_fai_log { + my ($fai_log_dir) = @_ ; + my $FAI_DIR; + + opendir($FAI_DIR, $fai_log_dir); + if (not defined $FAI_DIR) { + daemon_log("ERROR: can not open directory $fai_log_dir: $!", 1); + return; + } + + my @log_files = readdir($FAI_DIR); + closedir($FAI_DIR); + my @log_list; + + foreach my $log_file (@log_files) { + if( $log_file eq "." || $log_file eq ".." ) { next; } + my $log = "log_file:$log_file:"; + $log_file = File::Spec->catfile( $fai_log_dir, $log_file ); + open(my $FILE, "<$log_file"); + if (not defined $FILE ) { + daemon_log("ERROR: can not open '$log_file': $!", 1); + next; + } + my @lines = <$FILE>; + my $log_string = join("", @lines); + $log .= &encode_base64($log_string); + push(@log_list, $log); + close ($FILE); + } + + my $all_log_string = join("\n", @log_list); + my $msg_hash = &create_xml_hash("CLMSG_save_fai_log", $client_address, $server_address, $all_log_string); + &add_content2xml_hash($msg_hash, "macaddress", $client_mac_address); + my $msg = &create_xml_string($msg_hash); + &send_msg_to_target($msg, $server_address, $server_key, "CLMSG_save_fai_log"); + +} + + sub _start { my ($kernel, $heap) = @_[KERNEL, HEAP]; $kernel->alias_set('client_session'); @@ -1009,15 +1070,19 @@ sub _start { $kernel->yield('register_at_gosa_si_server'); # install all file watcher defined - while( my($file_name, $file) = each %files_to_watch ) { - my $file_watcher = POE::Wheel::FollowTail->new( + while( my($name, $file) = each %files_to_watch ) { + my $watcher = POE::Wheel::FollowTail->new( Filename => $file, - InputEvent => $file_name."_record", - ResetEvent => "file_reset", + InputEvent => $name."_record", + # ResetEvent => "file_reset", ErrorEvent => "file_error", ); - $heap->{services}->{ $file_watcher->ID } = $file_name; - $heap->{watchers}->{ $file_watcher->ID } = $file_watcher; +# $heap->{tail} = POE::Wheel::Run->new( +# Program => [ "/usr/bin/tail", "-f", $file ], +# StdoutEvent => $file_name."_record", +# ); + $heap->{services}->{ $watcher->ID } = $name; + $heap->{watchers}->{ $watcher->ID } = $watcher; } $kernel->yield('trigger_logged_in_users_report'); } @@ -1031,14 +1096,31 @@ sub _default { sub server_input { my ($kernel, $heap, $input, $wheel) = @_[KERNEL, HEAP, ARG0, ARG1]; + my $remote_ip = $heap->{'remote_ip'}, my $error = 0; my $answer; - daemon_log("Incoming msg:\n$input\n", 8); + + daemon_log("INFO: Incoming msg from '$remote_ip'", 5); + daemon_log("DEBUG: Incoming msg:\n$input\n", 8); my ($msg, $msg_hash) = &check_key_and_xml_validity($input, $server_key); if( (!$msg) || (!$msg_hash) ) { - daemon_log("Deciphering of incoming msg failed", 5); + daemon_log("WARNING: Deciphering of incoming msg failed", 3); + if($server_address =~ /$remote_ip/) { + # got a msg from gosa-si-server which can not be decrypted, may the secrete not up-to-date + # cause a reregistering with a new secrete handshake + daemon_log("WARNING: Message from gosa-si-server could not be understood, cause reregistering at server", 3); + + # if client is alread in a registration process, that means not registered, do nothing + # if not, cause re-registration + if (not $REGISTERED) { + &daemon_log("WARNING: gosa-si-client is already in a registration process so ignore this message", 3); + } else { + $REGISTERED = 0; + $kernel->post('client_session', 'register_at_gosa_si_server'); + } + } $error++; } @@ -1050,8 +1132,9 @@ sub server_input { my $source = @{$msg_hash->{source}}[0]; if( exists $event_hash->{$header} ) { + # a event exists with the header as name - daemon_log("found event '$header' at event-module '".$event_hash->{$header}."'", 5); + daemon_log("DEBUG: found event '$header' at event-module '".$event_hash->{$header}."'", 7); no strict 'refs'; $answer = &{$event_hash->{$header}."::$header"}($msg, $msg_hash); } @@ -1076,7 +1159,8 @@ sub server_input { $REGISTERED = 1; } else { - &send_msg_to_target($answer, $server_address, $server_key); + $answer =~ /
(\S+)<\/header>/; + &send_msg_to_target($answer, $server_address, $server_key, $1); } # postprocessing @@ -1184,7 +1268,7 @@ $default_server_key = $server_key; # add gosa-si-server address from config file at first position of server list my $server_check_cfg = Config::IniFiles->new( -file => $cfg_file ); -my $server_check = $server_check_cfg->val( "server", "ip"); +my $server_check = (defined($server_check_cfg))?$server_check_cfg->val( "server", "ip"):undef; if( defined $server_check ) { unshift(@servers, $server_address); my $servers_string = join(", ", @servers);