A I forgott the patch. [2024-01-27 12:11] Philipp <phil...@bureaucracy.de> > I have noticed that the table-ldap uses printf() to replace the '%s' of > the filter with the search key. This has some problems. The biggest one > is you can use the key only once in the filter. So a filter like: > > > (|(mail=%s)(uid=%s)) > > doesn't work. > > To fix this I have moved the replacement to the parsval function of aldap. > > Philipp
From f35feed68305472168ea3c702c20765fa9e98812 Mon Sep 17 00:00:00 2001 From: Philipp Takacs <phil...@bureaucracy.de> Date: Tue, 23 Jan 2024 22:06:24 +0100 Subject: [PATCH] table-ldap do the string replace in the ldap parser
This allows filter which uses the key multible times. I.e: (|(mail=%s)(username=%s)) --- extras/tables/table-ldap/aldap.c | 59 ++++++++++++++++++++------- extras/tables/table-ldap/aldap.h | 2 +- extras/tables/table-ldap/table_ldap.c | 11 +++-- 3 files changed, 52 insertions(+), 20 deletions(-) diff --git a/extras/tables/table-ldap/aldap.c b/extras/tables/table-ldap/aldap.c index 011a820..da63817 100644 --- a/extras/tables/table-ldap/aldap.c +++ b/extras/tables/table-ldap/aldap.c @@ -31,12 +31,12 @@ #define ALDAP_VERSION 3 static struct ber_element *ldap_parse_search_filter(struct ber_element *, - char *); + char *, const char *); static struct ber_element *ldap_do_parse_search_filter( - struct ber_element *, char **); + struct ber_element *, char **, const char *); char **aldap_get_stringset(struct ber_element *); char *utoa(char *); -char *parseval(char *, size_t); +char *parseval(char *, size_t, const char *); int aldap_create_page_control(struct ber_element *, int, struct aldap_page_control *); @@ -146,7 +146,7 @@ fail: int aldap_search(struct aldap *ldap, char *basedn, enum scope scope, char *filter, - char **attrs, int typesonly, int sizelimit, int timelimit, + const char *key, char **attrs, int typesonly, int sizelimit, int timelimit, struct aldap_page_control *page) { struct ber_element *root = NULL, *ber, *c; @@ -171,7 +171,7 @@ aldap_search(struct aldap *ldap, char *basedn, enum scope scope, char *filter, goto fail; } - if ((ber = ldap_parse_search_filter(ber, filter)) == NULL) { + if ((ber = ldap_parse_search_filter(ber, filter, key)) == NULL) { ldap->err = ALDAP_ERR_PARSER_ERROR; goto fail; } @@ -736,7 +736,7 @@ aldap_get_stringset(struct ber_element *elm) * NULL, parse failed */ static struct ber_element * -ldap_parse_search_filter(struct ber_element *ber, char *filter) +ldap_parse_search_filter(struct ber_element *ber, char *filter, const char *key) { struct ber_element *elm; char *cp; @@ -748,7 +748,7 @@ ldap_parse_search_filter(struct ber_element *ber, char *filter) return (NULL); } - if ((elm = ldap_do_parse_search_filter(ber, &cp)) == NULL) + if ((elm = ldap_do_parse_search_filter(ber, &cp, key)) == NULL) return (NULL); if (*cp != '\0') { @@ -778,7 +778,7 @@ ldap_parse_search_filter(struct ber_element *ber, char *filter) * */ static struct ber_element * -ldap_do_parse_search_filter(struct ber_element *prev, char **cpp) +ldap_do_parse_search_filter(struct ber_element *prev, char **cpp, const char *key) { struct ber_element *elm, *root = NULL; char *attr_desc, *attr_val, *parsed_val, *cp; @@ -810,7 +810,7 @@ ldap_do_parse_search_filter(struct ber_element *prev, char **cpp) while (*cp == '(') { if ((elm = - ldap_do_parse_search_filter(elm, &cp)) == NULL) + ldap_do_parse_search_filter(elm, &cp, key)) == NULL) goto bad; } @@ -824,7 +824,7 @@ ldap_do_parse_search_filter(struct ber_element *prev, char **cpp) ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_NOT); cp++; /* now points to sub-filter */ - if (ldap_do_parse_search_filter(root, &cp) == NULL) + if (ldap_do_parse_search_filter(root, &cp, key) == NULL) goto bad; if (*cp != ')') /* trailing `)` of filter */ @@ -915,7 +915,7 @@ ldap_do_parse_search_filter(struct ber_element *prev, char **cpp) else type = LDAP_FILT_SUBS_ANY; - if ((parsed_val = parseval(attr_val, len)) == + if ((parsed_val = parseval(attr_val, len, key)) == NULL) goto callfail; elm = ber_add_nstring(elm, parsed_val, @@ -930,7 +930,7 @@ ldap_do_parse_search_filter(struct ber_element *prev, char **cpp) break; } - if ((parsed_val = parseval(attr_val, len)) == NULL) + if ((parsed_val = parseval(attr_val, len, key)) == NULL) goto callfail; elm = ber_add_nstring(elm, parsed_val, strlen(parsed_val)); free(parsed_val); @@ -1218,13 +1218,13 @@ utoa(char *u) * the argument u should be a NULL terminated sequence of ASCII bytes. */ char * -parseval(char *p, size_t len) +parseval(char *p, size_t len, const char *key) { char hex[3]; char *cp = p, *buffer, *newbuffer; - size_t size, newsize, i, j; + size_t size, newsize, i, j, keylen; - size = 50; + size = len; if ((buffer = calloc(1, size)) == NULL) return NULL; @@ -1243,12 +1243,41 @@ parseval(char *p, size_t len) (void)strlcpy(hex, cp + j + 1, sizeof(hex)); buffer[i] = (char)strtoumax(hex, NULL, 16); j += 3; + } else if (cp[j] == '%') { + switch (cp[j + 1]) { + case '%': + buffer[i] = '%'; + j += 2; + break; + case 's': + if (!key) { + free(buffer); + return NULL; + } + keylen = strlen(key); + newsize = size + keylen; + if ((newbuffer = realloc(buffer, newsize)) == NULL) { + free(buffer); + return NULL; + } + buffer = newbuffer; + size = newsize; + memcpy(buffer + i, key, keylen); + i += keylen - 1; + j += 2; + break; + default: + buffer[i] = '%'; + j++; + break; + } } else { buffer[i] = cp[j]; j++; } } + buffer[i] = 0; return buffer; } diff --git a/extras/tables/table-ldap/aldap.h b/extras/tables/table-ldap/aldap.h index 7217634..6284d3c 100644 --- a/extras/tables/table-ldap/aldap.h +++ b/extras/tables/table-ldap/aldap.h @@ -193,7 +193,7 @@ void aldap_freemsg(struct aldap_message *); int aldap_bind(struct aldap *, char *, char *); int aldap_unbind(struct aldap *); -int aldap_search(struct aldap *, char *, enum scope, char *, char **, int, int, int, struct aldap_page_control *); +int aldap_search(struct aldap *, char *, enum scope, char *, const char *, char **, int, int, int, struct aldap_page_control *); int aldap_get_errno(struct aldap *, const char **); int aldap_get_resultcode(struct aldap_message *); diff --git a/extras/tables/table-ldap/table_ldap.c b/extras/tables/table-ldap/table_ldap.c index 0f25c60..5b829b5 100644 --- a/extras/tables/table-ldap/table_ldap.c +++ b/extras/tables/table-ldap/table_ldap.c @@ -340,7 +340,7 @@ table_ldap_lookup(int service, struct dict *params, const char *key, char *dst, } static int -ldap_query(const char *filter, char **attributes, char ***outp, size_t n) +ldap_query(const char *filter, const char *key, char **attributes, char ***outp, size_t n) { struct aldap_message *m = NULL; struct aldap_page_control *pg = NULL; @@ -348,15 +348,18 @@ ldap_query(const char *filter, char **attributes, char ***outp, size_t n) size_t i; char basedn__[MAX_LDAP_BASELEN]; char filter__[MAX_LDAP_FILTERLEN]; + char key__[MAX_LDAP_IDENTIFIER]; if (strlcpy(basedn__, basedn, sizeof basedn__) >= sizeof basedn__) return -1; if (strlcpy(filter__, filter, sizeof filter__) >= sizeof filter__) return -1; + if (strlcpy(key__, key, sizeof key__) >= sizeof key__) + return -1; found = 0; do { if ((ret = aldap_search(aldap, basedn__, LDAP_SCOPE_SUBTREE, - filter__, NULL, 0, 0, 0, pg)) == -1) { + filter__, key__, NULL, 0, 0, 0, pg)) == -1) { log_debug("ret=%d", ret); return -1; } @@ -420,14 +423,14 @@ ldap_run_query(int type, const char *key, char *dst, size_t sz) return -1; } - if (snprintf(filter, sizeof(filter), q->filter, key) + if (snprintf(filter, sizeof(filter), "%s", q->filter) >= (int)sizeof(filter)) { log_warnx("warn: filter too large"); return -1; } memset(res, 0, sizeof(res)); - ret = ldap_query(filter, q->attrs, res, q->attrn); + ret = ldap_query(filter, key, q->attrs, res, q->attrn); if (ret <= 0 || dst == NULL) goto end; -- 2.39.2