]> granicus.if.org Git - sudo/commitdiff
Add option to cvtsudoers to expand aliases in the output.
authorTodd C. Miller <Todd.Miller@sudo.ws>
Mon, 19 Feb 2018 22:32:56 +0000 (15:32 -0700)
committerTodd C. Miller <Todd.Miller@sudo.ws>
Mon, 19 Feb 2018 22:32:56 +0000 (15:32 -0700)
doc/cvtsudoers.cat
doc/cvtsudoers.man.in
doc/cvtsudoers.mdoc.in
plugins/sudoers/cvtsudoers.c
plugins/sudoers/cvtsudoers_json.c
plugins/sudoers/cvtsudoers_ldif.c
plugins/sudoers/fmtsudoers.c

index 37a3a87b2eda1b712e5f671e033d1a99b936efe9..76293f5ecea7bbbf38f98d806697f61165b0c402 100644 (file)
@@ -4,7 +4,7 @@ N\bNA\bAM\bME\bE
      c\bcv\bvt\bts\bsu\bud\bdo\boe\ber\brs\bs - convert between sudoers file formats
 
 S\bSY\bYN\bNO\bOP\bPS\bSI\bIS\bS
-     c\bcv\bvt\bts\bsu\bud\bdo\boe\ber\brs\bs [-\b-h\bhV\bV] [-\b-b\bb _\bd_\bn] [-\b-f\bf _\bf_\bo_\br_\bm_\ba_\bt] [-\b-o\bo _\bo_\bu_\bt_\bp_\bu_\bt_\b__\bf_\bi_\bl_\be] [_\bs_\bu_\bd_\bo_\be_\br_\bs_\b__\bf_\bi_\bl_\be]
+     c\bcv\bvt\bts\bsu\bud\bdo\boe\ber\brs\bs [-\b-e\beh\bhV\bV] [-\b-b\bb _\bd_\bn] [-\b-f\bf _\bf_\bo_\br_\bm_\ba_\bt] [-\b-o\bo _\bo_\bu_\bt_\bp_\bu_\bt_\b__\bf_\bi_\bl_\be] [_\bs_\bu_\bd_\bo_\be_\br_\bs_\b__\bf_\bi_\bl_\be]
 
 D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
      c\bcv\bvt\bts\bsu\bud\bdo\boe\ber\brs\bs can be used to convert a policy file in _\bs_\bu_\bd_\bo_\be_\br_\bs format to
@@ -25,6 +25,10 @@ D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
                  environment variable will be used instead.  Only necessary
                  when converting to LDIF format.
 
+     -\b-e\be, -\b--\b-e\bex\bxp\bpa\ban\bnd\bd-\b-a\bal\bli\bia\bas\bse\bes\bs
+                 Expand aliases in _\bs_\bu_\bd_\bo_\be_\br_\bs_\b__\bf_\bi_\bl_\be.  Aliases are preserved by
+                 default when the output _\bf_\bo_\br_\bm_\ba_\bt is JSON or sudoers.
+
      -\b-f\bf _\bo_\bu_\bt_\bp_\bu_\bt_\b__\bf_\bo_\br_\bm_\ba_\bt, -\b--\b-f\bfo\bor\brm\bma\bat\bt=_\bo_\bu_\bt_\bp_\bu_\bt_\b__\bf_\bo_\br_\bm_\ba_\bt
                  Specify the output format.  The following formats are
                  supported:
@@ -94,4 +98,4 @@ D\bDI\bIS\bSC\bCL\bLA\bAI\bIM\bME\bER\bR
      file distributed with s\bsu\bud\bdo\bo or https://www.sudo.ws/license.html for
      complete details.
 
-Sudo 1.8.23                    February 2, 2018                    Sudo 1.8.23
+Sudo 1.8.23                    February 18, 2018                   Sudo 1.8.23
index 9b7741617cbb98ab9cd84bdcbab45baafe4ae786..e439d742eaa1dfa7e8ca71ed6f9130dea5f03e98 100644 (file)
@@ -16,7 +16,7 @@
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "CVTSUDOERS" "8" "February 2, 2018" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
+.TH "CVTSUDOERS" "8" "February 18, 2018" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -25,7 +25,7 @@
 .SH "SYNOPSIS"
 .HP 11n
 \fBcvtsudoers\fR
