From c85bed32f98a74efbd9b12268e3959882ef0534f Mon Sep 17 00:00:00 2001 From: psc Date: Wed, 10 Mar 2010 18:55:07 +0000 Subject: [PATCH] Fix for #4070 - Add support for a new configuration option "dns-lookup" to control weither DNS lookups shall happen at all - Find servers from DNS always if the dnslookup option is true. This way these servers can be used as fallback even if a server is configured. Otherwise DNS lookups do not happen if a server is configured in the client configuration. - Support multiple servers in the configuration file. - Use a global for tracking the registration tries, because otherwise the used server will not be exchanged, because the try counter gets reset everytime a new register event is yielded - Minor bugfix: Do not try to compare $res to "0" if $res is not defined. git-svn-id: https://oss.gonicus.de/repositories/gosa/branches/2.6-lhm@16397 594d385d-05f5-0310-b6e9-bd551577e9d8 --- trunk/gosa-si/gosa-si-client | 191 ++++++++++++++++++++++------------- 1 file changed, 122 insertions(+), 69 deletions(-) diff --git a/trunk/gosa-si/gosa-si-client b/trunk/gosa-si/gosa-si-client index 45a3b2938..db4773b46 100755 --- a/trunk/gosa-si/gosa-si-client +++ b/trunk/gosa-si/gosa-si-client @@ -60,6 +60,7 @@ my @servers; my $gotoHardwareChecksum; my $gosa_si_client_fifo; my %files_to_watch; +my $servers_string; $verbose= 1; # globalise variables which are used in imported events @@ -73,9 +74,13 @@ our $client_mac_address; our $client_dnsname; our $client_force_hostname; our $server_key; +our $opts_dnslookup; # default variables our $REGISTERED = 0; +our $REGISTRATION_IN_PROGRESS = 0; +our $REGISTRATION_TRIES = 0; +our $FAILED_CRYPTO = 0; # path to fifo for non-gosa-si-client messages to gosa-si-server $gosa_si_client_fifo = "/var/run/gosa-si-client.socket"; @@ -86,6 +91,10 @@ $gosa_si_client_fifo = "/var/run/gosa-si-client.socket"; my $delay_set_time = 10; our $prg= basename($0); +# Threshold for the max number of wrong crypted packages, when triggered +# a new server is choosen +my $max_failed_crypto_messages = 5; + # all n seconds the client reports logged_in users to gosa-si-server my $trigger_logged_in_users_report_delay = 600; @@ -114,11 +123,12 @@ my $fai_log_dir = "/var/log/fai"; "force-hostname" => [\$client_force_hostname, "false"], }, "server" => { - "ip" => [\$server_ip, "127.0.0.1"], + "ip" => [\$servers_string, "127.0.0.1"], "port" => [\$server_port, "20081"], "key" => [\$server_key, ""], "timeout" => [\$server_timeout, 10], "key-lifetime" => [\$server_key_lifetime, 600], + "dns-lookup" => [\$opts_dnslookup, "true"], }, ); @@ -534,14 +544,15 @@ 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'); # client is not registered, start registration process } else { + $REGISTRATION_IN_PROGRESS = 1; + # clear all other triggered events and wait till registration was successful $kernel->delay('trigger_new_key'); @@ -550,21 +561,20 @@ sub register_at_gosa_si_server { my $events = join( ",", keys %{$event_hash} ); while(1) { - $try_to_register++; - - # after one complete round through all server, stop trying to register - if( $try_to_register > @servers ) { last; } + $REGISTRATION_TRIES++; # fetch first gosa-si-server from @servers # append shifted gosa-si-server at the end of @servers, so looking for servers never stop if # a registration never occured my $server = shift(@servers); - push( @servers, $server ); + push(@servers, $server); + ($server_ip = $server) =~ s/:.*$//; + $server_address = $server; # Check if our ip is resolvable - if not: don't try to register if(!(defined($server) && $server =~ m/^[0-9\.]*?:.*$/)) { &main::daemon_log("ERROR: Server with address '".defined($server)?$server:""."' is invalid!", 1); - if (length(@servers) == 1) { + if (scalar(@servers) == 1) { &main::daemon_log("ERROR: No valid servers found!", 1); exit(1); } @@ -608,9 +618,9 @@ sub register_at_gosa_si_server { my $res = &send_msg_hash_to_target($register_hash, $server, $default_server_key); # if delivery of registration msg succeed - if($res eq "0") { + if(defined($res) and $res eq "0") { # reset try_to_register - $try_to_register = 0; + $REGISTRATION_TRIES = 0; # Set fixed client address and mac address $client_ip= &get_local_ip_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/)); @@ -628,7 +638,7 @@ sub register_at_gosa_si_server { } # end of while # one circle through all servers finished and no registration succeed - if ( $try_to_register >= @servers ) { + if ( $REGISTRATION_TRIES >= (scalar(@servers)) ) { &write_to_file("gosa-si-no-server-available", $fai_logpath); $kernel->delay_set('register_at_gosa_si_server', $delay_set_time); @@ -1024,9 +1034,17 @@ sub server_input { # if client is alread in a registration process, that means not registered, do nothing # if not, cause re-registration - if (not $REGISTERED) { + if ($REGISTRATION_IN_PROGRESS) { &daemon_log("WARNING: gosa-si-client is already in a registration process so ignore this message", 3); } else { + if ($FAILED_CRYPTO > $max_failed_crypto_messages) { + # Force usage of a new server + daemon_log("Failed to decrypt a total of $max_failed_crypto_messages messages from the server. Trying to switch to another one", 3); + $REGISTRATION_TRIES = $max_failed_crypto_messages; + my $server = shift(@servers); + push(@servers, $server); + } + $FAILED_CRYPTO++; $REGISTERED = 0; $kernel->post('client_session', 'register_at_gosa_si_server'); } @@ -1038,6 +1056,9 @@ sub server_input { ###################### # process incoming msg if( $error == 0 ) { + # Reset failed crypto messages state + $FAILED_CRYPTO = 0; + my $header = @{$msg_hash->{header}}[0]; my $source = @{$msg_hash->{source}}[0]; @@ -1067,6 +1088,7 @@ sub server_input { if( $answer =~ "
registered
") { # set registered flag to true to stop sending further registered msgs $REGISTERED = 1; + $REGISTRATION_IN_PROGRESS = 0; } else { $answer =~ /
(\S+)<\/header>/; @@ -1087,6 +1109,91 @@ sub server_input { return; } +sub find_servers { + # add gosa-si-server address from config file at first position of server list + my $server_check_cfg = Config::IniFiles->new( -file => $cfg_file ); + + # Parse servers string + my @conf_servers = split(',', $servers_string); + + # Now search for fallback servers in the configuration + foreach my $cur_server (@conf_servers) { + # Remove spaces from the IP + $cur_server =~ s/\s//g; + + my $ip = $cur_server; + if(not $cur_server =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/) { + my $ip_address = inet_ntoa(scalar gethostbyname($ip)); + if(defined($ip_address) && $ip_address =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/) { + # Write ip address to $server_ip variable + $ip = $ip_address; + } + } + + my $server_addr = sprintf("%s:%s", $ip, $server_port); + if (not grep { $_ eq $server_addr } @servers) { + push(@servers, $server_addr); + } + } + + my $servers_string = join(", ", @servers); + daemon_log("INFO: found servers in configuration file: $servers_string", 1); + + # Last but not least search for fallback servers in the DNS + if (defined($opts_dnslookup) and $opts_dnslookup eq "true") { + my @tmp_servers; + if ( !$server_domain) { + # Try our DNS Searchlist + my @domain_list = &get_dns_domains(); + my $tmp_domains; + my $error_string; + for my $domain (@domain_list) { + chomp($domain); + ($tmp_domains, $error_string) = &get_server_addresses($domain); + if(@$tmp_domains) { + for my $tmp_server(@$tmp_domains) { + push @tmp_servers, $tmp_server; + } + } + } + + if (0 == @tmp_servers) { + daemon_log("INFO: No servers found in DNS.", 1); + } + else { + my $servers_string = join(", ", @tmp_servers); + daemon_log("INFO: found servers in DNS: $servers_string", 1); + } + } else { + @tmp_servers = &get_server_addresses($server_domain); + if( 0 == @tmp_servers ) { + daemon_log("INFO: No servers found in DNS for domain '$server_domain'",1); + } + } + + if ( 0 != @tmp_servers ) { + foreach my $server_addr (@tmp_servers) { + if (not grep { $_ eq $server_addr } @servers) { + push(@servers, $server_addr); + } + } + } + } + + if (0 == scalar(@servers)) { + daemon_log("ERROR: No servers found in the configuration or DNS.", 1); + exit(1); + } + + # Define first server as server_ip + $server_ip = $servers[0]; + + # prepare variables + if( inet_aton($server_ip) ){ $server_ip = inet_ntoa(inet_aton($server_ip)); } + if (defined $server_ip && defined $server_port) { + $server_address = $server_ip.":".$server_port; + } +} #==== MAIN = main ============================================================== # parse commandline options @@ -1102,7 +1209,6 @@ GetOptions("h|help" => \&usage, &read_configfile($cfg_file, %cfg_defaults); &check_pid; - # forward error messages to logfile if ( ! $foreground ) { open( STDIN, '+>/dev/null' ); @@ -1196,64 +1302,11 @@ POE::Component::Server::TCP->new( ); daemon_log("INFO: start socket for incoming xml messages at port '$client_port' ", 1); - -# prepare variables -if( inet_aton($server_ip) ){ $server_ip = inet_ntoa(inet_aton($server_ip)); } -if (defined $server_ip && defined $server_port) { - $server_address = $server_ip.":".$server_port; -} $xml = new XML::Simple(); $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 = (defined($server_check_cfg))?$server_check_cfg->val( "server", "ip"):undef; -if( defined $server_check ) { - unshift(@servers, $server_address); - my $servers_string = join(", ", @servers); - daemon_log("INFO: found servers in configuration file: $servers_string", 1); -} else { - my @tmp_servers; - if ( !$server_domain) { - # Try our DNS Searchlist - my @domain_list = &get_dns_domains(); - my $tmp_domains; - my $error_string; - for my $domain (@domain_list) { - chomp($domain); - ($tmp_domains, $error_string) = &get_server_addresses($domain); - if(@$tmp_domains) { - for my $tmp_server(@$tmp_domains) { - push @tmp_servers, $tmp_server; - } - } - } - if (0 == @tmp_servers) { - my $log_string = "no gosa-si-server found!"; - $log_string .= "\n\tdetermined domains out of /etc/resolv.conf: ".join(", ", @domain_list) if (@domain_list); - $log_string .= "\n\tdetermined server addresses in domains: ".join(", ",@$tmp_domains) if (defined($tmp_domains)); - daemon_log("ERROR: $log_string", 1) if (defined($log_string)); - daemon_log("ERROR: $error_string", 1) if (defined($error_string)); - daemon_log("ERROR: please specify a gosa-si-server address or a domain in config file", 1); - kill 2, $$; - } - } else { - @tmp_servers = &get_server_addresses($server_domain); - if( 0 == @tmp_servers ) { - daemon_log("ERROR: no gosa-si-server found in DNS for domain '$server_domain'",1); - daemon_log("ERROR: please specify a gosa-si-server address or a domain in config file", 1); - kill 2, $$; - } - } - - foreach my $server (@tmp_servers) { - unshift(@servers, $server); - } - my $servers_string = join(", ", @servers); - daemon_log("INFO: found servers in DNS: $servers_string", 1); -} - +# Find servers from config and DNS +&find_servers; # open fifo for non-gosa-si-client-msgs to gosa-si-server POSIX::mkfifo("$gosa_si_client_fifo", "0600"); -- 2.30.2