--- 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