From: rettenbe Date: Fri, 1 Feb 2008 10:06:17 +0000 (+0000) Subject: ---uncomplete--- new version of gosa-si-client POE based X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=ec9b22290ff2a8e6c38ddf4dc0932ede601bc64f;p=gosa.git ---uncomplete--- new version of gosa-si-client POE based git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@8711 594d385d-05f5-0310-b6e9-bd551577e9d8 --- diff --git a/gosa-si/new-gosa-si-client b/gosa-si/new-gosa-si-client new file mode 100755 index 000000000..8ad3f26e2 --- /dev/null +++ b/gosa-si/new-gosa-si-client @@ -0,0 +1,924 @@ +#!/usr/bin/perl +#=============================================================================== +# +# FILE: gosa-server +# +# USAGE: gosa-si-client +# +# DESCRIPTION: +# +# OPTIONS: --- +# REQUIREMENTS: libnetaddr-ip-perl +# BUGS: --- +# NOTES: +# AUTHOR: (Andreas Rettenberger), +# COMPANY: +# VERSION: 1.0 +# CREATED: 12.09.2007 08:54:41 CEST +# REVISION: --- +#=============================================================================== + +use strict; +use warnings; +use Getopt::Long; +use Config::IniFiles; +use POSIX; + +use POE qw(Component::Server::TCP); +use IO::Socket::INET; +use NetAddr::IP; +use Data::Dumper; +use Crypt::Rijndael; +use GOSA::GosaSupportDaemon; +use Digest::MD5 qw(md5_hex); +use MIME::Base64; +use XML::Simple; +#use Fcntl; +#use Sys::Syslog qw( :DEFAULT setlogsock); +#use File::Spec; +#use Cwd; + +my $event_dir = "/usr/lib/gosa-si/client/events"; +use lib "/usr/lib/gosa-si/client/events"; + + + +my ($cfg_file, %cfg_defaults, $foreground, $verbose, $pid_file, $procid, $pid, $log_file); +my ($server_ip, $server_port, $server_key, $server_timeout, $server_domain); +my ($client_ip, $client_port, $ldap_enabled, $ldap_config, $pam_config, $nss_config); + +# default variables +my $server_address; +my @servers; +my $client_address; +my $client_mac_address; +my $xml; +my $default_server_key; +my $event_hash; + +%cfg_defaults = ( +"general" => + {"log_file" => [\$log_file, "/var/run/".$0.".log"], + "pid_file" => [\$pid_file, "/var/run/".$0.".pid"], + }, +"client" => + {"client_port" => [\$client_port, "20083"], + "client_ip" => [\$client_ip, "0.0.0.0"], + "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"], + }, +"server" => + {"server_ip" => [\$server_ip, "127.0.0.1"], + "server_port" => [\$server_port, "20081"], + "server_key" => [\$server_key, ""], + "server_timeout" => [\$server_timeout, 10], + "server_domain" => [\$server_domain, ""], + }, + +); + + +#=== FUNCTIONS = functions ===================================================== + +#=== FUNCTION ================================================================ +# NAME: check_cmdline_param +# PARAMETERS: +# RETURNS: +# DESCRIPTION: +#=============================================================================== +sub check_cmdline_param () { + my $err_config; + my $err_counter = 0; + if(not defined($cfg_file)) { + $cfg_file = "/etc/gosa-si/client.conf"; + if(! -r $cfg_file) { + $err_config = "please specify a config file"; + $err_counter += 1; + } + } + if( $err_counter > 0 ) { + &usage( "", 1 ); + if( defined( $err_config)) { print STDERR "$err_config\n"} + print STDERR "\n"; + exit( -1 ); + } +} + + +#=== FUNCTION ================================================================ +# NAME: read_configfile +# PARAMETERS: cfg_file - string - +# RETURNS: +# DESCRIPTION: +#=============================================================================== +sub read_configfile { + my $cfg; + if( defined( $cfg_file) && ( length($cfg_file) > 0 )) { + if( -r $cfg_file ) { + $cfg = Config::IniFiles->new( -file => $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 ] ); + } + } +} + + +#=== FUNCTION ================================================================ +# NAME: check_pid +# PARAMETERS: +# RETURNS: +# DESCRIPTION: +#=============================================================================== +sub check_pid { + $pid = -1; + # Check, if we are already running + if( open(LOCK_FILE, "<$pid_file") ) { + $pid = ; + if( defined $pid ) { + chomp( $pid ); + if( -f "/proc/$pid/stat" ) { + my($stat) = `cat /proc/$pid/stat` =~ m/$pid \((.+)\).*/; + if( $0 eq $stat ) { + close( LOCK_FILE ); + exit -1; + } + } + } + close( LOCK_FILE ); + unlink( $pid_file ); + } + + # create a syslog msg if it is not to possible to open PID file + if (not sysopen(LOCK_FILE, $pid_file, O_WRONLY|O_CREAT|O_EXCL, 0644)) { + my($msg) = "Couldn't obtain lockfile '$pid_file' "; + if (open(LOCK_FILE, '<', $pid_file) + && ($pid = )) + { + chomp($pid); + $msg .= "(PID $pid)\n"; + } else { + $msg .= "(unable to read PID)\n"; + } + if( ! ($foreground) ) { + openlog( $0, "cons,pid", "daemon" ); + syslog( "warning", $msg ); + closelog(); + } + else { + print( STDERR " $msg " ); + } + exit( -1 ); + } +} + + +#=== FUNCTION ================================================================ +# NAME: logging +# PARAMETERS: level - string - default 'info' +# msg - string - +# facility - string - default 'LOG_DAEMON' +# RETURNS: +# DESCRIPTION: +#=============================================================================== +sub daemon_log { + # 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"); + 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", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); + $month = $monthnames[$month]; + $monthday = $monthday < 10 ? $monthday = "0".$monthday : $monthday; + $year+=1900; + my $name = $0; + $name =~ s/\.\///; + + my $log_msg = "$month $monthday $hours:$minutes:$seconds $name $msg\n"; + print LOG_HANDLE $log_msg; + if( $foreground ) { + print STDERR $log_msg; + } + } + close( LOG_HANDLE ); + } +#log into syslog +# my ($msg, $level, $facility) = @_; +# if(not defined $msg) {return} +# if(not defined $level) {$level = "info"} +# if(not defined $facility) {$facility = "LOG_DAEMON"} +# openlog($0, "pid,cons,", $facility); +# syslog($level, $msg); +# closelog; +# return; +} + + +#=== 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") { + if(defined($server_ip)) { + $result = &get_local_mac_for_remote_ip($server_ip); + } else { + $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 ($client_mac_address and length($client_mac_address) > 0) { + $result= $client_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_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 +# PARAMETERS: none (takes server_ip from global variable) +# RETURNS: (ip address from interface that is used for communication) +# DESCRIPTION: Uses ioctl to get routing table from system, checks which entry +# matches (defaultroute last). +#=============================================================================== +sub get_local_mac_for_remote_ip { + my $ifreq= shift; + my $result= "00:00:00:00:00:00"; + my $PROC_NET_ROUTE= ('/proc/net/route'); + + open(PROC_NET_ROUTE, "<$PROC_NET_ROUTE") + or die "Could not open $PROC_NET_ROUTE"; + + my @ifs = ; + + 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($server_ip)->within(new NetAddr::IP($destination, $mask))) { + # destination matches route, save mac and exit + $result= &get_mac($Iface); + last; + } + } + + + return $result; +} + + +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 get_server_addresses { + my $domain= shift; + my @result; + my $dig_cmd= 'dig +nocomments srv _gosad._tcp.'.$domain; + + my $output= `$dig_cmd 2>&1`; + open (PIPE, "$dig_cmd 2>&1 |"); + while() { + chomp $_; + # If it's not a comment + if($_ =~ m/^[^;]/) { + my @matches= split /\s+/; + + # Push hostname with port + if($matches[3] eq 'SRV') { + push @result, $matches[7].':'.$matches[6]; + } elsif ($matches[3] eq 'A') { + my $i=0; + + # Substitute the hostname with the ip address of the matching A record + foreach my $host (@result) { + if ((split /\:/, $host)[0] eq $matches[0]) { + $result[$i]= $matches[4].':'.(split /\:/, $host)[1]; + } + $i++; + } + } + } + } + close(PIPE); + return @result; +} + + +##=== FUNCTION ================================================================ +## NAME: create_ciphering +## PARAMETERS: passwd - string - used to create ciphering +## RETURNS: cipher - object +## DESCRIPTION: creates a Crypt::Rijndael::MODE_CBC object with passwd as key +##=============================================================================== +#sub create_ciphering { +# my ($passwd) = @_; +# $passwd = substr(md5_hex("$passwd") x 32, 0, 32); +# my $iv = substr(md5_hex('GONICUS GmbH'),0, 16); +# +# #daemon_log("iv: $iv", 7); +# #daemon_log("key: $passwd", 7); +# my $my_cipher = Crypt::Rijndael->new($passwd , Crypt::Rijndael::MODE_CBC()); +# $my_cipher->set_iv($iv); +# return $my_cipher; +#} +# +# +#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); +# { +# use bytes; +# $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; +#} + + +#=== FUNCTION ================================================================ +# NAME: send_msg_hash2address +# PARAMETERS: msg_hash - hash - xml_hash created with function create_xml_hash +# PeerAddr string - socket address to send msg +# PeerPort string - socket port, if not included in socket address +# RETURNS: nothing +# DESCRIPTION: ???? +#=============================================================================== +sub send_msg_hash2address { + my ($msg_hash, $address, $passwd) = @_ ; + + # fetch header for logging + my $header = @{$msg_hash->{header}}[0]; + + # generate xml string + my $msg_xml = &create_xml_string($msg_hash); + + # encrypt xml msg + my $crypted_msg = &encrypt_msg($msg_xml, $passwd); + + # opensocket + my $socket = &open_socket($address); + if(not defined $socket){ + daemon_log("cannot send '$header'-msg to $address , server not reachable", 5); + return 1; + } + + # send xml msg + print $socket $crypted_msg."\n"; + + close $socket; + + daemon_log("send '$header'-msg to $address", 1); + daemon_log("message:\n$msg_xml", 8); + return 0; +} + + +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; +} + + +#=== FUNCTION ================================================================ +# NAME: register_at_server +# PARAMETERS: +# RETURNS: +# DESCRIPTION: +#=============================================================================== +sub register_at_gosa_si_server { + + # create new passwd and ciphering object for client-server communication + $server_key = &create_passwd(); + +# # detect all client accepted events +# opendir(DIR, $event_dir) +# or daemon_log("cannot find directory $event_dir!\ngosa-si-client starts without any accepting events!", 1); +# my $file_name; +# my @events_list = (); +# my $events; +# while(defined($file_name = readdir(DIR))){ +# if ($file_name eq "." || $file_name eq "..") { +# next; +# } +# push(@events_list, $file_name); +# } +# if( 0 == @events_list ) { +# $events = "none"; +# } +# else { +# $events = join(",", @events_list); +# } +# daemon_log("events found for gosa-si-client: $events", 1); + my $events = join( ", ", keys %{$event_hash} ); + + + while(1) { + + # fetch first gosa-si-server from @servers + my $server = shift(@servers); + + if( !$server ) { + daemon_log("no gosa-si-server left in list of servers", 1); + exit(1) + } + + # create registration msg + my $register_hash = &create_xml_hash("here_i_am", $client_address, $server); + &add_content2xml_hash($register_hash, "new_passwd", $server_key); + &add_content2xml_hash($register_hash, "mac_address", $client_mac_address); + &add_content2xml_hash($register_hash, "events", $events); + + # send xml hash to server with general server passwd + my $res = &send_msg_hash2address($register_hash, $server, $default_server_key); + if( $res == 1 ) { + next; + } + + last; + } + + + +# my ($rout, $wout, $reg_server); +# foreach my $server (@servers) { +# +# # create msg hash +# my $register_hash = &create_xml_hash("here_i_am", $client_address, $server); +# &add_content2xml_hash($register_hash, "new_passwd", $new_server_key); +# &add_content2xml_hash($register_hash, "mac_address", $client_mac_address); +# &add_content2xml_hash($register_hash, "events", $events); +# +# # send xml hash to server with general server passwd +# my $answer = &send_msg_hash2address($register_hash, $server, $server_passwd); +# +# if ($answer != 0) { next; } +# +# # waiting for response +# daemon_log("waiting for response...\n", 5); +# my $nf = select($rout=$rbits, $wout=$wbits, undef, $server_timeout); +# +# # something is coming in +# if(vec $rout, fileno $input_socket, 1) { +# my $crypted_msg; +# my $client = $input_socket->accept(); +# my $other_end = getpeername($client); +# if(not defined $other_end) { +# daemon_log("client cannot be identified: $!\n"); +# } else { +# my ($port, $iaddr) = unpack_sockaddr_in($other_end); +# my $actual_ip = inet_ntoa($iaddr); +# daemon_log("\naccept client from $actual_ip\n", 5); +# my $in_msg = &read_from_socket($client); +# if(defined $in_msg){ +# chomp($in_msg); +# $crypted_msg = $in_msg; +# } else { +# daemon_log("cannot read from $actual_ip\n", 5); +# } +# } +# close($client); +# +# # validate acknowledge msg from server +# $new_server_cipher = &create_ciphering($new_server_passwd); +# my $msg_hash; +# eval { +# my $decrypted_msg = &decrypt_msg($crypted_msg, $new_server_cipher); +# daemon_log("decrypted register msg: $decrypted_msg", 5); +# $msg_hash = $xml->XMLin($decrypted_msg, ForceArray=>1); +# }; +# if($@) { +# daemon_log("ERROR: do not understand the incoming message:" , 5); +# daemon_log("$@", 7); +# } else { +# my $header = @{$msg_hash->{header}}[0]; +# if($header eq "registered") { +# $reg_server = $server; +# last; +# } elsif($header eq "denied") { +# my $reason = (&get_content_from_xml_hash($msg_hash, "denied"))[0]; +# daemon_log("registration at $server denied: $reason", 1); +# } else { +# daemon_log("cannot register at $server", 1); +# } +# } +# } +# # if no answer arrive, try next server in list +# +# } +# +# if(defined $reg_server) { +# daemon_log("registered at $reg_server", 1); +# } else { +# daemon_log("cannot register at any server", 1); +# daemon_log("exiting!!!", 1); +# exit(1); +# } +# +# # update the global available variables +# $server_address = $reg_server; +# $server_passwd = $new_server_passwd; +# $server_cipher = $new_server_cipher; + return; +} + + + +sub check_key_and_xml_validity { + my ($crypted_msg, $module_key) = @_; +#print STDERR "crypted_msg:$crypted_msg\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 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("import of event module '$event' failed", 1); + daemon_log("$@", 8); + next; + } + + $event =~ /(\S*?).pm$/; + my $event_module = $1; + my $events_l = eval( $1."::get_events()") ; + foreach my $event_name (@{$events_l}) { + print "$event_name\n"; + $event_hash->{$event_name} = $event_module; + } + + } +} + + +sub server_input { + my ($heap,$input,$wheel) = @_[HEAP, ARG0, ARG1]; + my $error = 0; + + daemon_log("Incoming msg:\n$input\n", 8); + + my ($msg, $msg_hash) = &check_key_and_xml_validity($input, $server_key); + if( (!$msg) || (!$msg_hash) ) { + daemon_log("Deciphering of incoming msg failed", 5); + $error++; + } + + if( $error == 0 ) { + #print STDERR "msg:\n$msg\n"; + #print STDERR Dumper($msg_hash); + + my $header = @{$msg_hash->{header}}[0]; + my $source = @{$msg_hash->{source}}[0]; + if ($header eq 'new_ldap_config') { if ($ldap_enabled == 1) {&new_ldap_config($msg_hash)}} + elsif ($header eq 'ping') { &got_ping($msg_hash) } + elsif ($header eq 'wake_up') { &execute_event($msg_hash)} + elsif ($header eq 'new_passwd') { &new_passwd()} + elsif ($header eq 'compute_hardware') { &compute_hardware() } + elsif ($header eq 'registered') { daemon_log("gosa-si-client registerd at $source", 1) } + else { daemon_log("ERROR: no function assigned to msg $header", 5) } + + } + return; +} + +#==== MAIN = main ============================================================== +# parse commandline options +Getopt::Long::Configure( "bundling" ); +GetOptions("h|help" => \&usage, + "c|config=s" => \$cfg_file, + "f|foreground" => \$foreground, + "v|verbose+" => \$verbose, + ); + +# read and set config parameters +&check_cmdline_param ; +&read_configfile; +&check_pid; + + +# forward error messages to logfile +if ( ! $foreground ) { + open STDIN, '/dev/null' or die "Can’t read /dev/null: $!"; + open STDOUT, '>>/dev/null' or die "Can't write to /dev/null: $!"; + open STDERR, '>>/dev/null' or die "Can't write to /dev/null: $!"; +} + +# Just fork, if we are not in foreground mode +if( ! $foreground ) { + chdir '/' or die "Can't chdir to /: $!"; + $pid = fork; + setsid or die "Can't start a new session: $!"; + umask 0; +} +else { + $pid = $$; +} + +# Do something useful - put our PID into the pid_file +if( 0 != $pid ) { + open( LOCK_FILE, ">$pid_file" ); + print LOCK_FILE "$pid\n"; + close( LOCK_FILE ); + if( !$foreground ) { + exit( 0 ) + }; +} + +daemon_log(" ", 1); +daemon_log("$0 started!", 1); + +# delete old DBsqlite lock files +system('rm -f /tmp/gosa_si_lock*gosa-si-client*'); + + +# complete client_address +$client_address = $client_ip.":".$client_port; + + +# detect own ip and mac address +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); + + +# import events +&import_events(); +#eval($event_hash->{'print_hello'}."::print_hello"); + + +# create socket for incoming xml messages +POE::Component::Server::TCP->new( + Alias => 'gosa-si-client', + Port => $client_port, + ClientInput => \&server_input, +); +daemon_log("start socket for incoming xml messages at port '$client_port' ", 1); + + +# prepare variables +if (defined $server_ip && defined $server_port) { + $server_address = $server_ip.":".$server_port; +} +$xml = new XML::Simple(); +$default_server_key = $server_key; + + +# find all possible gosa-si-servers in DNS +if (defined $server_domain) { + my @tmp_servers = &get_server_addresses($server_domain); + foreach my $server (@tmp_servers) { + unshift(@servers, $server); + } +} +# add gosa-si-server address from config file at first position of server list +if (defined $server_address) { + unshift(@servers, $server_address); +} +my $servers_string = join(", ", @servers); +daemon_log("found servers in configuration file and via DNS: $servers_string", 5); + + +POE::Session->create( + inline_states => { + _start => \®ister_at_gosa_si_server , + } +); + +POE::Kernel->run(); +exit; +