|
version 1.1.1.1, 2012/10/09 09:29:52
|
version 1.1.1.4, 2014/06/15 16:12:54
|
|
Line 1
|
Line 1
|
| /* |
/* |
| * Copyright (c) 2003-2012 Todd C. Miller <Todd.Miller@courtesan.com> | * Copyright (c) 2003-2013 Todd C. Miller <Todd.Miller@courtesan.com> |
| * Copyright (c) 2011 Daniel Kopecek <dkopecek@redhat.com> |
* Copyright (c) 2011 Daniel Kopecek <dkopecek@redhat.com> |
| * |
* |
| * This code is derived from software contributed by Aaron Spangler. |
* This code is derived from software contributed by Aaron Spangler. |
|
Line 21
|
Line 21
|
| |
|
| #include <sys/types.h> |
#include <sys/types.h> |
| #include <sys/time.h> |
#include <sys/time.h> |
| #include <sys/param.h> |
|
| #include <sys/stat.h> |
#include <sys/stat.h> |
| #include <stdio.h> |
#include <stdio.h> |
| #ifdef STDC_HEADERS |
#ifdef STDC_HEADERS |
|
Line 41
|
Line 40
|
| #ifdef HAVE_UNISTD_H |
#ifdef HAVE_UNISTD_H |
| # include <unistd.h> |
# include <unistd.h> |
| #endif /* HAVE_UNISTD_H */ |
#endif /* HAVE_UNISTD_H */ |
| #if TIME_WITH_SYS_TIME | #ifdef TIME_WITH_SYS_TIME |
| # include <time.h> |
# include <time.h> |
| #endif |
#endif |
| #ifdef HAVE_DLOPEN |
|
| # include <dlfcn.h> |
|
| #else |
|
| # include "compat/dlfcn.h" |
|
| #endif |
|
| #include <ctype.h> |
#include <ctype.h> |
| #include <pwd.h> |
#include <pwd.h> |
| #include <grp.h> |
#include <grp.h> |
|
Line 59
|
Line 53
|
| #include "sudoers.h" |
#include "sudoers.h" |
| #include "parse.h" |
#include "parse.h" |
| #include "lbuf.h" |
#include "lbuf.h" |
| |
#include "sudo_dso.h" |
| #include "sudo_debug.h" |
#include "sudo_debug.h" |
| |
|
| /* SSSD <--> SUDO interface - do not change */ |
/* SSSD <--> SUDO interface - do not change */ |
|
Line 180 sudo_sss_filter_result(struct sudo_sss_handle *handle,
|
Line 175 sudo_sss_filter_result(struct sudo_sss_handle *handle,
|
| debug_decl(sudo_sss_filter_result, SUDO_DEBUG_SSSD) |
debug_decl(sudo_sss_filter_result, SUDO_DEBUG_SSSD) |
| |
|
| sudo_debug_printf(SUDO_DEBUG_DEBUG, "in_res=%p, count=%u, act=%s", |
sudo_debug_printf(SUDO_DEBUG_DEBUG, "in_res=%p, count=%u, act=%s", |
| in_res, in_res->num_rules, | in_res, in_res ? in_res->num_rules : 0, |
| act == _SUDO_SSS_FILTER_EXCLUDE ? "EXCLUDE" : "INCLUDE"); |
act == _SUDO_SSS_FILTER_EXCLUDE ? "EXCLUDE" : "INCLUDE"); |
| |
|
| if (in_res == NULL) |
if (in_res == NULL) |
|
Line 212 sudo_sss_filter_result(struct sudo_sss_handle *handle,
|
Line 207 sudo_sss_filter_result(struct sudo_sss_handle *handle,
|
| sudo_debug_printf(SUDO_DEBUG_DEBUG, |
sudo_debug_printf(SUDO_DEBUG_DEBUG, |
| "reallocating result: %p (count: %u -> %u)", out_res->rules, |
"reallocating result: %p (count: %u -> %u)", out_res->rules, |
| in_res->num_rules, l); |
in_res->num_rules, l); |
| out_res->rules = erealloc3(out_res->rules, l, sizeof(struct sss_sudo_rule)); | if (l > 0) { |
| | out_res->rules = |
| | erealloc3(out_res->rules, l, sizeof(struct sss_sudo_rule)); |
| | } else { |
| | efree(out_res->rules); |
| | out_res->rules = NULL; |
| | } |
| } |
} |
| |
|
| out_res->num_rules = l; |
out_res->num_rules = l; |
|
Line 221 sudo_sss_filter_result(struct sudo_sss_handle *handle,
|
Line 222 sudo_sss_filter_result(struct sudo_sss_handle *handle,
|
| } |
} |
| |
|
| struct sudo_nss sudo_nss_sss = { |
struct sudo_nss sudo_nss_sss = { |
| &sudo_nss_sss, | { NULL, NULL }, |
| NULL, | |
| sudo_sss_open, |
sudo_sss_open, |
| sudo_sss_close, |
sudo_sss_close, |
| sudo_sss_parse, |
sudo_sss_parse, |
|
Line 246 static int sudo_sss_open(struct sudo_nss *nss)
|
Line 246 static int sudo_sss_open(struct sudo_nss *nss)
|
| handle = emalloc(sizeof(struct sudo_sss_handle)); |
handle = emalloc(sizeof(struct sudo_sss_handle)); |
| |
|
| /* Load symbols */ |
/* Load symbols */ |
| handle->ssslib = dlopen(path, RTLD_LAZY); | handle->ssslib = sudo_dso_load(path, SUDO_DSO_LAZY); |
| if (handle->ssslib == NULL) { |
if (handle->ssslib == NULL) { |
| warningx(_("Unable to dlopen %s: %s"), path, dlerror()); | warningx(U_("unable to load %s: %s"), path, sudo_dso_strerror()); |
| warningx(_("Unable to initialize SSS source. Is SSSD installed on your machine?")); | warningx(U_("unable to initialize SSS source. Is SSSD installed on your machine?")); |
| debug_return_int(EFAULT); |
debug_return_int(EFAULT); |
| } |
} |
| |
|
| handle->fn_send_recv = dlsym(handle->ssslib, "sss_sudo_send_recv"); | handle->fn_send_recv = |
| | sudo_dso_findsym(handle->ssslib, "sss_sudo_send_recv"); |
| if (handle->fn_send_recv == NULL) { |
if (handle->fn_send_recv == NULL) { |
| warningx(_("unable to find symbol \"%s\" in %s"), path, | warningx(U_("unable to find symbol \"%s\" in %s"), path, |
| "sss_sudo_send_recv"); |
"sss_sudo_send_recv"); |
| debug_return_int(EFAULT); |
debug_return_int(EFAULT); |
| } |
} |
| |
|
| handle->fn_send_recv_defaults = |
handle->fn_send_recv_defaults = |
| dlsym(handle->ssslib, "sss_sudo_send_recv_defaults"); | sudo_dso_findsym(handle->ssslib, "sss_sudo_send_recv_defaults"); |
| if (handle->fn_send_recv_defaults == NULL) { |
if (handle->fn_send_recv_defaults == NULL) { |
| warningx(_("unable to find symbol \"%s\" in %s"), path, | warningx(U_("unable to find symbol \"%s\" in %s"), path, |
| "sss_sudo_send_recv_defaults"); |
"sss_sudo_send_recv_defaults"); |
| debug_return_int(EFAULT); |
debug_return_int(EFAULT); |
| } |
} |
| |
|
| handle->fn_free_result = dlsym(handle->ssslib, "sss_sudo_free_result"); | handle->fn_free_result = |
| | sudo_dso_findsym(handle->ssslib, "sss_sudo_free_result"); |
| if (handle->fn_free_result == NULL) { |
if (handle->fn_free_result == NULL) { |
| warningx(_("unable to find symbol \"%s\" in %s"), path, | warningx(U_("unable to find symbol \"%s\" in %s"), path, |
| "sss_sudo_free_result"); |
"sss_sudo_free_result"); |
| debug_return_int(EFAULT); |
debug_return_int(EFAULT); |
| } |
} |
| |
|
| handle->fn_get_values = dlsym(handle->ssslib, "sss_sudo_get_values"); | handle->fn_get_values = |
| | sudo_dso_findsym(handle->ssslib, "sss_sudo_get_values"); |
| if (handle->fn_get_values == NULL) { |
if (handle->fn_get_values == NULL) { |
| warningx(_("unable to find symbol \"%s\" in %s"), path, | warningx(U_("unable to find symbol \"%s\" in %s"), path, |
| "sss_sudo_get_values"); |
"sss_sudo_get_values"); |
| debug_return_int(EFAULT); |
debug_return_int(EFAULT); |
| } |
} |
| |
|
| handle->fn_free_values = dlsym(handle->ssslib, "sss_sudo_free_values"); | handle->fn_free_values = |
| | sudo_dso_findsym(handle->ssslib, "sss_sudo_free_values"); |
| if (handle->fn_free_values == NULL) { |
if (handle->fn_free_values == NULL) { |
| warningx(_("unable to find symbol \"%s\" in %s"), path, | warningx(U_("unable to find symbol \"%s\" in %s"), path, |
| "sss_sudo_free_values"); |
"sss_sudo_free_values"); |
| debug_return_int(EFAULT); |
debug_return_int(EFAULT); |
| } |
} |
|
Line 306 static int sudo_sss_close(struct sudo_nss *nss)
|
Line 310 static int sudo_sss_close(struct sudo_nss *nss)
|
| |
|
| if (nss && nss->handle) { |
if (nss && nss->handle) { |
| handle = nss->handle; |
handle = nss->handle; |
| dlclose(handle->ssslib); | sudo_dso_unload(handle->ssslib); |
| | efree(nss->handle); |
| } |
} |
| |
|
| efree(nss->handle); |
|
| debug_return_int(0); |
debug_return_int(0); |
| } |
} |
| |
|
|
Line 345 static int sudo_sss_setdefs(struct sudo_nss *nss)
|
Line 348 static int sudo_sss_setdefs(struct sudo_nss *nss)
|
| |
|
| if (sss_error == ENOENT) { |
if (sss_error == ENOENT) { |
| sudo_debug_printf(SUDO_DEBUG_INFO, "The user was not found in SSSD."); |
sudo_debug_printf(SUDO_DEBUG_INFO, "The user was not found in SSSD."); |
| debug_return_int(-1); | debug_return_int(0); |
| } else if(sss_error != 0) { |
} else if(sss_error != 0) { |
| sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error); |
sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error); |
| debug_return_int(-1); |
debug_return_int(-1); |
|
Line 466 sudo_sss_check_runas_user(struct sudo_sss_handle *hand
|
Line 469 sudo_sss_check_runas_user(struct sudo_sss_handle *hand
|
| /* FALLTHROUGH */ |
/* FALLTHROUGH */ |
| sudo_debug_printf(SUDO_DEBUG_DEBUG, "FALLTHROUGH"); |
sudo_debug_printf(SUDO_DEBUG_DEBUG, "FALLTHROUGH"); |
| default: |
default: |
| if (strcasecmp(val, runas_pw->pw_name) == 0) { | if (userpw_matches(val, runas_pw->pw_name, runas_pw)) { |
| sudo_debug_printf(SUDO_DEBUG_DEBUG, |
sudo_debug_printf(SUDO_DEBUG_DEBUG, |
| "%s == %s (pw_name) => match", val, runas_pw->pw_name); |
"%s == %s (pw_name) => match", val, runas_pw->pw_name); |
| ret = true; |
ret = true; |
|
Line 529 sudo_sss_check_runas_group(struct sudo_sss_handle *han
|
Line 532 sudo_sss_check_runas_group(struct sudo_sss_handle *han
|
| * Walk through search results and return true if we have a runas match, |
* Walk through search results and return true if we have a runas match, |
| * else false. RunAs info is optional. |
* else false. RunAs info is optional. |
| */ |
*/ |
| static int | static bool |
| sudo_sss_check_runas(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) |
sudo_sss_check_runas(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) |
| { |
{ |
| int ret; | bool ret; |
| debug_decl(sudo_sss_check_runas, SUDO_DEBUG_SSSD); |
debug_decl(sudo_sss_check_runas, SUDO_DEBUG_SSSD); |
| |
|
| if (rule == NULL) |
if (rule == NULL) |
| debug_return_int(false); | debug_return_bool(false); |
| |
|
| ret = sudo_sss_check_runas_user(handle, rule) != false && |
ret = sudo_sss_check_runas_user(handle, rule) != false && |
| sudo_sss_check_runas_group(handle, rule) != false; |
sudo_sss_check_runas_group(handle, rule) != false; |
| |
|
| debug_return_int(ret); | debug_return_bool(ret); |
| } |
} |
| |
|
| static int | static bool |
| sudo_sss_check_host(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) |
sudo_sss_check_host(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) |
| { |
{ |
| char **val_array, *val; |
char **val_array, *val; |
| int ret = false, i; | bool ret = false; |
| | int i; |
| debug_decl(sudo_sss_check_host, SUDO_DEBUG_SSSD); |
debug_decl(sudo_sss_check_host, SUDO_DEBUG_SSSD); |
| |
|
| if (rule == NULL) |
if (rule == NULL) |
| debug_return_int(ret); | debug_return_bool(ret); |
| |
|
| /* get the values from the rule */ |
/* get the values from the rule */ |
| switch (handle->fn_get_values(rule, "sudoHost", &val_array)) |
switch (handle->fn_get_values(rule, "sudoHost", &val_array)) |
|
Line 561 sudo_sss_check_host(struct sudo_sss_handle *handle, st
|
Line 565 sudo_sss_check_host(struct sudo_sss_handle *handle, st
|
| break; |
break; |
| case ENOENT: |
case ENOENT: |
| sudo_debug_printf(SUDO_DEBUG_INFO, "No result."); |
sudo_debug_printf(SUDO_DEBUG_INFO, "No result."); |
| debug_return_int(false); | debug_return_bool(false); |
| default: |
default: |
| sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoHost): != 0"); |
sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoHost): != 0"); |
| debug_return_int(ret); | debug_return_bool(ret); |
| } |
} |
| |
|
| /* walk through values */ |
/* walk through values */ |
|
Line 584 sudo_sss_check_host(struct sudo_sss_handle *handle, st
|
Line 588 sudo_sss_check_host(struct sudo_sss_handle *handle, st
|
| |
|
| handle->fn_free_values(val_array); |
handle->fn_free_values(val_array); |
| |
|
| debug_return_int(ret); | debug_return_bool(ret); |
| } |
} |
| |
|
| |
/* |
| |
* Look for netgroup specifcations in the sudoUser attribute and |
| |
* if found, filter according to netgroup membership. |
| |
* returns: |
| |
* true -> netgroup spec found && netgroup member |
| |
* false -> netgroup spec found && not a member of netgroup |
| |
* true -> netgroup spec not found (filtered by SSSD already, netgroups are an exception) |
| |
*/ |
| |
static bool |
| |
sudo_sss_filter_user_netgroup(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) |
| |
{ |
| |
bool ret = false, netgroup_spec_found = false; |
| |
char **val_array, *val; |
| |
int i; |
| |
debug_decl(sudo_sss_filter_user_netgroup, SUDO_DEBUG_SSSD); |
| |
|
| |
if (!handle || !rule) |
| |
debug_return_bool(ret); |
| |
|
| |
switch (handle->fn_get_values(rule, "sudoUser", &val_array)) { |
| |
case 0: |
| |
break; |
| |
case ENOENT: |
| |
sudo_debug_printf(SUDO_DEBUG_INFO, "No result."); |
| |
debug_return_bool(ret); |
| |
default: |
| |
sudo_debug_printf(SUDO_DEBUG_INFO, |
| |
"handle->fn_get_values(sudoUser): != 0"); |
| |
debug_return_bool(ret); |
| |
} |
| |
|
| |
for (i = 0; val_array[i] != NULL && !ret; ++i) { |
| |
val = val_array[i]; |
| |
if (*val == '+') { |
| |
netgroup_spec_found = true; |
| |
} |
| |
sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val); |
| |
if (strcmp(val, "ALL") == 0 || netgr_matches(val, NULL, NULL, handle->pw->pw_name)) { |
| |
ret = true; |
| |
sudo_debug_printf(SUDO_DEBUG_DIAG, |
| |
"sssd/ldap sudoUser '%s' ... MATCH! (%s)", |
| |
val, handle->pw->pw_name); |
| |
break; |
| |
} |
| |
} |
| |
handle->fn_free_values(val_array); |
| |
debug_return_bool(netgroup_spec_found ? ret : true); |
| |
} |
| |
|
| static int |
static int |
| sudo_sss_result_filterp(struct sudo_sss_handle *handle, |
sudo_sss_result_filterp(struct sudo_sss_handle *handle, |
| struct sss_sudo_rule *rule, void *unused) |
struct sss_sudo_rule *rule, void *unused) |
|
Line 594 sudo_sss_result_filterp(struct sudo_sss_handle *handle
|
Line 647 sudo_sss_result_filterp(struct sudo_sss_handle *handle
|
| (void)unused; |
(void)unused; |
| debug_decl(sudo_sss_result_filterp, SUDO_DEBUG_SSSD); |
debug_decl(sudo_sss_result_filterp, SUDO_DEBUG_SSSD); |
| |
|
| if (sudo_sss_check_host(handle, rule)) | if (sudo_sss_check_host(handle, rule) && |
| | sudo_sss_filter_user_netgroup(handle, rule)) |
| debug_return_int(1); |
debug_return_int(1); |
| else |
else |
| debug_return_int(0); |
debug_return_int(0); |
|
Line 612 sudo_sss_result_get(struct sudo_nss *nss, struct passw
|
Line 666 sudo_sss_result_get(struct sudo_nss *nss, struct passw
|
| debug_return_ptr(NULL); |
debug_return_ptr(NULL); |
| |
|
| sudo_debug_printf(SUDO_DEBUG_DIAG, " username=%s", handle->pw->pw_name); |
sudo_debug_printf(SUDO_DEBUG_DIAG, " username=%s", handle->pw->pw_name); |
| sudo_debug_printf(SUDO_DEBUG_DIAG, "domainname=%s", handle->domainname); | sudo_debug_printf(SUDO_DEBUG_DIAG, "domainname=%s", |
| | handle->domainname ? handle->domainname : "NULL"); |
| |
|
| u_sss_result = f_sss_result = NULL; |
u_sss_result = f_sss_result = NULL; |
| |
|
|
Line 659 sudo_sss_result_get(struct sudo_nss *nss, struct passw
|
Line 714 sudo_sss_result_get(struct sudo_nss *nss, struct passw
|
| *state |= _SUDO_SSS_STATE_HOSTMATCH; |
*state |= _SUDO_SSS_STATE_HOSTMATCH; |
| } |
} |
| } |
} |
| |
sudo_debug_printf(SUDO_DEBUG_DEBUG, |
| |
"u_sss_result=(%p, %u) => f_sss_result=(%p, %u)", u_sss_result, |
| |
u_sss_result->num_rules, f_sss_result, f_sss_result->num_rules); |
| |
} else { |
| |
sudo_debug_printf(SUDO_DEBUG_DEBUG, |
| |
"u_sss_result=(%p, %u) => f_sss_result=NULL", u_sss_result, |
| |
u_sss_result->num_rules); |
| } |
} |
| |
|
| sudo_debug_printf(SUDO_DEBUG_DEBUG, |
|
| "u_sss_result=(%p, %u) => f_sss_result=(%p, %u)", u_sss_result, |
|
| u_sss_result->num_rules, f_sss_result, f_sss_result->num_rules); |
|
| |
|
| handle->fn_free_result(u_sss_result); |
handle->fn_free_result(u_sss_result); |
| |
|
| debug_return_ptr(f_sss_result); |
debug_return_ptr(f_sss_result); |
|
Line 713 sudo_sss_check_bool(struct sudo_sss_handle *handle, st
|
Line 771 sudo_sss_check_bool(struct sudo_sss_handle *handle, st
|
| } |
} |
| |
|
| /* |
/* |
| |
* If a digest prefix is present, fills in struct sudo_digest |
| |
* and returns a pointer to it, updating cmnd to point to the |
| |
* command after the digest. |
| |
*/ |
| |
static struct sudo_digest * |
| |
sudo_sss_extract_digest(char **cmnd, struct sudo_digest *digest) |
| |
{ |
| |
char *ep, *cp = *cmnd; |
| |
int digest_type = SUDO_DIGEST_INVALID; |
| |
debug_decl(sudo_sss_check_command, SUDO_DEBUG_LDAP) |
| |
|
| |
/* |
| |
* Check for and extract a digest prefix, e.g. |
| |
* sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1 /bin/ls |
| |
*/ |
| |
if (cp[0] == 's' && cp[1] == 'h' && cp[2] == 'a') { |
| |
switch (cp[3]) { |
| |
case '2': |
| |
if (cp[4] == '2' && cp[5] == '4') |
| |
digest_type = SUDO_DIGEST_SHA224; |
| |
else if (cp[4] == '5' && cp[5] == '6') |
| |
digest_type = SUDO_DIGEST_SHA256; |
| |
break; |
| |
case '3': |
| |
if (cp[4] == '8' && cp[5] == '4') |
| |
digest_type = SUDO_DIGEST_SHA384; |
| |
break; |
| |
case '5': |
| |
if (cp[4] == '1' && cp[5] == '2') |
| |
digest_type = SUDO_DIGEST_SHA512; |
| |
break; |
| |
} |
| |
if (digest_type != SUDO_DIGEST_INVALID) { |
| |
cp += 6; |
| |
while (isblank((unsigned char)*cp)) |
| |
cp++; |
| |
if (*cp == ':') { |
| |
cp++; |
| |
while (isblank((unsigned char)*cp)) |
| |
cp++; |
| |
ep = cp; |
| |
while (*ep != '\0' && !isblank((unsigned char)*ep)) |
| |
ep++; |
| |
if (*ep != '\0') { |
| |
digest->digest_type = digest_type; |
| |
digest->digest_str = estrndup(cp, (size_t)(ep - cp)); |
| |
cp = ep + 1; |
| |
while (isblank((unsigned char)*cp)) |
| |
cp++; |
| |
*cmnd = cp; |
| |
sudo_debug_printf(SUDO_DEBUG_INFO, |
| |
"%s digest %s for %s", |
| |
digest_type == SUDO_DIGEST_SHA224 ? "sha224" : |
| |
digest_type == SUDO_DIGEST_SHA256 ? "sha256" : |
| |
digest_type == SUDO_DIGEST_SHA384 ? "sha384" : |
| |
"sha512", digest->digest_str, cp); |
| |
debug_return_ptr(digest); |
| |
} |
| |
} |
| |
} |
| |
} |
| |
debug_return_ptr(NULL); |
| |
} |
| |
|
| |
/* |
| * Walk through search results and return true if we have a command match, |
* Walk through search results and return true if we have a command match, |
| * false if disallowed and UNSPEC if not matched. |
* false if disallowed and UNSPEC if not matched. |
| */ |
*/ |
|
Line 723 sudo_sss_check_command(struct sudo_sss_handle *handle,
|
Line 846 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 i, foundbang, ret = UNSPEC; |
int i, foundbang, ret = UNSPEC; |
| |
struct sudo_digest digest, *allowed_digest = NULL; |
| debug_decl(sudo_sss_check_command, SUDO_DEBUG_SSSD); |
debug_decl(sudo_sss_check_command, SUDO_DEBUG_SSSD); |
| |
|
| if (rule == NULL) |
if (rule == NULL) |
|
Line 754 sudo_sss_check_command(struct sudo_sss_handle *handle,
|
Line 878 sudo_sss_check_command(struct sudo_sss_handle *handle,
|
| continue; |
continue; |
| } |
} |
| |
|
| |
/* check for sha-2 digest */ |
| |
allowed_digest = sudo_sss_extract_digest(&val, &digest); |
| |
|
| /* check for !command */ |
/* check for !command */ |
| if (*val == '!') { |
if (*val == '!') { |
| foundbang = true; |
foundbang = true; |
|
Line 769 sudo_sss_check_command(struct sudo_sss_handle *handle,
|
Line 896 sudo_sss_check_command(struct sudo_sss_handle *handle,
|
| *allowed_args++ = '\0'; |
*allowed_args++ = '\0'; |
| |
|
| /* check the command like normal */ |
/* check the command like normal */ |
| if (command_matches(allowed_cmnd, allowed_args)) { | if (command_matches(allowed_cmnd, allowed_args, NULL)) { |
| /* |
/* |
| * 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. |