acls: Add a default-deny option, which allows you to specify what an empty ACL means.

When this option is specified, an empty ACL means "reject all clients". Without it,
an empty ACL means "accept all clients"
This commit is contained in:
nick
2012-06-01 14:48:34 +01:00
parent 71e755906b
commit 04d67b3bab
4 changed files with 41 additions and 11 deletions

View File

@@ -48,6 +48,7 @@ void params_serve(
char* s_port,
char* s_file,
char *s_ctrl_sock,
int default_deny,
int acl_entries,
char** s_acl_entries /* first may actually be path to control socket */
)
@@ -71,6 +72,10 @@ void params_serve(
* we pass NULL. */
out->control_socket_name = s_ctrl_sock;
/* If this is true then an empty ACL means "nobody is allowed to connect",
* rather than "anybody is allowed to connect" */
out->default_deny = default_deny;
out->acl_entries = acl_entries;
parsed = parse_acl(&out->acl, acl_entries, s_acl_entries);
if (parsed != acl_entries)
@@ -161,7 +166,8 @@ void do_read(struct mode_readwrite_params* params);
void do_write(struct mode_readwrite_params* params);
void do_remote_command(char* command, char* mode, int argc, char** argv);
void read_serve_param( int c, char **ip_addr, char **ip_port, char **file, char **sock )
void read_serve_param( int c, char **ip_addr, char **ip_port, char **file, char **sock, int *default_deny )
{
switch(c){
case 'h':
@@ -180,6 +186,9 @@ void read_serve_param( int c, char **ip_addr, char **ip_port, char **file, char
case 's':
*sock = optarg;
break;
case 'D':
*default_deny = 1;
break;
default:
exit_err( serve_help_text );
break;
@@ -267,14 +276,17 @@ int mode_serve( int argc, char *argv[] )
char *ip_port = NULL;
char *file = NULL;
char *sock = NULL;
int default_deny = 0; // not on by default
int err = 0;
struct mode_serve_params serve;
while (1) {
c = getopt_long(argc, argv, serve_short_options, serve_options, NULL);
if ( c == -1 ) break;
read_serve_param( c, &ip_addr, &ip_port, &file, &sock );
if ( c == -1 )
break;
read_serve_param( c, &ip_addr, &ip_port, &file, &sock, &default_deny );
}
if ( NULL == ip_addr || NULL == ip_port ) {
@@ -288,7 +300,7 @@ int mode_serve( int argc, char *argv[] )
if ( err ) { exit_err( serve_help_text ); }
memset( &serve, 0, sizeof( serve ) );
params_serve( &serve, ip_addr, ip_port, file, sock, argc - optind, argv + optind );
params_serve( &serve, ip_addr, ip_port, file, sock, default_deny, argc - optind, argv + optind );
do_serve( &serve );
return 0;

View File

@@ -8,6 +8,7 @@
#define OPT_SOCK "sock"
#define OPT_FROM "from"
#define OPT_SIZE "size"
#define OPT_DENY "default-deny"
#define CMD_SERVE "serve"
#define CMD_READ "read"
@@ -16,7 +17,7 @@
#define CMD_MIRROR "mirror"
#define CMD_STATUS "status"
#define CMD_HELP "help"
#define LEN_CMD_MAX 6
#define LEN_CMD_MAX 7
#define PATH_LEN_MAX 1024
#define ADDR_LEN_MAX 64
@@ -25,6 +26,8 @@
#define IS_CMD(x,c) (strncmp((x),(c),(LEN_CMD_MAX)) == 0)
#define GETOPT_HELP GETOPT_FLAG( OPT_HELP, 'h' )
#define GETOPT_DENY GETOPT_FLAG( OPT_DENY, 'D' )
#define GETOPT_ADDR GETOPT_ARG( OPT_ADDR, 'l' )
#define GETOPT_PORT GETOPT_ARG( OPT_PORT, 'p' )
#define GETOPT_FILE GETOPT_ARG( OPT_FILE, 'f' )
@@ -38,9 +41,10 @@ static struct option serve_options[] = {
GETOPT_PORT,
GETOPT_FILE,
GETOPT_SOCK,
GETOPT_DENY,
{0}
};
static char serve_short_options[] = "hl:p:f:s:";
static char serve_short_options[] = "Dhl:p:f:s:";
static char serve_help_text[] =
"Usage: flexnbd " CMD_SERVE " <options> [<acl address>*]\n\n"
"Serve FILE from ADDR:PORT, with an optional control socket at SOCK.\n\n"
@@ -48,6 +52,7 @@ static char serve_help_text[] =
"\t--" OPT_ADDR ",-l <ADDR>\tThe address to serve on.\n"
"\t--" OPT_PORT ",-p <PORT>\tThe port to serve on.\n"
"\t--" OPT_FILE ",-f <FILE>\tThe file to serve.\n"
"\t--" OPT_DENY ",-D\tDeny connections by default unless in ACL\n"
"\t--" OPT_SOCK ",-s <SOCK>\tPath to the control socket to open.\n";
static struct option read_options[] = {

View File

@@ -34,6 +34,8 @@ struct control_params {
struct mode_serve_params {
/** address/port to bind to */
union mysockaddr bind_to;
/** does an empty ACL mean "deny all"? */
int default_deny;
/** number of entries in current access control list*/
int acl_entries;
/** pointer to access control list entries*/

View File

@@ -452,6 +452,8 @@ void accept_nbd_client(struct mode_serve_params* params, int client_fd, union my
struct client_params* client_params;
int slot = cleanup_and_find_client_slot(params);
char s_client_address[64];
int acl_passed = 0;
if (inet_ntop(client_address->generic.sa_family, sockaddr_address_data(&client_address->generic), s_client_address, 64) == NULL) {
write(client_fd, "Bad client_address", 18);
@@ -459,12 +461,21 @@ void accept_nbd_client(struct mode_serve_params* params, int client_fd, union my
return;
}
if (params->acl &&
!is_included_in_acl(params->acl_entries, params->acl, client_address)) {
write(client_fd, "Access control error", 20);
close(client_fd);
return;
if (params->acl) {
if (is_included_in_acl(params->acl_entries, params->acl, client_address))
acl_passed = 1;
} else {
if (!params->default_deny)
acl_passed = 1;
}
if (!acl_passed) {
write(client_fd, "Access control error", 20);
close(client_fd);
return;
}
if (slot < 0) {
write(client_fd, "Too many clients", 16);