dirmngr: Do not block threads in LDAP keyserver calls.

* dirmngr/ks-engine-ldap.c: Wrap some ldap calls.
--

The former gpgkeys_ldap module has once been ported to dirmngr but
unfortunately the dirmngr_ldap wrapper has not been used so that we
have internal LDAP calls with these problems:

- No usable timeouts.
- On non-Windows platforms a lot of extra libs and possibly even a
  second copy of Libgcrypt is pulled in.
- Only one threads runs at a time.

This patch mitigates the last point.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2020-12-18 11:56:15 +01:00
parent 4a3836e2b2
commit 355e2992c0
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
1 changed files with 38 additions and 6 deletions

View File

@ -42,6 +42,7 @@
# define LDAP_DEPRECATED 1
# include <ldap.h>
#endif
#include <npth.h>
#include "dirmngr.h"
#include "misc.h"
@ -585,6 +586,7 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
LDAP_OPT_SERVER_CERTIFICATE, ..); */
#endif
npth_unprotect ();
err = ldap_start_tls_s (ldap_conn,
#ifdef HAVE_W32_SYSTEM
/* ServerReturnValue, result */
@ -592,6 +594,7 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
#endif
/* ServerControls, ClientControls */
NULL, NULL);
npth_protect ();
if (err)
{
log_error ("error connecting to LDAP server with TLS\n");
@ -605,7 +608,9 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
if (opt.debug)
log_debug ("LDAP bind to current user via AD\n");
#ifdef HAVE_W32_SYSTEM
npth_unprotect ();
err = ldap_bind_s (ldap_conn, NULL, NULL, LDAP_AUTH_NEGOTIATE);
npth_protect ();
#else
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
#endif
@ -622,7 +627,9 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
log_debug ("LDAP bind to %s, password %s\n",
user, password ? ">not shown<" : ">none<");
npth_unprotect ();
err = ldap_simple_bind_s (ldap_conn, user, password);
npth_protect ();
if (err != LDAP_SUCCESS)
{
log_error ("error binding to LDAP: %s\n", ldap_err2string (err));
@ -648,11 +655,18 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
LDAPMessage *res = NULL;
char *attr[] = { "namingContexts", NULL };
npth_unprotect ();
err = ldap_search_s (ldap_conn, "", LDAP_SCOPE_BASE,
"(objectClass=*)", attr, 0, &res);
npth_protect ();
if (err == LDAP_SUCCESS)
{
char **context = ldap_get_values (ldap_conn, res, "namingContexts");
char **context;
npth_unprotect ();
context = ldap_get_values (ldap_conn, res, "namingContexts");
npth_protect ();
if (context)
{
/* We found some, so try each namingContext as the
@ -674,8 +688,10 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
{
char *object = xasprintf ("cn=pgpServerInfo,%s",
context[i]);
npth_unprotect ();
err = ldap_search_s (ldap_conn, object, LDAP_SCOPE_BASE,
"(objectClass=*)", attr2, 0, &si_res);
npth_protect ();
xfree (object);
}
@ -741,8 +757,10 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
char *attr2[] = { "pgpBaseKeySpaceDN", "version", "software", NULL };
npth_unprotect ();
err = ldap_search_s (ldap_conn, "cn=pgpServerInfo", LDAP_SCOPE_BASE,
"(objectClass=*)", attr2, 0, &si_res);
npth_protect ();
if (err == LDAP_SUCCESS)
{
/* For the PGP LDAP keyserver, this is always
@ -836,7 +854,7 @@ extract_keys (estream_t output,
es_fprintf (output, "INFO %s BEGIN\n", certid);
es_fprintf (output, "pub:%s:", certid);
/* Note: ldap_get_values returns a NULL terminates array of
/* Note: ldap_get_values returns a NULL terminated array of
strings. */
vals = ldap_get_values (ldap_conn, message, "pgpkeytype");
if (vals && vals[0])
@ -967,8 +985,10 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec,
/* Replace "dummy". */
attrs[0] = (serverinfo & SERVERINFO_PGPKEYV2)? "pgpKeyV2" : "pgpKey";
npth_unprotect ();
ldap_err = ldap_search_s (ldap_conn, basedn, LDAP_SCOPE_SUBTREE,
filter, attrs, attrsonly, &message);
npth_protect ();
if (ldap_err)
{
err = ldap_err_to_gpg_err (ldap_err);
@ -1000,9 +1020,13 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec,
strlist_t seen = NULL;
LDAPMessage *each;
for (each = ldap_first_entry (ldap_conn, message);
for (npth_unprotect (),
each = ldap_first_entry (ldap_conn, message),
npth_protect ();
each;
each = ldap_next_entry (ldap_conn, each))
npth_unprotect (),
each = ldap_next_entry (ldap_conn, each),
npth_protect ())
{
char **vals;
char **certid;
@ -1158,8 +1182,10 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
if (opt.debug)
log_debug ("SEARCH '%s' => '%s' BEGIN\n", pattern, filter);
npth_unprotect ();
ldap_err = ldap_search_s (ldap_conn, basedn,
LDAP_SCOPE_SUBTREE, filter, attrs, 0, &res);
npth_protect ();
xfree (filter);
filter = NULL;
@ -1176,9 +1202,13 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
/* The LDAP server doesn't return a real count of unique keys, so we
can't use ldap_count_entries here. */
for (each = ldap_first_entry (ldap_conn, res);
for (npth_unprotect (),
each = ldap_first_entry (ldap_conn, res),
npth_protect ();
each;
each = ldap_next_entry (ldap_conn, each))
npth_unprotect (),
each = ldap_next_entry (ldap_conn, each),
npth_protect ())
{
char **certid = ldap_get_values (ldap_conn, each, "pgpcertid");
if (certid && certid[0] && ! strlist_find (dupelist, certid[0]))
@ -2182,9 +2212,11 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri,
if (opt.debug)
log_debug ("ks-ldap: using DN: %s\n", dn);
npth_unprotect ();
err = ldap_modify_s (ldap_conn, dn, modlist);
if (err == LDAP_NO_SUCH_OBJECT)
err = ldap_add_s (ldap_conn, dn, addlist);
npth_protect ();
xfree (dn);