Hi

As discussed on irc, an updated version with reallocarray is attached.

Philipp
From 005b65c90f6017225c96b2769a6531057a337e70 Mon Sep 17 00:00:00 2001
From: Philipp Takacs <phil...@bureaucracy.de>
Date: Wed, 31 Jan 2024 17:50:52 +0100
Subject: [PATCH 2/5] table-ldap handle more then one result

---
 configure.ac                          |   2 +-
 extras/tables/table-ldap/table_ldap.c | 105 ++++++++++++++++++--------
 2 files changed, 73 insertions(+), 34 deletions(-)

diff --git a/configure.ac b/configure.ac
index 14608b1..181a974 100644
--- a/configure.ac
+++ b/configure.ac
@@ -297,7 +297,7 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
 	;;
 *-*-linux* | *-gnu* | *-k*bsd*-gnu* )
 	use_pie=auto
-	CFLAGS="$CFLAGS -D_BSD_SOURCE"
+	CFLAGS="$CFLAGS -D_DEFAULT_SOURCE"
 	;;
 *-*-netbsd*)
 	if test "x$withval" != "xno" ; then
diff --git a/extras/tables/table-ldap/table_ldap.c b/extras/tables/table-ldap/table_ldap.c
index 3107d44..921935e 100644
--- a/extras/tables/table-ldap/table_ldap.c
+++ b/extras/tables/table-ldap/table_ldap.c
@@ -63,6 +63,10 @@ struct query {
 	int	 attrn;
 };
 
+struct query_result {
+	char	**v[MAX_ATTRS];
+};
+
 static int ldap_run_query(int type, const char *, char *, size_t);
 
 static char *config, *url, *username, *password, *basedn, *ca_file;
@@ -397,12 +401,25 @@ table_ldap_lookup(int service, struct dict *params, const char *key, char *dst,
 }
 
 static int
