]> andersk Git - gssapi-openssh.git/blob - setup/setup-openssh.pl
o Checkpoint commit. Moved main executable parts of script to the upper
[gssapi-openssh.git] / setup / setup-openssh.pl
1 #! perl
2 #
3 # setup-openssh.pl
4 #
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.
8 #
9 # Send comments/fixes/suggestions to:
10 # Chase Phillips <cphillip@ncsa.uiuc.edu>
11 #
12
13 #
14 # Get user's GPT_LOCATION since we may be installing this using a new(er)
15 # version of GPT.
16 #
17
18 $gptpath = $ENV{GPT_LOCATION};
19
20 #
21 # And the old standby..
22 #
23
24 $gpath = $ENV{GLOBUS_LOCATION};
25 if (!defined($gpath))
26 {
27     die "GLOBUS_LOCATION needs to be set before running this script"
28 }
29
30 #
31 # modify the ld library path for when we call ssh executables
32 #
33
34 $oldldpath = $ENV{LD_LIBRARY_PATH};
35 $newldpath = "$gpath/lib";
36 if (length($oldldpath) > 0)
37 {
38     $newldpath .= ":$oldldpath";
39 }
40 $ENV{LD_LIBRARY_PATH} = "$newldpath";
41
42 #
43 # i'm including this because other perl scripts in the gpt setup directories
44 # do so
45 #
46
47 if (defined($gptpath))
48 {
49     @INC = (@INC, "$gptpath/lib/perl", "$gpath/lib/perl");
50 }
51 else
52 {
53     @INC = (@INC, "$gpath/lib/perl");
54 }
55
56 require Grid::GPT::Setup;
57
58 my $globusdir = $gpath;
59 my $myname = "setup-openssh.pl";
60
61 #
62 # Set up path prefixes for use in the path translations
63 #
64
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";
72
73 my $keyfiles = {
74                  "dsa" => "ssh_host_dsa_key",
75                  "rsa" => "ssh_host_rsa_key",
76                  "rsa1" => "ssh_host_key",
77                };
78
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";
85 print "\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";
89 print "\n";
90
91 $response = query_boolean("Do you wish to continue with the setup package?","y");
92 if ($response eq "n")
93 {
94     print "\n";
95     print "Exiting gsi_openssh setup.\n";
96
97     exit 0;
98 }
99
100 print "\n";
101
102 makeConfDir();
103 $keyhash = determineKeys();
104 runKeyGen($keyhash->{gen});
105 copyKeyFiles($keyhash->{copy});
106 fixpaths();
107 copyConfigFiles();
108 alterFiles();
109
110 my $metadata = new Grid::GPT::Setup(package_name => "gsi_openssh_setup");
111
112 $metadata->finish();
113
114 print "\n";
115 print "Additional Notes:\n";
116 print "\n";
117 print "  o I see that you have your GLOBUS_LOCATION environmental variable\n";
118 print "    set to:\n";
119 print "\n";
120 print "    \t\"$gpath\"\n";
121 print "\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";
124 print "\n";
125 print "    After that you may run, e.g.:\n";
126 print "\n";
127 print "    \t\$ . \$GLOBUS_LOCATION/etc/globus-user-env.sh\n";
128 print "\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";
133
134 exit;
135
136 #
137 # subroutines
138 #
139
140 ### copyKeyFiles( $copylist )
141 #
142 # given an array of keys to copy, copy both the key and its public variant into
143 # the gsi-openssh configuration directory.
144 #
145
146 sub copyKeyFiles
147 {
148     my($copylist) = @_;
149     my($regex, $basename);
150
151     if (@$copylist)
152     {
153         print "Copying ssh host keys...\n";
154
155         for my $f (@$copylist)
156         {
157             $f =~ s:/+:/:g;
158
159             if (length($f) > 0)
160             {
161                 $keyfile = "$f";
162                 $pubkeyfile = "$f.pub";
163
164                 action("cp $localsshdir/$keyfile $sysconfdir/$keyfile");
165                 action("cp $localsshdir/$pubkeyfile $sysconfdir/$pubkeyfile");
166             }
167         }
168     }
169 }
170
171 ### isReadable( $file )
172 #
173 # given a file, return true if that file both exists and is readable by the
174 # effective user id.  return false otherwise.
175 #
176
177 sub isReadable
178 {
179     my($file) = @_;
180
181     if ( ( -e $file ) && ( -r $file ) )
182     {
183         return 1;
184     }
185     else
186     {
187         return 0;
188     }
189 }
190
191 ### isPresent( $file )
192 #
193 # given a file, return true if that file exists.  return false otherwise.
194 #
195
196 sub isPresent
197 {
198     my($file) = @_;
199
200     if ( -e $file )
201     {
202         return 1;
203     }
204     else
205     {
206         return 0;
207     }
208 }
209
210 ### makeConfDir( )
211 #
212 # make the gsi-openssh configuration directory if it doesn't already exist.
213 #
214
215 sub makeConfDir
216 {
217     if ( isPresent($sysconfdir) )
218     {
219         if ( -d $sysconfdir )
220         {
221             return;
222         }
223
224         die("${sysconfdir} already exists and is not a directory!\n");
225     }
226
227     print "Could not find ${sysconfdir} directory... creating.\n";
228     action("mkdir -p $sysconfdir");
229
230     return;
231 }
232
233 ### determineKeys( )
234 #
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.
238 #
239
240 sub determineKeys
241 {
242     my($keyhash, $keylist);
243     my($count);
244
245     #
246     # initialize our variables
247     #
248
249     $count = 0;
250
251     $keyhash = {};
252     $keyhash->{gen} = [];   # a list of keytypes to generate
253     $keyhash->{copy} = [];  # a list of files to copy from the 
254
255     $genlist = $keyhash->{gen};
256     $copylist = $keyhash->{copy};
257
258     #
259     # loop over our keytypes and determine what we need to do for each of them
260     #
261
262     for my $keytype (keys %$keyfiles)
263     {
264         $basekeyfile = $keyfiles->{$keytype};
265
266         #
267         # if the key's are already present, we don't need to bother with this rigamarole
268         #
269
270         $gkeyfile = "$sysconfdir/$basekeyfile";
271         $gpubkeyfile = "$sysconfdir/$basekeyfile.pub";
272
273         if ( isPresent($gkeyfile) && isPresent($gpubkeyfile) )
274         {
275             next;
276         }
277
278         #
279         # if we can find a copy of the keys in /etc/ssh, we'll copy them to the user's
280         # globus location
281         #
282
283         $mainkeyfile = "$localsshdir/$basekeyfile";
284         $mainpubkeyfile = "$localsshdir/$basekeyfile.pub";
285
286         if ( isReadable($mainkeyfile) && isReadable($mainpubkeyfile) )
287         {
288             push(@$copylist, $basekeyfile);
289             $count++;
290             next;
291         }
292
293         #
294         # otherwise, we need to generate the key
295         #
296
297         push(@$genlist, $keytype);
298         $count++;
299     }
300
301     if ($count > 0)
302     {
303         if ( ! -d $sysconfdir )
304         {
305             print "Could not find ${sysconfdir} directory... creating\n";
306             action("mkdir -p $sysconfdir");
307         }
308     }
309
310     return $keyhash;
311 }
312
313 ### runKeyGen( $gen_keys )
314 #
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.
317 #
318
319 sub runKeyGen
320 {
321     my($gen_keys) = @_;
322     my $keygen = "$bindir/ssh-keygen";
323
324     if (@$gen_keys && -x $keygen)
325     {
326         print "Generating ssh host keys...\n";
327
328         for my $k (@$gen_keys)
329         {
330             $keyfile = $keyfiles->{$k};
331
332             # if $sysconfdir/$keyfile doesn't exist..
333             action("$bindir/ssh-keygen -t $k -f $sysconfdir/$keyfile -N \"\"");
334         }
335     }
336
337     return 0;
338 }
339
340 ### fixpaths( )
341 #
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.
344 #
345
346 sub fixpaths
347 {
348     my($fileInput, $fileOutput);
349     my($mode, $uid, $gid);
350     my($line, $newline);
351
352     print "Fixing paths in sshd_config...\n";
353
354     $fileInput = "$setupdir/sshd_config.in";
355     $fileOutput = "$sysconfdir/sshd_config";
356
357     if ( ! -f "$fileInput" )
358     {
359         printf("Cannot find $fileInput!\n");
360         die();
361     }
362
363     if ( -e "$fileOutput" )
364     {
365         printf("$fileOutput already exists!\n");
366         die();
367     }
368
369     #
370     # Grab the current mode/uid/gid for use later
371     #
372
373     $mode = (stat($fileInput))[2];
374     $uid = (stat($fileInput))[4];
375     $gid = (stat($fileInput))[5];
376
377     #
378     # Open the files for reading and writing, and loop over the input's contents
379     #
380
381     open(IN, "<$fileInput") || die ("$0: input file $fileInput missing!\n");
382     open(OUT, ">$fileOutput") || die ("$0: unable to open output file $fileOutput!\n");
383
384     while (<IN>)
385     {
386         #
387         # sorry for the whacky regex, but i need to verify a whole line
388         #
389
390         $line = $_;
391         if ( $line =~ /^\s*Subsystem\s+sftp\s+\S+\s*$/ )
392         {
393             $newline = "Subsystem\tsftp\t$gpath/libexec/sftp-server\n";
394             $newline =~ s:/+:/:g;
395         }
396         elsif ( $line =~ /^\s*PidFile.*$/ )
397         {
398             $newline = "PidFile\t$gpath/var/sshd.pid\n";
399             $newline =~ s:/+:/:g;
400         }
401         else
402         {
403             $newline = $line;
404         }
405
406         print OUT "$newline";
407     } # while <IN>
408
409     close(OUT);
410     close(IN);
411
412     #
413     # An attempt to revert the new file back to the original file's
414     # mode/uid/gid
415     #
416
417     chmod($mode, $fileOutput);
418     chown($uid, $gid, $fileOutput);
419
420     return 0;
421 }
422
423 ### copyConfigFiles( )
424 #
425 # subroutine that copies some extra config files to their proper location in
426 # $GLOBUS_LOCATION/etc/ssh.
427 #
428
429 sub copyConfigFiles
430 {
431     print "Copying ssh_config and moduli to their proper location...\n";
432
433     action("cp $setupdir/ssh_config $sysconfdir/ssh_config");
434     action("cp $setupdir/moduli $sysconfdir/moduli");
435 }
436
437 ### alterFileGlobusLocation( $in, $out )
438 #
439 # parse the input file, substituting in place the value of GLOBUS_LOCATION, and
440 # write the result to the output file.
441 #
442
443 sub alterFileGlobusLocation
444 {
445     my ($in, $out) = @_;
446
447     if ( -r $in )
448     {
449         if ( ( -w $out ) || ( ! -e $out ) )
450         {
451             $data = readFile($in);
452             $data =~ s|\@GLOBUS_LOCATION\@|$gpath|g;
453             writeFile($out, $data);
454             action("chmod 755 $out");
455         }
456     }
457 }
458
459 ### alterFiles( )
460 #
461 # the main alteration function, which doesn't do much (other than have GLOBUS_LOCATION
462 # replaced in the sshd startup/shutdown script).
463 #
464
465 sub alterFiles
466 {
467     alterFileGlobusLocation("$setupdir/SXXsshd.in", "$sbindir/SXXsshd");
468 }
469
470 ### readFile( $filename )
471 #
472 # reads and returns $filename's contents
473 #
474
475 sub readFile
476 {
477     my ($filename) = @_;
478     my $data;
479
480     open (IN, "$filename") || die "Can't open '$filename': $!";
481     $/ = undef;
482     $data = <IN>;
483     $/ = "\n";
484     close(IN);
485
486     return $data;
487 }
488
489 ### writeFile( $filename, $fileinput )
490 #
491 # create the inputs to the ssl program at $filename, appending the common name to the
492 # stream in the process
493 #
494
495 sub writeFile
496 {
497     my ($filename, $fileinput) = @_;
498
499     #
500     # test for a valid $filename
501     #
502
503     if ( !defined($filename) || (length($filename) lt 1) )
504     {
505         die "Filename is undefined";
506     }
507
508     if ( ( -e "$filename" ) && ( ! -w "$filename" ) )
509     {
510         die "Cannot write to filename '$filename'";
511     }
512
513     #
514     # write the output to $filename
515     #
516
517     open(OUT, ">$filename");
518     print OUT "$fileinput";
519     close(OUT);
520 }
521
522 #
523 # Just need a minimal action() subroutine for now..
524 #
525
526 sub action
527 {
528     my ($command) = @_;
529
530     printf "$command\n";
531
532     my $result = system("LD_LIBRARY_PATH=\"$gpath/lib:\$LD_LIBRARY_PATH\"; $command 2>&1");
533
534     if (($result or $?) and $command !~ m!patch!)
535     {
536         die "ERROR: Unable to execute command: $!\n";
537     }
538 }
539
540 sub query_boolean
541 {
542     my ($query_text, $default) = @_;
543     my $nondefault, $foo, $bar;
544
545     #
546     # Set $nondefault to the boolean opposite of $default.
547     #
548
549     if ($default eq "n")
550     {
551         $nondefault = "y";
552     }
553     else
554     {
555         $nondefault = "n";
556     }
557
558     print "${query_text} ";
559     print "[$default] ";
560
561     $foo = <STDIN>;
562     ($bar) = split //, $foo;
563
564     if ( grep(/\s/, $bar) )
565     {
566         # this is debatable.  all whitespace means 'default'
567
568         $bar = $default;
569     }
570     elsif ($bar ne $default)
571     {
572         # everything else means 'nondefault'.
573
574         $bar = $nondefault;
575     }
576     else
577     {
578         # extraneous step.  to get here, $bar should be eq to $default anyway.
579
580         $bar = $default;
581     }
582
583     return $bar;
584 }
585
586 ### absolutePath( $file )
587 #
588 # converts a given pathname into a canonical path using the abs_path function.
589 #
590
591 sub absolutePath
592 {
593     my($file) = @_;
594     my $home = $ENV{'HOME'};
595     $file =~ s!~!$home!;
596     my $startd = cwd();
597     $file =~ s!^\./!$startd/!;
598     $file = "$startd/$file" if $file !~ m!^\s*/!;
599     $file = abs_path($file);
600     return $file;
601 }
This page took 0.085854 seconds and 5 git commands to generate.