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

Reply via email to