-ldap_query(const char *filter, const char *key, char **attributes, char ***outp, size_t n)
+realloc_results(struct query_result **r, size_t *num)
+{
+	struct query_result *new;
+	size_t newsize = MAX(1, (*num)*2);
+	if ((new = reallocarray(*r, newsize, sizeof(**r))) == NULL)
+		return 0;
+	*num = newsize;
+	*r = new;
+	return 1;
+}
+
+static int
+ldap_query(const char *filter, const char *key, char **attributes, struct query_result **results, size_t n)
 {
 	struct aldap_message		*m = NULL;
 	struct aldap_page_control	*pg = NULL;
-	int				 ret, found;
-	size_t				 i;
+	struct query_result		*res = NULL;
+	int				 ret;
+	size_t				 i, j, found = 0, numresults = 0;
 	char				 basedn__[MAX_LDAP_BASELEN];
 	char				 filter__[MAX_LDAP_FILTERLEN];
 	char				 key__[MAX_LDAP_IDENTIFIER];
@@ -413,12 +430,11 @@ ldap_query(const char *filter, const char *key, char **attributes, char ***outp,
 		return -1;
 	if (strlcpy(key__, key, sizeof key__) >= sizeof key__)
 		return -1;
-	found = -1;
 	do {
-		if ((ret = aldap_search(aldap, basedn__, LDAP_SCOPE_SUBTREE,
-		    filter__, key__, attributes, 0, 0, 0, pg)) == -1) {
-			log_debug("ret=%d", ret);
-			return -1;
+		ret = -1;
+		if (aldap_search(aldap, basedn__, LDAP_SCOPE_SUBTREE,
+		    filter__, key__, attributes, 0, 0, 0, pg) == -1) {
+			goto error;
 		}
 		if (pg != NULL) {
 			aldap_freepage(pg);
@@ -433,26 +449,40 @@ ldap_query(const char *filter, const char *key, char **attributes, char ***outp,
 					pg = m->page;
 				aldap_freemsg(m);
 				m = NULL;
-				if (found == -1)
-					found = 0;
+				ret = 0;
 				break;
 			}
 			if (m->message_type != LDAP_RES_SEARCH_ENTRY)
 				goto error;
 
-			found = 1;
+			if (found >= numresults) {
+				if (!realloc_results(&res, &numresults)) {
+					goto error;
+				}
+			}
+			memset(&res[found], 0, sizeof(res[found]));
 			for (i = 0; i < n; ++i)
-				if (aldap_match_attr(m, attributes[i], &outp[i]) != 1)
+				if (aldap_match_attr(m, attributes[i], &res[found].v[i]) != 1)
 					goto error;
 			aldap_freemsg(m);
 			m = NULL;
+			found++;
 		}
 	} while (pg != NULL);
 
+	if (ret == -1)
+		goto error;
 	ret = found;
+	*results = res;
 	goto end;
 
 error:
+	for (i = 0; i < found; i++) {
+		for (j = 0; j < n; j++) {
+			aldap_free_attr(res[i].v[j]);
+		}
+	}
+	free(res);
 	ret = -1;
 
 end:
@@ -465,9 +495,10 @@ end:
 static int
 ldap_run_query(int type, const char *key, char *dst, size_t sz)
 {
-	struct query	 *q;
-	char		**res[4], filter[MAX_LDAP_FILTERLEN];
-	int		  ret, i;
+	struct query		*q;
+	struct query_result	*res = NULL;
+	char			 filter[MAX_LDAP_FILTERLEN];
+	int			 ret, i, j;
 
 	switch (type) {
 	case K_ALIAS:		q = &queries[LDAP_ALIAS];	break;
@@ -495,39 +526,40 @@ ldap_run_query(int type, const char *key, char *dst, size_t sz)
 		return -1;
 	}
 
-	memset(res, 0, sizeof(res));
-	ret = ldap_query(filter, key, q->attrs, res, q->attrn);
+	ret = ldap_query(filter, key, q->attrs, &res, q->attrn);
 	if (ret <= 0 || dst == NULL)
 		goto end;
 
 	switch (type) {
 
 	case K_ALIAS:
+	case K_MAILADDRMAP:
 		memset(dst, 0, sz);
-		for (i = 0; res[0][i]; i++) {
-			if (i && strlcat(dst, ", ", sz) >= sz) {
-				ret = -1;
-				break;
-			}
-			if (strlcat(dst, res[0][i], sz) >= sz) {
-				ret = -1;
-				break;
+		for (j = 0; j < ret; j++) {
+			for (i = 0; res[j].v[0][i]; i++) {
+				if ((i || j) && strlcat(dst, ", ", sz) >= sz) {
+					ret = -1;
+					break;
+				}
+				if (strlcat(dst, res[j].v[0][i], sz) >= sz) {
+					ret = -1;
+					break;
+				}
 			}
 		}
 		break;
 	case K_DOMAIN:
 	case K_MAILADDR:
-	case K_MAILADDRMAP:
-		if (strlcpy(dst, res[0][0], sz) >= sz)
+		if (strlcpy(dst, res[0].v[0][0], sz) >= sz)
 			ret = -1;
 		break;
 	case K_CREDENTIALS:
-		if (snprintf(dst, sz, "%s:%s", res[0][0], res[1][0]) >= (int)sz)
+		if (snprintf(dst, sz, "%s:%s", res[0].v[0][0], res[0].v[1][0]) >= (int)sz)
 			ret = -1;
 		break;
 	case K_USERINFO:
-		if (snprintf(dst, sz, "%s:%s:%s", res[0][0], res[1][0],
-		    res[2][0]) >= (int)sz)
+		if (snprintf(dst, sz, "%s:%s:%s", res[0].v[0][0], res[0].v[1][0],
+		    res[0].v[2][0]) >= (int)sz)
 			ret = -1;
 		break;
 	default:
@@ -539,10 +571,17 @@ ldap_run_query(int type, const char *key, char *dst, size_t sz)
 		log_warnx("warn: could not format result");
 
 end:
-	for (i = 0; i < q->attrn; ++i)
-		if (res[i])
-			aldap_free_attr(res[i]);
+	for (j = 0; j < ret; ++j) {
+		for (i = 0; i < q->attrn; ++i) {
+			if (res[j].v[i]) {
+				aldap_free_attr(res[j].v[i]);
+			}
+		}
+	}
+	free(res);
 
+	if (ret > 0)
+		ret = 1;
 	return ret;
 }
 
-- 
2.39.2

Reply via email to