]> granicus.if.org Git - sudo/commitdiff
Quote special characters when creating the cn as per RFC2253
authorTodd C. Miller <Todd.Miller@sudo.ws>
Mon, 29 Jan 2018 18:00:43 +0000 (11:00 -0700)
committerTodd C. Miller <Todd.Miller@sudo.ws>
Mon, 29 Jan 2018 18:00:43 +0000 (11:00 -0700)
plugins/sudoers/cvtsudoers_ldif.c
plugins/sudoers/regress/sudoers/test2.ldif.ok
plugins/sudoers/regress/sudoers/test6.ldif.ok

index 0d8c77dc009bca95ddc21e9189812daeb7c0fc08..d2ca2e4946ad5e9e8edb92863b1502e615f2ac26 100644 (file)
@@ -36,7 +36,7 @@
 
 struct seen_user {
     const char *name;
-    long count;
+    unsigned long count;
 };
 
 static int sudo_order;
@@ -51,6 +51,15 @@ seen_user_compare(const void *aa, const void *bb)
     return strcasecmp(a->name, b->name);
 }
 
+static void
+seen_user_free(void *v)
+{
+    struct seen_user *su = v;
+
+    free((void *)su->name);
+    free(su);
+}
+
 /*
  * Print global Defaults in a single sudoRole object.
  */
@@ -295,6 +304,79 @@ print_cmndspec_ldif(FILE *fp, struct cmndspec *cs, struct cmndspec **nextp)
     debug_return;
 }
 
+/*
+ * Convert user name to cn, avoiding duplicates and quoting as needed.
+ */
+static char *
+user_to_cn(const char *user)
+{
+    struct seen_user key, *su = NULL;
+    struct rbnode *node;
+    const char *src;
+    char *cn, *dst;
+    size_t size;
+    debug_decl(user_to_cn, SUDOERS_DEBUG_UTIL)
+
+    /* Allocate as much as we could possibly need. */
+    size = (2 * strlen(user)) + 64 + 1;
+    if ((cn = malloc(size)) == NULL)
+       goto bad;
+
+    /*
+     * Increment the number of times we have seen this user.
+     */
+    key.name = user;
+    node = rbfind(seen_users, &key);
+    if (node != NULL) {
+       su = node->data;
+    } else {
+       if ((su = malloc(sizeof(*su))) == NULL)
+           goto bad;
+       su->count = 0;
+       if ((su->name = strdup(user)) == NULL)
+           goto bad;
+       if (rbinsert(seen_users, su, NULL) != 0)
+           goto bad;
+    }
+
+    /* Build cn, quoting special chars as needed (we allocated 2 x len). */
+    for (src = user, dst = cn; *src != '\0'; src++) {
+       switch (*src) {
+       case ',':
+       case '\\':
+       case '#':
+       case '+':
+       case '<':
+       case '>':
+       case ';':
+           *dst++ = '\\';
+           *dst++ = *src;
+           break;
+       default:
+           *dst++ = *src;
+           break;
+       }
+    }
+    *dst = '\0';
+
+    /* Append count if there are duplicate users (cn must be unique). */
+    if (su->count != 0) {
+       size -= (size_t)(dst - cn);
+       if ((size_t)snprintf(dst, size, "_%lu", su->count) >= size) {
+           sudo_warnx(U_("internal error, %s overflow"), __func__);
+           goto bad;
+       }
+    }
+    su->count++;
+
+    debug_return_str(cn);
+bad:
+    if (su != NULL && su->count == 1)
+       seen_user_free(su);
+    free(cn);
+    debug_return_str(NULL);
+}
+
 /*
  * Print a single User_Spec.
  */
@@ -304,7 +386,6 @@ print_userspec_ldif(FILE *fp, struct userspec *us, const char *base)
     struct privilege *priv;
     struct member *m;
     struct cmndspec *cs, *next;
-    struct rbnode *node;
     debug_decl(print_userspec_ldif, SUDOERS_DEBUG_UTIL)
 
     /*
@@ -315,33 +396,13 @@ print_userspec_ldif(FILE *fp, struct userspec *us, const char *base)
     TAILQ_FOREACH(priv, &us->privileges, entries) {
        TAILQ_FOREACH_SAFE(cs, &priv->cmndlist, entries, next) {
            char *cn;
-           struct seen_user *su, key;
 
            /*
             * Increment the number of times we have seen this user.
             * If more than one user is listed, just use the first one.
             */
            m = TAILQ_FIRST(&us->users);
