X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=gosa-si%2Fgosa-si-client;h=9b0374de264db0b450c8f716dd700f741b50a421;hb=3a7450dc50ba1025b3f92be435eecfa2f0156fa1;hp=d4e17c29f187f21dbe6cbc92efe4b16b76c7e468;hpb=d2f2a734736784c5bda3eae332583ef60f77109b;p=gosa.git diff --git a/gosa-si/gosa-si-client b/gosa-si/gosa-si-client index d4e17c29f..9b0374de2 100755 --- a/gosa-si/gosa-si-client +++ b/gosa-si/gosa-si-client @@ -35,11 +35,12 @@ use Digest::MD5 qw(md5_hex md5 md5_base64); use MIME::Base64; use XML::Simple; use Net::DNS; +use File::Basename; my $event_dir = "/usr/lib/gosa-si/client/events"; use lib "/usr/lib/gosa-si/client/events"; -my ($cfg_file, %cfg_defaults, $foreground, $verbose, $pid_file, $procid, $pid, $log_file, $fai_logpath); +my ($cfg_file, %cfg_defaults, $foreground, $verbose, $pid_file, $opts_file, $procid, $pid, $log_file, $fai_logpath); my ($server_ip, $server_port, $server_key, $server_timeout, $server_domain, $server_key_lifetime); my ($client_ip, $client_port, $client_mac_address, $ldap_enabled, $ldap_config, $pam_config, $nss_config); my $xml; @@ -47,6 +48,7 @@ my $default_server_key; my $event_hash; my @servers; my $gotoHardwareChecksum; +$verbose= 1; # globalise variables which are used in imported events our $cfg_file; @@ -55,30 +57,36 @@ our $client_address; our $server_key; # default variables -our $REGISTERED_FLAG = 1; +our $REGISTERED = 0; + +# 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; +our $prg= basename($0); %cfg_defaults = ( "general" => - {"log_file" => [\$log_file, "/var/run/".$0.".log"], - "pid_file" => [\$pid_file, "/var/run/".$0.".pid"], - "fai_logpath" => [\$fai_logpath, "/var/log/fai/fai.log"], + {"log-file" => [\$log_file, "/var/run/".$prg.".log"], + "pid-file" => [\$pid_file, "/var/run/".$prg.".pid"], + "opts-file" => [\$opts_file, "/var/run/".$prg.".opts"], }, "client" => - {"client_port" => [\$client_port, "20083"], - "client_ip" => [\$client_ip, "0.0.0.0"], - "client_mac_address" => [\$client_mac_address, "00:00:00:00:00:00"], + {"port" => [\$client_port, "20083"], + "ip" => [\$client_ip, "0.0.0.0"], + "mac-address" => [\$client_mac_address, "00:00:00:00:00:00"], + "server-domain" => [\$server_domain, ""], "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"], + "ldap-config" => [\$ldap_config, "/etc/ldap/ldap.conf"], + "pam-config" => [\$pam_config, "/etc/pam_ldap.conf"], + "nss-config" => [\$nss_config, "/etc/libnss_ldap.conf"], + "fai-logpath" => [\$fai_logpath, "/var/log/fai/fai.log"], }, -"server" => - {"server_ip" => [\$server_ip, "127.0.0.1"], - "server_port" => [\$server_port, "20081"], - "server_key" => [\$server_key, ""], - "server_timeout" => [\$server_timeout, 10], - "server_domain" => [\$server_domain, ""], - "server_key_lifetime" => [\$server_key_lifetime, 600], +"server" => { + "ip" => [\$server_ip, "127.0.0.1"], + "port" => [\$server_port, "20081"], + "key" => [\$server_key, ""], + "timeout" => [\$server_timeout, 10], + "key-lifetime" => [\$server_key_lifetime, 600], }, ); @@ -216,10 +224,8 @@ sub daemon_log { $month = $monthnames[$month]; $monthday = $monthday < 10 ? $monthday = "0".$monthday : $monthday; $year+=1900; - my $name = $0; - $name =~ s/\.\///; - my $log_msg = "$month $monthday $hours:$minutes:$seconds $name $msg\n"; + my $log_msg = "$month $monthday $hours:$minutes:$seconds $prg $msg\n"; print LOG_HANDLE $log_msg; if( $foreground ) { print STDERR $log_msg; @@ -742,40 +748,20 @@ sub get_server_addresses { #=== FUNCTION ================================================================ -# NAME: send_msg_hash2address +# NAME: send_msg_hash_to_target # PARAMETERS: msg_hash - hash - xml_hash created with function create_xml_hash # PeerAddr string - socket address to send msg # PeerPort string - socket port, if not included in socket address # RETURNS: nothing # DESCRIPTION: ???? #=============================================================================== -sub send_msg_hash2address { - my ($msg_hash, $address, $passwd) = @_ ; - - # fetch header for logging - my $header = @{$msg_hash->{header}}[0]; - - # generate xml string - my $msg_xml = &create_xml_string($msg_hash); - - # encrypt xml msg - my $crypted_msg = &encrypt_msg($msg_xml, $passwd); - - # opensocket - my $socket = &open_socket($address); - if(not defined $socket){ - daemon_log("cannot send '$header'-msg to $address , server not reachable", 5); - return 1; - } +sub send_msg_hash_to_target { + my ($msg_hash, $address, $encrypt_key) = @_ ; + my $msg = &create_xml_string($msg_hash); + my $header = @{$msg_hash->{'header'}}[0]; + my $error = &send_msg_to_target($msg, $address, $encrypt_key, $header); - # send xml msg - print $socket $crypted_msg."\n"; - - close $socket; - - daemon_log("send '$header'-msg to $address", 1); - daemon_log("message:\n$msg_xml", 8); - return 0; + return $error; } @@ -814,7 +800,33 @@ sub send_msg_to_target { close $socket; } - return; + return $error; +} + + +sub write_to_file { + my ($string, $file) = @_; + my $error = 0; + + if( not defined $file || not -f $file ) { + &main::daemon_log("ERROR: $prg: check '-f file' failed: $file", 1); + $error++; + } + if( not defined $string || 0 == length($string)) { + &main::daemon_log("ERROR: $prg: empty string to write to file '$file'", 1); + $error++; + } + + if( $error == 0 ) { + + chomp($string); + + open(FILE, ">> $file"); + print FILE $string."\n"; + close(FILE); + } + + return; } @@ -845,57 +857,89 @@ sub open_socket { #=============================================================================== sub register_at_gosa_si_server { my ($kernel) = $_[KERNEL]; + my $try_to_register = 0; - if( $REGISTERED_FLAG == 1 ) { - - + 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 $resolver= Net::DNS::Resolver->new; my $dnsresult= $resolver->search($ip); + my $dnsname=""; if(!defined($dnsresult)) { - &write_to_file("goto-dns-error:Could not resolve hostname for ip $ip", $fai_logpath); + &write_to_file("goto-error-dns:$ip", $fai_logpath); exit(1); + } else { + $dnsname=$dnsresult->{answer}[0]->{ptrdname}; } - if( !$server ) { - daemon_log("no gosa-si-server left in list of servers", 1); - daemon_log("unable to register at a gosa-si-server, force shutdown", 1); - exit(1); - } - # create registration msg - my $register_hash = &create_xml_hash("here_i_am", &get_local_ip_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/)).":".$client_port, $server); + 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", &get_local_mac_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/))); + &add_content2xml_hash($register_hash, "mac_address", $local_mac); &add_content2xml_hash($register_hash, "events", $events); &add_content2xml_hash($register_hash, "gotoHardwareChecksum", $gotoHardwareChecksum); # send xml hash to server with general server passwd - my $res = &send_msg_hash2address($register_hash, $server, $default_server_key); + 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 $client_ip= &get_local_ip_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/)); $client_address= "$client_ip:$client_port"; + + # Write the MAC address to file + if(stat($opts_file)) { + unlink($opts_file); + } + my $opts_file_FH; + my $hostname= $dnsname; + $hostname =~ s/\..*$//; + open($opts_file_FH, ">$opts_file"); + print $opts_file_FH "MAC=\"$local_mac\"\n"; + print $opts_file_FH "IPADDRESS=\"$client_ip\"\n"; + print $opts_file_FH "HOSTNAME=\"$hostname\"\n"; + print $opts_file_FH "FQDN=\"$dnsname\"\n"; + close($opts_file_FH); last; } else { + $try_to_register++; + # wait 1 sec until trying to register again + sleep(1); next; } } - daemon_log("waiting for msg 'register_at_gosa_si_server'",1); - $kernel->delay_set('register_at_gosa_si_server',180); - # clear old settings and set it again - $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("waiting for msg 'register_at_gosa_si_server'",1); + $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; } @@ -914,6 +958,7 @@ sub check_key_and_xml_validity { $msg_hash = $xml->XMLin($msg, ForceArray=>1); + ############## # check header my $header_l = $msg_hash->{'header'}; if( 1 != @{$header_l} ) { @@ -924,36 +969,102 @@ sub check_key_and_xml_validity { die 'header has length 0'; } + ############## # check source my $source_l = $msg_hash->{'source'}; if( 1 != @{$source_l} ) { - die 'no or more sources specified'; + die 'no or more than 1 sources specified'; } my $source = @{$source_l}[0]; if( 0 == length $source) { die 'source has length 0'; } - - # check target + unless( $source =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+$/ ) { + die "source '$source' is neither a complete ip-address with port nor 'GOSA'"; + } + + ############## + # check target my $target_l = $msg_hash->{'target'}; if( 1 != @{$target_l} ) { - die 'no or more targets specified '; + die 'no or more than 1 targets specified '; } my $target = @{$target_l}[0]; if( 0 == length $target) { die 'target has length 0 '; } - + unless( $target =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+$/ ){ + die "source is neither a complete ip-address with port nor 'GOSA'"; + } }; if($@) { &main::daemon_log("WARNING: do not understand the message or msg is not gosa-si envelope conform:", 5); &main::daemon_log("$@", 8); + $msg = undef; + $msg_hash = undef; } return ($msg, $msg_hash); } +sub check_outgoing_xml_validity { + my ($msg) = @_; + + my $msg_hash; + eval{ + $msg_hash = $xml->XMLin($msg, ForceArray=>1); + + ############## + # check header + my $header_l = $msg_hash->{'header'}; + if( 1 != @{$header_l} ) { + die 'no or more than one headers specified'; + } + my $header = @{$header_l}[0]; + if( 0 == length $header) { + die 'header has length 0'; + } + + ############## + # check source + my $source_l = $msg_hash->{'source'}; + if( 1 != @{$source_l} ) { + die 'no or more than 1 sources specified'; + } + my $source = @{$source_l}[0]; + if( 0 == length $source) { + die 'source has length 0'; + } + unless( $source =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+$/ || + $source =~ /^GOSA$/i ) { + die "source '$source' is neither a complete ip-address with port"; + } + + ############## + # check target + my $target_l = $msg_hash->{'target'}; + if( 1 != @{$target_l} ) { + die "no or more than one targets specified"; + } + foreach my $target (@$target_l) { + if( 0 == length $target) { + die "target has length 0"; + } + unless( $target =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+$/ ) { + die "target '$target' is not a complete ip-address with port or a valid target name"; + } + } + }; + if($@) { + daemon_log("WARNING: outgoing msg is not gosa-si envelope conform", 5); + daemon_log("$@ $msg", 8); + $msg_hash = undef; + } + return ($msg_hash); +} + + sub import_events { if (not -e $event_dir) { @@ -1012,6 +1123,7 @@ sub server_input { $error++; } + ###################### # process incoming msg if( $error == 0 ) { @@ -1032,21 +1144,31 @@ sub server_input { ######## # answer if( $answer ) { - # preprocessing - if( $answer =~ "
registered
") { - # set registered flag to true to stop sending further registered msgs - $REGISTERED_FLAG = 0; - } - else { - &send_msg_to_target($answer, $server_address, $server_key); - } - # postprocessing - if( $answer =~ "
new_key
") { - # set new key to global variable - $answer =~ /(\S*?)<\/new_key>/; - my $new_key = $1; - $server_key = $new_key; + + #check gosa-si envelope validity + my $answer_hash = &check_outgoing_xml_validity($answer); + + if( $answer_hash ) { + # answer is valid + + # preprocessing + if( $answer =~ "
registered
") { + # set registered flag to true to stop sending further registered msgs + $REGISTERED = 1; + } + else { + &send_msg_to_target($answer, $server_address, $server_key); + } + + # postprocessing + if( $answer =~ "
new_key
") { + # set new key to global variable + $answer =~ /(\S*?)<\/new_key>/; + my $new_key = $1; + $server_key = $new_key; + } } + } return; @@ -1096,7 +1218,7 @@ if( 0 != $pid ) { } daemon_log(" ", 1); -daemon_log("$0 started!", 1); +daemon_log("$prg started!", 1); # delete old DBsqlite lock files system('rm -f /tmp/gosa_si_lock*gosa-si-client*');