X-Git-Url: https://vcs.fsf.org/?p=exim.git;a=blobdiff_plain;f=src%2Fsrc%2Flookups%2Fldap.c;h=b9a52d2512ce0677ccafe4f6cc642be426c70090;hp=f77318626aabff64db75d9b46188f678c9c657a6;hb=d447dbd160a0fb503ed1e763f3f23d28744b6ddd;hpb=d7978c0f8af20ff4c3f770589b1bb81568aecff3 diff --git a/src/src/lookups/ldap.c b/src/src/lookups/ldap.c index f77318626..b9a52d251 100644 --- a/src/src/lookups/ldap.c +++ b/src/src/lookups/ldap.c @@ -163,8 +163,8 @@ int rescount = 0; BOOL attribute_found = FALSE; BOOL ldapi = FALSE; -DEBUG(D_lookup) - debug_printf("perform_ldap_search: ldap%s URL = \"%s\" server=%s port=%d " +DEBUG(D_lookup) debug_printf_indent("perform_ldap_search:" + " ldap%s URL = \"%s\" server=%s port=%d " "sizelimit=%d timelimit=%d tcplimit=%d\n", search_type == SEARCH_LDAP_MULTIPLE ? "m" : search_type == SEARCH_LDAP_DN ? "dn" : @@ -207,7 +207,7 @@ else port = ludp->lud_port; } -DEBUG(D_lookup) debug_printf("after ldap_url_parse: host=%s port=%d\n", +DEBUG(D_lookup) debug_printf_indent("after ldap_url_parse: host=%s port=%d\n", host, port); if (port == 0) port = LDAP_PORT; /* Default if none given */ @@ -301,24 +301,18 @@ if (!lcp) 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 @@ -326,22 +320,22 @@ if (!lcp) 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("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 ---------------------- */ @@ -409,7 +403,7 @@ if (!lcp) ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, (void *)&eldap_version); #endif - DEBUG(D_lookup) debug_printf("initialized for LDAP (v%d) server %s%s\n", + DEBUG(D_lookup) debug_printf_indent("initialized for LDAP (v%d) server %s%s\n", eldap_version, host, porttext); /* If not using ldapi and TLS is available, set appropriate TLS options: hard @@ -429,9 +423,9 @@ if (!lcp) : Ustrcmp(eldap_require_cert, "try") == 0 ? LDAP_OPT_X_TLS_TRY : LDAP_OPT_X_TLS_NEVER; - DEBUG(D_lookup) - debug_printf("Require certificate overrides LDAP_OPT_X_TLS option (%d)\n", - tls_option); + DEBUG(D_lookup) debug_printf_indent( + "Require certificate overrides LDAP_OPT_X_TLS option (%d)\n", + tls_option); } else # endif /* LDAP_OPT_X_TLS_REQUIRE_CERT */ @@ -439,13 +433,13 @@ if (!lcp) { tls_option = LDAP_OPT_X_TLS_HARD; DEBUG(D_lookup) - debug_printf("LDAP_OPT_X_TLS_HARD set due to ldaps:// URI\n"); + debug_printf_indent("LDAP_OPT_X_TLS_HARD set due to ldaps:// URI\n"); } else { tls_option = LDAP_OPT_X_TLS_TRY; DEBUG(D_lookup) - debug_printf("LDAP_OPT_X_TLS_TRY set due to ldap:// URI\n"); + debug_printf_indent("LDAP_OPT_X_TLS_TRY set due to ldap:// URI\n"); } ldap_set_option(ld, LDAP_OPT_X_TLS, (void *)&tls_option); } @@ -488,21 +482,21 @@ if (!lcp) rc = ldap_set_option(ldsetctx, LDAP_OPT_X_TLS_REQUIRE_CERT, &cert_option); if (rc) DEBUG(D_lookup) - debug_printf("Unable to set TLS require cert_option(%d) globally: %s\n", + debug_printf_indent("Unable to set TLS require cert_option(%d) globally: %s\n", cert_option, ldap_err2string(rc)); } #endif #ifdef LDAP_OPT_X_TLS_NEWCTX if ((rc = ldap_set_option(ldsetctx, LDAP_OPT_X_TLS_NEWCTX, &am_server))) DEBUG(D_lookup) - debug_printf("Unable to reload TLS context %d: %s\n", + debug_printf_indent("Unable to reload TLS context %d: %s\n", rc, ldap_err2string(rc)); #endif /* 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; @@ -517,7 +511,7 @@ if (!lcp) else DEBUG(D_lookup) - debug_printf("re-using cached connection to LDAP server %s%s\n", + debug_printf_indent("re-using cached connection to LDAP server %s%s\n", host, porttext); /* Bind with the user/password supplied, or an anonymous bind if these values @@ -532,7 +526,7 @@ if ( !lcp->bound || lcp->password && password && Ustrcmp(lcp->password, password) != 0 ) { - DEBUG(D_lookup) debug_printf("%sbinding with user=%s password=%s\n", + DEBUG(D_lookup) debug_printf_indent("%sbinding with user=%s password=%s\n", lcp->bound ? "re-" : "", user, password); if (eldap_start_tls && !lcp->is_start_tls_called && !ldapi) @@ -551,7 +545,7 @@ if ( !lcp->bound } lcp->is_start_tls_called = TRUE; #else - DEBUG(D_lookup) debug_printf("TLS initiation not supported with this Exim" + DEBUG(D_lookup) debug_printf_indent("TLS initiation not supported with this Exim" " and your LDAP library.\n"); #endif } @@ -580,7 +574,7 @@ if ( !lcp->bound if (search_type == SEARCH_LDAP_AUTH && rc == LDAP_INVALID_CREDENTIALS) { DEBUG(D_lookup) - debug_printf("Invalid credentials: ldapauth returns FAIL\n"); + debug_printf_indent("Invalid credentials: ldapauth returns FAIL\n"); error_yield = FAIL; goto RETURN_ERROR_NOMSG; } @@ -609,7 +603,7 @@ if ( !lcp->bound if (search_type == SEARCH_LDAP_AUTH) { - DEBUG(D_lookup) debug_printf("Bind succeeded: ldapauth returns OK\n"); + DEBUG(D_lookup) debug_printf_indent("Bind succeeded: ldapauth returns OK\n"); goto RETURN_OK; } @@ -641,7 +635,7 @@ ldap_set_option(lcp->ld, LDAP_OPT_REFERRALS, referrals); /* Start the search on the server. */ -DEBUG(D_lookup) debug_printf("Start search\n"); +DEBUG(D_lookup) debug_printf_indent("Start search\n"); msgid = ldap_search(lcp->ld, ludp->lud_dn, ludp->lud_scope, ludp->lud_filter, ludp->lud_attrs, 0); @@ -673,7 +667,7 @@ while ((rc = ldap_result(lcp->ld, msgid, 0, timeoutptr, &result)) == then we get two entries, one for A and one for B. Here we just count the values per entry */ - DEBUG(D_lookup) debug_printf("LDAP result loop\n"); + DEBUG(D_lookup) debug_printf_indent("LDAP result loop\n"); for(e = ldap_first_entry(lcp->ld, result), valuecount = 0; e; @@ -682,7 +676,7 @@ while ((rc = ldap_result(lcp->ld, msgid, 0, timeoutptr, &result)) == uschar *new_dn; BOOL insert_space = FALSE; - DEBUG(D_lookup) debug_printf("LDAP entry loop\n"); + DEBUG(D_lookup) debug_printf_indent("LDAP entry loop\n"); rescount++; /* Count results */ @@ -731,7 +725,7 @@ while ((rc = ldap_result(lcp->ld, msgid, 0, timeoutptr, &result)) == else for (uschar * attr = US ldap_first_attribute(lcp->ld, e, &ber); attr; attr = US ldap_next_attribute(lcp->ld, e, ber)) { - DEBUG(D_lookup) debug_printf("LDAP attr loop\n"); + DEBUG(D_lookup) debug_printf_indent("LDAP attr loop\n"); /* In case of attrs_requested == 1 we just count the values, in all other cases (0, >1) we count the values per attribute */ @@ -759,7 +753,7 @@ while ((rc = ldap_result(lcp->ld, msgid, 0, timeoutptr, &result)) == int len = Ustrlen(value); ++valuecount; - DEBUG(D_lookup) debug_printf("LDAP value loop %s:%s\n", attr, value); + DEBUG(D_lookup) debug_printf_indent("LDAP value loop %s:%s\n", attr, value); /* In case we requested one attribute only but got several times into that attr loop, we need to append the additional values. @@ -838,7 +832,7 @@ an empty string. */ if (!data) data = string_get(1); (void) string_from_gstring(data); -gstring_reset_unused(data); +gstring_release_unused(data); /* Copy the last dn into eldap_dn */ @@ -852,7 +846,7 @@ if (dn) #endif } -DEBUG(D_lookup) debug_printf("search ended by ldap_result yielding %d\n",rc); +DEBUG(D_lookup) debug_printf_indent("search ended by ldap_result yielding %d\n",rc); if (rc == 0) { @@ -874,7 +868,7 @@ methods of handling error codes and generating error messages. */ if (rc == -1 || !result) { int err; - DEBUG(D_lookup) debug_printf("ldap_result failed\n"); + DEBUG(D_lookup) debug_printf_indent("ldap_result failed\n"); #if defined LDAP_LIB_SOLARIS || defined LDAP_LIB_OPENLDAP2 ldap_get_option(lcp->ld, LDAP_OPT_ERROR_NUMBER, &err); @@ -917,7 +911,7 @@ We need to parse the message to find out exactly what's happened. */ ldap_rc = rc; ldap_parse_rc = ldap_parse_result(lcp->ld, result, &rc, CSS &matched, CSS &error2, NULL, NULL, 0); - DEBUG(D_lookup) debug_printf("ldap_parse_result: %d\n", ldap_parse_rc); + DEBUG(D_lookup) debug_printf_indent("ldap_parse_result: %d\n", ldap_parse_rc); if (ldap_parse_rc < 0 && (ldap_parse_rc != LDAP_NO_RESULTS_RETURNED #ifdef LDAP_RES_SEARCH_REFERENCE @@ -959,7 +953,7 @@ We need to parse the message to find out exactly what's happened. */ the lookup, so return DEFER (which is the default in error_yield). */ -DEBUG(D_lookup) debug_printf("ldap_parse_result yielded %d: %s\n", +DEBUG(D_lookup) debug_printf_indent("ldap_parse_result yielded %d: %s\n", rc, ldap_err2string(rc)); if (rc != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED @@ -985,7 +979,7 @@ if (rc != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED #endif { - DEBUG(D_lookup) debug_printf("lookup failure forced\n"); + DEBUG(D_lookup) debug_printf_indent("lookup failure forced\n"); error_yield = FAIL; } goto RETURN_ERROR; @@ -1004,7 +998,7 @@ if (search_type != SEARCH_LDAP_MULTIPLE && rescount > 1) if (rescount < 1) { - *errmsg = string_sprintf("LDAP search: no results"); + *errmsg = US"LDAP search: no results"; error_yield = FAIL; goto RETURN_ERROR_BREAK; } @@ -1021,7 +1015,7 @@ if (!attribute_found) /* Otherwise, it's all worked */ -DEBUG(D_lookup) debug_printf("LDAP search: returning: %s\n", data->s); +DEBUG(D_lookup) debug_printf_indent("LDAP search: returning: %s\n", data->s); *res = data->s; RETURN_OK: @@ -1035,7 +1029,7 @@ RETURN_ERROR_BREAK: *defer_break = TRUE; RETURN_ERROR: -DEBUG(D_lookup) debug_printf("%s\n", *errmsg); +DEBUG(D_lookup) debug_printf_indent("%s\n", *errmsg); RETURN_ERROR_NOMSG: if (result) ldap_msgfree(result); @@ -1110,7 +1104,7 @@ NAME has the value "ldap". */ while (strncmpic(url, US"ldap", 4) != 0) { const uschar *name = url; - while (*url != 0 && *url != '=') url++; + while (*url && *url != '=') url++; if (*url == '=') { int namelen; @@ -1144,7 +1138,7 @@ while (strncmpic(url, US"ldap", 4) != 0) { *errmsg = string_sprintf("LDAP_OP_DEREF not defined in this LDAP " "library - cannot use \"dereference\""); - DEBUG(D_lookup) debug_printf("%s\n", *errmsg); + DEBUG(D_lookup) debug_printf_indent("%s\n", *errmsg); return DEFER; } #endif @@ -1156,9 +1150,8 @@ while (strncmpic(url, US"ldap", 4) != 0) else if (strcmpic(value, US"nofollow") == 0) referrals = LDAP_OPT_OFF; else { - *errmsg = string_sprintf("LDAP option REFERRALS is not \"follow\" " - "or \"nofollow\""); - DEBUG(D_lookup) debug_printf("%s\n", *errmsg); + *errmsg = US"LDAP option REFERRALS is not \"follow\" or \"nofollow\""; + DEBUG(D_lookup) debug_printf_indent("%s\n", *errmsg); return DEFER; } } @@ -1167,7 +1160,7 @@ while (strncmpic(url, US"ldap", 4) != 0) { *errmsg = string_sprintf("LDAP_OP_REFERRALS not defined in this LDAP " "library - cannot use \"referrals\""); - DEBUG(D_lookup) debug_printf("%s\n", *errmsg); + DEBUG(D_lookup) debug_printf_indent("%s\n", *errmsg); return DEFER; } #endif @@ -1177,7 +1170,7 @@ while (strncmpic(url, US"ldap", 4) != 0) *errmsg = string_sprintf("unknown parameter \"%.*s\" precedes LDAP URL", namelen, name); - DEBUG(D_lookup) debug_printf("LDAP query error: %s\n", *errmsg); + DEBUG(D_lookup) debug_printf_indent("LDAP query error: %s\n", *errmsg); return DEFER; } while (isspace(*url)) url++; @@ -1185,7 +1178,7 @@ while (strncmpic(url, US"ldap", 4) != 0) } } *errmsg = US"malformed parameter setting precedes LDAP URL"; - DEBUG(D_lookup) debug_printf("LDAP query error: %s\n", *errmsg); + DEBUG(D_lookup) debug_printf_indent("LDAP query error: %s\n", *errmsg); return DEFER; } @@ -1195,7 +1188,7 @@ result of ${quote_ldap_dn:...} quoting, which does apply URL quoting, because 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++) @@ -1216,9 +1209,9 @@ if (user != NULL) } DEBUG(D_lookup) - debug_printf("LDAP parameters: user=%s pass=%s size=%d time=%d connect=%d " + 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 @@ -1226,14 +1219,14 @@ password are considered anonymous, and will succeed on most installations. */ 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("Empty password: ldapauth returns FAIL\n"); + DEBUG(D_lookup) debug_printf_indent("Empty password: ldapauth returns FAIL\n"); return FAIL; } } @@ -1246,28 +1239,26 @@ if (Ustrncmp(p, "://", 3) != 0) { *errmsg = string_sprintf("LDAP URL does not start with \"ldap://\", " "\"ldaps://\", or \"ldapi://\" (it starts with \"%.16s...\")", url); - DEBUG(D_lookup) debug_printf("LDAP query error: %s\n", *errmsg); + DEBUG(D_lookup) debug_printf_indent("LDAP query error: %s\n", *errmsg); return DEFER; } /* 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) +list = !local_servers ? eldap_default_servers : local_servers; +while ((server = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))) { int rc; int port = 0; uschar *colon = Ustrchr(server, ':'); - if (colon != NULL) + if (colon) { *colon = 0; port = Uatoi(colon+1); @@ -1292,8 +1283,8 @@ are handled by a common function, with a flag to differentiate between them. 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) { /* Keep picky compilers happy */ do_cache = do_cache; @@ -1301,8 +1292,8 @@ 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) { /* Keep picky compilers happy */ do_cache = do_cache; @@ -1310,8 +1301,8 @@ 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) { /* Keep picky compilers happy */ do_cache = do_cache; @@ -1319,8 +1310,8 @@ 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; @@ -1336,7 +1327,7 @@ 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 */ } @@ -1358,7 +1349,7 @@ eldap_dn = NULL; while ((lcp = ldap_connections) != NULL) { - DEBUG(D_lookup) debug_printf("unbind LDAP connection to %s:%d\n", lcp->host, + 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); @@ -1483,7 +1474,7 @@ if (count == 0) return s; /* 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 */ @@ -1538,7 +1529,7 @@ else { 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 */ @@ -1555,7 +1546,7 @@ else while (*ss++ != 0) { - Ustrncpy(t, "%5C%20", 6); + Ustrncpy(t, US"%5C%20", 6); t += 6; } }