Test for acl rejection

This commit is contained in:
Alex Young
2012-06-28 13:29:22 +01:00
parent c9fdd5a60e
commit 4de4cee3d0
6 changed files with 99 additions and 46 deletions

View File

@@ -134,6 +134,7 @@ int control_accept( struct control * control )
FD_ZERO( &fds ); FD_ZERO( &fds );
FD_SET( control->control_fd, &fds ); FD_SET( control->control_fd, &fds );
self_pipe_fd_set( control->close_signal, &fds ); self_pipe_fd_set( control->close_signal, &fds );
debug("Control thread selecting");
FATAL_UNLESS( 0 < select( FD_SETSIZE, &fds, NULL, NULL, NULL ), FATAL_UNLESS( 0 < select( FD_SETSIZE, &fds, NULL, NULL, NULL ),
"Control select failed." ); "Control select failed." );
@@ -398,49 +399,44 @@ void control_cleanup(struct control_client* client,
void control_respond(struct control_client * client) void control_respond(struct control_client * client)
{ {
char **lines = NULL; char **lines = NULL;
int finished=0;
error_set_handler((cleanup_handler*) control_cleanup, client); error_set_handler((cleanup_handler*) control_cleanup, client);
while (!finished) { int i, linesc;
int i, linesc; linesc = read_lines_until_blankline(client->socket, 256, &lines);
linesc = read_lines_until_blankline(client->socket, 256, &lines);
if (linesc < 1)
if (linesc < 1) {
{ write(client->socket, "9: missing command\n", 19);
write(client->socket, "9: missing command\n", 19); /* ignore failure */
finished = 1;
/* ignore failure */
}
else if (strcmp(lines[0], "acl") == 0) {
info("acl command received" );
if (control_acl(client, linesc-1, lines+1) < 0) {
finished = 1;
}
}
else if (strcmp(lines[0], "mirror") == 0) {
info("mirror command received" );
if (control_mirror(client, linesc-1, lines+1) < 0) {
finished = 1;
}
}
else if (strcmp(lines[0], "status") == 0) {
info("status command received" );
if (control_status(client, linesc-1, lines+1) < 0) {
finished = 1;
}
}
else {
write(client->socket, "10: unknown command\n", 23);
finished = 1;
}
for (i=0; i<linesc; i++) {
free(lines[i]);
}
free(lines);
} }
else if (strcmp(lines[0], "acl") == 0) {
info("acl command received" );
if (control_acl(client, linesc-1, lines+1) < 0) {
debug("acl command failed");
}
}
else if (strcmp(lines[0], "mirror") == 0) {
info("mirror command received" );
if (control_mirror(client, linesc-1, lines+1) < 0) {
debug("mirror command failed");
}
}
else if (strcmp(lines[0], "status") == 0) {
info("status command received" );
if (control_status(client, linesc-1, lines+1) < 0) {
debug("status command failed");
}
}
else {
write(client->socket, "10: unknown command\n", 23);
}
for (i=0; i<linesc; i++) {
free(lines[i]);
}
free(lines);
control_cleanup(client, 0); control_cleanup(client, 0);
debug("control command handled" ); debug("control command handled" );
} }

View File

@@ -299,6 +299,7 @@ int flexnbd_serve( struct flexnbd * flexnbd )
if ( flexnbd->control ) { if ( flexnbd->control ) {
debug( "Stopping control thread" ); debug( "Stopping control thread" );
flexnbd_stop_control( flexnbd ); flexnbd_stop_control( flexnbd );
debug("Control thread stopped");
} }
return success; return success;

View File

@@ -0,0 +1,23 @@
#!/usr/bin/env ruby
# encoding: utf-8
# We connect from a local address which should be blocked, sleep for a
# bit, then try to read from the socket. We should get an instant EOF
# as we've been cut off by the destination.
require 'timeout'
require 'flexnbd/fake_source'
include FlexNBD::FakeSource
addr, port = *ARGV
sock = connect( addr, port, "Timed out connecting", "127.0.0.6" )
sleep( 0.25 )
Timeout.timeout( 2 ) do
fail "Not disconnected" if sock.read(1)
end
sock.close
exit(0)

View File

@@ -265,6 +265,13 @@ class FlexNBD
"#{@debug}" "#{@debug}"
end end
def acl_cmd( *acl )
"#{@bin} acl " \
"--sock #{ctrl} "\
"#{@debug} "\
"#{acl.join " "}"
end
def run_serve_cmd(cmd) def run_serve_cmd(cmd)
File.unlink(ctrl) if File.exists?(ctrl) File.unlink(ctrl) if File.exists?(ctrl)
@@ -354,6 +361,7 @@ class FlexNBD
@wait_thread.join @wait_thread.join
end end
def mirror_unchecked( dest_ip, dest_port, bandwidth=nil, action=nil, timeout=nil ) def mirror_unchecked( dest_ip, dest_port, bandwidth=nil, action=nil, timeout=nil )
cmd = mirror_cmd( dest_ip, dest_port) cmd = mirror_cmd( dest_ip, dest_port)
debug( cmd ) debug( cmd )
@@ -361,6 +369,7 @@ class FlexNBD
maybe_timeout( cmd, timeout ) maybe_timeout( cmd, timeout )
end end
def maybe_timeout(cmd, timeout=nil ) def maybe_timeout(cmd, timeout=nil )
stdout, stderr = "","" stdout, stderr = "",""
run = Proc.new do run = Proc.new do
@@ -388,8 +397,12 @@ class FlexNBD
stdout stdout
end end
def acl(*acl) def acl(*acl)
control_command("acl", *acl) cmd = acl_cmd( *acl )
debug( cmd )
maybe_timeout( cmd, 2 )
end end
@@ -403,6 +416,11 @@ class FlexNBD
end end
def launched?
!!@pid
end
protected protected
def control_command(*args) def control_command(*args)
raise "Server not running" unless @pid raise "Server not running" unless @pid

View File

@@ -7,9 +7,9 @@ require 'flexnbd/constants'
module FlexNBD module FlexNBD
module FakeSource module FakeSource
def connect( addr, port, err_msg ) def connect( addr, port, err_msg, source_addr=nil, source_port=0 )
timing_out( 2, err_msg ) do timing_out( 2, err_msg ) do
TCPSocket.open( addr, port ) TCPSocket.new( addr, port, source_addr, source_port )
end end
end end

View File

@@ -33,7 +33,7 @@ class Environment
def listen1( *acl ) def listen1( *acl )
@nbd1.listen( @filename1, *acl ) @nbd1.listen( @filename1, *(acl.empty? ? @acl1: acl) )
end end
def listen2( *acl ) def listen2( *acl )
@@ -41,6 +41,15 @@ class Environment
end end
def acl1( *acl )
@nbd1.acl( *acl )
end
def acl2( *acl )
@nbd2.acl( *acl )
end
def status1 def status1
@nbd1.status.first @nbd1.status.first
end end
@@ -304,10 +313,16 @@ class NBDConnectDestFailureScenarios < Test::Unit::TestCase
end end
def test_acl_rejection
@env.acl1("127.0.0.1")
run_fake( "source/connect_from_banned_ip")
end
private private
def run_fake( name ) def run_fake( name )
@env.run_fake( name, @env.ip, @env.port1 ) @env.run_fake( name, @env.ip, @env.port1 )
assert @env.fake_reports_success assert @env.fake_reports_success, "#{name} failed."
end end
def assert_no_control def assert_no_control