diff -r 9ff263c701ef -r f9fbeced9093 sap-vpn.pl --- 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 ] + [-l|--linkname ] [-u|--user ] [-p|--passcode ] [-H|--host ] [-s|--script