From 1b442ce10091bc59e11f55e7e1c8bcd6987a2bb9 Mon Sep 17 00:00:00 2001 From: rettenbe Date: Mon, 7 Jan 2008 10:54:00 +0000 Subject: [PATCH] add ldap interface in gosa-si/modules/GosaPackages.pm (query_jobdb) change known_clients storage from shared memory to sqlitedb git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@8233 594d385d-05f5-0310-b6e9-bd551577e9d8 --- gosa-si/gosa-si-server | 280 +++++++++++++++------------ gosa-si/modules/DBsqlite.pm | 99 +++++++--- gosa-si/modules/GosaPackages.pm | 142 ++++++++++---- gosa-si/modules/GosaSupportDaemon.pm | 53 +++-- gosa-si/modules/ServerPackages.pm | 78 +++++--- gosa-si/server.conf | 1 + gosa-si/tests/client.php | 7 +- 7 files changed, 414 insertions(+), 246 deletions(-) diff --git a/gosa-si/gosa-si-server b/gosa-si/gosa-si-server index 9ae65c92c..c60c5e288 100755 --- a/gosa-si/gosa-si-server +++ b/gosa-si/gosa-si-server @@ -8,7 +8,9 @@ # DESCRIPTION: # # OPTIONS: --- -# REQUIREMENTS: libconfig-inifiles-perl libcrypt-rijndael-perl libxml-simple-perl libipc-shareable-perl libdata-dumper-simple-perl +# REQUIREMENTS: libconfig-inifiles-perl libcrypt-rijndael-perl libxml-simple-perl +# libipc-shareable-perl libdata-dumper-simple-perl +# libdbd-sqlite3-perl libnet-ldap-perl # BUGS: --- # NOTES: # AUTHOR: (Andreas Rettenberger), @@ -48,7 +50,7 @@ my (%cfg_defaults, $foreground, $verbose, $ping_timeout); my ($bus, $msg_to_bus, $bus_cipher); my ($server, $server_mac_address, $server_events); my ($gosa_server, $job_queue_timeout, $job_queue_table_name, $job_queue_file_name); -my ($known_daemons, $shmda, $known_clients, $shmcl, $known_modules); +my ($known_daemons, $shmda, $known_clients, $shmcl, $known_modules, $known_clients_file_name, $known_server_file_name, $known_clients_db, $known_server_db); my ($max_clients); my ($pid_file, $procid, $pid, $log_file); my (%free_child, %busy_child, $child_max, $child_min, %child_alive_time, $child_timeout); @@ -87,9 +89,11 @@ $no_bus = 0; $no_arp = 0; # name of table for storing gosa jobs -$job_queue_table_name = 'jobs'; +our $job_queue_table_name = 'jobs'; +our $job_db; # holds all other gosa-sd as well as the gosa-sd-bus +our $known_server; our $known_daemons = {}; our $shmda = tie($known_daemons, 'IPC::Shareable', undef, {create => 1, exclusive => 1, @@ -97,12 +101,13 @@ our $shmda = tie($known_daemons, 'IPC::Shareable', undef, {create => 1, destroy => 1, }); # holds all registrated clients -our $known_clients = {}; -our $shmcl = tie($known_clients, 'IPC::Shareable', undef, {create => 1, - exclusive => 1, - mode => 0666, - destroy => 1, - }); +our $known_clients; +#our $known_clients = {}; +#our $shmcl = tie($known_clients, 'IPC::Shareable', undef, {create => 1, +# exclusive => 1, +# mode => 0666, +# destroy => 1, +# }); %cfg_defaults = @@ -114,6 +119,8 @@ our $shmcl = tie($known_clients, 'IPC::Shareable', undef, {create => 1, "child_timeout" => [\$child_timeout, 180], "job_queue_timeout" => [\$job_queue_timeout, undef], "job_queue_file_name" => [\$job_queue_file_name, '/var/lib/gosa-si/jobs.db'], + "known_clients_file_name" => [\$known_clients_file_name, '/var/lib/gosa-si/known_clients.db' ], + "known_server_file_name" => [\$known_server_file_name, '/var/lib/gosa-si/kown_server.db'], }, "bus" => {"bus_activ" => [\$bus_activ, "on"], @@ -514,10 +521,12 @@ sub get_processing_child { my $answer; my %act_modules = %$known_modules; while( my ($module, $info) = each(%act_modules)) { + &daemon_log("##########", 5); my $tmp = &{ $module."::process_incoming_msg" }($msg); if (defined $tmp) { $answer = $tmp; } + &daemon_log("##########", 5); } #&print_known_daemons(); @@ -737,31 +746,31 @@ sub update_known_daemons { # RETURNS: nothing # DESCRIPTION: nomen est omen #=============================================================================== -sub print_known_clients { - - print "####################################\n"; - print "# status of known_clients\n"; - $shmcl->shlock(LOCK_EX); - my @hosts = keys %$known_clients; - if (@hosts) { - foreach my $host (@hosts) { - my $status = $known_clients->{$host}->{status} ; - my $passwd = $known_clients->{$host}->{passwd}; - my $timestamp = $known_clients->{$host}->{timestamp}; - my $mac_address = $known_clients->{$host}->{mac_address}; - my $events = $known_clients->{$host}->{events}; - print "$host\n"; - print "\tstatus: $status\n"; - print "\tpasswd: $passwd\n"; - print "\ttimestamp: $timestamp\n"; - print "\tmac_address: $mac_address\n"; - print "\tevents: $events\n"; - } - } - $shmcl->shunlock(LOCK_EX); - print "####################################\n"; - return; -} +#sub print_known_clients { +# +# print "####################################\n"; +# print "# status of known_clients\n"; +# $shmcl->shlock(LOCK_EX); +# my @hosts = keys %$known_clients; +# if (@hosts) { +# foreach my $host (@hosts) { +# my $status = $known_clients->{$host}->{status} ; +# my $passwd = $known_clients->{$host}->{passwd}; +# my $timestamp = $known_clients->{$host}->{timestamp}; +# my $mac_address = $known_clients->{$host}->{mac_address}; +# my $events = $known_clients->{$host}->{events}; +# print "$host\n"; +# print "\tstatus: $status\n"; +# print "\tpasswd: $passwd\n"; +# print "\ttimestamp: $timestamp\n"; +# print "\tmac_address: $mac_address\n"; +# print "\tevents: $events\n"; +# } +# } +# $shmcl->shunlock(LOCK_EX); +# print "####################################\n"; +# return; +#} #=== FUNCTION ================================================================ @@ -772,14 +781,28 @@ sub print_known_clients { #=============================================================================== sub create_known_client { my ($hostname) = @_; - $shmcl->shlock(LOCK_EX); - $known_clients->{$hostname} = {}; - $known_clients->{$hostname}->{status} = "none"; - $known_clients->{$hostname}->{passwd} = "none"; - $known_clients->{$hostname}->{timestamp} = "none"; - $known_clients->{$hostname}->{mac_address} = "none"; - $known_clients->{$hostname}->{events} = "none"; - $shmcl->shunlock(LOCK_EX); + + 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); + } + +# $shmcl->shlock(LOCK_EX); +# $known_clients->{$hostname} = {}; +# $known_clients->{$hostname}->{status} = "none"; +# $known_clients->{$hostname}->{passwd} = "none"; +# $known_clients->{$hostname}->{timestamp} = "none"; +# $known_clients->{$hostname}->{mac_address} = "none"; +# $known_clients->{$hostname}->{events} = "none"; +# $shmcl->shunlock(LOCK_EX); return; } @@ -795,16 +818,17 @@ sub create_known_client { # RETURNS: nothing # DESCRIPTION: nome est omen and updates each time the timestamp of hostname #=============================================================================== -sub add_content2known_clients { +sub update_known_clients { my $arg = { - hostname => undef, status => undef, passwd => undef, - mac_address => undef, events => undef, + hostname => undef, status => undef, hostkey => undef, + macaddress => undef, events => undef, timestamp=>undef, @_ }; my $hostname = $arg->{hostname}; my $status = $arg->{status}; - my $passwd = $arg->{passwd}; - my $mac_address = $arg->{mac_address}; + my $hostkey = $arg->{hostkey}; + my $macaddress = $arg->{macaddress}; my $events = $arg->{events}; + my $timestamp = $arg->{timestamp}; if (not defined $hostname) { daemon_log("ERROR: function add_content2known_clients is not invoked with requiered parameter 'hostname'", 1); @@ -821,22 +845,27 @@ sub add_content2known_clients { $monthday = $monthday < 10 ? $monthday = "0".$monthday : $monthday; $year+=1900; my $t = "$year$month$monthday$hours$minutes$seconds"; - - $shmcl->shlock(LOCK_EX); + + my $change_entry = { table=>'known_clients', + where=>'hostname', + timestamp=>$t, + }; + + if (defined $status) { - $known_clients->{$hostname}->{status} = $status; + $change_entry->{status} = $status; } - if (defined $passwd) { - $known_clients->{$hostname}->{passwd} = $passwd; + if (defined $hostkey) { + $change_entry->{hostkey} = $hostkey; } - if (defined $mac_address) { - $known_clients->{$hostname}->{mac_address} = $mac_address; + if (defined $macaddress) { + $change_entry->{macaddress} = $macaddress; } if (defined $events) { - $known_clients->{$hostname}->{events} = $events; + $change_entry->{events} = $events; } - $known_clients->{$hostname}->{timestamp} = $t; - $shmcl->shlock(LOCK_EX); + + $known_clients->change_dbentry($change_entry); return; } @@ -875,50 +904,48 @@ sub clean_up_known_clients { # RETURNS: nothing # DESCRIPTION: nome est omen and updates each time the timestamp of hostname #=============================================================================== -sub update_known_clients { - my $arg = { - hostname => undef, status => undef, passwd => undef, - mac_address => undef, events => undef, - @_ }; - my $hostname = $arg->{hostname}; - my $status = $arg->{status}; - my $passwd = $arg->{passwd}; - my $mac_address = $arg->{mac_address}; - my $events = $arg->{events}; - - if (not defined $hostname) { - daemon_log("ERROR: function add_content2known_daemons is not invoked with requiered parameter 'hostname'", 1); - return; - } - - 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; - my $t = "$year$month$monthday$hours$minutes$seconds"; - - $shmcl->shlock(LOCK_EX); - if (defined $status) { - $known_clients->{$hostname}->{status} = $status; - } - if (defined $passwd) { - $known_clients->{$hostname}->{passwd} = $passwd; - } - if (defined $mac_address) { - $known_clients->{$hostname}->{mac_address} = $mac_address; - } - if (defined $events) { - $known_clients->{$hostname}->{events} = $events; - } - $known_clients->{$hostname}->{timestamp} = $t; - $shmcl->shunlock(LOCK_EX); - return; -} +#sub update_known_clients { +# my $arg = { +# hostname => undef, status => undef, passwd => undef, +# mac_address => undef, events => undef, +# @_ }; +# my $hostname = $arg->{hostname}; +# my $status = $arg->{status}; +# my $passwd = $arg->{passwd}; +# my $mac_address = $arg->{mac_address}; +# my $events = $arg->{events}; +# +# if (not defined $hostname) { +# daemon_log("ERROR: function add_content2known_daemons is not invoked with requiered parameter 'hostname'", 1); +# return; +# } +# +# 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; +# my $t = "$year$month$monthday$hours$minutes$seconds"; +# +# if (defined $status) { +# $known_clients->{$hostname}->{status} = $status; +# } +# if (defined $passwd) { +# $known_clients->{$hostname}->{passwd} = $passwd; +# } +# if (defined $mac_address) { +# $known_clients->{$hostname}->{mac_address} = $mac_address; +# } +# if (defined $events) { +# $known_clients->{$hostname}->{events} = $events; +# } +# $known_clients_db->{$hostname}->{timestamp} = $t; +# return; +#} @@ -962,14 +989,21 @@ close( LOCK_FILE ); if( !$foreground ) { exit( 0 ) }; } +# connect to gosa-si job queue +my @job_col_names = ("timestamp", "status", "result", "header", "target", "xmlmessage", "macaddress"); +$job_db = GOSA::DBsqlite->new($job_queue_file_name); +$job_db->create_table('jobs', \@job_col_names); + +# connect to known_clients_db +my @clients_col_names = ('hostname', 'status', 'hostkey', 'timestamp', 'macaddress', 'events'); +$known_clients_db = GOSA::DBsqlite->new($known_clients_file_name); +$known_clients_db->create_table('known_clients', \@clients_col_names); + # import all modules &import_modules; # check wether all modules are gosa-si valid passwd check -# connect to gosa-si job queue -my $job_db = GOSA::DBsqlite->new($job_queue_file_name); - # create reading and writing vectors my $rbits = my $wbits = my $ebits = ""; @@ -1130,23 +1164,17 @@ while(1) { my $timestamp = "$year$month$monthday$hours$minutes$seconds"; - my $sql = "SELECT * FROM '$job_queue_table_name' WHERE status='waiting' AND timestamp<'$timestamp'"; - my $res = $job_db->exec_statement($sql); - foreach my $msg (@{$res}) { - - my $jobdb_id = @{$msg}[0]; - my $job_msg_hash = &transform_msg2hash(@{$msg}[6]); + #my $res = $job_db->select_dbentry( { table=>$job_queue_table_name, status=>'waiting', timestamp=>'$timestamp'} ); + my $res = $job_db->select_dbentry( { table=>$job_queue_table_name, status=>'waiting', timestamp=>'2007010709014800'} ); + while( my ($id, $hit) = each %{$res} ) { + + my $jobdb_id = $hit->{ROWID}; + my $macaddress = $hit->{macaddress}; + my $job_msg_hash = &transform_msg2hash($hit->{xmlmessage}); my $out_msg_hash = $job_msg_hash; - - # hole mac address und suche die entsprechende ip addresse - my $target; - my @hostnames = keys %{$known_clients}; - foreach my $hostname (@hostnames) { - if ($known_clients->{$hostname}->{mac_address} eq $job_msg_hash->{mac}[0]) { - $target = $hostname; - last; - } - } + my $res_hash = $known_clients_db->select_dbentry( {table=>'known_clients', macaddress=>$macaddress} ); + # expect macaddress is unique!!!!!! + my $target = $res_hash->{1}->{hostname}; if (not defined $target) { &daemon_log("ERROR: no host found for mac address: $job_msg_hash->{mac}[0]", 1); @@ -1167,16 +1195,16 @@ while(1) { # add sqlite_id &add_content2xml_hash($out_msg_hash, "jobdb_id", $jobdb_id); -# my $out_msg = &create_xml_string($out_msg_hash); -# -# # encrypt msg as a GosaPackage module -# my $cipher = &create_ciphering($gosa_passwd); -# my $crypted_out_msg = &encrypt_msg($out_msg, $cipher); + my $out_msg = &create_xml_string($out_msg_hash); + + # encrypt msg as a GosaPackage module + my $cipher = &create_ciphering($gosa_passwd); + my $crypted_out_msg = &encrypt_msg($out_msg, $cipher); my $error = &send_msg_hash2address($out_msg_hash, "$gosa_ip:$gosa_port", $gosa_passwd); if ($error == 0) { - my $sql = "UPDATE '$job_queue_table_name' SET status='processing', target='$target' WHERE id='$jobdb_id'"; + my $sql = "UPDATE '$job_queue_table_name' SET status='processing', target='$target' WHERE ROWID='$jobdb_id'"; my $res = $job_db->exec_statement($sql); } diff --git a/gosa-si/modules/DBsqlite.pm b/gosa-si/modules/DBsqlite.pm index 46d13beaa..76014acde 100644 --- a/gosa-si/modules/DBsqlite.pm +++ b/gosa-si/modules/DBsqlite.pm @@ -25,7 +25,9 @@ sub create_table { my $object = shift; my $table_name = shift; my $col_names_ref = shift; - my $sql_statement = "CREATE TABLE IF NOT EXISTS $table_name (".join(', ', @{$col_names_ref}).")"; +# unshift(@{$col_names_ref}, "id INTEGER PRIMARY KEY AUTOINCREMENT"); + my $col_names_string = join(', ', @{$col_names_ref}); + my $sql_statement = "CREATE TABLE IF NOT EXISTS $table_name ( $col_names_string )"; $object->{dbh}->do($sql_statement); return 0; } @@ -42,50 +44,58 @@ sub add_dbentry { if (not defined $table) { return 1; } - - # incrementing running id - if (not exists $arg->{id}) { - my $max_id = @{@{$obj->{dbh}->selectall_arrayref("SELECT MAX(id) FROM $table")}[0]}[0]; - if (not defined $max_id) { - $max_id = 0; + + # specify primary key in table + my $primkey = $arg->{primkey}; + + # check wether value to primary key is specified + if ( ( defined $primkey ) && ( not $arg->{ $primkey } ) ) { + return 2; + } + + # check wether primkey is unique in table, otherwise return errorflag 3 + if ( defined $primkey ) { + my $res = @{ $obj->{dbh}->selectall_arrayref( "SELECT * FROM $table WHERE $primkey='$arg->{$primkey}'") }; + if ($res != 0) { + return 3; } - $arg->{id} = $max_id + 1; } - - + # fetch column names of table my $col_names = $obj->get_table_columns($table); # assign values to column name variables my @add_list; foreach my $col_name (@{$col_names}) { + # use function parameter for column values if (exists $arg->{$col_name}) { push(@add_list, $arg->{$col_name}); - } else { - my $default_val = "none"; - if ($col_name eq "timestamp") { - $default_val = "19700101000000"; - } - push(@add_list, $default_val); } - + # use default values for column values +# } else { +# my $default_val = "none"; +# if ($col_name eq "timestamp") { +# $default_val = "19700101000000"; +# } +# push(@add_list, $default_val); +# } } - # check wether id does not exists in table, otherwise return errorflag 2 - my $res = @{$obj->{dbh}->selectall_arrayref( "SELECT * FROM $table WHERE id='$arg->{id}'")}; - if ($res != 0) { - return 2; - } - - my $sql_statement = " INSERT INTO $table VALUES ('".join("', '", @add_list)."') "; + my $sql_statement = " INSERT INTO $table VALUES ('".join("', '", @add_list)."')"; print " INSERT INTO $table VALUES ('".join("', '", @add_list)."')\n"; $obj->{dbh}->do($sql_statement); - return 0; } -sub change_dbentry { + +# error-flags +# 1 no table ($table) defined +# 2 no restriction parameter ($restric_pram) defined +# 3 no restriction value ($restric_val) defined +# 4 column name not known in table +# 5 no column names to change specified +sub update_dbentry { my $obj = shift; my $arg = shift; @@ -134,7 +144,7 @@ sub change_dbentry { push(@change_list, "$pram='$val'"); } - if (not@change_list) { + if (not @change_list) { return 5; } @@ -210,13 +220,38 @@ sub select_dbentry { # collect select statements my @select_list; - my $sql_part; + my $sql_statement; while (my ($pram, $val) = each %{$arg}) { - push(@select_list, "$pram = '$val'"); + if ( $pram eq 'timestamp' ) { + push(@select_list, "$pram < '$val'"); + } else { + push(@select_list, "$pram = '$val'"); + } + + } + if (@select_list == 0) { + $sql_statement = "SELECT ROWID, * FROM '$table'"; + } else { + $sql_statement = "SELECT ROWID, * FROM '$table' WHERE ".join(' AND ', @select_list); } + + # query db + my $query_answer = $obj->{dbh}->selectall_arrayref($sql_statement); + + # fetch column list of db and create a hash with column_name->column_value of the select query + my $column_list = &get_table_columns($obj, $table); + my $list_len = @{ $column_list } ; + my $answer = {}; + my $hit_counter = 0; + - my $sql_statement = "SELECT * FROM 'jobs' WHERE ".join(' AND ', @select_list); - my $answer = $obj->{dbh}->selectall_arrayref($sql_statement); + foreach my $hit ( @{ $query_answer }) { + $hit_counter++; + $answer->{ $hit_counter }->{ 'ROWID' } = shift @{ $hit }; + for ( my $i = 0; $i < $list_len; $i++) { + $answer->{ $hit_counter }->{ @{ $column_list }[$i] } = @{ $hit }[$i]; + } + } return $answer; } @@ -224,7 +259,7 @@ sub select_dbentry { sub show_table { my $obj = shift; my $table_name = shift; - my @res = @{$obj->{dbh}->selectall_arrayref( "SELECT * FROM $table_name")}; + my @res = @{$obj->{dbh}->selectall_arrayref( "SELECT ROWID, * FROM $table_name")}; my @answer; foreach my $hit (@res) { push(@answer, "hit: ".join(', ', @{$hit})); diff --git a/gosa-si/modules/GosaPackages.pm b/gosa-si/modules/GosaPackages.pm index d6eb36525..a441a2fe1 100644 --- a/gosa-si/modules/GosaPackages.pm +++ b/gosa-si/modules/GosaPackages.pm @@ -9,21 +9,19 @@ use GOSA::GosaSupportDaemon; use IO::Socket::INET; use XML::Simple; use File::Spec; +use Data::Dumper; use GOSA::DBsqlite; +use MIME::Base64; BEGIN{} END{} -my ($server_activ, $server_port, $server_passwd, $max_clients); +my ($server_activ, $server_port, $server_passwd, $max_clients, $server_event_dir); my ($bus_activ, $bus_passwd, $bus_ip, $bus_port); my ($gosa_activ, $gosa_ip, $gosa_port, $gosa_passwd); my ($job_queue_timeout, $job_queue_file_name); my $gosa_server; -my $event_dir = "/etc/gosa-si/server/events"; - -# name of table for storing gosa jobs -my $job_queue_table_name = 'jobs'; my %cfg_defaults = ("general" => @@ -34,6 +32,7 @@ my %cfg_defaults = "server_port" => [\$server_port, "20081"], "server_passwd" => [\$server_passwd, ""], "max_clients" => [\$max_clients, 100], + "server_event_dir" => [\$server_event_dir, '/usr/lib/gosa-si/server/events'], }, "bus" => {"bus_activ" => [\$bus_activ, "on"], @@ -50,7 +49,7 @@ my %cfg_defaults = ); -### START ########################## +## START ########################## # read configfile and import variables &read_configfile(); @@ -88,12 +87,12 @@ my @col_names = ("id", "timestamp", "status", "result", "header", "target", "xml", "mac"); my $table_name = "jobs"; my $sqlite = GOSA::DBsqlite->new($job_queue_file_name); -$sqlite->create_table($table_name, \@col_names); +#$sqlite->create_table($table_name, \@col_names); -### FUNCTIONS ################################################################# +## FUNCTIONS ################################################################# sub get_module_info { my @info = ($gosa_address, @@ -195,29 +194,25 @@ sub process_incoming_msg { if(not defined $crypted_msg) { &main::daemon_log("function 'process_incoming_msg': got no msg", 7); } -# &main::daemon_log("GosaPackages: crypted_msg:$crypted_msg", 7); -# &main::daemon_log("GosaPackages: crypted_msg len:".length($crypted_msg), 7); + &main::daemon_log("GosaPackages: incoming msg: \n$crypted_msg", 7); $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); - &main::daemon_log("GosaPackages: crypted_msg:$crypted_msg", 7); -# &main::daemon_log("GosaPackages: crypted_msg len:".length($crypted_msg), 7); - - # 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: $msg", 7); + &main::daemon_log("GosaPackages: decrypted_msg: \n$msg", 7); $msg_hash = $xml->XMLin($msg, ForceArray=>1); }; @@ -241,15 +236,14 @@ sub process_incoming_msg { &main::daemon_log("ERROR: $header is not a valid GosaPackage-header, need a 'job_' or a 'gosa_' prefix"); } - if (not defined $out_msg) { return; } if ($out_msg =~ /(\d*?)<\/jobdb_id>/) { my $job_id = $1; - my $sql = "UPDATE '$job_queue_table_name' SET status='done', result='$out_msg' WHERE id='$job_id'"; - my $res = $sqlite->exec_statement($sql); + 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 { @@ -266,31 +260,35 @@ sub process_gosa_msg { $header =~ s/gosa_//; &main::daemon_log("GosaPackages: got a gosa msg $header", 5); - # fetch all available eventhandler under $event_dir - opendir (DIR, $event_dir) or &main::daemon_log("ERROR cannot open $event_dir: $!\n", 1) and return; - while (defined (my $file = readdir (DIR))) { - if (not $file eq $header) { - next; - } - # try to deliver incoming msg to eventhandler - - my $cmd = File::Spec->join($event_dir, $header)." '$msg'"; - &main::daemon_log("GosaPackages: execute event_handler $header", 3); - &main::daemon_log("GosaPackages: cmd: $cmd", 7); - - $out_msg = ""; - open(PIPE, "$cmd 2>&1 |"); - while() { - $out_msg.=$_; + # decide wether msg is a core function or a event handler + if ( $header eq 'query_jobdb') { $out_msg = &query_jobdb } + else { + # msg could not be assigned to core function + # fetch all available eventhandler under $server_event_dir + opendir (DIR, $server_event_dir) or &main::daemon_log("ERROR cannot open $server_event_dir: $!\n", 1) and return; + while (defined (my $file = readdir (DIR))) { + if (not $file eq $header) { + next; + } + # 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); + + $out_msg = ""; + open(PIPE, "$cmd 2>&1 |"); + while() { + $out_msg.=$_; + } + close(PIPE); + &main::daemon_log("GosaPackages: answer of cmd: $out_msg", 5); + last; } - close(PIPE); - &main::daemon_log("GosaPackages: answer of cmd: $out_msg", 5); - last; } # if delivery not possible raise error and return if (not defined $out_msg) { - &main::daemon_log("ERROR: GosaPackages: no event_handler defined for $header", 1); + &main::daemon_log("ERROR: GosaPackages: no event handler or core function defined for $header", 1); } elsif ($out_msg eq "") { &main::daemon_log("ERROR: GosaPackages got not answer from event_handler $header", 1); } @@ -310,16 +308,16 @@ sub process_job_msg { my $target = 'not known until now'; # add job to job queue - my $func_dic = {table=>$table_name, + my $func_dic = {table=>$main::job_queue_table_name, timestamp=>@{$msg_hash->{timestamp}}[0], status=>'waiting', result=>'none', header=>$header, target=>$target, - xml=>$msg, - mac=>@{$msg_hash->{mac}}[0], + xmlmessage=>$msg, + macaddress=>@{$msg_hash->{mac}}[0], }; - my $res = $sqlite->add_dbentry($func_dic); + my $res = $main::job_db->add_dbentry($func_dic); if (not $res == 0) { &main::daemon_log("ERROR: GosaPackages: process_job_msg: $res", 1); } @@ -329,5 +327,65 @@ sub process_job_msg { } + +sub db_res_2_xml { + my ($db_res) = @_ ; + my $xml = ""; + + while ( my ($hit, $hash) = each %{ $db_res } ) { + $xml .= "<$hit>"; + + while ( my ($column_name, $column_value) = each %{$hash} ) { + $xml .= "<$column_name>"; + my $xml_content = $column_value; + if( $column_name eq "xml" ) { + $xml_content = &encode_base64($column_value); + } + $xml .= $xml_content; + $xml .= ""; + } + + $xml .= ""; + } + + $xml .= ""; + return $xml; +} + + +## CORE FUNCTIONS ############################################################ + +sub query_jobdb { + my ($msg) = @_; + my $msg_hash = &transform_msg2hash($msg); + + # prepare query sql statement + my @where = @{$msg_hash->{where}}; + my $where_hash = {table=>$main::job_queue_table_name }; + foreach my $where_pram (@where) { + my $where_val = @{$msg_hash->{$where_pram}}[0]; + if (defined $where_val) { + $where_hash->{$where_pram} = $where_val; + } + } + + # execute db query + my $res_hash = $main::job_db->select_dbentry($where_hash); + + my $out_xml = &db_res_2_xml($res_hash); + return $out_xml; +} + + + 1; + + + + + + + + + diff --git a/gosa-si/modules/GosaSupportDaemon.pm b/gosa-si/modules/GosaSupportDaemon.pm index bc5458af4..670bb8e27 100644 --- a/gosa-si/modules/GosaSupportDaemon.pm +++ b/gosa-si/modules/GosaSupportDaemon.pm @@ -2,7 +2,7 @@ package GOSA::GosaSupportDaemon; use Exporter; @ISA = qw(Exporter); -@EXPORT = qw(create_xml_hash send_msg_hash2address get_content_from_xml_hash add_content2xml_hash create_xml_string encrypt_msg decrypt_msg create_ciphering transform_msg2hash send_msg); +@EXPORT = qw(create_xml_hash send_msg_hash2address get_content_from_xml_hash add_content2xml_hash create_xml_string encrypt_msg decrypt_msg create_ciphering transform_msg2hash get_time send_msg); use strict; use warnings; @@ -22,7 +22,6 @@ END {} my $xml = new XML::Simple(); - sub process_incoming_msg { return; } @@ -100,7 +99,6 @@ sub create_xml_hash { sub transform_msg2hash { my ($msg) = @_ ; - my $hash = $xml->XMLin($msg, ForceArray=>1); return $hash; } @@ -148,18 +146,18 @@ sub send_msg_hash2address { daemon_log("cannot send '$header'-msg to $address , server not reachable", 5); - if (exists $main::known_clients->{$address}) { - if ($main::known_clients->{$address}->{status} eq "down") { - # if status of not reachable client is already 'down', - # then delete client from known_clients - &clean_up_known_clients($address); - - } else { - # update status to 'down' - &update_known_clients(hostname=>$address, status=>"down"); - - } - } +# if (exists $main::known_clients->{$address}) { +# if ($main::known_clients->{$address}->{status} eq "down") { +# # if status of not reachable client is already 'down', +# # then delete client from known_clients +# &clean_up_known_clients($address); +# +# } else { +# # update status to 'down' +# &update_known_clients(hostname=>$address, status=>"down"); +# +# } +# } return 1; } @@ -176,11 +174,11 @@ sub send_msg_hash2address { #daemon_log("\t$crypted_msg", 7); # update status of client in known_clients with last send msg - if(exists $main::known_daemons->{$address}) { - #&update_known_daemons(); - } elsif(exists $main::known_clients->{$address}) { - &main::update_known_clients(hostname=>$address, status=>$header); - } +# if(exists $main::known_daemons->{$address}) { +# #&update_known_daemons(); +# } elsif(exists $main::known_clients->{$address}) { +# &main::update_known_clients(hostname=>$address, status=>$header); +# } return 0; } @@ -320,6 +318,21 @@ sub open_socket { } +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: send_msg # DESCRIPTION: Send a message to a destination diff --git a/gosa-si/modules/ServerPackages.pm b/gosa-si/modules/ServerPackages.pm index 846eed111..e810ffb0e 100644 --- a/gosa-si/modules/ServerPackages.pm +++ b/gosa-si/modules/ServerPackages.pm @@ -11,20 +11,25 @@ use warnings; use GOSA::GosaSupportDaemon; use IO::Socket::INET; use XML::Simple; +use Data::Dumper; use Net::LDAP; BEGIN{} END {} - +my ($known_clients_file_name); my ($server_activ, $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 $no_bus; my (@ldap_cfg, @pam_cfg, @nss_cfg, $goto_admin, $goto_secret); + my %cfg_defaults = -("server" => +("general" => + {"known_clients_file_name" => [\$known_clients_file_name, '/var/lib/gosa-si/known_clients.db' ], + }, +"server" => {"server_activ" => [\$server_activ, "on"], "server_port" => [\$server_port, "20081"], "server_passwd" => [\$server_passwd, ""], @@ -78,6 +83,10 @@ if($server_activ eq "on"){ } } +# connect to known_clients_db +my $known_clients_db = GOSA::DBsqlite->new($known_clients_file_name); + + # register at bus if ($main::no_bus > 0) { $bus_activ = "off" @@ -251,6 +260,8 @@ sub process_incoming_msg { &main::daemon_log("function 'process_incoming_msg': got no msg", 7); } + &main::daemon_log("ServerPackages: incoming msg: \n$crypted_msg", 7); + $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); @@ -291,7 +302,7 @@ sub process_incoming_msg { &main::daemon_log("ServerPackage: key_passwd: $key_passwd", 7); my $key_cipher = &create_ciphering($key_passwd); $msg = &decrypt_msg($crypted_msg, $key_cipher); - &main::daemon_log("ServerPackages: decrypted msg: $msg", 7); + &main::daemon_log("ServerPackages: decrypted msg: \n$msg", 7); $msg_hash = $xml->XMLin($msg, ForceArray=>1); #my $tmp = printf Dumper $msg_hash; #&main::daemon_log("DEBUG: ServerPackages: xml hash: $tmp", 7); @@ -315,12 +326,7 @@ sub process_incoming_msg { my $source = @{$msg_hash->{source}}[0]; &main::daemon_log("recieve '$header' at ServerPackages from $host", 1); -# &main::daemon_log("ServerPackages: msg from host:", 5); -# &main::daemon_log("\t$host", 5); -# &main::daemon_log("ServerPackages: header from msg:", 5); -# &main::daemon_log("\t$header", 5); - &main::daemon_log("ServerPackages: msg to process:", 5); - &main::daemon_log("\t$msg", 5); + &main::daemon_log("ServerPackages: msg to process: \n$msg", 5); my @targets = @{$msg_hash->{target}}; my $len_targets = @targets; @@ -331,11 +337,14 @@ sub process_incoming_msg { # we have only one target symbol my $target = $targets[0]; - &main::daemon_log("SeverPackages: msg is for:", 7); - &main::daemon_log("\t$target", 7); + &main::daemon_log("SeverPackages: msg is for: $target", 7); + # msg is for server if ($target eq $server_address) { - # msg is for server + + # msg is a event + + # msg is a hard implemented function 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) } @@ -346,18 +355,17 @@ sub process_incoming_msg { else { &main::daemon_log("ERROR: ServerPackages: no function assigned to this msg", 5) } + # msg is for all clients } elsif ($target eq "*") { - # msg is for all clients - my @target_addresses = keys(%$main::known_clients); foreach my $target_address (@target_addresses) { if ($target_address eq $source) { next; } $msg_hash->{target} = [$target_address]; &send_msg_hash2address($msg_hash, $target_address); - } + } + + # msg is for one host } else { - # msg is for one host - if (exists $main::known_clients->{$target}) { &send_msg_hash2address($msg_hash, $target); } elsif (exists $main::known_daemons->{$target}) { @@ -439,7 +447,7 @@ sub here_i_am { my $out_hash; # number of known clients - my $nu_clients = keys %$main::known_clients; + my $nu_clients = keys %{$known_clients_db->select_dbentry( {table=>'known_clients'} )}; # check wether client address or mac address is already known if (exists $main::known_clients->{$source}) { @@ -467,17 +475,39 @@ sub here_i_am { # create known_daemons entry my $events = @{$msg_hash->{events}}[0]; - &main::create_known_client($source); - &main::add_content2known_clients(hostname=>$source, events=>$events, mac_address=>$mac_address, - status=>"registered", passwd=>$new_passwd); - + + # add entry to known_clients_db + my $res = $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 == 3) { + $res = $known_clients_db->update_dbentry( {table=>'known_clients', + where=>'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); + &send_msg_hash2address($out_hash, $source, $new_passwd); # notify registered client to bus $out_hash = &create_xml_hash("new_client", $server_address, $bus_address, $source); - #&main::send_msg_hash2bus($out_hash); &send_msg_hash2address($out_hash, $bus_address); # give the new client his ldap config diff --git a/gosa-si/server.conf b/gosa-si/server.conf index 97047ce41..3386c00a6 100644 --- a/gosa-si/server.conf +++ b/gosa-si/server.conf @@ -17,6 +17,7 @@ server_activ = on server_port = 20081 server_passwd = secret-server-password max_clients = 5 +server_event_dir = /usr/lib/gosa-si/server/events [arp] arp_activ = off diff --git a/gosa-si/tests/client.php b/gosa-si/tests/client.php index 12f33c642..30c39b9d6 100755 --- a/gosa-si/tests/client.php +++ b/gosa-si/tests/client.php @@ -12,9 +12,12 @@ if($sock->connected()){ /* Prepare a hunge bunch of data to be send */ #$data = "
gosa_ping
10.89.1.155:2008211:22:33:44:55
"; #$data = "
job_ping
10.89.1.155:2008300:1B:77:04:8A:6C 19700101000000
"; - $data = "
job_ping
10.89.1.155:2008300:1B:77:04:8A:6C 20080102133900
"; + #$data = "
job_sayHello
10.89.1.155:2008300:1B:77:04:8A:6C 20130102133900
"; + #$data = "
job_ping
10.89.1.155:2008300:1B:77:04:8A:6C 20130102133900
"; + $data = "
gosa_query_jobdb
statuswaiting
"; $sock->write($data); - + + #$sock->setEncryptionKey("ferdinand_frost"); $answer = $sock->read(); -- 2.30.2