-[\fB\-hV\fR]
+[\fB\-ehV\fR]
 [\fB\-b\fR\ \fIdn\fR]
 [\fB\-f\fR\ \fIformat\fR]
 [\fB\-o\fR\ \fIoutput_file\fR]
@@ -61,6 +61,13 @@ If this option is not specified, the value of the
 environment variable will be used instead.
 Only necessary when converting to LDIF format.
 .TP 12n
+\fB\-e\fR, \fB\--expand-aliases\fR
+Expand aliases in
+\fIsudoers_file\fR.
+Aliases are preserved by default when the output
+\fIformat\fR
+is JSON or sudoers.
+.TP 12n
 \fB\-f\fR \fIoutput_format\fR, \fB\--format\fR=\fIoutput_format\fR
 Specify the output format.
 The following formats are supported:
index e5cb76878ba6b719e8ecbe0abfe3d92101b2bcba..f05be64305cde48e8538e42ff00fc0da068dd203 100644 (file)
@@ -14,7 +14,7 @@
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd February 2, 2018
+.Dd February 18, 2018
 .Dt CVTSUDOERS @mansectsu@
 .Os Sudo @PACKAGE_VERSION@
 .Sh NAME
@@ -22,7 +22,7 @@
 .Nd convert between sudoers file formats
 .Sh SYNOPSIS
 .Nm cvtsudoers
-.Op Fl hV
+.Op Fl ehV
 .Op Fl b Ar dn
 .Op Fl f Ar format
 .Op Fl o Ar output_file
@@ -57,6 +57,12 @@ If this option is not specified, the value of the
 .Ev SUDOERS_BASE
 environment variable will be used instead.
 Only necessary when converting to LDIF format.
+.It Fl e , Fl -expand-aliases
+Expand aliases in
+.Ar sudoers_file .
+Aliases are preserved by default when the output
+.Ar format
+is JSON or sudoers.
 .It Fl f Ar output_format , Fl -format Ns = Ns Ar output_format
 Specify the output format.
 The following formats are supported:
index ae96b3e85ea5889725af3a32100a5388f1b22912..9024ce48054ae0c116da3131d0920f71f12f3cec 100644 (file)
@@ -46,8 +46,8 @@
 # include "compat/getopt.h"
 #endif /* HAVE_GETOPT_LONG */
 
-static bool convert_sudoers_sudoers(const char *output_file);
-extern bool convert_sudoers_json(const char *output_file);
+static bool convert_sudoers_sudoers(const char *output_file, bool expand_aliases);
+extern bool convert_sudoers_json(const char *output_file, bool expand_aliases);
 extern bool convert_sudoers_ldif(const char *output_file, const char *base);
 extern void get_hostname(void);
 
@@ -56,9 +56,10 @@ extern void get_hostname(void);
  */
 struct sudo_user sudo_user;
 struct passwd *list_pw;
