#!/usr/bin/env perl

# wbmc_ssh_config, v 1.0 2002/02/08 10:28 hata

use Getopt::Long;

$ENV{HOME} = '/root';

chomp($localhost =`hostname`);
$authorized_keys_file = $ENV{HOME} . '/.ssh/authorized_keys';
$known_hosts_file = $ENV{HOME} . '/.ssh/known_hosts';
$touch_prog = '/bin/touch';
$cp_prog = '/bin/cp -bf';   # -vbf
$tmp_dir = '/tmp';
$umsconf_file = '/opt/nec/mail/ums.conf';
$ldapsearch_cmd = '/usr/bin/ldapsearch';

$wget_prog = '/usr/bin/wget';
$wget_opt = '--proxy=off -q';
$pubkey_http_path = ':50080/id_dsa.pub';
$pubkey2_http_path = ':50080/ssh_host_rsa_key.pub';

$LOCK_SH = 1;
$LOCK_EX = 2;
$LOCK_NB = 4;
$LOCK_UN = 8;

sub touchFile {
    my($file_name) = @_;
    system($touch_prog . ' ' . $file_name);
}

sub copyFile {
    my($from, $to) = @_;
    system($cp_prog . ' ' . $from . ' ' . $to);
}

sub parse_stsvr_list {
    my @stsvr_list = ();
    
  # /opt/nec/mail/ums.conf ɤ߹
  # - host, port, uri, basedn, binddn, bindpw 
  #
    open(UMSCONF_FILE, $umsconf_file);
    while(<UMSCONF_FILE>) {
        $line = $_;
        chomp($line);
        if ($line =~ /^host/) {
            ($para, $host) = split(/=/, $line);
            $host =~ s/"//g;
        }
        if ($line =~ /^port/) {
            ($para, $port) = split(/=/, $line);
            $port =~ s/"//g;
        }
        if ($line =~ /^uri/) {
            ($para, $uri) = split(/=/, $line);
            $uri =~ s/"//g;
        }
        if ($line =~ /^basedn/) {
            ($para, $basedn) = split(/basedn=/, $line);
            $basedn =~ s/"//g;
        }
        if ($line =~ /^binddn/) {
            ($para, $binddn) = split(/binddn=/, $line);
            $binddn =~ s/"//g;
        }
        if ($line =~ /^bindpw/) {
            ($para, $bindpw) = split(/bindpw=/, $line);
            $bindpw =~ s/"//g;
        }
    }

  # ldapseach ޥɤǳǼа
  # - ldapsearch -x -LLL -D "binddn" -w "bindpw" -h "host:port" -b "basedn"
  #                         "objectClass=expresMailServerStsvrConfig"
  #
  #   uid: hogehoge -> hogehoge get
  #
    $ldapsearch_opt = " -x -LLL -D '$binddn' -w $bindpw -H '$uri' -b '$basedn' ";
    $filter = '"objectClass=expressMailServerStsvrConfig"';
    $stsvr_search = $ldapsearch_cmd . $ldapsearch_opt . $filter;
    my $find = 0;
    open(SRCH, "$stsvr_search | ");
    while(<SRCH>) {
        $line = $_;
        chomp($line);
        if ($line !~ /^uid: /) {
            next;
        }
        ($uid, $stsvr) = split(/uid: /, $line);
      # if ($stsvr eq $localhost) {   # ۥȤϥå -> ۥȤоݤ
      #     next;
      # }
        if ($stsvr eq $host) {   # LDAPХۥȤå
            $found = 1;
        }
        push(@stsvr_list, $stsvr);
    }
    close(SRCH);
    if ($found == 0) {   # LDAPХۥȤʤɲ
        push(@stsvr_list, $host);
    }
    return @stsvr_list;
}

