diff --git a/gosa-si/gosa-si-client b/gosa-si/gosa-si-client
index c8116dc938fb0ddbcbc106ac1e3b38e67f504823..c3608750a3458e474bd86618ef628b7a7bdce57b 100755 (executable)
--- a/gosa-si/gosa-si-client
+++ b/gosa-si/gosa-si-client
use Digest::MD5 qw(md5_hex md5 md5_base64);
use MIME::Base64;
use XML::Simple;
-use Net::DNS;
use File::Basename;
use File::Spec;
# Workaround: need pure perl to make it work with UTF-8 :-(
$XML::Simple::PREFERRED_PARSER= "XML::SAX::PurePerl";
+my $client_version = '$HeadURL$:$Rev$';
+my $client_headURL;
+my $client_revision;
+my $client_status;
my $event_dir = "/usr/lib/gosa-si/client/events";
use lib "/usr/lib/gosa-si/client/events";
my (%cfg_defaults, $foreground, $verbose, $pid_file, $procid, $pid, $log_file, $fai_logpath);
-my ($server_ip, $server_port, $server_key, $server_timeout, $server_domain, $server_key_lifetime);
-my ($client_ip, $client_port, $client_mac_address, $ldap_enabled, $ldap_config, $pam_config, $nss_config);
+my ($server_ip, $server_port, $server_timeout, $server_domain, $server_key_lifetime);
+my ($client_port, $ldap_enabled, $ldap_config, $pam_config, $nss_config);
my $xml;
-my $default_server_key;
my $event_hash;
+my $default_server_key;
my @servers;
my $gotoHardwareChecksum;
my $gosa_si_client_fifo;
$verbose= 1;
# globalise variables which are used in imported events
+our $global_kernel;
our $cfg_file;
our $opts_file;
our $server_address;
{"port" => [\$client_port, "20083"],
"ip" => [\$client_ip, "0.0.0.0"],
"mac-address" => [\$client_mac_address, "00:00:00:00:00:00"],
- "server-domain" => [\$server_domain, ""],
+ "server-domain" => [\$server_domain, ""],
"ldap" => [\$ldap_enabled, 1],
"ldap-config" => [\$ldap_config, "/etc/ldap/ldap.conf"],
"pam-config" => [\$pam_config, "/etc/pam_ldap.conf"],
"nss-config" => [\$nss_config, "/etc/libnss-ldap.conf"],
- "fai-logpath" => [\$fai_logpath, "/var/log/fai/fai.log"],
- "force-hostname" => [\$client_force_hostname, "false"],
+ "fai-logpath" => [\$fai_logpath, "/var/log/fai/fai.log"],
+ "force-hostname" => [\$client_force_hostname, "false"],
},
"server" => {
"ip" => [\$server_ip, "127.0.0.1"],
sub read_configfile {
my ($cfg_file, %cfg_defaults) = @_ ;
my $cfg;
- if( defined( $cfg_file) && ( length($cfg_file) > 0 )) {
+ if( defined( $cfg_file) && ( (-s $cfg_file) > 0 )) {
if( -r $cfg_file ) {
$cfg = Config::IniFiles->new( -file => $cfg_file );
} else {
foreach my $section (keys %cfg_defaults) {
foreach my $param (keys %{$cfg_defaults{ $section }}) {
my $pinfo = $cfg_defaults{ $section }{ $param };
- ${@$pinfo[ 0 ]} = (defined($cfg))?$cfg->val( $section, $param, @$pinfo[ 1 ] ):${@$pinfo[ 0 ]} = @$pinfo[ 1 ];
+ ${@$pinfo[ 0 ]} = $cfg->val( $section, $param, @$pinfo[ 1 ] );
}
}
}
# DESCRIPTION:
#===============================================================================
sub daemon_log {
- # log into log_file
+# log into log_file
my( $msg, $level ) = @_;
if(not defined $msg) { return }
if(not defined $level) { $level = 1 }
if(defined $log_file){
open(LOG_HANDLE, ">>$log_file");
+ chmod 0600, $log_file;
if(not defined open( LOG_HANDLE, ">>$log_file" )) {
print STDERR "cannot open $log_file: $!";
- return }
- chomp($msg);
- if($level <= $verbose){
- 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;
- my @monthnames = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
- $month = $monthnames[$month];
- $monthday = $monthday < 10 ? $monthday = "0".$monthday : $monthday;
- $year+=1900;
-
- my $log_msg = "$month $monthday $hours:$minutes:$seconds $prg $msg\n";
- print LOG_HANDLE $log_msg;
- if( $foreground ) {
- print STDERR $log_msg;
- }
+ return
+ }
+ chomp($msg);
+ if($level <= $verbose){
+ 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;
+ my @monthnames = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
+ $month = $monthnames[$month];
+ $monthday = $monthday < 10 ? $monthday = "0".$monthday : $monthday;
+ $year+=1900;
+
+ my $log_msg = "$month $monthday $hours:$minutes:$seconds $prg $msg\n";
+ print LOG_HANDLE $log_msg;
+ if( $foreground ) {
+ print STDERR $log_msg;
}
+ }
close( LOG_HANDLE );
}
}
-#=== 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 = <PROC_NET_DEV>;
-
- 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)
}
-#=== 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;
- last;
- }
- }
- }
- }
- 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: get_local_mac_for_remote_ip
my $result="0.0.0.0";
if($server_ip =~ /^(\d\d?\d?\.){3}\d\d?\d?$/) {
- if($server_ip eq "127.0.0.1") {
- $result="127.0.0.1";
- } else {
+ # client should always have a 'valid' ip-address, which is available from other hosts too,
+ # 127.0.0.1 says nothing to foreign host
+ #if($server_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")
last;
}
}
- }
+ #}
} else {
daemon_log("get_local_ip_for_remote_ip was called with a non-ip parameter: $server_ip", 1);
}
}
-sub create_passwd {
- my $new_passwd = "";
- for(my $i=0; $i<31; $i++) {
- $new_passwd .= ("a".."z","A".."Z",0..9)[int(rand(62))]
- }
-
- return $new_passwd;
-}
-
-
sub create_ciphering {
my ($passwd) = @_;
if((!defined($passwd)) || length($passwd)==0) {
}
-sub get_server_addresses {
- my $domain= shift;
- my @result;
-
- my $error = 0;
- my $res = Net::DNS::Resolver->new;
- my $query = $res->send("_gosa-si._tcp.".$domain, "SRV");
- my @hits;
-
- if ($query) {
- foreach my $rr ($query->answer) {
- push(@hits, $rr->target.":".$rr->port);
- }
- }
- else {
- #warn "query failed: ", $res->errorstring, "\n";
- $error++;
- }
-
- if( $error == 0 ) {
- foreach my $hit (@hits) {
- my ($hit_name, $hit_port) = split(/:/, $hit);
- chomp($hit_name);
- chomp($hit_port);
-
- my $address_query = $res->send($hit_name);
- if( 1 == length($address_query->answer) ) {
- foreach my $rr ($address_query->answer) {
- push(@result, $rr->address.":".$hit_port);
- }
- }
- }
- }
-
- return @result;
-}
-
-
#=== FUNCTION ================================================================
# NAME: send_msg_hash_to_target
# PARAMETERS: msg_hash - hash - xml_hash created with function create_xml_hash
# encrypt xml msg
my $crypted_msg = &encrypt_msg($msg, $encrypt_key);
- # xxxxxxxxxxxxxx
-
-
-
# opensocket
my $socket = &open_socket($address);
if( !$socket ) {
daemon_log("ERROR: cannot send ".$msg_header."msg to $address , host not reachable", 1);
+ if ($REGISTERED == 1) {
+ $REGISTERED = 0; # if server is not available, cause reregistering
+ daemon_log("INFO: cause reregistering at gosa-si-server", 5);
+ $global_kernel->yield('register_at_gosa_si_server');
+
+ }
$error++;
}
if( $error == 0 ) {
print $socket $crypted_msg."\n";
daemon_log("INFO: send ".$msg_header."msg to $address", 5);
- daemon_log("DEBUG: message:\n$msg", 8);
+ daemon_log("DEBUG: message:\n$msg", 9);
}
# close socket in any case
if(not defined $socket) {
return;
}
- &daemon_log("open_socket: $PeerAddr", 7);
+ &daemon_log("DEBUG: open_socket: $PeerAddr", 7);
return $socket;
}
my $events = join( ",", keys %{$event_hash} );
while(1) {
- # fetch first gosa-si-server from @servers
- my $server = shift(@servers);
-
- # append shifted gosa-si-server at the end of @servers, so looking for servers never stop if
- # a registration never occured
- push( @servers, $server );
+ $try_to_register++;
+
+ # after one complete round through all server, stop trying to register
+ if( $try_to_register > @servers ) { last; }
+
+ # fetch first gosa-si-server from @servers
+ # append shifted gosa-si-server at the end of @servers, so looking for servers never stop if
+ # a registration never occured
+ my $server = shift(@servers);
+ push( @servers, $server );
+
+ # Check if our ip is resolvable - if not: don't try to register
+ if(!(defined($server) && $server =~ m/^[0-9\.]*?:.*$/)) {
+ &main::daemon_log("ERROR: Server with address '".defined($server)?$server:""."' is invalid!", 1);
+ if (length(@servers) == 1) {
+ &main::daemon_log("ERROR: No valid servers found!", 1);
+ exit(1);
+ }
+ }
# Check if our ip is resolvable - if not: don't try to register
my $ip= &get_local_ip_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/));
my $dnsname= gethostbyaddr(inet_aton($ip), AF_INET);
if(!defined($dnsname)) {
- &write_to_file("goto-error-dns:$ip", $fai_logpath);
- exit(1);
+ if( defined($client_force_hostname) && $client_force_hostname eq "true") {
+ $dnsname = `hostname`;
+ } else {
+ &write_to_file("goto-error-dns:$ip", $fai_logpath);
+ exit(1);
+ }
}
# create registration msg
&add_content2xml_hash($register_hash, "new_passwd", $server_key);
&add_content2xml_hash($register_hash, "mac_address", $local_mac);
&add_content2xml_hash($register_hash, "events", $events);
+ &add_content2xml_hash($register_hash, "client_status", $client_status);
+ &add_content2xml_hash($register_hash, "client_revision", $client_revision);
&add_content2xml_hash($register_hash, "gotoHardwareChecksum", $gotoHardwareChecksum);
+ &add_content2xml_hash($register_hash, "key_lifetime", $server_key_lifetime);
# Add $HOSTNAME from ENV if force-hostname is set
if( defined($client_force_hostname) && $client_force_hostname eq "true") {
# send xml hash to server with general server passwd
my $res = &send_msg_hash_to_target($register_hash, $server, $default_server_key);
-
- if( $try_to_register >= @servers ) { last; }
# if delivery of registration msg succeed
- if($res == 0) {
+ if($res eq "0") {
# reset try_to_register
$try_to_register = 0;
# delivery of registration msg failed
} else {
- $try_to_register++;
# wait 1 sec until trying to register again
sleep(1);
next;
}
} # end of while
-
# one circle through all servers finished and no registration succeed
if ( $try_to_register >= @servers ) {
&write_to_file("gosa-si-no-server-available", $fai_logpath);
my $msg_hash;
eval{
$msg = &decrypt_msg($crypted_msg, $module_key);
- &main::daemon_log("decrypted_msg: \n$msg", 8);
+ &main::daemon_log("decrypted_msg: \n$msg", 9);
$msg_hash = $xml->XMLin($msg, ForceArray=>1);
}
-sub import_events {
-
- if (not -e $event_dir) {
- daemon_log("ERROR: cannot find directory or directory is not readable: $event_dir", 1);
- }
- opendir (DIR, $event_dir) or die "ERROR while loading gosa-si-events from directory $event_dir : $!\n";
-
- while (defined (my $event = readdir (DIR))) {
- if( $event eq "." || $event eq ".." ) { next; }
-
- eval{ require $event; };
- if( $@ ) {
- daemon_log("ERROR: import of event module '$event' failed", 1);
- daemon_log("$@", 1);
- next;
- }
-
- $event =~ /(\S*?).pm$/;
- my $event_module = $1;
- my $events_l = eval( $1."::get_events()") ;
- foreach my $event_name (@{$events_l}) {
- $event_hash->{$event_name} = $event_module;
- }
-
- }
-
- my @all_events = keys %$event_hash;
- my $all_events_string = join(", ", @all_events);
-
- daemon_log("INFO: imported events: $all_events_string", 5);
-}
-
sub trigger_new_key {
my ($kernel) = $_[KERNEL] ;
}
-#sub generic_file_reset {
-# my ( $heap, $wheel_id ) = @_[ HEAP, ARG0 ];
-#
-# my $service = $heap->{services}->{$wheel_id};
-# daemon_log("INFO: '$service' watching reset", 5);
-# return;
-#}
-
sub generic_file_error {
my ( $heap, $operation, $errno, $error_string, $wheel_id ) =
@_[ HEAP, ARG0, ARG1, ARG2, ARG3 ];
}
+sub sig_handler {
+ my ($kernel, $signal) = @_[KERNEL, ARG0] ;
+ daemon_log("0 INFO got signal '$signal'", 1);
+ $kernel->sig_handled();
+ return;
+}
+
+
sub _start {
my ($kernel, $heap) = @_[KERNEL, HEAP];
$kernel->alias_set('client_session');
-
+ $global_kernel = $kernel; # this is used to throw events at each point of the skript
+
+ $kernel->sig(USR1 => "sig_handler");
+
# force a registration at a gosa-si-server
$kernel->yield('register_at_gosa_si_server');
daemon_log("INFO: Incoming msg from '$remote_ip'", 5);
- daemon_log("DEBUG: Incoming msg:\n$input\n", 8);
+ daemon_log("DEBUG: Incoming msg:\n$input\n", 9);
my ($msg, $msg_hash) = &check_key_and_xml_validity($input, $server_key);
if( (!$msg) || (!$msg_hash) ) {
if( exists $event_hash->{$header} ) {
# a event exists with the header as name
- daemon_log("DEBUG: found event '$header' at event-module '".$event_hash->{$header}."'", 7);
+ daemon_log("INFO: found event '$header' at event-module '".$event_hash->{$header}."'", 5);
no strict 'refs';
$answer = &{$event_hash->{$header}."::$header"}($msg, $msg_hash);
}
else {
- daemon_log("WARNING: no event '$header' found in event modules under $event_dir", 1);
+ daemon_log("WARNING: no event '$header' found in event modules under $event_dir", 3);
}
}
$pid = fork;
setsid or die "Can't start a new session: $!";
umask 0;
-}
-else {
+} else {
$pid = $$;
}
};
}
+# parse head url and revision from svn
+my $client_status_hash = { 'developmental'=>'revision', 'stable'=>'release'};
+$client_version =~ /^\$HeadURL: (\S+) \$:\$Rev: (\d+) \$$/;
+$client_headURL = defined $1 ? $1 : 'unknown' ;
+$client_revision = defined $2 ? $2 : 'unknown' ;
+if ($client_headURL =~ /\/tag\// ||
+ $client_headURL =~ /\/branches\// ) {
+ $client_status = "stable";
+} else {
+ $client_status = "developmental" ;
+}
+
daemon_log(" ", 1);
daemon_log("$prg started!", 1);
+daemon_log("INFO: status: $client_status", 1);
+daemon_log("INFO: ".$client_status_hash->{$client_status}.": $client_revision", 1);
# delete old DBsqlite lock files
system('rm -f /tmp/gosa_si_lock*gosa-si-client*');
$client_address = $client_ip.":".$client_port;
my $network_interface= &get_interface_for_ip($client_ip);
$client_mac_address= &get_mac($network_interface);
-daemon_log("gosa-si-client ip address detected: $client_ip", 1);
-daemon_log("gosa-si-client mac address detected: $client_mac_address", 1);
+daemon_log("INFO: ip address detected: $client_ip", 1);
+daemon_log("INFO: gosa-si-client mac address detected: $client_mac_address", 1);
# import events
-&import_events();
+my ($error, $result, $tmp_hash) = &import_events($event_dir);
+$event_hash = $tmp_hash;
+
+foreach my $log_line (@$result) {
+ if ($log_line =~ / succeed: /) {
+ &main::daemon_log("0 DEBUG: $log_line", 7);
+ } else {
+ &main::daemon_log("0 ERROR: $log_line", 1);
+ }
+}
# compute hardware checksum
$gotoHardwareChecksum= &generate_hw_digest();
-daemon_log("gosa-si-client gotoHardwareChecksum detected: $gotoHardwareChecksum", 1);
+daemon_log("INFO: gotoHardwareChecksum detected: $gotoHardwareChecksum", 1);
# create socket for incoming xml messages
Port => $client_port,
ClientInput => \&server_input,
);
-daemon_log("start socket for incoming xml messages at port '$client_port' ", 1);
+daemon_log("INFO: start socket for incoming xml messages at port '$client_port' ", 1);
# prepare variables
if( inet_aton($server_ip) ){ $server_ip = inet_ntoa(inet_aton($server_ip)); }
-############################################################
-# to change
-if( $server_ip eq "127.0.1.1" ) { $server_ip = "127.0.0.1" }
-############################################################
if (defined $server_ip && defined $server_port) {
$server_address = $server_ip.":".$server_port;
}
inline_states => {
_start => \&_start,
_default => \&_default,
+ sig_handler => \&sig_handler,
register_at_gosa_si_server => \®ister_at_gosa_si_server,
# trigger periodical tasks