X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=gosa-si%2Fgosa-si-client;h=86e2f2afef55a5e094e2971e7945934bbef91246;hb=42cd560ae87438edb4fbcd7f82fdac8c60bca1e1;hp=b7c64d9561adaac5efc5957975cd1074f7c1e0c4;hpb=7a175f7355bbc2dfb1b4165a5f684b4f833286c4;p=gosa.git diff --git a/gosa-si/gosa-si-client b/gosa-si/gosa-si-client index b7c64d956..86e2f2afe 100755 --- a/gosa-si/gosa-si-client +++ b/gosa-si/gosa-si-client @@ -3,12 +3,12 @@ # # FILE: gosa-server # -# USAGE: ./gosasc +# USAGE: gosa-si-client # # DESCRIPTION: # # OPTIONS: --- -# REQUIREMENTS: --- +# REQUIREMENTS: libnetaddr-ip-perl # BUGS: --- # NOTES: # AUTHOR: (Andreas Rettenberger), @@ -35,17 +35,18 @@ use Data::Dumper; use Sys::Syslog qw( :DEFAULT setlogsock); use File::Spec; use Cwd; -use GosaSupportDaemon; +use NetAddr::IP; +use GOSA::GosaSupportDaemon; my ($cfg_file, %cfg_defaults, $foreground, $verbose, $pid_file, $procid, $pid, $log_file); my ($server_address, $server_ip, $server_port, $server_domain, $server_passwd, $server_cipher, $server_timeout); -my ($client_address, $client_ip, $client_port, $client_mac_address); -my ($input_socket, $rbits, $wbits, $ebits, $xml, $known_hosts); +my ($client_address, $client_ip, $client_port, $client_mac_address, $network_interface, $ldap_config, $pam_config, $nss_config); +my ($input_socket, $rbits, $wbits, $ebits, $xml, $known_hosts, $ldap_enabled); my (@events); # default variables -my $event_dir = "/etc/gosac/events"; +my $event_dir = "/usr/lib/gosa-si/client/events"; $known_hosts = {}; $foreground = 0 ; %cfg_defaults = @@ -55,6 +56,11 @@ $foreground = 0 ; }, "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, ""], @@ -136,13 +142,12 @@ sub daemon_log { sub check_cmdline_param () { my $err_config; my $err_counter = 0; - if( not defined( $cfg_file)) { - #$err_config = "please specify a config file"; - #$err_counter += 1; - my $cwd = getcwd; - my $name = "/etc/gosa-si/client.conf"; - $cfg_file = File::Spec->catfile( $cwd, $name ); - print STDERR "no conf file specified\n try to use default: $cfg_file\n"; + 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 ); @@ -201,32 +206,172 @@ sub check_pid { } } +#=== 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_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; +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; } - if (/inet Adresse:(\d+).(\d+).(\d+).(\d+)/) { - $ip = "$1.$2.$3.$4"; - last; + + 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 ($ip, $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: 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; +} #=== FUNCTION ================================================================ # NAME: usage @@ -306,16 +451,16 @@ sub register_at_server { # detect all client accepted events opendir(DIR, $event_dir) - or daemon_log("cannot find directory $event_dir!\ngosac starts without any accepting events!", 1); + or daemon_log("cannot find directory $event_dir!\ngosa-si-client starts without any accepting events!", 1); my $file_name; - @events = (); + my @events_list = (); while(defined($file_name = readdir(DIR))){ if ($file_name eq "." || $file_name eq "..") { next; } - push(@events, $file_name); + push(@events_list, $file_name); } - my $events = join(",", @events); + my $events = join(",", @events_list); daemon_log("found events: $events", 1); # fill in all possible servers @@ -335,10 +480,11 @@ sub register_at_server { 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_passwd); - &add_content2xml_hash($register_hash, "client_mac_address", $client_mac_address); + &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 @@ -820,12 +966,13 @@ sub process_incoming_msg { return; } - my $header = &get_content_from_xml_hash($msg_hash, "header"); + my $header = @{$msg_hash->{header}}[0]; - daemon_log("header from msg:", 1); - daemon_log("\t$header", 1); - daemon_log("msg to process:", 7); - daemon_log("\t$msg", 7); + daemon_log("receive '$header' from $host", 1); +# daemon_log("header from msg:", 1); +# daemon_log("\t$header", 1); +# daemon_log("msg to process:", 7); +# daemon_log("\t$msg", 7); #check whether msg to process is a event opendir(DIR, $event_dir) @@ -854,9 +1001,7 @@ sub process_incoming_msg { close(DIR); daemon_log("could not assign the msg $header to an event", 5); - - - if ($header eq 'new_ldap_config') { &new_ldap_config($msg_hash)} + 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()} @@ -925,10 +1070,112 @@ sub got_ping { sub new_ldap_config { my ($msg_hash) = @_ ; + my $element; + my @ldap_uris; + my $ldap_base; + my @ldap_options; + my @pam_options; + my @nss_options; + my $goto_admin; + my $goto_secret; + + # Transform input into array + while ( my ($key, $value) = each(%$msg_hash) ) { + if ($key =~ /^(source|target|header)$/) { + next; + } + + foreach $element (@$value) { + if ($key =~ /^ldap_uri$/) { + push (@ldap_uris, $element); + next; + } + if ($key =~ /^ldap_base$/) { + $ldap_base= $element; + next; + } + if ($key =~ /^goto_admin$/) { + $goto_admin= $element; + next; + } + if ($key =~ /^goto_secret$/) { + $goto_secret= $element; + next; + } + if ($key =~ /^ldap_cfg$/) { + push (@ldap_options, "$element"); + next; + } + if ($key =~ /^pam_cfg$/) { + push (@pam_options, "$element"); + next; + } + if ($key =~ /^nss_cfg$/) { + push (@nss_options, "$element"); + next; + } + } + } + + # Setup ldap.conf + my $file1; + my $file2; + open(file1, "> $ldap_config"); + print file1 "# This file was automatically generated by gosa-si-client. Do not change.\n"; + print file1 "URI"; + foreach $element (@ldap_uris) { + print file1 " $element"; + } + print file1 "\nBASE $ldap_base\n"; + foreach $element (@ldap_options) { + print file1 "$element\n"; + } + close (file1); + daemon_log("wrote $ldap_config", 5); + + # Setup pam_ldap.conf / libnss_ldap.conf + open(file1, "> $pam_config"); + open(file2, "> $nss_config"); + print file1 "# This file was automatically generated by gosa-si-client. Do not change.\n"; + print file2 "# This file was automatically generated by gosa-si-client. Do not change.\n"; + print file1 "uri"; + print file2 "uri"; + foreach $element (@ldap_uris) { + print file1 " $element"; + print file2 " $element"; + } + print file1 "\nbase $ldap_base\n"; + print file2 "\nbase $ldap_base\n"; + foreach $element (@pam_options) { + print file1 "$element\n"; + } + foreach $element (@nss_options) { + print file2 "$element\n"; + } + close (file2); + daemon_log("wrote $nss_config", 5); + close (file1); + daemon_log("wrote $pam_config", 5); + + # Create goto.secrets if told so - for compatibility reasons + if (defined $goto_admin){ + open(file1, "> /etc/goto/secret"); + close(file1); + chown(0,0, "/etc/goto/secret"); + chmod(0600, "/etc/goto/secret"); + open(file1, "> /etc/goto/secret"); + print file1 "GOTOADMIN=\"$goto_admin\"\nGOTOSECRET=\"$goto_secret\"\n"; + close(file1); + daemon_log("wrote /etc/goto/secret", 5); + } - my @gotoLdapServer = &get_content_from_xml_hash($msg_hash, "new_ldap_config"); - print Dumper @gotoLdapServer; + # TODO: write these values to /etc/ldap/ldap-shell.conf + # LDAP_BASE= + # ADMIN_BASE= + # DEPARTMENT= + # UNIT_TAG= + # UNIT_TAG_FILTER= return; @@ -937,7 +1184,7 @@ sub new_ldap_config { sub execute_event { my ($msg_hash)= @_; - my $configdir= '/etc/gosac/events/'; + my $configdir= '/etc/gosa-si/client/events/'; my $result; my $header = &get_content_from_xml_hash($msg_hash, 'header'); @@ -948,7 +1195,7 @@ sub execute_event { if((not defined $source) && (not defined $target) && (not defined $header)) { - daemon_log("ERROR: Entries missing in XML msg for gosa events under /etc/gosac/events"); + daemon_log("ERROR: Entries missing in XML msg for gosa events under $configdir"); } else { my $parameters=""; my @params = &get_content_from_xml_hash($msg_hash, $header); @@ -1012,6 +1259,13 @@ GetOptions("h|help" => \&usage, &read_configfile; &check_pid; +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: $!"; +} + + # restart daemon log file if(-e $log_file ) { unlink $log_file } daemon_log(" ", 1); @@ -1030,10 +1284,13 @@ if( 0 != $pid ) { } # detect own ip and mac address -($client_ip, $client_mac_address) = &get_ip_and_mac(); -if (not defined $client_ip) { - die "EXIT: ip address of $0 could not be detected"; -} +$network_interface= &get_interface_for_ip($client_ip); +$client_mac_address= &get_mac($network_interface); + +# ($client_ip, $client_mac_address) = &get_ip_and_mac(); +#if (not defined $client_ip) { +# die "EXIT: ip address of $0 could not be detected"; +#} daemon_log("client ip address detected: $client_ip", 1); daemon_log("client mac address detected: $client_mac_address", 1);