sub add_authorized_keys {
    my($addr, $name, $pub_file) = @_;

    my $ssh_dir = $ENV{'HOME'} . '/.ssh';
    if(not -d $ssh_dir) {
	mkdir($ssh_dir, 0700);
    }
    if(not -f $authorized_keys_file) {
	&touchFile($authorized_keys_file);
    }
    chmod(0600, $authorized_keys_file);
    &copyFile($authorized_keys_file, $authorized_keys_file . '.orig');
    open(AUTHKEYS_FILE, '+< ' . $authorized_keys_file);
    flock(AUTHKEYS_FILE, $LOCK_EX);
    seek(AUTHKEYS_FILE, 0, 0);
    my $new_authkeys = '';
    my $need_modify = 1;

    while(<AUTHKEYS_FILE>) {
	$line = $_;
	if ($line =~ /$addr/) {
	    $need_modify = 0;
	    if ($opt_force) {
		next;
	    }
	}
	chomp($line);
	$new_authkeys .= $line . "\n";
    }

    if ($need_modify || $opt_force) {
	my $pub_key_str;
	open(PUB_FILE, $pub_file);
	$pub_key_str = <PUB_FILE>;
	close(PUB_FILE);
#	$new_authkeys .= $pub_key_str . "\n";
	$new_authkeys .= $pub_key_str;

	seek(AUTHKEYS_FILE, 0, 0);
	print AUTHKEYS_FILE $new_authkeys;
    }
    flock(AUTHKEYS_FILE, $LOCK_UN);
}

sub add_known_hosts {
    my($addr, $name, $pub_file) = @_;
    my($hostname);
    $hostname = $addr;
    $addr = (gethostbyname($addr))[4];
    $addr = sprintf("%u.%u.%u.%u", unpack("C*", $addr));
    $addr = "$hostname,$addr";
    my $ssh_dir = $ENV{'HOME'} . '/.ssh';
    if(not -d $ssh_dir) {
	mkdir($ssh_dir, 0700);
    }
    if(not -f $known_hosts_file) {
	&touchFile($known_hosts_file);
    }
    &copyFile($known_hosts_file, $known_hosts_file . '.orig');
    open(KNOWN_HOSTS_FILE, '+< ' . $known_hosts_file);
    flock(KNOWN_HOSTS_FILE, $LOCK_EX);
    seek(KNOWN_HOSTS_FILE, 0, 0);
    my $new_hosts = '';
    my $need_modify = 1;
    while(<KNOWN_HOSTS_FILE>) {
	$line = $_;
	if ($line =~ /^$addr\s+/) {
	    $need_modify = 0;
	    if($opt_force) {
		next;
	    }
	}
	chomp($line);
	$new_hosts .= $line . "\n";
    }
    if ($need_modify || $opt_force) {
	my $pub_key_str;
	my @pub_key_line;
	open(PUB_FILE, $pub_file);
	$pub_key_str = <PUB_FILE>;
	close(PUB_FILE);
      # hostname, ipaddress exponent modulus
	@pub_key_line = split(/\s/, $pub_key_str);
	$exponent = $pub_key_line[0];
	$modulus = $pub_key_line[1];
	if ($modulus ne "") {
	    $new_hosts .= "$addr $exponent $modulus\n";
	}
	seek(KNOWN_HOSTS_FILE, 0, 0);
	print KNOWN_HOSTS_FILE $new_hosts;
    }
    flock(KNOWN_HOSTS_FILE, $LOCK_UN);
}

sub get_pub_key {
    my($addr, $out_file) = @_;
    system("$wget_prog $wget_opt -O $out_file http://${addr}$pubkey_http_path");
}

sub get_pub_key2 {
    my($addr, $out_file) = @_;
    system("$wget_prog $wget_opt -O $out_file http://${addr}$pubkey2_http_path");
}

GetOptions("name=s", "force");

# Ǽ &add_authorized_keys
#
@stsvr_list = &parse_stsvr_list;
for $stsvr (@stsvr_list) {
    $remove_pubkey = 0;
#   if (not defined($opt_pubkeyfile)) {
        $opt_pubkeyfile = "$tmp_dir/pubkey.tmp$$";
        $remove_pubkey = 1;
        &get_pub_key($stsvr, $opt_pubkeyfile);
#   }
    &add_authorized_keys($stsvr, $opt_name, $opt_pubkeyfile);

    if($remove_pubkey) {
       unlink($opt_pubkeyfile);
    }

    $remove_pubkey = 0;
#   if (not defined($opt_pubkeyfile)) {
        $opt_pubkeyfile = "$tmp_dir/pubkey.tmp$$";
        $remove_pubkey = 1;
        &get_pub_key2($stsvr, $opt_pubkeyfile);
#   }
    &add_known_hosts($stsvr, $opt_name, $opt_pubkeyfile);

    if($remove_pubkey) {
       unlink($opt_pubkeyfile);
    }
}
