Allow the ALL keyword to be specified with a digest list.

This commit is contained in:
Todd C. Miller
2020-03-11 11:19:37 -06:00
parent 3edd30a27d
commit ea8445e364
16 changed files with 254 additions and 108 deletions

View File

@@ -981,6 +981,10 @@ If a
\fRDigest_List\fR \fRDigest_List\fR
is present, the command will only match successfully if it can be verified is present, the command will only match successfully if it can be verified
using one of the SHA-2 digests in the list. using one of the SHA-2 digests in the list.
Starting with version 1.9.0, the
\fBALL\fR
reserved word can be used in conjunction with a
\fRDigest_List\fR.
The following digest formats are supported: sha224, sha256, sha384 and sha512. The following digest formats are supported: sha224, sha256, sha384 and sha512.
The string may be specified in either hex or base64 format The string may be specified in either hex or base64 format
(base64 is more compact). (base64 is more compact).

View File

@@ -945,6 +945,10 @@ If a
.Li Digest_List .Li Digest_List
is present, the command will only match successfully if it can be verified is present, the command will only match successfully if it can be verified
using one of the SHA-2 digests in the list. using one of the SHA-2 digests in the list.
Starting with version 1.9.0, the
.Sy ALL
reserved word can be used in conjunction with a
.Li Digest_List .
The following digest formats are supported: sha224, sha256, sha384 and sha512. The following digest formats are supported: sha224, sha256, sha384 and sha512.
The string may be specified in either hex or base64 format The string may be specified in either hex or base64 format
(base64 is more compact). (base64 is more compact).

View File

@@ -84,7 +84,7 @@ print_command_json(struct json_container *json, const char *name, bool negated)
} }
} }
value.type = JSON_STRING; value.type = JSON_STRING;
value.u.string = cmnd; value.u.string = cmnd ? cmnd : "ALL";
if (!negated && TAILQ_EMPTY(&c->digests)) { if (!negated && TAILQ_EMPTY(&c->digests)) {
/* Print as { "command": "command and args" } */ /* Print as { "command": "command and args" } */
@@ -175,19 +175,22 @@ print_member_json_int(struct json_container *json,
/* Most of the time we print a string. */ /* Most of the time we print a string. */
value.type = JSON_STRING; value.type = JSON_STRING;
if (name != NULL) {
value.u.string = name;
} else {
switch (type) { switch (type) {
case ALL: case ALL:
if (name == NULL) {
value.u.string = "ALL"; value.u.string = "ALL";
} else {
/* ALL used with digest, print as a command. */
type = COMMAND;
}
break; break;
case MYSELF: case MYSELF:
value.u.string = ""; value.u.string = "";
break; break;
default: default:
if (name == NULL)
sudo_fatalx("missing member name for type %d", type); sudo_fatalx("missing member name for type %d", type);
} value.u.string = name;
} }
switch (type) { switch (type) {

View File

@@ -217,12 +217,13 @@ static char *
format_cmnd(struct sudo_command *c, bool negated) format_cmnd(struct sudo_command *c, bool negated)
{ {
struct command_digest *digest; struct command_digest *digest;
char *buf, *cp; char *buf, *cp, *cmnd;
size_t bufsiz; size_t bufsiz;
int len; int len;
debug_decl(format_cmnd, SUDOERS_DEBUG_UTIL); debug_decl(format_cmnd, SUDOERS_DEBUG_UTIL);
bufsiz = negated + strlen(c->cmnd) + 1; cmnd = c->cmnd ? c->cmnd : "ALL";
bufsiz = negated + strlen(cmnd) + 1;
if (c->args != NULL) if (c->args != NULL)
bufsiz += 1 + strlen(c->args); bufsiz += 1 + strlen(c->args);
TAILQ_FOREACH(digest, &c->digests, entries) { TAILQ_FOREACH(digest, &c->digests, entries) {
@@ -248,7 +249,7 @@ format_cmnd(struct sudo_command *c, bool negated)
} }
len = snprintf(cp, bufsiz - (cp - buf), "%s%s%s%s", negated ? "!" : "", len = snprintf(cp, bufsiz - (cp - buf), "%s%s%s%s", negated ? "!" : "",
c->cmnd, c->args ? " " : "", c->args ? c->args : ""); cmnd, c->args ? " " : "", c->args ? c->args : "");
if (len < 0 || len >= (int)bufsiz - (cp - buf)) if (len < 0 || len >= (int)bufsiz - (cp - buf))
sudo_fatalx(U_("internal error, %s overflow"), __func__); sudo_fatalx(U_("internal error, %s overflow"), __func__);
@@ -270,13 +271,16 @@ print_member_ldif(FILE *fp, struct sudoers_parse_tree *parse_tree, char *name,
debug_decl(print_member_ldif, SUDOERS_DEBUG_UTIL); debug_decl(print_member_ldif, SUDOERS_DEBUG_UTIL);
switch (type) { switch (type) {
case ALL:
print_attribute_ldif(fp, attr_name, negated ? "!ALL" : "ALL");
break;
case MYSELF: case MYSELF:
/* Only valid for sudoRunasUser */ /* Only valid for sudoRunasUser */
print_attribute_ldif(fp, attr_name, ""); print_attribute_ldif(fp, attr_name, "");
break; break;
case ALL:
if (name == NULL) {
print_attribute_ldif(fp, attr_name, negated ? "!ALL" : "ALL");
break;
}
/* FALLTHROUGH */
case COMMAND: case COMMAND:
attr_val = format_cmnd((struct sudo_command *)name, negated); attr_val = format_cmnd((struct sudo_command *)name, negated);
print_attribute_ldif(fp, attr_name, attr_val); print_attribute_ldif(fp, attr_name, attr_val);

View File

@@ -55,13 +55,16 @@ sudoers_format_member_int(struct sudo_lbuf *lbuf,
debug_decl(sudoers_format_member_int, SUDOERS_DEBUG_UTIL); debug_decl(sudoers_format_member_int, SUDOERS_DEBUG_UTIL);
switch (type) { switch (type) {
case ALL:
sudo_lbuf_append(lbuf, "%sALL", negated ? "!" : "");
break;
case MYSELF: case MYSELF:
sudo_lbuf_append(lbuf, "%s%s", negated ? "!" : "", sudo_lbuf_append(lbuf, "%s%s", negated ? "!" : "",
user_name ? user_name : ""); user_name ? user_name : "");
break; break;
case ALL:
if (name == NULL) {
sudo_lbuf_append(lbuf, "%sALL", negated ? "!" : "");
break;
}
/* FALLTHROUGH */
case COMMAND: case COMMAND:
c = (struct sudo_command *) name; c = (struct sudo_command *) name;
TAILQ_FOREACH(digest, &c->digests, entries) { TAILQ_FOREACH(digest, &c->digests, entries) {
@@ -71,7 +74,8 @@ sudoers_format_member_int(struct sudo_lbuf *lbuf,
} }
if (negated) if (negated)
sudo_lbuf_append(lbuf, "!"); sudo_lbuf_append(lbuf, "!");
sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED" \t", "%s", c->cmnd); sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED" \t", "%s",
c->cmnd ? c->cmnd : "ALL");
if (c->args) { if (c->args) {
sudo_lbuf_append(lbuf, " "); sudo_lbuf_append(lbuf, " ");
sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", c->args); sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", c->args);

View File

@@ -680,7 +680,7 @@ short *yysslim;
YYSTYPE *yyvs; YYSTYPE *yyvs;
unsigned int yystacksize; unsigned int yystacksize;
int yyparse(void); int yyparse(void);
#line 922 "gram.y" #line 928 "gram.y"
void void
sudoerserror(const char *s) sudoerserror(const char *s)
{ {
@@ -752,6 +752,24 @@ new_member(char *name, int type)
debug_return_ptr(m); debug_return_ptr(m);
} }
static struct sudo_command *
new_command(char *cmnd, char *args)
{
struct sudo_command *c;
debug_decl(new_command, SUDOERS_DEBUG_PARSER);
if ((c = calloc(1, sizeof(*c))) == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to allocate memory");
debug_return_ptr(NULL);
}
c->cmnd = cmnd;
c->args = args;
TAILQ_INIT(&c->digests);
debug_return_ptr(c);
}
static struct command_digest * static struct command_digest *
new_digest(int digest_type, char *digest_str) new_digest(int digest_type, char *digest_str)
@@ -853,7 +871,7 @@ free_member(struct member *m)
{ {
debug_decl(free_member, SUDOERS_DEBUG_PARSER); debug_decl(free_member, SUDOERS_DEBUG_PARSER);
if (m->type == COMMAND) { if (m->type == COMMAND || (m->type == ALL && m->name != NULL)) {
struct command_digest *digest; struct command_digest *digest;
struct sudo_command *c = (struct sudo_command *)m->name; struct sudo_command *c = (struct sudo_command *)m->name;
free(c->cmnd); free(c->cmnd);
@@ -1112,7 +1130,7 @@ init_options(struct command_options *opts)
opts->limitprivs = NULL; opts->limitprivs = NULL;
#endif #endif
} }
#line 1058 "gram.c" #line 1076 "gram.c"
/* allocate initial stack or double stack size, up to YYMAXDEPTH */ /* allocate initial stack or double stack size, up to YYMAXDEPTH */
#if defined(__cplusplus) || defined(__STDC__) #if defined(__cplusplus) || defined(__STDC__)
static int yygrowstack(void) static int yygrowstack(void)
@@ -1714,84 +1732,92 @@ case 44:
struct sudo_command *c = struct sudo_command *c =
(struct sudo_command *) yyvsp[0].member->name; (struct sudo_command *) yyvsp[0].member->name;
if (yyvsp[0].member->type != COMMAND) { if (yyvsp[0].member->type != COMMAND && yyvsp[0].member->type != ALL) {
sudoerserror(N_("a digest requires a path name")); sudoerserror(N_("a digest requires a path name"));
YYERROR; YYERROR;
} }
if (c == NULL) {
/* lazy-allocate sudo_command for ALL */
if ((c = new_command(NULL, NULL)) == NULL) {
sudoerserror(N_("unable to allocate memory"));
YYERROR;
}
yyvsp[0].member->name = (char *)c;
}
HLTQ_TO_TAILQ(&c->digests, yyvsp[-1].digest, entries); HLTQ_TO_TAILQ(&c->digests, yyvsp[-1].digest, entries);
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
} }
break; break;
case 45: case 45:
#line 508 "gram.y" #line 516 "gram.y"
{ {
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
yyval.member->negated = false; yyval.member->negated = false;
} }
break; break;
case 46: case 46:
#line 512 "gram.y" #line 520 "gram.y"
{ {
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
yyval.member->negated = true; yyval.member->negated = true;
} }
break; break;
case 47: case 47:
#line 518 "gram.y" #line 526 "gram.y"
{ {
yyval.string = yyvsp[0].string; yyval.string = yyvsp[0].string;
} }
break; break;
case 48: case 48:
#line 523 "gram.y" #line 531 "gram.y"
{ {
yyval.string = yyvsp[0].string; yyval.string = yyvsp[0].string;
} }
break; break;
case 49: case 49:
#line 527 "gram.y" #line 535 "gram.y"
{ {
yyval.string = yyvsp[0].string; yyval.string = yyvsp[0].string;
} }
break; break;
case 50: case 50:
#line 532 "gram.y" #line 540 "gram.y"
{ {
yyval.string = yyvsp[0].string; yyval.string = yyvsp[0].string;
} }
break; break;
case 51: case 51:
#line 537 "gram.y" #line 545 "gram.y"
{ {
yyval.string = yyvsp[0].string; yyval.string = yyvsp[0].string;
} }
break; break;
case 52: case 52:
#line 542 "gram.y" #line 550 "gram.y"
{ {
yyval.string = yyvsp[0].string; yyval.string = yyvsp[0].string;
} }
break; break;
case 53: case 53:
#line 546 "gram.y" #line 554 "gram.y"
{ {
yyval.string = yyvsp[0].string; yyval.string = yyvsp[0].string;
} }
break; break;
case 54: case 54:
#line 551 "gram.y" #line 559 "gram.y"
{ {
yyval.runas = NULL; yyval.runas = NULL;
} }
break; break;
case 55: case 55:
#line 554 "gram.y" #line 562 "gram.y"
{ {
yyval.runas = yyvsp[-1].runas; yyval.runas = yyvsp[-1].runas;
} }
break; break;
case 56: case 56:
#line 559 "gram.y" #line 567 "gram.y"
{ {
yyval.runas = calloc(1, sizeof(struct runascontainer)); yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas != NULL) { if (yyval.runas != NULL) {
@@ -1809,7 +1835,7 @@ case 56:
} }
break; break;
case 57: case 57:
#line 574 "gram.y" #line 582 "gram.y"
{ {
yyval.runas = calloc(1, sizeof(struct runascontainer)); yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas == NULL) { if (yyval.runas == NULL) {
@@ -1821,7 +1847,7 @@ case 57:
} }
break; break;
case 58: case 58:
#line 583 "gram.y" #line 591 "gram.y"
{ {
yyval.runas = calloc(1, sizeof(struct runascontainer)); yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas == NULL) { if (yyval.runas == NULL) {
@@ -1833,7 +1859,7 @@ case 58:
} }
break; break;
case 59: case 59:
#line 592 "gram.y" #line 600 "gram.y"
{ {
yyval.runas = calloc(1, sizeof(struct runascontainer)); yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas == NULL) { if (yyval.runas == NULL) {
@@ -1845,7 +1871,7 @@ case 59:
} }
break; break;
case 60: case 60:
#line 601 "gram.y" #line 609 "gram.y"
{ {
yyval.runas = calloc(1, sizeof(struct runascontainer)); yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas != NULL) { if (yyval.runas != NULL) {
@@ -1863,13 +1889,13 @@ case 60:
} }
break; break;
case 61: case 61:
#line 618 "gram.y" #line 626 "gram.y"
{ {
init_options(&yyval.options); init_options(&yyval.options);
} }
break; break;
case 62: case 62:
#line 621 "gram.y" #line 629 "gram.y"
{ {
yyval.options.notbefore = parse_gentime(yyvsp[0].string); yyval.options.notbefore = parse_gentime(yyvsp[0].string);
free(yyvsp[0].string); free(yyvsp[0].string);
@@ -1880,7 +1906,7 @@ case 62:
} }
break; break;
case 63: case 63:
#line 629 "gram.y" #line 637 "gram.y"
{ {
yyval.options.notafter = parse_gentime(yyvsp[0].string); yyval.options.notafter = parse_gentime(yyvsp[0].string);
free(yyvsp[0].string); free(yyvsp[0].string);
@@ -1891,7 +1917,7 @@ case 63:
} }
break; break;
case 64: case 64:
#line 637 "gram.y" #line 645 "gram.y"
{ {
yyval.options.timeout = parse_timeout(yyvsp[0].string); yyval.options.timeout = parse_timeout(yyvsp[0].string);
free(yyvsp[0].string); free(yyvsp[0].string);
@@ -1905,7 +1931,7 @@ case 64:
} }
break; break;
case 65: case 65:
#line 648 "gram.y" #line 656 "gram.y"
{ {
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
free(yyval.options.role); free(yyval.options.role);
@@ -1914,7 +1940,7 @@ case 65:
} }
break; break;
case 66: case 66:
#line 654 "gram.y" #line 662 "gram.y"
{ {
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
free(yyval.options.type); free(yyval.options.type);
@@ -1923,7 +1949,7 @@ case 66:
} }
break; break;
case 67: case 67:
#line 660 "gram.y" #line 668 "gram.y"
{ {
#ifdef HAVE_PRIV_SET #ifdef HAVE_PRIV_SET
free(yyval.options.privs); free(yyval.options.privs);
@@ -1932,7 +1958,7 @@ case 67:
} }
break; break;
case 68: case 68:
#line 666 "gram.y" #line 674 "gram.y"
{ {
#ifdef HAVE_PRIV_SET #ifdef HAVE_PRIV_SET
free(yyval.options.limitprivs); free(yyval.options.limitprivs);
@@ -1941,97 +1967,97 @@ case 68:
} }
break; break;
case 69: case 69:
#line 674 "gram.y" #line 682 "gram.y"
{ {
TAGS_INIT(yyval.tag); TAGS_INIT(yyval.tag);
} }
break; break;
case 70: case 70:
#line 677 "gram.y" #line 685 "gram.y"
{ {
yyval.tag.nopasswd = true; yyval.tag.nopasswd = true;
} }
break; break;
case 71: case 71:
#line 680 "gram.y" #line 688 "gram.y"
{ {
yyval.tag.nopasswd = false; yyval.tag.nopasswd = false;
} }
break; break;
case 72: case 72:
#line 683 "gram.y" #line 691 "gram.y"
{ {
yyval.tag.noexec = true; yyval.tag.noexec = true;
} }
break; break;
case 73: case 73:
#line 686 "gram.y" #line 694 "gram.y"
{ {
yyval.tag.noexec = false; yyval.tag.noexec = false;
} }
break; break;
case 74: case 74:
#line 689 "gram.y" #line 697 "gram.y"
{ {
yyval.tag.setenv = true; yyval.tag.setenv = true;
} }
break; break;
case 75: case 75:
#line 692 "gram.y" #line 700 "gram.y"
{ {
yyval.tag.setenv = false; yyval.tag.setenv = false;
} }
break; break;
case 76: case 76:
#line 695 "gram.y" #line 703 "gram.y"
{ {
yyval.tag.log_input = true; yyval.tag.log_input = true;
} }
break; break;
case 77: case 77:
#line 698 "gram.y" #line 706 "gram.y"
{ {
yyval.tag.log_input = false; yyval.tag.log_input = false;
} }
break; break;
case 78: case 78:
#line 701 "gram.y" #line 709 "gram.y"
{ {
yyval.tag.log_output = true; yyval.tag.log_output = true;
} }
break; break;
case 79: case 79:
#line 704 "gram.y" #line 712 "gram.y"
{ {
yyval.tag.log_output = false; yyval.tag.log_output = false;
} }
break; break;
case 80: case 80:
#line 707 "gram.y" #line 715 "gram.y"
{ {
yyval.tag.follow = true; yyval.tag.follow = true;
} }
break; break;
case 81: case 81:
#line 710 "gram.y" #line 718 "gram.y"
{ {
yyval.tag.follow = false; yyval.tag.follow = false;
} }
break; break;
case 82: case 82:
#line 713 "gram.y" #line 721 "gram.y"
{ {
yyval.tag.send_mail = true; yyval.tag.send_mail = true;
} }
break; break;
case 83: case 83:
#line 716 "gram.y" #line 724 "gram.y"
{ {
yyval.tag.send_mail = false; yyval.tag.send_mail = false;
} }
break; break;
case 84: case 84:
#line 721 "gram.y" #line 729 "gram.y"
{ {
yyval.member = new_member(NULL, ALL); yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2041,7 +2067,7 @@ case 84:
} }
break; break;
case 85: case 85:
#line 728 "gram.y" #line 736 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, ALIAS); yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2051,16 +2077,14 @@ case 85:
} }
break; break;
case 86: case 86:
#line 735 "gram.y" #line 743 "gram.y"
{ {
struct sudo_command *c = calloc(1, sizeof(*c)); struct sudo_command *c;
if (c == NULL) {
if ((c = new_command(yyvsp[0].command.cmnd, yyvsp[0].command.args)) == NULL) {
sudoerserror(N_("unable to allocate memory")); sudoerserror(N_("unable to allocate memory"));
YYERROR; YYERROR;
} }
c->cmnd = yyvsp[0].command.cmnd;
c->args = yyvsp[0].command.args;
TAILQ_INIT(&c->digests);
yyval.member = new_member((char *)c, COMMAND); yyval.member = new_member((char *)c, COMMAND);
if (yyval.member == NULL) { if (yyval.member == NULL) {
free(c); free(c);
@@ -2070,7 +2094,7 @@ case 86:
} }
break; break;
case 89: case 89:
#line 757 "gram.y" #line 763 "gram.y"
{ {
const char *s; const char *s;
s = alias_add(&parsed_policy, yyvsp[-2].string, HOSTALIAS, s = alias_add(&parsed_policy, yyvsp[-2].string, HOSTALIAS,
@@ -2082,14 +2106,14 @@ case 89:
} }
break; break;
case 91: case 91:
#line 769 "gram.y" #line 775 "gram.y"
{ {
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member; yyval.member = yyvsp[-2].member;
} }
break; break;
case 94: case 94:
#line 779 "gram.y" #line 785 "gram.y"
{ {
const char *s; const char *s;
s = alias_add(&parsed_policy, yyvsp[-2].string, CMNDALIAS, s = alias_add(&parsed_policy, yyvsp[-2].string, CMNDALIAS,
@@ -2101,14 +2125,14 @@ case 94:
} }
break; break;
case 96: case 96:
#line 791 "gram.y" #line 797 "gram.y"
{ {
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member; yyval.member = yyvsp[-2].member;
} }
break; break;
case 99: case 99:
#line 801 "gram.y" #line 807 "gram.y"
{ {
const char *s; const char *s;
s = alias_add(&parsed_policy, yyvsp[-2].string, RUNASALIAS, s = alias_add(&parsed_policy, yyvsp[-2].string, RUNASALIAS,
@@ -2120,7 +2144,7 @@ case 99:
} }
break; break;
case 102: case 102:
#line 816 "gram.y" #line 822 "gram.y"
{ {
const char *s; const char *s;
s = alias_add(&parsed_policy, yyvsp[-2].string, USERALIAS, s = alias_add(&parsed_policy, yyvsp[-2].string, USERALIAS,
@@ -2132,28 +2156,28 @@ case 102:
} }
break; break;
case 104: case 104:
#line 828 "gram.y" #line 834 "gram.y"
{ {
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member; yyval.member = yyvsp[-2].member;
} }
break; break;
case 105: case 105:
#line 834 "gram.y" #line 840 "gram.y"
{ {
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
yyval.member->negated = false; yyval.member->negated = false;
} }
break; break;
case 106: case 106:
#line 838 "gram.y" #line 844 "gram.y"
{ {
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
yyval.member->negated = true; yyval.member->negated = true;
} }
break; break;
case 107: case 107:
#line 844 "gram.y" #line 850 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, ALIAS); yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2163,7 +2187,7 @@ case 107:
} }
break; break;
case 108: case 108:
#line 851 "gram.y" #line 857 "gram.y"
{ {
yyval.member = new_member(NULL, ALL); yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2173,7 +2197,7 @@ case 108:
} }
break; break;
case 109: case 109:
#line 858 "gram.y" #line 864 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, NETGROUP); yyval.member = new_member(yyvsp[0].string, NETGROUP);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2183,7 +2207,7 @@ case 109:
} }
break; break;
case 110: case 110:
#line 865 "gram.y" #line 871 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, USERGROUP); yyval.member = new_member(yyvsp[0].string, USERGROUP);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2193,7 +2217,7 @@ case 110:
} }
break; break;
case 111: case 111:
#line 872 "gram.y" #line 878 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, WORD); yyval.member = new_member(yyvsp[0].string, WORD);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2203,28 +2227,28 @@ case 111:
} }
break; break;
case 113: case 113:
#line 882 "gram.y" #line 888 "gram.y"
{ {
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member; yyval.member = yyvsp[-2].member;
} }
break; break;
case 114: case 114:
#line 888 "gram.y" #line 894 "gram.y"
{ {
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
yyval.member->negated = false; yyval.member->negated = false;
} }
break; break;
case 115: case 115:
#line 892 "gram.y" #line 898 "gram.y"
{ {
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
yyval.member->negated = true; yyval.member->negated = true;
} }
break; break;
case 116: case 116:
#line 898 "gram.y" #line 904 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, ALIAS); yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2234,7 +2258,7 @@ case 116:
} }
break; break;
case 117: case 117:
#line 905 "gram.y" #line 911 "gram.y"
{ {
yyval.member = new_member(NULL, ALL); yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2244,7 +2268,7 @@ case 117:
} }
break; break;
case 118: case 118:
#line 912 "gram.y" #line 918 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, WORD); yyval.member = new_member(yyvsp[0].string, WORD);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2253,7 +2277,7 @@ case 118:
} }
} }
break; break;
#line 2199 "gram.c" #line 2223 "gram.c"
} }
yyssp -= yym; yyssp -= yym;
yystate = *yyssp; yystate = *yyssp;

View File

@@ -496,10 +496,18 @@ digcmnd : opcmnd {
struct sudo_command *c = struct sudo_command *c =
(struct sudo_command *) $2->name; (struct sudo_command *) $2->name;
if ($2->type != COMMAND) { if ($2->type != COMMAND && $2->type != ALL) {
sudoerserror(N_("a digest requires a path name")); sudoerserror(N_("a digest requires a path name"));
YYERROR; YYERROR;
} }
if (c == NULL) {
/* lazy-allocate sudo_command for ALL */
if ((c = new_command(NULL, NULL)) == NULL) {
sudoerserror(N_("unable to allocate memory"));
YYERROR;
}
$2->name = (char *)c;
}
HLTQ_TO_TAILQ(&c->digests, $1, entries); HLTQ_TO_TAILQ(&c->digests, $1, entries);
$$ = $2; $$ = $2;
} }
@@ -733,14 +741,12 @@ cmnd : ALL {
} }
} }
| COMMAND { | COMMAND {
struct sudo_command *c = calloc(1, sizeof(*c)); struct sudo_command *c;
if (c == NULL) {
if ((c = new_command($1.cmnd, $1.args)) == NULL) {
sudoerserror(N_("unable to allocate memory")); sudoerserror(N_("unable to allocate memory"));
YYERROR; YYERROR;
} }
c->cmnd = $1.cmnd;
c->args = $1.args;
TAILQ_INIT(&c->digests);
$$ = new_member((char *)c, COMMAND); $$ = new_member((char *)c, COMMAND);
if ($$ == NULL) { if ($$ == NULL) {
free(c); free(c);
@@ -990,6 +996,24 @@ new_member(char *name, int type)
debug_return_ptr(m); debug_return_ptr(m);
} }
static struct sudo_command *
new_command(char *cmnd, char *args)
{
struct sudo_command *c;
debug_decl(new_command, SUDOERS_DEBUG_PARSER);
if ((c = calloc(1, sizeof(*c))) == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to allocate memory");
debug_return_ptr(NULL);
}
c->cmnd = cmnd;
c->args = args;
TAILQ_INIT(&c->digests);
debug_return_ptr(c);
}
static struct command_digest * static struct command_digest *
new_digest(int digest_type, char *digest_str) new_digest(int digest_type, char *digest_str)
@@ -1091,7 +1115,7 @@ free_member(struct member *m)
{ {
debug_decl(free_member, SUDOERS_DEBUG_PARSER); debug_decl(free_member, SUDOERS_DEBUG_PARSER);
if (m->type == COMMAND) { if (m->type == COMMAND || (m->type == ALL && m->name != NULL)) {
struct command_digest *digest; struct command_digest *digest;
struct sudo_command *c = (struct sudo_command *)m->name; struct sudo_command *c = (struct sudo_command *)m->name;
free(c->cmnd); free(c->cmnd);

View File

@@ -398,6 +398,14 @@ cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m)
switch (m->type) { switch (m->type) {
case ALL: case ALL:
if (m->name == NULL) {
matched = !m->negated;
break;
}
/* FALLTHROUGH */
case COMMAND:
c = (struct sudo_command *)m->name;
if (command_matches(c->cmnd, c->args, &c->digests))
matched = !m->negated; matched = !m->negated;
break; break;
case ALIAS: case ALIAS:
@@ -409,11 +417,6 @@ cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m)
alias_put(a); alias_put(a);
} }
break; break;
case COMMAND:
c = (struct sudo_command *)m->name;
if (command_matches(c->cmnd, c->args, &c->digests))
matched = !m->negated;
break;
} }
debug_return_int(matched); debug_return_int(matched);
} }

View File

@@ -263,6 +263,36 @@ command_matches_dir(const char *sudoers_dir, size_t dlen,
debug_return_bool(false); debug_return_bool(false);
} }
static bool
command_matches_all(const struct command_digest_list *digests)
{
struct stat sb; /* XXX - unused */
int fd = -1;
debug_decl(command_matches_all, SUDOERS_DEBUG_MATCH);
if (user_cmnd[0] == '/') {
/* Open the file for fdexec or for digest matching. */
if (!open_cmnd(user_cmnd, digests, &fd))
goto bad;
if (!do_stat(fd, user_cmnd, &sb))
goto bad;
}
/* Check digest of user_cmnd since we have no sudoers_cmnd for ALL. */
if (!digest_matches(fd, user_cmnd, digests))
goto bad;
set_cmnd_fd(fd);
/* No need to set safe_cmnd for ALL. */
debug_return_bool(true);
bad:
if (fd != -1) {
close(fd);
fd = -1;
}
debug_return_bool(false);
}
static bool static bool
command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args, command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args,
const struct command_digest_list *digests) const struct command_digest_list *digests)
@@ -503,6 +533,11 @@ command_matches(const char *sudoers_cmnd, const char *sudoers_args, const struct
bool rc = false; bool rc = false;
debug_decl(command_matches, SUDOERS_DEBUG_MATCH); debug_decl(command_matches, SUDOERS_DEBUG_MATCH);
if (sudoers_cmnd == NULL) {
rc = command_matches_all(digests);
goto done;
}
/* Check for pseudo-commands */ /* Check for pseudo-commands */
if (sudoers_cmnd[0] != '/') { if (sudoers_cmnd[0] != '/') {
/* /*

View File

@@ -2,3 +2,5 @@ Cmnd_Alias LS = sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1,
Cmnd_Alias SH = sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh Cmnd_Alias SH = sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh
millert ALL = LS, SH, sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill millert ALL = LS, SH, sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill
operator ALL = sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= ALL

View File

@@ -35,6 +35,28 @@
] ]
} }
] ]
},
{
"User_List": [
{ "username": "operator" }
],
"Host_List": [
{ "hostname": "ALL" }
],
"Cmnd_Specs": [
{
"Options": [
{ "setenv": true }
],
"Commands": [
{
"command": "ALL",
"sha256": "hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=",
"sha256": "1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4="
}
]
}
]
} }
] ]
} }

View File

@@ -9,3 +9,12 @@ sudoCommand: sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCx
sudoCommand: sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill sudoCommand: sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill
sudoOrder: 1 sudoOrder: 1
dn: cn=operator,ou=SUDOers,dc=sudo,dc=ws
objectClass: top
objectClass: sudoRole
cn: operator
sudoUser: operator
sudoHost: ALL
sudoCommand: sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= ALL
sudoOrder: 2

View File

@@ -5,3 +5,7 @@ millert ALL = sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1,\
sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh,\ sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh,\
sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw\ sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw\
/bin/kill /bin/kill
# sudoRole operator
operator ALL = sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=,\
sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= ALL

View File

@@ -4,3 +4,4 @@ Cmnd_Alias LS = sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1,
Cmnd_Alias SH = sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh Cmnd_Alias SH = sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh
millert ALL = LS, SH, sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill millert ALL = LS, SH, sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill
operator ALL = sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= ALL

View File

@@ -2,3 +2,5 @@ CMNDALIAS ALIAS = SHA224_TOK : DIGEST , SHA224_TOK : DIGEST COMMAND
CMNDALIAS ALIAS = SHA256_TOK : DIGEST , SHA256_TOK : DIGEST COMMAND CMNDALIAS ALIAS = SHA256_TOK : DIGEST , SHA256_TOK : DIGEST COMMAND
WORD(5) ALL = ALIAS , ALIAS , SHA512_TOK : DIGEST COMMAND WORD(5) ALL = ALIAS , ALIAS , SHA512_TOK : DIGEST COMMAND
WORD(5) ALL = SHA256_TOK : DIGEST , SHA256_TOK : DIGEST ALL

View File

@@ -67,11 +67,12 @@
* 44 sudo 1.8.13, added MAIL/NOMAIL tags. * 44 sudo 1.8.13, added MAIL/NOMAIL tags.
* 45 sudo 1.8.15, added FOLLOW/NOFOLLOW tags as well as sudoedit_follow and sudoedit_checkdir Defaults. * 45 sudo 1.8.15, added FOLLOW/NOFOLLOW tags as well as sudoedit_follow and sudoedit_checkdir Defaults.
* 46 sudo 1.8.20, added TIMEOUT, NOTBEFORE and NOTAFTER options. * 46 sudo 1.8.20, added TIMEOUT, NOTBEFORE and NOTAFTER options.
* 47 sudo 1.9.0, Cmd_Alias treated as Cmnd_Alias, support for multiple digests per command and for ALL.
*/ */
#ifndef SUDOERS_VERSION_H #ifndef SUDOERS_VERSION_H
#define SUDOERS_VERSION_H #define SUDOERS_VERSION_H
#define SUDOERS_GRAMMAR_VERSION 46 #define SUDOERS_GRAMMAR_VERSION 47
#endif /* SUDOERS_VERSION_H */ #endif /* SUDOERS_VERSION_H */