Allow a list of digests to be specified for a command.
This commit is contained in:
@@ -887,6 +887,9 @@ Digest_Spec ::= "sha224" ':' digest |
|
||||
"sha384" ':' digest |
|
||||
"sha512" ':' digest
|
||||
|
||||
Digest_List ::= Digest_Spec |
|
||||
Digest_Spec ',' Digest_List
|
||||
|
||||
Cmnd_List ::= Cmnd |
|
||||
Cmnd ',' Cmnd_List
|
||||
|
||||
@@ -894,7 +897,7 @@ command name ::= file name |
|
||||
file name args |
|
||||
file name '""'
|
||||
|
||||
Cmnd ::= Digest_Spec? '!'* command name |
|
||||
Cmnd ::= Digest_List? '!'* command name |
|
||||
'!'* directory |
|
||||
'!'* "sudoedit" |
|
||||
'!'* Cmnd_Alias
|
||||
@@ -967,12 +970,17 @@ A fully-qualified path for
|
||||
is treated as an error by
|
||||
\fBvisudo\fR.
|
||||
.PP
|
||||
If a
|
||||
A
|
||||
\fRcommand name\fR
|
||||
is prefixed with a
|
||||
\fRDigest_Spec\fR,
|
||||
the command will only match successfully if it can be verified
|
||||
using the specified SHA-2 digest.
|
||||
may be preceded by a
|
||||
\fRDigest_List\fR,
|
||||
a comma-separated list of one or more
|
||||
\fRDigest_Spec\fR
|
||||
entries.
|
||||
If a
|
||||
\fRDigest_List\fR
|
||||
is present, the command will only match successfully if it can be verified
|
||||
using one of the SHA-2 digests in the list.
|
||||
The following digest formats are supported: sha224, sha256, sha384 and sha512.
|
||||
The string may be specified in either hex or base64 format
|
||||
(base64 is more compact).
|
||||
|
@@ -852,6 +852,9 @@ Digest_Spec ::= "sha224" ':' digest |
|
||||
"sha384" ':' digest |
|
||||
"sha512" ':' digest
|
||||
|
||||
Digest_List ::= Digest_Spec |
|
||||
Digest_Spec ',' Digest_List
|
||||
|
||||
Cmnd_List ::= Cmnd |
|
||||
Cmnd ',' Cmnd_List
|
||||
|
||||
@@ -859,7 +862,7 @@ command name ::= file name |
|
||||
file name args |
|
||||
file name '""'
|
||||
|
||||
Cmnd ::= Digest_Spec? '!'* command name |
|
||||
Cmnd ::= Digest_List? '!'* command name |
|
||||
'!'* directory |
|
||||
'!'* "sudoedit" |
|
||||
'!'* Cmnd_Alias
|
||||
@@ -931,12 +934,17 @@ A fully-qualified path for
|
||||
is treated as an error by
|
||||
.Nm visudo .
|
||||
.Pp
|
||||
If a
|
||||
A
|
||||
.Li command name
|
||||
is prefixed with a
|
||||
.Li Digest_Spec ,
|
||||
the command will only match successfully if it can be verified
|
||||
using the specified SHA-2 digest.
|
||||
may be preceded by a
|
||||
.Li Digest_List ,
|
||||
a comma-separated list of one or more
|
||||
.Li Digest_Spec
|
||||
entries.
|
||||
If a
|
||||
.Li Digest_List
|
||||
is present, the command will only match successfully if it can be verified
|
||||
using one of the SHA-2 digests in the list.
|
||||
The following digest formats are supported: sha224, sha256, sha384 and sha512.
|
||||
The string may be specified in either hex or base64 format
|
||||
(base64 is more compact).
|
||||
|
@@ -70,6 +70,7 @@ static void
|
||||
print_command_json(struct json_container *json, const char *name, bool negated)
|
||||
{
|
||||
struct sudo_command *c = (struct sudo_command *)name;
|
||||
struct command_digest *digest;
|
||||
struct json_value value;
|
||||
char *cmnd = c->cmnd;
|
||||
const char *digest_name;
|
||||
@@ -85,7 +86,7 @@ print_command_json(struct json_container *json, const char *name, bool negated)
|
||||
value.type = JSON_STRING;
|
||||
value.u.string = cmnd;
|
||||
|
||||
if (!negated && c->digest == NULL) {
|
||||
if (!negated && TAILQ_EMPTY(&c->digests)) {
|
||||
/* Print as { "command": "command and args" } */
|
||||
sudo_json_add_value_as_object(json, "command", &value);
|
||||
} else {
|
||||
@@ -93,11 +94,11 @@ print_command_json(struct json_container *json, const char *name, bool negated)
|
||||
sudo_json_open_object(json, NULL);
|
||||
sudo_json_add_value(json, "command", &value);
|
||||
|
||||
/* Optional digest. */
|
||||
if (c->digest != NULL) {
|
||||
digest_name = digest_type_to_name(c->digest->digest_type);
|
||||
/* Optional digest list. */
|
||||
TAILQ_FOREACH(digest, &c->digests, entries) {
|
||||
digest_name = digest_type_to_name(digest->digest_type);
|
||||
value.type = JSON_STRING;
|
||||
value.u.string = c->digest->digest_str;
|
||||
value.u.string = digest->digest_str;
|
||||
sudo_json_add_value(json, digest_name, &value);
|
||||
}
|
||||
|
||||
|
@@ -209,6 +209,52 @@ print_global_defaults_ldif(FILE *fp, struct sudoers_parse_tree *parse_tree,
|
||||
debug_return_bool(!ferror(fp));
|
||||
}
|
||||
|
||||
/*
|
||||
* Format a sudo_command as a string.
|
||||
* Returns the formatted, dynamically allocated string or dies on error.
|
||||
*/
|
||||
static char *
|
||||
format_cmnd(struct sudo_command *c, bool negated)
|
||||
{
|
||||
struct command_digest *digest;
|
||||
char *buf, *cp;
|
||||
size_t bufsiz;
|
||||
int len;
|
||||
debug_decl(format_cmnd, SUDOERS_DEBUG_UTIL);
|
||||
|
||||
bufsiz = negated + strlen(c->cmnd) + 1;
|
||||
if (c->args != NULL)
|
||||
bufsiz += 1 + strlen(c->args);
|
||||
TAILQ_FOREACH(digest, &c->digests, entries) {
|
||||
bufsiz += strlen(digest_type_to_name(digest->digest_type)) + 1 +
|
||||
strlen(digest->digest_str) + 1;
|
||||
if (TAILQ_NEXT(digest, entries) != NULL)
|
||||
bufsiz += 2;
|
||||
}
|
||||
|
||||
if ((buf = malloc(bufsiz)) == NULL) {
|
||||
sudo_fatalx(U_("%s: %s"), __func__,
|
||||
U_("unable to allocate memory"));
|
||||
}
|
||||
|
||||
cp = buf;
|
||||
TAILQ_FOREACH(digest, &c->digests, entries) {
|
||||
len = snprintf(cp, bufsiz - (cp - buf), "%s:%s%s ",
|
||||
digest_type_to_name(digest->digest_type), digest->digest_str,
|
||||
TAILQ_NEXT(digest, entries) ? "," : "");
|
||||
if (len < 0 || len >= (int)bufsiz - (cp - buf))
|
||||
sudo_fatalx(U_("internal error, %s overflow"), __func__);
|
||||
cp += len;
|
||||
}
|
||||
|
||||
len = snprintf(cp, bufsiz - (cp - buf), "%s%s%s%s", negated ? "!" : "",
|
||||
c->cmnd, c->args ? " " : "", c->args ? c->args : "");
|
||||
if (len < 0 || len >= (int)bufsiz - (cp - buf))
|
||||
sudo_fatalx(U_("internal error, %s overflow"), __func__);
|
||||
|
||||
debug_return_str(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print struct member in LDIF format as the specified attribute.
|
||||
* See print_member_int() in parse.c.
|
||||
@@ -219,7 +265,6 @@ print_member_ldif(FILE *fp, struct sudoers_parse_tree *parse_tree, char *name,
|
||||
{
|
||||
struct alias *a;
|
||||
struct member *m;
|
||||
struct sudo_command *c;
|
||||
char *attr_val;
|
||||
int len;
|
||||
debug_decl(print_member_ldif, SUDOERS_DEBUG_UTIL);
|
||||
@@ -233,16 +278,7 @@ print_member_ldif(FILE *fp, struct sudoers_parse_tree *parse_tree, char *name,
|
||||
print_attribute_ldif(fp, attr_name, "");
|
||||
break;
|
||||
case COMMAND:
|
||||
c = (struct sudo_command *)name;
|
||||
len = asprintf(&attr_val, "%s%s%s%s%s%s%s%s",
|
||||
c->digest ? digest_type_to_name(c->digest->digest_type) : "",
|
||||
c->digest ? ":" : "", c->digest ? c->digest->digest_str : "",
|
||||
c->digest ? " " : "", negated ? "!" : "", c->cmnd,
|
||||
c->args ? " " : "", c->args ? c->args : "");
|
||||
if (len == -1) {
|
||||
sudo_fatalx(U_("%s: %s"), __func__,
|
||||
U_("unable to allocate memory"));
|
||||
}
|
||||
attr_val = format_cmnd((struct sudo_command *)name, negated);
|
||||
print_attribute_ldif(fp, attr_name, attr_val);
|
||||
free(attr_val);
|
||||
break;
|
||||
|
@@ -51,6 +51,7 @@ sudoers_format_member_int(struct sudo_lbuf *lbuf,
|
||||
struct alias *a;
|
||||
struct member *m;
|
||||
struct sudo_command *c;
|
||||
struct command_digest *digest;
|
||||
debug_decl(sudoers_format_member_int, SUDOERS_DEBUG_UTIL);
|
||||
|
||||
switch (type) {
|
||||
@@ -63,10 +64,10 @@ sudoers_format_member_int(struct sudo_lbuf *lbuf,
|
||||
break;
|
||||
case COMMAND:
|
||||
c = (struct sudo_command *) name;
|
||||
if (c->digest != NULL) {
|
||||
sudo_lbuf_append(lbuf, "%s:%s ",
|
||||
digest_type_to_name(c->digest->digest_type),
|
||||
c->digest->digest_str);
|
||||
TAILQ_FOREACH(digest, &c->digests, entries) {
|
||||
sudo_lbuf_append(lbuf, "%s:%s%s ",
|
||||
digest_type_to_name(digest->digest_type),
|
||||
digest->digest_str, TAILQ_NEXT(digest, entries) ? "," : "");
|
||||
}
|
||||
if (negated)
|
||||
sudo_lbuf_append(lbuf, "!");
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 1996, 1998-2005, 2007-2013, 2014-2018
|
||||
* Copyright (c) 1996, 1998-2005, 2007-2013, 2014-2020
|
||||
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@@ -174,7 +174,8 @@ static struct command_digest *new_digest(int, char *);
|
||||
%type <string> timeoutspec
|
||||
%type <string> notbeforespec
|
||||
%type <string> notafterspec
|
||||
%type <digest> digest
|
||||
%type <digest> digestspec
|
||||
%type <digest> digestlist
|
||||
|
||||
%%
|
||||
|
||||
@@ -451,7 +452,7 @@ cmndspec : runasspec options cmndtag digcmnd {
|
||||
}
|
||||
;
|
||||
|
||||
digest : SHA224_TOK ':' DIGEST {
|
||||
digestspec : SHA224_TOK ':' DIGEST {
|
||||
$$ = new_digest(SUDO_DIGEST_SHA224, $3);
|
||||
if ($$ == NULL) {
|
||||
sudoerserror(N_("unable to allocate memory"));
|
||||
@@ -481,16 +482,25 @@ digest : SHA224_TOK ':' DIGEST {
|
||||
}
|
||||
;
|
||||
|
||||
digestlist : digestspec
|
||||
| digestlist ',' digestspec {
|
||||
HLTQ_CONCAT($1, $3, entries);
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
digcmnd : opcmnd {
|
||||
$$ = $1;
|
||||
}
|
||||
| digest opcmnd {
|
||||
| digestlist opcmnd {
|
||||
struct sudo_command *c =
|
||||
(struct sudo_command *) $2->name;
|
||||
|
||||
if ($2->type != COMMAND) {
|
||||
sudoerserror(N_("a digest requires a path name"));
|
||||
YYERROR;
|
||||
}
|
||||
/* XXX - yuck */
|
||||
((struct sudo_command *) $2->name)->digest = $1;
|
||||
HLTQ_TO_TAILQ(&c->digests, $1, entries);
|
||||
$$ = $2;
|
||||
}
|
||||
;
|
||||
@@ -730,6 +740,7 @@ cmnd : ALL {
|
||||
}
|
||||
c->cmnd = $1.cmnd;
|
||||
c->args = $1.args;
|
||||
TAILQ_INIT(&c->digests);
|
||||
$$ = new_member((char *)c, COMMAND);
|
||||
if ($$ == NULL) {
|
||||
free(c);
|
||||
@@ -992,6 +1003,7 @@ new_digest(int digest_type, char *digest_str)
|
||||
debug_return_ptr(NULL);
|
||||
}
|
||||
|
||||
HLTQ_INIT(digest, entries);
|
||||
digest->digest_type = digest_type;
|
||||
digest->digest_str = digest_str;
|
||||
if (digest->digest_str == NULL) {
|
||||
@@ -1080,13 +1092,15 @@ free_member(struct member *m)
|
||||
debug_decl(free_member, SUDOERS_DEBUG_PARSER);
|
||||
|
||||
if (m->type == COMMAND) {
|
||||
struct sudo_command *c = (struct sudo_command *)m->name;
|
||||
free(c->cmnd);
|
||||
free(c->args);
|
||||
if (c->digest != NULL) {
|
||||
free(c->digest->digest_str);
|
||||
free(c->digest);
|
||||
}
|
||||
struct command_digest *digest;
|
||||
struct sudo_command *c = (struct sudo_command *)m->name;
|
||||
free(c->cmnd);
|
||||
free(c->args);
|
||||
while ((digest = TAILQ_FIRST(&c->digests)) != NULL) {
|
||||
TAILQ_REMOVE(&c->digests, digest, entries);
|
||||
free(digest->digest_str);
|
||||
free(digest);
|
||||
}
|
||||
}
|
||||
free(m->name);
|
||||
free(m);
|
||||
|
@@ -288,6 +288,110 @@ oom:
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* If a digest prefix is present, add it to struct command_digest_list
|
||||
* and update cmnd to point to the command after the digest.
|
||||
* Returns 1 if a digest was parsed, 0 if not and -1 on error.
|
||||
*/
|
||||
static int
|
||||
sudo_ldap_extract_digest(char **cmnd, struct command_digest_list *digests)
|
||||
{
|
||||
char *ep, *cp = *cmnd;
|
||||
struct command_digest *digest;
|
||||
int digest_type = SUDO_DIGEST_INVALID;
|
||||
debug_decl(sudo_ldap_extract_digest, SUDOERS_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 != ',')
|
||||
ep++;
|
||||
if (isblank((unsigned char)*ep) || *ep == ',') {
|
||||
if ((digest = malloc(sizeof(*digest))) == NULL) {
|
||||
sudo_warnx(U_("%s: %s"), __func__,
|
||||
U_("unable to allocate memory"));
|
||||
debug_return_int(-1);
|
||||
}
|
||||
digest->digest_type = digest_type;
|
||||
digest->digest_str = strndup(cp, (size_t)(ep - cp));
|
||||
if (digest->digest_str == NULL) {
|
||||
sudo_warnx(U_("%s: %s"), __func__,
|
||||
U_("unable to allocate memory"));
|
||||
free(digest);
|
||||
debug_return_int(-1);
|
||||
}
|
||||
while (isblank((unsigned char)*ep))
|
||||
ep++;
|
||||
*cmnd = ep;
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO,
|
||||
"%s digest %s for %s",
|
||||
digest_type_to_name(digest_type),
|
||||
digest->digest_str, cp);
|
||||
TAILQ_INSERT_TAIL(digests, digest, entries);
|
||||
debug_return_int(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
debug_return_int(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If a digest list is present, fill in struct command_digest_list
|
||||
* and update cmnd to point to the command after the digest.
|
||||
* Returns false on error, else true.
|
||||
*/
|
||||
static bool
|
||||
sudo_ldap_extract_digests(char **cmnd, struct command_digest_list *digests)
|
||||
{
|
||||
char *cp = *cmnd;
|
||||
int rc;
|
||||
debug_decl(sudo_ldap_extract_digests, SUDOERS_DEBUG_LDAP);
|
||||
|
||||
for (;;) {
|
||||
rc = sudo_ldap_extract_digest(&cp, digests);
|
||||
if (rc != 1)
|
||||
break;
|
||||
|
||||
/* Check for additional digestspecs, separated by a comma. */
|
||||
if (*cp != ',')
|
||||
break;
|
||||
do {
|
||||
cp++;
|
||||
} while (isblank((unsigned char)*cp));
|
||||
}
|
||||
*cmnd = cp;
|
||||
|
||||
debug_return_bool(rc != -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an LDAP sudoRole to a sudoers privilege.
|
||||
* Pass in struct berval ** for LDAP or char *** for SSSD.
|
||||
@@ -358,6 +462,7 @@ sudo_ldap_role_to_priv(const char *cn, void *hosts, void *runasusers,
|
||||
goto oom;
|
||||
}
|
||||
m->name = (char *)c;
|
||||
TAILQ_INIT(&c->digests);
|
||||
}
|
||||
|
||||
/* Negated commands have precedence so insert them at the end. */
|
||||
@@ -481,17 +586,13 @@ sudo_ldap_role_to_priv(const char *cn, void *hosts, void *runasusers,
|
||||
if (cmndspec->tags.setenv == UNSPEC)
|
||||
cmndspec->tags.setenv = IMPLIED;
|
||||
} else {
|
||||
struct command_digest digest;
|
||||
char *args;
|
||||
|
||||
m->type = COMMAND;
|
||||
|
||||
/* Fill in command with optional digest. */
|
||||
if (sudo_ldap_extract_digest(&cmnd, &digest) != NULL) {
|
||||
if ((c->digest = malloc(sizeof(*c->digest))) == NULL)
|
||||
goto oom;
|
||||
*c->digest = digest;
|
||||
}
|
||||
/* Fill in command with optional digests. */
|
||||
if (!sudo_ldap_extract_digests(&cmnd, &c->digests))
|
||||
goto oom;
|
||||
if ((args = strpbrk(cmnd, " \t")) != NULL) {
|
||||
*args++ = '\0';
|
||||
if ((c->args = strdup(args)) == NULL)
|
||||
@@ -515,70 +616,3 @@ oom:
|
||||
}
|
||||
debug_return_ptr(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* If a digest prefix is present, fills in struct command_digest
|
||||
* and returns a pointer to it, updating cmnd to point to the
|
||||
* command after the digest.
|
||||
*/
|
||||
struct command_digest *
|
||||
sudo_ldap_extract_digest(char **cmnd, struct command_digest *digest)
|
||||
{
|
||||
char *ep, *cp = *cmnd;
|
||||
int digest_type = SUDO_DIGEST_INVALID;
|
||||
debug_decl(sudo_ldap_check_command, SUDOERS_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 = strndup(cp, (size_t)(ep - cp));
|
||||
if (digest->digest_str == NULL) {
|
||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||
debug_return_ptr(NULL);
|
||||
}
|
||||
cp = ep + 1;
|
||||
while (isblank((unsigned char)*cp))
|
||||
cp++;
|
||||
*cmnd = cp;
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO,
|
||||
"%s digest %s for %s",
|
||||
digest_type_to_name(digest_type),
|
||||
digest->digest_str, cp);
|
||||
debug_return_ptr(digest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
debug_return_ptr(NULL);
|
||||
}
|
||||
|
@@ -411,7 +411,7 @@ cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m)
|
||||
break;
|
||||
case COMMAND:
|
||||
c = (struct sudo_command *)m->name;
|
||||
if (command_matches(c->cmnd, c->args, c->digest))
|
||||
if (command_matches(c->cmnd, c->args, &c->digests))
|
||||
matched = !m->negated;
|
||||
break;
|
||||
}
|
||||
|
@@ -126,18 +126,18 @@ is_script(int fd)
|
||||
* Returns false on error, else true.
|
||||
*/
|
||||
static bool
|
||||
open_cmnd(const char *path, const struct command_digest *digest, int *fdp)
|
||||
open_cmnd(const char *path, const struct command_digest_list *digests, int *fdp)
|
||||
{
|
||||
int fd = -1;
|
||||
debug_decl(open_cmnd, SUDOERS_DEBUG_MATCH);
|
||||
|
||||
/* Only open the file for fdexec or for digest matching. */
|
||||
if (def_fdexec != always && digest == NULL)
|
||||
if (def_fdexec != always && TAILQ_EMPTY(digests))
|
||||
debug_return_bool(true);
|
||||
|
||||
fd = open(path, O_RDONLY|O_NONBLOCK);
|
||||
# ifdef O_EXEC
|
||||
if (fd == -1 && errno == EACCES && digest == NULL) {
|
||||
if (fd == -1 && errno == EACCES && TAILQ_EMPTY(digests))
|
||||
/* Try again with O_EXEC if no digest is specified. */
|
||||
const int saved_errno = errno;
|
||||
if ((fd = open(path, O_EXEC)) == -1)
|
||||
@@ -197,7 +197,7 @@ set_cmnd_fd(int fd)
|
||||
*/
|
||||
static bool
|
||||
command_matches_dir(const char *sudoers_dir, size_t dlen,
|
||||
const struct command_digest *digest)
|
||||
const struct command_digest_list *digests)
|
||||
{
|
||||
struct stat sudoers_stat;
|
||||
struct dirent *dent;
|
||||
@@ -233,7 +233,7 @@ command_matches_dir(const char *sudoers_dir, size_t dlen,
|
||||
continue;
|
||||
|
||||
/* Open the file for fdexec or for digest matching. */
|
||||
if (!open_cmnd(buf, digest, &fd))
|
||||
if (!open_cmnd(buf, digests, &fd))
|
||||
continue;
|
||||
if (!do_stat(fd, buf, &sudoers_stat))
|
||||
continue;
|
||||
@@ -241,7 +241,7 @@ command_matches_dir(const char *sudoers_dir, size_t dlen,
|
||||
if (user_stat == NULL ||
|
||||
(user_stat->st_dev == sudoers_stat.st_dev &&
|
||||
user_stat->st_ino == sudoers_stat.st_ino)) {
|
||||
if (digest != NULL && !digest_matches(fd, buf, digest))
|
||||
if (!digest_matches(fd, buf, digests))
|
||||
continue;
|
||||
free(safe_cmnd);
|
||||
if ((safe_cmnd = strdup(buf)) == NULL) {
|
||||
@@ -265,7 +265,7 @@ command_matches_dir(const char *sudoers_dir, size_t dlen,
|
||||
|
||||
static bool
|
||||
command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args,
|
||||
const struct command_digest *digest)
|
||||
const struct command_digest_list *digests)
|
||||
{
|
||||
struct stat sb; /* XXX - unused */
|
||||
int fd = -1;
|
||||
@@ -282,12 +282,12 @@ command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args,
|
||||
debug_return_bool(false);
|
||||
if (command_args_match(sudoers_cmnd, sudoers_args)) {
|
||||
/* Open the file for fdexec or for digest matching. */
|
||||
if (!open_cmnd(user_cmnd, digest, &fd))
|
||||
if (!open_cmnd(user_cmnd, digests, &fd))
|
||||
goto bad;
|
||||
if (!do_stat(fd, user_cmnd, &sb))
|
||||
goto bad;
|
||||
/* Check digest of user_cmnd since sudoers_cmnd is a pattern. */
|
||||
if (digest != NULL && !digest_matches(fd, user_cmnd, digest))
|
||||
if (!digest_matches(fd, user_cmnd, digests))
|
||||
goto bad;
|
||||
set_cmnd_fd(fd);
|
||||
|
||||
@@ -305,7 +305,7 @@ bad:
|
||||
|
||||
static bool
|
||||
command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args,
|
||||
const struct command_digest *digest)
|
||||
const struct command_digest_list *digests)
|
||||
{
|
||||
struct stat sudoers_stat;
|
||||
bool bad_digest = false;
|
||||
@@ -349,7 +349,7 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args,
|
||||
if (strcmp(cp, user_cmnd) != 0)
|
||||
continue;
|
||||
/* Open the file for fdexec or for digest matching. */
|
||||
if (!open_cmnd(cp, digest, &fd))
|
||||
if (!open_cmnd(cp, digests, &fd))
|
||||
continue;
|
||||
if (!do_stat(fd, cp, &sudoers_stat))
|
||||
continue;
|
||||
@@ -357,7 +357,7 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args,
|
||||
(user_stat->st_dev == sudoers_stat.st_dev &&
|
||||
user_stat->st_ino == sudoers_stat.st_ino)) {
|
||||
/* There could be multiple matches, check digest early. */
|
||||
if (digest != NULL && !digest_matches(fd, cp, digest)) {
|
||||
if (!digest_matches(fd, cp, digests)) {
|
||||
bad_digest = true;
|
||||
continue;
|
||||
}
|
||||
@@ -385,7 +385,7 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args,
|
||||
/* If it ends in '/' it is a directory spec. */
|
||||
dlen = strlen(cp);
|
||||
if (cp[dlen - 1] == '/') {
|
||||
if (command_matches_dir(cp, dlen, digest))
|
||||
if (command_matches_dir(cp, dlen, digests))
|
||||
debug_return_bool(true);
|
||||
continue;
|
||||
}
|
||||
@@ -399,14 +399,14 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args,
|
||||
continue;
|
||||
|
||||
/* Open the file for fdexec or for digest matching. */
|
||||
if (!open_cmnd(cp, digest, &fd))
|
||||
if (!open_cmnd(cp, digests, &fd))
|
||||
continue;
|
||||
if (!do_stat(fd, cp, &sudoers_stat))
|
||||
continue;
|
||||
if (user_stat == NULL ||
|
||||
(user_stat->st_dev == sudoers_stat.st_dev &&
|
||||
user_stat->st_ino == sudoers_stat.st_ino)) {
|
||||
if (digest != NULL && !digest_matches(fd, cp, digest))
|
||||
if (!digest_matches(fd, cp, digests))
|
||||
continue;
|
||||
free(safe_cmnd);
|
||||
if ((safe_cmnd = strdup(cp)) == NULL) {
|
||||
@@ -433,7 +433,7 @@ done:
|
||||
}
|
||||
|
||||
static bool
|
||||
command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const struct command_digest *digest)
|
||||
command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const struct command_digest_list *digests)
|
||||
{
|
||||
struct stat sudoers_stat;
|
||||
const char *base;
|
||||
@@ -444,7 +444,7 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const
|
||||
/* If it ends in '/' it is a directory spec. */
|
||||
dlen = strlen(sudoers_cmnd);
|
||||
if (sudoers_cmnd[dlen - 1] == '/')
|
||||
debug_return_bool(command_matches_dir(sudoers_cmnd, dlen, digest));
|
||||
debug_return_bool(command_matches_dir(sudoers_cmnd, dlen, digests));
|
||||
|
||||
/* Only proceed if user_base and basename(sudoers_cmnd) match */
|
||||
if ((base = strrchr(sudoers_cmnd, '/')) == NULL)
|
||||
@@ -455,7 +455,7 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const
|
||||
debug_return_bool(false);
|
||||
|
||||
/* Open the file for fdexec or for digest matching. */
|
||||
if (!open_cmnd(sudoers_cmnd, digest, &fd))
|
||||
if (!open_cmnd(sudoers_cmnd, digests, &fd))
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
@@ -476,7 +476,7 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const
|
||||
}
|
||||
if (!command_args_match(sudoers_cmnd, sudoers_args))
|
||||
goto bad;
|
||||
if (digest != NULL && !digest_matches(fd, sudoers_cmnd, digest)) {
|
||||
if (!digest_matches(fd, sudoers_cmnd, digests)) {
|
||||
/* XXX - log functions not available but we should log very loudly */
|
||||
goto bad;
|
||||
}
|
||||
@@ -498,7 +498,7 @@ bad:
|
||||
* otherwise, return true if user_cmnd names one of the inodes in path.
|
||||
*/
|
||||
bool
|
||||
command_matches(const char *sudoers_cmnd, const char *sudoers_args, const struct command_digest *digest)
|
||||
command_matches(const char *sudoers_cmnd, const char *sudoers_args, const struct command_digest_list *digests)
|
||||
{
|
||||
bool rc = false;
|
||||
debug_decl(command_matches, SUDOERS_DEBUG_MATCH);
|
||||
@@ -526,11 +526,11 @@ command_matches(const char *sudoers_cmnd, const char *sudoers_args, const struct
|
||||
* use glob(3) and/or fnmatch(3) to do the matching.
|
||||
*/
|
||||
if (def_fast_glob)
|
||||
rc = command_matches_fnmatch(sudoers_cmnd, sudoers_args, digest);
|
||||
rc = command_matches_fnmatch(sudoers_cmnd, sudoers_args, digests);
|
||||
else
|
||||
rc = command_matches_glob(sudoers_cmnd, sudoers_args, digest);
|
||||
rc = command_matches_glob(sudoers_cmnd, sudoers_args, digests);
|
||||
} else {
|
||||
rc = command_matches_normal(sudoers_cmnd, sudoers_args, digest);
|
||||
rc = command_matches_normal(sudoers_cmnd, sudoers_args, digests);
|
||||
}
|
||||
done:
|
||||
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 1996, 1998-2005, 2007-2019
|
||||
* Copyright (c) 1996, 1998-2005, 2007-2020
|
||||
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@@ -41,61 +41,81 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sudoers.h"
|
||||
#include "sudo_digest.h"
|
||||
#include <gram.h>
|
||||
|
||||
bool
|
||||
digest_matches(int fd, const char *file, const struct command_digest *digest)
|
||||
digest_matches(int fd, const char *file, const struct command_digest_list *digests)
|
||||
{
|
||||
unsigned int digest_type = SUDO_DIGEST_INVALID;
|
||||
unsigned char *file_digest = NULL;
|
||||
unsigned char *sudoers_digest = NULL;
|
||||
struct command_digest *digest;
|
||||
bool matched = false;
|
||||
size_t digest_len;
|
||||
debug_decl(digest_matches, SUDOERS_DEBUG_MATCH);
|
||||
|
||||
if (fd == -1)
|
||||
goto done;
|
||||
|
||||
file_digest = sudo_filedigest(fd, file, digest->digest_type, &digest_len);
|
||||
if (lseek(fd, (off_t)0, SEEK_SET) == -1) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
|
||||
"unable to rewind digest fd");
|
||||
if (TAILQ_EMPTY(digests)) {
|
||||
/* No digest, no problem. */
|
||||
debug_return_bool(true);
|
||||
}
|
||||
if (file_digest == NULL) {
|
||||
/* Warning (if any) printed by sudo_filedigest() */
|
||||
|
||||
if (fd == -1) {
|
||||
/* No file, no match. */
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Convert the command digest from ascii to binary. */
|
||||
if ((sudoers_digest = malloc(digest_len)) == NULL) {
|
||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||
goto done;
|
||||
}
|
||||
if (strlen(digest->digest_str) == digest_len * 2) {
|
||||
/* Convert ascii hex to binary. */
|
||||
unsigned int i;
|
||||
for (i = 0; i < digest_len; i++) {
|
||||
const int h = hexchar(&digest->digest_str[i + i]);
|
||||
if (h == -1)
|
||||
TAILQ_FOREACH(digest, digests, entries) {
|
||||
/* Compute file digest if needed. */
|
||||
if (digest->digest_type != digest_type) {
|
||||
free(file_digest);
|
||||
file_digest = sudo_filedigest(fd, file, digest->digest_type,
|
||||
&digest_len);
|
||||
if (lseek(fd, (off_t)0, SEEK_SET) == -1) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
|
||||
"unable to rewind digest fd");
|
||||
}
|
||||
if (file_digest == NULL) {
|
||||
/* Warning (if any) printed by sudo_filedigest() */
|
||||
goto done;
|
||||
}
|
||||
digest_type = digest->digest_type;
|
||||
}
|
||||
|
||||
/* Convert the command digest from ascii to binary. */
|
||||
if ((sudoers_digest = malloc(digest_len)) == NULL) {
|
||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||
goto done;
|
||||
}
|
||||
if (strlen(digest->digest_str) == digest_len * 2) {
|
||||
/* Convert ascii hex to binary. */
|
||||
unsigned int i;
|
||||
for (i = 0; i < digest_len; i++) {
|
||||
const int h = hexchar(&digest->digest_str[i + i]);
|
||||
if (h == -1)
|
||||
goto bad_format;
|
||||
sudoers_digest[i] = (unsigned char)h;
|
||||
}
|
||||
} else {
|
||||
/* Convert base64 to binary. */
|
||||
size_t len = base64_decode(digest->digest_str, sudoers_digest, digest_len);
|
||||
if (len != digest_len) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"incorrect length for digest, expected %zu, got %zu",
|
||||
digest_len, len);
|
||||
goto bad_format;
|
||||
sudoers_digest[i] = (unsigned char)h;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Convert base64 to binary. */
|
||||
size_t len = base64_decode(digest->digest_str, sudoers_digest, digest_len);
|
||||
if (len != digest_len) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"incorrect length for digest, expected %zu, got %zu",
|
||||
digest_len, len);
|
||||
goto bad_format;
|
||||
if (memcmp(file_digest, sudoers_digest, digest_len) == 0) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (memcmp(file_digest, sudoers_digest, digest_len) == 0) {
|
||||
matched = true;
|
||||
} else {
|
||||
sudo_debug_printf(SUDO_DEBUG_DIAG|SUDO_DEBUG_LINENO,
|
||||
"%s digest mismatch for %s, expecting %s",
|
||||
digest_type_to_name(digest->digest_type), file, digest->digest_str);
|
||||
free(sudoers_digest);
|
||||
sudoers_digest = NULL;
|
||||
}
|
||||
goto done;
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 1996, 1998-2000, 2004, 2007-2018
|
||||
* Copyright (c) 1996, 1998-2000, 2004, 2007-2020
|
||||
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@@ -105,20 +105,11 @@
|
||||
(cs1)->runasgrouplist != (cs2)->runasgrouplist)
|
||||
|
||||
struct command_digest {
|
||||
TAILQ_ENTRY(command_digest) entries;
|
||||
unsigned int digest_type;
|
||||
char *digest_str;
|
||||
};
|
||||
|
||||
/*
|
||||
* A command with option args and digest.
|
||||
* XXX - merge into struct member
|
||||
*/
|
||||
struct sudo_command {
|
||||
char *cmnd;
|
||||
char *args;
|
||||
struct command_digest *digest;
|
||||
};
|
||||
|
||||
/*
|
||||
* Tags associated with a command.
|
||||
* Possible values: true, false, IMPLIED, UNSPEC.
|
||||
@@ -164,13 +155,14 @@ struct command_options {
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tail queue list head structure.
|
||||
* Tail queue list head structures.
|
||||
*/
|
||||
TAILQ_HEAD(defaults_list, defaults);
|
||||
TAILQ_HEAD(userspec_list, userspec);
|
||||
TAILQ_HEAD(member_list, member);
|
||||
TAILQ_HEAD(privilege_list, privilege);
|
||||
TAILQ_HEAD(cmndspec_list, cmndspec);
|
||||
TAILQ_HEAD(command_digest_list, command_digest);
|
||||
STAILQ_HEAD(comment_list, sudoers_comment);
|
||||
|
||||
/*
|
||||
@@ -196,6 +188,16 @@ struct privilege {
|
||||
struct defaults_list defaults; /* list of sudoOptions */
|
||||
};
|
||||
|
||||
/*
|
||||
* A command with option args and digest.
|
||||
* XXX - merge into struct member
|
||||
*/
|
||||
struct sudo_command {
|
||||
char *cmnd;
|
||||
char *args;
|
||||
struct command_digest_list digests;
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure describing a linked list of Cmnd_Specs.
|
||||
* XXX - include struct command_options instad of its contents inline
|
||||
@@ -306,10 +308,10 @@ void reparent_parse_tree(struct sudoers_parse_tree *new_tree);
|
||||
bool addr_matches(char *n);
|
||||
|
||||
/* match_command.c */
|
||||
bool command_matches(const char *sudoers_cmnd, const char *sudoers_args, const struct command_digest *digest);
|
||||
bool command_matches(const char *sudoers_cmnd, const char *sudoers_args, const struct command_digest_list *digests);
|
||||
|
||||
/* match_digest.c */
|
||||
bool digest_matches(int fd, const char *file, const struct command_digest *digest);
|
||||
bool digest_matches(int fd, const char *file, const struct command_digest_list *digests);
|
||||
|
||||
/* match.c */
|
||||
struct group;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
Cmnd_Alias LS = sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1 /bin/ls
|
||||
Cmnd_Alias SH = sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM= /bin/sh
|
||||
Cmnd_Alias LS = sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1, sha224:d7910e1967342b4605cb73a550944044c631cd3514001900966962ac /bin/ls
|
||||
Cmnd_Alias SH = sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh
|
||||
|
||||
millert ALL = LS, SH, sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill
|
||||
|
@@ -3,13 +3,15 @@
|
||||
"LS": [
|
||||
{
|
||||
"command": "/bin/ls",
|
||||
"sha224": "d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1"
|
||||
"sha224": "d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1",
|
||||
"sha224": "d7910e1967342b4605cb73a550944044c631cd3514001900966962ac"
|
||||
}
|
||||
],
|
||||
"SH": [
|
||||
{
|
||||
"command": "/bin/sh",
|
||||
"sha256": "hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM="
|
||||
"sha256": "hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=",
|
||||
"sha256": "1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4="
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@@ -4,8 +4,8 @@ objectClass: sudoRole
|
||||
cn: millert
|
||||
sudoUser: millert
|
||||
sudoHost: ALL
|
||||
sudoCommand: sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1 /bin/ls
|
||||
sudoCommand: sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM= /bin/sh
|
||||
sudoCommand: sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1, sha224:d7910e1967342b4605cb73a550944044c631cd3514001900966962ac /bin/ls
|
||||
sudoCommand: sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh
|
||||
sudoCommand: sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill
|
||||
sudoOrder: 1
|
||||
|
||||
|
@@ -1,5 +1,7 @@
|
||||
# sudoRole millert
|
||||
millert ALL = sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1\
|
||||
/bin/ls, sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM= /bin/sh,\
|
||||
millert ALL = sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1,\
|
||||
sha224:d7910e1967342b4605cb73a550944044c631cd3514001900966962ac /bin/ls,\
|
||||
sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=,\
|
||||
sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh,\
|
||||
sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw\
|
||||
/bin/kill
|
||||
|
@@ -1,6 +1,6 @@
|
||||
Parses OK.
|
||||
|
||||
Cmnd_Alias LS = sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1 /bin/ls
|
||||
Cmnd_Alias SH = sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM= /bin/sh
|
||||
Cmnd_Alias LS = sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1, sha224:d7910e1967342b4605cb73a550944044c631cd3514001900966962ac /bin/ls
|
||||
Cmnd_Alias SH = sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh
|
||||
|
||||
millert ALL = LS, SH, sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill
|
||||
|
@@ -1,4 +1,4 @@
|
||||
CMNDALIAS ALIAS = SHA224_TOK : DIGEST COMMAND
|
||||
CMNDALIAS ALIAS = SHA256_TOK : DIGEST COMMAND
|
||||
CMNDALIAS ALIAS = SHA224_TOK : DIGEST , SHA224_TOK : DIGEST COMMAND
|
||||
CMNDALIAS ALIAS = SHA256_TOK : DIGEST , SHA256_TOK : DIGEST COMMAND
|
||||
|
||||
WORD(5) ALL = ALIAS , ALIAS , SHA512_TOK : DIGEST COMMAND
|
||||
|
@@ -27,6 +27,5 @@ bool sudo_ldap_is_negated(char **valp);
|
||||
bool sudo_ldap_add_default(const char *var, const char *val, int op, char *source, struct defaults_list *defs);
|
||||
int sudo_ldap_parse_option(char *optstr, char **varp, char **valp);
|
||||
struct privilege *sudo_ldap_role_to_priv(const char *cn, void *hosts, void *runasusers, void *runasgroups, void *cmnds, void *opts, const char *notbefore, const char *notafter, bool warnings, bool store_options, sudo_ldap_iter_t iter);
|
||||
struct command_digest *sudo_ldap_extract_digest(char **cmnd, struct command_digest *digest);
|
||||
|
||||
#endif /* SUDOERS_LDAP_H */
|
||||
|
Reference in New Issue
Block a user