]> granicus.if.org Git - sudo/commitdiff
Add -M option to cvtsudoers to force the use of the local passwd
authorTodd C. Miller <Todd.Miller@sudo.ws>
Thu, 22 Mar 2018 19:24:41 +0000 (13:24 -0600)
committerTodd C. Miller <Todd.Miller@sudo.ws>
Thu, 22 Mar 2018 19:24:41 +0000 (13:24 -0600)
and group databases when matching.

doc/cvtsudoers.cat
doc/cvtsudoers.man.in
doc/cvtsudoers.mdoc.in
plugins/sudoers/cvtsudoers.c
plugins/sudoers/cvtsudoers.h
plugins/sudoers/cvtsudoers_pwutil.c
plugins/sudoers/pwutil.c
plugins/sudoers/sudoers.h

index eec3a9174917892d5a004b508c049d88324f72ab..75d0cac50b26641954d444231f5385c8557e9e29 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-e\beh\bhV\bV] [-\b-b\bb _\bd_\bn] [-\b-c\bc _\bc_\bo_\bn_\bf_\b__\bf_\bi_\bl_\be] [-\b-f\bf _\bo_\bu_\bt_\bp_\bu_\bt_\b__\bf_\bo_\br_\bm_\ba_\bt]
+     c\bcv\bvt\bts\bsu\bud\bdo\boe\ber\brs\bs [-\b-e\beh\bhM\bMV\bV] [-\b-b\bb _\bd_\bn] [-\b-c\bc _\bc_\bo_\bn_\bf_\b__\bf_\bi_\bl_\be] [-\b-f\bf _\bo_\bu_\bt_\bp_\bu_\bt_\b__\bf_\bo_\br_\bm_\ba_\bt]
                 [-\b-i\bi _\bi_\bn_\bp_\bu_\bt_\b__\bf_\bo_\br_\bm_\ba_\bt] [-\b-I\bI _\bi_\bn_\bc_\br_\be_\bm_\be_\bn_\bt] [-\b-m\bm _\bf_\bi_\bl_\bt_\be_\br] [-\b-o\bo _\bo_\bu_\bt_\bp_\bu_\bt_\b__\bf_\bi_\bl_\be]
                 [-\b-O\bO _\bs_\bt_\ba_\br_\bt_\b__\bp_\bo_\bi_\bn_\bt] [-\b-s\bs _\bs_\be_\bc_\bt_\bi_\bo_\bn_\bs] [_\bi_\bn_\bp_\bu_\bt_\b__\bf_\bi_\bl_\be]
 
@@ -99,6 +99,16 @@ D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
                  are referenced by the filtered policy rules will be
                  displayed.
 
