mirror of
https://github.com/opnsense/src.git
synced 2026-06-20 22:19:13 -04:00
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:
parent
e1849d9a8d
commit
eb0dc901a5
5 changed files with 221 additions and 281 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue