sap-vpn.pl
changeset 11 16e6b1683c63
parent 10 13b84a92a65a
child 12 8cd92042fb8b
child 14 5682bf09533c
--- a/sap-vpn.pl	Fri Nov 14 23:07:00 2008 +0000
+++ b/sap-vpn.pl	Tue Jan 06 07:27:55 2009 +0000
@@ -11,13 +11,15 @@
 use Pod::Usage;
 use File::Basename;
 use English qw(-no_match_vars);
+use lib ".";
+
+my $use_lwp = -f "lwp";
 
 ($EUID, $UID) = ($UID, $EUID);    # release ROOT, doesn't harm, if not suid
 ($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";
 
@@ -63,6 +65,7 @@
 
 sub verbose(@) { print STDERR @_ if $opt_verbose }
 sub debug(@)   { warn @_         if $opt_debug }
+sub ohshit(@) { die ME . ": ", @_ }
 sub do_kill($);
 
 MAIN: {
@@ -91,34 +94,34 @@
 
     $opt_verbose += $opt_debug;
 
-    untaint($opt_linkname) or die ME . ": linkname didn't pass verification\n";
+    untaint($opt_linkname) or ohshit "linkname didn't pass verification\n";
     untaint($opt_script)
-      or die ME . ": script name didn't pass verification\n"
+      or ohshit "script name didn't pass verification\n"
       if $opt_script;
     map { untaint } @ppp_opts;
 
-    die ME . ": need to run with root permissions!\n"
+    ohshit "need to run with root permissions!\n"
       if not $EUID == 0 || $UID == 0;
 
     exit do_kill($opt_linkname) if $opt_kill;
 
     untaint($opt_user)
-      or die ME . ": username didn't pass verification\n";
+      or ohshit "username didn't pass verification\n";
 
     if (not defined $opt_passcode) {
         chomp(my $settings = qx{stty "-g"});
-        open(IN, "/dev/tty") or die ME . ": Can't open /dev/tty: $!\n";
+        open(IN, "/dev/tty") or ohshit "Can't open /dev/tty: $!\n";
         print "Passcode for $opt_user: ";
         system stty => "-echo";
         chomp($opt_passcode = <IN>);
         system stty => $settings;
         print "\n";
     }
-    untaint($opt_passcode) or die ME . ": passcode didn't pass verification\n";
+    untaint($opt_passcode) or ohshit "passcode didn't pass verification\n";
     pod2usage(-verbose => 0, -exitval => 0) if not defined $opt_passcode;
 
     -x $opt_script
-      or die ME . ": Script $opt_script is not executable: $!\n"
+      or ohshit "Script $opt_script is not executable: $!\n"
       if defined $opt_script;
 
     push @ppp_opts, $opt_debug ? qw(nodetach debug dump) : qw(nolog updetach);
@@ -138,16 +141,42 @@
 
     # Make initial request to get client_data
     verbose "% initial request\n";
-    $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";
+
+    my $client_data;
+    my $ua;
+    my $cookies;
+
+    if (!$use_lwp) {
+        $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 ohshit "Invalid Host specified or not reachable: $opt_host\n";
 
-    $response = qx(echo "${request}" | ${openssl} 2>/dev/null)
-      or die ME . ": Invalid Host specified or not reachable: $opt_host\n";
+    }
+    else {
+        use LWP::UserAgent;
+        use HTTP::Request::Common;
+        use HTTP::Status;
+	use HTTP::Cookies;
+	#use LWP::Debug qw(+);
+	$cookies = new HTTP::Cookies;
+        $ua = new LWP::UserAgent;
+        $ua->agent("");
+        $ua->env_proxy;
+	$ua->cookie_jar($cookies);
+        $response = $ua->get("https://$opt_host:443/my.logon.php3?check=1");
+
+        ohshit "initial failed with http code @{[$response->message]}\n"
+          unless $response->is_success;
+
+        $response = $response->as_string;
+    }
 
     $response =~ s/<INPUT type="hidden" name="client_data" value="(.*)">/$1/;
-    my $client_data = $1;
+    $client_data = $1;
 
 ###
 ### STEP 2 :: Log in to FirePass.
@@ -159,27 +188,49 @@
   # 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 =
+
+    if (!$use_lwp) {
+        $request =
 "check=1&username=${opt_user}&password=${opt_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";
+        $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);
+        $response = qx(echo "${request}" | ${openssl} 2>/dev/null);
+    }
+    else {
+        $response = $ua->post(
+            "https://$opt_host:443/my.activation.php3",
+            check        => 1,
+            username     => $opt_user,
+            password     => $opt_passcode,
+            mrhlogonform => 1,
+            client_data  => $client_data
+        );
+
+        ohshit "login failed with http code @{[$response->message]}\n"
+          unless $response->is_success;
+
+        $response = $response->as_string;
+    }
 
   # 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;
     verbose "% session id ${sessionid}\n";
 
+    $cookies->set_cookie(0, MRHSession => $sessionid, "/", $opt_host, 443, 1, 0, 10, 0, {});
+    #warn $cookies->as_string;
+
 ###
 ### STEP 3 :: Create the SSL VPN tunnel.
 ###
@@ -189,17 +240,33 @@
    # 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);
+    #if (!$use_lwp) {
+    if (1) {
+        $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);
+    }
+    else {
+        $response = $ua->get("https://$opt_host:443/vdesk/vpn/index.php3?outform=xml");
+
+        ohshit "creating tunnel failed with http code @{[$response->message]}\n"
+          unless $response->is_success;
+
+	$response = $response->as_string;
+    }
 
  # 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.
