diff -r 5f08067bc677 -r 01314d620fe0 vpn --- a/vpn Thu Nov 13 10:16:29 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,282 +0,0 @@ -#! /usr/bin/perl -T -# $Id$ -# $URL$ -# based on a version Uwe Werler downloaded from f5networks developer -# area http://devcentral.f5.com/SDK/sslvpn.public.pl.txt - -use 5.8.8; -use strict; -use warnings; -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. -### -### This script requires recent versions of Perl, OpenSSL and PPPD (including -### the 'chat' program), and that they all be in our PATH. This script was -### written and tested with the following versions: -### FirePass: 5.5 and 6.0 -### Perl: 5.8.8 -### OpenSSL: 0.9.8b -### PPPD: 2.4.4 - -### -### STEP 1 :: Set up variables with the proper information to log in. -### - -# Default values for the FQDN or IP of the FirePass we wish to connect to, the -# name of our Network Access favorite, and our username/pasword. All of these -# can be passed as arguments, if desired. - -my $opt_user; -my $opt_passcode; -my $opt_host = 'connectwdf.sap.com'; -my $opt_name = 'SAP Network Access'; -my $opt_help = 0; -my $opt_man = 0; -my @ppp_opts = (); -my $opt_debug; -my $opt_script; - -MAIN: { - - GetOptions( - "u|user=s" => \$opt_user, - "p|passcode=s" => \$opt_passcode, - "H|host=s" => \$opt_host, - "n|favorite=s" => \$opt_name, - "d|debug" => \$opt_debug, - "o|opts=s" => \@ppp_opts, - "h|help" => \$opt_help, - "m|man" => \$opt_man, - "s|script" => \$opt_script, - ) or pod2usage(); - - pod2usage(-verbose => 1, -exitval => 0) if $opt_help; - pod2usage(-verbose => 2, -exitval => 0) if $opt_man; - pod2usage(-verbose => 0, -exitval => 0) if not defined $opt_user; - - (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 for $opt_user: "; - system stty => "-echo"; - chomp($opt_passcode = ); - system stty => $settings; - print "\n"; - } - - 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; - - push @ppp_opts, "nodetach" if $opt_debug; - push @ppp_opts, $opt_debug ? "debug" : "nolog"; - push @ppp_opts, "nodefaultroute" if not grep /^defaultroute$/, @ppp_opts; - print "\nPPP-Options: @ppp_opts\n" if $opt_debug; - - # Declare variables used throughout the rest of the script. - my ($request, $response, $sessionid, $favorite); - - # Store the OpenSSL command in a variable for convienence. - my $openssl = - "openssl s_client" - . (-d "/etc/ssl/certs" ? " -CApath /etc/ssl/certs" : "") - . " -ign_eof -quiet -connect ${opt_host}:443"; - - # Make initial request to get client_data - $request = - "GET /my.logon.php3?check=1 HTTP/1.0\r\n" - . "Content-Type: application/x-www-form-urlencoded\r\n" - . "Connection: close\r\n" . "\r\n"; - - $response = qx(echo "${request}" | ${openssl} 2>/dev/null) - or die ME . ": Invalid Host specified or not reachable: $opt_host\n"; - - $response =~ s//$1/; - my $client_data = $1; - -### -### STEP 2 :: Log in to FirePass. -### - - # This is the bare minimum required in order to successfully log in. A normal - # browser will make many more requests than this to complete the log in - # sequence, but all that is required is this POST with our credentails. This - # may fail if the FirePass has End-Point Security Policies configured. - $request = -"check=1&username=${user}&password=${passcode}&mrhlogonform=1&client_data=${client_data}"; - - $request = - "POST /my.activation.php3 HTTP/1.0\r\n" - . "Host: ${opt_host}\r\n" - . "Content-Type: application/x-www-form-urlencoded\r\n" - . "Content-Length: " - . length($request) . "\r\n" - . "Connection: close\r\n" . "\r\n" - . "${request}\r\n"; - - $response = qx(echo "${request}" | ${openssl} 2>/dev/null); - - # We can then parse the response for the MRHSession Cookie, which contains our - # SessionID. In this example, we print out the SessionID in order to verify - # that our log in attempt worked. - $response =~ /MRHSession=(\w+);/; - $sessionid = $1; - print "SessionID: ${sessionid}\n" if $opt_debug; - -### -### STEP 3 :: Create the SSL VPN tunnel. -### - - # Now that we are authenticated and have a valid SessionID, we must request - # specific pages/objects in order to initiate a SSL VPN tunnel. Before we do - # this, let's determine the resource locator for our Network Access favorite. - $request = "GET /vdesk/vpn/index.php3?outform=xml HTTP/1.0\r\n" - . "Cookie: MRHSession=${sessionid}\r\n" . "\r\n"; - $response = qx(echo "${request}" | ${openssl} 2>/dev/null); - - # The response is XML, so we can safely grab what we are looking for using some - # regular expression magic. Same with the SessionID, we're printing out the - # final value to make sure we're on the right track. - $response =~ /${opt_name}[^\n]+\n[^Z]+Z=\d+,(\d+)/; - $favorite = $1; - print "Favorite: ${favorite}\n" if $opt_debug; - - # We're all set! Let's visit the necessary pages/objects to notify FirePass - # that we wish to open a SSL VPN tunnel. - foreach my $uri ("/vdesk/", "/vdesk/vpn/connect.php3?Z=0,${favorite}",) { - $request = "GET ${uri} HTTP/1.0\r\n" - . "Cookie: MRHSession=${sessionid}\r\n" . "\r\n"; - system("echo \"${request}\" | ${openssl} >/dev/null 2>&1"); - } - -# We are now authenticated, and have requested the necessary pre-tunnel -# pages/objects. It's time to start our SSL VPN connection. To do this, we are -# simply calling PPPD, and having it use OpenSSL as a psuedo terminal device. - $request = "GET /myvpn?sess=${sessionid} HTTP/1.0\r\n" - . "Cookie: MRHSession=${sessionid}\r\n" . "\r\n"; - $request = "chat -v '' '${request}'"; - - { - 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 - # network using our favorite networking tools. Happy hacking! - - exit(0); - -} - -__END__ - -=head1 SYNOPSIS - - vpn [-d|--debug] [-H|--host ] [-o|--opt ]... - [-s|--script