Code

Updated application acls
[gosa.git] / gosa-si / gosa-si-server-nobus
index 0e177473eec45cdc43a6cc9c11fab54bd60bffda..7bd0ba2709faed68e4ee3ec4ab50af4cf80f59f6 100755 (executable)
@@ -54,6 +54,7 @@ use POE qw(Component::Server::TCP Wheel::Run Filter::Reference);
 use Net::LDAP;
 use Net::LDAP::Util qw(:escape);
 use Time::HiRes qw( usleep);
+use DateTime;
 
 my $modules_path = "/usr/lib/gosa-si/modules";
 use lib "/usr/lib/gosa-si/modules";
@@ -66,14 +67,14 @@ my $server_status;
 our $prg= basename($0);
 
 our $global_kernel;
-my (%cfg_defaults, $foreground, $verbose, $ping_timeout);
+my ($foreground, $ping_timeout);
 my ($bus_activ, $bus, $msg_to_bus, $bus_cipher);
 my ($server);
 my ($gosa_server, $job_queue_timeout, $job_queue_loop_delay);
 my ($messaging_db_loop_delay);
 my ($known_modules);
-my ($pid_file, $procid, $pid, $log_file);
-my ($arp_activ, $arp_fifo);
+my ($procid, $pid);
+my ($arp_fifo);
 my ($xml);
 my $sources_list;
 my $max_clients;
@@ -127,6 +128,7 @@ my @incoming_col_names = ("id INTEGER PRIMARY KEY",
                "targettag DEFAULT 'none'",
         "xmlmessage DEFAULT 'none'",
         "module DEFAULT 'none'",
+        "sessionid DEFAULT '0'",
         );
 
 # holds all gosa jobs
@@ -155,7 +157,7 @@ my @known_server_col_names = ("hostname", "status", "hostkey", "timestamp");
 our $known_clients_db;
 our $known_clients_tn = "known_clients";
 my $known_clients_file_name;
-my @known_clients_col_names = ("hostname", "status", "hostkey", "timestamp", "macaddress", "events");
+my @known_clients_col_names = ("hostname", "status", "hostkey", "timestamp", "macaddress", "events", "keylifetime");
 
 # holds all registered clients at a foreign server
 our $foreign_clients_db;
@@ -247,7 +249,7 @@ my $max_children = 2;
     "address"      => [\$foreign_server_string, ""],
     "domain"  => [\$server_domain, ""],
     "key"     => [\$ServerPackages_key, "none"],
-    "key-lifetime" => [\$foreign_servers_register_delay, 600],
+    "key-lifetime" => [\$foreign_servers_register_delay, 120],
 }
 );
 
