Skip to content

Commit e9d65e6

Browse files
committed
Treat unresolvable User_Alias/Host_Alias as non-aliases in JSON output.
This matches the behavior of the sudoers parser. There is no way to tell for sure if an upper case word is an alias or a user or host name. An unresolvable command alias is never a command since it doesn't start with a '/'. GitHub issue #381
1 parent 4e1c587 commit e9d65e6

File tree

3 files changed

+87
-41
lines changed

3 files changed

+87
-41
lines changed

plugins/sudoers/cvtsudoers_json.c

+42-41
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,9 @@ print_member_json_int(struct json_container *jsonc,
192192
{
193193
struct json_value value;
194194
const char *typestr = NULL;
195-
const char *errstr;
196195
short alias_type = UNSPEC;
196+
struct alias *a = NULL;
197+
const char *errstr;
197198
id_t id;
198199
debug_decl(print_member_json_int, SUDOERS_DEBUG_UTIL);
199200

@@ -217,6 +218,37 @@ print_member_json_int(struct json_container *jsonc,
217218
value.u.string = name;
218219
}
219220

221+
/* Special handling for ALIAS, which might actually be a WORD. */
222+
if (type == ALIAS) {
223+
switch (word_type) {
224+
case TYPE_COMMAND:
225+
alias_type = CMNDALIAS;
226+
typestr = "cmndalias";
227+
break;
228+
case TYPE_HOSTNAME:
229+
alias_type = HOSTALIAS;
230+
typestr = "hostalias";
231+
break;
232+
case TYPE_RUNASGROUP:
233+
case TYPE_RUNASUSER:
234+
alias_type = RUNASALIAS;
235+
typestr = "runasalias";
236+
break;
237+
case TYPE_USERNAME:
238+
alias_type = USERALIAS;
239+
typestr = "useralias";
240+
break;
241+
default:
242+
sudo_fatalx("unexpected word type %d", word_type);
243+
}
244+
245+
a = alias_get(parse_tree, value.u.string, alias_type);
246+
if (a == NULL && alias_type != CMNDALIAS) {
247+
/* Alias does not resolve, treat as WORD instead. */
248+
type = WORD;
249+
}
250+
}
251+
220252
switch (type) {
221253
case USERGROUP:
222254
value.u.string++; /* skip leading '%' */
@@ -293,57 +325,22 @@ print_member_json_int(struct json_container *jsonc,
293325
}
294326
break;
295327
case ALIAS:
296-
switch (word_type) {
297-
case TYPE_COMMAND:
298-
if (expand_aliases) {
299-
alias_type = CMNDALIAS;
300-
} else {
301-
typestr = "cmndalias";
302-
}
303-
break;
304-
case TYPE_HOSTNAME:
305-
if (expand_aliases) {
306-
alias_type = HOSTALIAS;
307-
} else {
308-
typestr = "hostalias";
309-
}
310-
break;
311-
case TYPE_RUNASGROUP:
312-
case TYPE_RUNASUSER:
313-
if (expand_aliases) {
314-
alias_type = RUNASALIAS;
315-
} else {
316-
typestr = "runasalias";
317-
}
318-
break;
319-
case TYPE_USERNAME:
320-
if (expand_aliases) {
321-
alias_type = USERALIAS;
322-
} else {
323-
typestr = "useralias";
324-
}
325-
break;
326-
default:
327-
sudo_fatalx("unexpected word type %d", word_type);
328-
}
328+
/* handled earlier */
329329
break;
330330
default:
331331
sudo_fatalx("unexpected member type %d", type);
332332
}
333333

334334
if (expand_aliases && type == ALIAS) {
335-
struct alias *a;
336-
struct member *m;
337-
338335
/* Print each member of the alias. */
339-
if ((a = alias_get(parse_tree, value.u.string, alias_type)) != NULL) {
336+
if (a != NULL) {
337+
struct member *m;
338+
340339
TAILQ_FOREACH(m, &a->members, entries) {
341340
if (!print_member_json_int(jsonc, parse_tree, m->name, m->type,
342-
negated ? !m->negated : m->negated,
343-
alias_to_word_type(alias_type), true))
341+
negated ? !m->negated : m->negated, word_type, true))
344342
goto oom;
345343
}
346-
alias_put(a);
347344
}
348345
} else {
349346
if (negated) {
@@ -363,9 +360,13 @@ print_member_json_int(struct json_container *jsonc,
363360
}
364361
}
365362

363+
if (a != NULL)
364+
alias_put(a);
366365
debug_return_bool(true);
367366
oom:
368367
/* warning printed by caller */
368+
if (a != NULL)
369+
alias_put(a);
369370
debug_return_bool(false);
370371
}
371372

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"Defaults": [
3+
{
4+
"Binding": [
5+
{ "username": "CLI_USR" }
6+
],
7+
"Options": [
8+
{ "lecture": false }
9+
]
10+
},
11+
{
12+
"Binding": [
13+
{ "hostname": "SUN_HST" }
14+
],
15+
"Options": [
16+
{ "log_year": true }
17+
]
18+
},
19+
{
20+
"Binding": [
21+
],
22+
"Options": [
23+
{ "use_pty": false }
24+
]
25+
}
26+
]
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/sh
2+
#
3+
# Test behavior of undefined aliases using --expand-aliases in JSON output.
4+
# https://github.com/sudo-project/sudo/issues/381
5+
#
6+
7+
: ${CVTSUDOERS=cvtsudoers}
8+
9+
$CVTSUDOERS -c "" -f json -e <<EOF
10+
User_Alias CLI_USER = cli
11+
Defaults:CLI_USR !lecture
12+
13+
Host_Alias SUN_HOST = sparc5
14+
Defaults@SUN_HST log_year
15+
16+
Cmnd_Alias REBOOT = /sbin/halt, /sbin/reboot, /sbin/poweroff
17+
Defaults!REBOT !use_pty
18+
EOF

0 commit comments

Comments
 (0)