X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=gosa-si%2Fmodules%2FServerPackages.pm;h=cb7c976f95d75ca3a8d34a9fe36ce37c891d6f4d;hb=9babc999348d7e826e8a9cdab847a1d8ca96000c;hp=ea9632d1e11d9d9951e8d5f9c4efd95f73b01604;hpb=2052d150f05495b25d4c41248a7c2420619d73b0;p=gosa.git diff --git a/gosa-si/modules/ServerPackages.pm b/gosa-si/modules/ServerPackages.pm index ea9632d1e..cb7c976f9 100644 --- a/gosa-si/modules/ServerPackages.pm +++ b/gosa-si/modules/ServerPackages.pm @@ -3,7 +3,7 @@ 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 recieves 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. +# 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; @@ -13,14 +13,16 @@ 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_port, $server_passwd, $max_clients, $ldap_uri, $ldap_base, $ldap_admin_dn, $ldap_admin_password); +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); @@ -29,6 +31,8 @@ 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], @@ -47,17 +51,12 @@ my %cfg_defaults = ### START ##################################################################### - # read configfile and import variables &read_configfile(); -# detect own ip and mac address -my ($server_ip, $server_mac_address) = &get_ip_and_mac(); -if (not defined $server_ip) { - die "EXIT: ip address of $0 could not be detected"; -} -&main::daemon_log("server ip address detected: $server_ip", 1); -&main::daemon_log("server mac address detected: $server_mac_address", 1); +# 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"; @@ -66,48 +65,16 @@ my $bus_address = "$bus_ip:$bus_port"; # create general settings for this module my $xml = new XML::Simple(); -# open server socket -if($server_activ eq "on"){ - &main::daemon_log(" ", 1); - $server = IO::Socket::INET->new(LocalPort => $server_port, - Type => SOCK_STREAM, - Reuse => 1, - Listen => 20, - ); - if(not defined $server){ - &main::daemon_log("cannot be a tcp server at $server_port : $@"); - } else { - &main::daemon_log("start server: $server_address", 1); - } -} - -# TODO -# füge den server selbst zu known_server hinzu, msgs können nämlich auch von sich selbst kommen (gosa!!!) - - # register at bus if ($main::no_bus > 0) { $bus_activ = "off" } if($bus_activ eq "on") { - &main::daemon_log(" ", 1); ®ister_at_bus(); } ### functions ################################################################# -#sub get_module_tags { -# -# # lese config file aus dort gibt es eine section Basic -# # dort stehen drei packettypen, für die sich das modul anmelden kann, gosa-admin-packages, -# # server-packages, client-packages -# my %tag_hash = (gosa_admin_packages => "yes", -# server_packages => "yes", -# client_packages => "yes", -# ); -# return \%tag_hash; -#} - sub get_module_info { my @info = ($server_address, @@ -171,32 +138,126 @@ sub read_configfile { } +#=== 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_ip_and_mac -# PARAMETERS: nothing -# RETURNS: (ip, mac) -# DESCRIPTION: executes /sbin/ifconfig and parses the output, the first occurence -# of a inet address is returned as well as the mac address in the line -# above the inet address +# NAME: get_interfaces +# PARAMETERS: none +# RETURNS: (list of interfaces) +# DESCRIPTION: Uses proc fs (/proc/net/dev) to get list of interfaces. #=============================================================================== -sub get_ip_and_mac { - my $ip = "0.0.0.0.0"; # Defualt-IP - my $mac = "00:00:00:00:00:00"; # Default-MAC - my @ifconfig = qx(/sbin/ifconfig); - foreach(@ifconfig) { - if (/Hardware Adresse (\S{2}):(\S{2}):(\S{2}):(\S{2}):(\S{2}):(\S{2})/) { - $mac = "$1:$2:$3:$4:$5:$6"; - next; - } - if (/inet Adresse:(\d+).(\d+).(\d+).(\d+)/) { - $ip = "$1.$2.$3.$4"; - last; - } - } - return ($ip, $mac); +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: open_socket @@ -205,23 +266,23 @@ sub get_ip_and_mac { # 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; -} +#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: register_at_bus @@ -239,16 +300,6 @@ sub register_at_bus { hostkey=>$bus_passwd, timestamp=>&get_time, } ); -# if ($res == 3) { -# my $update_hash = { table=>'known_server' }; -# $update_hash->{where} = [ { hostname=>[$bus_address] } ]; -# $update_hash->{update} = [ { -# hostkey=>[$bus_passwd], -# timestamp=>[&get_time], -# } ]; -# $res = $main::known_server_db->update_dbentry( $update_hash ); -# } - 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); @@ -272,11 +323,14 @@ 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); + &main::daemon_log("ServerPackages: incoming msg: \n$crypted_msg", 8); $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); + my $host="0.0.0.0"; + if($1 && $2 && $3 && $4) { + $host = sprintf("%s.%s.%s.%s", $2, $3, $4, $5); + } my $msg; my $msg_hash; @@ -290,7 +344,7 @@ sub process_incoming_msg { &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 = &decrypt_msg($crypted_msg, $key_cipher); $msg_hash = &transform_msg2hash($msg); }; if($@) { @@ -362,7 +416,7 @@ sub process_incoming_msg { if( not defined $msg ) { &main::daemon_log("WARNING: ServerPackage do not understand the message:", 5); - &main::daemon_log("$@", 7); + &main::daemon_log("$@", 8); return; } @@ -370,7 +424,7 @@ sub process_incoming_msg { my $header = @{$msg_hash->{header}}[0]; my $source = @{$msg_hash->{source}}[0]; - &main::daemon_log("recieve '$header' at ServerPackages from $host", 1); + &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}}; @@ -383,51 +437,56 @@ sub process_incoming_msg { my $target = $targets[0]; &main::daemon_log("SeverPackages: msg is for: $target", 7); - if ($target eq $server_address) { - # 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 { &main::daemon_log("ERROR: ServerPackages: no function assigned to this msg", 5) } - - } elsif ($target eq "*") { - # msg is for all clients - my $query_res = $main::known_clients_db->select_dbentry( {table=>'known_clients'} ); - 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); - } - return; - - } else { - # msg is for one host - my $query_res = $main::known_clients_db->select_dbentry( {table=>'known_clients', hostname=>$target} ); - if( 1 == keys %{$query_res} ) { - $host_key = $query_res->{1}->{host_key}; - &send_msg_hash2address($msg_hash, $target, $host_key); - return; - } + # 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 $query_res = $main::known_clients_db->select_dbentry( {table=>'known_clients'} ); + 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); + } - my $query_res = $main::known_server_db->select_dbentry( {table=>'known_server', hostname=>$target} ); - if( 1 == keys %{$query_res} ) { - $host_key = $query_res->{1}->{host_key}; - &send_msg_hash2address($msg_hash, $target, $host_key); - return; + } else { + # msg is for one host + my $host_key; + + + if( not defined $host_key ) { + my $query_res = $main::known_clients_db->select_dbentry( {table=>'known_clients', hostname=>$target} ); + if( 1 == keys %{$query_res} ) { + $host_key = $query_res->{1}->{host_key}; + } + } + + if( not defined $host_key ) { + my $query_res = $main::known_server_db->select_dbentry( {table=>'known_server', hostname=>$target} ); + 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); + } } - - &main::daemon_log("ERROR: ServerPackages: target '$target' is not known neither in known_clients nor in known_server",1); - return; } } elsif ($len_targets > 1 ) { # we have more than one target - return; + # TODO to be implemented } return ; @@ -532,7 +591,7 @@ sub here_i_am { my $out_hash; # number of known clients - my $nu_clients = keys %{$main::known_clients_db->select_dbentry( {table=>'known_clients'} )}; + my $nu_clients = keys %{ $main::known_clients_db->select_dbentry( {table=>'known_clients'} ) }; # check wether client address or mac address is already known if (exists $main::known_clients->{$source}) { @@ -571,18 +630,8 @@ sub here_i_am { hostkey=>$new_passwd, timestamp=>&get_time, } ); -# if ($res == 3) { -# my $update_hash = { table=>'known_clients' }; -# $update_hash->{where} = [ { hostname=>[$source] } ]; -# $update_hash->{update} = [ { events=>[$events], -# macaddress=>[$mac_address], -# status=>['registered'], -# hostkey=>[$new_passwd], -# timestamp=>[&get_time], -# } ]; -# $res = $main::known_clients_db->update_dbentry( $update_hash ); -# } - if ($res != 1) { + + if ($res != 0) { &main::daemon_log("ERROR: cannot add entry to known_clients: $res"); return; } @@ -593,9 +642,15 @@ sub here_i_am { # notify registered client to bus if( $bus_activ eq "on") { - &main::daemon_log("send bus msg that client '$source' has registerd at server '$server_address'", 3); + # fetch actual bus key + my $query_res = $main::known_server_db->select_dbentry( {table=>'known_server'} ); + 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); + &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 @@ -667,7 +722,6 @@ sub new_ldap_config { 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 $tmp = print Dumer $res; } my $macaddress = $res->{1}->{macaddress};