-static const char short_opts[] =  "b:f:ho:V";
+static const char short_opts[] =  "b:ef:ho:V";
 static struct option long_opts[] = {
     { "base",          required_argument,      NULL,   'b' },
+    { "expand-aliases",        no_argument,            NULL,   'e' },
     { "format",                required_argument,      NULL,   'f' },
     { "help",          no_argument,            NULL,   'h' },
 #ifdef notyet
@@ -87,6 +88,7 @@ main(int argc, char *argv[])
     const char *input_file = "-";
     const char *output_file = "-";
     const char *sudoers_base = NULL;
+    bool expand_aliases = false;
     debug_decl(main, SUDOERS_DEBUG_MAIN)
 
 #if defined(SUDO_DEVEL) && defined(__OpenBSD__)
@@ -119,6 +121,9 @@ main(int argc, char *argv[])
        case 'b':
            sudoers_base = optarg;
            break;
+       case 'e':
+           expand_aliases = true;
+           break;
        case 'f':
            if (strcasecmp(optarg, "json") == 0) {
                output_format = output_json;
@@ -209,13 +214,13 @@ main(int argc, char *argv[])
 
     switch (output_format) {
     case output_json:
-       exitcode = !convert_sudoers_json(output_file);
+       exitcode = !convert_sudoers_json(output_file, expand_aliases);
        break;
     case output_ldif:
        exitcode = !convert_sudoers_ldif(output_file, sudoers_base);
        break;
     case output_sudoers:
-       exitcode = !convert_sudoers_sudoers(output_file);
+       exitcode = !convert_sudoers_sudoers(output_file, expand_aliases);
        break;
     default:
        sudo_fatalx("error: unhandled output format %d", output_format);
@@ -236,35 +241,42 @@ open_sudoers(const char *sudoers, bool doedit, bool *keepopen)
  * Display Defaults entries
  */
 static bool
-print_defaults_sudoers(struct sudo_lbuf *lbuf)
+print_defaults_sudoers(struct sudo_lbuf *lbuf, bool expand_aliases)
 {
     struct defaults *def, *next;
-    struct member *m;
     debug_decl(print_defaults_sudoers, SUDOERS_DEBUG_UTIL)
 
     TAILQ_FOREACH_SAFE(def, &defaults, entries, next) {
+       struct member *m;
+       int alias_type;
+
        /* Print Defaults type and binding (if present) */
        switch (def->type) {
-           case DEFAULTS:
-               sudo_lbuf_append(lbuf, "Defaults");
-               break;
            case DEFAULTS_HOST:
                sudo_lbuf_append(lbuf, "Defaults@");
+               alias_type = HOSTALIAS;
                break;
            case DEFAULTS_USER:
                sudo_lbuf_append(lbuf, "Defaults:");
+               alias_type = expand_aliases ? USERALIAS : UNSPEC;
                break;
            case DEFAULTS_RUNAS:
                sudo_lbuf_append(lbuf, "Defaults>");
+               alias_type = expand_aliases ? RUNASALIAS : UNSPEC;
                break;
            case DEFAULTS_CMND:
                sudo_lbuf_append(lbuf, "Defaults!");
+               alias_type = expand_aliases ? CMNDALIAS : UNSPEC;
+               break;
+           default:
+               sudo_lbuf_append(lbuf, "Defaults");
+               alias_type = UNSPEC;
                break;
        }
        TAILQ_FOREACH(m, def->binding, entries) {
            if (m != TAILQ_FIRST(def->binding))
                sudo_lbuf_append(lbuf, ", ");
-           sudoers_format_member(lbuf, m, NULL, UNSPEC);
+           sudoers_format_member(lbuf, m, ", ", alias_type);
        }
 
        /* Print Defaults with the same binding, there may be multiple. */
@@ -327,7 +339,7 @@ convert_sudoers_output(const char *buf)
  * Convert back to sudoers.
  */
 static bool
-convert_sudoers_sudoers(const char *output_file)
+convert_sudoers_sudoers(const char *output_file, bool expand_aliases)
 {
     bool ret = true;
     struct sudo_lbuf lbuf;
@@ -344,7 +356,7 @@ convert_sudoers_sudoers(const char *output_file)
     sudo_lbuf_init(&lbuf, convert_sudoers_output, 4, "\\", 80);
 
     /* Print Defaults */
-    if (!print_defaults_sudoers(&lbuf))
+    if (!print_defaults_sudoers(&lbuf, expand_aliases))
        goto done;
     if (lbuf.len > 0) {
        sudo_lbuf_print(&lbuf);
@@ -352,15 +364,17 @@ convert_sudoers_sudoers(const char *output_file)
     }
 
     /* Print Aliases */
-    if (!print_aliases_sudoers(&lbuf))
-       goto done;
-    if (lbuf.len > 1) {
-       sudo_lbuf_print(&lbuf);
-       sudo_lbuf_append(&lbuf, "\n");
+    if (!expand_aliases) {
+       if (!print_aliases_sudoers(&lbuf))
+           goto done;
+       if (lbuf.len > 1) {
+           sudo_lbuf_print(&lbuf);
+           sudo_lbuf_append(&lbuf, "\n");
+       }
     }
 
     /* Print User_Specs */
-    if (!sudoers_format_userspecs(&lbuf, &userspecs, false))
+    if (!sudoers_format_userspecs(&lbuf, &userspecs, expand_aliases))
        goto done;
     if (lbuf.len > 1) {
        sudo_lbuf_print(&lbuf);
@@ -388,9 +402,8 @@ done:
 static void
 usage(int fatal)
 {
-    (void) fprintf(fatal ? stderr : stdout,
-       "usage: %s [-hV] [-b dn] [-f format] [-o output_file] [sudoers_file]\n",
-           getprogname());
+    (void) fprintf(fatal ? stderr : stdout, "usage: %s [-ehV] [-b dn] "
+       "[-f format] [-o output_file] [sudoers_file]\n", getprogname());
     if (fatal)
        exit(1);
 }
index 0460cb69175b793a870d8054391479435edd613f..72fe1bc190c7db3e07d6b2e2344322e2dff774b7 100644 (file)
@@ -225,15 +225,15 @@ printstr_json(FILE *fp, const char *pre, const char *str, const char *post,
  * that closes the object.
  */
 static void
-print_command_json(FILE *fp, struct member *m, int indent, bool last_one)
+print_command_json(FILE *fp, const char *name, int type, bool negated, int indent, bool last_one)
 {
-    struct sudo_command *c = (struct sudo_command *)m->name;
+    struct sudo_command *c = (struct sudo_command *)name;
     struct json_value value;
     const char *digest_name;
     debug_decl(print_command_json, SUDOERS_DEBUG_UTIL)
 
     printstr_json(fp, "{", NULL, NULL, indent);
-    if (m->negated || c->digest != NULL) {
+    if (negated || c->digest != NULL) {
        putc('\n', fp);
        indent += 4;
     } else {
@@ -262,7 +262,7 @@ print_command_json(FILE *fp, struct member *m, int indent, bool last_one)
     }
 
     /* Command may be negated. */
-    if (m->negated) {
+    if (negated) {
        fputs(",\n", fp);
        value.type = JSON_BOOL;
        value.u.boolean = true;
@@ -330,30 +330,32 @@ defaults_to_word_type(int defaults_type)
  * that closes the object.
  */
 static void
-print_member_json(FILE *fp, struct member *m, enum word_type word_type,
-    bool last_one, int indent)
+print_member_json_int(FILE *fp, char *name, int type, bool negated,
+    enum word_type word_type, bool last_one, int indent, bool expand_aliases)
 {
     struct json_value value;
     const char *typestr;
     const char *errstr;
+    int alias_type = UNSPEC;
+    bool need_newline = true;
     id_t id;
     debug_decl(print_member_json, SUDOERS_DEBUG_UTIL)
 
     /* Most of the time we print a string. */
     value.type = JSON_STRING;
-    value.u.string = m->name;
+    value.u.string = name;
 
-    switch (m->type) {
+    switch (type) {
     case USERGROUP:
        value.u.string++; /* skip leading '%' */
        if (*value.u.string == ':') {
            value.u.string++;
            typestr = "nonunixgroup";
            if (*value.u.string == '#') {
-               id = sudo_strtoid(m->name + 3, NULL, NULL, &errstr);
+               id = sudo_strtoid(name + 3, NULL, NULL, &errstr);
                if (errstr != NULL) {
                    sudo_warnx("internal error: non-Unix group ID %s: \"%s\"",
-                       errstr, m->name);
+                       errstr, name);
                } else {
                    value.type = JSON_ID;
                    value.u.id = id;
@@ -363,10 +365,10 @@ print_member_json(FILE *fp, struct member *m, enum word_type word_type,
        } else {
            typestr = "usergroup";
            if (*value.u.string == '#') {
-               id = sudo_strtoid(m->name + 2, NULL, NULL, &errstr);
+               id = sudo_strtoid(name + 2, NULL, NULL, &errstr);
                if (errstr != NULL) {
                    sudo_warnx("internal error: group ID %s: \"%s\"",
-                       errstr, m->name);
+                       errstr, name);
                } else {
                    value.type = JSON_ID;
                    value.u.id = id;
@@ -383,7 +385,7 @@ print_member_json(FILE *fp, struct member *m, enum word_type word_type,
        typestr = "networkaddr";
        break;
     case COMMAND:
-       print_command_json(fp, m, indent, last_one);
+       print_command_json(fp, name, type, negated, indent, last_one);
        debug_return;
     case ALL:
        value.u.string = "ALL";
@@ -403,10 +405,10 @@ print_member_json(FILE *fp, struct member *m, enum word_type word_type,
        case TYPE_USERNAME:
            typestr = "username";
            if (*value.u.string == '#') {
-               id = sudo_strtoid(m->name + 1, NULL, NULL, &errstr);
+               id = sudo_strtoid(name + 1, NULL, NULL, &errstr);
                if (errstr != NULL) {
                    sudo_warnx("internal error: user ID %s: \"%s\"",
-                       errstr, m->name);
+                       errstr, name);
                } else {
                    value.type = JSON_ID;
                    value.u.id = id;
@@ -421,27 +423,57 @@ print_member_json(FILE *fp, struct member *m, enum word_type word_type,
     case ALIAS:
        switch (word_type) {
        case TYPE_COMMAND:
-           typestr = "cmndalias";
+           if (expand_aliases) {
+               alias_type = CMNDALIAS;
+           } else {
+               typestr = "cmndalias";
+           }
            break;
        case TYPE_HOSTNAME:
-           typestr = "hostalias";
+           if (expand_aliases) {
+               alias_type = HOSTALIAS;
+           } else {
+               typestr = "hostalias";
+           }
            break;
        case TYPE_RUNASGROUP:
        case TYPE_RUNASUSER:
-           typestr = "runasalias";
+           if (expand_aliases) {
+               alias_type = RUNASALIAS;
+           } else {
+               typestr = "runasalias";
+           }
            break;
        case TYPE_USERNAME:
-           typestr = "useralias";
+           if (expand_aliases) {
+               alias_type = USERALIAS;
+           } else {
+               typestr = "useralias";
+           }
            break;
        default:
            sudo_fatalx("unexpected word type %d", word_type);
        }
        break;
     default:
-       sudo_fatalx("unexpected member type %d", m->type);
+       sudo_fatalx("unexpected member type %d", type);
     }
 
-    if (m->negated) {
+    if (expand_aliases && type == ALIAS) {
+       struct alias *a;
+       struct member *m;
+
+       if ((a = alias_get(name, alias_type)) != NULL) {
+           TAILQ_FOREACH(m, &a->members, entries) {
+               print_member_json_int(fp, m->name, m->type,
+                   negated ? !m->negated : m->negated,
+                   alias_to_word_type(alias_type),
+                   last_one && TAILQ_NEXT(m, entries) == NULL, indent, true);
+           }
+           alias_put(a);
+           need_newline = false;
+       }
+    } else if (negated) {
        print_indent(fp, indent);
        fputs("{\n", fp);
        indent += 4;
@@ -457,11 +489,20 @@ print_member_json(FILE *fp, struct member *m, enum word_type word_type,
     }
     if (!last_one)
        putc(',', fp);
-    putc('\n', fp);
+    if (need_newline)
+       putc('\n', fp);
 
     debug_return;
 }
 
+static void
+print_member_json(FILE *fp, struct member *m, enum word_type word_type,
+    bool last_one, int indent, bool expand_aliases)
+{
+    return print_member_json_int(fp, m->name, m->type, m->negated, word_type,
+       last_one, indent, expand_aliases);
+}
+
 /*
  * Callback for alias_apply() to print an alias entry if it matches
  * the type specified in the closure.
@@ -492,7 +533,7 @@ print_alias_json(void *v1, void *v2)
     TAILQ_FOREACH(m, &a->members, entries) {
        print_member_json(closure->fp, m,
            alias_to_word_type(closure->alias_type),
-           TAILQ_NEXT(m, entries) == NULL, closure->indent);
+           TAILQ_NEXT(m, entries) == NULL, closure->indent, false);
     }
     closure->indent -= 4;
     debug_return_int(0);
@@ -502,7 +543,7 @@ print_alias_json(void *v1, void *v2)
  * Print the binding for a Defaults entry of the specified type.
  */
 static void
-print_binding_json(FILE *fp, struct member_list *binding, int type, int indent)
+print_binding_json(FILE *fp, struct member_list *binding, int type, int indent, bool expand_aliases)
 {
     struct member *m;
     debug_decl(print_binding_json, SUDOERS_DEBUG_UTIL)
@@ -516,7 +557,7 @@ print_binding_json(FILE *fp, struct member_list *binding, int type, int indent)
     /* Print each member object in binding. */
     TAILQ_FOREACH(m, binding, entries) {
        print_member_json(fp, m, defaults_to_word_type(type),
-            TAILQ_NEXT(m, entries) == NULL, indent);
+            TAILQ_NEXT(m, entries) == NULL, indent, expand_aliases);
     }
 
     indent -= 4;
@@ -601,7 +642,7 @@ get_defaults_type(struct defaults *def)
  * Export all Defaults in JSON format.
  */
 static bool
-print_defaults_json(FILE *fp, int indent, bool need_comma)
+print_defaults_json(FILE *fp, int indent, bool expand_aliases, bool need_comma)
 {
     struct json_value value;
     struct defaults *def, *next;
@@ -625,7 +666,7 @@ print_defaults_json(FILE *fp, int indent, bool need_comma)
        /* Found it, print object container and binding (if any). */
        fprintf(fp, "%*s{\n", indent, "");
        indent += 4;
-       print_binding_json(fp, def->binding, def->type, indent);
+       print_binding_json(fp, def->binding, def->type, indent, expand_aliases);
 
        /* Validation checks. */
        /* XXX - validate values in addition to names? */
@@ -732,7 +773,7 @@ print_aliases_json(FILE *fp, int indent, bool need_comma)
  */
 static void
 print_cmndspec_json(FILE *fp, struct cmndspec *cs, struct cmndspec **nextp,
-    int indent)
+    bool expand_aliases, int indent)
 {
     struct cmndspec *next = *nextp;
     struct json_value value;
@@ -752,7 +793,7 @@ print_cmndspec_json(FILE *fp, struct cmndspec *cs, struct cmndspec **nextp,
        indent += 4;
        TAILQ_FOREACH(m, cs->runasuserlist, entries) {
            print_member_json(fp, m, TYPE_RUNASUSER,
-               TAILQ_NEXT(m, entries) == NULL, indent);
+               TAILQ_NEXT(m, entries) == NULL, indent, expand_aliases);
        }
        indent -= 4;
        fprintf(fp, "%*s],\n", indent, "");
@@ -764,7 +805,7 @@ print_cmndspec_json(FILE *fp, struct cmndspec *cs, struct cmndspec **nextp,
        indent += 4;
        TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
            print_member_json(fp, m, TYPE_RUNASGROUP,
-               TAILQ_NEXT(m, entries) == NULL, indent);
+               TAILQ_NEXT(m, entries) == NULL, indent, expand_aliases);
        }
        indent -= 4;
        fprintf(fp, "%*s],\n", indent, "");
@@ -919,7 +960,8 @@ print_cmndspec_json(FILE *fp, struct cmndspec *cs, struct cmndspec **nextp,
 #endif /* HAVE_SELINUX */
            ;
 
-       print_member_json(fp, cs->cmnd, TYPE_COMMAND, last_one, indent);
+       print_member_json(fp, cs->cmnd, TYPE_COMMAND,
+           last_one, indent, expand_aliases);
        if (last_one)
            break;
        cs = next;
@@ -941,7 +983,7 @@ print_cmndspec_json(FILE *fp, struct cmndspec *cs, struct cmndspec **nextp,
  * Print a User_Spec in JSON format at the specified indent level.
  */
 static void
-print_userspec_json(FILE *fp, struct userspec *us, int indent)
+print_userspec_json(FILE *fp, struct userspec *us, int indent, bool expand_aliases)
 {
     struct privilege *priv;
     struct member *m;
@@ -963,7 +1005,7 @@ print_userspec_json(FILE *fp, struct userspec *us, int indent)
        indent += 4;
        TAILQ_FOREACH(m, &us->users, entries) {
            print_member_json(fp, m, TYPE_USERNAME,
-               TAILQ_NEXT(m, entries) == NULL, indent);
+               TAILQ_NEXT(m, entries) == NULL, indent, expand_aliases);
        }
        indent -= 4;
        fprintf(fp, "%*s],\n", indent, "");
@@ -973,7 +1015,7 @@ print_userspec_json(FILE *fp, struct userspec *us, int indent)
        indent += 4;
        TAILQ_FOREACH(m, &priv->hostlist, entries) {
            print_member_json(fp, m, TYPE_HOSTNAME,
-               TAILQ_NEXT(m, entries) == NULL, indent);
+               TAILQ_NEXT(m, entries) == NULL, indent, expand_aliases);
        }
        indent -= 4;
        fprintf(fp, "%*s],\n", indent, "");
@@ -982,7 +1024,7 @@ print_userspec_json(FILE *fp, struct userspec *us, int indent)
        fprintf(fp, "%*s\"Cmnd_Specs\": [\n", indent, "");
        indent += 4;
        TAILQ_FOREACH_SAFE(cs, &priv->cmndlist, entries, next) {
-           print_cmndspec_json(fp, cs, &next, indent);
+           print_cmndspec_json(fp, cs, &next, expand_aliases, indent);
        }
        indent -= 4;
        fprintf(fp, "%*s]\n", indent, "");
@@ -997,7 +1039,7 @@ print_userspec_json(FILE *fp, struct userspec *us, int indent)
 }
 
 static bool
-print_userspecs_json(FILE *fp, int indent, bool need_comma)
+print_userspecs_json(FILE *fp, int indent, bool expand_aliases, bool need_comma)
 {
     struct userspec *us;
     debug_decl(print_userspecs_json, SUDOERS_DEBUG_UTIL)
@@ -1008,7 +1050,7 @@ print_userspecs_json(FILE *fp, int indent, bool need_comma)
     fprintf(fp, "%s\n%*s\"User_Specs\": [\n", need_comma ? "," : "", indent, "");
     indent += 4;
     TAILQ_FOREACH(us, &userspecs, entries) {
-       print_userspec_json(fp, us, indent);
+       print_userspec_json(fp, us, indent, expand_aliases);
     }
     indent -= 4;
     fprintf(fp, "%*s]", indent, "");
@@ -1020,7 +1062,7 @@ print_userspecs_json(FILE *fp, int indent, bool need_comma)
  * Export the parsed sudoers file in JSON format.
  */
 bool
-convert_sudoers_json(const char *output_file)
+convert_sudoers_json(const char *output_file, bool expand_aliases)
 {
     bool ret = true, need_comma = false;
     const int indent = 4;
@@ -1036,13 +1078,14 @@ convert_sudoers_json(const char *output_file)
     putc('{', output_fp);
 
     /* Dump Defaults in JSON format. */
-    need_comma = print_defaults_json(output_fp, indent, need_comma);
+    need_comma = print_defaults_json(output_fp, indent, expand_aliases, need_comma);
 
     /* Dump Aliases in JSON format. */
-    need_comma = print_aliases_json(output_fp, indent, need_comma);
+    if (!expand_aliases)
+       need_comma = print_aliases_json(output_fp, indent, need_comma);
 
     /* Dump User_Specs in JSON format. */
-    print_userspecs_json(output_fp, indent, need_comma);
+    print_userspecs_json(output_fp, indent, expand_aliases, need_comma);
 
     /* Close JSON output. */
     fputs("\n}\n", output_fp);
index 697188b50d822886dd9e3c64460b5ad8ff3eaa93..cf35c3939e4dd100e53190a8252677d84405235a 100644 (file)
@@ -120,7 +120,7 @@ warn_bound_defaults_ldif(FILE *fp)
  * See print_member_int() in parse.c.
  */
 static void
-print_member_ldif(FILE *fp, char *name, int type, int negated,
+print_member_ldif(FILE *fp, char *name, int type, bool negated,
     int alias_type, const char *prefix)
 {
     struct alias *a;
index b57605e69a2f048158d3b4d2388925b96e61fc1d..04097f3978980ab39e140745136f2ba9529d8797 100644 (file)
@@ -39,7 +39,7 @@
  */
 static bool
 sudoers_format_member_int(struct sudo_lbuf *lbuf, char *name, int type,
-    int negated, const char *separator, int alias_type)
+    bool negated, const char *separator, int alias_type)
 {
     struct alias *a;
     struct member *m;
@@ -245,7 +245,8 @@ sudoers_format_userspec(struct sudo_lbuf *lbuf, struct userspec *us,
     TAILQ_FOREACH(m, &us->users, entries) {
        if (m != TAILQ_FIRST(&us->users))
            sudo_lbuf_append(lbuf, ", ");
-       sudoers_format_member(lbuf, m, NULL, UNSPEC);
+       sudoers_format_member(lbuf, m, ", ",
+           expand_aliases ? USERALIAS : UNSPEC);
     }
 
     TAILQ_FOREACH(priv, &us->privileges, entries) {