Code

Updated setup, sambaMachineAccountRDN closes #621
[gosa.git] / gosa-si / gosa-si-client
index fa2afbdbbdf12f703b801f5ecfac11ee93ca7442..94b7c66f1cdad922a9a26c0df970debf0206259d 100755 (executable)
@@ -18,6 +18,8 @@
 #     REVISION:  ---
 #===============================================================================
 
+my $client_version = '$HeadURL$:$Rev$';
+
 use strict;
 use warnings;
 use Getopt::Long;
@@ -40,7 +42,6 @@ use File::Spec;
 # Workaround: need pure perl to make it work with UTF-8 :-(
 $XML::Simple::PREFERRED_PARSER= "XML::SAX::PurePerl";
 
-my $client_version = '$HeadURL$:$Rev$';
 my $client_headURL;
 my $client_revision;
 my $client_status;
@@ -83,18 +84,15 @@ $gosa_si_client_fifo = "/var/run/gosa-si-client.socket";
 my $delay_set_time = 10;
 our $prg= basename($0);
 
-# all x seconds the client reports logged_in users to gosa-si-server
+# all n seconds the client reports logged_in users to gosa-si-server
 my $trigger_logged_in_users_report_delay = 600;
 
+# all n seconds the client reports messages seen by user
+my $trigger_seen_messages_delay = 30;
+
 # directory where all log files from installation are stored
 my $fai_log_dir = "/var/log/fai"; 
 
-# dak variables
-our $dak_base_directory;
-our $dak_signing_keys_directory;
-our $dak_queue_directory;
-our $dak_user;
-
 %cfg_defaults = (
 "general" =>
     {"log-file"           => [\$log_file, "/var/run/".$prg.".log"],
@@ -112,10 +110,6 @@ our $dak_user;
      "nss-config"         => [\$nss_config, "/etc/libnss-ldap.conf"],
      "fai-logpath"        => [\$fai_logpath, "/var/log/fai/fai.log"],
      "force-hostname"    => [\$client_force_hostname, "false"],
-     "dak-base" => [\$dak_base_directory, "/srv/archive"],
-     "dak-keyring" => [\$dak_signing_keys_directory, "/srv/archive/keyrings"],
-     "dak-queue" => [\$dak_queue_directory, "/srv/archive/queue"],
-     "dak-user" => [\$dak_user, "deb-dak"],
     },
 "server" => {
     "ip"          => [\$server_ip, "127.0.0.1"],
@@ -130,6 +124,19 @@ our $dak_user;
 
 #=== FUNCTIONS = functions =====================================================
 
+sub usage {
+    print STDERR << "EOF" ;
+usage: $prg [-hvf] [-c config]
+
+           -h        : this (help) message
+           -c <file> : config file
+           -f        : foreground, process will not be forked to background
+           -v        : be verbose (multiple to increase verbosity)
+EOF
+    print "\n" ;
+}
+
 #===  FUNCTION  ================================================================
 #         NAME: check_cmdline_param
 #   PARAMETERS: 
@@ -155,33 +162,6 @@ sub check_cmdline_param () {
 }
 
 
-#===  FUNCTION  ================================================================
-#         NAME:  read_configfile
-#   PARAMETERS:  cfg_file - string - 
-#      RETURNS:  
-#  DESCRIPTION: 
-#===============================================================================
-sub read_configfile {
-    my ($cfg_file, %cfg_defaults) = @_ ;
-    my $cfg;
-    if( defined( $cfg_file) && ( (-s $cfg_file) > 0 )) {
-        if( -r $cfg_file ) {
-            $cfg = Config::IniFiles->new( -file => $cfg_file );
-        } else {
-            print STDERR "Couldn't read config file!";
-        }
-    } else {
-        $cfg = Config::IniFiles->new() ;
-    }
-    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 ] );
-        }
-    }
-}
-
-
 #===  FUNCTION  ================================================================
 #         NAME: check_pid
 #   PARAMETERS:
