]> andersk Git - gssapi-openssh.git/blob - setup/setup-openssh.pl
o Add moduli, ssh_config, and sshd_config from the mainline gsi_openssh
[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 sub determineKeys
135 {
136     my($keyhash, $keylist);
137     my($count);
138
139     #
140     # initialize our variables
141     #
142
143     $count = 0;
144
145     $keyhash = {};
146     $keyhash->{gen} = [];   # a list of keytypes to generate
147     $keyhash->{copy} = [];  # a list of files to copy from the 
148
149     $genlist = $keyhash->{gen};
150     $copylist = $keyhash->{copy};
151
152     #
153     # loop over our keytypes and determine what we need to do for each of them
154     #
155
156     for my $keytype (keys %$keyfiles)
157     {
158         $basekeyfile = $keyfiles->{$keytype};
159
160         #
161         # if the key's are already present, we don't need to bother with this rigamarole
162         #
163
164         $gkeyfile = "$sysconfdir/$basekeyfile";
165         $gpubkeyfile = "$sysconfdir/$basekeyfile.pub";
166
167         if ( isPresent($gkeyfile) && isPresent($gpubkeyfile) )
168         {
169             next;
170         }
171
172         #
173         # if we can find a copy of the keys in /etc/ssh, we'll copy them to the user's
174         # globus location
175         #
176
177         $mainkeyfile = "$localsshdir/$basekeyfile";
178         $mainpubkeyfile = "$localsshdir/$basekeyfile.pub";
179
180         if ( isReadable($mainkeyfile) && isReadable($mainpubkeyfile) )
181         {
182             push(@$copylist, $basekeyfile);
183             $count++;
184             next;
185         }
186
187         #
188         # otherwise, we need to generate the key
189         #
190
191         push(@$genlist, $keytype);
192         $count++;
193     }
194
195     if ($count > 0)
196     {
197         if ( ! -d $sysconfdir )
198         {
199             print "Could not find ${sysconfdir} directory... creating\n";
200             action("mkdir -p $sysconfdir");
201         }
202     }
203
204     return $keyhash;
205 }
206
207 sub runKeyGen
208 {
209     my($gen_keys) = @_;
210     my $keygen = "$bindir/ssh-keygen";
211
212     if (@$gen_keys && -x $keygen)
213     {
214         print "Generating ssh host keys...\n";
215
216         for my $k (@$gen_keys)
217         {
218             $keyfile = $keyfiles->{$k};
219
220             # if $sysconfdir/$keyfile doesn't exist..
221             action("$bindir/ssh-keygen -t $k -f $sysconfdir/$keyfile -N \"\"");
222         }
223     }
224
225     return 0;
226 }
227
228 ### fixpaths( )
229 #
230 # this subroutine 'edits' the paths in sshd_config to suit them to the current environment
231 # in which the setup script is being run.
232 #
233
234 sub fixpaths
235 {
236     my($fileInput, $fileOutput);
237     my($mode, $uid, $gid);
238     my($line, $newline);
239
240     print "Fixing paths in sshd_config...\n";
241
242     $fileInput = "$setupdir/sshd_config.in";
243     $fileOutput = "$sysconfdir/sshd_config";
244
245     if ( ! -f "$fileInput" )
246     {
247         printf("Cannot find $fileInput!\n");
248         die();
249     }
250
251     if ( -e "$fileOutput" )
252     {
253         printf("$fileOutput already exists!\n");
254         die();
255     }
256
257     #
258     # Grab the current mode/uid/gid for use later
259     #
260
261     $mode = (stat($fileInput))[2];
262     $uid = (stat($fileInput))[4];
263     $gid = (stat($fileInput))[5];
264
265     #
266     # Open the files for reading and writing, and loop over the input's contents
267     #
268
269     open(IN, "<$fileInput") || die ("$0: input file $fileInput missing!\n");
270     open(OUT, ">$fileOutput") || die ("$0: unable to open output file $fileOutput!\n");
271
272     while (<IN>)
273     {
274         #
275         # sorry for the whacky regex, but i need to verify a whole line
276         #
277
278         $line = $_;
279         if ( $line =~ /^\s*Subsystem\s+sftp\s+\S+\s*$/ )
280         {
281             $newline = "Subsystem\tsftp\t$gpath/libexec/sftp-server\n";
282             $newline =~ s:/+:/:g;
283         }
284         elsif ( $line =~ /^\s*PidFile.*$/ )
285         {
286             $newline = "PidFile\t$gpath/var/sshd.pid\n";
287             $newline =~ s:/+:/:g;
288         }
289         else
290         {
291             $newline = $line;
292         }
293
294         print OUT "$newline";
295     } # while <IN>
296
297     close(OUT);
298     close(IN);
299
300     #
301     # An attempt to revert the new file back to the original file's
302     # mode/uid/gid
303     #
304
305     chmod($mode, $fileOutput);
306     chown($uid, $gid, $fileOutput);
307
308     return 0;
309 }
310
311 ### copyConfigFiles( )
312 #
313 # subroutine that copies some extra config files to their proper location in
314 # $GLOBUS_LOCATION/etc/ssh.
315 #
316
317 sub copyConfigFiles
318 {
319     print "Copying ssh_config and moduli to their proper location...\n";
320
321     action("cp $setupdir/ssh_config $sysconfdir/ssh_config");
322     action("cp $setupdir/moduli $sysconfdir/moduli");
323 }
324
325 sub alterFileGlobusLocation
326 {
327     my ($in, $out) = @_;
328
329     if ( -r $in )
330     {
331         if ( ( -w $out ) || ( ! -e $out ) )
332         {
333             $data = readFile($in);
334             $data =~ s|\@GLOBUS_LOCATION\@|$gpath|g;
335             writeFile($out, $data);
336             action("chmod 755 $out");
337         }
338     }
339 }
340
341 sub alterFiles
342 {
343     alterFileGlobusLocation("$setupdir/SXXsshd.in", "$sbindir/SXXsshd");
344 }
345
346 ### readFile( $filename )
347 #
348 # reads and returns $filename's contents
349 #
350
351 sub readFile
352 {
353     my ($filename) = @_;
354     my $data;
355
356     open (IN, "$filename") || die "Can't open '$filename': $!";
357     $/ = undef;
358     $data = <IN>;
359     $/ = "\n";
360     close(IN);
361
362     return $data;
363 }
364
365 ### writeFile( $filename, $fileinput )
366 #
367 # create the inputs to the ssl program at $filename, appending the common name to the
368 # stream in the process
369 #
370
371 sub writeFile
372 {
373     my ($filename, $fileinput) = @_;
374
375     #
376     # test for a valid $filename
377     #
378
379     if ( !defined($filename) || (length($filename) lt 1) )
380     {
381         die "Filename is undefined";
382     }
383
384     if ( ( -e "$filename" ) && ( ! -w "$filename" ) )
385     {
386         die "Cannot write to filename '$filename'";
387     }
388
389     #
390     # write the output to $filename
391     #
392
393     open(OUT, ">$filename");
394     print OUT "$fileinput";
395     close(OUT);
396 }
397
398 print "---------------------------------------------------------------------\n";
399 print "Hi, I'm the setup script for the gsi_openssh package!  There\n";
400 print "are some last minute details that I've got to set straight\n";
401 print "in the sshd config file, along with generating the ssh keys\n";
402 print "for this machine (if it doesn't already have them).\n";
403 print "\n";
404 print "If I find a pair of host keys in /etc/ssh, I will copy them into\n";
405 print "\$GLOBUS_LOCATION/etc/ssh.  If they aren't present, I will generate\n";
406 print "them for you.\n";
407 print "\n";
408
409 $response = query_boolean("Do you wish to continue with the setup package?","y");
410 if ($response eq "n")
411 {
412     print "\n";
413     print "Okay.. exiting gsi_openssh setup.\n";
414
415     exit 0;
416 }
417
418 print "\n";
419
420 $keyhash = determineKeys();
421 runKeyGen($keyhash->{gen});
422 copyKeyFiles($keyhash->{copy});
423 fixpaths();
424 copyConfigFiles();
425 alterFiles();
426
427 my $metadata = new Grid::GPT::Setup(package_name => "gsi_openssh_setup");
428
429 $metadata->finish();
430
431 print "\n";
432 print "Additional Notes:\n";
433 print "\n";
434 print "  o I see that you have your GLOBUS_LOCATION environmental variable\n";
435 print "    set to:\n";
436 print "\n";
437 print "    \t\"$gpath\"\n";
438 print "\n";
439 print "    Remember to keep this variable set (correctly) when you want to\n";
440 print "    use the executables that came with this package.\n";
441 print "\n";
442 print "    After that you may run, e.g.:\n";
443 print "\n";
444 print "    \t\$ . \$GLOBUS_LOCATION/etc/globus-user-env.sh\n";
445 print "\n";
446 print "    to prepare your environment for running the gsi_openssh\n";
447 print "    executables.\n";
448 print "\n";
449 print "---------------------------------------------------------------------\n";
450 print "$myname: Finished configuring package 'gsi_openssh'.\n";
451
452 #
453 # Just need a minimal action() subroutine for now..
454 #
455
456 sub action
457 {
458     my ($command) = @_;
459
460     printf "$command\n";
461
462     my $result = system("LD_LIBRARY_PATH=\"$gpath/lib:\$LD_LIBRARY_PATH\"; $command 2>&1");
463
464     if (($result or $?) and $command !~ m!patch!)
465     {
466         die "ERROR: Unable to execute command: $!\n";
467     }
468 }
469
470 sub query_boolean
471 {
472     my ($query_text, $default) = @_;
473     my $nondefault, $foo, $bar;
474
475     #
476     # Set $nondefault to the boolean opposite of $default.
477     #
478
479     if ($default eq "n")
480     {
481         $nondefault = "y";
482     }
483     else
484     {
485         $nondefault = "n";
486     }
487
488     print "${query_text} ";
489     print "[$default] ";
490
491     $foo = <STDIN>;
492     ($bar) = split //, $foo;
493
494     if ( grep(/\s/, $bar) )
495     {
496         # this is debatable.  all whitespace means 'default'
497
498         $bar = $default;
499     }
500     elsif ($bar ne $default)
501     {
502         # everything else means 'nondefault'.
503
504         $bar = $nondefault;
505     }
506     else
507     {
508         # extraneous step.  to get here, $bar should be eq to $default anyway.
509
510         $bar = $default;
511     }
512
513     return $bar;
514 }
This page took 0.083308 seconds and 5 git commands to generate.