vpn
changeset 2 5f08067bc677
parent 1 a5a1e5f284d2
equal deleted inserted replaced
1:a5a1e5f284d2 2:5f08067bc677
     1 #! /usr/bin/perl
     1 #! /usr/bin/perl -T
     2 # $Id$
     2 # $Id$
     3 # $URL$
     3 # $URL$
     4 # based on a version Uwe Werler downloaded from f5networks developer
     4 # based on a version Uwe Werler downloaded from f5networks developer
     5 # area http://devcentral.f5.com/SDK/sslvpn.public.pl.txt
     5 # area http://devcentral.f5.com/SDK/sslvpn.public.pl.txt
     6 
     6 
     8 use strict;
     8 use strict;
     9 use warnings;
     9 use warnings;
    10 use Getopt::Long qw(:config no_ignore_case bundling);
    10 use Getopt::Long qw(:config no_ignore_case bundling);
    11 use Pod::Usage;
    11 use Pod::Usage;
    12 use File::Basename;
    12 use File::Basename;
       
    13 use English qw(-no_match_vars);
       
    14 
       
    15 ($EUID, $UID) = ($UID, $EUID);    # release ROOT
       
    16 ($0) = ($0 =~ /(\w+)/);           # untaint $0
    13 
    17 
    14 use constant ME => basename $0;
    18 use constant ME => basename $0;
       
    19 
       
    20 delete @ENV{ grep /PATH/, keys %ENV };
       
    21 $ENV{PATH} = "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/sbin:/bin";
    15 
    22 
    16 ###
    23 ###
    17 ### STEP 0 :: Verify that we have the necessary requirements.
    24 ### STEP 0 :: Verify that we have the necessary requirements.
    18 ###
    25 ###
    19 ### This script requires recent versions of Perl, OpenSSL and PPPD (including
    26 ### This script requires recent versions of Perl, OpenSSL and PPPD (including
    30 
    37 
    31 # Default values for the FQDN or IP of the FirePass we wish to connect to, the
    38 # Default values for the FQDN or IP of the FirePass we wish to connect to, the
    32 # name of our Network Access favorite, and our username/pasword.  All of these
    39 # name of our Network Access favorite, and our username/pasword.  All of these
    33 # can be passed as arguments, if desired.
    40 # can be passed as arguments, if desired.
    34 
    41 
    35 my $user;
    42 my $opt_user;
    36 my $passcode;
    43 my $opt_passcode;
    37 my $opt_host = 'connectwdf.sap.com';
    44 my $opt_host = 'connectwdf.sap.com';
    38 my $opt_name = 'SAP Network Access';
    45 my $opt_name = 'SAP Network Access';
    39 my $opt_help = 0;
    46 my $opt_help = 0;
    40 my $opt_man  = 0;
    47 my $opt_man  = 0;
    41 my @ppp_opts = ();
    48 my @ppp_opts = ();
    43 my $opt_script;
    50 my $opt_script;
    44 
    51 
    45 MAIN: {
    52 MAIN: {
    46 
    53 
    47     GetOptions(
    54     GetOptions(
    48         "u|user=s"     => \$user,
    55         "u|user=s"     => \$opt_user,
    49         "p|passcode=s" => \$passcode,
    56         "p|passcode=s" => \$opt_passcode,
    50         "H|host=s"     => \$opt_host,
    57         "H|host=s"     => \$opt_host,
    51         "n|favorite=s" => \$opt_name,
    58         "n|favorite=s" => \$opt_name,
    52         "d|debug"      => \$opt_debug,
    59         "d|debug"      => \$opt_debug,
    53         "o|opts=s"     => \@ppp_opts,
    60         "o|opts=s"     => \@ppp_opts,
    54         "h|help"       => \$opt_help,
    61         "h|help"       => \$opt_help,
    55         "m|man"        => \$opt_man,
    62         "m|man"        => \$opt_man,
    56         "s|script"     => \$opt_script,
    63         "s|script"     => \$opt_script,
    57     ) or pod2usage();
    64     ) or pod2usage();
    58 
    65 
    59     die ME . ": need to run with root permissions!\n" if $> != 0;
       
    60 
       
    61     pod2usage(-verbose => 1, -exitval => 0) if $opt_help;
    66     pod2usage(-verbose => 1, -exitval => 0) if $opt_help;
    62     pod2usage(-verbose => 2, -exitval => 0) if $opt_man;
    67     pod2usage(-verbose => 2, -exitval => 0) if $opt_man;
    63     pod2usage(-verbose => 0, -exitval => 0) if not defined $user;
    68     pod2usage(-verbose => 0, -exitval => 0) if not defined $opt_user;
    64 
    69 
    65     if (not defined $passcode) {
    70     (my $user) = ($opt_user =~ /([a-z]\d+)/i);
       
    71     die ME . ": username \"$opt_user\" didn't pass verification\n"
       
    72       if $user ne $opt_user;
       
    73 
       
    74     die ME . ": need to run with root permissions!\n"
       
    75       if not $EUID == 0 || $UID == 0;
       
    76 
       
    77     if (not defined $opt_passcode) {
    66         chomp(my $settings = qx{stty "-g"});
    78         chomp(my $settings = qx{stty "-g"});
    67         open(IN, "/dev/tty") or die ME . ": Can't open /dev/tty: $!\n";
    79         open(IN, "/dev/tty") or die ME . ": Can't open /dev/tty: $!\n";
    68         print "Passcode: ";
    80         print "Passcode for $opt_user: ";
    69         system stty => "-echo";
    81         system stty => "-echo";
    70         chomp($passcode = <IN>);
    82         chomp($opt_passcode = <IN>);
    71         system stty => $settings;
    83         system stty => $settings;
    72         print "\n";
    84         print "\n";
    73     }
    85     }
    74 
    86 
    75     pod2usage(-verbose => 0, -exitval => 0) if not defined $passcode;
    87     pod2usage(-verbose => 0, -exitval => 0) if not defined $opt_passcode;
       
    88     (my $passcode) = ($opt_passcode =~ /(\d+)/i);
       
    89     die ME . ": passcode didn't pass verification\n"
       
    90       if $passcode ne $opt_passcode;
       
    91 
    76     -x $opt_script
    92     -x $opt_script
    77       or die ME . ": Script $opt_script is not executable: $!\n"
    93       or die ME . ": Script $opt_script is not executable: $!\n"
    78       if defined $opt_script;
    94       if defined $opt_script;
    79 
    95 
    80     push @ppp_opts, "nodetach" if $opt_debug;
    96     push @ppp_opts, "nodetach" if $opt_debug;
   162 # pages/objects.  It's time to start our SSL VPN connection.  To do this, we are
   178 # pages/objects.  It's time to start our SSL VPN connection.  To do this, we are
   163 # simply calling PPPD, and having it use OpenSSL as a psuedo terminal device.
   179 # simply calling PPPD, and having it use OpenSSL as a psuedo terminal device.
   164     $request = "GET /myvpn?sess=${sessionid} HTTP/1.0\r\n"
   180     $request = "GET /myvpn?sess=${sessionid} HTTP/1.0\r\n"
   165       . "Cookie: MRHSession=${sessionid}\r\n" . "\r\n";
   181       . "Cookie: MRHSession=${sessionid}\r\n" . "\r\n";
   166     $request = "chat -v '' '${request}'";
   182     $request = "chat -v '' '${request}'";
   167     system(
   183 
   168         pppd     => @ppp_opts,
   184     {
   169         pty      => ${openssl},
   185         local $EUID = $UID;    # get ROOT, the pppd want's to see
   170         connect  => ${request},
   186                                # the UID and the EUID to be ROOT
   171         linkname => "sap-vpn",
   187         system(
   172         qw(noauth crtscts passive noproxyarp
   188             pppd     => @ppp_opts,
   173           local),
   189             pty      => ${openssl},
   174     );
   190             connect  => ${request},
       
   191             linkname => "sap-vpn",
       
   192             qw(noauth crtscts passive noproxyarp
       
   193               local),
       
   194         );
       
   195     }
   175 
   196 
   176     # Voila!  We should now have a PPP connection running over SSL.  We can exit
   197     # Voila!  We should now have a PPP connection running over SSL.  We can exit
   177     # from this script cleanly, and move on to setting up routes to the remote
   198     # from this script cleanly, and move on to setting up routes to the remote
   178     # network using our favorite networking tools.  Happy hacking!
   199     # network using our favorite networking tools.  Happy hacking!
   179 
   200 
   193  vpn [-m|--man]
   214  vpn [-m|--man]
   194 
   215 
   195 =head1 DESCRIPTION
   216 =head1 DESCRIPTION
   196 
   217 
   197 Ths script establishes a VPN connecttion to a FirePass server.
   218 Ths script establishes a VPN connecttion to a FirePass server.
   198 B<Note:> This script requires root privileges and should be run via sudo
   219 B<Note:> This script requires B<root> privileges and should be run via sudo
   199 or some other approbiate mechanism.
   220 or some other approbiate mechanism. (You may install it SUID root. This
       
   221 is the safest way, since the script rises its privileges only when
       
   222 necessary, instead of operating all the time as root.)
   200 
   223 
   201 =head1 OPTIONS
   224 =head1 OPTIONS
   202 
   225 
   203 =over
   226 =over
   204 
   227