]> andersk Git - gssapi-openssh.git/blob - setup/setup-openssh.pl
e83032a9279e35e5da80f26da64466a8a8be3ec8
[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 #
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     exitDie "GLOBUS_LOCATION needs to be set before running this script"
28 }
29
30 #
31 # Include standard modules
32 #
33
34 use Getopt::Long;
35 use Cwd;
36 use Cwd 'abs_path';
37
38 #
39 # modify the ld library path for when we call ssh executables
40 #
41
42 $oldldpath = $ENV{LD_LIBRARY_PATH};
43 $newldpath = "$gpath/lib";
44 if (length($oldldpath) > 0)
45 {
46     $newldpath .= ":$oldldpath";
47 }
48 $ENV{LD_LIBRARY_PATH} = "$newldpath";
49
50 #
51 # i'm including this because other perl scripts in the gpt setup directories
52 # do so
53 #
54
55 if (defined($gptpath))
56 {
57     @INC = (@INC, "$gptpath/lib/perl", "$gpath/lib/perl");
58 }
59 else
60 {
61     @INC = (@INC, "$gpath/lib/perl");
62 }
63
64 require Grid::GPT::Setup;
65
66 #
67 # script-centred variable initialization
68 #
69
70 my $globusdir = $gpath;
71 my $myname = "setup-openssh.pl";
72
73 #
74 # Set up path prefixes for use in the path translations
75 #
76
77 $prefix = ${globusdir};
78 $exec_prefix = "${prefix}";
79 $bindir = "${exec_prefix}/bin";
80 $sbindir = "${exec_prefix}/sbin";
81 $sysconfdir = "$prefix/etc/ssh";
82 $localsshdir = "/etc/ssh";
83 $setupdir = "$prefix/setup/gsi_openssh_setup";
84
85 #
86 # standard key types and their root file name mappings
87 #
88
89 my $keyfiles = {
90                  "dsa" => "ssh_host_dsa_key",
91                  "rsa" => "ssh_host_rsa_key",
92                  "rsa1" => "ssh_host_key",
93                };
94
95 #
96 # argument specification.  we offload some processing work from later functions
97 # to verify correct args by using anon subs in various places.
98 #
99
100 my($prompt, $force, $verbose);
101
102 $prompt = 1;
103
104 GetOptions(
105             'prompt!' => \$prompt,
106             'force' => \$force,
107             'verbose' => \$verbose,
108           ) or pod2usage(2);
109
110 #
111 # miscellaneous initialization functions
112 #
113
114 setPrivilegeSeparation(0);
115
116 #
117 # main execution.  This should find its way into a subroutine at some future
118 # point.
119 #
120
121 print "$myname: Configuring package 'gsi_openssh'...\n";
122 print "---------------------------------------------------------------------\n";
123 print "Hi, I'm the setup script for the gsi_openssh package!  I will create\n";
124 print "a number of configuration files based on your local system setup.  I\n";
125 print "will also attempt to copy or create a number of SSH key pairs for\n";
126 print "this machine.  (Loosely, if I find a pair of host keys in /etc/ssh,\n";
127 print "I will copy them into \$GLOBUS_LOCATION/etc/ssh.  Otherwise, I will\n";
128 print "generate them for you.)\n";
129 print "\n";
130
131 if ( isForced() )
132 {
133     print "WARNING:\n";
134     print "\n";
135     print "    Using the '-force' flag will cause all gsi_openssh_setup files to\n";
136     print "    be removed and replaced by new versions!  Backup any critical\n";
137     print "    SSH configuration files before you choose to continue!\n";
138     print "\n";
139 }
140
141 $response = query_boolean("Do you wish to continue with the setup package?","y");
142 if ($response eq "n")
143 {
144     print "\n";
145     print "Exiting gsi_openssh setup.\n";
146
147     exit;
148 }
149
150 print "\n";
151
152 makeConfDir();
153 copyPRNGFile();
154 $keyhash = determineKeys();
155 runKeyGen($keyhash->{gen});
156 copyKeyFiles($keyhash->{copy});
157 copyConfigFiles();
158
159 my $metadata = new Grid::GPT::Setup(package_name => "gsi_openssh_setup");
160
161 $metadata->finish();
162
163 print "\n";
164 print "Additional Notes:\n";
165 print "\n";
166 print "  o I see that you have your GLOBUS_LOCATION environmental variable\n";
167 print "    set to:\n";
168 print "\n";
169 print "        \"$gpath\"\n";
170 print "\n";
171 print "    Remember to keep this variable set (correctly) when you want to\n";
172 print "    use the executables that came with this package.\n";
173 print "\n";
174 print "    After that you may execute, for example:\n";
175 print "\n";
176 print "        \$ . \$GLOBUS_LOCATION/etc/globus-user-env.sh\n";
177 print "\n";
178 print "    to prepare your environment for running the gsi_openssh\n";
179 print "    executables.\n";
180 print "\n";
181 print "  o I recommend you review and customize to your liking the contents of\n";
182 print "\n";
183 print "        \$GLOBUS_LOCATION/etc/ssh\n";
184 print "\n";
185 print "    \"I can only show you the door.  You have to walk through it.\"\n";
186
187 if ( !getPrivilegeSeparation() )
188 {
189     print "\n";
190     print "  o For System Administrators:\n";
191     print "\n";
192     print "    If you are going to run the GSI-OpenSSH server, we recommend\n";
193     print "    enabling privilege separation.  Although this package supports\n";
194     print "    this feature, your system appears to require some additional\n";
195     print "    configuration.\n";
196     print "\n";
197     print "    From the file README.privsep, included as a part of the OpenSSH\n";
198     print "    distribution:\n";
199     print "\n";
200     print "        When privsep is enabled, during the pre-authentication\n";
201     print "        phase sshd will chroot(2) to \"/var/empty\" and change its\n";
202     print "        privileges to the \"sshd\" user and its primary group.  sshd\n";
203     print "        is a pseudo-account that should not be used by other\n";
204     print "        daemons, and must be locked and should contain a \"nologin\"\n";
205     print "        or invalid shell.\n";
206     print "\n";
207     print "        You should do something like the following to prepare the\n";
208     print "        privsep preauth environment:\n";
209     print "\n";
210     print "            \# mkdir /var/empty\n";
211     print "            \# chown root:sys /var/empty\n";
212     print "            \# chmod 755 /var/empty\n";
213     print "            \# groupadd sshd\n";
214     print "            \# useradd -g sshd -c 'sshd privsep' -d /var/empty \\\n";
215     print "            -s /bin/false sshd\n";
216     print "\n";
217     print "        /var/empty should not contain any files.\n";
218 }
219
220 print "\n";
221 print "  o For more information about GSI-Enabled OpenSSH, visit:\n";
222 print "    <http://grid.ncsa.uiuc.edu/ssh/>\n";
223
224 #
225 # give the user a chance to read all of this output
226 #
227
228 if ( $prompt )
229 {
230     print "\n";
231     print "Press <return> to continue... ";
232     $trash = <STDIN>;
233 }
234
235 print "---------------------------------------------------------------------\n";
236 print "$myname: Finished configuring package 'gsi_openssh'.\n";
237
238 exit;
239
240 #
241 # subroutines
242 #
243
244 ### initPRNGHash( )
245 #
246 # initialize the PRNG pathname hash
247 #
248
249 sub initPRNGHash( )
250 {
251     #
252     # standard prng to executable conversion names
253     #
254
255     addPRNGCommand("\@PROG_LS\@", "ls");
256     addPRNGCommand("\@PROG_NETSTAT\@", "netstat");
257     addPRNGCommand("\@PROG_ARP\@", "arp");
258     addPRNGCommand("\@PROG_IFCONFIG\@", "ifconfig");
259     addPRNGCommand("\@PROG_PS\@", "ps");
260     addPRNGCommand("\@PROG_JSTAT\@", "jstat");
261     addPRNGCommand("\@PROG_W\@", "w");
262     addPRNGCommand("\@PROG_WHO\@", "who");
263     addPRNGCommand("\@PROG_LAST\@", "last");
264     addPRNGCommand("\@PROG_LASTLOG\@", "lastlog");
265     addPRNGCommand("\@PROG_DF\@", "df");
266     addPRNGCommand("\@PROG_SAR\@", "sar");
267     addPRNGCommand("\@PROG_VMSTAT\@", "vmstat");
268     addPRNGCommand("\@PROG_UPTIME\@", "uptime");
269     addPRNGCommand("\@PROG_IPCS\@", "ipcs");
270     addPRNGCommand("\@PROG_TAIL\@", "tail");
271
272     print "Determining paths for PRNG commands...\n";
273
274     $paths = determinePRNGPaths();
275
276     return;
277 }
278
279 ### getDirectoryPaths( )
280 #
281 # return an array ref containing all of the directories in which we should search
282 # for our listing of executable names.
283 #
284
285 sub getDirectoryPaths( )
286 {
287     #
288     # read in the PATH environmental variable and prepend a set of 'safe'
289     # directories from which to test PRNG commands.
290     #
291
292     $path = $ENV{PATH};
293     $path = "/bin:/usr/bin:/sbin:/usr/sbin:/etc:" . $path;
294     @dirs = split(/:/, $path);
295
296     #
297     # sanitize each directory listed in the array.
298     #
299
300     @dirs = map {
301                   $tmp = $_;
302                   $tmp =~ s:/+:/:g;
303                   $tmp =~ s:^\s+|\s+$::g;
304                   $tmp;
305                 } @dirs;
306
307     return \@dirs;
308 }
309
310 ### addPRNGCommand( $prng_name, $exec_name )
311 #
312 # given a PRNG name and a corresponding executable name, add it to our list of
313 # PRNG commands for which to find on the system.
314 #
315
316 sub addPRNGCommand
317 {
318     my($prng_name, $exec_name) = @_;
319
320     prngAddNode($prng_name, $exec_name);
321 }
322
323 ### copyPRNGFile( )
324 #
325 # read in ssh_prng_cmds.in, translate the program listings to the paths we have
326 # found on the local system, and then write the output to ssh_prng_cmds.
327 #
328
329 sub copyPRNGFile
330 {
331     my($fileInput, $fileOutput);
332     my($mode, $uid, $gid);
333     my($data);
334
335     if ( isPresent("$sysconfdir/ssh_prng_cmds") && !isForced() )
336     {
337         printf("ssh_prng_cmds found and not forced.  Not installing ssh_prng_cmds...\n");
338         return;
339     }
340
341     initPRNGHash();
342
343     print "Fixing paths in ssh_prng_cmds...\n";
344
345     $fileInput = "$setupdir/ssh_prng_cmds.in";
346     $fileOutput = "$sysconfdir/ssh_prng_cmds";
347
348     #
349     # verify that we are prepared to work with $fileInput
350     #
351
352     if ( !isReadable($fileInput) )
353     {
354         printf("Cannot read $fileInput... skipping.\n");
355         return;
356     }
357
358     #
359     # verify that we are prepared to work with $fileOuput
360     #
361
362     if ( !prepareFileWrite($fileOutput) )
363     {
364         return;
365     }
366
367     #
368     # Grab the current mode/uid/gid for use later
369     #
370
371     $mode = (stat($fileInput))[2];
372     $uid = (stat($fileInput))[4];
373     $gid = (stat($fileInput))[5];
374
375     #
376     # Open the files for reading and writing, and loop over the input's contents
377     #
378
379     $data = readFile($fileInput);
380     for my $k (keys %$prngcmds)
381     {
382         $sub = prngGetExecPath($k);
383         $data =~ s:$k:$sub:g;
384     }
385     writeFile($fileOutput, $data);
386
387     #
388     # An attempt to revert the new file back to the original file's
389     # mode/uid/gid
390     #
391
392     chmod($mode, $fileOutput);
393     chown($uid, $gid, $fileOutput);
394
395     return 0;
396 }
397
398 ### determinePRNGPaths( )
399 #
400 # for every entry in the PRNG hash, seek out and find the path for the
401 # corresponding executable name.
402 #
403
404 sub determinePRNGPaths
405 {
406     my(@paths, @dirs);
407     my($exec_name, $exec_path);
408
409     $dirs = getDirectoryPaths();
410
411     for my $k (keys %$prngcmds)
412     {
413         $exec_name = prngGetExecName($k);
414         $exec_path = findExecutable($exec_name, $dirs);
415         prngSetExecPath($k, $exec_path);
416     }
417
418     return;
419 }
420
421 ### prngAddNode( $prng_name, $exec_name )
422 #
423 # add a new node to the PRNG hash
424 #
425
426 sub prngAddNode
427 {
428     my($prng_name, $exec_name) = @_;
429     my($node);
430
431     if (!defined($prngcmds))
432     {
433         $prngcmds = {};
434     }
435
436     $node = {};
437     $node->{prng} = $prng_name;
438     $node->{exec} = $exec_name;
439
440     $prngcmds->{$prng_name} = $node;
441 }
442
443 ### prngGetExecName( $key )
444 #
445 # get the executable name from the prng commands hash named by $key
446 #
447
448 sub prngGetExecName
449 {
450     my($key) = @_;
451
452     return $prngcmds->{$key}->{exec};
453 }
454
455 ### prngGetExecPath( $key )
456 #
457 # get the executable path from the prng commands hash named by $key
458 #
459
460 sub prngGetExecPath
461 {
462     my($key) = @_;
463
464     return $prngcmds->{$key}->{exec_path};
465 }
466
467 ### prngGetNode( $key )
468 #
469 # return a reference to the node named by $key
470 #
471
472 sub prngGetNode
473 {
474     my($key) = @_;
475
476     return ${$prngcmds}{$key};
477 }
478
479 ### prngSetExecPath( $key, $path )
480 #
481 # given a key, set the executable path in that node to $path
482 #
483
484 sub prngSetExecPath
485 {
486     my($key, $path) = @_;
487
488     $prngcmds->{$key}->{exec_path} = $path;
489 }
490
491 ### findExecutable( $exec_name, $dirs )
492 #
493 # given an executable name, test each possible path in $dirs to see if such
494 # an executable exists.
495 #
496
497 sub findExecutable
498 {
499     my($exec_name, $dirs) = @_;
500
501     for my $d (@$dirs)
502     {
503         $test = "$d/$exec_name";
504
505         if ( isExecutable($test) )
506         {
507             return $test;
508         }
509     }
510
511     return "undef";
512 }
513
514 ### copyKeyFiles( $copylist )
515 #
516 # given an array of keys to copy, copy both the key and its public variant into
517 # the gsi-openssh configuration directory.
518 #
519
520 sub copyKeyFiles
521 {
522     my($copylist) = @_;
523     my($regex, $basename);
524
525     if (@$copylist)
526     {
527         print "Copying ssh host keys...\n";
528
529         for my $f (@$copylist)
530         {
531             $f =~ s:/+:/:g;
532
533             if (length($f) > 0)
534             {
535                 $keyfile = "$f";
536                 $pubkeyfile = "$f.pub";
537
538                 copyFile("$localsshdir/$keyfile", "$sysconfdir/$keyfile");
539                 copyFile("$localsshdir/$pubkeyfile", "$sysconfdir/$pubkeyfile");
540             }
541         }
542     }
543 }
544
545 ### isForced( )
546 #
547 # return true if the user passed in the force flag.  return false otherwise.
548 #
549
550 sub isForced
551 {
552     if ( defined($force) && $force )
553     {
554         return 1;
555     }
556     else
557     {
558         return 0;
559     }
560 }
561
562 ### isReadable( $file )
563 #
564 # given a file, return true if that file both exists and is readable by the
565 # effective user id.  return false otherwise.
566 #
567
568 sub isReadable
569 {
570     my($file) = @_;
571
572     if ( ( -e $file ) && ( -r $file ) )
573     {
574         return 1;
575     }
576     else
577     {
578         return 0;
579     }
580 }
581
582 ### isExecutable( $file )
583 #
584 # return true if $file is executable.  return false otherwise.
585 #
586
587 sub isExecutable
588 {
589     my($file) = @_;
590
591     if ( -x $file )
592     {
593         return 1;
594     }
595     else
596     {
597         return 0;
598     }
599 }
600
601 ### isWritable( $file )
602 #
603 # given a file, return true if that file does not exist or is writable by the
604 # effective user id.  return false otherwise.
605 #
606
607 sub isWritable
608 {
609     my($file) = @_;
610
611     if ( ( ! -e $file ) || ( -w $file ) )
612     {
613         return 1;
614     }
615     else
616     {
617         return 0;
618     }
619 }
620
621 ### isPresent( $file )
622 #
623 # given a file, return true if that file exists.  return false otherwise.
624 #
625
626 sub isPresent
627 {
628     my($file) = @_;
629
630     if ( -e $file )
631     {
632         return 1;
633     }
634     else
635     {
636         return 0;
637     }
638 }
639
640 ### makeConfDir( )
641 #
642 # make the gsi-openssh configuration directory if it doesn't already exist.
643 #
644
645 sub makeConfDir
646 {
647     if ( isPresent($sysconfdir) )
648     {
649         if ( -d $sysconfdir )
650         {
651             return;
652         }
653
654         print("${sysconfdir} already exists and is not a directory!\n");
655         exit;
656     }
657
658     print "Could not find ${sysconfdir} directory... creating.\n";
659     action("mkdir -p $sysconfdir");
660
661     return;
662 }
663
664 ### determineKeys( )
665 #
666 # based on a set of key types, triage them to determine if for each key type, that
667 # key type should be copied from the main ssh configuration directory, or if it
668 # should be generated using ssh-keygen.
669 #
670
671 sub determineKeys
672 {
673     my($keyhash, $keylist);
674     my($count);
675
676     #
677     # initialize our variables
678     #
679
680     $count = 0;
681
682     $keyhash = {};
683     $keyhash->{gen} = [];   # a list of keytypes to generate
684     $keyhash->{copy} = [];  # a list of files to copy from the 
685
686     $genlist = $keyhash->{gen};
687     $copylist = $keyhash->{copy};
688
689     #
690     # loop over our keytypes and determine what we need to do for each of them
691     #
692
693     for my $keytype (keys %$keyfiles)
694     {
695         $basekeyfile = $keyfiles->{$keytype};
696
697         #
698         # if the key's are already present, we don't need to bother with this rigamarole
699         #
700
701         $gkeyfile = "$sysconfdir/$basekeyfile";
702         $gpubkeyfile = "$sysconfdir/$basekeyfile.pub";
703
704         if ( isPresent($gkeyfile) && isPresent($gpubkeyfile) )
705         {
706             if ( isForced() )
707             {
708                 if ( isWritable("$sysconfdir/$basekeyfile") && isWritable("$sysconfdir/$basekeyfile.pub") )
709                 {
710                      action("rm $sysconfdir/$basekeyfile");
711                      action("rm $sysconfdir/$basekeyfile.pub");
712                 }
713                 else
714                 {
715                      next;
716                 }
717             }
718         }
719
720         #
721         # if we can find a copy of the keys in /etc/ssh, we'll copy them to the user's
722         # globus location
723         #
724
725         $mainkeyfile = "$localsshdir/$basekeyfile";
726         $mainpubkeyfile = "$localsshdir/$basekeyfile.pub";
727
728         if ( isReadable($mainkeyfile) && isReadable($mainpubkeyfile) )
729         {
730             push(@$copylist, $basekeyfile);
731             $count++;
732             next;
733         }
734
735         #
736         # otherwise, we need to generate the key
737         #
738
739         push(@$genlist, $keytype);
740         $count++;
741     }
742
743     return $keyhash;
744 }
745
746 ### runKeyGen( $gen_keys )
747 #
748 # given a set of key types, generate private and public keys for that key type and
749 # place them in the gsi-openssh configuration directory.
750 #
751
752 sub runKeyGen
753 {
754     my($gen_keys) = @_;
755     my $keygen = "$bindir/ssh-keygen";
756
757     if (@$gen_keys && -x $keygen)
758     {
759         print "Generating ssh host keys...\n";
760
761         for my $k (@$gen_keys)
762         {
763             $keyfile = $keyfiles->{$k};
764
765             if ( !isPresent("$sysconfdir/$keyfile") )
766             {
767                 action("$bindir/ssh-keygen -t $k -f $sysconfdir/$keyfile -N \"\"");
768             }
769         }
770     }
771
772     return 0;
773 }
774
775 ### copySSHDConfigFile( )
776 #
777 # this subroutine 'edits' the paths in sshd_config to suit them to the current environment
778 # in which the setup script is being run.
779 #
780
781 sub copySSHDConfigFile
782 {
783     my($fileInput, $fileOutput);
784     my($mode, $uid, $gid);
785     my($line, $newline);
786     my($privsep_enabled);
787
788     print "Fixing paths in sshd_config...\n";
789
790     $fileInput = "$setupdir/sshd_config.in";
791     $fileOutput = "$sysconfdir/sshd_config";
792
793     #
794     # verify that we are prepared to work with $fileInput
795     #
796
797     if ( !isReadable($fileInput) )
798     {
799         printf("Cannot read $fileInput... skipping.\n");
800         return;
801     }
802
803     #
804     # verify that we are prepared to work with $fileOuput
805     #
806
807     if ( !prepareFileWrite($fileOutput) )
808     {
809         return;
810     }
811
812     #
813     # check to see whether we should enable privilege separation
814     #
815
816     if ( userExists("sshd") && ( -d "/var/empty" ) && ( getOwnerID("/var/empty") eq 0 ) )
817     {
818         setPrivilegeSeparation(1);
819     }
820     else
821     {
822         setPrivilegeSeparation(0);
823     }
824
825     if ( getPrivilegeSeparation() )
826     {
827         $privsep_enabled = "yes";
828     }
829     else
830     {
831         $privsep_enabled = "no";
832     }
833
834     #
835     # Grab the current mode/uid/gid for use later
836     #
837
838     $mode = (stat($fileInput))[2];
839     $uid = (stat($fileInput))[4];
840     $gid = (stat($fileInput))[5];
841
842     #
843     # Open the files for reading and writing, and loop over the input's contents
844     #
845
846     $data = readFile($fileInput);
847
848     # #
849     # # alter the PidFile config
850     # #
851     # 
852     # $text = "PidFile\t$gpath/var/sshd.pid";
853     # $data =~ s:^[\s|#]*PidFile.*$:$text:gm;
854
855     #
856     # set the sftp directive
857     #
858
859     $text = "Subsystem\tsftp\t$gpath/libexec/sftp-server";
860     $data =~ s:^[\s|#]*Subsystem\s+sftp\s+.*$:$text:gm;
861
862     #
863     # set the privilege separation directive
864     #
865
866     $text = "UsePrivilegeSeparation\t${privsep_enabled}";
867     $data =~ s:^[\s|#]*UsePrivilegeSeparation.*$:$text:gm;
868
869     #
870     # dump the modified output to the config file
871     #
872
873     writeFile($fileOutput, $data);
874
875     #
876     # An attempt to revert the new file back to the original file's
877     # mode/uid/gid
878     #
879
880     chmod($mode, $fileOutput);
881     chown($uid, $gid, $fileOutput);
882
883     return 0;
884 }
885
886 ### setPrivilegeSeparation( $value )
887 #
888 # set the privilege separation variable to $value
889 #
890
891 sub setPrivilegeSeparation
892 {
893     my($value) = @_;
894
895     $privsep = $value;
896 }
897
898 ### getPrivilegeSeparation( )
899 #
900 # return the value of the privilege separation variable
901 #
902
903 sub getPrivilegeSeparation
904 {
905     return $privsep;
906 }
907
908 ### prepareFileWrite( $file )
909 #
910 # test $file to prepare for writing to it.
911 #
912
913 sub prepareFileWrite
914 {
915     my($file) = @_;
916
917     if ( isPresent($file) )
918     {
919         printf("$file already exists... ");
920
921         if ( isForced() )
922         {
923             if ( isWritable($file) )
924             {
925                 printf("removing.\n");
926                 action("rm $file");
927                 return 1;
928             }
929             else
930             {
931                 printf("not writable -- skipping.\n");
932                 return 0;
933             }
934         }
935         else
936         {
937             printf("skipping.\n");
938             return 0;
939         }
940     }
941
942     return 1;
943 }
944
945 ### copyConfigFiles( )
946 #
947 # subroutine that copies some extra config files to their proper location in
948 # $GLOBUS_LOCATION/etc/ssh.
949 #
950
951 sub copyConfigFiles
952 {
953     #
954     # copy the sshd_config file into the ssh configuration directory and alter
955     # the paths in the file.
956     #
957
958     copySSHDConfigFile();
959
960     #
961     # do straight copies of the ssh_config and moduli files.
962     #
963
964     printf("Copying ssh_config and moduli to their proper location...\n");
965
966     copyFile("$setupdir/ssh_config", "$sysconfdir/ssh_config");
967     copyFile("$setupdir/moduli", "$sysconfdir/moduli");
968
969     #
970     # copy and alter the SXXsshd script.
971     #
972
973     copySXXScript("$setupdir/SXXsshd.in", "$sbindir/SXXsshd");
974 }
975
976 ### copyFile( $src, $dest )
977 #
978 # copy the file pointed to by $src to the location specified by $dest.  in the
979 # process observe the rules regarding when the '-force' flag was passed to us.
980 #
981
982 sub copyFile
983 {
984     my($src, $dest) = @_;
985
986     if ( !isReadable($src) )
987     {
988         printf("$src is not readable... not creating $dest.\n");
989         return;
990     }
991
992     if ( !prepareFileWrite($dest) )
993     {
994         return;
995     }
996
997     action("cp $src $dest");
998 }
999
1000 ### copySXXScript( $in, $out )
1001 #
1002 # parse the input file, substituting in place the value of GLOBUS_LOCATION, and
1003 # write the result to the output file.
1004 #
1005
1006 sub copySXXScript
1007 {
1008     my($in, $out) = @_;
1009     my($tmpgpath);
1010
1011     if ( !isReadable($in) )
1012     {
1013         printf("$in is not readable... not creating $out.\n");
1014         return;
1015     }
1016
1017     if ( !prepareFileWrite($out) )
1018     {
1019         return;
1020     }
1021
1022     #
1023     # clean up any junk in the globus path variable
1024     #
1025
1026     $tmpgpath = $gpath;
1027     $tmpgpath =~ s:/+:/:g;
1028     $tmpgpath =~ s:([^/]+)/$:\1:g;
1029
1030     #
1031     # read in the script, substitute globus location, then write it back out
1032     #
1033
1034     $data = readFile($in);
1035     $data =~ s|\@GLOBUS_LOCATION\@|$tmpgpath|g;
1036     writeFile($out, $data);
1037     action("chmod 755 $out");
1038 }
1039
1040 ### readFile( $filename )
1041 #
1042 # reads and returns $filename's contents
1043 #
1044
1045 sub readFile
1046 {
1047     my($filename) = @_;
1048     my($data);
1049
1050     open(IN, "$filename") || exitDie "Can't open '$filename': $!";
1051     $/ = undef;
1052     $data = <IN>;
1053     $/ = "\n";
1054     close(IN);
1055
1056     return $data;
1057 }
1058
1059 ### writeFile( $filename, $fileinput )
1060 #
1061 # create the inputs to the ssl program at $filename, appending the common name to the
1062 # stream in the process
1063 #
1064
1065 sub writeFile
1066 {
1067     my($filename, $fileinput) = @_;
1068
1069     #
1070     # test for a valid $filename
1071     #
1072
1073     if ( !defined($filename) || (length($filename) lt 1) )
1074     {
1075         exitDie "Filename is undefined";
1076     }
1077
1078     #
1079     # verify that we are prepared to work with $filename
1080     #
1081
1082     if ( !prepareFileWrite($filename) )
1083     {
1084         return;
1085     }
1086
1087     #
1088     # write the output to $filename
1089     #
1090
1091     open(OUT, ">$filename");
1092     print OUT "$fileinput";
1093     close(OUT);
1094 }
1095
1096 ### action( $command )
1097 #
1098 # run $command within a proper system() command.
1099 #
1100
1101 sub action
1102 {
1103     my($command) = @_;
1104
1105     printf "$command\n";
1106
1107     my $result = system("LD_LIBRARY_PATH=\"$gpath/lib:\$LD_LIBRARY_PATH\"; $command 2>&1");
1108
1109     if (($result or $?) and $command !~ m!patch!)
1110     {
1111         exitDie "ERROR: Unable to execute command: $!\n";
1112     }
1113 }
1114
1115 ### exitDie( $error )
1116 #
1117 # a horribly named method meant to look like die but only exit, thereby not causing
1118 # gpt-postinstall to croak.
1119 #
1120
1121 sub exitDie
1122 {
1123     my($error) = @_;
1124
1125     print $error;
1126     exit;
1127 }
1128
1129 ### query_boolean( $query_text, $default )
1130 #
1131 # query the user with a string, and expect a response.  If the user hits
1132 # 'enter' instead of entering an input, then accept the default response.
1133 #
1134
1135 sub query_boolean
1136 {
1137     my($query_text, $default) = @_;
1138     my($nondefault, $foo, $bar);
1139
1140     if ( !$prompt )
1141     {
1142         print "Prompt suppressed.  Continuing...\n";
1143         return "y";
1144     }
1145
1146     #
1147     # Set $nondefault to the boolean opposite of $default.
1148     #
1149
1150     if ($default eq "n")
1151     {
1152         $nondefault = "y";
1153     }
1154     else
1155     {
1156         $nondefault = "n";
1157     }
1158
1159     print "${query_text} ";
1160     print "[$default] ";
1161
1162     $foo = <STDIN>;
1163     ($bar) = split //, $foo;
1164
1165     if ( grep(/\s/, $bar) )
1166     {
1167         # this is debatable.  all whitespace means 'default'
1168
1169         $bar = $default;
1170     }
1171     elsif ($bar eq '')
1172     {
1173         $bar = $default;
1174     }
1175     elsif ($bar ne $default)
1176     {
1177         # everything else means 'nondefault'.
1178
1179         $bar = $nondefault;
1180     }
1181     else
1182     {
1183         # extraneous step.  to get here, $bar should be eq to $default anyway.
1184
1185         $bar = $default;
1186     }
1187
1188     return $bar;
1189 }
1190
1191 ### absolutePath( $file )
1192 #
1193 # converts a given pathname into a canonical path using the abs_path function.
1194 #
1195
1196 sub absolutePath
1197 {
1198     my($file) = @_;
1199     my $home = $ENV{'HOME'};
1200     $file =~ s!~!$home!;
1201     my $startd = cwd();
1202     $file =~ s!^\./!$startd/!;
1203     $file = "$startd/$file" if $file !~ m!^\s*/!;
1204     $file = abs_path($file);
1205     return $file;
1206 }
1207
1208 ### getOwnerID( $file )
1209 #
1210 # return the uid containing the owner ID of the given file.
1211 #
1212
1213 sub getOwnerID
1214 {
1215     my($file) = @_;
1216     my($uid);
1217
1218     #
1219     # call stat() to get the mode of the file
1220     #
1221
1222     $uid = (stat($file))[4];
1223
1224     return $uid;
1225 }
1226
1227 ### getMode( $file )
1228 #
1229 # return a string containing the mode of the given file.
1230 #
1231
1232 sub getMode
1233 {
1234     my($file) = @_;
1235     my($tempmode, $mode);
1236
1237     #
1238     # call stat() to get the mode of the file
1239     #
1240
1241     $tempmode = (stat($file))[2];
1242     if (length($tempmode) < 1)
1243     {
1244         return "";
1245     }
1246
1247     #
1248     # call sprintf to format the mode into a UNIX-like string
1249     #
1250
1251     $mode = sprintf("%04o", $tempmode & 07777);
1252
1253     return $mode;
1254 }
1255
1256 ### userExists( $username )
1257 #
1258 # given a username, return true if the user exists on the system.  return false
1259 # otherwise.
1260 #
1261
1262 sub userExists
1263 {
1264     my($username) = @_;
1265     my($uid);
1266
1267     #
1268     # retrieve the userid of the user with the given username
1269     #
1270
1271     $uid = getpwnam($username);
1272
1273     #
1274     # return true if $uid is defined and has a length greater than 0
1275     #
1276
1277     if ( defined($uid) and (length($uid) > 0) )
1278     {
1279         return 1;
1280     }
1281     else
1282     {
1283         return 0;
1284     }
1285 }
This page took 0.13526 seconds and 3 git commands to generate.