@@ -255,7 +235,6 @@ sub daemon_log {
     if(not defined $level) { $level = 1 }
     if(defined $log_file){
         open(LOG_HANDLE, ">>$log_file");
-        chmod 0600, $log_file;
         if(not defined open( LOG_HANDLE, ">>$log_file" )) {
             print STDERR "cannot open $log_file: $!";
             return 
@@ -375,49 +354,6 @@ sub get_local_mac_for_remote_ip {
        return $result;
 }
 
-sub get_local_ip_for_remote_ip {
-       my $server_ip= shift;
-       my $result="0.0.0.0";
-
-       if($server_ip =~ /^(\d\d?\d?\.){3}\d\d?\d?$/) {
-        # client should always have a 'valid' ip-address, which is available from other hosts too,
-        # 127.0.0.1 says nothing to foreign host
-               #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 generate_hw_digest {
        my $hw_data;
@@ -494,6 +430,10 @@ sub send_msg_to_target {
     if( $msg_header ) { $msg_header = "'$msg_header'-"; }
     else { $msg_header = ""; }
 
+    # Memorize own source address
+    $msg =~ /<source>(\S+)<\/source>/;
+    my $own_source_address = $1;
+
     # encrypt xml msg
     my $crypted_msg = &encrypt_msg($msg, $encrypt_key);
 
@@ -512,7 +452,7 @@ sub send_msg_to_target {
     
     # send xml msg
     if( $error == 0 ) {
-        print $socket $crypted_msg."\n";
+        print $socket $crypted_msg.";$own_source_address\n";
         daemon_log("INFO: send ".$msg_header."msg to $address", 5);
         daemon_log("DEBUG: message:\n$msg", 9);
     }
@@ -619,14 +559,15 @@ sub register_at_gosa_si_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)) {
-                       if( defined($client_force_hostname) && $client_force_hostname eq "true") {
-                               $dnsname = `hostname`;
-                       } else {
-                               &write_to_file("goto-error-dns:$ip", $fai_logpath);
-                               exit(1);
-                       }
-               }
+            if(!defined($dnsname)) {
+                if( defined($client_force_hostname) && $client_force_hostname eq "true") {
+                    $dnsname = `hostname`;
+                } else {
+                    &write_to_file("goto-error-dns:$ip", $fai_logpath);
+                    &main::daemon_log("ERROR: ip is not resolvable, no registration possible. Write 'goto-error-dns:$ip' to $fai_logpath", 1);
+                    exit(1);
+                }
+            }
 
                # create registration msg
                        my $local_ip = &get_local_ip_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/));
@@ -840,6 +781,68 @@ sub trigger_logged_in_users_report {
 }
 
 
+sub trigger_seen_messages {
+    my ($kernel) = $_[KERNEL] ;
+
+    # Select all files under /tmp with prefix 'goto_notify'
+    my $goto_dir = "/tmp";
+    opendir(DIR, $goto_dir);
+    my @goto_files = grep { /^goto_notify_/ && -f "$goto_dir/$_" } readdir(DIR);
+    closedir DIR;
+
+    # Check if file has 'seen' tag
+    foreach my $goto_file (@goto_files) {
+        open(FILE, "$goto_dir/$goto_file");
+        my @lines = <FILE>;
+        close FILE;
+
+        my $source;
+        my $target;
+        my $usr;
+        my $subject;
+        my $message;
+        my $seen = 0;
+        chomp(@lines);
+        foreach my $line (@lines) {
+            if ($line =~ /^source:([\S\s]*)$/) {
+                $source = $1
+            }
+            if ($line =~ /^target:([\S\s]*)$/) {
+                $target = $1;
+            }
+            if ($line =~ /^usr:([\S\s]*)$/) {
+                $usr = $1;
+            }
+            if ($line =~ /^subject:([\S\s]*)$/) {
+                $subject = $1;
+            }
+            if ($line =~ /^message:([\S\s]*)$/) {
+                $message = $1;
+            }
+            if ($line =~ /^seen$/) {
+                $seen++;       
+            }
+        }
+
+        # Send 'confirm_usr_msg' back to msg-hosting server
+        if ($seen) {
+            my %data = ('usr'=>$usr, 'subject'=>$subject, 'message'=>$message);
+            my $confirm_msg = &build_msg("confirm_usr_msg", $target, $source, \%data);
+            my $send_error = &send_msg_to_target($confirm_msg, $server_address, $server_key);
+
+            # Delete file
+            if (not $send_error) {
+                system("rm $goto_dir/$goto_file");
+            }
+        }
+    }
+
+    $kernel->delay_set('trigger_seen_messages', $trigger_seen_messages_delay);
+
+    return;
+}
+
+
 sub generic_file_error {
     my ( $heap, $operation, $errno, $error_string, $wheel_id ) =
       @_[ HEAP, ARG0, ARG1, ARG2, ARG3 ];
@@ -873,6 +876,8 @@ sub fifo_got_record {
 
     my $clmsg_hash = &create_xml_hash("CLMSG_$header", $client_address, $server_address, $content);
     &add_content2xml_hash($clmsg_hash, "macaddress", $client_mac_address);
+    my $utc_ts = &main::get_utc_time(); 
+    &add_content2xml_hash($clmsg_hash, "timestamp", $utc_ts);
     my $clmsg = &create_xml_string($clmsg_hash);
     &send_msg_to_target($clmsg, $server_address, $server_key, "CLMSG_$header");
 
@@ -889,30 +894,40 @@ 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; 
+       # Directory for log files after a softupdate
+    my $log_dir = File::Spec->catdir($fai_log_dir, "localhost/last");
+
+    if (not -d $log_dir) { 
+               # Directory for log files after a new installation
+               $log_dir = "/tmp/fai";
+               if (not -d $log_dir) {
+                               daemon_log("ERROR: cannot open directory $log_dir", 1);
+                               return; 
+               }
     }
 
+    opendir($FAI_DIR, "$log_dir");
     my @log_files = readdir($FAI_DIR);
     closedir($FAI_DIR);   
-    my @log_list;
 
+    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);
+        $log_file = File::Spec->catfile( $log_dir, $log_file );
+
+        if (not -f $log_file) {
+            daemon_log("ERROR: cannot read $log_file", 1);
             next;
         }
-        my @lines = <$FILE>;
+
+        open(FILE, "<$log_file");
+        my @lines = <FILE> ;
+        close (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); 
@@ -958,6 +973,7 @@ sub _start {
         $heap->{watchers}->{ $watcher->ID } = $watcher;
     }
     $kernel->yield('trigger_logged_in_users_report'); 
+    $kernel->yield('trigger_seen_messages');
 }
 
 
@@ -1105,6 +1121,13 @@ if ($client_headURL =~ /\/tag\// ||
     $client_status = "developmental" ;
 }
 
+# Prepare log file
+my $root_uid = getpwnam('root');
+my $adm_gid = getgrnam('adm');
+chmod(0640, $log_file);
+chown($root_uid, $adm_gid, $log_file);
+
+
 daemon_log(" ", 1);
 daemon_log("$prg started!", 1);
 daemon_log("INFO: status: $client_status", 1);
@@ -1123,7 +1146,11 @@ daemon_log("INFO: gosa-si-client mac address detected: $client_mac_address", 1);
 
 # import events
 my ($error, $result, $tmp_hash) = &import_events($event_dir);
-$event_hash = $tmp_hash;
+while (my ($module, $mod_event_hash) = each %$tmp_hash) {
+    while (my ($event_name, $nothing) = each %$mod_event_hash) {
+        $event_hash->{$event_name} = $module;
+    }
+}
 
 foreach my $log_line (@$result) {
     if ($log_line =~ / succeed: /) {
@@ -1163,21 +1190,29 @@ my $server_check = (defined($server_check_cfg))?$server_check_cfg->val( "server"
 if( defined $server_check ) {
        unshift(@servers, $server_address);
        my $servers_string = join(", ", @servers);
-       daemon_log("INFO: found servers in configuration file: $servers_string", 5);
+       daemon_log("INFO: found servers in configuration file: $servers_string", 1);
 } else {
        my @tmp_servers;
        if ( !$server_domain) {
                # Try our DNS Searchlist
-               for my $domain(get_dns_domains()) {
+               my @domain_list = &get_dns_domains();
+               my $tmp_domains;
+               my $error_string;
+               for my $domain (@domain_list) {
                        chomp($domain);
-                       my @tmp_domains= &get_server_addresses($domain);
-                       if(@tmp_domains) {
-                               for my $tmp_server(@tmp_domains) {
+                       ($tmp_domains, $error_string) = &get_server_addresses($domain);
+                       if(@$tmp_domains) {
+                               for my $tmp_server(@$tmp_domains) {
                                        push @tmp_servers, $tmp_server;
                                }
                        }
                }
-               if(@tmp_servers && length(@tmp_servers)==0) {
+               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, $$;
                }
@@ -1190,11 +1225,11 @@ if( defined $server_check ) {
                } 
        }
 
-    foreach my $server (@tmp_servers) { 
-        unshift(@servers, $server); 
-    }
-    my $servers_string = join(", ", @servers);
-    daemon_log("INFO: found servers in DNS: $servers_string", 5);
+       foreach my $server (@tmp_servers) { 
+               unshift(@servers, $server); 
+       }
+       my $servers_string = join(", ", @servers);
+       daemon_log("INFO: found servers in DNS: $servers_string", 1);
 }
 
 
@@ -1212,6 +1247,7 @@ POE::Session->create(
         # trigger periodical tasks
         trigger_new_key => \&trigger_new_key,
         trigger_logged_in_users_report => \&trigger_logged_in_users_report,
+        trigger_seen_messages => \&trigger_seen_messages,
         
         # handle records from each defined file differently
         fifo_record => \&fifo_got_record,