Code

Save outgoing address when registration was sucessfull.
[gosa.git] / gosa-si / gosa-si-client
index 1f0ae9b9ba4115943da54a9f2c4dc06a8e45f668..3d627c9b070a20ee51c733819ab2fe9c56be833b 100755 (executable)
@@ -34,20 +34,13 @@ use GOSA::GosaSupportDaemon;
 use Digest::MD5  qw(md5_hex md5 md5_base64);
 use MIME::Base64;
 use XML::Simple;
-
-
-#use Fcntl;
-#use Sys::Syslog qw( :DEFAULT setlogsock);
-#use File::Spec;
-#use Cwd;
-
-
+use Net::DNS;
 
 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);
-my ($server_ip, $server_port, $server_key, $server_timeout, $server_domain);
+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;
 my $default_server_key;
@@ -72,7 +65,7 @@ our $REGISTERED_FLAG = 1;
 "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:00"],
+     "client_mac_address" => [\$client_mac_address, "00:00:00:00:00:00"],
      "ldap" => [\$ldap_enabled, 1],
      "ldap_config" => [\$ldap_config, "/etc/ldap/ldap.conf"],
      "pam_config" => [\$pam_config, "/etc/pam_ldap.conf"],
@@ -84,6 +77,7 @@ our $REGISTERED_FLAG = 1;
     "server_key" => [\$server_key, ""],
     "server_timeout" => [\$server_timeout, 10],
     "server_domain" => [\$server_domain, ""],
+    "server_key_lifetime" => [\$server_key_lifetime, 600], 
     },
 
 );
