iscsi-scst: Add internal_portal parameter

Add an internal_portal parameter to allow specified portals to
bypass CHAP controls for both discovery and target login.  If not
populated, then the current behavior will be preserved.
This commit is contained in:
Brian M
2024-07-31 13:26:29 -07:00
committed by Gleb Chesnokov
parent 0b00e0af96
commit aa086c9fb3
6 changed files with 107 additions and 1 deletions

View File

@@ -200,6 +200,13 @@ is /sys/kernel/scst_tgt/targets/iscsi. It has the following entries:
iSCSI-SCST attributes before it starts accepting new connections. 0
by default.
- internal_portal - May designate one or more existing portals as being
internal. This will eliminate the need to supply a CHAP user/secret
during discovery or target login to any targets configured on those
portals. This is particularly useful for internal targets used as
part of ALUA configuration. Multiple addresses may be supplied,
separated by space characters. Empty by default.
- link_local - if set, makes the response to an IPv6 SendTargets include
any link local addresses. Default is set.
@@ -552,6 +559,7 @@ both iSCSI-SCST targets will look like:
| |-- IncomingUser
| |-- OutgoingUser
| |-- enabled
| |-- internal_portal
| |-- iSNSServer
| |-- iqn.2006-10.net.vlnb:tgt
| | |-- DataDigest

View File

@@ -654,6 +654,18 @@ static int handle_e_get_attr_value(int fd, const struct iscsi_kern_event *event)
snprintf(res_str, sizeof(res_str), "%d\n", send_targets_link_local);
if (send_targets_link_local != DEFAULT_SEND_TARGETS_LINK_LOCAL)
add_key_mark(res_str, sizeof(res_str), 0);
} else if (strcasecmp(ISCSI_INTERNAL_PORTAL_ATTR_NAME, pp) == 0) {
if (target != NULL) {
log_error("Not NULL target %s for global attribute %s",
target->name, pp);
res = -EINVAL;
goto out_free;
}
if (internal_portal) {
snprintf(res_str, sizeof(res_str), "%s\n", internal_portal);
add_key_mark(res_str, sizeof(res_str), 0);
} else
snprintf(res_str, sizeof(res_str), "\n");
} else {
log_error("Unknown attribute %s", pp);
res = -EINVAL;
@@ -669,6 +681,14 @@ out:
return res;
}
static bool is_addr(char *addr)
{
struct in_addr ia;
struct in6_addr ia6;
return (inet_pton(AF_INET, addr, &ia) == 1) || inet_pton(AF_INET6, addr, &ia6);
}
static int handle_target_redirect(struct target *target, char *p)
{
int res = 0;
@@ -1094,6 +1114,51 @@ static int handle_e_set_attr_value(int fd, const struct iscsi_kern_event *event)
res = -EINVAL;
goto out_free;
}
} else if (strcasecmp(ISCSI_INTERNAL_PORTAL_ATTR_NAME, pp) == 0) {
if (target != NULL) {
log_error("Not NULL target %s for global attribute %s",
target->name, pp);
res = -EINVAL;
goto out_free;
}
p = config_strip_string(p);
if (!p || *p == '\0') {
free(internal_portal);
internal_portal = NULL;
} else {
/* We have been provided with a string, check the contents. */
if (strchr(p, ' ')) {
char *portals = strdup(p);
char *portal;
if (!portals) {
log_error("Memory error (internal_portal)");
res = -ENOMEM;
goto out_free;
}
portal = strtok(portals, " ");
while (portal != NULL) {
if (!is_addr(portal)) {
free(portals);
log_error("Invalid address supplied %s", portal);
res = -EINVAL;
goto out_free;
}
portal = strtok(NULL, " ");
}
free(portals);
} else {
/* No spaces */
if (!is_addr(p)) {
log_error("Invalid address supplied %s", p);
res = -EINVAL;
goto out_free;
}
}
free(internal_portal);
internal_portal = strdup(p);
}
} else {
log_error("Unknown attribute %s", pp);
res = -EINVAL;

View File

@@ -962,6 +962,9 @@ int main(int argc, char **argv)
if (err != 0)
exit(err);
err = kernel_attr_add(NULL, ISCSI_LINK_LOCAL_ATTR_NAME, 0644, 0);
if (err != 0)
exit(err);
err = kernel_attr_add(NULL, ISCSI_INTERNAL_PORTAL_ATTR_NAME, 0644, 0);
if (err != 0)
exit(err);

View File

@@ -27,6 +27,7 @@
#include "iscsid.h"
int iscsi_enabled;
char *internal_portal;
static u32 ttt;
@@ -1011,6 +1012,32 @@ static int cmnd_exec_auth(struct connection *conn)
return res;
}
static bool on_internal_portal(struct connection *conn)
{
if (!internal_portal)
return false;
if (strchr(internal_portal, ' ')) {
char *portals = strdup(internal_portal);
if (portals) {
char *portal = strtok(portals, " ");
while (portal != NULL) {
if (!strcmp(portal, conn->target_portal)) {
free(portals);
return true;
}
portal = strtok(NULL, " ");
}
free(portals);
}
return false;
} else {
return !strcmp(internal_portal, conn->target_portal);
}
}
static void cmnd_exec_login(struct connection *conn)
{
struct iscsi_login_req_hdr *req = (struct iscsi_login_req_hdr *)&conn->req.bhs;
@@ -1083,7 +1110,8 @@ static void cmnd_exec_login(struct connection *conn)
login_start(conn);
if (rsp->status_class)
return;
if (!accounts_empty(conn->tid, ISCSI_USER_DIR_INCOMING))
if (!accounts_empty(conn->tid, ISCSI_USER_DIR_INCOMING) &&
!on_internal_portal(conn))
goto auth_err;
if (rsp->status_class)
return;

View File

@@ -265,6 +265,7 @@ extern const char *get_error_str(int error);
/* iscsid.c */
extern int iscsi_enabled;
extern char *internal_portal;
extern int cmnd_execute(struct connection *conn);
extern void cmnd_finish(struct connection *conn);

View File

@@ -21,6 +21,7 @@
#define ISCSI_ENABLED_ATTR_NAME "enabled"
#define ISCSI_ISNS_ENTITY_ATTR_NAME "isns_entity_name"
#define ISCSI_ALLOWED_PORTAL_ATTR_NAME "allowed_portal"
#define ISCSI_INTERNAL_PORTAL_ATTR_NAME "internal_portal"
#define ISCSI_PER_PORTAL_ACL_ATTR_NAME "per_portal_acl"
#define ISCSI_TARGET_REDIRECTION_ATTR_NAME "redirect"
#define ISCSI_TARGET_REDIRECTION_VALUE_TEMP "temp"