5 # Adapts the installed gsi-openssh environment to the current machine,
6 # performing actions that originally occurred during the package's
7 # 'make install' phase.
9 # Send comments/fixes/suggestions to:
10 # Chase Phillips <cphillip@ncsa.uiuc.edu>
14 # Get user's GPT_LOCATION since we may be installing this using a new(er)
18 $gptpath = $ENV{GPT_LOCATION};
21 # And the old standby..
24 $gpath = $ENV{GLOBUS_LOCATION};
27 die "GLOBUS_LOCATION needs to be set before running this script"
31 # modify the ld library path for when we call ssh executables
34 $oldldpath = $ENV{LD_LIBRARY_PATH};
35 $newldpath = "$gpath/lib";
36 if (length($oldldpath) > 0)
38 $newldpath .= ":$oldldpath";
40 $ENV{LD_LIBRARY_PATH} = "$newldpath";
43 # i'm including this because other perl scripts in the gpt setup directories
47 if (defined($gptpath))
49 @INC = (@INC, "$gptpath/lib/perl", "$gpath/lib/perl");
53 @INC = (@INC, "$gpath/lib/perl");
56 require Grid::GPT::Setup;
58 my $globusdir = $gpath;
59 my $myname = "setup-openssh.pl";
62 # Set up path prefixes for use in the path translations
65 $prefix = ${globusdir};
66 $exec_prefix = "${prefix}";
67 $bindir = "${exec_prefix}/bin";
68 $sbindir = "${exec_prefix}/sbin";
69 $sysconfdir = "$prefix/etc/ssh";
70 $localsshdir = "/etc/ssh";
71 $setupdir = "$prefix/setup/gsi_openssh_setup";
74 "dsa" => "ssh_host_dsa_key",
75 "rsa" => "ssh_host_rsa_key",
76 "rsa1" => "ssh_host_key",
79 print "$myname: Configuring package 'gsi_openssh'...\n";
80 print "---------------------------------------------------------------------\n";
81 print "Hi, I'm the setup script for the gsi_openssh package! There\n";
82 print "are some last minute details that I've got to set straight\n";
83 print "in the sshd config file, along with generating the ssh keys\n";
84 print "for this machine (if it doesn't already have them).\n";
86 print "If I find a pair of host keys in /etc/ssh, I will copy them into\n";
87 print "\$GLOBUS_LOCATION/etc/ssh. If they aren't present, I will generate\n";
88 print "them for you.\n";
91 $response = query_boolean("Do you wish to continue with the setup package?","y");
95 print "Exiting gsi_openssh setup.\n";
103 $keyhash = determineKeys();
104 runKeyGen($keyhash->{gen});
105 copyKeyFiles($keyhash->{copy});
110 my $metadata = new Grid::GPT::Setup(package_name => "gsi_openssh_setup");
115 print "Additional Notes:\n";
117 print " o I see that you have your GLOBUS_LOCATION environmental variable\n";
120 print " \t\"$gpath\"\n";
122 print " Remember to keep this variable set (correctly) when you want to\n";
123 print " use the executables that came with this package.\n";
125 print " After that you may run, e.g.:\n";
127 print " \t\$ . \$GLOBUS_LOCATION/etc/globus-user-env.sh\n";
129 print " to prepare your environment for running the gsi_openssh\n";
130 print " executables.\n";
131 print "---------------------------------------------------------------------\n";
132 print "$myname: Finished configuring package 'gsi_openssh'.\n";
140 ### copyKeyFiles( $copylist )
142 # given an array of keys to copy, copy both the key and its public variant into
143 # the gsi-openssh configuration directory.
149 my($regex, $basename);
153 print "Copying ssh host keys...\n";
155 for my $f (@$copylist)
162 $pubkeyfile = "$f.pub";
164 action("cp $localsshdir/$keyfile $sysconfdir/$keyfile");
165 action("cp $localsshdir/$pubkeyfile $sysconfdir/$pubkeyfile");
171 ### isReadable( $file )
173 # given a file, return true if that file both exists and is readable by the
174 # effective user id. return false otherwise.
181 if ( ( -e $file ) && ( -r $file ) )
191 ### isPresent( $file )
193 # given a file, return true if that file exists. return false otherwise.
212 # make the gsi-openssh configuration directory if it doesn't already exist.
217 if ( isPresent($sysconfdir) )
219 if ( -d $sysconfdir )
224 die("${sysconfdir} already exists and is not a directory!\n");
227 print "Could not find ${sysconfdir} directory... creating.\n";
228 action("mkdir -p $sysconfdir");
235 # based on a set of key types, triage them to determine if for each key type, that
236 # key type should be copied from the main ssh configuration directory, or if it
237 # should be generated using ssh-keygen.
242 my($keyhash, $keylist);
246 # initialize our variables
252 $keyhash->{gen} = []; # a list of keytypes to generate
253 $keyhash->{copy} = []; # a list of files to copy from the
255 $genlist = $keyhash->{gen};
256 $copylist = $keyhash->{copy};
259 # loop over our keytypes and determine what we need to do for each of them
262 for my $keytype (keys %$keyfiles)
264 $basekeyfile = $keyfiles->{$keytype};
267 # if the key's are already present, we don't need to bother with this rigamarole
270 $gkeyfile = "$sysconfdir/$basekeyfile";
271 $gpubkeyfile = "$sysconfdir/$basekeyfile.pub";
273 if ( isPresent($gkeyfile) && isPresent($gpubkeyfile) )
279 # if we can find a copy of the keys in /etc/ssh, we'll copy them to the user's
283 $mainkeyfile = "$localsshdir/$basekeyfile";
284 $mainpubkeyfile = "$localsshdir/$basekeyfile.pub";
286 if ( isReadable($mainkeyfile) && isReadable($mainpubkeyfile) )
288 push(@$copylist, $basekeyfile);
294 # otherwise, we need to generate the key
297 push(@$genlist, $keytype);
303 if ( ! -d $sysconfdir )
305 print "Could not find ${sysconfdir} directory... creating\n";
306 action("mkdir -p $sysconfdir");
313 ### runKeyGen( $gen_keys )
315 # given a set of key types, generate private and public keys for that key type and
316 # place them in the gsi-openssh configuration directory.
322 my $keygen = "$bindir/ssh-keygen";
324 if (@$gen_keys && -x $keygen)
326 print "Generating ssh host keys...\n";
328 for my $k (@$gen_keys)
330 $keyfile = $keyfiles->{$k};
332 # if $sysconfdir/$keyfile doesn't exist..
333 action("$bindir/ssh-keygen -t $k -f $sysconfdir/$keyfile -N \"\"");
342 # this subroutine 'edits' the paths in sshd_config to suit them to the current environment
343 # in which the setup script is being run.
348 my($fileInput, $fileOutput);
349 my($mode, $uid, $gid);
352 print "Fixing paths in sshd_config...\n";
354 $fileInput = "$setupdir/sshd_config.in";
355 $fileOutput = "$sysconfdir/sshd_config";
357 if ( ! -f "$fileInput" )
359 printf("Cannot find $fileInput!\n");
363 if ( -e "$fileOutput" )
365 printf("$fileOutput already exists!\n");
370 # Grab the current mode/uid/gid for use later
373 $mode = (stat($fileInput))[2];
374 $uid = (stat($fileInput))[4];
375 $gid = (stat($fileInput))[5];
378 # Open the files for reading and writing, and loop over the input's contents
381 open(IN, "<$fileInput") || die ("$0: input file $fileInput missing!\n");
382 open(OUT, ">$fileOutput") || die ("$0: unable to open output file $fileOutput!\n");
387 # sorry for the whacky regex, but i need to verify a whole line
391 if ( $line =~ /^\s*Subsystem\s+sftp\s+\S+\s*$/ )
393 $newline = "Subsystem\tsftp\t$gpath/libexec/sftp-server\n";
394 $newline =~ s:/+:/:g;
396 elsif ( $line =~ /^\s*PidFile.*$/ )
398 $newline = "PidFile\t$gpath/var/sshd.pid\n";
399 $newline =~ s:/+:/:g;
406 print OUT "$newline";
413 # An attempt to revert the new file back to the original file's
417 chmod($mode, $fileOutput);
418 chown($uid, $gid, $fileOutput);
423 ### copyConfigFiles( )
425 # subroutine that copies some extra config files to their proper location in
426 # $GLOBUS_LOCATION/etc/ssh.
431 print "Copying ssh_config and moduli to their proper location...\n";
433 action("cp $setupdir/ssh_config $sysconfdir/ssh_config");
434 action("cp $setupdir/moduli $sysconfdir/moduli");
437 ### alterFileGlobusLocation( $in, $out )
439 # parse the input file, substituting in place the value of GLOBUS_LOCATION, and
440 # write the result to the output file.
443 sub alterFileGlobusLocation
449 if ( ( -w $out ) || ( ! -e $out ) )
451 $data = readFile($in);
452 $data =~ s|\@GLOBUS_LOCATION\@|$gpath|g;
453 writeFile($out, $data);
454 action("chmod 755 $out");
461 # the main alteration function, which doesn't do much (other than have GLOBUS_LOCATION
462 # replaced in the sshd startup/shutdown script).
467 alterFileGlobusLocation("$setupdir/SXXsshd.in", "$sbindir/SXXsshd");
470 ### readFile( $filename )
472 # reads and returns $filename's contents
480 open (IN, "$filename") || die "Can't open '$filename': $!";
489 ### writeFile( $filename, $fileinput )
491 # create the inputs to the ssl program at $filename, appending the common name to the
492 # stream in the process
497 my ($filename, $fileinput) = @_;
500 # test for a valid $filename
503 if ( !defined($filename) || (length($filename) lt 1) )
505 die "Filename is undefined";
508 if ( ( -e "$filename" ) && ( ! -w "$filename" ) )
510 die "Cannot write to filename '$filename'";
514 # write the output to $filename
517 open(OUT, ">$filename");
518 print OUT "$fileinput";
523 # Just need a minimal action() subroutine for now..
532 my $result = system("LD_LIBRARY_PATH=\"$gpath/lib:\$LD_LIBRARY_PATH\"; $command 2>&1");
534 if (($result or $?) and $command !~ m!patch!)
536 die "ERROR: Unable to execute command: $!\n";
542 my ($query_text, $default) = @_;
543 my $nondefault, $foo, $bar;
546 # Set $nondefault to the boolean opposite of $default.
558 print "${query_text} ";
562 ($bar) = split //, $foo;
564 if ( grep(/\s/, $bar) )
566 # this is debatable. all whitespace means 'default'
570 elsif ($bar ne $default)
572 # everything else means 'nondefault'.
578 # extraneous step. to get here, $bar should be eq to $default anyway.
586 ### absolutePath( $file )
588 # converts a given pathname into a canonical path using the abs_path function.
594 my $home = $ENV{'HOME'};
597 $file =~ s!^\./!$startd/!;
598 $file = "$startd/$file" if $file !~ m!^\s*/!;
599 $file = abs_path($file);