@@ -217,7 +211,7 @@ sub daemon_log {
                 $hours = $hours < 10 ? $hours = "0".$hours : $hours;
                 $minutes = $minutes < 10 ? $minutes = "0".$minutes : $minutes;
                 $seconds = $seconds < 10 ? $seconds = "0".$seconds : $seconds;
-                my @monthnames = ("Jan", "Feb", "Mar", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
+                my @monthnames = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
                 $month = $monthnames[$month];
                 $monthday = $monthday < 10 ? $monthday = "0".$monthday : $monthday;
                 $year+=1900;
@@ -289,7 +283,7 @@ sub get_mac {
                        if(defined($server_ip)) {
                                $result = &get_local_mac_for_remote_ip($server_ip);
                        } 
-                       elsif ($client_mac_address && length($client_mac_address) > 0){
+                       elsif ($client_mac_address && length($client_mac_address) > 0 && !($client_mac_address eq "00:00:00:00:00:00")){
                                $result = &client_mac_address;
                        } 
                        else {
@@ -299,7 +293,7 @@ sub get_mac {
                        my $SIOCGIFHWADDR= 0x8927;     # man 2 ioctl_list
 
                        # A configured MAC Address should always override a guessed value
-                       if ($client_mac_address and length($client_mac_address) > 0) {
+                       if ($client_mac_address and length($client_mac_address) > 0 and not($client_mac_address eq "00:00:00:00:00:00")) {
                                $result= $client_mac_address;
                        }
                        else {
@@ -386,40 +380,83 @@ sub get_ip {
 #                matches (defaultroute last).
 #===============================================================================
 sub get_local_mac_for_remote_ip {
-    my $ifreq= shift;
-    my $result= "00:00:00:00:00:00";
-    my $PROC_NET_ROUTE= ('/proc/net/route');
-
-    open(PROC_NET_ROUTE, "<$PROC_NET_ROUTE")
-        or die "Could not open $PROC_NET_ROUTE";
-
-    my @ifs = <PROC_NET_ROUTE>;
-
-    close(PROC_NET_ROUTE);
-
-    # Eat header line
-    shift @ifs;
-    chomp @ifs;
-    foreach my $line(@ifs) {
-        my ($Iface,$Destination,$Gateway,$Flags,$RefCnt,$Use,$Metric,$Mask,$MTU,$Window,$IRTT)=split(/\s/, $line);
-        my $destination;
-        my $mask;
-        my ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Destination);
-        $destination= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
-        ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Mask);
-        $mask= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
-        if(new NetAddr::IP($server_ip)->within(new NetAddr::IP($destination, $mask))) {
-            # destination matches route, save mac and exit
-            $result= &get_mac($Iface);
-            last;
-        }
-    }
+       my $server_ip= shift;
+       my $result= "00:00:00:00:00:00";
+
+       if($server_ip =~ /^(\d\d?\d?\.){3}\d\d?\d?$/) {
+               my $PROC_NET_ROUTE= ('/proc/net/route');
+
+               open(PROC_NET_ROUTE, "<$PROC_NET_ROUTE")
+                       or die "Could not open $PROC_NET_ROUTE";
+
+               my @ifs = <PROC_NET_ROUTE>;
+
+               close(PROC_NET_ROUTE);
+
+               # Eat header line
+               shift @ifs;
+               chomp @ifs;
+               foreach my $line(@ifs) {
+                       my ($Iface,$Destination,$Gateway,$Flags,$RefCnt,$Use,$Metric,$Mask,$MTU,$Window,$IRTT)=split(/\s/, $line);
+                       my $destination;
+                       my $mask;
+                       my ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Destination);
+                       $destination= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
+                       ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Mask);
+                       $mask= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
+                       if(new NetAddr::IP($server_ip)->within(new NetAddr::IP($destination, $mask))) {
+                               # destination matches route, save mac and exit
+                               $result= &get_mac($Iface);
+                               last;
+                       }
+               }
+       } else {
+               daemon_log("get_local_mac_for_remote_ip was called with a non-ip parameter: $server_ip", 1);
+       }
+       return $result;
+}
 
+sub get_local_ip_for_remote_ip {
+       my $server_ip= shift;
+       my $result="0.0.0.0";
 
-    return $result;
+       if($server_ip =~ /^(\d\d?\d?\.){3}\d\d?\d?$/) {
+               if($server_ip eq "127.0.0.1") {
+                       $result="127.0.0.1";
+               } else {
+                       my $PROC_NET_ROUTE= ('/proc/net/route');
+
+                       open(PROC_NET_ROUTE, "<$PROC_NET_ROUTE")
+                               or die "Could not open $PROC_NET_ROUTE";
+
+                       my @ifs = <PROC_NET_ROUTE>;
+
+                       close(PROC_NET_ROUTE);
+
+                       # Eat header line
+                       shift @ifs;
+                       chomp @ifs;
+                       foreach my $line(@ifs) {
+                               my ($Iface,$Destination,$Gateway,$Flags,$RefCnt,$Use,$Metric,$Mask,$MTU,$Window,$IRTT)=split(/\s/, $line);
+                               my $destination;
+                               my $mask;
+                               my ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Destination);
+                               $destination= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
+                               ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Mask);
+                               $mask= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
+                               if(new NetAddr::IP($server_ip)->within(new NetAddr::IP($destination, $mask))) {
+                                       # destination matches route, save mac and exit
+                                       $result= &get_ip($Iface);
+                                       last;
+                               }
+                       }
+               }
+       } else {
+               daemon_log("get_local_ip_for_remote_ip was called with a non-ip parameter: $server_ip", 1);
+       }
+       return $result;
 }
 
-
 sub new_ldap_config {
     my ($msg_hash) = @_ ;
     my $element;
@@ -583,33 +620,62 @@ sub create_passwd {
 sub get_server_addresses {
     my $domain= shift;
     my @result;
-    my $dig_cmd= 'dig +nocomments srv _gosad._tcp.'.$domain;
-
-    my $output= `$dig_cmd 2>&1`;
-    open (PIPE, "$dig_cmd 2>&1 |");
-    while(<PIPE>) {
-        chomp $_;
-        # If it's not a comment
-        if($_ =~ m/^[^;]/) {
-            my @matches= split /\s+/;
-
-            # Push hostname with port
-            if($matches[3] eq 'SRV') {
-                push @result, $matches[7].':'.$matches[6];
-            } elsif ($matches[3] eq 'A') {
-                my $i=0;
-
-                # Substitute the hostname with the ip address of the matching A record
-                foreach my $host (@result) {
-                    if ((split /\:/, $host)[0] eq $matches[0]) {
-                        $result[$i]= $matches[4].':'.(split /\:/, $host)[1];
-                    }
-                    $i++;
+    my $error = 0;
+    my $res   = Net::DNS::Resolver->new;
+    my $query = $res->send("_gosad._tcp.".$domain, "SRV");
+    my @hits;
+
+    if ($query) {
+        foreach my $rr ($query->answer) {
+            push(@hits, $rr->target.":".$rr->port);
+        }
+    }
+    else {
+        #warn "query failed: ", $res->errorstring, "\n";
+        $error++;
+    }
+
+    if( $error == 0 ) {
+        foreach my $hit (@hits) {
+            my ($hit_name, $hit_port) = split(/:/, $hit);
+
+            my $address_query = $res->send($hit_name);
+            if( 1 == length($address_query->answer) ) {
+                foreach my $rr ($address_query->answer) {
+                    push(@result, $rr->address.":".$hit_port);
                 }
             }
         }
     }
-    close(PIPE);
+
+#    my $dig_cmd= 'dig +nocomments srv _gosad._tcp.'.$domain;
+#
+#    my $output= `$dig_cmd 2>&1`;
+#    open (PIPE, "$dig_cmd 2>&1 |");
+#    while(<PIPE>) {
+#        chomp $_;
+#        # If it's not a comment
+#        if($_ =~ m/^[^;]/) {
+#            my @matches= split /\s+/;
+#
+#            # Push hostname with port
+#            if($matches[3] eq 'SRV') {
+#                push @result, $matches[7].':'.$matches[6];
+#            } elsif ($matches[3] eq 'A') {
+#                my $i=0;
+#
+#                # Substitute the hostname with the ip address of the matching A record
+#                foreach my $host (@result) {
+#                    if ((split /\:/, $host)[0] eq $matches[0]) {
+#                        $result[$i]= $matches[4].':'.(split /\:/, $host)[1];
+#                    }
+#                    $i++;
+#                }
+#            }
+#        }
+#    }
+#    close(PIPE);
     return @result;
 }
 
@@ -792,18 +858,27 @@ sub register_at_gosa_si_server {
             }
 
             # create registration msg
-            my $register_hash = &create_xml_hash("here_i_am", $client_address, $server);
+            my $register_hash = &create_xml_hash("here_i_am", &get_local_ip_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/)).":".$client_port, $server);
             &add_content2xml_hash($register_hash, "new_passwd", $server_key);
-            &add_content2xml_hash($register_hash, "mac_address", $client_mac_address);
+                       &add_content2xml_hash($register_hash, "mac_address", &get_local_mac_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/)));
             &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);
-            last;
+                       if($res == 0) {
+                               # Set fixed client address
+                               $client_ip= &get_local_ip_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/));
+                               $client_address= "$client_ip:$client_port";
+                               last;
+                       } else {
+                               next;
+                       }
         }
         daemon_log("waiting for msg 'register_at_gosa_si_server'",1);
-        $kernel->delay_set('register_at_gosa_si_server',2);
+        $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);
     }
     return;
 }
