2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-09-04 16:25:25 +00:00

Add sudo_ldap_is_negated() and sudo_ldap_is_negated() functions

and use them to parse negated entries instead of doing it manually.
This commit is contained in:
Todd C. Miller
2016-11-16 13:46:38 -07:00
parent da73733724
commit d6c30ba273
2 changed files with 94 additions and 92 deletions

View File

@@ -713,6 +713,28 @@ sudo_ldap_check_non_unix_group(LDAP *ld, LDAPMessage *entry, struct passwd *pw)
debug_return_bool(ret); debug_return_bool(ret);
} }
/*
* Returns true if the string pointed to by valp begins with an
* odd number of '!' characters. Intervening blanks are ignored.
* Stores the address of the string after '!' removal in valp.
*/
static bool
sudo_ldap_is_negated(char **valp)
{
char *val = *valp;
bool ret = false;
debug_decl(sudo_ldap_is_negated, SUDOERS_DEBUG_LDAP)
while (*val == '!') {
ret = !ret;
do {
val++;
} while (isblank((unsigned char)*val));
}
*valp = val;
debug_return_bool(ret);
}
/* /*
* Walk through search results and return true if we have a * Walk through search results and return true if we have a
* host match, else false. * host match, else false.
@@ -722,6 +744,7 @@ sudo_ldap_check_host(LDAP *ld, LDAPMessage *entry, struct passwd *pw)
{ {
struct berval **bv, **p; struct berval **bv, **p;
char *val; char *val;
bool negated;
int matched = UNSPEC; int matched = UNSPEC;
debug_decl(sudo_ldap_check_host, SUDOERS_DEBUG_LDAP) debug_decl(sudo_ldap_check_host, SUDOERS_DEBUG_LDAP)
@@ -735,14 +758,8 @@ sudo_ldap_check_host(LDAP *ld, LDAPMessage *entry, struct passwd *pw)
/* walk through values */ /* walk through values */
for (p = bv; *p != NULL && matched != false; p++) { for (p = bv; *p != NULL && matched != false; p++) {
bool foundbang = false;
val = (*p)->bv_val; val = (*p)->bv_val;
negated = sudo_ldap_is_negated(&val);
if (*val == '!') {
val++;
foundbang = true;
}
/* match any or address or netgroup or hostname */ /* match any or address or netgroup or hostname */
if (strcmp(val, "ALL") == 0 || addr_matches(val) || if (strcmp(val, "ALL") == 0 || addr_matches(val) ||
@@ -750,7 +767,7 @@ sudo_ldap_check_host(LDAP *ld, LDAPMessage *entry, struct passwd *pw)
def_netgroup_tuple ? pw->pw_name : NULL) || def_netgroup_tuple ? pw->pw_name : NULL) ||
hostname_matches(user_srunhost, user_runhost, val)) { hostname_matches(user_srunhost, user_runhost, val)) {
matched = foundbang ? false : true; matched = negated ? false : true;
} }
DPRINTF2("ldap sudoHost '%s' ... %s", DPRINTF2("ldap sudoHost '%s' ... %s",
val, matched == true ? "MATCH!" : "not"); val, matched == true ? "MATCH!" : "not");
@@ -971,8 +988,8 @@ sudo_ldap_check_command(LDAP *ld, LDAPMessage *entry, int *setenv_implied)
struct sudo_digest digest, *allowed_digest = NULL; struct sudo_digest digest, *allowed_digest = NULL;
struct berval **bv, **p; struct berval **bv, **p;
char *allowed_cmnd, *allowed_args, *val; char *allowed_cmnd, *allowed_args, *val;
bool foundbang;
int ret = UNSPEC; int ret = UNSPEC;
bool negated;
debug_decl(sudo_ldap_check_command, SUDOERS_DEBUG_LDAP) debug_decl(sudo_ldap_check_command, SUDOERS_DEBUG_LDAP)
if (!entry) if (!entry)
@@ -984,6 +1001,7 @@ sudo_ldap_check_command(LDAP *ld, LDAPMessage *entry, int *setenv_implied)
for (p = bv; *p != NULL && ret != false; p++) { for (p = bv; *p != NULL && ret != false; p++) {
val = (*p)->bv_val; val = (*p)->bv_val;
/* Match against ALL ? */ /* Match against ALL ? */
if (strcmp(val, "ALL") == 0) { if (strcmp(val, "ALL") == 0) {
ret = true; ret = true;
@@ -997,13 +1015,8 @@ sudo_ldap_check_command(LDAP *ld, LDAPMessage *entry, int *setenv_implied)
allowed_digest = sudo_ldap_extract_digest(&val, &digest); allowed_digest = sudo_ldap_extract_digest(&val, &digest);
/* check for !command */ /* check for !command */
if (*val == '!') { allowed_cmnd = val;
foundbang = true; negated = sudo_ldap_is_negated(&allowed_cmnd);
allowed_cmnd = val + 1; /* !command */
} else {
foundbang = false;
allowed_cmnd = val; /* command */
}
/* split optional args away from command */ /* split optional args away from command */
allowed_args = strchr(allowed_cmnd, ' '); allowed_args = strchr(allowed_cmnd, ' ');
@@ -1016,7 +1029,7 @@ sudo_ldap_check_command(LDAP *ld, LDAPMessage *entry, int *setenv_implied)
* If allowed (no bang) set ret but keep on checking. * If allowed (no bang) set ret but keep on checking.
* If disallowed (bang), exit loop. * If disallowed (bang), exit loop.
*/ */
ret = foundbang ? false : true; ret = negated ? false : true;
} }
if (allowed_args != NULL) if (allowed_args != NULL)
allowed_args[-1] = ' '; /* restore val */ allowed_args[-1] = ' '; /* restore val */
@@ -1041,7 +1054,8 @@ static int
sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, char *option) sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, char *option)
{ {
struct berval **bv, **p; struct berval **bv, **p;
char ch, *var; char *var;
bool negated;
int ret = UNSPEC; int ret = UNSPEC;
debug_decl(sudo_ldap_check_bool, SUDOERS_DEBUG_LDAP) debug_decl(sudo_ldap_check_bool, SUDOERS_DEBUG_LDAP)
@@ -1054,13 +1068,12 @@ sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, char *option)
/* walk through options */ /* walk through options */
for (p = bv; *p != NULL; p++) { for (p = bv; *p != NULL; p++) {
var = (*p)->bv_val;; var = (*p)->bv_val;
DPRINTF2("ldap sudoOption: '%s'", var); DPRINTF2("ldap sudoOption: '%s'", var);
if ((ch = *var) == '!') negated = sudo_ldap_is_negated(&var);
var++;
if (strcmp(var, option) == 0) if (strcmp(var, option) == 0)
ret = (ch != '!'); ret = negated ? false : true;
} }
ldap_value_free_len(bv); ldap_value_free_len(bv);
@@ -1112,13 +1125,7 @@ sudo_ldap_parse_option(char *optstr, char **varp, char **valp)
} }
} else { } else {
/* Boolean value, either true or false. */ /* Boolean value, either true or false. */
op = true; op = sudo_ldap_is_negated(&var) ? false : true;
while (*var == '!') {
op = !op;
do {
var++;
} while (isblank((unsigned char)*var));
}
} }
*varp = var; *varp = var;
*valp = val; *valp = val;
@@ -2448,24 +2455,18 @@ sudo_ldap_display_entry_short(LDAP *ld, LDAPMessage *entry, struct passwd *pw,
bv = ldap_get_values_len(ld, entry, "sudoOption"); bv = ldap_get_values_len(ld, entry, "sudoOption");
if (bv != NULL) { if (bv != NULL) {
for (p = bv; *p != NULL; p++) { for (p = bv; *p != NULL; p++) {
char *cp = (*p)->bv_val; char *val = (*p)->bv_val;
if (*cp == '!') bool negated = sudo_ldap_is_negated(&val);
cp++; if (strcmp(val, "authenticate") == 0)
if (strcmp(cp, "authenticate") == 0) sudo_lbuf_append(lbuf, negated ? "NOPASSWD: " : "PASSWD: ");
sudo_lbuf_append(lbuf, (*p)->bv_val[0] == '!' ? else if (strcmp(val, "sudoedit_follow") == 0)
"NOPASSWD: " : "PASSWD: "); sudo_lbuf_append(lbuf, negated ? "NOFOLLOW: " : "FOLLOW: ");
else if (strcmp(cp, "sudoedit_follow") == 0) else if (strcmp(val, "noexec") == 0)
sudo_lbuf_append(lbuf, (*p)->bv_val[0] == '!' ? sudo_lbuf_append(lbuf, negated ? "EXEC: " : "NOEXEC: ");
"NOFOLLOW: " : "FOLLOW: "); else if (strcmp(val, "setenv") == 0)
else if (strcmp(cp, "noexec") == 0) sudo_lbuf_append(lbuf, negated ? "NOSETENV: " : "SETENV: ");
sudo_lbuf_append(lbuf, (*p)->bv_val[0] == '!' ? else if (strcmp(val, "mail_all_cmnds") == 0 || strcmp(val, "mail_always") == 0)
"EXEC: " : "NOEXEC: "); sudo_lbuf_append(lbuf, negated ? "NOMAIL: " : "MAIL: ");
else if (strcmp(cp, "setenv") == 0)
sudo_lbuf_append(lbuf, (*p)->bv_val[0] == '!' ?
"NOSETENV: " : "SETENV: ");
else if (strcmp(cp, "mail_all_cmnds") == 0 || strcmp(cp, "mail_always") == 0)
sudo_lbuf_append(lbuf, (*p)->bv_val[0] == '!' ?
"NOMAIL: " : "MAIL: ");
} }
ldap_value_free_len(bv); ldap_value_free_len(bv);
} }

View File

@@ -541,6 +541,28 @@ bad:
debug_return_int(-1); debug_return_int(-1);
} }
/*
* Returns true if the string pointed to by valp begins with an
* odd number of '!' characters. Intervening blanks are ignored.
* Stores the address of the string after '!' removal in valp.
*/
static bool
sudo_sss_is_negated(char **valp)
{
char *val = *valp;
bool ret = false;
debug_decl(sudo_sss_is_negated, SUDOERS_DEBUG_SSSD)
while (*val == '!') {
ret = !ret;
do {
val++;
} while (isblank((unsigned char)*val));
}
*valp = val;
debug_return_bool(ret);
}
static int static int
sudo_sss_checkpw(struct sudo_nss *nss, struct passwd *pw) sudo_sss_checkpw(struct sudo_nss *nss, struct passwd *pw)
{ {
@@ -742,6 +764,7 @@ sudo_sss_check_host(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
{ {
char **val_array, *val; char **val_array, *val;
int matched = UNSPEC; int matched = UNSPEC;
bool negated;
int i; int i;
debug_decl(sudo_sss_check_host, SUDOERS_DEBUG_SSSD); debug_decl(sudo_sss_check_host, SUDOERS_DEBUG_SSSD);
@@ -762,15 +785,10 @@ sudo_sss_check_host(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
/* walk through values */ /* walk through values */
for (i = 0; val_array[i] != NULL && matched != false; ++i) { for (i = 0; val_array[i] != NULL && matched != false; ++i) {
bool foundbang = false;
val = val_array[i]; val = val_array[i];
sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val); sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val);
if (*val == '!') { negated = sudo_sss_is_negated(&val);
val++;
foundbang = true;
}
/* match any or address or netgroup or hostname */ /* match any or address or netgroup or hostname */
if (strcmp(val, "ALL") == 0 || addr_matches(val) || if (strcmp(val, "ALL") == 0 || addr_matches(val) ||
@@ -778,7 +796,7 @@ sudo_sss_check_host(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
def_netgroup_tuple ? handle->pw->pw_name : NULL) || def_netgroup_tuple ? handle->pw->pw_name : NULL) ||
hostname_matches(handle->shost, handle->host, val)) { hostname_matches(handle->shost, handle->host, val)) {
matched = foundbang ? false : true; matched = negated ? false : true;
} }
sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoHost '%s' ... %s", sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoHost '%s' ... %s",
@@ -950,8 +968,9 @@ static int
sudo_sss_check_bool(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule, sudo_sss_check_bool(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule,
char *option) char *option)
{ {
char ch, *var, **val_array = NULL; char *var, **val_array = NULL;
int i, ret = UNSPEC; int i, ret = UNSPEC;
bool negated;
debug_decl(sudo_sss_check_bool, SUDOERS_DEBUG_SSSD); debug_decl(sudo_sss_check_bool, SUDOERS_DEBUG_SSSD);
if (rule == NULL) if (rule == NULL)
@@ -973,10 +992,9 @@ sudo_sss_check_bool(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule,
var = val_array[i]; var = val_array[i];
sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoOption: '%s'", var); sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoOption: '%s'", var);
if ((ch = *var) == '!') negated = sudo_sss_is_negated(&var);
var++;
if (strcmp(var, option) == 0) if (strcmp(var, option) == 0)
ret = (ch != '!'); ret = negated ? false : true;
} }
handle->fn_free_values(val_array); handle->fn_free_values(val_array);
@@ -1064,7 +1082,7 @@ sudo_sss_check_command(struct sudo_sss_handle *handle,
char **val_array = NULL, *val; char **val_array = NULL, *val;
char *allowed_cmnd, *allowed_args; char *allowed_cmnd, *allowed_args;
int ret = UNSPEC; int ret = UNSPEC;
bool foundbang; bool negated;
unsigned int i; unsigned int i;
struct sudo_digest digest, *allowed_digest = NULL; struct sudo_digest digest, *allowed_digest = NULL;
debug_decl(sudo_sss_check_command, SUDOERS_DEBUG_SSSD); debug_decl(sudo_sss_check_command, SUDOERS_DEBUG_SSSD);
@@ -1102,13 +1120,8 @@ sudo_sss_check_command(struct sudo_sss_handle *handle,
allowed_digest = sudo_sss_extract_digest(&val, &digest); allowed_digest = sudo_sss_extract_digest(&val, &digest);
/* check for !command */ /* check for !command */
if (*val == '!') { allowed_cmnd = val;
foundbang = true; negated = sudo_sss_is_negated(&allowed_cmnd);
allowed_cmnd = val + 1; /* !command */
} else {
foundbang = false;
allowed_cmnd = val; /* command */
}
/* split optional args away from command */ /* split optional args away from command */
allowed_args = strchr(allowed_cmnd, ' '); allowed_args = strchr(allowed_cmnd, ' ');
@@ -1121,7 +1134,7 @@ sudo_sss_check_command(struct sudo_sss_handle *handle,
* If allowed (no bang) set ret but keep on checking. * If allowed (no bang) set ret but keep on checking.
* If disallowed (bang), exit loop. * If disallowed (bang), exit loop.
*/ */
ret = foundbang ? false : true; ret = negated ? false : true;
} }
if (allowed_args != NULL) if (allowed_args != NULL)
allowed_args[-1] = ' '; /* restore val */ allowed_args[-1] = ' '; /* restore val */
@@ -1181,13 +1194,7 @@ sudo_sss_parse_option(char *optstr, char **varp, char **valp)
} }
} else { } else {
/* Boolean value, either true or false. */ /* Boolean value, either true or false. */
op = true; op = sudo_sss_is_negated(&var) ? false : true;
while (*var == '!') {
op = !op;
do {
var++;
} while (isblank((unsigned char)*var));
}
} }
*varp = var; *varp = var;
*valp = val; *valp = val;
@@ -1709,24 +1716,18 @@ sudo_sss_display_entry_short(struct sudo_sss_handle *handle,
switch (handle->fn_get_values(rule, "sudoOption", &val_array)) { switch (handle->fn_get_values(rule, "sudoOption", &val_array)) {
case 0: case 0:
for (i = 0; val_array[i] != NULL; ++i) { for (i = 0; val_array[i] != NULL; ++i) {
char *cp = val_array[i]; char *val = val_array[i];
if (*cp == '!') bool negated = sudo_sss_is_negated(&val);
cp++; if (strcmp(val, "authenticate") == 0)
if (strcmp(cp, "authenticate") == 0) sudo_lbuf_append(lbuf, negated ? "NOPASSWD: " : "PASSWD: ");
sudo_lbuf_append(lbuf, val_array[i][0] == '!' ? else if (strcmp(val, "sudoedit_follow") == 0)
"NOPASSWD: " : "PASSWD: "); sudo_lbuf_append(lbuf, negated ? "NOFOLLOW: " : "FOLLOW: ");
else if (strcmp(cp, "sudoedit_follow") == 0) else if (strcmp(val, "noexec") == 0)
sudo_lbuf_append(lbuf, val_array[i][0] == '!' ? sudo_lbuf_append(lbuf, negated ? "EXEC: " : "NOEXEC: ");
"NOFOLLOW: " : "FOLLOW: "); else if (strcmp(val, "setenv") == 0)
else if (strcmp(cp, "noexec") == 0) sudo_lbuf_append(lbuf, negated ? "NOSETENV: " : "SETENV: ");
sudo_lbuf_append(lbuf, val_array[i][0] == '!' ? else if (strcmp(val, "mail_all_cmnds") == 0 || strcmp(val, "mail_always") == 0)
"EXEC: " : "NOEXEC: "); sudo_lbuf_append(lbuf, negated ? "NOMAIL: " : "MAIL: ");
else if (strcmp(cp, "setenv") == 0)
sudo_lbuf_append(lbuf, val_array[i][0] == '!' ?
"NOSETENV: " : "SETENV: ");
else if (strcmp(cp, "mail_all_cmnds") == 0 || strcmp(cp, "mail_always") == 0)
sudo_lbuf_append(lbuf, val_array[i][0] == '!' ?
"NOMAIL: " : "MAIL: ");
} }
handle->fn_free_values(val_array); handle->fn_free_values(val_array);
break; break;