--- 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