I found a bug in my patch, break the reconnect logic again. [2024-02-01 15:40] Philipp <phil...@bureaucracy.de> > [...] > @@ -413,12 +429,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; > + ret = -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; > + goto error;
Here I missed to remove the 'ret =', this will cause a wrong return value when the connection is lost. An updated patch is attached. > } > if (pg != NULL) { > aldap_freepage(pg);
From 4a997162811d6b43a748af1cfb783bad6177dca8 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/2] table-ldap handle more then one result --- extras/tables/table-ldap/table_ldap.c | 98 +++++++++++++++++---------- 1 file changed, 64 insertions(+), 34 deletions(-) diff --git a/extras/tables/table-ldap/table_ldap.c b/extras/tables/table-ldap/table_ldap.c index 3107d44..7f93fa6 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,24 @@ 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 = realloc(*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; + int ret; + size_t i, found = 0, numresults = 0; char basedn__[MAX_LDAP_BASELEN]; char filter__[MAX_LDAP_FILTERLEN]; char key__[MAX_LDAP_IDENTIFIER]; @@ -413,12 +429,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; + ret = -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; + 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 +448,32 @@ 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(results, &numresults)) { + goto error; + } + } for (i = 0; i < n; ++i) - if (aldap_match_attr(m, attributes[i], &outp[i]) != 1) + if (aldap_match_attr(m, attributes[i], &(*results)[found].v[i]) != 1) goto error; aldap_freemsg(m); m = NULL; + found++; } } while (pg != NULL); - ret = found; + if (found) + ret = found; goto end; error: + free(*results); ret = -1; end: @@ -465,9 +486,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 +517,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 +562,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