vpn
changeset 2 5f08067bc677
parent 1 a5a1e5f284d2
--- a/vpn	Thu Oct 16 18:11:38 2008 +0000
+++ b/vpn	Thu Nov 13 10:16:29 2008 +0000
@@ -1,4 +1,4 @@
-#! /usr/bin/perl
+#! /usr/bin/perl -T
 # $Id$
 # $URL$
 # based on a version Uwe Werler downloaded from f5networks developer
@@ -10,9 +10,16 @@
 use Getopt::Long qw(:config no_ignore_case bundling);
 use Pod::Usage;
 use File::Basename;
+use English qw(-no_match_vars);
+
+($EUID, $UID) = ($UID, $EUID);    # release ROOT
+($0) = ($0 =~ /(\w+)/);           # untaint $0
 
 use constant ME => basename $0;
 
+delete @ENV{ grep /PATH/, keys %ENV };
+$ENV{PATH} = "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/sbin:/bin";
+
 ###
 ### STEP 0 :: Verify that we have the necessary requirements.
 ###
@@ -32,8 +39,8 @@
 # name of our Network Access favorite, and our username/pasword.  All of these
 # can be passed as arguments, if desired.
 
-my $user;
-my $passcode;
+my $opt_user;
+my $opt_passcode;
 my $opt_host = 'connectwdf.sap.com';
 my $opt_name = 'SAP Network Access';
 my $opt_help = 0;
@@ -45,8 +52,8 @@
 MAIN: {
 
     GetOptions(
-        "u|user=s"     => \$user,
-        "p|passcode=s" => \$passcode,
+        "u|user=s"     => \$opt_user,
+        "p|passcode=s" => \$opt_passcode,
         "H|host=s"     => \$opt_host,
         "n|favorite=s" => \$opt_name,
         "d|debug"      => \$opt_debug,
@@ -56,23 +63,32 @@
         "s|script"     => \$opt_script,
     ) or pod2usage();
 
-    die ME . ": need to run with root permissions!\n" if $> != 0;
-
     pod2usage(-verbose => 1, -exitval => 0) if $opt_help;
     pod2usage(-verbose => 2, -exitval => 0) if $opt_man;
-    pod2usage(-verbose => 0, -exitval => 0) if not defined $user;
+    pod2usage(-verbose => 0, -exitval => 0) if not defined $opt_user;
 
-    if (not defined $passcode) {
+    (my $user) = ($opt_user =~ /([a-z]\d+)/i);
+    die ME . ": username \"$opt_user\" didn't pass verification\n"
+      if $user ne $opt_user;
+
+    die ME . ": need to run with root permissions!\n"
+      if not $EUID == 0 || $UID == 0;
+
+    if (not defined $opt_passcode) {
         chomp(my $settings = qx{stty "-g"});
         open(IN, "/dev/tty") or die ME . ": Can't open /dev/tty: $!\n";
-        print "Passcode: ";
+        print "Passcode for $opt_user: ";
         system stty => "-echo";
-        chomp($passcode = <IN>);
+        chomp($opt_passcode = <IN>);
         system stty => $settings;
         print "\n";
     }
 
-    pod2usage(-verbose => 0, -exitval => 0) if not defined $passcode;
+    pod2usage(-verbose => 0, -exitval => 0) if not defined $opt_passcode;
+    (my $passcode) = ($opt_passcode =~ /(\d+)/i);
+    die ME . ": passcode didn't pass verification\n"
+      if $passcode ne $opt_passcode;
+
     -x $opt_script
       or die ME . ": Script $opt_script is not executable: $!\n"
       if defined $opt_script;
@@ -164,14 +180,19 @@
     $request = "GET /myvpn?sess=${sessionid} HTTP/1.0\r\n"
       . "Cookie: MRHSession=${sessionid}\r\n" . "\r\n";
     $request = "chat -v '' '${request}'";
-    system(
-        pppd     => @ppp_opts,
-        pty      => ${openssl},
-        connect  => ${request},
-        linkname => "sap-vpn",
-        qw(noauth crtscts passive noproxyarp
-          local),
-    );
+
+    {
+        local $EUID = $UID;    # get ROOT, the pppd want's to see
+                               # the UID and the EUID to be ROOT
+        system(
+            pppd     => @ppp_opts,
+            pty      => ${openssl},
+            connect  => ${request},
+            linkname => "sap-vpn",
+            qw(noauth crtscts passive noproxyarp
+              local),
+        );
+    }
 
     # Voila!  We should now have a PPP connection running over SSL.  We can exit
     # from this script cleanly, and move on to setting up routes to the remote
@@ -195,8 +216,10 @@
 =head1 DESCRIPTION
 
 Ths script establishes a VPN connecttion to a FirePass server.
-B<Note:> This script requires root privileges and should be run via sudo
-or some other approbiate mechanism.
+B<Note:> This script requires B<root> privileges and should be run via sudo
+or some other approbiate mechanism. (You may install it SUID root. This
+is the safest way, since the script rises its privileges only when
+necessary, instead of operating all the time as root.)
 
 =head1 OPTIONS