diff --git a/gosa-si/gosa-si-server b/gosa-si/gosa-si-server
index 7cf1e482d307108fe919e1603d5e4ce2a022f256..99e02fdb491627812c2f21e8471a5d669134226b 100755 (executable)
--- a/gosa-si/gosa-si-server
+++ b/gosa-si/gosa-si-server
use Net::LDAP;
use Net::LDAP::Util qw(:escape);
use Time::HiRes qw( usleep);
-use DateTime;
my $modules_path = "/usr/lib/gosa-si/modules";
use lib "/usr/lib/gosa-si/modules";
$wake_on_lan_passwd, $job_synchronization, $modified_jobs_loop_delay,
$arp_enabled, $arp_interface,
$opsi_enabled, $opsi_server, $opsi_admin, $opsi_password,
+ $new_systems_ou,
);
# additional variable which should be globaly accessable
our $known_server_db;
our $known_server_tn = "known_server";
my $known_server_file_name;
-my @known_server_col_names = ("hostname", "status", "hostkey", "loaded_modules", "timestamp");
+my @known_server_col_names = ("hostname", "macaddress", "status", "hostkey", "loaded_modules", "timestamp");
# holds all registrated clients
our $known_clients_db;
our $opsi_client;
our $opsi_url;
+# Lifetime of logged in user information. If no update information comes after n seconds,
+# the user is expeceted to be no longer logged in or the host is no longer running. Because
+# of this, the user is deleted from login_users_db
+our $logged_in_user_date_of_expiry = 600;
%cfg_defaults = (
"job-queue-loop-delay" => [\$job_queue_loop_delay, 3],
"messaging-db-loop-delay" => [\$messaging_db_loop_delay, 3],
"key" => [\$GosaPackages_key, "none"],
+ "new-systems-ou" => [\$new_systems_ou, 'ou=workstations,ou=systems'],
},
"ClientPackages" => {
"key" => [\$ClientPackages_key, "none"],
+ "user-date-of-expiry" => [\$logged_in_user_date_of_expiry, 600],
},
"ServerPackages"=> {
"address" => [\$foreign_server_string, ""],
}
-sub get_local_ip_for_remote_ip {
- my $remote_ip= shift;
- my $result="0.0.0.0";
-
- if($remote_ip =~ /^(\d\d?\d?\.){3}\d\d?\d?$/) {
- if($remote_ip eq "127.0.0.1") {
- $result = "127.0.0.1";
- } else {
- my $PROC_NET_ROUTE= ('/proc/net/route');
-
- open(PROC_NET_ROUTE, "<$PROC_NET_ROUTE")
- or die "Could not open $PROC_NET_ROUTE";
-
- my @ifs = <PROC_NET_ROUTE>;
-
- close(PROC_NET_ROUTE);
-
- # Eat header line
- shift @ifs;
- chomp @ifs;
- foreach my $line(@ifs) {
- my ($Iface,$Destination,$Gateway,$Flags,$RefCnt,$Use,$Metric,$Mask,$MTU,$Window,$IRTT)=split(/\s/, $line);
- my $destination;
- my $mask;
- my ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Destination);
- $destination= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
- ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Mask);
- $mask= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
- if(new NetAddr::IP($remote_ip)->within(new NetAddr::IP($destination, $mask))) {
- # destination matches route, save mac and exit
- $result= &get_ip($Iface);
- last;
- }
- }
- }
- } else {
- daemon_log("0 WARNING: get_local_ip_for_remote_ip() was called with a non-ip parameter: '$remote_ip'", 1);
- }
- return $result;
-}
+#sub get_local_ip_for_remote_ip {
+# my $remote_ip= shift;
+# my $result="0.0.0.0";
+#
+# if($remote_ip =~ /^(\d\d?\d?\.){3}\d\d?\d?$/) {
+# if($remote_ip eq "127.0.0.1") {
+# $result = "127.0.0.1";
+# } else {
+# my $PROC_NET_ROUTE= ('/proc/net/route');
+#
+# open(PROC_NET_ROUTE, "<$PROC_NET_ROUTE")
+# or die "Could not open $PROC_NET_ROUTE";
+#
+# my @ifs = <PROC_NET_ROUTE>;
+#
+# close(PROC_NET_ROUTE);
+#
+# # Eat header line
+# shift @ifs;
+# chomp @ifs;
+# foreach my $line(@ifs) {
+# my ($Iface,$Destination,$Gateway,$Flags,$RefCnt,$Use,$Metric,$Mask,$MTU,$Window,$IRTT)=split(/\s/, $line);
+# my $destination;
+# my $mask;
+# my ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Destination);
+# $destination= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
+# ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Mask);
+# $mask= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
+# if(new NetAddr::IP($remote_ip)->within(new NetAddr::IP($destination, $mask))) {
+# # destination matches route, save mac and exit
+# $result= &get_ip($Iface);
+# last;
+# }
+# }
+# }
+# } else {
+# daemon_log("0 WARNING: get_local_ip_for_remote_ip() was called with a non-ip parameter: '$remote_ip'", 1);
+# }
+# return $result;
+#}
sub send_msg_to_target {
my $not_found_in_known_server_db = 0;
my $not_found_in_foreign_clients_db = 0;
my $local_address;
+ my $local_mac;
my ($target_ip, $target_port) = split(':', $target);
+
+ # Determine the local ip address if target is an ip address
if ($target =~ /^\d+\.\d+\.\d+\.\d+:\d+$/) {
$local_address = &get_local_ip_for_remote_ip($target_ip).":$server_port";
} else {
$local_address = $server_address;
}
+ # Determine the local mac address if target is a mac address
+ if ($target =~ /^([0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2})$/i) {
+ my $loc_ip = &get_local_ip_for_remote_ip($heap->{'remote_ip'});
+ my $network_interface= &get_interface_for_ip($loc_ip);
+ $local_mac = &get_mac_for_interface($network_interface);
+ } else {
+ $local_mac = $server_mac_address;
+ }
+
# target and source is equal to GOSA -> process here
if (not $done) {
if ($target eq "GOSA" && $source eq "GOSA") {
# target is own address without forward_to_gosa-tag -> process here
if (not $done) {
+ #if ((($target eq $local_address) || ($target eq $local_mac) ) && (not exists $msg_hash->{'forward_to_gosa'})) {
if (($target eq $local_address) && (not exists $msg_hash->{'forward_to_gosa'})) {
$done = 1;
if ($source eq "GOSA") {
$done = 1;
my $hostname = $res->{1}->{'hostname'};
$msg =~ s/<target>$target<\/target>/<target>$hostname<\/target>/;
- #print STDERR "target is a client address in known_clients -> process here\n";
+ #print STDERR "target is a client address in known_clients -> process here\n";
my $local_address = &get_local_ip_for_remote_ip($target_ip).":$server_port";
if ($source eq "GOSA") {
$msg =~ s/<\/xml>/<forward_to_gosa>$local_address,$session_id<\/forward_to_gosa><\/xml>/;
# target is a server address -> forward to server
if (not $done) {
- $sql = "SELECT * FROM $known_server_tn WHERE hostname='$target'";
+ $sql = "SELECT * FROM $known_server_tn WHERE (hostname='$target' OR macaddress LIKE '$target')";
$res = $known_server_db->select_dbentry($sql);
if (keys(%$res) > 0) {
my $hostkey = $res->{1}->{'hostkey'};
&send_msg_to_target($msg, $target, $hostkey, $header, $session_id);
$done = 1;
- #print STDERR "target is a server address -> forward to server\n";
} else {
$not_found_in_known_server_db = 1;
}
# Skip new jobs for host if there is a processing job
if(defined($res) and defined @{$res}[0]) {
+ # Prevent race condition if there is a trigger_activate job waiting and a goto-activation job processing
+ if(@{$res}[5] eq 'trigger_action_reinstall') {
+ my $sql_statement_2 = "SELECT * FROM $job_queue_tn WHERE macaddress LIKE '$macaddress' AND status='waiting' AND headertag = 'trigger_activate_new'";
+ my $res_2 = $job_db->exec_statement( $sql_statement_2 );
+ if(defined($res_2) and defined @{$res}[0]) {
+ # Set status from goto-activation to 'waiting' and update timestamp
+ $job_db->exec_statement = "UPDATE $job_queue_tn SET status='waiting' WHERE macaddress LIKE '$macaddress' AND headertag = 'trigger_action_reinstall'";
+ $job_db->exec_statement = "UPDATE $job_queue_tn SET timestamp='".&get_time(30)."' WHERE macaddress LIKE '$macaddress' AND headertag = 'trigger_action_reinstall'";
+ }
+ }
next;
}
my $send_succeed = 0;
foreach my $hit (@$res) {
my $receiver_host = @$hit[0];
+ my $delivered2host = 0;
&daemon_log("M DEBUG: user '$receiver' is logged in at host '$receiver_host'", 7);
- # fetch key to encrypt msg propperly for usr/host
+ # Looking for host in know_clients_db
my $sql = "SELECT * FROM $known_clients_tn WHERE (hostname='$receiver_host')";
- &daemon_log("0 DEBUG: $sql", 7);
my $res = $known_clients_db->exec_statement($sql);
- # host is already down
- if (not ref(@$res[0]) eq "ARRAY") { next; }
+ # Host is known in known_clients_db
+ if (ref(@$res[0]) eq "ARRAY") {
+ my $receiver_key = @{@{$res}[0]}[2];
+ my %data = ('subject' => $subject, 'message' => $message, 'usr' => $receiver);
+ my $out_msg = &build_msg("usr_msg", $server_address, $receiver_host, \%data );
+ my $error = &send_msg_to_target($out_msg, $receiver_host, $receiver_key, "usr_msg", 0);
+ if ($error == 0 ) {
+ $send_succeed++ ;
+ $delivered2host++ ;
+ &daemon_log("M DEBUG: send message for user '$receiver' to host '$receiver_host'", 7);
+ } else {
+ &daemon_log("M DEBUG: cannot send message for user '$receiver' to host '$receiver_host'", 7);
+ }
+ }
+
+ # Message already send, do not need to do anything more, otherwise ...
+ if ($delivered2host) { next;}
+
+ # ...looking for host in foreign_clients_db
+ $sql = "SELECT * FROM $foreign_clients_tn WHERE (hostname='$receiver_host')";
+ $res = $foreign_clients_db->exec_statement($sql);
+
+ # Host is known in foreign_clients_db
+ if (ref(@$res[0]) eq "ARRAY") {
+ my $registration_server = @{@{$res}[0]}[2];
+
+ # Fetch encryption key for registration server
+ my $sql = "SELECT * FROM $known_server_tn WHERE (hostname='$registration_server')";
+ my $res = $known_server_db->exec_statement($sql);
+ if (ref(@$res[0]) eq "ARRAY") {
+ my $registration_server_key = @{@{$res}[0]}[3];
+ my %data = ('subject' => $subject, 'message' => $message, 'usr' => $receiver);
+ my $out_msg = &build_msg("usr_msg", $server_address, $receiver_host, \%data );
+ my $error = &send_msg_to_target($out_msg, $registration_server, $registration_server_key, "usr_msg", 0);
+ if ($error == 0 ) {
+ $send_succeed++ ;
+ $delivered2host++ ;
+ &daemon_log("M DEBUG: send message for user '$receiver' to server '$registration_server'", 7);
+ } else {
+ &daemon_log("M ERROR: cannot send message for user '$receiver' to server '$registration_server'", 1);
+ }
- # host is on
- my $receiver_key = @{@{$res}[0]}[2];
- my %data = ('subject' => $subject, 'message' => $message, 'usr' => $receiver);
- my $out_msg = &build_msg("usr_msg", $server_address, $receiver_host, \%data );
- my $error = &send_msg_to_target($out_msg, $receiver_host, $receiver_key, "usr_msg", 0);
- if ($error == 0 ) {
- $send_succeed++ ;
- }
+ } else {
+ &daemon_log("M ERROR: host '$receiver_host' is reported to be ".
+ "registrated at server '$registration_server', ".
+ "but no data available in known_server_db ", 1);
+ }
+ }
+
+ if (not $delivered2host) {
+ &daemon_log("M ERROR: unable to send user message to host '$receiver_host'", 1);
+ }
}
if ($send_succeed) {
# set outgoing msg at db to deliverd
my $sql = "UPDATE $messaging_tn SET flag='d' WHERE (id='$msg_id' AND direction='out' AND message_to='$receiver')";
- &daemon_log("0 DEBUG: $sql", 7);
my $res = $messaging_db->exec_statement($sql);
- }
+ &daemon_log("M INFO: send message for user '$receiver' to logged in hosts", 5);
+ } else {
+ &daemon_log("M WARNING: failed to deliver message for user '$receiver'", 3);
+ }
}
$kernel->delay_set('watch_for_delivery_messages', $messaging_db_loop_delay);
&add_content2xml_hash($myhash, 'key', $hostkey);
map(&add_content2xml_hash($myhash, 'client', @{$_}[0].",".@{$_}[4]), @$client_res);
+ # add locally loaded gosa-si modules to registration message
my $loaded_modules = {};
while (my ($package, $pck_info) = each %$known_modules) {
- foreach my $act_module (keys(%{@$pck_info[2]})) {
- $loaded_modules->{$act_module} = "";
- }
+ next if ((!defined(@$pck_info[2])) || (!(ref (@$pck_info[2]) eq 'HASH')));
+ foreach my $act_module (keys(%{@$pck_info[2]})) {
+ $loaded_modules->{$act_module} = "";
+ }
}
+
map(&add_content2xml_hash($myhash, "loaded_modules", $_), keys(%$loaded_modules));
+
+ # add macaddress to registration message
+ my ($host_ip, $host_port) = split(/:/, $hostname);
+ my $local_ip = &get_local_ip_for_remote_ip($host_ip);
+ my $network_interface= &get_interface_for_ip($local_ip);
+ my $host_mac = &get_mac_for_interface($network_interface);
+ &add_content2xml_hash($myhash, 'macaddress', $host_mac);
# build registration message and send it
my $foreign_server_msg = &create_xml_string($myhash);
my $res = $known_server_db->add_dbentry( {table=>$known_server_tn,
primkey=>['hostname'],
hostname=>$foreign_server,
+ macaddress=>"",
status=>'not_jet_registered',
hostkey=>"none",
+ loaded_modules => "none",
timestamp=>$act_timestamp,
} );
}