[2024-02-04 10:50] Omar Polo <o...@omarpolo.com> > Some comments inline. > > > 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]; > > +}; > > There are too many level of pointers for my taste, and too much shared > state passed around.
Yes this had been also a bit my problem, I belive I found now a sane solution. Pass a pointer-pointer to ldap_query() and set the pointer when there is no error. > For starters, why don't make this struct query_result more useful? It > could be a container for the N results of the query, making the > management more easy. Something like (with better naming) > > struct query_hit { > char **v[MAX_ATTRS]; > }; > > struct query_result { > struct query_hit *res; > size_t len; > size_t cap; > }; > > At that point we can declare query_result on the stack in ldap_run_query > and pass around only one pointer instead of a two-level thingy. I understand the idea, but im not convicend it is currently usefull. Because currently the result is only allocated in ldap_query and used/freed in ldap_run_query. So putting the len and cap variable in a struct only adds a level of indirection without a benetfit. > > 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; > > I like this change. it's easier to reason about this stuff if we assume > ret is -1 and set it to 0 or 1 only when we're about to return. Problem is, there is still a bug in there. ret must be set to -1 at each itteration of the do-while loop. A fixed version is attached. But in general this make the code more readable. > > 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); > > don't we need to aldap_free_attr() too? Yes, I forgott the aldap_free_attr(). > also, now this error label could go away entirely, we can just goto end > and check there if ret == -1 and free the results. This can be done in > a separate diff however, earlier or before this one, as you prefer. I have attached a patch for this. Philipp
From c75c608a764213a1fa691a7b1f1ab9f3b98f2627 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/3] table-ldap handle more then one result --- extras/tables/table-ldap/table_ldap.c | 105 ++++++++++++++++++-------- 1 file changed, 72 insertions(+), 33 deletions(-) diff --git a/extras/tables/table-ldap/table_ldap.c b/extras/tables/table-ldap/table_ldap.c index 3107d44..354e09d 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 = 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; + 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
From d1ec83464689a1b927bf08a5de758c54ab04f688 Mon Sep 17 00:00:00 2001 From: Philipp Takacs <phil...@bureaucracy.de> Date: Sun, 4 Feb 2024 15:22:58 +0100 Subject: [PATCH 3/3] table-ldap make error handle more readable --- extras/tables/table-ldap/table_ldap.c | 34 ++++++++++++--------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/extras/tables/table-ldap/table_ldap.c b/extras/tables/table-ldap/table_ldap.c index 354e09d..8b2ffa9 100644 --- a/extras/tables/table-ldap/table_ldap.c +++ b/extras/tables/table-ldap/table_ldap.c @@ -434,7 +434,7 @@ ldap_query(const char *filter, const char *key, char **attributes, struct query_ ret = -1; if (aldap_search(aldap, basedn__, LDAP_SCOPE_SUBTREE, filter__, key__, attributes, 0, 0, 0, pg) == -1) { - goto error; + goto end; } if (pg != NULL) { aldap_freepage(pg); @@ -443,7 +443,7 @@ ldap_query(const char *filter, const char *key, char **attributes, struct query_ while ((m = aldap_parse(aldap)) != NULL) { if (aldap->msgid != m->msgid) - goto error; + goto end; if (m->message_type == LDAP_RES_SEARCH_RESULT) { if (m->page != NULL && m->page->cookie_len) pg = m->page; @@ -453,39 +453,35 @@ ldap_query(const char *filter, const char *key, char **attributes, struct query_ break; } if (m->message_type != LDAP_RES_SEARCH_ENTRY) - goto error; + goto end; if (found >= numresults) { if (!realloc_results(&res, &numresults)) { - goto error; + goto end; } } memset(&res[found], 0, sizeof(res[found])); for (i = 0; i < n; ++i) if (aldap_match_attr(m, attributes[i], &res[found].v[i]) != 1) - goto error; + goto end; 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]); +end: + if (ret == -1) { + for (i = 0; i < found; i++) { + for (j = 0; j < n; j++) { + aldap_free_attr(res[i].v[j]); + } } + free(res); + } else { + ret = found; + *results = res; } - free(res); - ret = -1; - -end: if (m) aldap_freemsg(m); log_debug("debug: table_ldap: ldap_query: filter=%s, ret=%d", filter, ret); -- 2.39.2