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:
@@ -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;
|
||||
|
@@ -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[] = {
|
||||
|
@@ -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*/
|
||||
|
21
src/serve.c
21
src/serve.c
@@ -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);
|
||||
|
Reference in New Issue
Block a user