-           key.name = m->name ? m->name : "ALL";
-           node = rbfind(seen_users, &key);
-           if (node != NULL) {
-               su = node->data;
-               if (asprintf(&cn, "%s_%ld", key.name, su->count) == -1)
-                   cn = NULL;
-               su->count++;
-           } else {
-               if ((su = malloc(sizeof(*su))) == NULL) {
-                   sudo_fatalx(U_("%s: %s"), __func__,
-                       U_("unable to allocate memory"));
-               }
-               su->name = key.name;
-               su->count = 1;
-               if (rbinsert(seen_users, su, NULL) != 0) {
-                   sudo_fatalx(U_("%s: %s"), __func__,
-                       U_("unable to allocate memory"));
-               }
-               cn = strdup(key.name);
-           }
+           cn = user_to_cn(m->name ? m->name : "ALL");
            if (cn == NULL) {
                sudo_fatalx(U_("%s: %s"), __func__,
                    U_("unable to allocate memory"));
@@ -422,7 +483,7 @@ convert_sudoers_ldif(const char *output_file, const char *base)
     warn_bound_defaults_ldif(output_fp);
 
     /* Clean up. */
-    rbdestroy(seen_users, free);
+    rbdestroy(seen_users, seen_user_free);
 
     (void)fflush(output_fp);
     if (ferror(output_fp))
index 7550acc834ca3c54d6c0c175363a560edc3b3846..4c47b478e4845691a30ce7f16fbd5eae8371b5b6 100644 (file)
@@ -84,10 +84,10 @@ sudoRunAsUser: root
 sudoCommand: ALL
 sudoOrder: 8
 
-dn: cn=%:C/non\'UNIX\'1 c,ou=SUDOers,dc=sudo,dc=ws
+dn: cn=%:C/non\\'UNIX\\'1 c,ou=SUDOers,dc=sudo,dc=ws
 objectClass: top
 objectClass: sudoRole
-cn: %:C/non\'UNIX\'1 c
+cn: %:C/non\\'UNIX\\'1 c
 sudoUser: %:C/non\'UNIX\'1 c
 sudoHost: hostd
 sudoRunAsUser: root
@@ -114,20 +114,20 @@ sudoRunAsUser: root
 sudoCommand: ALL
 sudoOrder: 11
 
-dn: cn=%:C/non\'UNIX_3 c,ou=SUDOers,dc=sudo,dc=ws
+dn: cn=%:C/non\\'UNIX_3 c,ou=SUDOers,dc=sudo,dc=ws
 objectClass: top
 objectClass: sudoRole
-cn: %:C/non\'UNIX_3 c
+cn: %:C/non\\'UNIX_3 c
 sudoUser: %:C/non\'UNIX_3 c
 sudoHost: hostg
 sudoRunAsUser: root
 sudoCommand: ALL
 sudoOrder: 12
 
-dn: cn=+netgr,ou=SUDOers,dc=sudo,dc=ws
+dn: cn=\+netgr,ou=SUDOers,dc=sudo,dc=ws
 objectClass: top
 objectClass: sudoRole
-cn: +netgr
+cn: \+netgr
 sudoUser: +netgr
 sudoHost: hosth
 sudoRunAsUser: root
index b281595732103dcda8f6fa79bc6a06bc6e3d9c57..6703fa2a1f0178061012ea2eca2621cbca685337 100644 (file)
@@ -4,19 +4,19 @@ objectClass: sudoRole
 cn: defaults
 description: Default sudoOption's go here
 
-dn: cn=#0,ou=SUDOers,dc=sudo,dc=ws
+dn: cn=\#0,ou=SUDOers,dc=sudo,dc=ws
 objectClass: top
 objectClass: sudoRole
-cn: #0
+cn: \#0
 sudoUser: #0
 sudoHost: ALL
 sudoCommand: ALL
 sudoOrder: 1
 
-dn: cn=#0_1,ou=SUDOers,dc=sudo,dc=ws
+dn: cn=\#0_1,ou=SUDOers,dc=sudo,dc=ws
 objectClass: top
 objectClass: sudoRole
-cn: #0_1
+cn: \#0_1
 sudoUser: #0
 sudoHost: ALL
 sudoRunAsUser: #0
@@ -24,19 +24,19 @@ sudoRunAsGroup: #0
 sudoCommand: ALL
 sudoOrder: 2
 
-dn: cn=#0_2,ou=SUDOers,dc=sudo,dc=ws
+dn: cn=\#0_2,ou=SUDOers,dc=sudo,dc=ws
 objectClass: top
 objectClass: sudoRole
-cn: #0_2
+cn: \#0_2
 sudoUser: #0
 sudoHost: ALL
 sudoCommand: ALL
 sudoOrder: 3
 
-dn: cn=#0_3,ou=SUDOers,dc=sudo,dc=ws
+dn: cn=\#0_3,ou=SUDOers,dc=sudo,dc=ws
 objectClass: top
 objectClass: sudoRole
-cn: #0_3
+cn: \#0_3
 sudoUser: #0
 sudoHost: ALL
 sudoRunAsUser: #0
@@ -44,19 +44,19 @@ sudoRunAsGroup: #0
 sudoCommand: ALL
 sudoOrder: 4
 
-dn: cn=%#0,ou=SUDOers,dc=sudo,dc=ws
+dn: cn=%\#0,ou=SUDOers,dc=sudo,dc=ws
 objectClass: top
 objectClass: sudoRole
-cn: %#0
+cn: %\#0
 sudoUser: %#0
 sudoHost: ALL
 sudoCommand: ALL
 sudoOrder: 5
 
-dn: cn=%#0_1,ou=SUDOers,dc=sudo,dc=ws
+dn: cn=%\#0_1,ou=SUDOers,dc=sudo,dc=ws
 objectClass: top
 objectClass: sudoRole
-cn: %#0_1
+cn: %\#0_1
 sudoUser: %#0
 sudoHost: ALL
 sudoCommand: ALL