diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2013-06-04 04:17:43 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2013-06-04 04:17:43 +0000 |
commit | 95ad9ef12960b03110a02a648883a7648922a42e (patch) | |
tree | a9b1698a9326144f3efb9a0975995181c903b814 /regress/sys | |
parent | f3342d9b31eff3980fd4f93a2cd0efbb7e7126dc (diff) |
Add tests for raw IP divert. Set effective user ID to 0 only during
privileged operations for raw sockets and bind any.
Diffstat (limited to 'regress/sys')
-rw-r--r-- | regress/sys/net/pf_divert/Client.pm | 21 | ||||
-rw-r--r-- | regress/sys/net/pf_divert/Makefile | 6 | ||||
-rw-r--r-- | regress/sys/net/pf_divert/Remote.pm | 9 | ||||
-rw-r--r-- | regress/sys/net/pf_divert/Server.pm | 7 | ||||
-rw-r--r-- | regress/sys/net/pf_divert/args-rip-reply.pl | 14 | ||||
-rw-r--r-- | regress/sys/net/pf_divert/args-rip-to.pl | 14 | ||||
-rw-r--r-- | regress/sys/net/pf_divert/args-tcp-reply.pl | 5 | ||||
-rw-r--r-- | regress/sys/net/pf_divert/args-tcp-to.pl | 2 | ||||
-rw-r--r-- | regress/sys/net/pf_divert/args-udp-reply.pl | 2 | ||||
-rw-r--r-- | regress/sys/net/pf_divert/funcs.pl | 24 | ||||
-rw-r--r-- | regress/sys/net/pf_divert/remote.pl | 33 |
11 files changed, 94 insertions, 43 deletions
diff --git a/regress/sys/net/pf_divert/Client.pm b/regress/sys/net/pf_divert/Client.pm index 8c66a8e79ae..11c84151408 100644 --- a/regress/sys/net/pf_divert/Client.pm +++ b/regress/sys/net/pf_divert/Client.pm @@ -1,4 +1,4 @@ -# $OpenBSD: Client.pm,v 1.1 2013/06/03 05:06:38 bluhm Exp $ +# $OpenBSD: Client.pm,v 1.2 2013/06/04 04:17:42 bluhm Exp $ # Copyright (c) 2010-2013 Alexander Bluhm <bluhm@openbsd.org> # @@ -39,30 +39,32 @@ sub new { or croak "$class connect domain not given"; $self->{connectaddr} or croak "$class connect addr not given"; - $self->{connectport} + $self->{connectport} || $self->{protocol} !~ /^(tcp|udp)$/ or croak "$class connect port not given"; my $cs; if ($self->{bindany}) { - $cs = IO::Socket::INET6->new( + do { local $> = 0; $cs = IO::Socket::INET6->new( + Type => $self->{socktype}, Proto => $self->{protocol}, Domain => $self->{connectdomain}, Blocking => ($self->{nonblocking} ? 0 : 1), - ) or die ref($self), " socket connect failed: $!"; - $cs->setsockopt(SOL_SOCKET, SO_BINDANY, 1) + ) } or die ref($self), " socket connect failed: $!"; + do { local $> = 0; $cs->setsockopt(SOL_SOCKET, SO_BINDANY, 1) } or die ref($self), " setsockopt SO_BINDANY failed: $!"; my @rres = getaddrinfo($self->{bindaddr}, $self->{bindport}||0, $self->{connectdomain}, SOCK_STREAM, 0, AI_PASSIVE); $cs->bind($rres[3]) or die ref($self), " bind failed: $!"; } elsif ($self->{bindaddr} || $self->{bindport}) { - $cs = IO::Socket::INET6->new( + do { local $> = 0; $cs = IO::Socket::INET6->new( + Type => $self->{socktype}, Proto => $self->{protocol}, Domain => $self->{connectdomain}, Blocking => ($self->{nonblocking} ? 0 : 1), LocalAddr => $self->{bindaddr}, LocalPort => $self->{bindport}, - ) or die ref($self), " socket connect failed: $!"; + ) } or die ref($self), " socket connect failed: $!"; } if ($cs) { $self->{bindaddr} = $cs->sockhost(); @@ -76,11 +78,12 @@ sub new { sub child { my $self = shift; - my $cs = $self->{cs} || IO::Socket::INET6->new( + my $cs = $self->{cs} || do { local $> = 0; IO::Socket::INET6->new( + Type => $self->{socktype}, Proto => $self->{protocol}, Domain => $self->{connectdomain}, Blocking => ($self->{nonblocking} ? 0 : 1), - ) or die ref($self), " socket connect failed: $!"; + ) } or die ref($self), " socket connect failed: $!"; if ($self->{oobinline}) { setsockopt($cs, SOL_SOCKET, SO_OOBINLINE, pack('i', 1)) or die ref($self), " set oobinline connect failed: $!"; diff --git a/regress/sys/net/pf_divert/Makefile b/regress/sys/net/pf_divert/Makefile index b06d572a39a..5c20b3a412f 100644 --- a/regress/sys/net/pf_divert/Makefile +++ b/regress/sys/net/pf_divert/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.1 2013/06/03 05:06:38 bluhm Exp $ +# $OpenBSD: Makefile,v 1.2 2013/06/04 04:17:42 bluhm Exp $ # The following ports must be installed for the regression tests: # p5-IO-Socket-INET6 object interface for AF_INET and AF_INET6 domain sockets @@ -66,11 +66,11 @@ PERLPATH = ${.CURDIR}/ run-regress-$a: $a .if !empty (LOCAL_ADDR) @echo - time SUDO=${SUDO} perl ${PERLINC} ${PERLPATH}remote.pl inet ${LOCAL_ADDR} ${FAKE_ADDR} ${REMOTE_SSH} ${PERLPATH}$a + time ${SUDO} SUDO=${SUDO} perl ${PERLINC} ${PERLPATH}remote.pl inet ${LOCAL_ADDR} ${FAKE_ADDR} ${REMOTE_SSH} ${PERLPATH}$a .endif .if !empty (LOCAL_ADDR6) @echo - time SUDO=${SUDO} perl ${PERLINC} ${PERLPATH}remote.pl inet6 ${LOCAL_ADDR6} ${FAKE_ADDR6} ${REMOTE_SSH} ${PERLPATH}$a + time ${SUDO} SUDO=${SUDO} perl ${PERLINC} ${PERLPATH}remote.pl inet6 ${LOCAL_ADDR6} ${FAKE_ADDR6} ${REMOTE_SSH} ${PERLPATH}$a .endif .endfor diff --git a/regress/sys/net/pf_divert/Remote.pm b/regress/sys/net/pf_divert/Remote.pm index 957c3ceafb5..a49eb64a192 100644 --- a/regress/sys/net/pf_divert/Remote.pm +++ b/regress/sys/net/pf_divert/Remote.pm @@ -1,4 +1,4 @@ -# $OpenBSD: Remote.pm,v 1.1 2013/06/03 05:06:38 bluhm Exp $ +# $OpenBSD: Remote.pm,v 1.2 2013/06/04 04:17:42 bluhm Exp $ # Copyright (c) 2010-2013 Alexander Bluhm <bluhm@openbsd.org> # @@ -46,7 +46,7 @@ sub new { sub up { my $self = Proc::up(shift, @_); my $timeout = shift || 10; - if ($self->{connectport}) { + if ($self->{connect}) { $self->loggrep(qr/^Connected$/, $timeout) or croak ref($self), " no Connected in $self->{logfile} ". "after $timeout seconds"; @@ -67,9 +67,7 @@ sub child { print STDERR $self->{up}, "\n"; my @opts = split(' ', $ENV{SSH_OPTIONS}) if $ENV{SSH_OPTIONS}; - # if sudo is set, run the remote perl as root, otherwise pass SUDO - my @sudo = !$ENV{SUDO} ? () : - $self->{sudo} ? $ENV{SUDO} : "SUDO=$ENV{SUDO}"; + my @sudo = $ENV{SUDO} ? ($ENV{SUDO}, "SUDO=$ENV{SUDO}") : (); my $dir = dirname($0); $dir = getcwd() if ! $dir || $dir eq '.'; my @cmd = ('ssh', '-n', @opts, $self->{remotessh}, @sudo, 'perl', @@ -78,6 +76,7 @@ sub child { ($self->{testfile} ? "$dir/".basename($self->{testfile}) : ())); print STDERR "execute: @cmd\n"; + $< = $>; exec @cmd; die "Exec @cmd failed: $!"; } diff --git a/regress/sys/net/pf_divert/Server.pm b/regress/sys/net/pf_divert/Server.pm index 06ca0698832..d0f1fafbe9e 100644 --- a/regress/sys/net/pf_divert/Server.pm +++ b/regress/sys/net/pf_divert/Server.pm @@ -1,4 +1,4 @@ -# $OpenBSD: Server.pm,v 1.1 2013/06/03 05:06:38 bluhm Exp $ +# $OpenBSD: Server.pm,v 1.2 2013/06/04 04:17:42 bluhm Exp $ # Copyright (c) 2010-2013 Alexander Bluhm <bluhm@openbsd.org> # @@ -34,13 +34,14 @@ sub new { $self->{protocol} ||= "tcp"; $self->{listendomain} or croak "$class listen domain not given"; - my $ls = IO::Socket::INET6->new( + my $ls = do { local $> = 0; IO::Socket::INET6->new( + Type => $self->{socktype}, Proto => $self->{protocol}, ReuseAddr => 1, Domain => $self->{listendomain}, $self->{listenaddr} ? (LocalAddr => $self->{listenaddr}) : (), $self->{listenport} ? (LocalPort => $self->{listenport}) : (), - ) or die ref($self), " socket failed: $!"; + ) } or die ref($self), " socket failed: $!"; if ($self->{oobinline}) { setsockopt($ls, SOL_SOCKET, SO_OOBINLINE, pack('i', 1)) or die ref($self), " set oobinline listen failed: $!"; diff --git a/regress/sys/net/pf_divert/args-rip-reply.pl b/regress/sys/net/pf_divert/args-rip-reply.pl new file mode 100644 index 00000000000..1c71ecddb20 --- /dev/null +++ b/regress/sys/net/pf_divert/args-rip-reply.pl @@ -0,0 +1,14 @@ +# test divert-reply with raw ip + +use strict; +use warnings; +use Socket; + +our %args = ( + socktype => Socket::SOCK_RAW, + protocol => 254, + skip => sub { shift->{af} eq "inet" ? 20 : 0 }, + client => { func => \&write_datagram, noin => 1, }, + server => { func => \&read_datagram, noout => 1, }, + divert => "reply", +); diff --git a/regress/sys/net/pf_divert/args-rip-to.pl b/regress/sys/net/pf_divert/args-rip-to.pl new file mode 100644 index 00000000000..2fd414eb33c --- /dev/null +++ b/regress/sys/net/pf_divert/args-rip-to.pl @@ -0,0 +1,14 @@ +# test divert-to with raw ip + +use strict; +use warnings; +use Socket; + +our %args = ( + socktype => Socket::SOCK_RAW, + protocol => 254, + skip => sub { shift->{af} eq "inet" ? 20 : 0 }, + client => { func => \&write_datagram, noin => 1, }, + server => { func => \&read_datagram, noout => 1, }, + divert => "to", +); diff --git a/regress/sys/net/pf_divert/args-tcp-reply.pl b/regress/sys/net/pf_divert/args-tcp-reply.pl index 67f64f49173..82d435632d9 100644 --- a/regress/sys/net/pf_divert/args-tcp-reply.pl +++ b/regress/sys/net/pf_divert/args-tcp-reply.pl @@ -1,7 +1,4 @@ -# test divert-reply -# swap client and server -# server is local -# client diverts packets with reply-to +# test divert-reply with tcp use strict; use warnings; diff --git a/regress/sys/net/pf_divert/args-tcp-to.pl b/regress/sys/net/pf_divert/args-tcp-to.pl index e2af43dd2fe..0e67e4c873e 100644 --- a/regress/sys/net/pf_divert/args-tcp-to.pl +++ b/regress/sys/net/pf_divert/args-tcp-to.pl @@ -1,4 +1,4 @@ -# test divert-to +# test divert-to with tcp use strict; use warnings; diff --git a/regress/sys/net/pf_divert/args-udp-reply.pl b/regress/sys/net/pf_divert/args-udp-reply.pl index e5ab629de58..7e2c5a77f37 100644 --- a/regress/sys/net/pf_divert/args-udp-reply.pl +++ b/regress/sys/net/pf_divert/args-udp-reply.pl @@ -1,4 +1,4 @@ -# test divert-to with udp +# test divert-reply with udp use strict; use warnings; diff --git a/regress/sys/net/pf_divert/funcs.pl b/regress/sys/net/pf_divert/funcs.pl index 2004aead2d7..3fb71811d89 100644 --- a/regress/sys/net/pf_divert/funcs.pl +++ b/regress/sys/net/pf_divert/funcs.pl @@ -1,4 +1,4 @@ -# $OpenBSD: funcs.pl,v 1.2 2013/06/03 21:07:45 bluhm Exp $ +# $OpenBSD: funcs.pl,v 1.3 2013/06/04 04:17:42 bluhm Exp $ # Copyright (c) 2010-2013 Alexander Bluhm <bluhm@openbsd.org> # @@ -44,8 +44,18 @@ sub write_datagram { sub read_datagram { my $self = shift; - - my $in = <STDIN>; + my $skip = $self->{skip}; + $skip = $skip->($self) if ref $skip eq 'CODE'; + + my $in; + if ($skip) { + # Raw sockets include the IPv4 header. + sysread(STDIN, $in, 70000); + # Cut the header off. + substr($in, 0, $skip, ""); + } else { + $in = <STDIN>; + } print STDERR "<<< $in"; } @@ -65,15 +75,15 @@ sub check_inout { my ($c, $s, %args) = @_; if ($c && !$args{client}{nocheck}) { - $c->loggrep(qr/^>>> Client$/) or die "no client out" + $c->loggrep(qr/^>>> Client$/) or die "no client output" unless $args{client}{noout}; - $c->loggrep(qr/^<<< Server$/) or die "no client in" + $c->loggrep(qr/^<<< Server$/) or die "no client input" unless $args{client}{noin}; } if ($s && !$args{server}{nocheck}) { - $s->loggrep(qr/^>>> Server$/) or die "no server out" + $s->loggrep(qr/^>>> Server$/) or die "no server output" unless $args{server}{noout}; - $s->loggrep(qr/^<<< Client$/) or die "no server in" + $s->loggrep(qr/^<<< Client$/) or die "no server input" unless $args{server}{noin}; } } diff --git a/regress/sys/net/pf_divert/remote.pl b/regress/sys/net/pf_divert/remote.pl index 18e4af31389..30992ef5658 100644 --- a/regress/sys/net/pf_divert/remote.pl +++ b/regress/sys/net/pf_divert/remote.pl @@ -1,5 +1,5 @@ #!/usr/bin/perl -# $OpenBSD: remote.pl,v 1.2 2013/06/03 21:07:45 bluhm Exp $ +# $OpenBSD: remote.pl,v 1.3 2013/06/04 04:17:42 bluhm Exp $ # Copyright (c) 2010-2013 Alexander Bluhm <bluhm@openbsd.org> # @@ -17,6 +17,13 @@ use strict; use warnings; + +BEGIN { + if ($> == 0 && $ENV{SUDO_UID}) { + $> = $ENV{SUDO_UID}; + } +} + use File::Basename; use File::Copy; use Socket; @@ -73,6 +80,7 @@ if ($local eq "server") { func => $func, %args, %{$args{server}}, + af => $af, logfile => $logfile, listendomain => $domain, listenaddr => $mode ne "divert" ? $ARGV[0] : @@ -87,9 +95,9 @@ if ($mode eq "auto") { testfile => $test, remotessh => $ARGV[2], bindaddr => $ARGV[1], + connect => $remote eq "client", connectaddr => $ARGV[0], connectport => $s ? $s->{listenport} : 0, - sudo => $ENV{SUDO}, ); $r->run->up; $r->loggrep(qr/^Diverted$/, 10) @@ -100,6 +108,7 @@ if ($local eq "client") { func => $func, %args, %{$args{client}}, + af => $af, logfile => $logfile, connectdomain => $domain, connectaddr => $ARGV[1], @@ -120,18 +129,22 @@ if ($mode eq "divert") { }; copy($log, \*STDERR); - my @sudo = $ENV{SUDO} ? $ENV{SUDO} : (); - my @cmd = (@sudo, qw(pfctl -a regress -f -)); - open(my $pf, '|-', @cmd) + my @cmd = qw(pfctl -a regress -f -); + my $pf; + do { local $> = 0; open($pf, '|-', @cmd) } or die "Open pipe to pf '@cmd' failed: $!"; if ($local eq "server") { + my $port = $args{protocol} =~ /^(tcp|udp)$/ ? + "port $s->{listenport}" : ""; + my $divertport = $port || "port 1"; # XXX bad pf syntax print $pf "pass in log $af proto $args{protocol} ". - "from $ARGV[1] to $ARGV[0] port $s->{listenport} ". - "divert-to $s->{listenaddr} port $s->{listenport}\n"; + "from $ARGV[1] to $ARGV[0] $port ". + "divert-to $s->{listenaddr} $divertport\n"; } else { + my $port = $args{protocol} =~ /^(tcp|udp)$/ ? + "port $ARGV[2]" : ""; print $pf "pass out log $af proto $args{protocol} ". - "from $c->{bindaddr} to $ARGV[1] port $ARGV[2] ". - "divert-reply\n"; + "from $c->{bindaddr} to $ARGV[1] $port divert-reply\n"; } close($pf) or die $! ? "Close pipe to pf '@cmd' failed: $!" : @@ -156,4 +169,4 @@ $c->down if $c; $r->down if $r; $s->down if $s; -check_logs($c, $s, %args); +check_logs($c || $r, $s || $r, %args); |