From 9ff960457a5a89db56247b70d8049f46fd2bdd02 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Tue, 1 Sep 2020 06:26:05 -0600 Subject: [PATCH] Add support for runchroot and runcwd to "sudo -l" and cvtsudoers. --- MANIFEST | 7 +++ plugins/sudoers/cvtsudoers_json.c | 15 ++++- plugins/sudoers/cvtsudoers_ldif.c | 40 +++++++----- plugins/sudoers/fmtsudoers.c | 4 ++ plugins/sudoers/ldap_util.c | 6 ++ plugins/sudoers/parse.c | 8 +++ plugins/sudoers/regress/sudoers/test24.in | 6 ++ .../sudoers/regress/sudoers/test24.json.ok | 61 +++++++++++++++++++ .../sudoers/regress/sudoers/test24.ldif.ok | 39 ++++++++++++ .../regress/sudoers/test24.ldif2sudo.ok | 8 +++ plugins/sudoers/regress/sudoers/test24.out.ok | 7 +++ .../sudoers/regress/sudoers/test24.sudo.ok | 6 ++ .../sudoers/regress/sudoers/test24.toke.ok | 6 ++ 13 files changed, 195 insertions(+), 18 deletions(-) create mode 100644 plugins/sudoers/regress/sudoers/test24.in create mode 100644 plugins/sudoers/regress/sudoers/test24.json.ok create mode 100644 plugins/sudoers/regress/sudoers/test24.ldif.ok create mode 100644 plugins/sudoers/regress/sudoers/test24.ldif2sudo.ok create mode 100644 plugins/sudoers/regress/sudoers/test24.out.ok create mode 100644 plugins/sudoers/regress/sudoers/test24.sudo.ok create mode 100644 plugins/sudoers/regress/sudoers/test24.toke.ok diff --git a/MANIFEST b/MANIFEST index acd0120ca..68c2a01e9 100644 --- a/MANIFEST +++ b/MANIFEST @@ -776,6 +776,13 @@ plugins/sudoers/regress/sudoers/test23.ldif2sudo.ok plugins/sudoers/regress/sudoers/test23.out.ok plugins/sudoers/regress/sudoers/test23.sudo.ok plugins/sudoers/regress/sudoers/test23.toke.ok +plugins/sudoers/regress/sudoers/test24.in +plugins/sudoers/regress/sudoers/test24.json.ok +plugins/sudoers/regress/sudoers/test24.ldif.ok +plugins/sudoers/regress/sudoers/test24.ldif2sudo.ok +plugins/sudoers/regress/sudoers/test24.out.ok +plugins/sudoers/regress/sudoers/test24.sudo.ok +plugins/sudoers/regress/sudoers/test24.toke.ok plugins/sudoers/regress/sudoers/test3.in plugins/sudoers/regress/sudoers/test3.json.ok plugins/sudoers/regress/sudoers/test3.ldif.ok diff --git a/plugins/sudoers/cvtsudoers_json.c b/plugins/sudoers/cvtsudoers_json.c index 93224e7fd..5204d448f 100644 --- a/plugins/sudoers/cvtsudoers_json.c +++ b/plugins/sudoers/cvtsudoers_json.c @@ -579,7 +579,7 @@ cmndspec_continues(struct cmndspec *cs, struct cmndspec *next) #ifdef HAVE_SELINUX && cs->role == next->role && cs->type == next->type #endif /* HAVE_SELINUX */ - ; + && cs->runchroot == next->runchroot && cs->runcwd == next->runcwd; return ret; } @@ -626,10 +626,21 @@ print_cmndspec_json(struct json_container *json, /* Print options and tags */ if (cs->timeout > 0 || cs->notbefore != UNSPEC || cs->notafter != UNSPEC || - TAGS_SET(cs->tags) || !TAILQ_EMPTY(options)) { + cs->runchroot != NULL || cs->runcwd != NULL || TAGS_SET(cs->tags) || + !TAILQ_EMPTY(options)) { struct cmndtag tag = cs->tags; sudo_json_open_array(json, "Options"); + if (cs->runchroot != NULL) { + value.type = JSON_STRING; + value.u.string = cs->runchroot; + sudo_json_add_value(json, "runchroot", &value); + } + if (cs->runcwd != NULL) { + value.type = JSON_STRING; + value.u.string = cs->runcwd; + sudo_json_add_value(json, "runcwd", &value); + } if (cs->timeout > 0) { value.type = JSON_NUMBER; value.u.number = cs->timeout; diff --git a/plugins/sudoers/cvtsudoers_ldif.c b/plugins/sudoers/cvtsudoers_ldif.c index dfab73ad4..c9261843a 100644 --- a/plugins/sudoers/cvtsudoers_ldif.c +++ b/plugins/sudoers/cvtsudoers_ldif.c @@ -319,6 +319,7 @@ print_cmndspec_ldif(FILE *fp, struct sudoers_parse_tree *parse_tree, struct cmndspec *next = *nextp; struct member *m; struct tm *tp; + char *attr_val; bool last_one; char timebuf[sizeof("20120727121554Z")]; debug_decl(print_cmndspec_ldif, SUDOERS_DEBUG_UTIL); @@ -365,7 +366,6 @@ print_cmndspec_ldif(FILE *fp, struct sudoers_parse_tree *parse_tree, /* Print timeout as a sudoOption. */ if (cs->timeout > 0) { - char *attr_val; if (asprintf(&attr_val, "command_timeout=%d", cs->timeout) == -1) { sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); @@ -414,22 +414,35 @@ print_cmndspec_ldif(FILE *fp, struct sudoers_parse_tree *parse_tree, } print_options_ldif(fp, options); + /* Print runchroot and runcwd. */ + if (cs->runchroot != NULL) { + if (asprintf(&attr_val, "runchroot=%s", cs->runchroot) == -1) { + sudo_fatalx(U_("%s: %s"), __func__, + U_("unable to allocate memory")); + } + print_attribute_ldif(fp, "sudoOption", attr_val); + free(attr_val); + } + if (cs->runcwd != NULL) { + if (asprintf(&attr_val, "runcwd=%s", cs->runcwd) == -1) { + sudo_fatalx(U_("%s: %s"), __func__, + U_("unable to allocate memory")); + } + print_attribute_ldif(fp, "sudoOption", attr_val); + free(attr_val); + } + #ifdef HAVE_SELINUX /* Print SELinux role/type */ if (cs->role != NULL && cs->type != NULL) { - char *attr_val; - int len; - - len = asprintf(&attr_val, "role=%s", cs->role); - if (len == -1) { + if (asprintf(&attr_val, "role=%s", cs->role) == -1) { sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); } print_attribute_ldif(fp, "sudoOption", attr_val); free(attr_val); - len = asprintf(&attr_val, "type=%s", cs->type); - if (len == -1) { + if (asprintf(&attr_val, "type=%s", cs->type) == -1) { sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); } @@ -441,12 +454,8 @@ print_cmndspec_ldif(FILE *fp, struct sudoers_parse_tree *parse_tree, #ifdef HAVE_PRIV_SET /* Print Solaris privs/limitprivs */ if (cs->privs != NULL || cs->limitprivs != NULL) { - char *attr_val; - int len; - if (cs->privs != NULL) { - len = asprintf(&attr_val, "privs=%s", cs->privs); - if (len == -1) { + if (asprintf(&attr_val, "privs=%s", cs->privs) == -1) { sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); } @@ -454,8 +463,7 @@ print_cmndspec_ldif(FILE *fp, struct sudoers_parse_tree *parse_tree, free(attr_val); } if (cs->limitprivs != NULL) { - len = asprintf(&attr_val, "limitprivs=%s", cs->limitprivs); - if (len == -1) { + if (asprintf(&attr_val, "limitprivs=%s", cs->limitprivs) == -1) { sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); } @@ -481,7 +489,7 @@ print_cmndspec_ldif(FILE *fp, struct sudoers_parse_tree *parse_tree, #ifdef HAVE_SELINUX || cs->role != next->role || cs->type != next->type #endif /* HAVE_SELINUX */ - ; + || cs->runchroot != next->runchroot || cs->runcwd != next->runcwd; print_member_ldif(fp, parse_tree, cs->cmnd->name, cs->cmnd->type, cs->cmnd->negated, CMNDALIAS, "sudoCommand"); diff --git a/plugins/sudoers/fmtsudoers.c b/plugins/sudoers/fmtsudoers.c index 43f68e148..e14bac054 100644 --- a/plugins/sudoers/fmtsudoers.c +++ b/plugins/sudoers/fmtsudoers.c @@ -228,6 +228,10 @@ sudoers_format_cmndspec(struct sudo_lbuf *lbuf, if (cs->type != NULL && FIELD_CHANGED(prev_cs, cs, type)) sudo_lbuf_append(lbuf, "TYPE=%s ", cs->type); #endif /* HAVE_SELINUX */ + if (cs->runchroot != NULL && FIELD_CHANGED(prev_cs, cs, runchroot)) + sudo_lbuf_append(lbuf, "CHROOT=%s ", cs->runchroot); + if (cs->runcwd != NULL && FIELD_CHANGED(prev_cs, cs, runcwd)) + sudo_lbuf_append(lbuf, "CWD=%s ", cs->runcwd); if (cs->timeout > 0 && FIELD_CHANGED(prev_cs, cs, timeout)) { char numbuf[(((sizeof(int) * 8) + 2) / 3) + 2]; (void)snprintf(numbuf, sizeof(numbuf), "%d", cs->timeout); diff --git a/plugins/sudoers/ldap_util.c b/plugins/sudoers/ldap_util.c index 62163905d..8e3278f22 100644 --- a/plugins/sudoers/ldap_util.c +++ b/plugins/sudoers/ldap_util.c @@ -516,6 +516,12 @@ sudo_ldap_role_to_priv(const char *cn, void *hosts, void *runasusers, op = sudo_ldap_parse_option(opt, &var, &val); if (strcmp(var, "command_timeout") == 0 && val != NULL) { cmndspec->timeout = parse_timeout(val); + } else if (strcmp(var, "runchroot") == 0 && val != NULL) { + if ((cmndspec->runchroot = strdup(val)) == NULL) + break; + } else if (strcmp(var, "runcwd") == 0 && val != NULL) { + if ((cmndspec->runcwd = strdup(val)) == NULL) + break; #ifdef HAVE_SELINUX } else if (strcmp(var, "role") == 0 && val != NULL) { if ((cmndspec->role = strdup(val)) == NULL) diff --git a/plugins/sudoers/parse.c b/plugins/sudoers/parse.c index f01bb93e3..3307677a2 100644 --- a/plugins/sudoers/parse.c +++ b/plugins/sudoers/parse.c @@ -426,6 +426,10 @@ new_long_entry(struct cmndspec *cs, struct cmndspec *prev_cs) if (cs->type && (!prev_cs->type || strcmp(cs->type, prev_cs->type) != 0)) debug_return_bool(true); #endif /* HAVE_SELINUX */ + if (cs->runchroot && (!prev_cs->runchroot || strcmp(cs->runchroot, prev_cs->runchroot) != 0)) + debug_return_bool(true); + if (cs->runcwd && (!prev_cs->runcwd || strcmp(cs->runcwd, prev_cs->runcwd) != 0)) + debug_return_bool(true); if (cs->timeout != prev_cs->timeout) debug_return_bool(true); if (cs->notbefore != prev_cs->notbefore) @@ -520,6 +524,10 @@ display_priv_long(struct sudoers_parse_tree *parse_tree, struct passwd *pw, if (cs->type) sudo_lbuf_append(lbuf, " Type: %s\n", cs->type); #endif /* HAVE_SELINUX */ + if (cs->runchroot != NULL) + sudo_lbuf_append(lbuf, " Chroot: %s\n", cs->runchroot); + if (cs->runcwd != NULL) + sudo_lbuf_append(lbuf, " Cwd: %s\n", cs->runcwd); if (cs->timeout > 0) { char numbuf[(((sizeof(int) * 8) + 2) / 3) + 2]; (void)snprintf(numbuf, sizeof(numbuf), "%d", cs->timeout); diff --git a/plugins/sudoers/regress/sudoers/test24.in b/plugins/sudoers/regress/sudoers/test24.in new file mode 100644 index 000000000..3fc3bbc8e --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test24.in @@ -0,0 +1,6 @@ +# Test parsing of CHROOT and CWD syntax +Defaults runcwd=~ +Defaults runchroot=/ +# +user0 ALL = CHROOT=/var/www CWD=/htdocs /bin/ksh +user1 ALL = CWD=~root /usr/bin/id, CWD=/tmp /bin/ls diff --git a/plugins/sudoers/regress/sudoers/test24.json.ok b/plugins/sudoers/regress/sudoers/test24.json.ok new file mode 100644 index 000000000..964359caf --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test24.json.ok @@ -0,0 +1,61 @@ +{ + "Defaults": [ + { + "Options": [ + { "runcwd": "~" } + ] + }, + { + "Options": [ + { "runchroot": "/" } + ] + } + ], + "User_Specs": [ + { + "User_List": [ + { "username": "user0" } + ], + "Host_List": [ + { "hostname": "ALL" } + ], + "Cmnd_Specs": [ + { + "Options": [ + "runchroot": "/var/www", + "runcwd": "/htdocs" + ], + "Commands": [ + { "command": "/bin/ksh" } + ] + } + ] + }, + { + "User_List": [ + { "username": "user1" } + ], + "Host_List": [ + { "hostname": "ALL" } + ], + "Cmnd_Specs": [ + { + "Options": [ + "runcwd": "~root" + ], + "Commands": [ + { "command": "/usr/bin/id" } + ] + }, + { + "Options": [ + "runcwd": "/tmp" + ], + "Commands": [ + { "command": "/bin/ls" } + ] + } + ] + } + ] +} diff --git a/plugins/sudoers/regress/sudoers/test24.ldif.ok b/plugins/sudoers/regress/sudoers/test24.ldif.ok new file mode 100644 index 000000000..aeb5f7a49 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test24.ldif.ok @@ -0,0 +1,39 @@ +dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws +objectClass: top +objectClass: sudoRole +cn: defaults +description: Default sudoOption's go here +sudoOption: runcwd=~ +sudoOption: runchroot=/ + +dn: cn=user0,ou=SUDOers,dc=sudo,dc=ws +objectClass: top +objectClass: sudoRole +cn: user0 +sudoUser: user0 +sudoHost: ALL +sudoOption: runchroot=/var/www +sudoOption: runcwd=/htdocs +sudoCommand: /bin/ksh +sudoOrder: 1 + +dn: cn=user1,ou=SUDOers,dc=sudo,dc=ws +objectClass: top +objectClass: sudoRole +cn: user1 +sudoUser: user1 +sudoHost: ALL +sudoOption: runcwd=~root +sudoCommand: /usr/bin/id +sudoOrder: 2 + +dn: cn=user1_1,ou=SUDOers,dc=sudo,dc=ws +objectClass: top +objectClass: sudoRole +cn: user1_1 +sudoUser: user1 +sudoHost: ALL +sudoOption: runcwd=/tmp +sudoCommand: /bin/ls +sudoOrder: 3 + diff --git a/plugins/sudoers/regress/sudoers/test24.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test24.ldif2sudo.ok new file mode 100644 index 000000000..4c096575c --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test24.ldif2sudo.ok @@ -0,0 +1,8 @@ +Defaults runcwd=~ +Defaults runchroot=/ + +# sudoRole user0 +user0 ALL = CHROOT=/var/www CWD=/htdocs /bin/ksh + +# sudoRole user1, user1_1 +user1 ALL = CWD=~root /usr/bin/id, CWD=/tmp /bin/ls diff --git a/plugins/sudoers/regress/sudoers/test24.out.ok b/plugins/sudoers/regress/sudoers/test24.out.ok new file mode 100644 index 000000000..530b7005a --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test24.out.ok @@ -0,0 +1,7 @@ +Parses OK + +Defaults runcwd=~ +Defaults runchroot=/ + +user0 ALL = CHROOT=/var/www CWD=/htdocs /bin/ksh +user1 ALL = CWD=~root /usr/bin/id, CWD=/tmp /bin/ls diff --git a/plugins/sudoers/regress/sudoers/test24.sudo.ok b/plugins/sudoers/regress/sudoers/test24.sudo.ok new file mode 100644 index 000000000..8203b0c48 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test24.sudo.ok @@ -0,0 +1,6 @@ +Defaults runcwd=~ +Defaults runchroot=/ + +user0 ALL = CHROOT=/var/www CWD=/htdocs /bin/ksh + +user1 ALL = CWD=~root /usr/bin/id, CWD=/tmp /bin/ls diff --git a/plugins/sudoers/regress/sudoers/test24.toke.ok b/plugins/sudoers/regress/sudoers/test24.toke.ok new file mode 100644 index 000000000..47842f4dc --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test24.toke.ok @@ -0,0 +1,6 @@ +# +DEFAULTS DEFVAR = WORD(2) +DEFAULTS DEFVAR = WORD(2) +# +WORD(6) ALL = CHROOT = WORD(5) CWD = WORD(5) COMMAND +WORD(6) ALL = CWD = WORD(5) COMMAND , CWD = WORD(5) COMMAND