Add per-source innetgr function pointer and use it in netgr_matches().
This will be used to implement LDAP-specific netgroup lookups when netgroup_base is set in ldap.conf.
This commit is contained in:
@@ -134,7 +134,7 @@ main(int argc, char *argv[])
|
|||||||
textdomain("sudoers");
|
textdomain("sudoers");
|
||||||
|
|
||||||
/* Initialize early, before any "goto done". */
|
/* Initialize early, before any "goto done". */
|
||||||
init_parse_tree(&merged_tree, NULL, NULL);
|
init_parse_tree(&merged_tree, NULL, NULL, NULL);
|
||||||
|
|
||||||
/* Read debug and plugin sections of sudo.conf. */
|
/* Read debug and plugin sections of sudo.conf. */
|
||||||
if (sudo_conf_read(NULL, SUDO_CONF_DEBUG|SUDO_CONF_PLUGINS) == -1)
|
if (sudo_conf_read(NULL, SUDO_CONF_DEBUG|SUDO_CONF_PLUGINS) == -1)
|
||||||
@@ -390,7 +390,7 @@ main(int argc, char *argv[])
|
|||||||
parse_tree = malloc(sizeof(*parse_tree));
|
parse_tree = malloc(sizeof(*parse_tree));
|
||||||
if (parse_tree == NULL)
|
if (parse_tree == NULL)
|
||||||
sudo_fatalx("%s", U_("unable to allocate memory"));
|
sudo_fatalx("%s", U_("unable to allocate memory"));
|
||||||
init_parse_tree(parse_tree, lhost, shost);
|
init_parse_tree(parse_tree, lhost, shost, NULL);
|
||||||
TAILQ_INSERT_TAIL(&parse_trees, parse_tree, entries);
|
TAILQ_INSERT_TAIL(&parse_trees, parse_tree, entries);
|
||||||
|
|
||||||
/* Setup defaults data structures. */
|
/* Setup defaults data structures. */
|
||||||
|
@@ -74,7 +74,7 @@ sudo_file_open(struct sudo_nss *nss)
|
|||||||
if (handle != NULL) {
|
if (handle != NULL) {
|
||||||
handle->fp = open_sudoers(sudoers_file, false, NULL);
|
handle->fp = open_sudoers(sudoers_file, false, NULL);
|
||||||
if (handle->fp != NULL) {
|
if (handle->fp != NULL) {
|
||||||
init_parse_tree(&handle->parse_tree, NULL, NULL);
|
init_parse_tree(&handle->parse_tree, NULL, NULL, nss);
|
||||||
} else {
|
} else {
|
||||||
free(handle);
|
free(handle);
|
||||||
handle = NULL;
|
handle = NULL;
|
||||||
|
@@ -3921,13 +3921,15 @@ free_userspec(struct userspec *us)
|
|||||||
* Takes ownership of lhost and shost.
|
* Takes ownership of lhost and shost.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
init_parse_tree(struct sudoers_parse_tree *parse_tree, char *lhost, char *shost)
|
init_parse_tree(struct sudoers_parse_tree *parse_tree, char *lhost, char *shost,
|
||||||
|
struct sudo_nss *nss)
|
||||||
{
|
{
|
||||||
TAILQ_INIT(&parse_tree->userspecs);
|
TAILQ_INIT(&parse_tree->userspecs);
|
||||||
TAILQ_INIT(&parse_tree->defaults);
|
TAILQ_INIT(&parse_tree->defaults);
|
||||||
parse_tree->aliases = NULL;
|
parse_tree->aliases = NULL;
|
||||||
parse_tree->shost = shost;
|
parse_tree->shost = shost;
|
||||||
parse_tree->lhost = lhost;
|
parse_tree->lhost = lhost;
|
||||||
|
parse_tree->nss = nss;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -1738,13 +1738,15 @@ free_userspec(struct userspec *us)
|
|||||||
* Takes ownership of lhost and shost.
|
* Takes ownership of lhost and shost.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
init_parse_tree(struct sudoers_parse_tree *parse_tree, char *lhost, char *shost)
|
init_parse_tree(struct sudoers_parse_tree *parse_tree, char *lhost, char *shost,
|
||||||
|
struct sudo_nss *nss)
|
||||||
{
|
{
|
||||||
TAILQ_INIT(&parse_tree->userspecs);
|
TAILQ_INIT(&parse_tree->userspecs);
|
||||||
TAILQ_INIT(&parse_tree->defaults);
|
TAILQ_INIT(&parse_tree->defaults);
|
||||||
parse_tree->aliases = NULL;
|
parse_tree->aliases = NULL;
|
||||||
parse_tree->shost = shost;
|
parse_tree->shost = shost;
|
||||||
parse_tree->lhost = lhost;
|
parse_tree->lhost = lhost;
|
||||||
|
parse_tree->nss = nss;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -348,7 +348,9 @@ sudo_ldap_check_non_unix_group(LDAP *ld, LDAPMessage *entry, struct passwd *pw)
|
|||||||
negated = true;
|
negated = true;
|
||||||
}
|
}
|
||||||
if (*val == '+') {
|
if (*val == '+') {
|
||||||
if (netgr_matches(val, def_netgroup_tuple ? user_runhost : NULL,
|
/* Custom innetgr() function not used here. */
|
||||||
|
if (netgr_matches(NULL, val,
|
||||||
|
def_netgroup_tuple ? user_runhost : NULL,
|
||||||
def_netgroup_tuple ? user_srunhost : NULL, pw->pw_name))
|
def_netgroup_tuple ? user_srunhost : NULL, pw->pw_name))
|
||||||
ret = true;
|
ret = true;
|
||||||
DPRINTF2("ldap sudoUser netgroup '%s%s' ... %s",
|
DPRINTF2("ldap sudoUser netgroup '%s%s' ... %s",
|
||||||
@@ -1766,7 +1768,7 @@ sudo_ldap_open(struct sudo_nss *nss)
|
|||||||
}
|
}
|
||||||
handle->ld = ld;
|
handle->ld = ld;
|
||||||
/* handle->pw = NULL; */
|
/* handle->pw = NULL; */
|
||||||
init_parse_tree(&handle->parse_tree, NULL, NULL);
|
init_parse_tree(&handle->parse_tree, NULL, NULL, nss);
|
||||||
nss->handle = handle;
|
nss->handle = handle;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@@ -79,7 +79,7 @@ user_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
|
|||||||
matched = !m->negated;
|
matched = !m->negated;
|
||||||
break;
|
break;
|
||||||
case NETGROUP:
|
case NETGROUP:
|
||||||
if (netgr_matches(m->name,
|
if (netgr_matches(parse_tree->nss, m->name,
|
||||||
def_netgroup_tuple ? lhost : NULL,
|
def_netgroup_tuple ? lhost : NULL,
|
||||||
def_netgroup_tuple ? shost : NULL, pw->pw_name))
|
def_netgroup_tuple ? shost : NULL, pw->pw_name))
|
||||||
matched = !m->negated;
|
matched = !m->negated;
|
||||||
@@ -174,7 +174,7 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
|
|||||||
user_matched = !m->negated;
|
user_matched = !m->negated;
|
||||||
break;
|
break;
|
||||||
case NETGROUP:
|
case NETGROUP:
|
||||||
if (netgr_matches(m->name,
|
if (netgr_matches(parse_tree->nss, m->name,
|
||||||
def_netgroup_tuple ? lhost : NULL,
|
def_netgroup_tuple ? lhost : NULL,
|
||||||
def_netgroup_tuple ? shost : NULL,
|
def_netgroup_tuple ? shost : NULL,
|
||||||
runas_pw->pw_name))
|
runas_pw->pw_name))
|
||||||
@@ -332,7 +332,7 @@ host_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
|
|||||||
matched = !m->negated;
|
matched = !m->negated;
|
||||||
break;
|
break;
|
||||||
case NETGROUP:
|
case NETGROUP:
|
||||||
if (netgr_matches(m->name, lhost, shost,
|
if (netgr_matches(parse_tree->nss, m->name, lhost, shost,
|
||||||
def_netgroup_tuple ? pw->pw_name : NULL))
|
def_netgroup_tuple ? pw->pw_name : NULL))
|
||||||
matched = !m->negated;
|
matched = !m->negated;
|
||||||
break;
|
break;
|
||||||
@@ -670,7 +670,8 @@ sudo_getdomainname(void)
|
|||||||
* in which case that argument is not checked...
|
* in which case that argument is not checked...
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
netgr_matches(const char *netgr, const char *lhost, const char *shost, const char *user)
|
netgr_matches(struct sudo_nss *nss, const char *netgr,
|
||||||
|
const char *lhost, const char *shost, const char *user)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_INNETGR
|
#ifdef HAVE_INNETGR
|
||||||
const char *domain;
|
const char *domain;
|
||||||
@@ -683,7 +684,6 @@ netgr_matches(const char *netgr, const char *lhost, const char *shost, const cha
|
|||||||
debug_return_bool(false);
|
debug_return_bool(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_INNETGR
|
|
||||||
/* make sure we have a valid netgroup, sudo style */
|
/* make sure we have a valid netgroup, sudo style */
|
||||||
if (*netgr++ != '+') {
|
if (*netgr++ != '+') {
|
||||||
sudo_debug_printf(SUDO_DEBUG_DIAG, "netgroup %s has no leading '+'",
|
sudo_debug_printf(SUDO_DEBUG_DIAG, "netgroup %s has no leading '+'",
|
||||||
@@ -694,16 +694,42 @@ netgr_matches(const char *netgr, const char *lhost, const char *shost, const cha
|
|||||||
/* get the domain name (if any) */
|
/* get the domain name (if any) */
|
||||||
domain = sudo_getdomainname();
|
domain = sudo_getdomainname();
|
||||||
|
|
||||||
if (innetgr(netgr, lhost, user, domain))
|
/* Use nss-specific innetgr() function if available. */
|
||||||
rc = true;
|
if (nss != NULL && nss->innetgr != NULL) {
|
||||||
else if (lhost != shost && innetgr(netgr, shost, user, domain))
|
switch (nss->innetgr(nss, netgr, lhost, user, domain)) {
|
||||||
rc = true;
|
case 0:
|
||||||
|
if (lhost != shost) {
|
||||||
|
if (nss->innetgr(nss, netgr, shost, user, domain) == 1)
|
||||||
|
rc = true;
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
case 1:
|
||||||
|
rc = true;
|
||||||
|
goto done;
|
||||||
|
default:
|
||||||
|
/* Not supported, use system innetgr(3). */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_INNETGR
|
||||||
|
/* Use system innetgr() function. */
|
||||||
|
if (innetgr(netgr, lhost, user, domain) == 1) {
|
||||||
|
rc = true;
|
||||||
|
} else if (lhost != shost) {
|
||||||
|
if (innetgr(netgr, shost, user, domain) == 1)
|
||||||
|
rc = true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
|
||||||
|
"%s: no system netgroup support", __func__);
|
||||||
|
#endif /* HAVE_INNETGR */
|
||||||
|
|
||||||
|
done:
|
||||||
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
|
||||||
"netgroup %s matches (%s|%s, %s, %s): %s", netgr, lhost ? lhost : "",
|
"netgroup %s matches (%s|%s, %s, %s): %s", netgr, lhost ? lhost : "",
|
||||||
shost ? shost : "", user ? user : "", domain ? domain : "",
|
shost ? shost : "", user ? user : "", domain ? domain : "",
|
||||||
rc ? "true" : "false");
|
rc ? "true" : "false");
|
||||||
#endif /* HAVE_INNETGR */
|
|
||||||
|
|
||||||
debug_return_bool(rc);
|
debug_return_bool(rc);
|
||||||
}
|
}
|
||||||
|
@@ -302,12 +302,14 @@ struct defaults {
|
|||||||
/*
|
/*
|
||||||
* Parsed sudoers policy.
|
* Parsed sudoers policy.
|
||||||
*/
|
*/
|
||||||
|
struct sudo_nss;
|
||||||
struct sudoers_parse_tree {
|
struct sudoers_parse_tree {
|
||||||
TAILQ_ENTRY(sudoers_parse_tree) entries;
|
TAILQ_ENTRY(sudoers_parse_tree) entries;
|
||||||
struct userspec_list userspecs;
|
struct userspec_list userspecs;
|
||||||
struct defaults_list defaults;
|
struct defaults_list defaults;
|
||||||
struct rbtree *aliases;
|
struct rbtree *aliases;
|
||||||
char *shost, *lhost;
|
char *shost, *lhost;
|
||||||
|
struct sudo_nss *nss;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -380,7 +382,7 @@ void free_userspec(struct userspec *us);
|
|||||||
void free_userspecs(struct userspec_list *usl);
|
void free_userspecs(struct userspec_list *usl);
|
||||||
void free_default(struct defaults *def);
|
void free_default(struct defaults *def);
|
||||||
void free_defaults(struct defaults_list *defs);
|
void free_defaults(struct defaults_list *defs);
|
||||||
void init_parse_tree(struct sudoers_parse_tree *parse_tree, char *lhost, char *shost);
|
void init_parse_tree(struct sudoers_parse_tree *parse_tree, char *lhost, char *shost, struct sudo_nss *nss);
|
||||||
void free_parse_tree(struct sudoers_parse_tree *parse_tree);
|
void free_parse_tree(struct sudoers_parse_tree *parse_tree);
|
||||||
void reparent_parse_tree(struct sudoers_parse_tree *new_tree);
|
void reparent_parse_tree(struct sudoers_parse_tree *new_tree);
|
||||||
bool parser_leak_add(enum parser_leak_types type, void *v);
|
bool parser_leak_add(enum parser_leak_types type, void *v);
|
||||||
@@ -401,7 +403,7 @@ struct group;
|
|||||||
struct passwd;
|
struct passwd;
|
||||||
bool group_matches(const char *sudoers_group, const struct group *gr);
|
bool group_matches(const char *sudoers_group, const struct group *gr);
|
||||||
bool hostname_matches(const char *shost, const char *lhost, const char *pattern);
|
bool hostname_matches(const char *shost, const char *lhost, const char *pattern);
|
||||||
bool netgr_matches(const char *netgr, const char *lhost, const char *shost, const char *user);
|
bool netgr_matches(struct sudo_nss *nss, const char *netgr, const char *lhost, const char *shost, const char *user);
|
||||||
bool usergr_matches(const char *group, const char *user, const struct passwd *pw);
|
bool usergr_matches(const char *group, const char *user, const struct passwd *pw);
|
||||||
bool userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw);
|
bool userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw);
|
||||||
int cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m, const char *runchroot, struct cmnd_info *info);
|
int cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m, const char *runchroot, struct cmnd_info *info);
|
||||||
|
@@ -304,7 +304,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Only one sudoers source, the sudoers file itself. */
|
/* Only one sudoers source, the sudoers file itself. */
|
||||||
init_parse_tree(&parse_tree, NULL, NULL);
|
init_parse_tree(&parse_tree, NULL, NULL, NULL);
|
||||||
memset(&sudo_nss_fuzz, 0, sizeof(sudo_nss_fuzz));
|
memset(&sudo_nss_fuzz, 0, sizeof(sudo_nss_fuzz));
|
||||||
sudo_nss_fuzz.parse_tree = &parse_tree;
|
sudo_nss_fuzz.parse_tree = &parse_tree;
|
||||||
sudo_nss_fuzz.query = sudo_fuzz_query;
|
sudo_nss_fuzz.query = sudo_fuzz_query;
|
||||||
|
@@ -139,7 +139,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
|||||||
|
|
||||||
/* Initialize defaults and parse LDIF-format sudoers. */
|
/* Initialize defaults and parse LDIF-format sudoers. */
|
||||||
init_defaults();
|
init_defaults();
|
||||||
init_parse_tree(&parse_tree, NULL, NULL);
|
init_parse_tree(&parse_tree, NULL, NULL, NULL);
|
||||||
sudoers_parse_ldif(&parse_tree, fp, "ou=SUDOers,dc=sudo,dc=ws", true);
|
sudoers_parse_ldif(&parse_tree, fp, "ou=SUDOers,dc=sudo,dc=ws", true);
|
||||||
|
|
||||||
/* Cleanup. */
|
/* Cleanup. */
|
||||||
|
@@ -203,7 +203,7 @@ sudo_sss_check_user(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
|
|||||||
switch (*val) {
|
switch (*val) {
|
||||||
case '+':
|
case '+':
|
||||||
/* Netgroup spec found, check membership. */
|
/* Netgroup spec found, check membership. */
|
||||||
if (netgr_matches(val, def_netgroup_tuple ? host : NULL,
|
if (netgr_matches(NULL, val, def_netgroup_tuple ? host : NULL,
|
||||||
def_netgroup_tuple ? shost : NULL, handle->pw->pw_name)) {
|
def_netgroup_tuple ? shost : NULL, handle->pw->pw_name)) {
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
@@ -638,7 +638,8 @@ sudo_sss_open(struct sudo_nss *nss)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The "parse tree" contains userspecs, defaults, aliases and hostnames. */
|
/* The "parse tree" contains userspecs, defaults, aliases and hostnames. */
|
||||||
init_parse_tree(&handle->parse_tree, handle->ipa_host, handle->ipa_shost);
|
init_parse_tree(&handle->parse_tree, handle->ipa_host, handle->ipa_shost,
|
||||||
|
nss);
|
||||||
nss->handle = handle;
|
nss->handle = handle;
|
||||||
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_DEBUG, "handle=%p", handle);
|
sudo_debug_printf(SUDO_DEBUG_DEBUG, "handle=%p", handle);
|
||||||
|
@@ -33,6 +33,8 @@ struct sudo_nss {
|
|||||||
struct sudoers_parse_tree *(*parse)(struct sudo_nss *nss);
|
struct sudoers_parse_tree *(*parse)(struct sudo_nss *nss);
|
||||||
int (*query)(struct sudo_nss *nss, struct passwd *pw);
|
int (*query)(struct sudo_nss *nss, struct passwd *pw);
|
||||||
int (*getdefs)(struct sudo_nss *nss);
|
int (*getdefs)(struct sudo_nss *nss);
|
||||||
|
int (*innetgr)(struct sudo_nss *nss, const char *netgr, const char *host,
|
||||||
|
const char *user, const char *domain);
|
||||||
void *handle;
|
void *handle;
|
||||||
struct sudoers_parse_tree *parse_tree;
|
struct sudoers_parse_tree *parse_tree;
|
||||||
bool ret_if_found;
|
bool ret_if_found;
|
||||||
|
Reference in New Issue
Block a user