--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.perltidyrc Thu Oct 16 16:50:38 2008 +0000
@@ -0,0 +1,1 @@
+--paren-tightness=2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vpn Thu Oct 16 16:50:38 2008 +0000
@@ -0,0 +1,228 @@
+#! /usr/bin/perl
+
+# based on a version Uwe Werler downloaded from f5networks developer
+# area
+
+use 5.8.8;
+use strict;
+use warnings;
+use Getopt::Long qw(:config no_ignore_case bundling);
+use Pod::Usage;
+use File::Basename;
+
+use constant ME => basename $0;
+
+###
+### 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 $user;
+my $passcode;
+my $host = 'connectwdf.sap.com';
+my $name = 'SAP Network Access';
+my $opt_help = 0;
+my $opt_man = 0;
+my $debug;
+my $ppp_opts = [];
+my $opt_script;
+
+MAIN: {
+
+ GetOptions(
+ "u|user=s" => \$user,
+ "p|passcode=s" => \$passcode,
+ "H|host=s" => \$host,
+ "n|favorite=s" => \$name,
+ "d|debug" => \$debug,
+ "o|opts=s" => $ppp_opts,
+ "h|help" => \$opt_help,
+ "m|man" => \$opt_man,
+ "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;
+
+ if (not defined $passcode) {
+ chomp(my $settings = qx{stty "-g"});
+ open(IN, "/dev/tty") or die "Can't open /dev/tty: $!\n";
+ print "Passcode: ";
+ system stty => "-echo";
+ chomp($passcode = <IN>);
+ system stty => $settings;
+ print "\n";
+ }
+
+ pod2usage(-verbose => 0, -exitval => 0) if not defined $passcode;
+
+ push @$ppp_opts, "nodetach" if !@$ppp_opts;
+ push @$ppp_opts, $debug ? "debug" : "nolog";
+ push @$ppp_opts, "nodefaultroute" if not grep /^defaultroute$/, @$ppp_opts;
+ $ppp_opts = join(" ", @$ppp_opts);
+ print "\nPPP-Options: $ppp_opts\n" if $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 ${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 "Invalid Host spezified or not reachable: $host\n";
+
+ $response =~ s/<INPUT type="hidden" name="client_data" value="(.*)">/$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: ${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 $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 =~ /${name}[^\n]+\n[^Z]+Z=\d+,(\d+)/;
+ $favorite = $1;
+ print "Favorite: ${favorite}\n" if $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}'";
+ system(
+"pppd ${ppp_opts} noauth crtscts passive noproxyarp local pty \"${openssl}\" connect \"${request}\""
+ );
+
+ # 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 <host>] [-o|--opt <ppp option>]...
+ [-s|--script <script>]
+ [-u|--user <user>] [-p|--passcode <passcode>]
+
+ vpn [-h|--help]
+ vpn [-m|--man]
+
+=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.
+
+=head1 OPTIONS
+
+
+=over
+
+=item B<-u>|B<--user> I<user>
+
+Your D|C|I user, not really optional. (no default)
+
+=item B<-p>|B<--passcode> I<passcode>
+
+Your passcode, if not supplied, F</dev/tty> is opened for reading
+the passcode. (no default)
+
+=item B<-H>|B<--host> I<host>
+
+Host to connect to. (defaults to C<connectwdf.sap.corp>)
+
+=item B<-n>|B<--name> I<name>
+
+Name of the service(?). (default: to 'SAP Network Access')
+
+=item B<-d>
+
+Print debug output from pppd. (default: 0)
+
+=item B<-o>|B<--opts> I<ppp options>
+
+Additional options for ppp. Can be specified multiple times. (default: nodetach)
+Good choices are C<detach>, or C<updetach>.
+B<Note:> The C<nodefaultroute> is set automatically.
+
+=back
+
+=cut
+
+###
+### End of file.
+###