Add netmasks support to initiator-portal option.
MFC after: 2 weeks
This commit is contained in:
parent
56e397023c
commit
073edb1c91
@ -27,7 +27,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd July 20, 2014
|
.Dd July 28, 2014
|
||||||
.Dt CTL.CONF 5
|
.Dt CTL.CONF 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -119,7 +119,7 @@ name.
|
|||||||
Otherwise, only initiators with names matching one of defined
|
Otherwise, only initiators with names matching one of defined
|
||||||
ones will be allowed to connect.
|
ones will be allowed to connect.
|
||||||
.It Ic initiator-portal Ao Ar address Ac
|
.It Ic initiator-portal Ao Ar address Ac
|
||||||
Specifies iSCSI initiator portal - IPv4 or IPv6 address.
|
Specifies iSCSI initiator portal - IPv4 or IPv6 address or network.
|
||||||
If not defined, there will be no restrictions based on initiator
|
If not defined, there will be no restrictions based on initiator
|
||||||
address.
|
address.
|
||||||
Otherwise, only initiators with addresses matching one of defined
|
Otherwise, only initiators with addresses matching one of defined
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -319,14 +320,56 @@ const struct auth_portal *
|
|||||||
auth_portal_new(struct auth_group *ag, const char *portal)
|
auth_portal_new(struct auth_group *ag, const char *portal)
|
||||||
{
|
{
|
||||||
struct auth_portal *ap;
|
struct auth_portal *ap;
|
||||||
|
char *net, *mask, *str, *tmp;
|
||||||
|
int len, dm, m;
|
||||||
|
|
||||||
ap = calloc(1, sizeof(*ap));
|
ap = calloc(1, sizeof(*ap));
|
||||||
if (ap == NULL)
|
if (ap == NULL)
|
||||||
log_err(1, "calloc");
|
log_err(1, "calloc");
|
||||||
ap->ap_auth_group = ag;
|
ap->ap_auth_group = ag;
|
||||||
ap->ap_initator_portal = checked_strdup(portal);
|
ap->ap_initator_portal = checked_strdup(portal);
|
||||||
|
mask = str = checked_strdup(portal);
|
||||||
|
net = strsep(&mask, "/");
|
||||||
|
if (net[0] == '[')
|
||||||
|
net++;
|
||||||
|
len = strlen(net);
|
||||||
|
if (len == 0)
|
||||||
|
goto error;
|
||||||
|
if (net[len - 1] == ']')
|
||||||
|
net[len - 1] = 0;
|
||||||
|
if (strchr(net, ':') != NULL) {
|
||||||
|
struct sockaddr_in6 *sin6 =
|
||||||
|
(struct sockaddr_in6 *)&ap->ap_sa;
|
||||||
|
|
||||||
|
sin6->sin6_len = sizeof(*sin6);
|
||||||
|
sin6->sin6_family = AF_INET6;
|
||||||
|
if (inet_pton(AF_INET6, net, &sin6->sin6_addr) <= 0)
|
||||||
|
goto error;
|
||||||
|
dm = 128;
|
||||||
|
} else {
|
||||||
|
struct sockaddr_in *sin =
|
||||||
|
(struct sockaddr_in *)&ap->ap_sa;
|
||||||
|
|
||||||
|
sin->sin_len = sizeof(*sin);
|
||||||
|
sin->sin_family = AF_INET;
|
||||||
|
if (inet_pton(AF_INET, net, &sin->sin_addr) <= 0)
|
||||||
|
goto error;
|
||||||
|
dm = 32;
|
||||||
|
}
|
||||||
|
if (mask != NULL) {
|
||||||
|
m = strtol(mask, &tmp, 0);
|
||||||
|
if (m < 0 || m > dm || tmp[0] != 0)
|
||||||
|
goto error;
|
||||||
|
} else
|
||||||
|
m = dm;
|
||||||
|
ap->ap_mask = m;
|
||||||
|
free(str);
|
||||||
TAILQ_INSERT_TAIL(&ag->ag_portals, ap, ap_next);
|
TAILQ_INSERT_TAIL(&ag->ag_portals, ap, ap_next);
|
||||||
return (ap);
|
return (ap);
|
||||||
|
|
||||||
|
error:
|
||||||
|
log_errx(1, "Incorrect initiator portal '%s'", portal);
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -347,13 +390,34 @@ auth_portal_defined(const struct auth_group *ag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const struct auth_portal *
|
const struct auth_portal *
|
||||||
auth_portal_find(const struct auth_group *ag, const char *portal)
|
auth_portal_find(const struct auth_group *ag, const struct sockaddr_storage *ss)
|
||||||
{
|
{
|
||||||
const struct auth_portal *auth_portal;
|
const struct auth_portal *ap;
|
||||||
|
uint8_t *a, *b, bmask;
|
||||||
|
int i;
|
||||||
|
|
||||||
TAILQ_FOREACH(auth_portal, &ag->ag_portals, ap_next) {
|
TAILQ_FOREACH(ap, &ag->ag_portals, ap_next) {
|
||||||
if (strcmp(auth_portal->ap_initator_portal, portal) == 0)
|
if (ap->ap_sa.ss_family != ss->ss_family)
|
||||||
return (auth_portal);
|
continue;
|
||||||
|
if (ss->ss_family == AF_INET) {
|
||||||
|
a = (uint8_t *)&((struct sockaddr_in *)ss)->sin_addr;
|
||||||
|
b = (uint8_t *)&((struct sockaddr_in *)&ap->ap_sa)->sin_addr;
|
||||||
|
} else {
|
||||||
|
a = (uint8_t *)&((struct sockaddr_in6 *)ss)->sin6_addr;
|
||||||
|
b = (uint8_t *)&((struct sockaddr_in6 *)&ap->ap_sa)->sin6_addr;
|
||||||
|
}
|
||||||
|
for (i = 0; i < ap->ap_mask / 8; i++) {
|
||||||
|
if (a[i] != b[i])
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
if (ap->ap_mask % 8) {
|
||||||
|
bmask = 0xff << (8 - (ap->ap_mask % 8));
|
||||||
|
if ((a[i] & bmask) != (b[i] & bmask))
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
return (ap);
|
||||||
|
next:
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@ -950,7 +1014,8 @@ lun_option_set(struct lun_option *lo, const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct connection *
|
static struct connection *
|
||||||
connection_new(struct portal *portal, int fd, const char *host)
|
connection_new(struct portal *portal, int fd, const char *host,
|
||||||
|
const struct sockaddr *client_sa)
|
||||||
{
|
{
|
||||||
struct connection *conn;
|
struct connection *conn;
|
||||||
|
|
||||||
@ -960,6 +1025,7 @@ connection_new(struct portal *portal, int fd, const char *host)
|
|||||||
conn->conn_portal = portal;
|
conn->conn_portal = portal;
|
||||||
conn->conn_socket = fd;
|
conn->conn_socket = fd;
|
||||||
conn->conn_initiator_addr = checked_strdup(host);
|
conn->conn_initiator_addr = checked_strdup(host);
|
||||||
|
memcpy(&conn->conn_initiator_sa, client_sa, client_sa->sa_len);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Default values, from RFC 3720, section 12.
|
* Default values, from RFC 3720, section 12.
|
||||||
@ -1586,7 +1652,7 @@ wait_for_children(bool block)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
handle_connection(struct portal *portal, int fd,
|
handle_connection(struct portal *portal, int fd,
|
||||||
const struct sockaddr *client_sa, socklen_t client_salen, bool dont_fork)
|
const struct sockaddr *client_sa, bool dont_fork)
|
||||||
{
|
{
|
||||||
struct connection *conn;
|
struct connection *conn;
|
||||||
int error;
|
int error;
|
||||||
@ -1621,7 +1687,7 @@ handle_connection(struct portal *portal, int fd,
|
|||||||
}
|
}
|
||||||
pidfile_close(conf->conf_pidfh);
|
pidfile_close(conf->conf_pidfh);
|
||||||
|
|
||||||
error = getnameinfo(client_sa, client_salen,
|
error = getnameinfo(client_sa, client_sa->sa_len,
|
||||||
host, sizeof(host), NULL, 0, NI_NUMERICHOST);
|
host, sizeof(host), NULL, 0, NI_NUMERICHOST);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
log_errx(1, "getnameinfo: %s", gai_strerror(error));
|
log_errx(1, "getnameinfo: %s", gai_strerror(error));
|
||||||
@ -1631,7 +1697,7 @@ handle_connection(struct portal *portal, int fd,
|
|||||||
log_set_peer_addr(host);
|
log_set_peer_addr(host);
|
||||||
setproctitle("%s", host);
|
setproctitle("%s", host);
|
||||||
|
|
||||||
conn = connection_new(portal, fd, host);
|
conn = connection_new(portal, fd, host, client_sa);
|
||||||
set_timeout(conf);
|
set_timeout(conf);
|
||||||
kernel_capsicate();
|
kernel_capsicate();
|
||||||
login(conn);
|
login(conn);
|
||||||
@ -1687,6 +1753,9 @@ main_loop(struct conf *conf, bool dont_fork)
|
|||||||
client_salen = sizeof(client_sa);
|
client_salen = sizeof(client_sa);
|
||||||
kernel_accept(&connection_id, &portal_id,
|
kernel_accept(&connection_id, &portal_id,
|
||||||
(struct sockaddr *)&client_sa, &client_salen);
|
(struct sockaddr *)&client_sa, &client_salen);
|
||||||
|
if (client_salen < client_sa.ss_len)
|
||||||
|
log_errx(1, "salen %u < %u",
|
||||||
|
client_salen, client_sa.ss_len);
|
||||||
|
|
||||||
log_debugx("incoming connection, id %d, portal id %d",
|
log_debugx("incoming connection, id %d, portal id %d",
|
||||||
connection_id, portal_id);
|
connection_id, portal_id);
|
||||||
@ -1703,8 +1772,7 @@ main_loop(struct conf *conf, bool dont_fork)
|
|||||||
|
|
||||||
found:
|
found:
|
||||||
handle_connection(portal, connection_id,
|
handle_connection(portal, connection_id,
|
||||||
(struct sockaddr *)&client_sa, client_salen,
|
(struct sockaddr *)&client_sa, dont_fork);
|
||||||
dont_fork);
|
|
||||||
} else {
|
} else {
|
||||||
#endif
|
#endif
|
||||||
assert(proxy_mode == false);
|
assert(proxy_mode == false);
|
||||||
@ -1731,9 +1799,13 @@ main_loop(struct conf *conf, bool dont_fork)
|
|||||||
&client_salen);
|
&client_salen);
|
||||||
if (client_fd < 0)
|
if (client_fd < 0)
|
||||||
log_err(1, "accept");
|
log_err(1, "accept");
|
||||||
|
if (client_salen < client_sa.ss_len)
|
||||||
|
log_errx(1, "salen %u < %u",
|
||||||
|
client_salen,
|
||||||
|
client_sa.ss_len);
|
||||||
handle_connection(portal, client_fd,
|
handle_connection(portal, client_fd,
|
||||||
(struct sockaddr *)&client_sa,
|
(struct sockaddr *)&client_sa,
|
||||||
client_salen, dont_fork);
|
dont_fork);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,8 @@
|
|||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#ifdef ICL_KERNEL_PROXY
|
#ifdef ICL_KERNEL_PROXY
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <libutil.h>
|
#include <libutil.h>
|
||||||
|
|
||||||
@ -67,6 +67,8 @@ struct auth_portal {
|
|||||||
TAILQ_ENTRY(auth_portal) ap_next;
|
TAILQ_ENTRY(auth_portal) ap_next;
|
||||||
struct auth_group *ap_auth_group;
|
struct auth_group *ap_auth_group;
|
||||||
char *ap_initator_portal;
|
char *ap_initator_portal;
|
||||||
|
struct sockaddr_storage ap_sa;
|
||||||
|
int ap_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define AG_TYPE_UNKNOWN 0
|
#define AG_TYPE_UNKNOWN 0
|
||||||
@ -179,6 +181,7 @@ struct connection {
|
|||||||
char *conn_initiator_addr;
|
char *conn_initiator_addr;
|
||||||
char *conn_initiator_alias;
|
char *conn_initiator_alias;
|
||||||
uint8_t conn_initiator_isid[6];
|
uint8_t conn_initiator_isid[6];
|
||||||
|
struct sockaddr_storage conn_initiator_sa;
|
||||||
uint32_t conn_cmdsn;
|
uint32_t conn_cmdsn;
|
||||||
uint32_t conn_statsn;
|
uint32_t conn_statsn;
|
||||||
size_t conn_max_data_segment_length;
|
size_t conn_max_data_segment_length;
|
||||||
@ -235,7 +238,7 @@ const struct auth_portal *auth_portal_new(struct auth_group *ag,
|
|||||||
const char *initiator_portal);
|
const char *initiator_portal);
|
||||||
bool auth_portal_defined(const struct auth_group *ag);
|
bool auth_portal_defined(const struct auth_group *ag);
|
||||||
const struct auth_portal *auth_portal_find(const struct auth_group *ag,
|
const struct auth_portal *auth_portal_find(const struct auth_group *ag,
|
||||||
const char *initiator_portal);
|
const struct sockaddr_storage *sa);
|
||||||
|
|
||||||
struct portal_group *portal_group_new(struct conf *conf, const char *name);
|
struct portal_group *portal_group_new(struct conf *conf, const char *name);
|
||||||
void portal_group_delete(struct portal_group *pg);
|
void portal_group_delete(struct portal_group *pg);
|
||||||
|
@ -954,7 +954,7 @@ login(struct connection *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (auth_portal_defined(ag)) {
|
if (auth_portal_defined(ag)) {
|
||||||
if (auth_portal_find(ag, conn->conn_initiator_addr) == NULL) {
|
if (auth_portal_find(ag, &conn->conn_initiator_sa) == NULL) {
|
||||||
login_send_error(request, 0x02, 0x02);
|
login_send_error(request, 0x02, 0x02);
|
||||||
log_errx(1, "initiator does not match allowed "
|
log_errx(1, "initiator does not match allowed "
|
||||||
"initiator portals");
|
"initiator portals");
|
||||||
|
Loading…
Reference in New Issue
Block a user