+ open(X, ">response.out") or die;
+ print X $response;
+
     $response =~ /${opt_name}[^\n]+\n[^Z]+Z=\d+,(\d+)/;
     $favorite = $1;
     verbose "% favorite ${favorite}\n";
 
+    exit;
+
     # 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}",) {
@@ -217,7 +284,7 @@
 
     {
         my $pid = fork();    # this way we've better control
-        die ME . ": can't fork: $!\n" if not defined $pid;
+        ohshit "can't fork: $!\n" if not defined $pid;
 
         if ($pid == 0) {
             $EUID = $UID;    # get ROOT, the pppd want's to see
@@ -228,11 +295,11 @@
                 connect  => ${request},
                 linkname => $opt_linkname,
                 qw(noauth crtscts passive noproxyarp local)
-            ) or die ME . ": Can't exec: $!\n";
+            ) or ohshit "Can't exec: $!\n";
 
         }
         wait;
-        die ME . ": pppd didn't return sucessfully (rc: @{[$? >> 8]})\n" if $?;
+        ohshit "pppd didn't return sucessfully (rc: @{[$? >> 8]})\n" if $?;
     }
 
     # now executing the script
@@ -241,13 +308,13 @@
     if (defined $opt_script and not $opt_debug) {
 
         my $pid = fork();
-        die ME . ": Can't fork: $!\n" if not defined $pid;
+        ohshit "Can't fork: $!\n" if not defined $pid;
 
         if ($pid == 0) {    # child
 
             if ($UID != $EUID) {
                 my ($owner, $group) = (stat $opt_script)[ 4, 5 ];
-                die ME . ": can't stat $opt_script\n" if not defined $owner;
+                ohshit "can't stat $opt_script\n" if not defined $owner;
 
                 $UID = $EUID = $owner;
                 $GID = $EGID = $group;
@@ -257,7 +324,7 @@
               "% executing script $opt_script with uid $UID and gid $GID\n";
 
             exec $opt_script
-              or die ME . ": Can't exec $opt_script: $!\n";
+              or ohshit "Can't exec $opt_script: $!\n";
         }
         $pid = wait;
         verbose "% script returned $?\n";
@@ -275,7 +342,7 @@
 sub do_kill($) {
     my $linkname = shift;
     open((my $fh), $_ = "/var/run/ppp-$linkname.pid")
-      or die ME . ": Can't open the link file \"$_\": $!\n";
+      or ohshit "Can't open the link file \"$_\": $!\n";
 
     my $pid   = <$fh>;
     my $iface = <$fh>;
@@ -284,10 +351,10 @@
 
     # become root doesn't seem to be necessary, as long as our
     # real uid is 0
-    kill 15, $pid or die ME . ": Can't kill pid $pid: $!\n";
+    kill 15, $pid or ohshit "Can't kill pid $pid: $!\n";
 
     waitpid $pid, 0 != -1
-      or die ME . ": was not able to wait for the ppp process: $!\n";
+      or ohshit "was not able to wait for the ppp process: $!\n";
 
     verbose "% process killed, rc: "
       . ($? >> 8)
@@ -308,8 +375,8 @@
 
  sap-vpn [-l|--linkname <link name>] -k|--kill
 
- sap-vpn [-h|--help]
- sap-vpn [-m|--man]
+ sap-vpn -h|--help
+ sap-vpn -m|--man
 
 =head1 DESCRIPTION