diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c index 616a2a69a..1e224dc11 100644 --- a/plugins/sudoers/ldap.c +++ b/plugins/sudoers/ldap.c @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: ISC * - * Copyright (c) 2003-2022 Todd C. Miller + * Copyright (c) 2003-2023 Todd C. Miller * * This code is derived from software contributed by Aaron Spangler. * @@ -67,14 +67,6 @@ #include "sudo_ldap_conf.h" #include "sudo_dso.h" -#ifndef LDAP_OPT_RESULT_CODE -# define LDAP_OPT_RESULT_CODE LDAP_OPT_ERROR_NUMBER -#endif - -#ifndef LDAP_OPT_SUCCESS -# define LDAP_OPT_SUCCESS LDAP_SUCCESS -#endif - #if defined(HAVE_LDAP_SASL_INTERACTIVE_BIND_S) && !defined(LDAP_SASL_QUIET) # define LDAP_SASL_QUIET 0 #endif @@ -83,21 +75,6 @@ #define ldap_unbind_ext_s(a, b, c) ldap_unbind_s(a) #endif -#ifndef HAVE_LDAP_SEARCH_EXT_S -# ifdef HAVE_LDAP_SEARCH_ST -# define ldap_search_ext_s(a, b, c, d, e, f, g, h, i, j, k) \ - ldap_search_st(a, b, c, d, e, f, i, k) -# else -# define ldap_search_ext_s(a, b, c, d, e, f, g, h, i, j, k) \ - ldap_search_s(a, b, c, d, e, f, k) -# endif -#endif - -#define LDAP_FOREACH(var, ld, res) \ - for ((var) = ldap_first_entry((ld), (res)); \ - (var) != NULL; \ - (var) = ldap_next_entry((ld), (var))) - /* The TIMEFILTER_LENGTH is the length of the filter when timed entries are used. The length is computed as follows: 81 for the filter itself @@ -305,7 +282,7 @@ sudo_ldap_get_values_len(LDAP *ld, LDAPMessage *entry, const char *attr, int *rc bval = ldap_get_values_len(ld, entry, attr); if (bval == NULL) { - int optrc = ldap_get_option(ld, LDAP_OPT_RESULT_CODE, rc); + const int optrc = ldap_get_option(ld, LDAP_OPT_RESULT_CODE, rc); if (optrc != LDAP_OPT_SUCCESS) *rc = optrc; } else { @@ -341,7 +318,7 @@ sudo_ldap_check_non_unix_group(LDAP *ld, LDAPMessage *entry, struct passwd *pw) /* walk through values */ for (p = bv; *p != NULL && !ret; p++) { bool negated = false; - char *val = (*p)->bv_val; + const char *val = (*p)->bv_val; if (*val == '!') { val++; @@ -556,122 +533,6 @@ sudo_ldap_build_default_filter(void) debug_return_str(filt); } -/* - * Determine length of query value after escaping characters - * as per RFC 4515. - */ -static size_t -sudo_ldap_value_len(const char *value) -{ - const char *s; - size_t len = 0; - - for (s = value; *s != '\0'; s++) { - switch (*s) { - case '\\': - case '(': - case ')': - case '*': - len += 2; - break; - } - } - len += (size_t)(s - value); - return len; -} - -/* - * Like strlcat() but escapes characters as per RFC 4515. - */ -static size_t -sudo_ldap_value_cat(char *dst, const char *src, size_t size) -{ - char *d = dst; - const char *s = src; - size_t n = size; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = size - dlen; - - if (n == 0) - return dlen + strlen(s); - while (*s != '\0') { - switch (*s) { - case '\\': - if (n < 3) - goto done; - *d++ = '\\'; - *d++ = '5'; - *d++ = 'c'; - n -= 3; - break; - case '(': - if (n < 3) - goto done; - *d++ = '\\'; - *d++ = '2'; - *d++ = '8'; - n -= 3; - break; - case ')': - if (n < 3) - goto done; - *d++ = '\\'; - *d++ = '2'; - *d++ = '9'; - n -= 3; - break; - case '*': - if (n < 3) - goto done; - *d++ = '\\'; - *d++ = '2'; - *d++ = 'a'; - n -= 3; - break; - default: - if (n < 1) - goto done; - *d++ = *s; - n--; - break; - } - s++; - } -done: - *d = '\0'; - while (*s != '\0') - s++; - return dlen + (s - src); /* count does not include NUL */ -} - -/* - * Like strdup() but escapes characters as per RFC 4515. - */ -static char * -sudo_ldap_value_dup(const char *src) -{ - char *dst; - size_t size; - - size = sudo_ldap_value_len(src) + 1; - dst = malloc(size); - if (dst == NULL) - return NULL; - - *dst = '\0'; - if (sudo_ldap_value_cat(dst, src, size) >= size) { - /* Should not be possible... */ - free(dst); - dst = NULL; - } - return dst; -} - /* * Check the netgroups list beginning at "start" for nesting. * Parent nodes with a memberNisNetgroup that match one of the diff --git a/plugins/sudoers/ldap_conf.c b/plugins/sudoers/ldap_conf.c index 2b566dd0e..12243cbc3 100644 --- a/plugins/sudoers/ldap_conf.c +++ b/plugins/sudoers/ldap_conf.c @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: ISC * - * Copyright (c) 2003-2020 Todd C. Miller + * Copyright (c) 2003-2023 Todd C. Miller * * This code is derived from software contributed by Aaron Spangler. * @@ -59,10 +59,6 @@ extern int ldapssl_set_strength(LDAP *ldap, int strength); # define LDAP_OPT_NETWORK_TIMEOUT LDAP_OPT_CONNECT_TIMEOUT #endif -#ifndef LDAP_OPT_SUCCESS -# define LDAP_OPT_SUCCESS LDAP_SUCCESS -#endif - #ifndef LDAPS_PORT # define LDAPS_PORT 636 #endif diff --git a/plugins/sudoers/ldap_util.c b/plugins/sudoers/ldap_util.c index a5ca40498..dfb74a6b0 100644 --- a/plugins/sudoers/ldap_util.c +++ b/plugins/sudoers/ldap_util.c @@ -632,3 +632,119 @@ sudo_ldap_new_member_all(void) m->type = ALL; debug_return_ptr(m); } + +/* + * Determine length of query value after escaping characters + * as per RFC 4515. + */ +size_t +sudo_ldap_value_len(const char *value) +{ + const char *s; + size_t len = 0; + + for (s = value; *s != '\0'; s++) { + switch (*s) { + case '\\': + case '(': + case ')': + case '*': + len += 2; + break; + } + } + len += (size_t)(s - value); + return len; +} + +/* + * Like strlcat() but escapes characters as per RFC 4515. + */ +size_t +sudo_ldap_value_cat(char *dst, const char *src, size_t size) +{ + char *d = dst; + const char *s = src; + size_t n = size; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = size - dlen; + + if (n == 0) + return dlen + strlen(s); + while (*s != '\0') { + switch (*s) { + case '\\': + if (n < 3) + goto done; + *d++ = '\\'; + *d++ = '5'; + *d++ = 'c'; + n -= 3; + break; + case '(': + if (n < 3) + goto done; + *d++ = '\\'; + *d++ = '2'; + *d++ = '8'; + n -= 3; + break; + case ')': + if (n < 3) + goto done; + *d++ = '\\'; + *d++ = '2'; + *d++ = '9'; + n -= 3; + break; + case '*': + if (n < 3) + goto done; + *d++ = '\\'; + *d++ = '2'; + *d++ = 'a'; + n -= 3; + break; + default: + if (n < 1) + goto done; + *d++ = *s; + n--; + break; + } + s++; + } +done: + *d = '\0'; + while (*s != '\0') + s++; + return dlen + (s - src); /* count does not include NUL */ +} + +/* + * Like strdup() but escapes characters as per RFC 4515. + */ +char * +sudo_ldap_value_dup(const char *src) +{ + char *dst; + size_t size; + + size = sudo_ldap_value_len(src) + 1; + dst = malloc(size); + if (dst == NULL) + return NULL; + + *dst = '\0'; + if (sudo_ldap_value_cat(dst, src, size) >= size) { + /* Should not be possible... */ + free(dst); + dst = NULL; + } + return dst; +} diff --git a/plugins/sudoers/sudo_ldap.h b/plugins/sudoers/sudo_ldap.h index 1c0035dbe..0fc839b35 100644 --- a/plugins/sudoers/sudo_ldap.h +++ b/plugins/sudoers/sudo_ldap.h @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: ISC * - * Copyright (c) 2018 Todd C. Miller + * Copyright (c) 2018, 2021, 2023 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,11 +19,41 @@ #ifndef SUDOERS_LDAP_H #define SUDOERS_LDAP_H +#ifndef LDAP_OPT_RESULT_CODE +# define LDAP_OPT_RESULT_CODE LDAP_OPT_ERROR_NUMBER +#endif + +#if !defined(LDAP_OPT_NETWORK_TIMEOUT) && defined(LDAP_OPT_CONNECT_TIMEOUT) +# define LDAP_OPT_NETWORK_TIMEOUT LDAP_OPT_CONNECT_TIMEOUT +#endif + +#ifndef LDAP_OPT_SUCCESS +# define LDAP_OPT_SUCCESS LDAP_SUCCESS +#endif + +#ifndef HAVE_LDAP_SEARCH_EXT_S +# ifdef HAVE_LDAP_SEARCH_ST +# define ldap_search_ext_s(a, b, c, d, e, f, g, h, i, j, k) \ + ldap_search_st(a, b, c, d, e, f, i, k) +# else +# define ldap_search_ext_s(a, b, c, d, e, f, g, h, i, j, k) \ + ldap_search_s(a, b, c, d, e, f, k) +# endif +#endif + +#define LDAP_FOREACH(var, ld, res) \ + for ((var) = ldap_first_entry((ld), (res)); \ + (var) != NULL; \ + (var) = ldap_next_entry((ld), (var))) + /* Iterators used by sudo_ldap_role_to_priv() to handle bervar ** or char ** */ typedef char * (*sudo_ldap_iter_t)(void **); /* ldap_util.c */ bool sudo_ldap_is_negated(char **valp); +size_t sudo_ldap_value_len(const char *value); +size_t sudo_ldap_value_cat(char *dst, const char *src, size_t size); +char *sudo_ldap_value_dup(const char *src); int sudo_ldap_parse_option(char *optstr, char **varp, char **valp); struct privilege *sudo_ldap_role_to_priv(const char *cn, void *hosts, void *runasusers, void *runasgroups, void *cmnds, void *opts, const char *notbefore, const char *notafter, bool warnings, bool store_options, sudo_ldap_iter_t iter); struct member *sudo_ldap_new_member_all(void);