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