@@ -889,9 +964,26 @@ sub import_events {
     }
 }
 
+sub trigger_new_key {
+    my ($kernel) = $_[KERNEL] ;   
+
+    my $msg = "<xml><header>new_key</header><source>$client_address</source><target>$client_address</target></xml>";
+    &send_msg_to_target($msg, $client_address, $server_key, 'new_key');
+
+    $kernel->delay_set('trigger_new_key', $server_key_lifetime);
+
+}
+
+
+sub _start {
+    my ($kernel) = $_[KERNEL];
+    $kernel->alias_set('client_session');
+    $kernel->yield('register_at_gosa_si_server');
+}
+
 
 sub server_input {
-    my ($heap,$input,$wheel) = @_[HEAP, ARG0, ARG1];
+    my ($kernel, $heap, $input, $wheel) = @_[KERNEL, HEAP, ARG0, ARG1];
     my $error = 0;
     my $answer;
     
@@ -920,11 +1012,20 @@ sub server_input {
     ########
     # answer
     if( $answer ) {
+        # preprocessing
         if( $answer =~ "<header>registered</header>") {
+            # set registered flag to true to stop sending further registered msgs
             $REGISTERED_FLAG = 0;
         } 
         else {
-        &send_msg_to_address($answer, $server_address, $server_key);
+            &send_msg_to_target($answer, $server_address, $server_key);
+        }
+        # postprocessing
+        if( $answer =~ "<header>new_key</header>") {
+            # set new key to global variable
+            $answer =~ /<new_key>(\S*?)<\/new_key>/;
+            my $new_key = $1;
+            $server_key = $new_key;
         }
     }
 
@@ -1035,8 +1136,9 @@ daemon_log("found servers in configuration file and via DNS: $servers_string", 5
 
 POE::Session->create(
        inline_states => {
-               _start => \&register_at_gosa_si_server ,
+               _start => \&_start, 
         register_at_gosa_si_server => \&register_at_gosa_si_server,
+        trigger_new_key => \&trigger_new_key,
        }
 );