@@ -315,6 +317,7 @@ 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 }
@@ -890,6 +893,7 @@ sub send_msg_to_target {
     my ($msg, $address, $encrypt_key, $msg_header, $session_id) = @_ ;
     my $error = 0;
     my $header;
+    my $timestamp = &get_time();
     my $new_status;
     my $act_status;
     my ($sql_statement, $res);
@@ -937,14 +941,14 @@ sub send_msg_to_target {
     # known_clients
     $sql_statement = "SELECT * FROM known_clients WHERE hostname='$address'";
     $res = $known_clients_db->select_dbentry($sql_statement);
-    if( keys(%$res) > 0) {
+    if( keys(%$res) == 1) {
         $act_status = $res->{1}->{'status'};
         if ($act_status eq "down" && $new_status eq "down") {
             $sql_statement = "DELETE FROM known_clients WHERE hostname='$address'";
             $res = $known_clients_db->del_dbentry($sql_statement);
             daemon_log("$session_id WARNING: failed 2x to send msg to host '$address', delete host from known_clients", 3);
         } else { 
-            $sql_statement = "UPDATE known_clients SET status='$new_status' WHERE hostname='$address'";
+            $sql_statement = "UPDATE known_clients SET status='$new_status', timestamp='$timestamp' WHERE hostname='$address'";
             $res = $known_clients_db->update_dbentry($sql_statement);
             if($new_status eq "down"){
                 daemon_log("$session_id WARNING: set '$address' from status '$act_status' to '$new_status'", 3);
@@ -957,7 +961,7 @@ sub send_msg_to_target {
     # known_server
     $sql_statement = "SELECT * FROM $known_server_tn WHERE hostname='$address'";
     $res = $known_server_db->select_dbentry($sql_statement);
-    if( keys(%$res) > 0 ) {
+    if( keys(%$res) == 1) {
         $act_status = $res->{1}->{'status'};
         if ($act_status eq "down" && $new_status eq "down") {
             $sql_statement = "DELETE FROM known_server WHERE hostname='$address'";
@@ -965,7 +969,7 @@ sub send_msg_to_target {
             daemon_log("$session_id WARNING: failed 2x to send a message to host '$address', delete host from known_server", 3);
         } 
         else { 
-            $sql_statement = "UPDATE known_server SET status='$new_status' WHERE hostname='$address'";
+            $sql_statement = "UPDATE known_server SET status='$new_status', timestamp='$timestamp' WHERE hostname='$address'";
             $res = $known_server_db->update_dbentry($sql_statement);
             if($new_status eq "down"){
                 daemon_log("$session_id WARNING: set '$address' from status '$act_status' to '$new_status'", 3);
@@ -1003,16 +1007,6 @@ sub update_jobdb_status_for_send_msgs {
     }
 }
 
-sub _start {
-    my ($kernel) = $_[KERNEL];
-    &trigger_db_loop($kernel);
-    $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->sig(USR1 => "sig_handler");
-       $kernel->sig(USR2 => "create_packages_list_db");
-}
 
 sub sig_handler {
        my ($kernel, $signal) = @_[KERNEL, ARG0] ;
@@ -1023,7 +1017,7 @@ sub sig_handler {
 
 
 sub msg_to_decrypt {
-    my ($session, $heap) = @_[SESSION, HEAP];
+    my ($kernel, $session, $heap) = @_[KERNEL, SESSION, HEAP];
     my $session_id = $session->ID;
     my ($msg, $msg_hash, $module);
     my $error = 0;
@@ -1071,6 +1065,7 @@ sub msg_to_decrypt {
                 xmlmessage=>$msg,
                 timestamp=>&get_time,
                 module=>$module,
+                sessionid=>$session_id,
                 } );
         if ($res != 0) {
                        # TODO ist das mit $! so ok???
@@ -1082,16 +1077,15 @@ sub msg_to_decrypt {
 
 
 sub next_task {
-    my ($session, $heap) = @_[SESSION, HEAP];
-    my $task = POE::Wheel::Run->new(
-            Program => sub { process_task($session, $heap) },
+    my ($session, $heap, $task) = @_[SESSION, HEAP, ARG0];
+    my $running_task = POE::Wheel::Run->new(
+            Program => sub { process_task($session, $heap, $task) },
             StdioFilter => POE::Filter::Reference->new(),
             StdoutEvent  => "task_result",
             StderrEvent  => "task_debug",
             CloseEvent   => "task_done",
             );
-
-    $heap->{task}->{ $task->ID } = $task;
+    $heap->{task}->{ $running_task->ID } = $running_task;
 }
 
 sub handle_task_result {
@@ -1125,54 +1119,31 @@ sub handle_task_done {
 
 sub process_task {
     no strict "refs";
-    my ($session, $heap, $input) = @_;
-    my $session_id = $session->ID;
+    my ($session, $heap, $task) = @_;
     my $error = 0;
     my $answer_l;
     my ($answer_header, @answer_target_l, $answer_source);
     my $client_answer = "";
 
-       ##################################################
-       # fetch first unprocessed message from incoming_db
-    # sometimes the program is faster than sqlite, so wait until informations are present at db
-    my $id_sql;
-    my $id_res;
-    my $message_id;
-# TODO : das hier ist sehr sehr unschön       
-# to be tested: speed enhancement with usleep 100000???
-    while (1) {
-        $id_sql = "SELECT min(id) FROM $incoming_tn WHERE (NOT headertag LIKE 'answer%')"; 
-        $id_res = $incoming_db->exec_statement($id_sql);
-        $message_id = @{@$id_res[0]}[0];
-        if (defined $message_id) { last }
-        usleep(100000);
-    }
-
-    # fetch new message from incoming_db
-    my $sql = "SELECT * FROM $incoming_tn WHERE id=$message_id"; 
-    my $res = $incoming_db->exec_statement($sql);
-
     # prepare all variables needed to process message
-    my $msg = @{@$res[0]}[4];
-    my $incoming_id = @{@$res[0]}[0];
-    my $module = @{@$res[0]}[5];
-    my $header =  @{@$res[0]}[2];
+    my $msg = $task->{'xmlmessage'};
+    my $incoming_id = $task->{'id'};
+    my $module = $task->{'module'};
+    my $header =  $task->{'headertag'};
+    my $session_id = $task->{'sessionid'};
     my $msg_hash = $xml->XMLin($msg, ForceArray=>1);
-
-    # messages which are an answer to a still running process should not be processed here
-    if ($header =~ /^answer_(\d+)/) {
-        return;
-    }
-   
-    # delete message from db 
-    my $delete_sql = "DELETE FROM $incoming_tn WHERE id=$incoming_id";
-    my $delete_res = $incoming_db->exec_statement($delete_sql);
+    my $source = @{$msg_hash->{'source'}}[0];
+    
+    # set timestamp of incoming client uptodate, so client will not 
+    # be deleted from known_clients because of expiration
+    my $act_time = &get_time();
+    my $sql = "UPDATE $known_clients_tn SET timestamp='$act_time' WHERE hostname='$source'"; 
+    my $res = $known_clients_db->exec_statement($sql);
 
     ######################
     # process incoming msg
     if( $error == 0) {
-        daemon_log("$session_id INFO: Incoming msg (session_id=$session_id) with header '".@{$msg_hash->{'header'}}[0].
-                               "' from '".$heap->{'remote_ip'}."'", 5); 
+        daemon_log("$session_id INFO: Incoming msg (session_id=$session_id) with header '".@{$msg_hash->{'header'}}[0]."'", 5); 
         daemon_log("$session_id DEBUG: Processing module ".$module, 7);
         $answer_l = &{ $module."::process_incoming_msg" }($msg, $msg_hash, $session_id);
 
@@ -1330,6 +1301,17 @@ sub process_task {
 
 }
 
+sub session_start {
+    my ($kernel) = $_[KERNEL];
+    &trigger_db_loop($kernel);
+    $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 => "create_packages_list_db");
+}
 
 sub trigger_db_loop {
        my ($kernel) = @_ ;
@@ -1338,6 +1320,7 @@ sub trigger_db_loop {
        $kernel->delay_set('watch_for_new_messages', $messaging_db_loop_delay);
     $kernel->delay_set('watch_for_delivery_messages', $messaging_db_loop_delay);
        $kernel->delay_set('watch_for_done_messages', $messaging_db_loop_delay);
+    $kernel->delay_set('watch_for_old_known_clients', $job_queue_loop_delay);
 }
 
 
@@ -1572,7 +1555,7 @@ sub watch_for_delivery_messages {
                                # fetch key to encrypt msg propperly for usr/host
                                my $sql = "SELECT * FROM $known_clients_tn WHERE (hostname='$receiver_host')";
                                &daemon_log("0 DEBUG: $sql", 7);
-                               my $res = $known_clients_db->exec_statement($sql);
+                               my $res = $known_clients_db->select_dbentry($sql);
 
                                # host is already down
                                if (not ref(@$res[0]) eq "ARRAY") { next; }
@@ -1628,6 +1611,64 @@ sub watch_for_done_messages {
 }
 
 
+sub watch_for_old_known_clients {
+    my ($kernel,$heap) = @_[KERNEL, HEAP];
+
+    my $sql_statement = "SELECT * FROM $known_clients_tn";
+    my $res = $known_clients_db->select_dbentry( $sql_statement );
+
+    my $act_time = int(&get_time());
+
+    while ( my ($hit_num, $hit) = each %$res) {
+        my $expired_timestamp = int($hit->{'timestamp'});
+        $expired_timestamp =~ /(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/;
+        my $dt = DateTime->new( year   => $1,
+                month  => $2,
+                day    => $3,
+                hour   => $4,
+                minute => $5,
+                second => $6,
+                );
+
+        $dt->add( seconds => 2 * int($hit->{'keylifetime'}) );
+        $expired_timestamp = $dt->ymd('').$dt->hms('')."\n";
+        if ($act_time > $expired_timestamp) {
+            my $hostname = $hit->{'hostname'};
+            my $del_sql = "DELETE FROM $known_clients_tn WHERE hostname='$hostname'"; 
+            my $del_res = $known_clients_db->exec_statement($del_sql);
+
+            &main::daemon_log("0 INFO: timestamp '".$hit->{'timestamp'}."' of client '$hostname' is expired('$expired_timestamp'), client will be deleted from known_clients_db", 5);
+        }
+
+    }
+
+    $kernel->delay_set('watch_for_old_known_clients', $job_queue_loop_delay);
+}
+
+
+sub watch_for_next_tasks {
+    my ($kernel,$heap) = @_[KERNEL, HEAP];
+    
+    my $sql = "SELECT * FROM $incoming_tn";
+    my $res = $incoming_db->select_dbentry($sql);
+
+    while ( my ($hit_num, $hit) = each %$res) {
+        my $headertag = $hit->{'headertag'};
+        if ($headertag =~ /^answer_(\d+)/) {
+            # do not start processing, this message is for a still running POE::Wheel
+            next;
+        }
+        my $message_id = $hit->{'id'};
+        $kernel->yield('next_task', $hit);
+
+        my $sql = "DELETE FROM $incoming_tn WHERE id=$message_id";
+        my $res = $incoming_db->exec_statement($sql);
+    }
+
+    $kernel->delay_set('watch_for_next_tasks', 1); 
+}
+
+
 sub get_ldap_handle {
        my ($session_id) = @_;
        my $heap;
@@ -1639,7 +1680,7 @@ sub get_ldap_handle {
        if ($session_id == 0) {
                daemon_log("$session_id DEBUG: get_ldap_handle invoked without a session_id, create a new ldap_handle", 7); 
                $ldap_handle = Net::LDAP->new( $ldap_uri );
-               $ldap_handle->bind($ldap_admin_dn, password => $ldap_admin_password); 
+               $ldap_handle->bind($ldap_admin_dn, apassword => $ldap_admin_password); 
 
        } else {
                my $session_reference = $global_kernel->ID_id_to_session($session_id);
@@ -2792,17 +2833,17 @@ foreach my $foreign_server (@foreign_server_list) {
 
 
 POE::Component::Server::TCP->new(
+    Alias => "TCP_SERVER",
        Port => $server_port,
        ClientInput => sub {
         my ($kernel, $input) = @_[KERNEL, ARG0];
         push(@tasks, $input);
         push(@msgs_to_decrypt, $input);
         $kernel->yield("msg_to_decrypt");
-        $kernel->yield("next_task");
         },
     InlineStates => {
-        next_task => \&next_task,
         msg_to_decrypt => \&msg_to_decrypt,
+        next_task => \&next_task,
         task_result => \&handle_task_result,
         task_done   => \&handle_task_done,
         task_debug  => \&handle_task_debug,
@@ -2815,14 +2856,20 @@ daemon_log("start socket for incoming xml messages at port '$server_port' ", 1);
 # create session for repeatedly checking the job queue for jobs
 POE::Session->create(
        inline_states => {
-               _start => \&_start,
+               _start => \&session_start,
         register_at_foreign_servers => \&register_at_foreign_servers,
-               sig_handler => \&sig_handler,
+        sig_handler => \&sig_handler,
+        next_task => \&next_task,
+        task_result => \&handle_task_result,
+        task_done   => \&handle_task_done,
+        task_debug  => \&handle_task_debug,
+        watch_for_next_tasks => \&watch_for_next_tasks,
         watch_for_new_messages => \&watch_for_new_messages,
         watch_for_delivery_messages => \&watch_for_delivery_messages,
         watch_for_done_messages => \&watch_for_done_messages,
                watch_for_new_jobs => \&watch_for_new_jobs,
         watch_for_done_jobs => \&watch_for_done_jobs,
+        watch_for_old_known_clients => \&watch_for_old_known_clients,
         create_packages_list_db => \&run_create_packages_list_db,
         create_fai_server_db => \&run_create_fai_server_db,
         create_fai_release_db => \&run_create_fai_release_db,