From 7055784da1dcd9060ddf4e61cbf6d1e0b7de9043 Mon Sep 17 00:00:00 2001 From: rettenbe Date: Wed, 30 Jan 2008 16:31:04 +0000 Subject: [PATCH] complete new version of gosa-si-server, internal logic changed git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@8677 594d385d-05f5-0310-b6e9-bd551577e9d8 --- gosa-si/gosa-si-client | 9 +- gosa-si/gosa-si-server | 482 +++++++++++++++--- gosa-si/modules/DBsqlite.pm | 6 +- gosa-si/modules/GosaPackages.pm | 92 +--- gosa-si/modules/GosaSupportDaemon.pm | 11 +- .../{ServerPackages.pm => SIPackages.pm} | 261 +++------- gosa-si/server.conf | 4 +- gosa-si/tests/client.php | 7 +- 8 files changed, 526 insertions(+), 346 deletions(-) rename gosa-si/modules/{ServerPackages.pm => SIPackages.pm} (73%) diff --git a/gosa-si/gosa-si-client b/gosa-si/gosa-si-client index d88988cef..fe07d32f4 100755 --- a/gosa-si/gosa-si-client +++ b/gosa-si/gosa-si-client @@ -970,10 +970,6 @@ sub process_incoming_msg { my $header = @{$msg_hash->{header}}[0]; daemon_log("receive '$header' from $host", 1); -# daemon_log("header from msg:", 1); -# daemon_log("\t$header", 1); -# daemon_log("msg to process:", 7); -# daemon_log("\t$msg", 7); #check whether msg to process is a event opendir(DIR, $event_dir) @@ -1326,6 +1322,11 @@ daemon_log("client mac address detected: $client_mac_address", 1); if (defined $server_ip && defined $server_port) { $server_address = $server_ip.":".$server_port; } + +# this is necessary that gosa-si-server knowns to which ip-address he can send msgs +if( $client_ip eq "0.0.0.0" ) { + $client_ip = "127.0.0.1"; +} $client_address = $client_ip.":".$client_port; # setup xml parser diff --git a/gosa-si/gosa-si-server b/gosa-si/gosa-si-server index 515fe6ef2..96aea80fc 100755 --- a/gosa-si/gosa-si-server +++ b/gosa-si/gosa-si-server @@ -40,7 +40,6 @@ use Data::Dumper; use Sys::Syslog qw( :DEFAULT setlogsock); use Cwd; use File::Spec; -use GOSA::GosaSupportDaemon; use GOSA::DBsqlite; use POE qw(Component::Server::TCP); @@ -56,17 +55,17 @@ my ($max_clients); my ($pid_file, $procid, $pid, $log_file); my (%free_child, %busy_child, $child_max, $child_min, %child_alive_time, $child_timeout); my ($arp_activ, $arp_fifo, $arp_fifo_path); +my ($xml); # variables declared in config file are always set to 'our' our (%cfg_defaults, $log_file, $pid_file, $bus_activ, $bus_passwd, $bus_ip, $bus_port, - $server_activ, $server_ip, $server_port, $server_passwd, $max_clients, + $server_activ, $server_ip, $server_port, $SIPackages_key, $max_clients, $arp_activ, $arp_fifo_path, - $gosa_activ, $gosa_passwd, $gosa_ip, $gosa_port, $gosa_timeout, + $gosa_activ, $GosaPackages_key, $gosa_ip, $gosa_port, $gosa_timeout, ); # additional variable which should be globaly accessable -our $xml; our $server_address; our $bus_address; our $gosa_address; @@ -122,7 +121,7 @@ our $known_clients_db; {"server_activ" => [\$server_activ, "on"], "server_ip" => [\$server_ip, "0.0.0.0"], "server_port" => [\$server_port, "20081"], - "server_passwd" => [\$server_passwd, ""], + "SIPackages_key" => [\$SIPackages_key, "none"], "max_clients" => [\$max_clients, 100], }, "arp" => @@ -133,7 +132,7 @@ our $known_clients_db; {"gosa_activ" => [\$gosa_activ, "on"], "gosa_ip" => [\$gosa_ip, "0.0.0.0"], "gosa_port" => [\$gosa_port, "20082"], - "gosa_passwd" => [\$gosa_passwd, "none"], + "GosaPackages_key" => [\$GosaPackages_key, "none"], }, ); @@ -238,6 +237,21 @@ sub daemon_log { } +sub get_time { + my ($seconds, $minutes, $hours, $monthday, $month, + $year, $weekday, $yearday, $sommertime) = localtime(time); + $hours = $hours < 10 ? $hours = "0".$hours : $hours; + $minutes = $minutes < 10 ? $minutes = "0".$minutes : $minutes; + $seconds = $seconds < 10 ? $seconds = "0".$seconds : $seconds; + $month+=1; + $month = $month < 10 ? $month = "0".$month : $month; + $monthday = $monthday < 10 ? $monthday = "0".$monthday : $monthday; + $year+=1900; + return "$year$month$monthday$hours$minutes$seconds"; + +} + + #=== FUNCTION ================================================================ # NAME: check_cmdline_param # PARAMETERS: nothing @@ -316,8 +330,8 @@ sub check_pid { # PARAMETERS: module_path - string - abs. path to the directory the modules # are stored # RETURNS: nothing -# DESCRIPTION: each file in module_path which ends with '.pm' is imported by -# "require 'file';" +# DESCRIPTION: each file in module_path which ends with '.pm' and activation +# state is on is imported by "require 'file';" #=============================================================================== sub import_modules { daemon_log(" ", 1); @@ -332,19 +346,20 @@ sub import_modules { next; } - if( $no_arp > 0 ) { - if( $file =~ /ArpHandler.pm/ ) { - next; - } - } + if( $file =~ /ArpHandler.pm/ ) { + if( $no_arp > 0 ) { + next; + } + } + eval { require $file; }; if ($@) { daemon_log("ERROR: gosa-si-server could not load module $file", 1); daemon_log("$@", 5); - } else { + } + else { my $mod_name = $1; my $info = eval($mod_name.'::get_module_info()'); - # Only load module if get_module_info() returns a non-null object if(defined($info)) { my ($input_address, $input_key, $input, $input_active, $input_type) = @{$info}; @@ -353,12 +368,6 @@ sub import_modules { } } } - - # for debugging - #while ( my ($module, $tag_hash) = each(%$known_modules)) { - # print "\tmodule: $module"."\n"; - # print "\ttags: ".join(", ", keys(%$tag_hash))."\n"; - #} close (DIR); } @@ -378,63 +387,409 @@ sub sig_int_handler { $SIG{INT} = \&sig_int_handler; + +sub check_key_and_xml_validity { + my ($crypted_msg, $module_key) = @_; +#print STDERR "crypted_msg:$crypted_msg\n"; +#print STDERR "modul:$module\n"; +#print STDERR "modul_key:$module_key\n"; + + my $msg; + my $msg_hash; + eval{ + $msg = &decrypt_msg($crypted_msg, $module_key); + &main::daemon_log("decrypted_msg: \n$msg", 8); + + $msg_hash = $xml->XMLin($msg, ForceArray=>1); + + # check header + my $header_l = $msg_hash->{'header'}; + if( 1 != @{$header_l} ) { + die'header error'; + } + my $header = @{$header_l}[0]; + if( 0 == length $header) { + die 'header error'; + } + + # check source + my $source_l = $msg_hash->{'source'}; + if( 1 != @{$source_l} ) { + die'source error'; + } + my $source = @{$source_l}[0]; + if( 0 == length $source) { + die 'source error'; + } + + # check target + my $target_l = $msg_hash->{'target'}; + if( 1 != @{$target_l} ) { + die'target error'; + } + my $target = @{$target_l}[0]; + if( 0 == length $target) { + die 'target error'; + } + + }; + if($@) { + &main::daemon_log("WARNING: do not understand the message:", 5); + &main::daemon_log("$@", 8); + } + + return ($msg, $msg_hash); +} + + +sub input_from_known_server { + my ($input, $remote_ip) = @_ ; + my ($msg, $msg_hash, $module); + + + my $sql_statement= "SELECT * FROM known_server"; + my $query_res = $known_server_db->select_dbentry( $sql_statement ); + while( my ($hit_num, $hit) = each %{ $query_res } ) { + my $host_name = $hit->{hostname}; + if( not $host_name =~ "^$remote_ip") { + next; + } + my $host_key = $hit->{hostkey}; + daemon_log("ServerPackages: host_name: $host_name", 7); + daemon_log("ServerPackages: host_key: $host_key", 7); + + # check if module can open msg envelope with module key + my ($msg, $msg_hash) = &check_key_and_xml_validity($input, $host_key); + if( (!$msg) || (!$msg_hash) ) { + daemon_log("ServerPackages: deciphering raise error", 7); + daemon_log("$@", 8); + next; + } + else { + $module = "ServerPackages"; + last; + } + } + + if( (!$msg) || (!$msg_hash) || (!$module) ) { + daemon_log("Incoming message is not from a known server", 3); + } + + return ($msg, $msg_hash, $module); +} + + +sub input_from_known_client { + my ($input, $remote_ip) = @_ ; + my ($msg, $msg_hash, $module); + + my $sql_statement= "SELECT * FROM known_clients"; + my $query_res = $known_clients_db->select_dbentry( $sql_statement ); + while( my ($hit_num, $hit) = each %{ $query_res } ) { + my $host_name = $hit->{hostname}; + if( not $host_name =~ "^$remote_ip") { + next; + } + my $host_key = $hit->{hostkey}; + daemon_log("ServerPackages: host_name: $host_name", 7); + daemon_log("ServerPackages: host_key: $host_key", 7); + + # check if module can open msg envelope with module key + my ($msg, $msg_hash) = &check_key_and_xml_validity($input, $host_key); + if( (!$msg) || (!$msg_hash) ) { + daemon_log("ServerPackages: deciphering raise error", 7); + daemon_log("$@", 8); + next; + } + else { + $module = "ServerPackages"; + last; + } + } + + if( (!$msg) || (!$msg_hash) || (!$module) ) { + daemon_log("Incoming message is not from a known client", 3); + } + + return ($msg, $msg_hash, $module); +} + + +sub input_from_unknown_host { + no strict "refs"; + my ($input) = @_ ; + my ($msg, $msg_hash, $module); + + my %act_modules = %$known_modules; + + while( my ($mod, $info) = each(%act_modules)) { + # check a key exists for this module + my $module_key = ${$mod."_key"}; + if( ! $module_key ) { + daemon_log("ERROR: no key specified in config file for $mod", 1); + next; + } + daemon_log("$mod: $module_key", 5); + + # check if module can open msg envelope with module key + ($msg, $msg_hash) = &check_key_and_xml_validity($input, $module_key); + if( (!$msg) || (!$msg_hash) ) { + daemon_log("$mod: deciphering failed", 5); + next; + } + else { + $module = $mod; + last; + } + } + + if( (!$msg) || (!$msg_hash) || (!$module)) { + daemon_log("Incoming message is not from a unknown host", 3); + } + + return ($msg, $msg_hash, $module); +} + +sub create_ciphering { + my ($passwd) = @_; + $passwd = substr(md5_hex("$passwd") x 32, 0, 32); + my $iv = substr(md5_hex('GONICUS GmbH'),0, 16); + my $my_cipher = Crypt::Rijndael->new($passwd , Crypt::Rijndael::MODE_CBC()); + $my_cipher->set_iv($iv); + return $my_cipher; +} + + +sub encrypt_msg { + my ($msg, $key) = @_; + my $my_cipher = &create_ciphering($key); + $msg = "\0"x(16-length($msg)%16).$msg; + $msg = $my_cipher->encrypt($msg); + chomp($msg = &encode_base64($msg)); + # there are no newlines allowed inside msg + $msg=~ s/\n//g; + return $msg; +} + + +sub decrypt_msg { + my ($msg, $key) = @_ ; + $msg = &decode_base64($msg); + my $my_cipher = &create_ciphering($key); + $msg = $my_cipher->decrypt($msg); + $msg =~ s/\0*//g; + return $msg; +} + + +sub get_encrypt_key { + my ($target) = @_ ; + my $encrypt_key; + my $error = 0; + + # target can be in known_server + if( !$encrypt_key ) { + my $sql_statement= "SELECT * FROM known_server"; + my $query_res = $known_server_db->select_dbentry( $sql_statement ); + while( my ($hit_num, $hit) = each %{ $query_res } ) { + my $host_name = $hit->{hostname}; + if( $host_name ne $target ) { + next; + } + my $host_key = $hit->{hostkey}; + last; + } + } + + + # target can be in known_client + if( !$encrypt_key ) { + my $sql_statement= "SELECT * FROM known_clients"; + my $query_res = $known_clients_db->select_dbentry( $sql_statement ); + while( my ($hit_num, $hit) = each %{ $query_res } ) { + my $host_name = $hit->{hostname}; + if( $host_name ne $target ) { + next; + } + $encrypt_key = $hit->{hostkey}; + last; + } + } + + return $encrypt_key; +} + + #=== FUNCTION ================================================================ -# NAME: create_known_client -# PARAMETERS: hostname - string - key for the hash known_clients -# RETURNS: nothing -# DESCRIPTION: creates a dummy entry for hostname in known_clients +# NAME: open_socket +# PARAMETERS: PeerAddr string something like 192.168.1.1 or 192.168.1.1:10000 +# [PeerPort] string necessary if port not appended by PeerAddr +# RETURNS: socket IO::Socket::INET +# DESCRIPTION: open a socket to PeerAddr #=============================================================================== -sub create_known_client { - my ($hostname) = @_; - - my $entry = { table=>'known_clients', - hostname=>$hostname, - status=>'none', - hostkey=>'none', - timestamp=>'none', - macaddress=>'none', - events=>'none', - }; - my $res = $known_clients_db->add_dbentry($entry); - if ($res > 0) { - daemon_log("ERROR: cannot add entry to known_clients.db: $res", 1); +sub open_socket { + my ($PeerAddr, $PeerPort) = @_ ; + if(defined($PeerPort)){ + $PeerAddr = $PeerAddr.":".$PeerPort; + } + my $socket; + $socket = new IO::Socket::INET(PeerAddr => $PeerAddr, + Porto => "tcp", + Type => SOCK_STREAM, + Timeout => 5, + ); + if(not defined $socket) { + return; + } + &daemon_log("open_socket: $PeerAddr", 7); + return $socket; +} + + +sub send_msg_to_target { + my ($msg, $address, $encrypt_key, $msg_header) = @_ ; + my $error = 0; + + if( !$msg_header ) { + $msg_header = ""; + } + + # encrypt xml msg + my $crypted_msg = &encrypt_msg($msg, $encrypt_key); + + # opensocket + my $socket = &open_socket($address); + if(not defined $socket){ + daemon_log("cannot send $msg_header msg to $address , host not reachable", 1); + $error++; + } + + if( $error == 0 ) { + + # send xml msg + print $socket $crypted_msg."\n"; + + close $socket; + + daemon_log("send msg to $address", 1); + daemon_log("message:\n$msg", 8); + } - return; + return; } + sub client_input { - my ($heap,$input,$wheel) = @_[HEAP, ARG0, ARG1]; + no strict "refs"; + my ($heap,$input,$wheel) = @_[HEAP, ARG0, ARG1]; + my ($msg, $msg_hash, $module); + my $error = 0; + my $answer_l; + my ($answer_header, @answer_target_l, $answer_source); + my $client_answer; daemon_log("Incoming msg:\n$input\n", 8); - ###################################### - # forward msg to all imported modules - no strict "refs"; - my $answer; - my %act_modules = %$known_modules; - while( my ($module, $info) = each(%act_modules)) { - daemon_log("Processing module ".$module, 3); - my $tmp = &{ $module."::process_incoming_msg" }($input.".".$heap->{remote_ip}."\n"); - if (defined $tmp) { - $answer = $tmp; - daemon_log("Got answer from module ".$module.": \n".$answer,8); - } - } - daemon_log("processing of msg finished", 5); + # msg is from a new client or gosa + ($msg, $msg_hash, $module) = &input_from_unknown_host($input); - if (defined $answer) { - $heap->{client}->put($answer); - } else { - $heap->{client}->put("done\n"); - } + # msg is from a gosa-si-server or gosa-si-bus + if(( !$msg ) || ( !$msg_hash ) || ( !$module )){ + ($msg, $msg_hash, $module) = &input_from_known_server($input, $heap->{'remote_ip'}); + } + + # msg is from a gosa-si-client + if(( !$msg ) || ( !$msg_hash ) || ( !$module )){ + ($msg, $msg_hash, $module) = &input_from_known_client($input); + } + + # an error occurred + if(( !$msg ) || ( !$msg_hash ) || ( !$module )){ + $error++; + } + + ###################### + # process incoming msg + if( $error == 0) { + daemon_log("Processing module ".$module, 3); + $answer_l = &{ $module."::process_incoming_msg" }($msg, $msg_hash); + + if ( 0 > @{$answer_l} ) { + my $answer_str = join("\n", @{$answer_l}); + daemon_log("$module: Got answer from module: \n".$answer_str,8); + } + } + if( !$answer_l ) { $error++ }; + + # for each answer in answer list + foreach my $answer ( @{$answer_l} ) { + + # check answer if gosa-si envelope conform + if( $error == 0 ) { + my $answer_hash = $xml->XMLin($answer, ForceArray=>1); + $answer_header = @{$answer_hash->{'header'}}[0]; + @answer_target_l = @{$answer_hash->{'target'}}; + $answer_source = @{$answer_hash->{'source'}}[0]; + if( !$answer_header ) { + daemon_log('ERROR: module answer is not gosa-si envelope conform: no header', 1); + $error++; + } + if( 0 == length @answer_target_l ) { + daemon_log('ERROR: module answer is not gosa-si envelope conform: no targets', 1); + $error++; + } + if( !$answer_source ) { + daemon_log('ERROR: module answer is not gosa-si envelope conform: no source', 1); + $error++; + } + } + + # deliver msg to all targets + foreach my $answer_target ( @answer_target_l ) { + if( $answer_target eq "*" ) { + # answer is for all clients + my $sql_statement= "SELECT * FROM known_clients"; + my $query_res = $known_clients_db->select_dbentry( $sql_statement ); + while( my ($hit_num, $hit) = each %{ $query_res } ) { + my $host_name = $hit->{hostname}; + my $host_key = $hit->{hostkey}; + &send_msg_to_target($answer, $host_name, $host_key); + } + } + elsif( $answer_target eq "GOSA" ) { + # answer is for GOSA and has to returned to connected client + my $gosa_answer = &encrypt_msg($answer, $GosaPackages_key); + $client_answer = $gosa_answer; + } + else { + # answer is for one specific host + # get encrypt_key + my $encrypt_key = &get_encrypt_key($answer_target); + if( !$encrypt_key ) { + daemon_log("ERROR: no encrypt key found for answer target '$answer_target'", 1); + next; + } + # send_msg + &send_msg_to_target($answer, $answer_target, $encrypt_key); + } + } + } + + if( $client_answer ) { + $heap->{client}->put($client_answer); + } + + return; } + sub trigger_db_loop { my ($kernel) = $_[KERNEL]; $kernel->delay_set('watch_for_new_jobs',3); } + sub watch_for_new_jobs { my ($kernel,$heap) = @_[KERNEL, HEAP]; @@ -482,10 +837,10 @@ sub watch_for_new_jobs { my $out_msg = &create_xml_string($out_msg_hash); # encrypt msg as a GosaPackage module - my $cipher = &create_ciphering($gosa_passwd); + my $cipher = &create_ciphering($GosaPackages_key); my $crypted_out_msg = &encrypt_msg($out_msg, $cipher); - my $error = &send_msg_hash2address($out_msg_hash, "$gosa_ip:$gosa_port", $gosa_passwd); + my $error = &send_msg_hash2address($out_msg_hash, "$gosa_ip:$gosa_port", $GosaPackages_key); if ($error == 0) { my $sql_statement = "UPDATE $job_queue_table_name ". @@ -574,6 +929,9 @@ $known_server_db->create_table('known_server', \@server_col_names); # check wether all modules are gosa-si valid passwd check +# create xml object used for en/decrypting +$xml = new XML::Simple(); + # create session for repeatedly checking the job queue for jobs POE::Session->create( inline_states => { diff --git a/gosa-si/modules/DBsqlite.pm b/gosa-si/modules/DBsqlite.pm index 92de527ab..481ae92e6 100644 --- a/gosa-si/modules/DBsqlite.pm +++ b/gosa-si/modules/DBsqlite.pm @@ -37,7 +37,7 @@ sub lock_exists : locked { my $lock = $self->{db_lock}; my $result=(-f $lock); if($result) { - &main::daemon_log("(".((defined $funcname)?$funcname:"").") Lock (PID ".$$.") $lock gefunden", 8); + #&main::daemon_log("(".((defined $funcname)?$funcname:"").") Lock (PID ".$$.") $lock gefunden", 8); usleep 100; } return $result; @@ -46,7 +46,7 @@ sub lock_exists : locked { sub create_lock : locked { my $self=shift; my $funcname=shift; - &main::daemon_log("(".((defined $funcname)?$funcname:"").") Erzeuge Lock (PID ".$$.") ".($self->{db_lock}),8); +# &main::daemon_log("(".((defined $funcname)?$funcname:"").") Erzeuge Lock (PID ".$$.") ".($self->{db_lock}),8); my $lock = $self->{db_lock}; while( -f $lock ) { @@ -60,7 +60,7 @@ sub create_lock : locked { sub remove_lock : locked { my $self=shift; my $funcname=shift; - &main::daemon_log("(".((defined $funcname)?$funcname:"").") Entferne Lock (PID ".$$.") ".$self->{db_lock}, 8); +# &main::daemon_log("(".((defined $funcname)?$funcname:"").") Entferne Lock (PID ".$$.") ".$self->{db_lock}, 8); close($self->{db_lock_handle}); unlink($self->{db_lock}); } diff --git a/gosa-si/modules/GosaPackages.pm b/gosa-si/modules/GosaPackages.pm index d8942c9e6..f13ed3bc1 100644 --- a/gosa-si/modules/GosaPackages.pm +++ b/gosa-si/modules/GosaPackages.pm @@ -64,7 +64,7 @@ my $bus_address = "$bus_ip:$bus_port"; my $gosa_address = "$gosa_ip:$gosa_port"; # create general settings for this module -my $gosa_cipher = &create_ciphering($gosa_passwd); +#y $gosa_cipher = &create_ciphering($gosa_passwd); my $xml = new XML::Simple(); @@ -227,31 +227,6 @@ sub get_ip { return $result; } -#=== FUNCTION ================================================================ -# NAME: open_socket -# PARAMETERS: PeerAddr string something like 192.168.1.1 or 192.168.1.1:10000 -# [PeerPort] string necessary if port not appended by PeerAddr -# RETURNS: socket IO::Socket::INET -# DESCRIPTION: open a socket to PeerAddr -#=============================================================================== -#sub open_socket { -# my ($PeerAddr, $PeerPort) = @_ ; -# if(defined($PeerPort)){ -# $PeerAddr = $PeerAddr.":".$PeerPort; -# } -# my $socket; -# $socket = new IO::Socket::INET(PeerAddr => $PeerAddr , -# Porto => "tcp" , -# Type => SOCK_STREAM, -# Timeout => 5, -# ); -# if(not defined $socket) { -# return; -# } -# &main::daemon_log("open_socket to: $PeerAddr", 7); -# return $socket; -#} - #=== FUNCTION ================================================================ # NAME: process_incoming_msg @@ -260,72 +235,37 @@ sub get_ip { # DESCRIPTION: handels the proceeded distribution to the appropriated functions #=============================================================================== sub process_incoming_msg { - my ($crypted_msg) = @_ ; - if( (not(defined($crypted_msg))) || (length($crypted_msg) <= 0)) { - &main::daemon_log("function 'process_incoming_msg': got no msg", 7); - return; - } - - $crypted_msg =~ /^([\s\S]*?)\.(\d{1,3}?)\.(\d{1,3}?)\.(\d{1,3}?)\.(\d{1,3}?)$/; - $crypted_msg = $1; - my $host = sprintf("%s.%s.%s.%s", $2, $3, $4, $5); - - # collect addresses from possible incoming clients - # only gosa is allowd as incoming client - &main::daemon_log("GosaPackages: host_key: $host", 7); - &main::daemon_log("GosaPackages: key_passwd: $gosa_passwd", 7); - - $gosa_cipher = &create_ciphering($gosa_passwd); - - # determine the correct passwd for deciphering of the incoming msgs - my $msg = ""; - my $msg_hash; - eval{ - $msg = &decrypt_msg($crypted_msg, $gosa_cipher); - &main::daemon_log("GosaPackages: decrypted_msg: \n$msg", 8); - - $msg_hash = $xml->XMLin($msg, ForceArray=>1); - }; - if($@) { - &main::daemon_log("WARNING: GosaPackages do not understand the message:", 5); - &main::daemon_log("$@", 7); - return; - } - + my ($msg, $msg_hash) = @_ ; my $header = @{$msg_hash->{header}}[0]; + my $out_msg; - &main::daemon_log("GosaPackages: receive '$header' from $host", 1); + &main::daemon_log("GosaPackages: receive '$header'", 1); - my $out_msg; if ($header =~ /^job_/) { $out_msg = &process_job_msg($msg, $msg_hash); - } elsif ($header =~ /^gosa_/) { + } + elsif ($header =~ /^gosa_/) { $out_msg = &process_gosa_msg($msg, $header); - } else { + } + else { &main::daemon_log("ERROR: $header is not a valid GosaPackage-header, need a 'job_' or a 'gosa_' prefix"); } - - if (not defined $out_msg) { - return; - } - + + # keep job queue uptodate and save result and status if ($out_msg =~ /(\d*?)<\/jobdb_id>/) { my $job_id = $1; my $sql = "UPDATE '".$main::job_queue_table_name. "' SET status='done', result='".$out_msg. "' WHERE id='$job_id'"; my $res = $main::job_db->exec_statement($sql); - return; - - } else { - - my $out_cipher = &create_ciphering($gosa_passwd); - $out_msg = &encrypt_msg($out_msg, $out_cipher); - return $out_msg; - } + } + my @out_msg_l; + push(@out_msg_l, $out_msg); + return \@out_msg_l; } + sub process_gosa_msg { my ($msg, $header) = @_ ; my $out_msg; @@ -348,7 +288,7 @@ sub process_gosa_msg { # try to deliver incoming msg to eventhandler my $cmd = File::Spec->join($server_event_dir, $header)." '$msg'"; &main::daemon_log("GosaPackages: execute event_handler $header", 3); - &main::daemon_log("GosaPackages: cmd: $cmd", 7); + &main::daemon_log("GosaPackages: cmd: $cmd", 8); $out_msg = ""; open(PIPE, "$cmd 2>&1 |"); diff --git a/gosa-si/modules/GosaSupportDaemon.pm b/gosa-si/modules/GosaSupportDaemon.pm index 571d5008b..270666e79 100644 --- a/gosa-si/modules/GosaSupportDaemon.pm +++ b/gosa-si/modules/GosaSupportDaemon.pm @@ -313,17 +313,20 @@ sub send_msg ($$$$$) { &add_content2xml_hash($out_hash, $key, $value); } } - - &send_msg_hash2address($out_hash, $to, $hostkey); + my $out_msg = &create_xml_string($out_hash); + return $out_msg; } sub get_where_statement { - my ($msg, $msg_hash)= @_; + my ($msg, $msg_hash) = @_; my $error= 0; my $clause_str= ""; - if( (not exists $msg_hash->{'where'}) || (not exists @{$msg_hash->{'where'}}[0]->{'clause'}) ) { $error++; }; + if( (not exists $msg_hash->{'where'}) || (not exists @{$msg_hash->{'where'}}[0]->{'clause'}) ) { + $error++; + } + if( $error == 0 ) { my @clause_l; my @where = @{@{$msg_hash->{'where'}}[0]->{'clause'}}; diff --git a/gosa-si/modules/ServerPackages.pm b/gosa-si/modules/SIPackages.pm similarity index 73% rename from gosa-si/modules/ServerPackages.pm rename to gosa-si/modules/SIPackages.pm index c06aba4f0..6cdd52760 100644 --- a/gosa-si/modules/ServerPackages.pm +++ b/gosa-si/modules/SIPackages.pm @@ -1,4 +1,4 @@ -package ServerPackages; +package SIPackages; use Exporter; @ISA = ("Exporter"); @@ -59,6 +59,9 @@ $network_interface= &get_interface_for_ip($server_ip); $server_mac_address= &get_mac($network_interface); # complete addresses +if( $server_ip eq "0.0.0.0" ) { + $server_ip = "127.0.0.1"; +} my $server_address = "$server_ip:$server_port"; my $bus_address = "$bus_ip:$bus_port"; @@ -287,6 +290,7 @@ sub register_at_bus { return; } + #=== FUNCTION ================================================================ # NAME: process_incoming_msg # PARAMETERS: crypted_msg - string - incoming crypted message @@ -294,184 +298,48 @@ sub register_at_bus { # DESCRIPTION: handels the proceeded distribution to the appropriated functions #=============================================================================== sub process_incoming_msg { - my ($crypted_msg) = @_ ; - if(not defined $crypted_msg) { - &main::daemon_log("function 'process_incoming_msg': got no msg", 7); - } - - $crypted_msg =~ /^([\s\S]*?)\.(\d{1,3}?)\.(\d{1,3}?)\.(\d{1,3}?)\.(\d{1,3}?)$/; - $crypted_msg = $1; - my $host="0.0.0.0"; - if(defined $2 && defined $3 && defined $4 && defined $5) { - $host = sprintf("%s.%s.%s.%s", $2, $3, $4, $5); - } - - my $msg; - my $msg_hash; + my ($msg, $msg_hash) = @_ ; + my $error = 0; my $host_name; my $host_key; + my @out_msg_l; - # check wether incoming msg is a new msg - $host_name = $server_address; - $host_key = $server_passwd; - &main::daemon_log("ServerPackage: host_name: $host_name", 7); - &main::daemon_log("ServerPackage: host_key: $host_key", 7); - eval{ - my $key_cipher = &create_ciphering($host_key); - $msg = &decrypt_msg($crypted_msg, $key_cipher); - $msg_hash = &transform_msg2hash($msg); - }; - if($@) { - &main::daemon_log("ServerPackage: deciphering raise error", 7); - &main::daemon_log("$@", 8); - $msg = undef; - $msg_hash = undef; - $host_name = undef; - $host_key = undef; - } - - # check wether incoming msg is from a known_server - if( not defined $msg ) { - my $sql_statement= "SELECT * FROM known_server"; - my $query_res = $main::known_server_db->select_dbentry( $sql_statement ); + # process incoming msg + my $header = @{$msg_hash->{header}}[0]; + my $source = @{$msg_hash->{source}}[0]; + my @target_l = @{$msg_hash->{target}}; - while( my ($hit_num, $hit) = each %{ $query_res } ) { - $host_name = $hit->{hostname}; + &main::daemon_log("SIPackages: msg to process: $header", 3); + &main::daemon_log("$msg", 8); - if( not $host_name =~ "^$host") { - next; - } - $host_key = $hit->{hostkey}; - &main::daemon_log("ServerPackage: host_name: $host_name", 7); - &main::daemon_log("ServerPackage: host_key: $host_key", 7); - eval{ - my $key_cipher = &create_ciphering($host_key); - $msg = &decrypt_msg($crypted_msg, $key_cipher); - $msg_hash = &transform_msg2hash($msg); - }; - if($@) { - &main::daemon_log("ServerPackage: deciphering raise error", 7); - &main::daemon_log("$@", 8); - $msg = undef; - $msg_hash = undef; - $host_name = undef; - $host_key = undef; - } else { - last; - } - } + if( 0 == length @target_l){ + &main::daemon_log("ERROR: no target specified for msg $header", 1); + $error++; } - # check wether incoming msg is from a known_client - if( not defined $msg ) { - #my $query_res = $main::known_clients_db->select_dbentry( {table=>'known_clients'} ); - my $sql_statement= "SELECT * FROM known_clients"; - my $query_res = $main::known_clients_db->select_dbentry( $sql_statement ); - while( my ($hit_num, $hit) = each %{ $query_res } ) { - $host_name = $hit->{hostname}; - if( not $host_name =~ "^$host") { - next; - } - $host_key = $hit->{hostkey}; - &main::daemon_log("ServerPackage: host_name: $host_name", 7); - &main::daemon_log("ServerPackage: host_key: $host_key", 7); - eval{ - my $key_cipher = &create_ciphering($host_key); - $msg = &decrypt_msg($crypted_msg, $key_cipher); - $msg_hash = &transform_msg2hash($msg); - }; - if($@) { - &main::daemon_log("ServerPackage: deciphering raise error", 7); - &main::daemon_log("$@", 8); - $msg = undef; - $msg_hash = undef; - $host_name = undef; - $host_key = undef; - } else { - last; + if( 1 == length @target_l) { + my $target = $target_l[0]; + if( $target eq $server_address ) { + if ($header eq 'new_passwd') { @out_msg_l = &new_passwd($msg_hash) } + elsif ($header eq 'here_i_am') { @out_msg_l = &here_i_am($msg_hash) } + elsif ($header eq 'who_has') { @out_msg_l = &who_has($msg_hash) } + elsif ($header eq 'who_has_i_do') { @out_msg_l = &who_has_i_do($msg_hash) } + elsif ($header eq 'got_ping') { @out_msg_l = &got_ping($msg_hash)} + elsif ($header eq 'get_load') { @out_msg_l = &execute_actions($msg_hash)} + else { + &main::daemon_log("ERROR: $header is an unknown core funktion", 1); + $error++; } } } - - if( not defined $msg ) { - &main::daemon_log("WARNING: ServerPackage do not understand the message:", 5); - &main::daemon_log("$@", 8); - return; - } - - # process incoming msg - my $header = @{$msg_hash->{header}}[0]; - my $source = @{$msg_hash->{source}}[0]; - - &main::daemon_log("receive '$header' at ServerPackages from $host", 1); - &main::daemon_log("ServerPackages: msg to process: \n$msg", 5); - - my @targets = @{$msg_hash->{target}}; - my $len_targets = @targets; - if ($len_targets == 0){ - &main::daemon_log("ERROR: ServerPackages: no target specified for msg $header", 1); - - } elsif ($len_targets == 1){ - # we have only one target symbol - my $target = $targets[0]; - &main::daemon_log("SeverPackages: msg is for: $target", 7); - - # msg is for server - if ($header eq 'new_passwd'){ &new_passwd($msg_hash)} - elsif ($header eq 'here_i_am') { &here_i_am($msg_hash)} - elsif ($header eq 'who_has') { &who_has($msg_hash) } - elsif ($header eq 'who_has_i_do') { &who_has_i_do($msg_hash)} - elsif ($header eq 'update_status') { &update_status($msg_hash) } - elsif ($header eq 'got_ping') { &got_ping($msg_hash)} - elsif ($header eq 'get_load') { &execute_actions($msg_hash)} - else { - if ($target eq "*") { - # msg is for all clients - my $sql_statement = "SELECT * FROM known_clients"; - my $query_res = $main::known_clients_db->select_dbentry( $sql_statement ); - while( my ($hit_num, $hit) = each %{ $query_res } ) { - $host_name = $hit->{hostname}; - $host_key = $hit->{hostkey}; - $msg_hash->{target} = [$host_name]; - &send_msg_hash2address($msg_hash, $host_name, $host_key); - } - - } else { - # msg is for one host - my $host_key; - - - if( not defined $host_key ) { - my $sql_statement = "SELECT * FROM known_clients WHERE hostname='$target'"; - my $query_res = $main::known_clients_db->select_dbentry( $sql_statement ); - if( 1 == keys %{$query_res} ) { - $host_key = $query_res->{1}->{host_key}; - } - } - - if( not defined $host_key ) { - my $sql_statement = "SELECT * FROM known_server WHERE hostname='$target'"; - my $query_res = $main::known_server_db->select_dbentry( $sql_statement ); - if( 1 == keys %{$query_res} ) { - $host_key = $query_res->{1}->{host_key}; - } - } - - if( not defined $host_key ) { - &main::daemon_log("ERROR: ServerPackages: target '".$target. - "' is not known neither in known_clients nor in known_server",1); - } else { - &send_msg_hash2address($msg_hash, $target, $host_key); - } - } + + if( $error == 0) { + if( 0 == @out_msg_l ) { + push(@out_msg_l, $msg); } - - } elsif ($len_targets > 1 ) { - # we have more than one target - # TODO to be implemented } - - return ; + + return \@out_msg_l; } @@ -506,7 +374,8 @@ sub got_ping { #=============================================================================== sub new_passwd { my ($msg_hash) = @_; - + my @out_msg_l; + my $header = @{$msg_hash->{header}}[0]; my $source_name = @{$msg_hash->{source}}[0]; my $source_key = @{$msg_hash->{new_passwd}}[0]; @@ -523,27 +392,29 @@ sub new_passwd { my $res = $main::known_clients_db->update_dbentry( $sql_statement ); my $hash = &create_xml_hash("confirm_new_passwd", $server_address, $source_name); - &send_msg_hash2address($hash, $source_name, $source_key); - return; + my $out_msg = &create_xml_string($hash); + push(@out_msg_l, $out_msg); } - # check known_server_db - $sql_statement = "SELECT * FROM known_server WHERE hostname='$source_name'"; - $query_res = $main::known_server_db->select_dbentry( $sql_statement ); - if( 1 == keys %{$query_res} ) { - my $act_time = &get_time; - my $sql_statement= "UPDATE known_server ". - "SET hostkey='$source_key', timestamp='$act_time' ". - "WHERE hostname='$source_name'"; - my $res = $main::known_server_db->update_dbentry( $sql_statement ); - - my $hash = &create_xml_hash("confirm_new_passwd", $server_address, $source_name); - &send_msg_hash2address($hash, $source_name, $source_key); - return; + # only do if host still not found + if( 0 == @out_msg_l ) { + # check known_server_db + $sql_statement = "SELECT * FROM known_server WHERE hostname='$source_name'"; + $query_res = $main::known_server_db->select_dbentry( $sql_statement ); + if( 1 == keys %{$query_res} ) { + my $act_time = &get_time; + my $sql_statement= "UPDATE known_server ". + "SET hostkey='$source_key', timestamp='$act_time' ". + "WHERE hostname='$source_name'"; + my $res = $main::known_server_db->update_dbentry( $sql_statement ); + + my $hash = &create_xml_hash("confirm_new_passwd", $server_address, $source_name); + my $out_msg = &create_xml_string($hash); + push(@out_msg_l, $out_msg); + } } - &main::daemon_log("ERROR: $source_name not known for '$header'-msg", 1); - return; + return @out_msg_l; } @@ -555,10 +426,11 @@ sub new_passwd { #=============================================================================== sub here_i_am { my ($msg_hash) = @_; + my @out_msg_l; + my $out_hash; my $source = @{$msg_hash->{source}}[0]; my $mac_address = @{$msg_hash->{mac_address}}[0]; - my $out_hash; # number of known clients my $nu_clients= $main::known_clients_db->count_dbentries('known_clients'); @@ -612,7 +484,8 @@ sub here_i_am { # return acknowledgement to client $out_hash = &create_xml_hash("registered", $server_address, $source); - &send_msg_hash2address($out_hash, $source, $new_passwd); + my $register_out = &create_xml_string($out_hash); + push(@out_msg_l, $register_out); # notify registered client to bus if( $bus_activ eq "on") { @@ -623,15 +496,19 @@ sub here_i_am { # send update msg to bus $out_hash = &create_xml_hash("new_client", $server_address, $bus_address, $source); - &send_msg_hash2address($out_hash, $bus_address, $hostkey); - + my $new_client_out = &create_xml_string($out_hash); + push(@out_msg_l, $new_client_out); &main::daemon_log("send bus msg that client '$source' has registerd at server '$server_address'", 3); } # give the new client his ldap config - &new_ldap_config($source); + my $new_ldap_config_out = &new_ldap_config($source); + if( $new_ldap_config_out ) { + push(@out_msg_l, $new_ldap_config_out); + } - return; + + return @out_msg_l; } @@ -744,7 +621,7 @@ sub new_ldap_config { my $base; # Do we need to look at an object class? - if (length(@servers) < 1){ + if ($#servers < 1){ $mesg = $ldap->search( base => $ldap_base, scope => 'sub', attrs => ['dn', 'gotoLdapServer'], diff --git a/gosa-si/server.conf b/gosa-si/server.conf index 05647e0f6..55c5d0a55 100644 --- a/gosa-si/server.conf +++ b/gosa-si/server.conf @@ -15,7 +15,7 @@ bus_port = 20080 [server] server_activ = on server_port = 20081 -server_passwd = secret-server-password +SIPackages_key = secret-server-password max_clients = 5 server_event_dir = /usr/lib/gosa-si/server/events @@ -29,5 +29,5 @@ ldap_admin_password = secret [gosa] gosa_activ = on -gosa_passwd = secret-gosa-password +GosaPackages_key = secret-gosa-password diff --git a/gosa-si/tests/client.php b/gosa-si/tests/client.php index cb4befec5..f66139378 100755 --- a/gosa-si/tests/client.php +++ b/gosa-si/tests/client.php @@ -33,15 +33,16 @@ $data = "
job_ping
10.89.1.155:20083 #$data= "
gosa_query_jobdb
ping05timestamp
"; #$data= "
gosa_query_jobdb
"; - # count #$data = "
gosa_count_jobdb
"; - - # clear #$data = "
gosa_clear_jobdb
"; +# set gosa-si-client to 'activated' +$data = "
gosa_set_activated_for_installation
127.0.0.1:20083 127.0.0.1:20081
"; + + $sock->write($data); $answer = "nothing"; $answer = $sock->read(); -- 2.30.2