struct seen_user {
const char *name;
- long count;
+ unsigned long count;
};
static int sudo_order;
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.
*/
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.
*/
struct privilege *priv;
struct member *m;
struct cmndspec *cs, *next;
- struct rbnode *node;
debug_decl(print_userspec_ldif, SUDOERS_DEBUG_UTIL)
/*
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"));
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))
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
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
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
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
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