#!/usr/bin/env perl

# $Id: wbmc_dc_enable_ssh,v 1.1 2006/12/22 05:33:58 shodai Exp $ 
# $Revision: 1.1 $ 
# $Date: 2006/12/22 05:33:58 $

use Getopt::Long;

$ENV{HOME} = '/root';

$sshd_config_file = &findFile(('/etc/ssh/sshd_config', '/etc/sshd_config'));
$shosts_file = $ENV{HOME} . '/.shosts';
$known_hosts_file = $ENV{HOME} . '/.ssh/known_hosts';
$authorized_keys_file = $ENV{HOME} . '/.ssh/authorized_keys'; 
$touch_prog = '/bin/touch';
$cp_prog = '/bin/cp -vbf';
$tmp_dir = '/tmp';

$wget_prog = '/usr/bin/wget';
$wget_opt = '--proxy=off';
## 070314 LB設定NG問題対応 sakai
$no_check_cert = '--no-check-certificate';
$pubkey_http_s_path = ':50453/ssh_host_key.pub';
$pubkey_http_path = ':50090/ssh_host_key.pub';
$rshkey_http_s_path = ':50453/wbmc_rsh.key.pub';
$rshkey_http_path = ':50090/wbmc_rsh.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 findFile {
    my @list = @_;
    for $i (@list) {
	if (-f $i) {
	    return $i;
	}
    }
    return 0;
}

sub makeTmpFileName {
    my($name) = @_;
    return $tmp_dir . '/' . $name . '/' . '.tmp' . $$;
}

sub modify_sshd_config {
    my %modification_list = 
	('PermitRootLogin' => 'without-password',
	 'IgnoreRhosts' => 'no',
	 'RhostsRSAAuthentication' => 'yes',
#	 'RSAAuthentication' => 'no',
	 );
    my $mode = 0600;
    if(not -f $sshd_config_file) {
	&touchFile($sshd_config_file);
    }
    &copyFile($sshd_config_file, $sshd_config_file . '.orig');
    open(CONFIG_FILE, '+< ' . $sshd_config_file);
    flock(CONFIG_FILE, $LOCK_EX);
    seek(CONFIG_FILE, 0, 0);
    my $new_config = '';
    my $need_modify = 0;
    while(<CONFIG_FILE>) {
	$line = $_;
	$new_config_item = $line;
	while(($key, $value) = each(%modification_list)) {
	    if ($line =~ /\#*$key\s+/) {
		delete($modification_list{$key});
		if ($line =~ /^$key\s+$value/ && not $opt_force) {
		    last;
		}
		$new_config_item = "$key $value\n";
		print "> $new_config_item";
		$need_modify = 1;
		last;
	    }
	}
	$new_config .= $new_config_item;
    }
    while(($key, $value) = each(%modification_list)) {
	$new_config .= $key . ' ' . $value . "\n";
	$need_modify = 1;
    }
    if($need_modify || $opt_force) {
#	print "modify!\n";
#	print $new_config;
	seek(CONFIG_FILE, 0, 0);
	print CONFIG_FILE $new_config;
    }
    flock(CONFIG_FILE, $LOCK_UN);    
}

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

    if(not -f $shosts_file) {
	&touchFile($shosts_file);
    }
    chmod(0600, $shosts_file);
    &copyFile($shosts_file, $shosts_file . '.orig');
    open(SHOSTS_FILE, '+< ' . $shosts_file);
    flock(SHOSTS_FILE, $LOCK_EX);
    seek(SHOSTS_FILE, 0, 0);
    my $new_hosts = '';
    my $need_modify = 1;
    while(<SHOSTS_FILE>) {
	$line = $_;
	if ($line =~ /^\Q$addr\E\s+\Q$name\E/) {
	    $need_modify = 0;
	    if ($opt_force) {
		next;
	    }
	}
	chomp($line);
	$new_hosts .= $line . "\n";
    }

    if($need_modify || $opt_force) {
	$new_hosts .= $addr . ' ' . $name . "\n";
	seek(SHOSTS_FILE, 0, 0);
	print SHOSTS_FILE $new_hosts;
    }
    flock(SHOSTS_FILE, $LOCK_UN);
}

sub add_known_hosts {
    my($addr, $name, $pub_file) = @_;
    my($hostname);
    if ($addr =~ /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) {
	$hostname = gethostbyaddr(pack("C4", split(/\./, $addr)), 2);
	$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 =~ /^\Q$addr\E\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);
# hostnames, bits, exponent, modulus, comment
	@pub_key_line = split(/\s/, $pub_key_str);
	$bits = $pub_key_line[0];
	$exponent = $pub_key_line[1];
	$modulus = $pub_key_line[2];
	$new_hosts .= "$addr $bits $exponent $modulus\n";

	seek(KNOWN_HOSTS_FILE, 0, 0);
	print KNOWN_HOSTS_FILE $new_hosts;
    }
    flock(KNOWN_HOSTS_FILE, $LOCK_UN);
}

sub add_authorized_keys {
    my($pub_file) = @_;
    if(-e $authorized_keys_file){
        &copyFile($authorized_keys_file, $authorized_keys_file . '.orig');
    }
    system("/bin/cat $pub_file >> $authorized_keys_file");
}

sub get_pub_key {
    my($addr, $out_file) = @_;
    if (system("$wget_prog $wget_opt $no_check_cert -O $out_file https://${addr}$pubkey_http_s_path") != 0) {
        if (system("$wget_prog $wget_opt -O $out_file http://${addr}$pubkey_http_path") != 0) {
            return (1);
        }
    }
}

sub get_rsh_key {
    my($addr, $out_file) = @_;
    if (system("$wget_prog $wget_opt $no_check_cert -O $out_file https://${addr}$rshkey_http_s_path") != 0) {
        if (system("$wget_prog $wget_opt -O $out_file http://${addr}$rshkey_http_path") != 0) {
            return (1);
        }
    }
}

GetOptions("addr=s", "name=s", "pubkeyfile=s", "force");
#&modify_sshd_config;
#&add_shosts_entry($opt_addr, $opt_name);
$remove_pubkey = 0;
$remove_pubkey2 = 0;
if(not defined($opt_pubkeyfile)) {
    $opt_pubkeyfile = "$tmp_dir/pubkey.tmp$$";
    $remove_pubkey = 1;
    &get_pub_key($opt_addr, $opt_pubkeyfile);
    $opt_pubkeyfile2 = "$tmp_dir/pubkey2.tmp$$";
    $remove_pubkey2 = 1;
    &get_rsh_key($opt_addr, $opt_pubkeyfile2);
}
&add_known_hosts($opt_addr, $opt_name, $opt_pubkeyfile);
&add_authorized_keys($opt_pubkeyfile2);

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