*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
/* Many thanks to Stuart Lynne for contributing the original code for this
than the host name + "ldaps:///" plus : and a port number, say 20 + the
length of the host name. What we get should accommodate both, easily. */
- uschar *shost = (host == NULL)? US"" : host;
- uschar *init_url = store_get(20 + 3 * Ustrlen(shost));
- uschar *init_ptr;
+ uschar * shost = host ? host : US"";
+ rmark reset_point = store_mark();
+ gstring * g;
/* Handle connection via Unix socket ("ldapi"). We build a basic LDAP URI to
contain the path name, with slashes escaped as %2F. */
if (ldapi)
{
- int ch;
- init_ptr = init_url + 8;
- Ustrcpy(init_url, "ldapi://");
- while ((ch = *shost++))
- if (ch == '/')
- { Ustrncpy(init_ptr, "%2F", 3); init_ptr += 3; }
- else
- *init_ptr++ = ch;
- *init_ptr = 0;
+ g = string_catn(NULL, US"ldapi://", 8);
+ for (uschar ch; (ch = *shost); shost++)
+ g = ch == '/' ? string_catn(g, US"%2F", 3) : string_catn(g, shost, 1);
}
/* This is not an ldapi call. Just build a URI with the protocol type, host
else
{
- init_ptr = Ustrchr(ldap_url, '/');
- Ustrncpy(init_url, ldap_url, init_ptr - ldap_url);
- init_ptr = init_url + (init_ptr - ldap_url);
- sprintf(CS init_ptr, "//%s:%d/", shost, port);
+ uschar * init_ptr = Ustrchr(ldap_url, '/');
+ g = string_catn(NULL, ldap_url, init_ptr - ldap_url);
+ g = string_fmt_append(g, "//%s:%d/", shost, port);
}
+ string_from_gstring(g);
/* Call ldap_initialize() and check the result */
- DEBUG(D_lookup) debug_printf_indent("ldap_initialize with URL %s\n", init_url);
- if ((rc = ldap_initialize(&ld, CS init_url)) != LDAP_SUCCESS)
+ DEBUG(D_lookup) debug_printf_indent("ldap_initialize with URL %s\n", g->s);
+ if ((rc = ldap_initialize(&ld, CS g->s)) != LDAP_SUCCESS)
{
*errmsg = string_sprintf("ldap_initialize: (error %d) URL \"%s\"\n",
- rc, init_url);
+ rc, g->s);
goto RETURN_ERROR;
}
- store_reset(init_url); /* Might as well save memory when we can */
+ store_reset(reset_point); /* Might as well save memory when we can */
/* ------------------------- Not OpenLDAP ---------------------- */
/* Now add this connection to the chain of cached connections */
- lcp = store_get(sizeof(LDAP_CONNECTION));
- lcp->host = (host == NULL)? NULL : string_copy(host);
+ lcp = store_get(sizeof(LDAP_CONNECTION), FALSE);
+ lcp->host = host ? string_copy(host) : NULL;
lcp->bound = FALSE;
lcp->user = NULL;
lcp->password = NULL;
if (rescount < 1)
{
- *errmsg = string_sprintf("LDAP search: no results");
+ *errmsg = US"LDAP search: no results";
error_yield = FAIL;
goto RETURN_ERROR_BREAK;
}
uschar *user = NULL;
uschar *password = NULL;
uschar *local_servers = NULL;
-uschar *server;
const uschar *list;
-uschar buffer[512];
while (isspace(*url)) url++;
while (strncmpic(url, US"ldap", 4) != 0)
{
const uschar *name = url;
- while (*url != 0 && *url != '=') url++;
+ while (*url && *url != '=') url++;
if (*url == '=')
{
int namelen;
else if (strcmpic(value, US"nofollow") == 0) referrals = LDAP_OPT_OFF;
else
{
+ *errmsg = US"LDAP option REFERRALS is not \"follow\" or \"nofollow\"";
DEBUG(D_lookup) debug_printf_indent("%s\n", *errmsg);
return DEFER;
}
that is needed when the DN is used as a base DN in a query. Sigh. This is all
far too complicated. */
-if (user != NULL)
+if (user)
{
uschar *t = user;
for (uschar * s = user; *s != 0; s++)
DEBUG(D_lookup)
debug_printf_indent("LDAP parameters: user=%s pass=%s size=%d time=%d connect=%d "
"dereference=%d referrals=%s\n", user, password, sizelimit, timelimit,
- tcplimit, dereference, (referrals == LDAP_OPT_ON)? "on" : "off");
+ tcplimit, dereference, referrals == LDAP_OPT_ON ? "on" : "off");
/* If the request is just to check authentication, some credentials must
be given. The password must not be empty because LDAP binds with an empty
if (search_type == SEARCH_LDAP_AUTH)
{
- if (user == NULL || password == NULL)
+ if (!user || !password)
{
*errmsg = US"ldapauth lookups must specify the username and password";
return DEFER;
}
- if (password[0] == 0)
+ if (!*password)
{
DEBUG(D_lookup) debug_printf_indent("Empty password: ldapauth returns FAIL\n");
return FAIL;
/* No default servers, or URL contains a server name: just one attempt */
-if ((eldap_default_servers == NULL && local_servers == NULL) || p[3] != '/')
- {
+if (!eldap_default_servers && !local_servers || p[3] != '/')
return perform_ldap_search(url, NULL, 0, search_type, res, errmsg,
&defer_break, user, password, sizelimit, timelimit, tcplimit, dereference,
referrals);
- }
-/* Loop through the default servers until OK or FAIL. Use local_servers list
- * if defined in the lookup, otherwise use the global default list */
-list = (local_servers == NULL) ? eldap_default_servers : local_servers;
-while ((server = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
+/* Loop through the servers until OK or FAIL. Use local_servers list
+if defined in the lookup, otherwise use the global default list */
+
+list = local_servers ? local_servers : eldap_default_servers;
+for (uschar * server; server = string_nextinlist(&list, &sep, NULL, 0); )
{
- int rc;
- int port = 0;
+ int rc, port = 0;
uschar *colon = Ustrchr(server, ':');
- if (colon != NULL)
+ if (colon)
{
*colon = 0;
port = Uatoi(colon+1);
The handle and filename arguments are not used. */
static int
-eldap_find(void *handle, uschar *filename, const uschar *ldap_url, int length,
- uschar **result, uschar **errmsg, uint *do_cache)
+eldap_find(void * handle, const uschar * filename, const uschar * ldap_url,
+ int length, uschar ** result, uschar ** errmsg, uint * do_cache,
+ const uschar * opts)
{
-/* Keep picky compilers happy */
-do_cache = do_cache;
return(control_ldap_search(ldap_url, SEARCH_LDAP_SINGLE, result, errmsg));
}
static int
-eldapm_find(void *handle, uschar *filename, const uschar *ldap_url, int length,
- uschar **result, uschar **errmsg, uint *do_cache)
+eldapm_find(void * handle, const uschar * filename, const uschar * ldap_url,
+ int length, uschar ** result, uschar ** errmsg, uint * do_cache,
+ const uschar * opts)
{
-/* Keep picky compilers happy */
-do_cache = do_cache;
return(control_ldap_search(ldap_url, SEARCH_LDAP_MULTIPLE, result, errmsg));
}
static int
-eldapdn_find(void *handle, uschar *filename, const uschar *ldap_url, int length,
- uschar **result, uschar **errmsg, uint *do_cache)
+eldapdn_find(void * handle, const uschar * filename, const uschar * ldap_url,
+ int length, uschar ** result, uschar ** errmsg, uint * do_cache,
+ const uschar * opts)
{
-/* Keep picky compilers happy */
-do_cache = do_cache;
return(control_ldap_search(ldap_url, SEARCH_LDAP_DN, result, errmsg));
}
int
-eldapauth_find(void *handle, uschar *filename, const uschar *ldap_url, int length,
- uschar **result, uschar **errmsg, uint *do_cache)
+eldapauth_find(void * handle, const uschar * filename, const uschar * ldap_url,
+ int length, uschar ** result, uschar ** errmsg, uint * do_cache)
{
-/* Keep picky compilers happy */
-do_cache = do_cache;
return(control_ldap_search(ldap_url, SEARCH_LDAP_AUTH, result, errmsg));
}
/* See local README for interface description. */
static void *
-eldap_open(uschar *filename, uschar **errmsg)
+eldap_open(const uschar * filename, uschar ** errmsg)
{
return (void *)(1); /* Just return something non-null */
}
static void
eldap_tidy(void)
{
-LDAP_CONNECTION *lcp = NULL;
eldap_dn = NULL;
-while ((lcp = ldap_connections) != NULL)
+for (LDAP_CONNECTION *lcp; lcp = ldap_connections; ldap_connections = lcp->next)
{
- DEBUG(D_lookup) debug_printf_indent("unbind LDAP connection to %s:%d\n", lcp->host,
- lcp->port);
- if(lcp->bound == TRUE)
- ldap_unbind(lcp->ld);
- ldap_connections = lcp->next;
+ DEBUG(D_lookup) debug_printf_indent("unbind LDAP connection to %s:%d\n",
+ lcp->host, lcp->port);
+ if(lcp->bound) ldap_unbind(lcp->ld);
}
}
/* Get sufficient store to hold the quoted string */
-t = quoted = store_get(len + count + 1);
+t = quoted = store_get(len + count + 1, is_tainted(s));
/* Handle plain quote_ldap */
{
if (Ustrchr(LDAP_DN_QUOTE, c) != NULL)
{
- Ustrncpy(t, "%5C", 3); /* insert \ where needed */
+ Ustrncpy(t, US"%5C", 3); /* insert \ where needed */
t += 3; /* fall through to check URL */
}
if (Ustrchr(URL_NONQUOTE, c) == NULL) /* e.g. ] => %5D */
while (*ss++ != 0)
{
- Ustrncpy(t, "%5C%20", 6);
+ Ustrncpy(t, US"%5C%20", 6);
t += 6;
}
}
static lookup_info ldap_lookup_info = {
- US"ldap", /* lookup name */
- lookup_querystyle, /* query-style lookup */
- eldap_open, /* open function */
- NULL, /* check function */
- eldap_find, /* find function */
- NULL, /* no close function */
- eldap_tidy, /* tidy function */
- eldap_quote, /* quoting function */
- ldap_version_report /* version reporting */
+ .name = US"ldap", /* lookup name */
+ .type = lookup_querystyle, /* query-style lookup */
+ .open = eldap_open, /* open function */
+ .check = NULL, /* check function */
+ .find = eldap_find, /* find function */
+ .close = NULL, /* no close function */
+ .tidy = eldap_tidy, /* tidy function */
+ .quote = eldap_quote, /* quoting function */
+ .version_report = ldap_version_report /* version reporting */
};
static lookup_info ldapdn_lookup_info = {
- US"ldapdn", /* lookup name */
- lookup_querystyle, /* query-style lookup */
- eldap_open, /* sic */ /* open function */
- NULL, /* check function */
- eldapdn_find, /* find function */
- NULL, /* no close function */
- eldap_tidy, /* sic */ /* tidy function */
- eldap_quote, /* sic */ /* quoting function */
- NULL /* no version reporting (redundant) */
+ .name = US"ldapdn", /* lookup name */
+ .type = lookup_querystyle, /* query-style lookup */
+ .open = eldap_open, /* sic */ /* open function */
+ .check = NULL, /* check function */
+ .find = eldapdn_find, /* find function */
+ .close = NULL, /* no close function */
+ .tidy = eldap_tidy, /* sic */ /* tidy function */
+ .quote = eldap_quote, /* sic */ /* quoting function */
+ .version_report = NULL /* no version reporting (redundant) */
};
static lookup_info ldapm_lookup_info = {
- US"ldapm", /* lookup name */
- lookup_querystyle, /* query-style lookup */
- eldap_open, /* sic */ /* open function */
- NULL, /* check function */
- eldapm_find, /* find function */
- NULL, /* no close function */
- eldap_tidy, /* sic */ /* tidy function */
- eldap_quote, /* sic */ /* quoting function */
- NULL /* no version reporting (redundant) */
+ .name = US"ldapm", /* lookup name */
+ .type = lookup_querystyle, /* query-style lookup */
+ .open = eldap_open, /* sic */ /* open function */
+ .check = NULL, /* check function */
+ .find = eldapm_find, /* find function */
+ .close = NULL, /* no close function */
+ .tidy = eldap_tidy, /* sic */ /* tidy function */
+ .quote = eldap_quote, /* sic */ /* quoting function */
+ .version_report = NULL /* no version reporting (redundant) */
};
#ifdef DYNLOOKUP