Code

Apply patch for #6281 from LHM
[gosa.git] / trunk / gosa-si / gosa-si-server
index 3864ad237190ee8cdae34703979ba68da9d3d4fc..c79bfdd1c9297b919b8121f3477987557619fb61 100755 (executable)
@@ -28,7 +28,7 @@ use Getopt::Long;
 use Config::IniFiles;
 use POSIX;
 
-use Fcntl;
+use Fcntl qw/:flock/;
 use IO::Socket::INET;
 use IO::Handle;
 use IO::Select;
@@ -212,6 +212,8 @@ our $client_fai_log_dir = "/var/log/fai";
 my @msgs_to_decrypt = qw();
 my $max_children = 2;
 
+# Allow 50 POE Childs
+sub MAX_CONCURRENT_TASKS () { 50 }
 
 # loop delay for job queue to look for opsi jobs
 my $job_queue_opsi_delay = 10;
@@ -324,11 +326,17 @@ sub daemon_log {
     if(not defined $msg) { return }
     if(not defined $level) { $level = 1 }
     if(defined $log_file){
-        open(LOG_HANDLE, ">>$log_file");
-        if(not defined open( LOG_HANDLE, ">>$log_file" )) {
+        my $open_log_fh = sysopen(LOG_HANDLE, $log_file, O_WRONLY | O_CREAT | O_APPEND , 0440);
+        if(not $open_log_fh) {
             print STDERR "cannot open $log_file: $!";
-            return 
+            return;
+        }
+        # check owner and group of log_file and update settings if necessary
+        my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat($log_file);
+        if((not $uid eq $root_uid) || (not $gid eq $adm_gid)) {
+            chown($root_uid, $adm_gid, $log_file);
         }
+
         chomp($msg);
         #$msg =~s/\n//g;   # no newlines are allowed in log messages, this is important for later log parsing
         if($level <= $verbose){
@@ -344,7 +352,10 @@ sub daemon_log {
             my $name = $prg;
 
             my $log_msg = "$month $monthday $hours:$minutes:$seconds $name $msg\n";
+                       flock(LOG_HANDLE, LOCK_EX);
+                       seek(LOG_HANDLE, 0, 2);
             print LOG_HANDLE $log_msg;
+                       flock(LOG_HANDLE, LOCK_UN);
             if( $foreground ) { 
                 print STDERR $log_msg;
             }
@@ -499,27 +510,42 @@ sub password_check {
 
 }
 
+sub clean_shutdown
+{
+    unlink($pid_file) if (-w $pid_file);
+    unlink($packages_list_under_construction) if (-w $packages_list_under_construction);
+}
 
-#===  FUNCTION  ================================================================
-#         NAME:  sig_int_handler
-#   PARAMETERS:  signal - string - signal arose from system
-#      RETURNS:  nothing
-#  DESCRIPTION:  handels tasks to be done befor signal becomes active
-#===============================================================================
-sub sig_int_handler {
+sub sig_int_or_term_handler
+{
     my ($signal) = @_;
+    daemon_log("Got SIG${signal} - shutting down gosa-si-server", 1);
+    clean_shutdown();
+    POE::Kernel->signal('gosa-si_server_session', 'KILL');
+    POE::Kernel->signal('TCP_SERVER', 'KILL');
+    return 1;
+}
 
-#      if (defined($ldap_handle)) {
-#              $ldap_handle->disconnect;
-#      }
-    # TODO alle verbliebenden ldap verbindungen aus allen heaps beenden
-    
+sub sig_warn_handler
+{
+    my @loc = caller(0);
+    daemon_log( "SIGWARN line " . $loc[2] . ": " . $_[0], 1 );
+    return 1;
+}
 
-    daemon_log("shutting down gosa-si-server", 1);
-    system("kill `ps -C gosa-si-server -o pid=`");
+sub sig_die_handler
+{
+    my @loc = caller(0);
+    daemon_log( "SIGDIE line " . $loc[2] . ": " . $_[0], 1 );
+    clean_shutdown();
+    return 1;
 }
-$SIG{INT} = \&sig_int_handler;
 
+$SIG{'INT'} = \&sig_int_or_term_handler;
+$SIG{'TERM'} = \&sig_int_or_term_handler;
+$SIG{'__WARN__'} = \&sig_warn_handler;
+$SIG{'__DIE__'} = \&sig_die_handler;
+$SIG{'USR1'} = 'IGNORE';
 
 sub check_key_and_xml_validity {
     my ($crypted_msg, $module_key, $session_id) = @_;
@@ -599,7 +625,7 @@ sub check_outgoing_xml_validity {
         }
 
                                # Check if source contains hostname instead of ip address
-                               if(not $source =~ /^[a-z0-9\.]+:\d+$/i) {
+                               if($source =~ /^[a-z][a-z0-9\.]+:\d+$/i) {
                                                my ($hostname,$port) = split(/:/, $source);
                                                my $ip_address = inet_ntoa(scalar gethostbyname($hostname));
                                                if(defined($ip_address) && $ip_address =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/ && $port =~ /^\d+$/) {
@@ -942,6 +968,10 @@ sub send_msg_to_target {
             $sql_statement = "DELETE FROM known_server WHERE hostname='$address'";
             $res = $known_server_db->del_dbentry($sql_statement);
             daemon_log("$session_id WARNING: failed 2x to send a message to host '$address', delete host from known_server", 3);
+
+            # Remove the registered clients of the server as well
+           $sql_statement = "DELETE FROM foreign_clients WHERE regserver='$address'";
+           $res = $foreign_clients_db->del_dbentry($sql_statement);
         } 
         else { 
             $sql_statement = "UPDATE known_server SET status='$new_status', timestamp='$timestamp' WHERE hostname='$address'";
@@ -1041,14 +1071,6 @@ sub reactivate_job_with_delay {
 }
 
 
-sub sig_handler {
-       my ($kernel, $signal) = @_[KERNEL, ARG0] ;
-       daemon_log("0 INFO got signal '$signal'", 1); 
-       $kernel->sig_handled();
-       return;
-}
-
-
 sub msg_to_decrypt {
        my ($kernel, $session, $heap) = @_[KERNEL, SESSION, HEAP];
        my $session_id = $session->ID;
@@ -1549,12 +1571,12 @@ sub process_task {
 
 sub session_start {
     my ($kernel) = $_[KERNEL];
+    $kernel->alias_set('gosa-si_server_session');
     $global_kernel = $kernel;
     $kernel->yield('register_at_foreign_servers');
        $kernel->yield('create_fai_server_db', $fai_server_tn );
        $kernel->yield('create_fai_release_db', $fai_release_tn );
     $kernel->yield('watch_for_next_tasks');
-       $kernel->sig(USR1 => "sig_handler");
        $kernel->sig(USR2 => "recreate_packages_db");
        $kernel->delay_set('watch_for_new_jobs', $job_queue_loop_delay);
        $kernel->delay_set('watch_for_done_jobs', $job_queue_loop_delay); 
@@ -1568,9 +1590,14 @@ sub session_start {
     if ($opsi_enabled eq "true") {
         $kernel->delay_set('watch_for_opsi_jobs', $job_queue_opsi_delay); 
     }
-
 }
 
+sub session_stop {
+    my ($kernel, $session, $heap) = @_[KERNEL, SESSION, HEAP];
+    $kernel->alias_remove($heap->{alias});
+    $kernel->alarm_remove_all();
+    $kernel->post($heap->{child_session}, '_stop');
+}
 
 sub watch_for_done_jobs {
        #CHECK: $heap for what?
@@ -1780,8 +1807,7 @@ sub watch_for_new_jobs {
                                        my $res_2 = $job_db->exec_statement( $sql_statement_2 );
                                        if(defined($res_2) and defined @{$res_2}[0]) {
                                                # Set status from goto-activation to 'waiting' and update timestamp
-                                               $job_db->exec_statement("UPDATE $job_queue_tn SET status='waiting' WHERE macaddress LIKE '$macaddress' AND headertag = 'trigger_action_reinstall'");
-                                               $job_db->exec_statement("UPDATE $job_queue_tn SET timestamp='".&calc_timestamp(&get_time(), 'plus', 30)."' WHERE macaddress LIKE '$macaddress' AND headertag = 'trigger_action_reinstall'");
+                                               $job_db->exec_statement("UPDATE $job_queue_tn SET status='waiting', timestamp='".&calc_timestamp(&get_time(), 'plus', 30)."' WHERE macaddress LIKE '$macaddress' AND headertag = 'trigger_action_reinstall'");
                                        }
                                }
                                next;
@@ -1928,7 +1954,8 @@ sub watch_for_delivery_messages {
     my ($kernel, $heap) = @_[KERNEL, HEAP];
 
     # select outgoing messages
-    my $sql_statement = "SELECT * FROM $messaging_tn WHERE ( flag='p' AND direction='out' )";
+    my $timestamp= &get_time();
+    my $sql_statement = "SELECT * FROM $messaging_tn WHERE ( flag='p' AND direction='out' AND delivery_time<$timestamp)";
     #&daemon_log("0 DEBUG: $sql", 7);
     my $res = $messaging_db->exec_statement( $sql_statement );
     
@@ -3193,6 +3220,10 @@ GetOptions("h|help" => \&usage,
         "no-arp+" => \$no_arp,
            );
 
+# Prepare UID / GID as daemon_log may need it quite early
+$root_uid = getpwnam('root');
+$adm_gid = getgrnam('adm');
+
 #  read and set config parameters
 &check_cmdline_param ;
 &read_configfile($cfg_file, %cfg_defaults);
@@ -3239,10 +3270,10 @@ if ($server_headURL =~ /\/tag\// ||
     $server_status = "developmental" ;
 }
 
-# Prepare log file
-$root_uid = getpwnam('root');
-$adm_gid = getgrnam('adm');
-chmod(0640, $log_file);
+# Prepare log file and set permissons
+open(FH, ">>$log_file");
+close FH;
+chmod(0440, $log_file);
 chown($root_uid, $adm_gid, $log_file);
 chown($root_uid, $adm_gid, "/var/lib/gosa-si");
 
@@ -3293,56 +3324,56 @@ daemon_log($server_status_hash->{$server_status}.": $server_revision", 1);
         # connect to gosa-si job queue
         unlink($job_queue_file_name);  ## just for debugging
         $job_db = GOSA::DBsqlite->new($job_queue_file_name);
-        chmod(0660, $job_queue_file_name);
+        chmod(0640, $job_queue_file_name);
         chown($root_uid, $adm_gid, $job_queue_file_name);
         
         # connect to known_clients_db
         unlink($known_clients_file_name);   ## just for debugging
         $known_clients_db = GOSA::DBsqlite->new($known_clients_file_name);
-        chmod(0660, $known_clients_file_name);
+        chmod(0640, $known_clients_file_name);
         chown($root_uid, $adm_gid, $known_clients_file_name);
         
         # connect to foreign_clients_db
         unlink($foreign_clients_file_name);
         $foreign_clients_db = GOSA::DBsqlite->new($foreign_clients_file_name);
-        chmod(0660, $foreign_clients_file_name);
+        chmod(0640, $foreign_clients_file_name);
         chown($root_uid, $adm_gid, $foreign_clients_file_name);
         
         # connect to known_server_db
         unlink($known_server_file_name);
         $known_server_db = GOSA::DBsqlite->new($known_server_file_name);
-        chmod(0660, $known_server_file_name);
+        chmod(0640, $known_server_file_name);
         chown($root_uid, $adm_gid, $known_server_file_name);
         
         # connect to login_usr_db
         unlink($login_users_file_name);
         $login_users_db = GOSA::DBsqlite->new($login_users_file_name);
-        chmod(0660, $login_users_file_name);
+        chmod(0640, $login_users_file_name);
         chown($root_uid, $adm_gid, $login_users_file_name);
         
         # connect to fai_server_db
         unlink($fai_server_file_name);
         $fai_server_db = GOSA::DBsqlite->new($fai_server_file_name);
-        chmod(0660, $fai_server_file_name);
+        chmod(0640, $fai_server_file_name);
         chown($root_uid, $adm_gid, $fai_server_file_name);
         
         # connect to fai_release_db
         unlink($fai_release_file_name);
         $fai_release_db = GOSA::DBsqlite->new($fai_release_file_name);
-        chmod(0660, $fai_release_file_name);
+        chmod(0640, $fai_release_file_name);
         chown($root_uid, $adm_gid, $fai_release_file_name);
         
         # connect to packages_list_db
         #unlink($packages_list_file_name);
         unlink($packages_list_under_construction);
         $packages_list_db = GOSA::DBsqlite->new($packages_list_file_name);
-        chmod(0660, $packages_list_file_name);
+        chmod(0640, $packages_list_file_name);
         chown($root_uid, $adm_gid, $packages_list_file_name);
         
         # connect to messaging_db
         unlink($messaging_file_name);
         $messaging_db = GOSA::DBsqlite->new($messaging_file_name);
-        chmod(0660, $messaging_file_name);
+        chmod(0640, $messaging_file_name);
         chown($root_uid, $adm_gid, $messaging_file_name);
     }
 }
@@ -3479,8 +3510,8 @@ daemon_log("0 INFO: start socket for incoming xml messages at port '$server_port
 POE::Session->create(
        inline_states => {
                _start => \&session_start,
+        _stop => \&session_stop,
         register_at_foreign_servers => \&register_at_foreign_servers,
-        sig_handler => \&sig_handler,
         next_task => \&next_task,
         task_result => \&handle_task_result,
         task_done   => \&handle_task_done,