+     -\b-M\bM, -\b--\b-m\bma\bat\btc\bch\bh-\b-l\blo\boc\bca\bal\bl
+                 When the -\b-m\bm option is also specified, use password and group
+                 database information when matching users and groups in the
+                 filter.  Only users and groups in the filter that exist on
+                 the local system will match, and a user's groups will
+                 automatically be added to the filter.  If the -\b-M\bM is _\bn_\bo_\bt
+                 specified, users and groups in the filter do not need to
+                 exist on the local system, but all groups used for matching
+                 must be explicitly listed in the filter.
+
      -\b-o\bo _\bo_\bu_\bt_\bp_\bu_\bt_\b__\bf_\bi_\bl_\be, -\b--\b-o\bou\but\btp\bpu\but\bt=_\bo_\bu_\bt_\bp_\bu_\bt_\b__\bf_\bi_\bl_\be
                  Write the converted output to _\bo_\bu_\bt_\bp_\bu_\bt_\b__\bf_\bi_\bl_\be.  If no _\bo_\bu_\bt_\bp_\bu_\bt_\b__\bf_\bi_\bl_\be
                  is specified, or if it is `-', the converted _\bs_\bu_\bd_\bo_\be_\br_\bs policy
index f08e7e328106c5791698627bbcc2b83dbb14bf0b..1cff19d3137bb94b1e383e8da895373f9fef3a3f 100644 (file)
@@ -25,7 +25,7 @@
 .SH "SYNOPSIS"
 .HP 11n
 \fBcvtsudoers\fR
-[\fB\-ehV\fR]
+[\fB\-ehMV\fR]
 [\fB\-b\fR\ \fIdn\fR]
 [\fB\-c\fR\ \fIconf_file\fR]
 [\fB\-f\fR\ \fIoutput_format\fR]
@@ -191,6 +191,21 @@ on the local system.
 Only aliases that are referenced by the filtered policy rules will
 be displayed.
 .TP 12n
+\fB\-M\fR, \fB\--match-local\fR
+When the
+\fB\-m\fR
+option is also specified, use password and group database information
+when matching users and groups in the filter.
+Only users and groups in the filter that exist on the local system will match,
+and a user's groups will automatically be added to the filter.
+If the
+\fB\-M\fR
+is
+\fInot\fR
+specified, users and groups in the filter do not need to exist on the
+local system, but all groups used for matching must be explicitly listed
+in the filter.
+.TP 12n
 \fB\-o\fR \fIoutput_file\fR, \fB\--output\fR=\fIoutput_file\fR
 Write the converted output to
 \fIoutput_file\fR.
index ce1e5630ec3db6f12f80bb6c779702152a2b0a95..2792e1c72afd531acd4c0a45d8c82656a47a9903 100644 (file)
@@ -22,7 +22,7 @@
 .Nd convert between sudoers file formats
 .Sh SYNOPSIS
 .Nm cvtsudoers
-.Op Fl ehV
+.Op Fl ehMV
 .Op Fl b Ar dn
 .Op Fl c Ar conf_file
 .Op Fl f Ar output_format
@@ -155,6 +155,20 @@ against the filter so the users and groups do not need to be present
 on the local system.
 Only aliases that are referenced by the filtered policy rules will
 be displayed.
+.It Fl M , Fl -match-local
+When the
+.Fl m
+option is also specified, use password and group database information
+when matching users and groups in the filter.
+Only users and groups in the filter that exist on the local system will match,
+and a user's groups will automatically be added to the filter.
+If the
+.Fl M
+is
+.Em not
+specified, users and groups in the filter do not need to exist on the
+local system, but all groups used for matching must be explicitly listed
+in the filter.
 .It Fl o Ar output_file , Fl -output Ns = Ns Ar output_file
 Write the converted output to
 .Ar output_file .
index 4cd5562522bdba91ca207937ed55b88f2d8be709..7ad26bbe3d492413a6fc6f758096e582cac45ac0 100644 (file)
@@ -56,7 +56,7 @@
 struct cvtsudoers_filter *filters;
 struct sudo_user sudo_user;
 struct passwd *list_pw;
-static const char short_opts[] =  "b:c:ef:hi:I:m:o:O:s:V";
+static const char short_opts[] =  "b:c:ef:hi:I:m:Mo:O:s:V";
 static struct option long_opts[] = {
     { "base",          required_argument,      NULL,   'b' },
     { "config",                required_argument,      NULL,   'c' },
@@ -66,6 +66,7 @@ static struct option long_opts[] = {
     { "input-format",  required_argument,      NULL,   'i' },
     { "increment",     required_argument,      NULL,   'I' },
     { "match",         required_argument,      NULL,   'm' },
+    { "match-local",   no_argument,            NULL,   'M' },
     { "order-start",   required_argument,      NULL,   'O' },
     { "output",                required_argument,      NULL,   'o' },
     { "suppress",      required_argument,      NULL,   's' },
@@ -93,6 +94,7 @@ main(int argc, char *argv[])
     enum sudoers_formats output_format = format_ldif;
     enum sudoers_formats input_format = format_sudoers;
     struct cvtsudoers_config *conf = NULL;
+    bool match_local = false;
     const char *input_file = "-";
     const char *output_file = "-";
     const char *conf_file = _PATH_CVTSUDOERS_CONF;
@@ -187,6 +189,9 @@ main(int argc, char *argv[])
        case 'm':
            conf->filter = optarg;
            break;
+       case 'M':
+           match_local = true;
+           break;
        case 'o':
            output_file = optarg;
            break;
@@ -272,6 +277,12 @@ main(int argc, char *argv[])
        }
     }
 
+    /* Set pwutil backend to use the filter data. */
+    if (conf->filter != NULL && !match_local) {
+       sudo_pwutil_set_backend(cvtsudoers_make_pwitem, cvtsudoers_make_gritem,
+           cvtsudoers_make_gidlist_item, cvtsudoers_make_grlist_item);
+    }
+
     /* We may need the hostname to resolve %h escapes in include files. */
     get_hostname();
 
@@ -610,7 +621,7 @@ open_sudoers(const char *sudoers, bool doedit, bool *keepopen)
     return fopen(sudoers, "r");
 }
 
-bool
+static bool
 userlist_matches_filter(struct member_list *userlist)
 {
     struct cvtsudoers_string *s;
@@ -658,7 +669,7 @@ userlist_matches_filter(struct member_list *userlist)
     debug_return_bool(matches);
 }
 
-bool
+static bool
 hostlist_matches_filter(struct member_list *hostlist)
 {
     struct cvtsudoers_string *s;
@@ -1011,7 +1022,7 @@ done:
 static void
 usage(int fatal)
 {
-    (void) fprintf(fatal ? stderr : stdout, "usage: %s [-ehV] [-b dn] "
+    (void) fprintf(fatal ? stderr : stdout, "usage: %s [-ehMV] [-b dn] "
        "[-c conf_file ] [-f output_format] [-i input_format] [-I increment] "
        "[-m filter] [-o output_file] [-O start_point] [-s sections] "
        "[input_file]\n", getprogname());
@@ -1031,7 +1042,8 @@ help(void)
        "  -i, --input-format=format  set input format: LDIF or sudoers\n"
        "  -I, --increment=num        amount to increase each sudoOrder by\n"
        "  -h, --help                 display help message and exit\n"
-       "  -m, --match=filter         only convert entries that match the filter expression\n"
+       "  -m, --match=filter         only convert entries that match the filter\n"
+       "  -M, --match-local          match filter uses passwd and group databases\n"
        "  -o, --output=output_file   write converted sudoers to output_file\n"
        "  -O, --order-start=num      starting point for first sudoOrder\n"
        "  -s, --suppress=sections    suppress output of certain sections\n"
index c3ff522ee6224187b3f8ff04801afc1d5ae76298..4ec4f3bf178253c1e80aa205adf58790ddf72e79 100644 (file)
@@ -74,21 +74,25 @@ struct cvtsudoers_filter {
     struct cvtsudoers_str_list hosts;
 };
 
-bool convert_sudoers_json(const char *output_file, struct cvtsudoers_config *conf);
-bool convert_sudoers_ldif(const char *output_file, struct cvtsudoers_config *conf);
-bool parse_ldif(const char *input_file, struct cvtsudoers_config *conf);
-void get_hostname(void);
-
-struct member_list;
-struct userspec_list;
-bool userlist_matches_filter(struct member_list *userlist);
-bool hostlist_matches_filter(struct member_list *hostlist);
-
+/* cvtsudoers.c */
+extern struct cvtsudoers_filter *filters;
 struct cvtsudoers_str_list *str_list_alloc(void);
 void str_list_free(void *v);
 struct cvtsudoers_string *cvtsudoers_string_alloc(const char *s);
 void cvtsudoers_string_free(struct cvtsudoers_string *ls);
 
-extern struct cvtsudoers_filter *filters;
+/* cvtsudoers_json.c */
+bool convert_sudoers_json(const char *output_file, struct cvtsudoers_config *conf);
+
+/* cvtsudoers_ldif.c */
+bool convert_sudoers_ldif(const char *output_file, struct cvtsudoers_config *conf);
+bool parse_ldif(const char *input_file, struct cvtsudoers_config *conf);
+void get_hostname(void);
+
+/* cvtsudoers_pwutil.c */
+struct cache_item *cvtsudoers_make_pwitem(uid_t uid, const char *name);
+struct cache_item *cvtsudoers_make_gritem(gid_t gid, const char *name);
+struct cache_item *cvtsudoers_make_gidlist_item(const struct passwd *pw, char * const *unused1, unsigned int type);
+struct cache_item *cvtsudoers_make_grlist_item(const struct passwd *pw, char * const *unused1);
 
 #endif /* SUDOERS_CVTSUDOERS_H */
index 4f8de07b5efa5ac488c0cbc1226b08eb40f351ee..9314b22c4ca2948a9a0b1367fc5e718408e5f5bd 100644 (file)
@@ -73,7 +73,7 @@ do {                                                  \
  * to ENOMEM or ENOENT respectively.
  */
 struct cache_item *
-sudo_make_pwitem(uid_t uid, const char *name)
+cvtsudoers_make_pwitem(uid_t uid, const char *name)
 {
     char *cp, uidstr[MAX_UID_T_LEN + 2];
     size_t nsize, psize, csize, gsize, dsize, ssize, total;
@@ -179,7 +179,7 @@ sudo_make_pwitem(uid_t uid, const char *name)
  * to ENOMEM or ENOENT respectively.
  */
 struct cache_item *
-sudo_make_gritem(gid_t gid, const char *name)
+cvtsudoers_make_gritem(gid_t gid, const char *name)
 {
     char *cp, gidstr[MAX_UID_T_LEN + 2];
     size_t nsize, psize, nmem, total, len;
@@ -292,7 +292,7 @@ static struct cache_item_gidlist *gidlist_item;
  * elements.  Fills in datum from user_gids or from getgrouplist(3).
  */
 struct cache_item *
-sudo_make_gidlist_item(const struct passwd *pw, char * const *unused1,
+cvtsudoers_make_gidlist_item(const struct passwd *pw, char * const *unused1,
     unsigned int type)
 {
     char *cp;
@@ -391,7 +391,7 @@ static struct cache_item_gidlist *grlist_item;
  * elements.  Fills in group names from a call to sudo_get_gidlist().
  */
 struct cache_item *
-sudo_make_grlist_item(const struct passwd *pw, char * const *unused1)
+cvtsudoers_make_grlist_item(const struct passwd *pw, char * const *unused1)
 {
     char *cp;
     size_t nsize, ngroups, total, len;
index 26235812a08b592a7a2cf1d40d4f7ea48a49afc2..e170c31e5d73fcf714644e132e4da84630982afa 100644 (file)
@@ -54,6 +54,14 @@ static int  cmp_pwuid(const void *, const void *);
 static int  cmp_pwnam(const void *, const void *);
 static int  cmp_grgid(const void *, const void *);
 
+/*
+ * Default functions for building cache items.
+ */
+static sudo_make_pwitem_t make_pwitem = sudo_make_pwitem;
+static sudo_make_gritem_t make_gritem = sudo_make_gritem;
+static sudo_make_gidlist_item_t make_gidlist_item = sudo_make_gidlist_item;
+static sudo_make_grlist_item_t make_grlist_item = sudo_make_grlist_item;
+
 #define cmp_grnam      cmp_pwnam
 
 /*
@@ -68,6 +76,24 @@ static int  cmp_grgid(const void *, const void *);
 # define getauthregistry(u, r) ((r)[0] = '\0')
 #endif
 
+/*
+ * Change the default pwutil backend functions.
+ * The default functions query the password and group databases.
+ */
+void
+sudo_pwutil_set_backend(sudo_make_pwitem_t pwitem, sudo_make_gritem_t gritem,
+    sudo_make_gidlist_item_t gidlist_item, sudo_make_grlist_item_t grlist_item)
+{
+    debug_decl(sudo_pwutil_set_backend, SUDOERS_DEBUG_NSS)
+
+    make_pwitem = pwitem;
+    make_gritem = gritem;
+    make_gidlist_item = gidlist_item;
+    make_grlist_item = grlist_item;
+
+    debug_return;
+}
+
 /*
  * Compare by user ID.
  * v1 is the key to find or data to insert, v2 is in-tree data.
@@ -179,7 +205,7 @@ sudo_getpwuid(uid_t uid)
 #ifdef HAVE_SETAUTHDB
     aix_setauthdb(IDtouser(uid), key.registry);
 #endif
-    item = sudo_make_pwitem(uid, NULL);
+    item = make_pwitem(uid, NULL);
 #ifdef HAVE_SETAUTHDB
     aix_restoreauthdb();
 #endif
@@ -250,7 +276,7 @@ sudo_getpwnam(const char *name)
 #ifdef HAVE_SETAUTHDB
     aix_setauthdb((char *) name, key.registry);
 #endif
-    item = sudo_make_pwitem((uid_t)-1, name);
+    item = make_pwitem((uid_t)-1, name);
 #ifdef HAVE_SETAUTHDB
     aix_restoreauthdb();
 #endif
@@ -497,7 +523,7 @@ sudo_getgrgid(gid_t gid)
     /*
      * Cache group db entry if it exists or a negative response if not.
      */
-    item = sudo_make_gritem(gid, NULL);
+    item = make_gritem(gid, NULL);
     if (item == NULL) {
        if (errno != ENOENT || (item = calloc(1, sizeof(*item))) == NULL) {
            sudo_warnx(U_("unable to cache gid %u, out of memory"),
@@ -562,7 +588,7 @@ sudo_getgrnam(const char *name)
     /*
      * Cache group db entry if it exists or a negative response if not.
      */
-    item = sudo_make_gritem((gid_t)-1, name);
+    item = make_gritem((gid_t)-1, name);
     if (item == NULL) {
        const size_t len = strlen(name) + 1;
        if (errno != ENOENT || (item = calloc(1, sizeof(*item) + len)) == NULL) {
@@ -789,7 +815,7 @@ sudo_get_grlist(const struct passwd *pw)
     /*
      * Cache group db entry if it exists or a negative response if not.
      */
-    item = sudo_make_grlist_item(pw, NULL);
+    item = make_grlist_item(pw, NULL);
     if (item == NULL) {
        /* Out of memory? */
        debug_return_ptr(NULL);
@@ -843,7 +869,7 @@ sudo_set_grlist(struct passwd *pw, char * const *groups)
     key.k.name = pw->pw_name;
     getauthregistry(NULL, key.registry);
     if ((node = rbfind(grlist_cache, &key)) == NULL) {
-       if ((item = sudo_make_grlist_item(pw, groups)) == NULL) {
+       if ((item = make_grlist_item(pw, groups)) == NULL) {
            sudo_warnx(U_("unable to parse groups for %s"), pw->pw_name);
            debug_return_int(-1);
        }
@@ -892,7 +918,7 @@ sudo_get_gidlist(const struct passwd *pw, unsigned int type)
     /*
      * Cache group db entry if it exists or a negative response if not.
      */
-    item = sudo_make_gidlist_item(pw, NULL, type);
+    item = make_gidlist_item(pw, NULL, type);
     if (item == NULL) {
        /* Out of memory? */
        debug_return_ptr(NULL);
@@ -947,7 +973,7 @@ sudo_set_gidlist(struct passwd *pw, char * const *gids, unsigned int type)
     key.type = type;
     getauthregistry(NULL, key.registry);
     if ((node = rbfind(gidlist_cache, &key)) == NULL) {
-       if ((item = sudo_make_gidlist_item(pw, gids, type)) == NULL) {
+       if ((item = make_gidlist_item(pw, gids, type)) == NULL) {
            sudo_warnx(U_("unable to parse gids for %s"), pw->pw_name);
            debug_return_int(-1);
        }
index 0825181f8fbcc20158eeb4fb902489fb3a3e70bf..a8139f9e08a6cdcd94a39a4ed699946dc7a922e8 100644 (file)
@@ -304,6 +304,10 @@ int display_privs(struct sudo_nss_list *, struct passwd *);
 int display_cmnd(struct sudo_nss_list *, struct passwd *);
 
 /* pwutil.c */
+typedef struct cache_item * (*sudo_make_pwitem_t)(uid_t uid, const char *user);
+typedef struct cache_item * (*sudo_make_gritem_t)(gid_t gid, const char *group);
+typedef struct cache_item * (*sudo_make_gidlist_item_t)(const struct passwd *pw, char * const *gids, unsigned int type);
+typedef struct cache_item * (*sudo_make_grlist_item_t)(const struct passwd *pw, char * const *groups);
 __dso_public struct group *sudo_getgrgid(gid_t);
 __dso_public struct group *sudo_getgrnam(const char *);
 __dso_public void sudo_gr_addref(struct group *);
@@ -327,6 +331,7 @@ void sudo_pw_addref(struct passwd *);
 void sudo_pw_delref(struct passwd *);
 int  sudo_set_gidlist(struct passwd *pw, char * const *gids, unsigned int type);
 int  sudo_set_grlist(struct passwd *pw, char * const *groups);
+void sudo_pwutil_set_backend(sudo_make_pwitem_t, sudo_make_gritem_t, sudo_make_gidlist_item_t, sudo_make_grlist_item_t);
 void sudo_setspent(void);
 
 /* timestr.c */