ctld: Convert struct auth_group to a C++ class

Make data members private and convert functions for adding and
checking user and initiator authentication into class methods.

Use std::string to store the label for an auth_group and add a label()
method to retrieve a const C string version for logging.

Replace AG_TYPE_* macros with a scoped enum.

Replace the TAILQ of auth_group objects in struct conf with an
unordered_map<> of named auth_group objects.  Anonymous auth_group
objects for targets are no longer stored in a global data structure.

Since a target can have a pointer to either named or anonymous
objects, use a shared_ptr<> to store references to auth_group objects.
Use the shared_ptr<>'s reference count to determine if a named
auth_group is unused in conf_verify() instead of walking all the
linked lists to check for references.

While here, avoid making a second copy of socket address for a client
and instead just store a pointer in ctld_connection.

Sponsored by:	Chelsio Communications
Pull Request:	https://github.com/freebsd/freebsd-src/pull/1794
This commit is contained in:
John Baldwin 2025-08-04 15:38:06 -04:00
parent e1849d9a8d
commit eb0dc901a5
5 changed files with 221 additions and 281 deletions

View file

@ -114,64 +114,35 @@ conf_set_timeout(int timeout)
conf->conf_timeout = timeout;
}
static bool
_auth_group_set_type(struct auth_group *ag, const char *str)
{
int type;
if (strcmp(str, "none") == 0) {
type = AG_TYPE_NO_AUTHENTICATION;
} else if (strcmp(str, "deny") == 0) {
type = AG_TYPE_DENY;
} else if (strcmp(str, "chap") == 0) {
type = AG_TYPE_CHAP;
} else if (strcmp(str, "chap-mutual") == 0) {
type = AG_TYPE_CHAP_MUTUAL;
} else {
log_warnx("invalid auth-type \"%s\" for %s", str, ag->ag_label);
return (false);
}
if (ag->ag_type != AG_TYPE_UNKNOWN && ag->ag_type != type) {
log_warnx("cannot set auth-type to \"%s\" for %s; "
"already has a different type", str, ag->ag_label);
return (false);
}
ag->ag_type = type;
return (true);
}
bool
auth_group_add_chap(const char *user, const char *secret)
{
return (auth_new_chap(auth_group, user, secret));
return (auth_group->add_chap(user, secret));
}
bool
auth_group_add_chap_mutual(const char *user, const char *secret,
const char *user2, const char *secret2)
{
return (auth_new_chap_mutual(auth_group, user, secret, user2, secret2));
return (auth_group->add_chap_mutual(user, secret, user2, secret2));
}
bool
auth_group_add_initiator_name(const char *name)
{
return (auth_name_new(auth_group, name));
return (auth_group->add_initiator_name(name));
}
bool
auth_group_add_initiator_portal(const char *portal)
{
return (auth_portal_new(auth_group, portal));
return (auth_group->add_initiator_portal(portal));
}
bool
auth_group_set_type(const char *type)
{
return (_auth_group_set_type(auth_group, type));
return (auth_group->set_type(type));
}
bool
@ -188,12 +159,12 @@ auth_group_start(const char *name)
}
conf->conf_default_ag_defined = true;
auth_group = auth_group_find(conf, "default");
auth_group = auth_group_find(conf, "default").get();
return (true);
}
auth_group = auth_group_new(conf, name);
return (auth_group != NULL);
return (auth_group != nullptr);
}
void
@ -245,14 +216,14 @@ portal_group_add_option(const char *name, const char *value)
bool
portal_group_set_discovery_auth_group(const char *name)
{
if (portal_group->pg_discovery_auth_group != NULL) {
if (portal_group->pg_discovery_auth_group != nullptr) {
log_warnx("discovery-auth-group for portal-group "
"\"%s\" specified more than once",
portal_group->pg_name);
return (false);
}
portal_group->pg_discovery_auth_group = auth_group_find(conf, name);
if (portal_group->pg_discovery_auth_group == NULL) {
if (portal_group->pg_discovery_auth_group == nullptr) {
log_warnx("unknown discovery-auth-group \"%s\" "
"for portal-group \"%s\"", name, portal_group->pg_name);
return (false);
@ -518,15 +489,15 @@ target_finish(void)
static bool
target_use_private_auth(const char *keyword)
{
if (target->t_auth_group != NULL) {
if (target->t_auth_group != nullptr) {
if (!target->t_private_auth) {
log_warnx("cannot use both auth-group and "
"%s for target \"%s\"", keyword, target->t_name);
return (false);
}
} else {
target->t_auth_group = auth_group_new(conf, target);
if (target->t_auth_group == NULL)
target->t_auth_group = auth_group_new(target);
if (target->t_auth_group == nullptr)
return (false);
target->t_private_auth = true;
}
@ -538,7 +509,7 @@ target_add_chap(const char *user, const char *secret)
{
if (!target_use_private_auth("chap"))
return (false);
return (auth_new_chap(target->t_auth_group, user, secret));
return (target->t_auth_group->add_chap(user, secret));
}
bool
@ -547,7 +518,7 @@ target_add_chap_mutual(const char *user, const char *secret,
{
if (!target_use_private_auth("chap-mutual"))
return (false);
return (auth_new_chap_mutual(target->t_auth_group, user, secret, user2,
return (target->t_auth_group->add_chap_mutual(user, secret, user2,
secret2));
}
@ -556,7 +527,7 @@ target_add_initiator_name(const char *name)
{
if (!target_use_private_auth("initiator-name"))
return (false);
return (auth_name_new(target->t_auth_group, name));
return (target->t_auth_group->add_initiator_name(name));
}
bool
@ -564,7 +535,7 @@ target_add_initiator_portal(const char *addr)
{
if (!target_use_private_auth("initiator-portal"))
return (false);
return (auth_portal_new(target->t_auth_group, addr));
return (target->t_auth_group->add_initiator_portal(addr));
}
bool
@ -599,7 +570,7 @@ bool
target_add_portal_group(const char *pg_name, const char *ag_name)
{
struct portal_group *pg;
struct auth_group *ag;
auth_group_sp ag;
struct port *p;
pg = portal_group_find(conf, pg_name);
@ -616,8 +587,7 @@ target_add_portal_group(const char *pg_name, const char *ag_name)
ag_name, target->t_name);
return (false);
}
} else
ag = NULL;
}
p = port_new(conf, target, pg);
if (p == NULL) {
@ -625,7 +595,7 @@ target_add_portal_group(const char *pg_name, const char *ag_name)
pg_name, target->t_name);
return (false);
}
p->p_auth_group = ag;
p->p_auth_group = std::move(ag);
return (true);
}
@ -644,7 +614,7 @@ target_set_alias(const char *alias)
bool
target_set_auth_group(const char *name)
{
if (target->t_auth_group != NULL) {
if (target->t_auth_group != nullptr) {
if (target->t_private_auth)
log_warnx("cannot use both auth-group and explicit "
"authorisations for target \"%s\"", target->t_name);
@ -654,7 +624,7 @@ target_set_auth_group(const char *name)
return (false);
}
target->t_auth_group = auth_group_find(conf, name);
if (target->t_auth_group == NULL) {
if (target->t_auth_group == nullptr) {
log_warnx("unknown auth-group \"%s\" for target \"%s\"", name,
target->t_name);
return (false);
@ -667,7 +637,7 @@ target_set_auth_type(const char *type)
{
if (!target_use_private_auth("auth-type"))
return (false);
return (_auth_group_set_type(target->t_auth_group, type));
return (target->t_auth_group->set_type(type));
}
bool

View file

@ -100,12 +100,9 @@ conf_new(void)
{
struct conf *conf;
conf = reinterpret_cast<struct conf *>(calloc(1, sizeof(*conf)));
if (conf == NULL)
log_err(1, "calloc");
conf = new struct conf();
TAILQ_INIT(&conf->conf_luns);
TAILQ_INIT(&conf->conf_targets);
TAILQ_INIT(&conf->conf_auth_groups);
TAILQ_INIT(&conf->conf_ports);
TAILQ_INIT(&conf->conf_portal_groups);
TAILQ_INIT(&conf->conf_isns);
@ -124,7 +121,6 @@ conf_delete(struct conf *conf)
{
struct lun *lun, *ltmp;
struct target *targ, *tmp;
struct auth_group *ag, *cagtmp;
struct portal_group *pg, *cpgtmp;
struct isns *is, *istmp;
@ -134,30 +130,65 @@ conf_delete(struct conf *conf)
lun_delete(lun);
TAILQ_FOREACH_SAFE(targ, &conf->conf_targets, t_next, tmp)
target_delete(targ);
TAILQ_FOREACH_SAFE(ag, &conf->conf_auth_groups, ag_next, cagtmp)
auth_group_delete(ag);
TAILQ_FOREACH_SAFE(pg, &conf->conf_portal_groups, pg_next, cpgtmp)
portal_group_delete(pg);
TAILQ_FOREACH_SAFE(is, &conf->conf_isns, i_next, istmp)
isns_delete(is);
assert(TAILQ_EMPTY(&conf->conf_ports));
free(conf->conf_pidfile_path);
free(conf);
delete conf;
}
bool
auth_group::set_type(const char *str)
{
auth_type type;
if (strcmp(str, "none") == 0) {
type = auth_type::NO_AUTHENTICATION;
} else if (strcmp(str, "deny") == 0) {
type = auth_type::DENY;
} else if (strcmp(str, "chap") == 0) {
type = auth_type::CHAP;
} else if (strcmp(str, "chap-mutual") == 0) {
type = auth_type::CHAP_MUTUAL;
} else {
log_warnx("invalid auth-type \"%s\" for %s", str, label());
return (false);
}
if (ag_type != auth_type::UNKNOWN && ag_type != type) {
log_warnx("cannot set auth-type to \"%s\" for %s; "
"already has a different type", str, label());
return (false);
}
ag_type = type;
return (true);
}
void
auth_group::set_type(auth_type type)
{
assert(ag_type == auth_type::UNKNOWN);
ag_type = type;
}
const struct auth *
auth_find(const struct auth_group *ag, const char *user)
auth_group::find_auth(std::string_view user) const
{
auto it = ag->ag_auths.find(user);
if (it == ag->ag_auths.end())
auto it = ag_auths.find(std::string(user));
if (it == ag_auths.end())
return (nullptr);
return (&it->second);
}
static void
auth_check_secret_length(const struct auth_group *ag, const char *user,
const char *secret, const char *secret_type)
void
auth_group::check_secret_length(const char *user, const char *secret,
const char *secret_type)
{
size_t len;
@ -165,34 +196,31 @@ auth_check_secret_length(const struct auth_group *ag, const char *user,
assert(len != 0);
if (len > 16) {
log_warnx("%s for user \"%s\", %s, is too long; it should be "
"at most 16 characters long", secret_type, user,
ag->ag_label);
"at most 16 characters long", secret_type, user, label());
}
if (len < 12) {
log_warnx("%s for user \"%s\", %s, is too short; it should be "
"at least 12 characters long", secret_type, user,
ag->ag_label);
"at least 12 characters long", secret_type, user, label());
}
}
bool
auth_new_chap(struct auth_group *ag, const char *user,
const char *secret)
auth_group::add_chap(const char *user, const char *secret)
{
if (ag->ag_type == AG_TYPE_UNKNOWN)
ag->ag_type = AG_TYPE_CHAP;
if (ag->ag_type != AG_TYPE_CHAP) {
if (ag_type == auth_type::UNKNOWN)
ag_type = auth_type::CHAP;
if (ag_type != auth_type::CHAP) {
log_warnx("cannot mix \"chap\" authentication with "
"other types for %s", ag->ag_label);
"other types for %s", label());
return (false);
}
auth_check_secret_length(ag, user, secret, "secret");
check_secret_length(user, secret, "secret");
const auto &pair = ag->ag_auths.try_emplace(user, secret);
const auto &pair = ag_auths.try_emplace(user, secret);
if (!pair.second) {
log_warnx("duplicate credentials for user \"%s\" for %s",
user, ag->ag_label);
user, label());
return (false);
}
@ -200,25 +228,24 @@ auth_new_chap(struct auth_group *ag, const char *user,
}
bool
auth_new_chap_mutual(struct auth_group *ag, const char *user,
const char *secret, const char *user2, const char *secret2)
auth_group::add_chap_mutual(const char *user, const char *secret,
const char *user2, const char *secret2)
{
if (ag->ag_type == AG_TYPE_UNKNOWN)
ag->ag_type = AG_TYPE_CHAP_MUTUAL;
if (ag->ag_type != AG_TYPE_CHAP_MUTUAL) {
if (ag_type == auth_type::UNKNOWN)
ag_type = auth_type::CHAP_MUTUAL;
if (ag_type != auth_type::CHAP_MUTUAL) {
log_warnx("cannot mix \"chap-mutual\" authentication "
"with other types for %s", ag->ag_label);
"with other types for %s", label());
return (false);
}
auth_check_secret_length(ag, user, secret, "secret");
auth_check_secret_length(ag, user, secret2, "mutual secret");
check_secret_length(user, secret, "secret");
check_secret_length(user, secret2, "mutual secret");
const auto &pair = ag->ag_auths.try_emplace(user, secret, user2,
secret2);
const auto &pair = ag_auths.try_emplace(user, secret, user2, secret2);
if (!pair.second) {
log_warnx("duplicate credentials for user \"%s\" for %s",
user, ag->ag_label);
user, label());
return (false);
}
@ -226,20 +253,20 @@ auth_new_chap_mutual(struct auth_group *ag, const char *user,
}
bool
auth_name_new(struct auth_group *ag, const char *name)
auth_group::add_initiator_name(std::string_view name)
{
/* Silently ignore duplicates. */
ag->ag_names.emplace(name);
ag_names.emplace(name);
return (true);
}
bool
auth_name_check(const struct auth_group *ag, const char *initiator_name)
auth_group::initiator_permitted(std::string_view initiator_name) const
{
if (ag->ag_names.empty())
if (ag_names.empty())
return (true);
return (ag->ag_names.count(initiator_name) != 0);
return (ag_names.count(std::string(initiator_name)) != 0);
}
bool
@ -309,15 +336,16 @@ auth_portal::parse(const char *portal)
}
bool
auth_portal_new(struct auth_group *ag, const char *portal)
auth_group::add_initiator_portal(const char *portal)
{
auth_portal ap;
if (!ap.parse(portal)) {
log_warnx("invalid initiator portal \"%s\"", portal);
log_warnx("invalid initiator portal \"%s\" for %s", portal,
label());
return (false);
}
ag->ag_portals.emplace_back(ap);
ag_portals.emplace_back(ap);
return (true);
}
@ -354,80 +382,46 @@ auth_portal::matches(const struct sockaddr *sa) const
}
bool
auth_portal_check(const struct auth_group *ag,
const struct sockaddr_storage *sa)
auth_group::initiator_permitted(const struct sockaddr *sa) const
{
if (ag->ag_portals.empty())
if (ag_portals.empty())
return (true);
for (const auth_portal &ap : ag->ag_portals)
if (ap.matches((const struct sockaddr *)sa))
for (const auth_portal &ap : ag_portals)
if (ap.matches(sa))
return (true);
return (false);
}
static struct auth_group *
auth_group_create(struct conf *conf, const char *name, char *label)
{
struct auth_group *ag;
ag = new auth_group();
if (name != NULL)
ag->ag_name = checked_strdup(name);
ag->ag_label = label;
ag->ag_conf = conf;
TAILQ_INSERT_TAIL(&conf->conf_auth_groups, ag, ag_next);
return (ag);
}
struct auth_group *
auth_group_new(struct conf *conf, const char *name)
{
struct auth_group *ag;
char *label;
ag = auth_group_find(conf, name);
if (ag != NULL) {
const auto &pair = conf->conf_auth_groups.try_emplace(name,
std::make_shared<auth_group>(freebsd::stringf("auth-group \"%s\"",
name)));
if (!pair.second) {
log_warnx("duplicated auth-group \"%s\"", name);
return (NULL);
}
asprintf(&label, "auth-group \"%s\"", name);
return (auth_group_create(conf, name, label));
return (pair.first->second.get());
}
struct auth_group *
auth_group_new(struct conf *conf, struct target *target)
auth_group_sp
auth_group_new(struct target *target)
{
char *label;
asprintf(&label, "target \"%s\"", target->t_name);
return (auth_group_create(conf, NULL, label));
return (std::make_shared<auth_group>(freebsd::stringf("target \"%s\"",
target->t_name)));
}
void
auth_group_delete(struct auth_group *ag)
{
TAILQ_REMOVE(&ag->ag_conf->conf_auth_groups, ag, ag_next);
free(ag->ag_label);
free(ag->ag_name);
delete ag;
}
struct auth_group *
auth_group_sp
auth_group_find(const struct conf *conf, const char *name)
{
struct auth_group *ag;
auto it = conf->conf_auth_groups.find(name);
if (it == conf->conf_auth_groups.end())
return {};
assert(name != NULL);
TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) {
if (ag->ag_name != NULL && strcmp(ag->ag_name, name) == 0)
return (ag);
}
return (NULL);
return (it->second);
}
static struct portal *
@ -466,9 +460,7 @@ portal_group_new(struct conf *conf, const char *name)
return (NULL);
}
pg = reinterpret_cast<struct portal_group *>(calloc(1, sizeof(*pg)));
if (pg == NULL)
log_err(1, "calloc");
pg = new portal_group();
pg->pg_name = checked_strdup(name);
pg->pg_options = nvlist_create(0);
TAILQ_INIT(&pg->pg_portals);
@ -498,7 +490,7 @@ portal_group_delete(struct portal_group *pg)
free(pg->pg_name);
free(pg->pg_offload);
free(pg->pg_redirection);
free(pg);
delete pg;
}
struct portal_group *
@ -920,9 +912,7 @@ port_new(struct conf *conf, struct target *target, struct portal_group *pg)
free(name);
return (NULL);
}
port = reinterpret_cast<struct port *>(calloc(1, sizeof(*port)));
if (port == NULL)
log_err(1, "calloc");
port = new struct port();
port->p_conf = conf;
port->p_name = name;
TAILQ_INSERT_TAIL(&conf->conf_ports, port, p_next);
@ -965,9 +955,7 @@ port_new_ioctl(struct conf *conf, struct kports *kports, struct target *target,
free(name);
return (NULL);
}
port = reinterpret_cast<struct port *>(calloc(1, sizeof(*port)));
if (port == NULL)
log_err(1, "calloc");
port = new struct port();
port->p_conf = conf;
port->p_name = name;
port->p_ioctl_port = true;
@ -994,9 +982,7 @@ port_new_pp(struct conf *conf, struct target *target, struct pport *pp)
free(name);
return (NULL);
}
port = reinterpret_cast<struct port *>(calloc(1, sizeof(*port)));
if (port == NULL)
log_err(1, "calloc");
port = new struct port();
port->p_conf = conf;
port->p_name = name;
TAILQ_INSERT_TAIL(&conf->conf_ports, port, p_next);
@ -1075,9 +1061,7 @@ target_new(struct conf *conf, const char *name)
if (valid_iscsi_name(name, log_warnx) == false) {
return (NULL);
}
targ = reinterpret_cast<struct target *>(calloc(1, sizeof(*targ)));
if (targ == NULL)
log_err(1, "calloc");
targ = new target();
targ->t_name = checked_strdup(name);
/*
@ -1106,7 +1090,7 @@ target_delete(struct target *targ)
free(targ->t_pport);
free(targ->t_name);
free(targ->t_redirection);
free(targ);
delete targ;
}
struct target *
@ -1260,7 +1244,7 @@ connection_new(struct portal *portal, int fd, const char *host,
conn->conn.conn_socket = fd;
conn->conn_portal = portal;
conn->conn_initiator_addr = checked_strdup(host);
memcpy(&conn->conn_initiator_sa, client_sa, client_sa->sa_len);
conn->conn_initiator_sa = client_sa;
return (conn);
}
@ -1324,9 +1308,7 @@ conf_verify_lun(struct lun *lun)
bool
conf_verify(struct conf *conf)
{
struct auth_group *ag;
struct portal_group *pg;
struct port *port;
struct target *targ;
struct lun *lun;
bool found;
@ -1393,32 +1375,16 @@ conf_verify(struct conf *conf)
pg->pg_unassigned = true;
}
}
TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) {
found = false;
TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
if (targ->t_auth_group == ag) {
found = true;
break;
}
}
TAILQ_FOREACH(port, &conf->conf_ports, p_next) {
if (port->p_auth_group == ag) {
found = true;
break;
}
}
TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
if (pg->pg_discovery_auth_group == ag) {
found = true;
break;
}
}
if (!found && ag->ag_name != NULL &&
strcmp(ag->ag_name, "default") != 0 &&
strcmp(ag->ag_name, "no-authentication") != 0 &&
strcmp(ag->ag_name, "no-access") != 0) {
for (const auto &kv : conf->conf_auth_groups) {
const std::string &ag_name = kv.first;
if (ag_name == "default" ||
ag_name == "no-authentication" ||
ag_name == "no-access")
continue;
if (kv.second.use_count() == 1) {
log_warnx("auth-group \"%s\" not assigned "
"to any target", ag->ag_name);
"to any target", ag_name.c_str());
}
}
@ -2200,11 +2166,11 @@ conf_new_from_file(const char *path, bool ucl)
ag = auth_group_new(conf, "no-authentication");
assert(ag != NULL);
ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
ag->set_type(auth_type::NO_AUTHENTICATION);
ag = auth_group_new(conf, "no-access");
assert(ag != NULL);
ag->ag_type = AG_TYPE_DENY;
ag->set_type(auth_type::DENY);
pg = portal_group_new(conf, "default");
assert(pg != NULL);
@ -2226,9 +2192,9 @@ conf_new_from_file(const char *path, bool ucl)
if (conf->conf_default_ag_defined == false) {
log_debugx("auth-group \"default\" not defined; "
"going with defaults");
ag = auth_group_find(conf, "default");
ag = auth_group_find(conf, "default").get();
assert(ag != NULL);
ag->ag_type = AG_TYPE_DENY;
ag->set_type(auth_type::DENY);
}
if (conf->conf_default_pg_defined == false) {

View file

@ -42,6 +42,7 @@
#include <libutil.h>
#include <list>
#include <memory>
#include <string>
#include <string_view>
#include <unordered_map>
@ -83,23 +84,47 @@ private:
int ap_mask = 0;
};
#define AG_TYPE_UNKNOWN 0
#define AG_TYPE_DENY 1
#define AG_TYPE_NO_AUTHENTICATION 2
#define AG_TYPE_CHAP 3
#define AG_TYPE_CHAP_MUTUAL 4
enum class auth_type {
UNKNOWN,
DENY,
NO_AUTHENTICATION,
CHAP,
CHAP_MUTUAL
};
struct auth_group {
TAILQ_ENTRY(auth_group) ag_next;
struct conf *ag_conf;
char *ag_name;
char *ag_label;
int ag_type;
auth_group(std::string label) : ag_label(label) {}
auth_type type() const { return ag_type; }
bool set_type(const char *str);
void set_type(auth_type type);
const char *label() const { return ag_label.c_str(); }
bool add_chap(const char *user, const char *secret);
bool add_chap_mutual(const char *user, const char *secret,
const char *user2, const char *secret2);
const struct auth *find_auth(std::string_view user) const;
bool add_initiator_name(std::string_view initiator_name);
bool initiator_permitted(std::string_view initiator_name) const;
bool add_initiator_portal(const char *initiator_portal);
bool initiator_permitted(const struct sockaddr *sa) const;
private:
void check_secret_length(const char *user, const char *secret,
const char *secret_type);
std::string ag_label;
auth_type ag_type = auth_type::UNKNOWN;
std::unordered_map<std::string, auth> ag_auths;
std::unordered_set<std::string> ag_names;
std::list<auth_portal> ag_portals;
};
using auth_group_sp = std::shared_ptr<auth_group>;
struct portal {
TAILQ_ENTRY(portal) p_next;
struct portal_group *p_portal_group;
@ -125,14 +150,14 @@ struct portal_group {
struct conf *pg_conf;
nvlist_t *pg_options;
char *pg_name;
struct auth_group *pg_discovery_auth_group;
int pg_discovery_filter;
bool pg_foreign;
bool pg_unassigned;
auth_group_sp pg_discovery_auth_group;
int pg_discovery_filter = PG_FILTER_UNKNOWN;
bool pg_foreign = false;
bool pg_unassigned = false;
TAILQ_HEAD(, portal) pg_portals;
TAILQ_HEAD(, port) pg_ports;
char *pg_offload;
char *pg_redirection;
char *pg_offload = nullptr;
char *pg_redirection = nullptr;
int pg_dscp;
int pg_pcp;
@ -156,15 +181,15 @@ struct port {
TAILQ_ENTRY(port) p_ts;
struct conf *p_conf;
char *p_name;
struct auth_group *p_auth_group;
struct portal_group *p_portal_group;
struct pport *p_pport;
auth_group_sp p_auth_group;
struct portal_group *p_portal_group = nullptr;
struct pport *p_pport = nullptr;
struct target *p_target;
bool p_ioctl_port;
int p_ioctl_pp;
int p_ioctl_vp;
uint32_t p_ctl_port;
bool p_ioctl_port = false;
int p_ioctl_pp = 0;
int p_ioctl_vp = 0;
uint32_t p_ctl_port = 0;
};
struct lun {
@ -187,8 +212,8 @@ struct lun {
struct target {
TAILQ_ENTRY(target) t_next;
struct conf *t_conf;
struct lun *t_luns[MAX_LUNS];
struct auth_group *t_auth_group;
struct lun *t_luns[MAX_LUNS] = {};
auth_group_sp t_auth_group;
TAILQ_HEAD(, port) t_ports;
char *t_name;
char *t_alias;
@ -206,10 +231,10 @@ struct isns {
};
struct conf {
char *conf_pidfile_path;
char *conf_pidfile_path = nullptr;
TAILQ_HEAD(, lun) conf_luns;
TAILQ_HEAD(, target) conf_targets;
TAILQ_HEAD(, auth_group) conf_auth_groups;
std::unordered_map<std::string, auth_group_sp> conf_auth_groups;
TAILQ_HEAD(, port) conf_ports;
TAILQ_HEAD(, portal_group) conf_portal_groups;
TAILQ_HEAD(, isns) conf_isns;
@ -220,13 +245,13 @@ struct conf {
int conf_maxproc;
#ifdef ICL_KERNEL_PROXY
int conf_portal_id;
int conf_portal_id = 0;
#endif
struct pidfh *conf_pidfh;
struct pidfh *conf_pidfh = nullptr;
bool conf_default_pg_defined;
bool conf_default_ag_defined;
bool conf_kernel_port_on;
bool conf_default_pg_defined = false;
bool conf_default_ag_defined = false;
bool conf_kernel_port_on = false;
};
/* Physical ports exposed by the kernel */
@ -248,7 +273,7 @@ struct ctld_connection {
char *conn_initiator_addr;
char *conn_initiator_alias;
uint8_t conn_initiator_isid[6];
struct sockaddr_storage conn_initiator_sa;
const struct sockaddr *conn_initiator_sa;
int conn_max_recv_data_segment_limit;
int conn_max_send_data_segment_limit;
int conn_max_burst_limit;
@ -270,30 +295,10 @@ void conf_start(struct conf *new_conf);
bool conf_verify(struct conf *conf);
struct auth_group *auth_group_new(struct conf *conf, const char *name);
struct auth_group *auth_group_new(struct conf *conf,
struct target *target);
void auth_group_delete(struct auth_group *ag);
struct auth_group *auth_group_find(const struct conf *conf,
auth_group_sp auth_group_new(struct target *target);
auth_group_sp auth_group_find(const struct conf *conf,
const char *name);
bool auth_new_chap(struct auth_group *ag, const char *user,
const char *secret);
bool auth_new_chap_mutual(struct auth_group *ag,
const char *user, const char *secret,
const char *user2, const char *secret2);
const struct auth *auth_find(const struct auth_group *ag,
const char *user);
bool auth_name_new(struct auth_group *ag,
const char *initiator_name);
bool auth_name_check(const struct auth_group *ag,
const char *initiator_name);
bool auth_portal_new(struct auth_group *ag,
const char *initiator_portal);
bool auth_portal_check(const struct auth_group *ag,
const struct sockaddr_storage *sa);
struct portal_group *portal_group_new(struct conf *conf, const char *name);
void portal_group_delete(struct portal_group *pg);
struct portal_group *portal_group_find(const struct conf *conf,

View file

@ -156,32 +156,32 @@ discovery_target_filtered_out(const struct ctld_connection *conn,
int error;
targ = port->p_target;
ag = port->p_auth_group;
if (ag == NULL)
ag = targ->t_auth_group;
ag = port->p_auth_group.get();
if (ag == nullptr)
ag = targ->t_auth_group.get();
pg = conn->conn_portal->p_portal_group;
assert(pg->pg_discovery_filter != PG_FILTER_UNKNOWN);
if (pg->pg_discovery_filter >= PG_FILTER_PORTAL &&
!auth_portal_check(ag, &conn->conn_initiator_sa)) {
!ag->initiator_permitted(conn->conn_initiator_sa)) {
log_debugx("initiator does not match initiator portals "
"allowed for target \"%s\"; skipping", targ->t_name);
return (true);
}
if (pg->pg_discovery_filter >= PG_FILTER_PORTAL_NAME &&
!auth_name_check(ag, conn->conn_initiator_name)) {
!ag->initiator_permitted(conn->conn_initiator_name)) {
log_debugx("initiator does not match initiator names "
"allowed for target \"%s\"; skipping", targ->t_name);
return (true);
}
if (pg->pg_discovery_filter >= PG_FILTER_PORTAL_NAME_AUTH &&
ag->ag_type != AG_TYPE_NO_AUTHENTICATION) {
ag->type() != auth_type::NO_AUTHENTICATION) {
if (conn->conn_chap == NULL) {
assert(pg->pg_discovery_auth_group->ag_type ==
AG_TYPE_NO_AUTHENTICATION);
assert(pg->pg_discovery_auth_group->type() ==
auth_type::NO_AUTHENTICATION);
log_debugx("initiator didn't authenticate, but target "
"\"%s\" requires CHAP; skipping", targ->t_name);
@ -189,7 +189,7 @@ discovery_target_filtered_out(const struct ctld_connection *conn,
}
assert(conn->conn_user != NULL);
auth = auth_find(ag, conn->conn_user);
auth = ag->find_auth(conn->conn_user);
if (auth == NULL) {
log_debugx("CHAP user \"%s\" doesn't match target "
"\"%s\"; skipping", conn->conn_user, targ->t_name);

View file

@ -367,9 +367,9 @@ login_receive_chap_r(struct connection *conn, struct auth_group *ag,
/*
* Verify the response.
*/
assert(ag->ag_type == AG_TYPE_CHAP ||
ag->ag_type == AG_TYPE_CHAP_MUTUAL);
auth = auth_find(ag, chap_n);
assert(ag->type() == auth_type::CHAP ||
ag->type() == auth_type::CHAP_MUTUAL);
auth = ag->find_auth(chap_n);
if (auth == NULL) {
login_send_error(request, 0x02, 0x01);
log_errx(1, "received CHAP Login with invalid user \"%s\"",
@ -987,32 +987,31 @@ login(struct ctld_connection *conn)
* At this point we know what kind of authentication we need.
*/
if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
ag = conn->conn_port->p_auth_group;
if (ag == NULL)
ag = conn->conn_target->t_auth_group;
if (conn->conn_port->p_auth_group == NULL &&
ag = conn->conn_port->p_auth_group.get();
if (ag == nullptr)
ag = conn->conn_target->t_auth_group.get();
if (conn->conn_port->p_auth_group == nullptr &&
conn->conn_target->t_private_auth) {
log_debugx("initiator requests to connect "
"to target \"%s\"", conn->conn_target->t_name);
} else {
log_debugx("initiator requests to connect "
"to target \"%s\"; %s",
conn->conn_target->t_name,
ag->ag_label);
conn->conn_target->t_name, ag->label());
}
} else {
assert(conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY);
ag = pg->pg_discovery_auth_group;
ag = pg->pg_discovery_auth_group.get();
log_debugx("initiator requests discovery session; %s",
ag->ag_label);
ag->label());
}
if (ag->ag_type == AG_TYPE_DENY) {
if (ag->type() == auth_type::DENY) {
login_send_error(request, 0x02, 0x01);
log_errx(1, "auth-type is \"deny\"");
}
if (ag->ag_type == AG_TYPE_UNKNOWN) {
if (ag->type() == auth_type::UNKNOWN) {
/*
* This can happen with empty auth-group.
*/
@ -1023,12 +1022,12 @@ login(struct ctld_connection *conn)
/*
* Enforce initiator-name and initiator-portal.
*/
if (!auth_name_check(ag, initiator_name)) {
if (!ag->initiator_permitted(initiator_name)) {
login_send_error(request, 0x02, 0x02);
log_errx(1, "initiator does not match allowed initiator names");
}
if (!auth_portal_check(ag, &conn->conn_initiator_sa)) {
if (!ag->initiator_permitted(conn->conn_initiator_sa)) {
login_send_error(request, 0x02, 0x02);
log_errx(1, "initiator does not match allowed "
"initiator portals");
@ -1039,7 +1038,7 @@ login(struct ctld_connection *conn)
* at all.
*/
if (login_csg(request) == BHSLR_STAGE_OPERATIONAL_NEGOTIATION) {
if (ag->ag_type != AG_TYPE_NO_AUTHENTICATION) {
if (ag->type() != auth_type::NO_AUTHENTICATION) {
login_send_error(request, 0x02, 0x01);
log_errx(1, "initiator skipped the authentication, "
"but authentication is required");
@ -1058,7 +1057,7 @@ login(struct ctld_connection *conn)
response_keys = keys_new();
trans = (bhslr->bhslr_flags & BHSLR_FLAGS_TRANSIT) != 0;
auth_method = keys_find(request_keys, "AuthMethod");
if (ag->ag_type == AG_TYPE_NO_AUTHENTICATION) {
if (ag->type() == auth_type::NO_AUTHENTICATION) {
log_debugx("authentication not required");
if (auth_method == NULL ||
login_list_contains(auth_method, "None")) {
@ -1104,7 +1103,7 @@ login(struct ctld_connection *conn)
exit(1);
}
if (ag->ag_type != AG_TYPE_NO_AUTHENTICATION) {
if (ag->type() != auth_type::NO_AUTHENTICATION) {
login_chap(conn, ag);
login_negotiate(conn, NULL);
} else if (trans) {