From 1ab3606019ee312b9dcdbf0d2acf8f73dc8df7af Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Fri, 18 May 2018 10:11:51 -0600 Subject: [PATCH] Add support for parsing base64-encoded attributes --- MANIFEST | 2 + plugins/sudoers/cvtsudoers_ldif.c | 118 +++++++++++------- .../sudoers/regress/cvtsudoers/test25.out.ok | 31 +++++ plugins/sudoers/regress/cvtsudoers/test25.sh | 52 ++++++++ 4 files changed, 161 insertions(+), 42 deletions(-) create mode 100644 plugins/sudoers/regress/cvtsudoers/test25.out.ok create mode 100755 plugins/sudoers/regress/cvtsudoers/test25.sh diff --git a/MANIFEST b/MANIFEST index 88a6d9b20..49e5f573b 100644 --- a/MANIFEST +++ b/MANIFEST @@ -429,6 +429,8 @@ plugins/sudoers/regress/cvtsudoers/test23.out.ok plugins/sudoers/regress/cvtsudoers/test23.sh plugins/sudoers/regress/cvtsudoers/test24.out.ok plugins/sudoers/regress/cvtsudoers/test24.sh +plugins/sudoers/regress/cvtsudoers/test25.out.ok +plugins/sudoers/regress/cvtsudoers/test25.sh plugins/sudoers/regress/cvtsudoers/test3.out.ok plugins/sudoers/regress/cvtsudoers/test3.sh plugins/sudoers/regress/cvtsudoers/test4.out.ok diff --git a/plugins/sudoers/cvtsudoers_ldif.c b/plugins/sudoers/cvtsudoers_ldif.c index 973d240b8..f56c11a02 100644 --- a/plugins/sudoers/cvtsudoers_ldif.c +++ b/plugins/sudoers/cvtsudoers_ldif.c @@ -27,7 +27,6 @@ #endif /* HAVE_STRINGS_H */ #include #include -#include #include "sudoers.h" #include "sudo_ldap.h" @@ -580,6 +579,46 @@ sudo_role_alloc(void) debug_return_ptr(role); } +/* + * Parse an LDIF attribute, including base64 support. + * See http://www.faqs.org/rfcs/rfc2849.html + */ +static char * +ldif_parse_attribute(char *str) +{ + bool encoded = false; + char *attr, *ep; + size_t len; + debug_decl(ldif_parse_attribute, SUDOERS_DEBUG_UTIL) + + /* Check for foo:: base64str. */ + if (*str == ':') { + encoded = true; + str++; + } + + /* Trim leading and trailing space. */ + while (*str == ' ') + str++; + + ep = str + strlen(str); + while (ep > str && ep[-1] == ' ') { + /* Don't trim ecaped trailing space if not base64. */ + if (!encoded && ep != str && ep[-2] == '\\') + break; + *--ep = '\0'; + } + + attr = str; + if (encoded) { + /* decode base64 inline and NUL-terminate */ + len = base64_decode(str, attr, strlen(str)); + attr[len] = '\0'; + } + + debug_return_str(attr); +} + /* * Allocate a struct cvtsudoers_string, store str in it and * insert into the specified strlist. @@ -590,8 +629,6 @@ ldif_store_string(const char *str, struct cvtsudoers_str_list *strlist, bool sor struct cvtsudoers_string *ls; debug_decl(ldif_store_string, SUDOERS_DEBUG_UTIL) - while (isblank((unsigned char)*str)) - str++; if ((ls = cvtsudoers_string_alloc(str)) == NULL) { sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); @@ -966,8 +1003,7 @@ parse_ldif(const char *input_file, struct cvtsudoers_config *conf) unsigned numroles = 0; bool in_role = false; size_t linesize = 0; - char *line = NULL; - char *savedline = NULL; + char *attr, *line = NULL, *savedline = NULL; ssize_t savedlen = 0; bool mismatch = false; FILE *fp; @@ -1085,32 +1121,28 @@ parse_ldif(const char *input_file, struct cvtsudoers_config *conf) if (strncasecmp(line, "dn:", 3) == 0) { /* Compare dn to base, if specified. */ if (conf->sudoers_base != NULL) { - char *cp = line + 3; - while (isblank((unsigned char)*cp)) - cp++; + attr = ldif_parse_attribute(line + 3); /* Skip over cn if present. */ - if (strncasecmp(cp, "cn=", 3) == 0) { - for (cp += 3; *cp != '\0'; cp++) { + if (strncasecmp(attr, "cn=", 3) == 0) { + for (attr += 3; *attr != '\0'; attr++) { /* Handle escaped ',' chars. */ - if (*cp == '\\') - cp++; - if (*cp == ',') { - cp++; + if (*attr == '\\') + attr++; + if (*attr == ',') { + attr++; break; } } } - if (strcasecmp(cp, conf->sudoers_base) != 0) { + if (strcasecmp(attr, conf->sudoers_base) != 0) { /* Doesn't match base, skip the rest of it. */ mismatch = true; continue; } } } else if (strncmp(line, "objectClass:", 12) == 0) { - char *cp = line + 12; - while (isblank((unsigned char)*cp)) - cp++; - if (strcmp(cp, "sudoRole") == 0) + attr = ldif_parse_attribute(line + 12); + if (strcmp(attr, "sudoRole") == 0) in_role = true; } @@ -1120,50 +1152,52 @@ parse_ldif(const char *input_file, struct cvtsudoers_config *conf) /* Part of a sudoRole, parse it. */ if (strncmp(line, "cn:", 3) == 0) { - char *cp = line + 3; - while (isblank((unsigned char)*cp)) - cp++; + attr = ldif_parse_attribute(line + 3); free(role->cn); - role->cn = unquote_cn(cp); + role->cn = unquote_cn(attr); if (role->cn == NULL) { sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); } } else if (strncmp(line, "sudoUser:", 9) == 0) { - ldif_store_string(line + 9, role->users, true); + attr = ldif_parse_attribute(line + 9); + ldif_store_string(attr, role->users, true); } else if (strncmp(line, "sudoHost:", 9) == 0) { - ldif_store_string(line + 9, role->hosts, true); + attr = ldif_parse_attribute(line + 9); + ldif_store_string(attr, role->hosts, true); } else if (strncmp(line, "sudoRunAs:", 10) == 0) { - ldif_store_string(line + 10, role->runasusers, true); + attr = ldif_parse_attribute(line + 10); + ldif_store_string(attr, role->runasusers, true); } else if (strncmp(line, "sudoRunAsUser:", 14) == 0) { - ldif_store_string(line + 14, role->runasusers, true); + attr = ldif_parse_attribute(line + 14); + ldif_store_string(attr, role->runasusers, true); } else if (strncmp(line, "sudoRunAsGroup:", 15) == 0) { - ldif_store_string(line + 15, role->runasgroups, true); + attr = ldif_parse_attribute(line + 15); + ldif_store_string(attr, role->runasgroups, true); } else if (strncmp(line, "sudoCommand:", 12) == 0) { - ldif_store_string(line + 12, role->cmnds, false); + attr = ldif_parse_attribute(line + 12); + ldif_store_string(attr, role->cmnds, false); } else if (strncmp(line, "sudoOption:", 11) == 0) { - ldif_store_string(line + 11, role->options, false); + attr = ldif_parse_attribute(line + 11); + ldif_store_string(attr, role->options, false); } else if (strncmp(line, "sudoOrder:", 10) == 0) { - char *ep, *cp = line + 10; - role->order = strtod(cp, &ep); - if (ep == cp || *ep != '\0') - sudo_warnx(U_("invalid sudoOrder attribute: %s"), cp); + char *ep; + attr = ldif_parse_attribute(line + 10); + role->order = strtod(attr, &ep); + if (ep == attr || *ep != '\0') + sudo_warnx(U_("invalid sudoOrder attribute: %s"), attr); } else if (strncmp(line, "sudoNotBefore:", 14) == 0) { - char *cp = line + 14; - while (isblank((unsigned char)*cp)) - cp++; + attr = ldif_parse_attribute(line + 14); free(role->notbefore); - role->notbefore = strdup(cp); + role->notbefore = strdup(attr); if (role->notbefore == NULL) { sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); } } else if (strncmp(line, "sudoNotAfter:", 13) == 0) { - char *cp = line + 13; - while (isblank((unsigned char)*cp)) - cp++; + attr = ldif_parse_attribute(line + 13); free(role->notafter); - role->notafter = strdup(cp); + role->notafter = strdup(attr); if (role->notafter == NULL) { sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); diff --git a/plugins/sudoers/regress/cvtsudoers/test25.out.ok b/plugins/sudoers/regress/cvtsudoers/test25.out.ok new file mode 100644 index 000000000..d4048153d --- /dev/null +++ b/plugins/sudoers/regress/cvtsudoers/test25.out.ok @@ -0,0 +1,31 @@ +dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws +objectClass: top +objectClass: sudoRole +cn: defaults +description: Default sudoOption's go here +sudoOption: log_output + +dn: cn=root,ou=SUDOers,dc=sudo,dc=ws +objectClass: top +objectClass: sudoRole +cn: root +sudoUser: root +sudoHost: ALL +sudoRunAsUser: ALL +sudoRunAsGroup: ALL +sudoOption: !authenticate +sudoCommand: ALL +sudoOrder: 10 + +dn: cn=%wheel,ou=SUDOers,dc=sudo,dc=ws +objectClass: top +objectClass: sudoRole +cn: %wheel +sudoUser: %wheel +sudoHost: +sudo-hosts +sudoRunAsUser: ALL +sudoRunAsGroup: ALL +sudoOption: !authenticate +sudoCommand: ALL +sudoOrder: 20 + diff --git a/plugins/sudoers/regress/cvtsudoers/test25.sh b/plugins/sudoers/regress/cvtsudoers/test25.sh new file mode 100755 index 000000000..7d26bb9fa --- /dev/null +++ b/plugins/sudoers/regress/cvtsudoers/test25.sh @@ -0,0 +1,52 @@ +#!/bin/sh +# +# Test LDAP base filtering. +# + +exec 2>&1 +./cvtsudoers -c "" -i ldif -b "ou=SUDOers,dc=sudo,dc=ws" -I 10 -O 10 <