From: rettenbe Date: Wed, 30 Jan 2008 16:31:04 +0000 (+0000) Subject: complete new version of gosa-si-server, internal logic changed X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=7055784da1dcd9060ddf4e61cbf6d1e0b7de9043;p=gosa.git 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 --- 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/SIPackages.pm b/gosa-si/modules/SIPackages.pm new file mode 100644 index 000000000..6cdd52760 --- /dev/null +++ b/gosa-si/modules/SIPackages.pm @@ -0,0 +1,722 @@ +package SIPackages; + +use Exporter; +@ISA = ("Exporter"); + +# Each module has to have a function 'process_incoming_msg'. This function works as a interface to gosa-sd and receives the msg hash from gosa-sd. 'process_incoming_function checks, wether it has a function to process the incoming msg and forward the msg to it. + + +use strict; +use warnings; +use GOSA::GosaSupportDaemon; +use IO::Socket::INET; +use XML::Simple; +use Data::Dumper; +use Net::LDAP; +use Socket qw/PF_INET SOCK_DGRAM inet_ntoa sockaddr_in/; + +BEGIN{} +END {} + +my ($known_clients_file_name); +my ($server_activ, $server_ip, $server_mac_address, $server_port, $server_passwd, $max_clients, $ldap_uri, $ldap_base, $ldap_admin_dn, $ldap_admin_password); +my ($bus_activ, $bus_passwd, $bus_ip, $bus_port); +my $server; +my $network_interface; +my $no_bus; +my (@ldap_cfg, @pam_cfg, @nss_cfg, $goto_admin, $goto_secret); + + +my %cfg_defaults = +( +"server" => + {"server_activ" => [\$server_activ, "on"], + "server_ip" => [\$server_ip, "0.0.0.0"], + "server_mac_address" => [\$server_mac_address, ""], + "server_port" => [\$server_port, "20081"], + "server_passwd" => [\$server_passwd, ""], + "max_clients" => [\$max_clients, 100], + "ldap_uri" => [\$ldap_uri, ""], + "ldap_base" => [\$ldap_base, ""], + "ldap_admin_dn" => [\$ldap_admin_dn, ""], + "ldap_admin_password" => [\$ldap_admin_password, ""], + }, +"bus" => + {"bus_activ" => [\$bus_activ, "on"], + "bus_passwd" => [\$bus_passwd, ""], + "bus_ip" => [\$bus_ip, ""], + "bus_port" => [\$bus_port, "20080"], + }, +); + +### START ##################################################################### + +# read configfile and import variables +&read_configfile(); + +# detect interfaces and mac address +$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"; + +# create general settings for this module +my $xml = new XML::Simple(); + +# register at bus +if ($main::no_bus > 0) { + $bus_activ = "off" +} +if($bus_activ eq "on") { + ®ister_at_bus(); +} + +### functions ################################################################# + + +sub get_module_info { + my @info = ($server_address, + $server_passwd, + $server, + $server_activ, + "socket", + ); + return \@info; +} + + +#=== FUNCTION ================================================================ +# NAME: read_configfile +# PARAMETERS: cfg_file - string - +# RETURNS: nothing +# DESCRIPTION: read cfg_file and set variables +#=============================================================================== +sub read_configfile { + my $cfg; + if( defined( $main::cfg_file) && ( length($main::cfg_file) > 0 )) { + if( -r $main::cfg_file ) { + $cfg = Config::IniFiles->new( -file => $main::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] ); + } + } + + # Read non predefined sections + my $param; + if ($cfg->SectionExists('ldap')){ + foreach $param ($cfg->Parameters('ldap')){ + push (@ldap_cfg, "$param ".$cfg->val('ldap', $param)); + } + } + if ($cfg->SectionExists('pam_ldap')){ + foreach $param ($cfg->Parameters('pam_ldap')){ + push (@pam_cfg, "$param ".$cfg->val('pam_ldap', $param)); + } + } + if ($cfg->SectionExists('nss_ldap')){ + foreach $param ($cfg->Parameters('nss_ldap')){ + push (@nss_cfg, "$param ".$cfg->val('nss_ldap', $param)); + } + } + if ($cfg->SectionExists('goto')){ + $goto_admin= $cfg->val('goto', 'terminal_admin'); + $goto_secret= $cfg->val('goto', 'terminal_secret'); + } else { + $goto_admin= undef; + $goto_secret= undef; + } + +} + +#=== FUNCTION ================================================================ +# NAME: get_interface_for_ip +# PARAMETERS: ip address (i.e. 192.168.0.1) +# RETURNS: array: list of interfaces if ip=0.0.0.0, matching interface if found, undef else +# DESCRIPTION: Uses proc fs (/proc/net/dev) to get list of interfaces. +#=============================================================================== +sub get_interface_for_ip { + my $result; + my $ip= shift; + if ($ip && length($ip) > 0) { + my @ifs= &get_interfaces(); + if($ip eq "0.0.0.0") { + $result = "all"; + } else { + foreach (@ifs) { + my $if=$_; + if(get_ip($if) eq $ip) { + $result = $if; + } + } + } + } + return $result; +} + +#=== FUNCTION ================================================================ +# NAME: get_interfaces +# PARAMETERS: none +# RETURNS: (list of interfaces) +# DESCRIPTION: Uses proc fs (/proc/net/dev) to get list of interfaces. +#=============================================================================== +sub get_interfaces { + my @result; + my $PROC_NET_DEV= ('/proc/net/dev'); + + open(PROC_NET_DEV, "<$PROC_NET_DEV") + or die "Could not open $PROC_NET_DEV"; + + my @ifs = ; + + close(PROC_NET_DEV); + + # Eat first two line + shift @ifs; + shift @ifs; + + chomp @ifs; + foreach my $line(@ifs) { + my $if= (split /:/, $line)[0]; + $if =~ s/^\s+//; + push @result, $if; + } + + return @result; +} + +#=== FUNCTION ================================================================ +# NAME: get_mac +# PARAMETERS: interface name (i.e. eth0) +# RETURNS: (mac address) +# DESCRIPTION: Uses ioctl to get mac address directly from system. +#=============================================================================== +sub get_mac { + my $ifreq= shift; + my $result; + if ($ifreq && length($ifreq) > 0) { + if($ifreq eq "all") { + $result = "00:00:00:00:00:00"; + } else { + my $SIOCGIFHWADDR= 0x8927; # man 2 ioctl_list + + # A configured MAC Address should always override a guessed value + if ($server_mac_address and length($server_mac_address) > 0) { + $result= $server_mac_address; + } + + socket SOCKET, PF_INET, SOCK_DGRAM, getprotobyname('ip') + or die "socket: $!"; + + if(ioctl SOCKET, $SIOCGIFHWADDR, $ifreq) { + my ($if, $mac)= unpack 'h36 H12', $ifreq; + + if (length($mac) > 0) { + $mac=~ m/^([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])$/; + $mac= sprintf("%s:%s:%s:%s:%s:%s", $1, $2, $3, $4, $5, $6); + $result = $mac; + } + } + } + } + return $result; +} + +#=== FUNCTION ================================================================ +# NAME: get_ip +# PARAMETERS: interface name (i.e. eth0) +# RETURNS: (ip address) +# DESCRIPTION: Uses ioctl to get ip address directly from system. +#=============================================================================== +sub get_ip { + my $ifreq= shift; + my $result= ""; + my $SIOCGIFADDR= 0x8915; # man 2 ioctl_list + my $proto= getprotobyname('ip'); + + socket SOCKET, PF_INET, SOCK_DGRAM, $proto + or die "socket: $!"; + + if(ioctl SOCKET, $SIOCGIFADDR, $ifreq) { + my ($if, $sin) = unpack 'a16 a16', $ifreq; + my ($port, $addr) = sockaddr_in $sin; + my $ip = inet_ntoa $addr; + + if ($ip && length($ip) > 0) { + $result = $ip; + } + } + + return $result; +} + + +#=== FUNCTION ================================================================ +# NAME: register_at_bus +# PARAMETERS: nothing +# RETURNS: nothing +# DESCRIPTION: creates an entry in known_daemons and send a 'here_i_am' msg to bus +#=============================================================================== +sub register_at_bus { + + # add bus to known_server_db + my $res = $main::known_server_db->add_dbentry( {table=>'known_server', + primkey=>'hostname', + hostname=>$bus_address, + status=>'bus', + hostkey=>$bus_passwd, + timestamp=>&get_time, + } ); + my $msg_hash = &create_xml_hash("here_i_am", $server_address, $bus_address); + my $answer = ""; + $answer = &send_msg_hash2address($msg_hash, $bus_address, $bus_passwd); + if ($answer == 0) { + &main::daemon_log("register at bus: $bus_address", 1); + } else { + &main::daemon_log("unable to send 'register'-msg to bus '$bus_address': $answer", 1); + } + return; +} + + +#=== FUNCTION ================================================================ +# NAME: process_incoming_msg +# PARAMETERS: crypted_msg - string - incoming crypted message +# RETURNS: nothing +# DESCRIPTION: handels the proceeded distribution to the appropriated functions +#=============================================================================== +sub process_incoming_msg { + my ($msg, $msg_hash) = @_ ; + my $error = 0; + my $host_name; + my $host_key; + my @out_msg_l; + + # process incoming msg + my $header = @{$msg_hash->{header}}[0]; + my $source = @{$msg_hash->{source}}[0]; + my @target_l = @{$msg_hash->{target}}; + + &main::daemon_log("SIPackages: msg to process: $header", 3); + &main::daemon_log("$msg", 8); + + if( 0 == length @target_l){ + &main::daemon_log("ERROR: no target specified for msg $header", 1); + $error++; + } + + 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( $error == 0) { + if( 0 == @out_msg_l ) { + push(@out_msg_l, $msg); + } + } + + return \@out_msg_l; +} + + +#=== FUNCTION ================================================================ +# NAME: got_ping +# PARAMETERS: msg_hash - hash - hash from function create_xml_hash +# RETURNS: nothing +# DESCRIPTION: process this incoming message +#=============================================================================== +sub got_ping { + my ($msg_hash) = @_; + + my $source = @{$msg_hash->{source}}[0]; + my $target = @{$msg_hash->{target}}[0]; + my $header = @{$msg_hash->{header}}[0]; + + if(exists $main::known_daemons->{$source}) { + &main::add_content2known_daemons(hostname=>$source, status=>$header); + } else { + &main::add_content2known_clients(hostname=>$source, status=>$header); + } + + return; +} + + +#=== FUNCTION ================================================================ +# NAME: new_passwd +# PARAMETERS: msg_hash - ref - hash from function create_xml_hash +# RETURNS: nothing +# DESCRIPTION: process this incoming message +#=============================================================================== +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]; + my $query_res; + + # check known_clients_db + my $sql_statement = "SELECT * FROM known_clients WHERE hostname='$source_name'"; + $query_res = $main::known_clients_db->select_dbentry( $sql_statement ); + if( 1 == keys %{$query_res} ) { + my $act_time = &get_time; + my $sql_statement= "UPDATE known_clients ". + "SET hostkey='$source_key', timestamp='$act_time' ". + "WHERE hostname='$source_name'"; + my $res = $main::known_clients_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); + } + + # 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); + } + } + + return @out_msg_l; +} + + +#=== FUNCTION ================================================================ +# NAME: here_i_am +# PARAMETERS: msg_hash - hash - hash from function create_xml_hash +# RETURNS: nothing +# DESCRIPTION: process this incoming message +#=============================================================================== +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]; + + # number of known clients + my $nu_clients= $main::known_clients_db->count_dbentries('known_clients'); + + # check wether client address or mac address is already known + my $sql_statement= "SELECT * FROM known_clients WHERE hostname='$source'"; + my $db_res= $main::known_clients_db->select_dbentry( $sql_statement ); + + if ( 1 == keys %{$db_res} ) { + &main::daemon_log("WARNING: $source is already known as a client", 1); + &main::daemon_log("WARNING: values for $source are being overwritten", 1); + $nu_clients --; + } + + # number of actual activ clients + my $act_nu_clients = $nu_clients; + + &main::daemon_log("number of actual activ clients: $act_nu_clients", 5); + &main::daemon_log("number of maximal allowed clients: $max_clients", 5); + + if($max_clients <= $act_nu_clients) { + my $out_hash = &create_xml_hash("denied", $server_address, $source); + &add_content2xml_hash($out_hash, "denied", "I_cannot_take_any_more_clients!"); + my $passwd = @{$msg_hash->{new_passwd}}[0]; + &send_msg_hash2address($out_hash, $source, $passwd); + return; + } + + # new client accepted + my $new_passwd = @{$msg_hash->{new_passwd}}[0]; + + # create entry in known_clients + my $events = @{$msg_hash->{events}}[0]; + + + # add entry to known_clients_db + my $res = $main::known_clients_db->add_dbentry( {table=>'known_clients', + primkey=>'hostname', + hostname=>$source, + events=>$events, + macaddress=>$mac_address, + status=>'registered', + hostkey=>$new_passwd, + timestamp=>&get_time, + } ); + + if ($res != 0) { + &main::daemon_log("ERROR: cannot add entry to known_clients: $res"); + return; + } + + # return acknowledgement to client + $out_hash = &create_xml_hash("registered", $server_address, $source); + my $register_out = &create_xml_string($out_hash); + push(@out_msg_l, $register_out); + + # notify registered client to bus + if( $bus_activ eq "on") { + # fetch actual bus key + my $sql_statement= "SELECT * FROM known_server WHERE status='bus'"; + my $query_res = $main::known_server_db->select_dbentry( $sql_statement ); + my $hostkey = $query_res->{1}->{'hostkey'}; + + # send update msg to bus + $out_hash = &create_xml_hash("new_client", $server_address, $bus_address, $source); + 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 + my $new_ldap_config_out = &new_ldap_config($source); + if( $new_ldap_config_out ) { + push(@out_msg_l, $new_ldap_config_out); + } + + + return @out_msg_l; +} + + +#=== FUNCTION ================================================================ +# NAME: who_has +# PARAMETERS: msg_hash - hash - hash from function create_xml_hash +# RETURNS: nothing +# DESCRIPTION: process this incoming message +#=============================================================================== +sub who_has { + my ($msg_hash) = @_ ; + + # what is your search pattern + my $search_pattern = @{$msg_hash->{who_has}}[0]; + my $search_element = @{$msg_hash->{$search_pattern}}[0]; + &main::daemon_log("who_has-msg looking for $search_pattern $search_element", 7); + + # scanning known_clients for search_pattern + my @host_addresses = keys %$main::known_clients; + my $known_clients_entries = length @host_addresses; + my $host_address; + foreach my $host (@host_addresses) { + my $client_element = $main::known_clients->{$host}->{$search_pattern}; + if ($search_element eq $client_element) { + $host_address = $host; + last; + } + } + + # search was successful + if (defined $host_address) { + my $source = @{$msg_hash->{source}}[0]; + my $out_msg = &create_xml_hash("who_has_i_do", $server_address, $source, "mac_address"); + &add_content2xml_hash($out_msg, "mac_address", $search_element); + &send_msg_hash2address($out_msg, $bus_address); + } + return; +} + + +sub who_has_i_do { + my ($msg_hash) = @_ ; + my $header = @{$msg_hash->{header}}[0]; + my $source = @{$msg_hash->{source}}[0]; + my $search_param = @{$msg_hash->{$header}}[0]; + my $search_value = @{$msg_hash->{$search_param}}[0]; + print "\ngot msg $header:\nserver $source has client with $search_param $search_value\n"; +} + + +#=== FUNCTION ================================================================ +# NAME: new_ldap_config +# PARAMETERS: address - string - ip address and port of a host +# RETURNS: nothing +# DESCRIPTION: send to address the ldap configuration found for dn gotoLdapServer +#=============================================================================== +sub new_ldap_config { + my ($address) = @_ ; + + my $sql_statement= "SELECT * FROM known_clients WHERE hostname='$address'"; + my $res = $main::known_clients_db->select_dbentry( $sql_statement ); + + # check hit + my $hit_counter = keys %{$res}; + if( not $hit_counter == 1 ) { + &main::daemon_log("ERROR: more or no hit found in known_clients_db by query by '$address'", 1); + } + + my $macaddress = $res->{1}->{macaddress}; + my $hostkey = $res->{1}->{hostkey}; + + if (not defined $macaddress) { + &main::daemon_log("ERROR: no mac address found for client $address", 1); + return; + } + + # Build LDAP connection + my $ldap = Net::LDAP->new($ldap_uri); + if( not defined $ldap ) { + &main::daemon_log("ERROR: cannot connect to ldap: $ldap_uri", 1); + return; + } + + + # Bind to a directory with dn and password + my $mesg= $ldap->bind($ldap_admin_dn, $ldap_admin_password); + + # Perform search + $mesg = $ldap->search( base => $ldap_base, + scope => 'sub', + attrs => ['dn', 'gotoLdapServer'], + filter => "(&(objectClass=GOhard)(macaddress=$macaddress))"); + $mesg->code && die $mesg->error; + + # Sanity check + if ($mesg->count != 1) { + &main::daemon_log("WARNING: client mac address $macaddress not found/not unique in ldap search", 1); + &main::daemon_log("\tbase: $ldap_base", 1); + &main::daemon_log("\tscope: sub", 1); + &main::daemon_log("\tattrs: dn, gotoLdapServer", 1); + &main::daemon_log("\tfilter: (&(objectClass=GOhard)(macaddress=$macaddress))", 1); + return; + } + + my $entry= $mesg->entry(0); + my $dn= $entry->dn; + my @servers= $entry->get_value("gotoLdapServer"); + my @ldap_uris; + my $server; + my $base; + + # Do we need to look at an object class? + if ($#servers < 1){ + $mesg = $ldap->search( base => $ldap_base, + scope => 'sub', + attrs => ['dn', 'gotoLdapServer'], + filter => "(&(objectClass=gosaGroupOfNames)(member=$dn))"); + $mesg->code && die $mesg->error; + + # Sanity check + if ($mesg->count != 1) { + &main::daemon_log("WARNING: no LDAP information found for client mac $macaddress", 1); + return; + } + + $entry= $mesg->entry(0); + $dn= $entry->dn; + @servers= $entry->get_value("gotoLdapServer"); + } + + @servers= sort (@servers); + + foreach $server (@servers){ + $base= $server; + $server =~ s%^[^:]+:[^:]+:(ldap.*://[^/]+)/.*$%$1%; + $base =~ s%^[^:]+:[^:]+:ldap.*://[^/]+/(.*)$%$1%; + push (@ldap_uris, $server); + } + + # Unbind + $mesg = $ldap->unbind; + + # Assemble data package + my %data = ( 'ldap_uri' => \@ldap_uris, 'ldap_base' => $base, + 'ldap_cfg' => \@ldap_cfg, 'pam_cfg' => \@pam_cfg,'nss_cfg' => \@nss_cfg ); + + # Need to append GOto settings? + if (defined $goto_admin and defined $goto_secret){ + $data{'goto_admin'}= $goto_admin; + $data{'goto_secret'}= $goto_secret; + } + + # Send information + send_msg("new_ldap_config", $server_address, $address, \%data, $hostkey); + + return; +} + + +#=== FUNCTION ================================================================ +# NAME: execute_actions +# PARAMETERS: msg_hash - hash - hash from function create_xml_hash +# RETURNS: nothing +# DESCRIPTION: invokes the script specified in msg_hash which is located under +# /etc/gosad/actions +#=============================================================================== +sub execute_actions { + my ($msg_hash) = @_ ; + my $configdir= '/etc/gosad/actions/'; + my $result; + + my $header = @{$msg_hash->{header}}[0]; + my $source = @{$msg_hash->{source}}[0]; + my $target = @{$msg_hash->{target}}[0]; + + if((not defined $source) + && (not defined $target) + && (not defined $header)) { + &main::daemon_log("ERROR: Entries missing in XML msg for gosad actions under /etc/gosad/actions"); + } else { + my $parameters=""; + my @params = @{$msg_hash->{$header}}; + my $params = join(", ", @params); + &main::daemon_log("execute_actions: got parameters: $params", 5); + + if (@params) { + foreach my $param (@params) { + my $param_value = (&get_content_from_xml_hash($msg_hash, $param))[0]; + &main::daemon_log("execute_actions: parameter -> value: $param -> $param_value", 7); + $parameters.= " ".$param_value; + } + } + + my $cmd= $configdir.$header."$parameters"; + &main::daemon_log("execute_actions: executing cmd: $cmd", 7); + $result= ""; + open(PIPE, "$cmd 2>&1 |"); + while() { + $result.=$_; + } + close(PIPE); + } + + # process the event result + + + return; +} + + +1; diff --git a/gosa-si/modules/ServerPackages.pm b/gosa-si/modules/ServerPackages.pm deleted file mode 100644 index c06aba4f0..000000000 --- a/gosa-si/modules/ServerPackages.pm +++ /dev/null @@ -1,845 +0,0 @@ -package ServerPackages; - -use Exporter; -@ISA = ("Exporter"); - -# Each module has to have a function 'process_incoming_msg'. This function works as a interface to gosa-sd and receives the msg hash from gosa-sd. 'process_incoming_function checks, wether it has a function to process the incoming msg and forward the msg to it. - - -use strict; -use warnings; -use GOSA::GosaSupportDaemon; -use IO::Socket::INET; -use XML::Simple; -use Data::Dumper; -use Net::LDAP; -use Socket qw/PF_INET SOCK_DGRAM inet_ntoa sockaddr_in/; - -BEGIN{} -END {} - -my ($known_clients_file_name); -my ($server_activ, $server_ip, $server_mac_address, $server_port, $server_passwd, $max_clients, $ldap_uri, $ldap_base, $ldap_admin_dn, $ldap_admin_password); -my ($bus_activ, $bus_passwd, $bus_ip, $bus_port); -my $server; -my $network_interface; -my $no_bus; -my (@ldap_cfg, @pam_cfg, @nss_cfg, $goto_admin, $goto_secret); - - -my %cfg_defaults = -( -"server" => - {"server_activ" => [\$server_activ, "on"], - "server_ip" => [\$server_ip, "0.0.0.0"], - "server_mac_address" => [\$server_mac_address, ""], - "server_port" => [\$server_port, "20081"], - "server_passwd" => [\$server_passwd, ""], - "max_clients" => [\$max_clients, 100], - "ldap_uri" => [\$ldap_uri, ""], - "ldap_base" => [\$ldap_base, ""], - "ldap_admin_dn" => [\$ldap_admin_dn, ""], - "ldap_admin_password" => [\$ldap_admin_password, ""], - }, -"bus" => - {"bus_activ" => [\$bus_activ, "on"], - "bus_passwd" => [\$bus_passwd, ""], - "bus_ip" => [\$bus_ip, ""], - "bus_port" => [\$bus_port, "20080"], - }, -); - -### START ##################################################################### - -# read configfile and import variables -&read_configfile(); - -# detect interfaces and mac address -$network_interface= &get_interface_for_ip($server_ip); -$server_mac_address= &get_mac($network_interface); - -# complete addresses -my $server_address = "$server_ip:$server_port"; -my $bus_address = "$bus_ip:$bus_port"; - -# create general settings for this module -my $xml = new XML::Simple(); - -# register at bus -if ($main::no_bus > 0) { - $bus_activ = "off" -} -if($bus_activ eq "on") { - ®ister_at_bus(); -} - -### functions ################################################################# - - -sub get_module_info { - my @info = ($server_address, - $server_passwd, - $server, - $server_activ, - "socket", - ); - return \@info; -} - - -#=== FUNCTION ================================================================ -# NAME: read_configfile -# PARAMETERS: cfg_file - string - -# RETURNS: nothing -# DESCRIPTION: read cfg_file and set variables -#=============================================================================== -sub read_configfile { - my $cfg; - if( defined( $main::cfg_file) && ( length($main::cfg_file) > 0 )) { - if( -r $main::cfg_file ) { - $cfg = Config::IniFiles->new( -file => $main::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] ); - } - } - - # Read non predefined sections - my $param; - if ($cfg->SectionExists('ldap')){ - foreach $param ($cfg->Parameters('ldap')){ - push (@ldap_cfg, "$param ".$cfg->val('ldap', $param)); - } - } - if ($cfg->SectionExists('pam_ldap')){ - foreach $param ($cfg->Parameters('pam_ldap')){ - push (@pam_cfg, "$param ".$cfg->val('pam_ldap', $param)); - } - } - if ($cfg->SectionExists('nss_ldap')){ - foreach $param ($cfg->Parameters('nss_ldap')){ - push (@nss_cfg, "$param ".$cfg->val('nss_ldap', $param)); - } - } - if ($cfg->SectionExists('goto')){ - $goto_admin= $cfg->val('goto', 'terminal_admin'); - $goto_secret= $cfg->val('goto', 'terminal_secret'); - } else { - $goto_admin= undef; - $goto_secret= undef; - } - -} - -#=== FUNCTION ================================================================ -# NAME: get_interface_for_ip -# PARAMETERS: ip address (i.e. 192.168.0.1) -# RETURNS: array: list of interfaces if ip=0.0.0.0, matching interface if found, undef else -# DESCRIPTION: Uses proc fs (/proc/net/dev) to get list of interfaces. -#=============================================================================== -sub get_interface_for_ip { - my $result; - my $ip= shift; - if ($ip && length($ip) > 0) { - my @ifs= &get_interfaces(); - if($ip eq "0.0.0.0") { - $result = "all"; - } else { - foreach (@ifs) { - my $if=$_; - if(get_ip($if) eq $ip) { - $result = $if; - } - } - } - } - return $result; -} - -#=== FUNCTION ================================================================ -# NAME: get_interfaces -# PARAMETERS: none -# RETURNS: (list of interfaces) -# DESCRIPTION: Uses proc fs (/proc/net/dev) to get list of interfaces. -#=============================================================================== -sub get_interfaces { - my @result; - my $PROC_NET_DEV= ('/proc/net/dev'); - - open(PROC_NET_DEV, "<$PROC_NET_DEV") - or die "Could not open $PROC_NET_DEV"; - - my @ifs = ; - - close(PROC_NET_DEV); - - # Eat first two line - shift @ifs; - shift @ifs; - - chomp @ifs; - foreach my $line(@ifs) { - my $if= (split /:/, $line)[0]; - $if =~ s/^\s+//; - push @result, $if; - } - - return @result; -} - -#=== FUNCTION ================================================================ -# NAME: get_mac -# PARAMETERS: interface name (i.e. eth0) -# RETURNS: (mac address) -# DESCRIPTION: Uses ioctl to get mac address directly from system. -#=============================================================================== -sub get_mac { - my $ifreq= shift; - my $result; - if ($ifreq && length($ifreq) > 0) { - if($ifreq eq "all") { - $result = "00:00:00:00:00:00"; - } else { - my $SIOCGIFHWADDR= 0x8927; # man 2 ioctl_list - - # A configured MAC Address should always override a guessed value - if ($server_mac_address and length($server_mac_address) > 0) { - $result= $server_mac_address; - } - - socket SOCKET, PF_INET, SOCK_DGRAM, getprotobyname('ip') - or die "socket: $!"; - - if(ioctl SOCKET, $SIOCGIFHWADDR, $ifreq) { - my ($if, $mac)= unpack 'h36 H12', $ifreq; - - if (length($mac) > 0) { - $mac=~ m/^([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])$/; - $mac= sprintf("%s:%s:%s:%s:%s:%s", $1, $2, $3, $4, $5, $6); - $result = $mac; - } - } - } - } - return $result; -} - -#=== FUNCTION ================================================================ -# NAME: get_ip -# PARAMETERS: interface name (i.e. eth0) -# RETURNS: (ip address) -# DESCRIPTION: Uses ioctl to get ip address directly from system. -#=============================================================================== -sub get_ip { - my $ifreq= shift; - my $result= ""; - my $SIOCGIFADDR= 0x8915; # man 2 ioctl_list - my $proto= getprotobyname('ip'); - - socket SOCKET, PF_INET, SOCK_DGRAM, $proto - or die "socket: $!"; - - if(ioctl SOCKET, $SIOCGIFADDR, $ifreq) { - my ($if, $sin) = unpack 'a16 a16', $ifreq; - my ($port, $addr) = sockaddr_in $sin; - my $ip = inet_ntoa $addr; - - if ($ip && length($ip) > 0) { - $result = $ip; - } - } - - return $result; -} - - -#=== FUNCTION ================================================================ -# NAME: register_at_bus -# PARAMETERS: nothing -# RETURNS: nothing -# DESCRIPTION: creates an entry in known_daemons and send a 'here_i_am' msg to bus -#=============================================================================== -sub register_at_bus { - - # add bus to known_server_db - my $res = $main::known_server_db->add_dbentry( {table=>'known_server', - primkey=>'hostname', - hostname=>$bus_address, - status=>'bus', - hostkey=>$bus_passwd, - timestamp=>&get_time, - } ); - my $msg_hash = &create_xml_hash("here_i_am", $server_address, $bus_address); - my $answer = ""; - $answer = &send_msg_hash2address($msg_hash, $bus_address, $bus_passwd); - if ($answer == 0) { - &main::daemon_log("register at bus: $bus_address", 1); - } else { - &main::daemon_log("unable to send 'register'-msg to bus '$bus_address': $answer", 1); - } - return; -} - -#=== FUNCTION ================================================================ -# NAME: process_incoming_msg -# PARAMETERS: crypted_msg - string - incoming crypted message -# RETURNS: nothing -# 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 $host_name; - my $host_key; - - # 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 ); - - 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; - } - } - } - - # 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( 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); - } - } - } - - } elsif ($len_targets > 1 ) { - # we have more than one target - # TODO to be implemented - } - - return ; -} - - -#=== FUNCTION ================================================================ -# NAME: got_ping -# PARAMETERS: msg_hash - hash - hash from function create_xml_hash -# RETURNS: nothing -# DESCRIPTION: process this incoming message -#=============================================================================== -sub got_ping { - my ($msg_hash) = @_; - - my $source = @{$msg_hash->{source}}[0]; - my $target = @{$msg_hash->{target}}[0]; - my $header = @{$msg_hash->{header}}[0]; - - if(exists $main::known_daemons->{$source}) { - &main::add_content2known_daemons(hostname=>$source, status=>$header); - } else { - &main::add_content2known_clients(hostname=>$source, status=>$header); - } - - return; -} - - -#=== FUNCTION ================================================================ -# NAME: new_passwd -# PARAMETERS: msg_hash - ref - hash from function create_xml_hash -# RETURNS: nothing -# DESCRIPTION: process this incoming message -#=============================================================================== -sub new_passwd { - my ($msg_hash) = @_; - - my $header = @{$msg_hash->{header}}[0]; - my $source_name = @{$msg_hash->{source}}[0]; - my $source_key = @{$msg_hash->{new_passwd}}[0]; - my $query_res; - - # check known_clients_db - my $sql_statement = "SELECT * FROM known_clients WHERE hostname='$source_name'"; - $query_res = $main::known_clients_db->select_dbentry( $sql_statement ); - if( 1 == keys %{$query_res} ) { - my $act_time = &get_time; - my $sql_statement= "UPDATE known_clients ". - "SET hostkey='$source_key', timestamp='$act_time' ". - "WHERE hostname='$source_name'"; - 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; - } - - # 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; - } - - &main::daemon_log("ERROR: $source_name not known for '$header'-msg", 1); - return; -} - - -#=== FUNCTION ================================================================ -# NAME: here_i_am -# PARAMETERS: msg_hash - hash - hash from function create_xml_hash -# RETURNS: nothing -# DESCRIPTION: process this incoming message -#=============================================================================== -sub here_i_am { - my ($msg_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'); - - # check wether client address or mac address is already known - my $sql_statement= "SELECT * FROM known_clients WHERE hostname='$source'"; - my $db_res= $main::known_clients_db->select_dbentry( $sql_statement ); - - if ( 1 == keys %{$db_res} ) { - &main::daemon_log("WARNING: $source is already known as a client", 1); - &main::daemon_log("WARNING: values for $source are being overwritten", 1); - $nu_clients --; - } - - # number of actual activ clients - my $act_nu_clients = $nu_clients; - - &main::daemon_log("number of actual activ clients: $act_nu_clients", 5); - &main::daemon_log("number of maximal allowed clients: $max_clients", 5); - - if($max_clients <= $act_nu_clients) { - my $out_hash = &create_xml_hash("denied", $server_address, $source); - &add_content2xml_hash($out_hash, "denied", "I_cannot_take_any_more_clients!"); - my $passwd = @{$msg_hash->{new_passwd}}[0]; - &send_msg_hash2address($out_hash, $source, $passwd); - return; - } - - # new client accepted - my $new_passwd = @{$msg_hash->{new_passwd}}[0]; - - # create entry in known_clients - my $events = @{$msg_hash->{events}}[0]; - - - # add entry to known_clients_db - my $res = $main::known_clients_db->add_dbentry( {table=>'known_clients', - primkey=>'hostname', - hostname=>$source, - events=>$events, - macaddress=>$mac_address, - status=>'registered', - hostkey=>$new_passwd, - timestamp=>&get_time, - } ); - - if ($res != 0) { - &main::daemon_log("ERROR: cannot add entry to known_clients: $res"); - return; - } - - # return acknowledgement to client - $out_hash = &create_xml_hash("registered", $server_address, $source); - &send_msg_hash2address($out_hash, $source, $new_passwd); - - # notify registered client to bus - if( $bus_activ eq "on") { - # fetch actual bus key - my $sql_statement= "SELECT * FROM known_server WHERE status='bus'"; - my $query_res = $main::known_server_db->select_dbentry( $sql_statement ); - my $hostkey = $query_res->{1}->{'hostkey'}; - - # 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); - - &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); - - return; -} - - -#=== FUNCTION ================================================================ -# NAME: who_has -# PARAMETERS: msg_hash - hash - hash from function create_xml_hash -# RETURNS: nothing -# DESCRIPTION: process this incoming message -#=============================================================================== -sub who_has { - my ($msg_hash) = @_ ; - - # what is your search pattern - my $search_pattern = @{$msg_hash->{who_has}}[0]; - my $search_element = @{$msg_hash->{$search_pattern}}[0]; - &main::daemon_log("who_has-msg looking for $search_pattern $search_element", 7); - - # scanning known_clients for search_pattern - my @host_addresses = keys %$main::known_clients; - my $known_clients_entries = length @host_addresses; - my $host_address; - foreach my $host (@host_addresses) { - my $client_element = $main::known_clients->{$host}->{$search_pattern}; - if ($search_element eq $client_element) { - $host_address = $host; - last; - } - } - - # search was successful - if (defined $host_address) { - my $source = @{$msg_hash->{source}}[0]; - my $out_msg = &create_xml_hash("who_has_i_do", $server_address, $source, "mac_address"); - &add_content2xml_hash($out_msg, "mac_address", $search_element); - &send_msg_hash2address($out_msg, $bus_address); - } - return; -} - - -sub who_has_i_do { - my ($msg_hash) = @_ ; - my $header = @{$msg_hash->{header}}[0]; - my $source = @{$msg_hash->{source}}[0]; - my $search_param = @{$msg_hash->{$header}}[0]; - my $search_value = @{$msg_hash->{$search_param}}[0]; - print "\ngot msg $header:\nserver $source has client with $search_param $search_value\n"; -} - - -#=== FUNCTION ================================================================ -# NAME: new_ldap_config -# PARAMETERS: address - string - ip address and port of a host -# RETURNS: nothing -# DESCRIPTION: send to address the ldap configuration found for dn gotoLdapServer -#=============================================================================== -sub new_ldap_config { - my ($address) = @_ ; - - my $sql_statement= "SELECT * FROM known_clients WHERE hostname='$address'"; - my $res = $main::known_clients_db->select_dbentry( $sql_statement ); - - # check hit - my $hit_counter = keys %{$res}; - if( not $hit_counter == 1 ) { - &main::daemon_log("ERROR: more or no hit found in known_clients_db by query by '$address'", 1); - } - - my $macaddress = $res->{1}->{macaddress}; - my $hostkey = $res->{1}->{hostkey}; - - if (not defined $macaddress) { - &main::daemon_log("ERROR: no mac address found for client $address", 1); - return; - } - - # Build LDAP connection - my $ldap = Net::LDAP->new($ldap_uri); - if( not defined $ldap ) { - &main::daemon_log("ERROR: cannot connect to ldap: $ldap_uri", 1); - return; - } - - - # Bind to a directory with dn and password - my $mesg= $ldap->bind($ldap_admin_dn, $ldap_admin_password); - - # Perform search - $mesg = $ldap->search( base => $ldap_base, - scope => 'sub', - attrs => ['dn', 'gotoLdapServer'], - filter => "(&(objectClass=GOhard)(macaddress=$macaddress))"); - $mesg->code && die $mesg->error; - - # Sanity check - if ($mesg->count != 1) { - &main::daemon_log("WARNING: client mac address $macaddress not found/not unique in ldap search", 1); - &main::daemon_log("\tbase: $ldap_base", 1); - &main::daemon_log("\tscope: sub", 1); - &main::daemon_log("\tattrs: dn, gotoLdapServer", 1); - &main::daemon_log("\tfilter: (&(objectClass=GOhard)(macaddress=$macaddress))", 1); - return; - } - - my $entry= $mesg->entry(0); - my $dn= $entry->dn; - my @servers= $entry->get_value("gotoLdapServer"); - my @ldap_uris; - my $server; - my $base; - - # Do we need to look at an object class? - if (length(@servers) < 1){ - $mesg = $ldap->search( base => $ldap_base, - scope => 'sub', - attrs => ['dn', 'gotoLdapServer'], - filter => "(&(objectClass=gosaGroupOfNames)(member=$dn))"); - $mesg->code && die $mesg->error; - - # Sanity check - if ($mesg->count != 1) { - &main::daemon_log("WARNING: no LDAP information found for client mac $macaddress", 1); - return; - } - - $entry= $mesg->entry(0); - $dn= $entry->dn; - @servers= $entry->get_value("gotoLdapServer"); - } - - @servers= sort (@servers); - - foreach $server (@servers){ - $base= $server; - $server =~ s%^[^:]+:[^:]+:(ldap.*://[^/]+)/.*$%$1%; - $base =~ s%^[^:]+:[^:]+:ldap.*://[^/]+/(.*)$%$1%; - push (@ldap_uris, $server); - } - - # Unbind - $mesg = $ldap->unbind; - - # Assemble data package - my %data = ( 'ldap_uri' => \@ldap_uris, 'ldap_base' => $base, - 'ldap_cfg' => \@ldap_cfg, 'pam_cfg' => \@pam_cfg,'nss_cfg' => \@nss_cfg ); - - # Need to append GOto settings? - if (defined $goto_admin and defined $goto_secret){ - $data{'goto_admin'}= $goto_admin; - $data{'goto_secret'}= $goto_secret; - } - - # Send information - send_msg("new_ldap_config", $server_address, $address, \%data, $hostkey); - - return; -} - - -#=== FUNCTION ================================================================ -# NAME: execute_actions -# PARAMETERS: msg_hash - hash - hash from function create_xml_hash -# RETURNS: nothing -# DESCRIPTION: invokes the script specified in msg_hash which is located under -# /etc/gosad/actions -#=============================================================================== -sub execute_actions { - my ($msg_hash) = @_ ; - my $configdir= '/etc/gosad/actions/'; - my $result; - - my $header = @{$msg_hash->{header}}[0]; - my $source = @{$msg_hash->{source}}[0]; - my $target = @{$msg_hash->{target}}[0]; - - if((not defined $source) - && (not defined $target) - && (not defined $header)) { - &main::daemon_log("ERROR: Entries missing in XML msg for gosad actions under /etc/gosad/actions"); - } else { - my $parameters=""; - my @params = @{$msg_hash->{$header}}; - my $params = join(", ", @params); - &main::daemon_log("execute_actions: got parameters: $params", 5); - - if (@params) { - foreach my $param (@params) { - my $param_value = (&get_content_from_xml_hash($msg_hash, $param))[0]; - &main::daemon_log("execute_actions: parameter -> value: $param -> $param_value", 7); - $parameters.= " ".$param_value; - } - } - - my $cmd= $configdir.$header."$parameters"; - &main::daemon_log("execute_actions: executing cmd: $cmd", 7); - $result= ""; - open(PIPE, "$cmd 2>&1 |"); - while() { - $result.=$_; - } - close(PIPE); - } - - # process the event result - - - return; -} - - -1; 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();