X-Git-Url: http://andersk.mit.edu/gitweb/gssapi-openssh.git/blobdiff_plain/69534dfa29600f8b00649214b7f57b7fb3c71dea..e3118504578e45e19efe81514d732dff14983f67:/setup/setup-openssh.pl diff --git a/setup/setup-openssh.pl b/setup/setup-openssh.pl index 51edbd9..42446a0 100644 --- a/setup/setup-openssh.pl +++ b/setup/setup-openssh.pl @@ -1,36 +1,65 @@ +#!/usr/bin/perl # -# setup-openssh.pl: -# Adapts the installed gsi-ssh environment to the current machine, -# performing actions that originally occurred during the package's -# 'make install' phase. +# setup-openssh.pl # -# Large parts adapted from 'fixpath', a tool found in openssh-3.0.2p1. +# Adapts the installed gsi-openssh environment to the current machine, +# performing actions that originally occurred during the package's +# 'make install' phase. # # Send comments/fixes/suggestions to: # Chase Phillips # +printf("setup-openssh.pl: Configuring gsi-openssh package\n"); + +# +# Get user's GPT_LOCATION since we may be installing this using a new(er) +# version of GPT. +# + +$gptpath = $ENV{GPT_LOCATION}; + +# +# And the old standby.. +# + $gpath = $ENV{GLOBUS_LOCATION}; if (!defined($gpath)) { die "GLOBUS_LOCATION needs to be set before running this script" } +# +# modify the ld library path for when we call ssh executables +# + +$oldldpath = $ENV{LD_LIBRARY_PATH}; +$newldpath = "$gpath/lib"; +if (length($oldldpath) > 0) +{ + $newldpath .= ":$oldldpath"; +} +$ENV{LD_LIBRARY_PATH} = "$newldpath"; + # # i'm including this because other perl scripts in the gpt setup directories # do so # -@INC = (@INC, "$gpath/lib/perl"); +if (defined($gptpath)) +{ + @INC = (@INC, "$gptpath/lib/perl", "$gpath/lib/perl"); +} +else +{ + @INC = (@INC, "$gpath/lib/perl"); +} require Grid::GPT::Setup; my $globusdir = $gpath; -my $setupdir = "$globusdir/setup/globus"; my $myname = "setup-openssh.pl"; -print "$myname: Configuring package 'gsi-openssh'\n"; - # # Set up path prefixes for use in the path translations # @@ -38,139 +67,416 @@ print "$myname: Configuring package 'gsi-openssh'\n"; $prefix = ${globusdir}; $exec_prefix = "${prefix}"; $bindir = "${exec_prefix}/bin"; -$mandir = "${prefix}/man"; -$mansubdir = "man"; -$libexecdir = "${exec_prefix}/libexec"; -$sysconfdir = "${prefix}/etc"; -$piddir = "/var/run"; -$xauth_path = "/usr/bin/X11/xauth"; +$sysconfdir = "$prefix/etc/ssh"; +$localsshdir = "/etc/ssh"; -sub fixpaths +my $keyfiles = { + "dsa" => "ssh_host_dsa_key", + "rsa" => "ssh_host_rsa_key", + "rsa1" => "ssh_host_key", + }; + +sub copyKeyFiles +{ + my($copylist) = @_; + my($regex, $basename); + + if (@$copylist) + { + print "Copying ssh host keys...\n"; + + for my $f (@$copylist) + { + $f =~ s:/+:/:g; + + if (length($f) > 0) + { + $keyfile = "$f"; + $pubkeyfile = "$f.pub"; + + action("cp $localsshdir/$keyfile $sysconfdir/$keyfile"); + action("cp $localsshdir/$pubkeyfile $sysconfdir/$pubkeyfile"); + } + } + } +} + +sub isReadable +{ + my($file) = @_; + + if ( ( -e $file ) && ( -r $file ) ) + { + return 1; + } + else + { + return 0; + } +} + +sub isPresent +{ + my($file) = @_; + + if ( -e $file ) + { + return 1; + } + else + { + return 0; + } +} + +sub determineKeys { + my($keyhash, $keylist); + my($count); + # - # Set up path translations for the installation files + # initialize our variables # - %def = ( - "/etc/ssh_config" => "${sysconfdir}/ssh_config", - "/etc/ssh_known_hosts" => "${sysconfdir}/ssh_known_hosts", - "/etc/sshd_config" => "${sysconfdir}/sshd_config", - "/usr/libexec" => "${libexecdir}", - "/etc/shosts.equiv" => "${sysconfdir}/shosts.equiv", - "/etc/ssh_host_key" => "${sysconfdir}/ssh_host_key", - "/etc/ssh_host_dsa_key" => "${sysconfdir}/ssh_host_dsa_key", - "/etc/ssh_host_rsa_key" => "${sysconfdir}/ssh_host_rsa_key", - "/var/run/sshd.pid" => "${piddir}/sshd.pid", - "/etc/moduli" => "${sysconfdir}/moduli", - "/etc/sshrc" => "${sysconfdir}/sshrc", - "/usr/X11R6/bin/xauth" => "${xauth_path}", - "/usr/bin:/bin:/usr/sbin:/sbin" => "/usr/bin:/bin:/usr/sbin:/sbin:${bindir}", - "/path/to/scp.real" => "${bindir}/scp.real", - "/path/to/ssh" => "${bindir}/ssh", - ); + $count = 0; + + $keyhash = {}; + $keyhash->{gen} = []; # a list of keytypes to generate + $keyhash->{copy} = []; # a list of files to copy from the + + $genlist = $keyhash->{gen}; + $copylist = $keyhash->{copy}; # - # Files on which to perform path translations + # loop over our keytypes and determine what we need to do for each of them # - @files = ( - "${bindir}/scp", - "${sysconfdir}/ssh_config", - "${sysconfdir}/sshd_config", - "${sysconfdir}/moduli", - "${mandir}/${mansubdir}1/scp.1", - "${mandir}/${mansubdir}1/ssh-add.1", - "${mandir}/${mansubdir}1/ssh-agent.1", - "${mandir}/${mansubdir}1/ssh-keygen.1", - "${mandir}/${mansubdir}1/ssh-keyscan.1", - "${mandir}/${mansubdir}1/ssh.1", - "${mandir}/${mansubdir}8/sshd.8", - "${mandir}/${mansubdir}8/sftp-server.8", - "${mandir}/${mansubdir}1/sftp.1", - ); - - print "Translating strings in config/man files...\n"; - for $f (@files) - { - $f =~ /(.*\/)*(.*)$/; - $g = "$f.tmp"; - - $result = system("mv $f $g"); - if ($result != 0) + for my $keytype (keys %$keyfiles) + { + $basekeyfile = $keyfiles->{$keytype}; + + # + # if the key's are already present, we don't need to bother with this rigamarole + # + + $gkeyfile = "$sysconfdir/$basekeyfile"; + $gpubkeyfile = "$sysconfdir/$basekeyfile.pub"; + + if ( isPresent($gkeyfile) && isPresent($gpubkeyfile) ) { - die "Failed to copy $f to $g!\n"; + next; } - open(IN, "<$g") || die ("$0: input file $g missing!\n"); - open(OUT, ">$f") || die ("$0: unable to open output file $f!\n"); + # + # if we can find a copy of the keys in /etc/ssh, we'll copy them to the user's + # globus location + # + + $mainkeyfile = "$localsshdir/$basekeyfile"; + $mainpubkeyfile = "$localsshdir/$basekeyfile.pub"; - while () + if ( isReadable($mainkeyfile) && isReadable($mainpubkeyfile) ) { - for $s (keys(%def)) - { - s#$s#$def{$s}#; - } # for $s - print OUT "$_"; - } # while + push(@$copylist, $basekeyfile); + $count++; + next; + } + + # + # otherwise, we need to generate the key + # - close(OUT); - close(IN); + push(@$genlist, $keytype); + $count++; + } - $result = system("rm $g"); - if ($result != 0) + if ($count > 0) + { + if ( ! -d $sysconfdir ) { - die "Failed to remove $g\n"; + print "Could not find ${sysconfdir} directory... creating\n"; + action("mkdir -p $sysconfdir"); } - } # for $f + } - return 0; + return $keyhash; } -sub setperms() +sub runKeyGen { - $result = system("chmod 755 $bindir/scp"); + my($gen_keys) = @_; + + if (@$gen_keys) + { + print "Generating ssh host keys...\n"; + + for my $k (@$gen_keys) + { + $keyfile = $keyfiles->{$k}; + + # if $sysconfdir/$keyfile doesn't exist.. + action("$bindir/ssh-keygen -t $k -f $sysconfdir/$keyfile -N \"\""); + } + } + + return 0; } -sub runkeygen +sub fixpaths { - print "Generating ssh keys (if necessary)...\n"; - if ( -e "${sysconfdir}/ssh_host_key" ) + my $g, $h; + + print "Fixing sftp-server path in sshd_config...\n"; + + $f = "$gpath/etc/ssh/sshd_config"; + $g = "$f.tmp"; + + if ( ! -f "$f" ) { - print "${sysconfdir}/ssh_host_key already exists, skipping.\n"; + die("Cannot find $f!"); } - else + + # + # Grab the current mode/uid/gid for use later + # + + $mode = (stat($f))[2]; + $uid = (stat($f))[4]; + $gid = (stat($f))[5]; + + # + # Move $f into a .tmp file for the translation step + # + + $result = system("mv $f $g 2>&1"); + if ($result or $?) { - # if $sysconfdir/ssh_host_key doesn't exist.. - system("$bindir/ssh-keygen -t rsa1 -f $sysconfdir/ssh_host_key -N \"\""); + die "ERROR: Unable to execute command: $!\n"; } - if ( -e "${sysconfdir}/ssh_host_dsa_key" ) + open(IN, "<$g") || die ("$0: input file $g missing!\n"); + open(OUT, ">$f") || die ("$0: unable to open output file $f!\n"); + + while () { - print "${sysconfdir}/ssh_host_dsa_key already exists, skipping.\n"; - } - else + # + # sorry for the whacky regex, but i need to verify a whole line + # + + if ( /^\s*Subsystem\s+sftp\s+\S+\s*$/ ) + { + $_ = "Subsystem\tsftp\t$gpath/libexec/sftp-server\n"; + $_ =~ s:/+:/:g; + } + print OUT "$_"; + } # while + + close(OUT); + close(IN); + + # + # Remove the old .tmp file + # + + $result = system("rm $g 2>&1"); + + if ($result or $?) { - # if $sysconfdir/ssh_host_dsa_key doesn't exist.. - system("$bindir/ssh-keygen -t dsa -f $sysconfdir/ssh_host_dsa_key -N \"\""); + die "ERROR: Unable to execute command: $!\n"; } - if ( -e "${sysconfdir}/ssh_host_rsa_key" ) + # + # An attempt to revert the new file back to the original file's + # mode/uid/gid + # + + chmod($mode, $f); + chown($uid, $gid, $f); + + return 0; +} + +sub alterFileGlobusLocation +{ + my ($file) = @_; + + $data = readFile($file); + $data =~ s|\@GSI_OPENSSH_GLOBUS_LOCATION\@|$gpath|g; + writeFile($file, $data); +} + +sub alterFiles +{ + my (@files); + + @files = ( + "$gosharedir/contrib/caldera/sshd.init", + ); +} + +### readFile( $filename ) +# +# reads and returns $filename's contents +# + +sub readFile +{ + my ($filename) = @_; + my $data; + + open (IN, "$filename") || die "Can't open '$filename': $!"; + $/ = undef; + $data = ; + $/ = "\n"; + close(IN); + + return $data; +} + +### writeFile( $filename, $fileinput ) +# +# create the inputs to the ssl program at $filename, appending the common name to the +# stream in the process +# + +sub writeFile +{ + my ($filename, $fileinput) = @_; + + # + # test for a valid $filename + # + + if ( !defined($filename) || (length($filename) lt 1) ) { - print "${sysconfdir}/ssh_host_rsa_key already exists, skipping.\n"; + die "Filename is undefined"; } - else + + if ( ( -e "$filename" ) && ( ! -w "$filename" ) ) { - # if $sysconfdir/ssh_host_rsa_key doesn't exist.. - system("$bindir/ssh-keygen -t rsa -f $sysconfdir/ssh_host_rsa_key -N \"\""); + die "Cannot write to filename '$filename'"; } - return 0; + # + # write the output to $filename + # + + open(OUT, ">$filename"); + print OUT "$fileinput"; + close(OUT); +} + +print "---------------------------------------------------------------------\n"; +print "Hi, I'm the setup script for the gsi_openssh package! There\n"; +print "are some last minute details that I've got to set straight\n"; +print "in the sshd config file, along with generating the ssh keys\n"; +print "for this machine (if it doesn't already have them).\n"; +print "\n"; +print "If I find a pair of host keys in /etc/ssh, I will copy them into\n"; +print "\$GLOBUS_LOCATION/etc/ssh. If they aren't present, I will generate\n"; +print "them for you.\n"; +print "\n"; + +$response = query_boolean("Do you wish to continue with the setup package?","y"); +if ($response eq "n") +{ + print "\n"; + print "Okay.. exiting gsi_openssh setup.\n"; + + exit 0; } +print "\n"; + +$keyhash = determineKeys(); +runKeyGen($keyhash->{gen}); +copyKeyFiles($keyhash->{copy}); fixpaths(); -setperms(); -runkeygen(); -my $metadata = new Grid::GPT::Setup(package_name => "gsi-openssh-setup"); +my $metadata = new Grid::GPT::Setup(package_name => "gsi_openssh_setup"); $metadata->finish(); + +print "\n"; +print "Additional Notes:\n"; +print "\n"; +print " o I see that you have your GLOBUS_LOCATION environmental variable\n"; +print " set to:\n"; +print "\n"; +print " \t\"$gpath\"\n"; +print "\n"; +print " Remember to keep this variable set (correctly) when you want to\n"; +print " use the executables that came with this package.\n"; +print "\n"; +print " o You may need to set LD_LIBRARY_PATH to point to the location in\n"; +print " which your globus libraries reside. For example:\n"; +print "\n"; +print " \t\$ LD_LIBRARY_PATH=\"$gpath/lib:\$LD_LIBRARY_PATH\"; \\\n"; +print " \t export LD_LIBRARY_PATH\n"; +print "\n"; +print "---------------------------------------------------------------------\n"; +print "$myname: Finished configuring package 'gsi_openssh'.\n"; + +# +# Just need a minimal action() subroutine for now.. +# + +sub action +{ + my ($command) = @_; + + printf "$command\n"; + + my $result = system("LD_LIBRARY_PATH=\"$gpath/lib:\$LD_LIBRARY_PATH\"; $command 2>&1"); + + if (($result or $?) and $command !~ m!patch!) + { + die "ERROR: Unable to execute command: $!\n"; + } +} + +sub query_boolean +{ + my ($query_text, $default) = @_; + my $nondefault, $foo, $bar; + + # + # Set $nondefault to the boolean opposite of $default. + # + + if ($default eq "n") + { + $nondefault = "y"; + } + else + { + $nondefault = "n"; + } + + print "${query_text} "; + print "[$default] "; + + $foo = ; + ($bar) = split //, $foo; + + if ( grep(/\s/, $bar) ) + { + # this is debatable. all whitespace means 'default' + + $bar = $default; + } + elsif ($bar ne $default) + { + # everything else means 'nondefault'. + + $bar = $nondefault; + } + else + { + # extraneous step. to get here, $bar should be eq to $default anyway. + + $bar = $default; + } + + return $bar; +}