sap-vpn.pl
changeset 7 f9fbeced9093
parent 6 9ff263c701ef
child 8 9f1f562a69a1
--- a/sap-vpn.pl	Thu Nov 13 21:19:48 2008 +0000
+++ b/sap-vpn.pl	Thu Nov 13 22:12:32 2008 +0000
@@ -13,7 +13,7 @@
 use English qw(-no_match_vars);
 
 ($EUID, $UID) = ($UID, $EUID);    # release ROOT, doesn't harm, if not suid
-($0) = ($0 =~ /([\/\w-]+)/);      # untaint $0
+($0) = ($0 =~ /([.\/\w-]+)/);     # untaint $0
 
 use constant ME => basename $0;
 
@@ -50,15 +50,18 @@
 my $opt_debug    = 0;
 my $opt_verbose  = 0;
 my $opt_script;
-my $opt_ppp = 1;
+my $opt_ppp  = 1;
+my $opt_kill = 0;
 
-sub untaint($) {
-    my ($x) = ($_[0] =~ /([\/\w.-]+)/i);
-    return $_[0] = $_[0] eq $x ? $x : undef;
+sub untaint(;$) {
+    my $ref = @_ ? \$_[0] : \$_;
+    my ($x) = ($$ref =~ /([\/\w.-]+)/i);
+    return $$ref = $$ref eq $x ? $x : undef;
 }
 
 sub verbose(@) { print STDERR @_ if $opt_verbose }
 sub debug(@)   { warn @_         if $opt_debug }
+sub do_kill($);
 
 MAIN: {
 
@@ -75,20 +78,31 @@
         "l|linkname"   => \$opt_linkname,
         "ppp!"         => \$opt_ppp,
         "v|verbose"    => \$opt_verbose,
+        "k|kill"       => \$opt_kill,
     ) 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;
+    pod2usage(-verbose => 0, -exitval => 0)
+      if not defined $opt_user
+          and not defined $opt_kill;
 
     $opt_verbose += $opt_debug;
 
-    untaint($opt_user)
-      or die ME . ": username \"$opt_user\" didn't pass verification\n";
+    untaint($opt_linkname) or die ME . ": linkname didn't pass verification\n";
+    untaint($opt_script)
+      or die ME . ": script name didn't pass verification\n"
+      if $opt_script;
+    map { untaint } @ppp_opts;
 
     die ME . ": 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 \"$opt_user\" 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";
@@ -98,13 +112,9 @@
         system stty => $settings;
         print "\n";
     }
-
+    untaint($opt_passcode) or die ME . ": passcode didn't pass verification\n";
     pod2usage(-verbose => 0, -exitval => 0) if not defined $opt_passcode;
 
-    untaint($opt_passcode) or die ME . ": passcode didn't pass verification\n";
-    untaint($opt_linkname) or die ME . ": linkname didn't pass verification\n";
-    untaint($opt_script) or die ME . ": script name didn't pass verification\n";
-
     -x $opt_script
       or die ME . ": Script $opt_script is not executable: $!\n"
       if defined $opt_script;
@@ -260,16 +270,39 @@
 
 }
 
+sub do_kill($) {
+    my $linkname = shift;
+    open((my $fh), $_ = "/var/run/ppp-$linkname.pid")
+	or die ME . ": Can't open the link file \"$_\": $!\n";
+
+    my $pid   = <$fh>;
+    my $iface = <$fh>;
+
+    map { chomp; untaint } $pid, $iface;
+
+    # 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";
+
+    waitpid $pid, 0 != -1 
+	or die ME . ": was not able to wait for the ppp process: $!\n";
+
+    verbose "% process killed, rc: @{[$? >> 8]}, sig: @{[$? & 0xff]}\n";
+}
+
 __END__
 
 =head1 SYNOPSIS
 
  sap-vpn [-d|--debug] [-v|--verbose] [--[no]ppp] 
      [-o|--opt <ppp option>]
+     [-l|--linkname <link name>]
      [-u|--user <user>] [-p|--passcode <passcode>]
      [-H|--host <host>]
      [-s|--script <script>]
 
+ sap-vpn [-l|--linkname <link name>] -k|--kill
+
  sap-vpn [-h|--help]
  sap-vpn [-m|--man]
 
@@ -299,6 +332,12 @@
 
 Host to connect to. (defaults to C<connectwdf.sap.corp>)
 
+=item B<-k>|B<--kill>
+
+This is not really an option. It kills the link. This functionality
+relies on finding the PID file of the PPPD in
+F</var/run/ppp->I<linkname>F<.pid>.
+
 =item B<-l>|B<--linkname> I<linkname>
 
 The name for the PPP link. Only word characters and "-" (minus sign) are