From d65a0335e5cb947dc527d62eccf7c2a3cdbcc788 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 28 Sep 2022 09:43:25 +0200 Subject: [PATCH] dirmngr: New server flag "areconly" (A-record-only) * dirmngr/dirmngr.h (struct ldap_server_s): Add field areconly. * dirmngr/ldapserver.c (ldapserver_parse_one): Parse "areconly" * dirmngr/ks-engine-ldap.c (my_ldap_connect): Implement this flag. * dirmngr/dirmngr_ldap.c: Add option --areconly (connect_ldap): Implement option. * dirmngr/ldap.c (run_ldap_wrapper): Add and pass that option. -- This flag is used to pass the Windows specific option LDAP_OPT_AREC_EXCLUSIVE. It is ignored on other systems. Signed-off-by: Werner Koch --- dirmngr/dirmngr.h | 1 + dirmngr/dirmngr_ldap.c | 15 +++++++++++++++ dirmngr/ks-engine-ldap.c | 20 ++++++++++++++++++-- dirmngr/ldap.c | 10 +++++++++- dirmngr/ldapserver.c | 5 +++++ doc/dirmngr.texi | 3 +++ 6 files changed, 51 insertions(+), 3 deletions(-) diff --git a/dirmngr/dirmngr.h b/dirmngr/dirmngr.h index d916cce5f..9f2157c0d 100644 --- a/dirmngr/dirmngr.h +++ b/dirmngr/dirmngr.h @@ -53,6 +53,7 @@ struct ldap_server_s unsigned int starttls:1; /* Use STARTTLS. */ unsigned int ldap_over_tls:1; /* Use LDAP over an TLS tunnel */ unsigned int ntds:1; /* Use Active Directory authentication. */ + unsigned int areconly:1; /* Set LDAP_OPT_AREC_EXCLUSIVE. */ }; typedef struct ldap_server_s *ldap_server_t; diff --git a/dirmngr/dirmngr_ldap.c b/dirmngr/dirmngr_ldap.c index 9c9fcc508..c6a4dd11f 100644 --- a/dirmngr/dirmngr_ldap.c +++ b/dirmngr/dirmngr_ldap.c @@ -92,6 +92,7 @@ enum oStartTLS, oLdapTLS, oNtds, + oARecOnly, oOnlySearchTimeout, oLogWithPID }; @@ -109,6 +110,7 @@ static gpgrt_opt_t opts[] = { { oStartTLS, "starttls", 0, "use STARTLS for the conenction"}, { oLdapTLS, "ldaptls", 0, "use a TLS for the connection"}, { oNtds, "ntds", 0, "authenticate using AD"}, + { oARecOnly, "areconly", 0, "do only an A record lookup"}, { oHost, "host", 2, "|NAME|connect to host NAME"}, { oPort, "port", 1, "|N|connect to port N"}, { oUser, "user", 2, "|NAME|use NAME for authentication"}, @@ -134,6 +136,7 @@ static struct int starttls; int ldaptls; int ntds; + int areconly; estream_t outstream; /* Send output to this stream. */ @@ -234,6 +237,7 @@ main (int argc, char **argv) case oStartTLS: opt.starttls = 1; opt.ldaptls = 0; break; case oLdapTLS: opt.starttls = 0; opt.ldaptls = 1; break; case oNtds: opt.ntds = 1; break; + case oARecOnly: opt.areconly = 1; break; case oMulti: opt.multi = 1; break; case oUser: opt.user = pargs.r.ret_str; break; case oPass: opt.pass = pargs.r.ret_str; break; @@ -436,6 +440,17 @@ connect_ldap (LDAP **r_ld) opt.host, opt.port, ldap_err2string (lerr)); goto leave; } + if (opt.areconly) + { + lerr = ldap_set_option (ld, LDAP_OPT_AREC_EXCLUSIVE, LDAP_OPT_ON); + if (lerr != LDAP_SUCCESS) + { + log_error ("ldap: unable to set AREC_EXLUSIVE: %s\n", + ldap_err2string (lerr)); + err = ldap_err_to_gpg_err (lerr); + goto leave; + } + } #else /* Unix */ tmpstr = xtryasprintf ("%s://%s:%d", opt.ldaptls? "ldaps" : "ldap", diff --git a/dirmngr/ks-engine-ldap.c b/dirmngr/ks-engine-ldap.c index b3f7f8ff5..8f6144994 100644 --- a/dirmngr/ks-engine-ldap.c +++ b/dirmngr/ks-engine-ldap.c @@ -405,6 +405,7 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, int port; /* Port to use. */ int use_tls; /* 1 = starttls, 2 = ldap-over-tls */ int use_ntds; /* Use Active Directory authentication. */ + int use_areconly; /* Lookup only via A record (Windows). */ const char *bindname; const char *password; const char *basedn_arg; @@ -432,6 +433,7 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, basedn_arg = server->base; use_tls = server->starttls? 1 : server->ldap_over_tls? 2 : 0; use_ntds = server->ntds; + use_areconly = server->areconly; } else { @@ -442,6 +444,7 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, basedn_arg = uri->path; use_tls = uri->use_tls ? 1 : 0; use_ntds = uri->ad_current; + use_areconly = 0; } if (!port) @@ -459,13 +462,14 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, } if (opt.verbose) - log_info ("ldap connect to '%s:%d:%s:%s:%s:%s%s'\n", + log_info ("ldap connect to '%s:%d:%s:%s:%s:%s%s%s'\n", host, port, basedn_arg ? basedn_arg : "", bindname ? bindname : "", password ? "*****" : "", use_tls == 1? "starttls" : use_tls == 2? "ldaptls" : "plain", - use_ntds ? ",ntds":""); + use_ntds ? ",ntds":"", + use_areconly? ",areconly":""); /* If the uri specifies a secure connection and we don't support @@ -494,6 +498,18 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, host, port, ldap_err2string (lerr)); goto out; } + if (use_areconly) + { + lerr = ldap_set_option (ldap_conn, LDAP_OPT_AREC_EXCLUSIVE, LDAP_OPT_ON); + if (lerr != LDAP_SUCCESS) + { + log_error ("ks-ldap: unable to set LDAP_OPT_AREC_EXLUSIVE: %s\n", + ldap_err2string (lerr)); + err = ldap_err_to_gpg_err (lerr); + goto out; + } + } + #else /* Unix */ tmpstr = xtryasprintf ("%s://%s:%d", use_tls == 2? "ldaps" : "ldap", diff --git a/dirmngr/ldap.c b/dirmngr/ldap.c index 174c6d93f..f9f6d5f1a 100644 --- a/dirmngr/ldap.c +++ b/dirmngr/ldap.c @@ -119,13 +119,14 @@ run_ldap_wrapper (ctrl_t ctrl, int multi_mode, int tls_mode, int ntds, + int areconly, const char *proxy, const char *host, int port, const char *user, const char *pass, const char *base, const char *filter, const char *attr, ksba_reader_t *reader) { - const char *argv[50]; + const char *argv[51]; int argc; char portbuf[30], timeoutbuf[30]; @@ -156,6 +157,9 @@ run_ldap_wrapper (ctrl_t ctrl, if (ntds) argv[argc++] = "--ntds"; + if (areconly) + argv[argc++] = "--areconly"; + if (opt.ldaptimeout) { snprintf (timeoutbuf, sizeof timeoutbuf, "%u", opt.ldaptimeout); @@ -262,6 +266,7 @@ url_fetch_ldap (ctrl_t ctrl, const char *url, ksba_reader_t *reader) 0, /* No Multi-mode. */ tls_mode, 0, /* No AD authentication. */ + 0, /* No areconly. */ opt.ldap_proxy, ludp->lud_host, ludp->lud_port, NULL, NULL, /* user, password */ @@ -308,6 +313,7 @@ url_fetch_ldap (ctrl_t ctrl, const char *url, ksba_reader_t *reader) 0, /* No Multi-mode */ tls_mode, server->ntds, + server->areconly, NULL, server->host, server->port, server->user, server->pass, @@ -358,6 +364,7 @@ attr_fetch_ldap (ctrl_t ctrl, 0, tls_mode, server->ntds, + server->areconly, opt.ldap_proxy, server->host, server->port, server->user, server->pass, @@ -625,6 +632,7 @@ start_cacert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *r_context, 1, /* --multi (record format) */ 0, /* No TLS */ 0, /* No AD authentication. */ + server->areconly, opt.ldap_proxy, server->host, server->port, server->user, server->pass, diff --git a/dirmngr/ldapserver.c b/dirmngr/ldapserver.c index 4ef28431c..14f87efb1 100644 --- a/dirmngr/ldapserver.c +++ b/dirmngr/ldapserver.c @@ -64,6 +64,7 @@ ldapserver_list_free (ldap_server_t servers) * plain := Switch to plain unsecured LDAP. * (The last of these 3 flags is the effective one) * ntds := Use Active Directory authentication + * areconly := Use option LDAP_OPT_AREC_EXCLUSIVE * * FILENAME and LINENO are used for diagnostic purposes only. */ @@ -175,6 +176,10 @@ ldapserver_parse_one (char *line, { server->ntds = 1; } + else if (!ascii_strcasecmp (s, "areconly")) + { + server->areconly = 1; + } else { if (filename) diff --git a/doc/dirmngr.texi b/doc/dirmngr.texi index 6c1c59b82..aaa30ec50 100644 --- a/doc/dirmngr.texi +++ b/doc/dirmngr.texi @@ -484,6 +484,9 @@ Tunnel LDAP through a TLS connection; the default port is 636. @item ntds On Windows authenticate the LDAP connection using the Active Directory with the current user. +@item areconly +On Windows use only the A or AAAA record when resolving the LDAP +server name. @end table Note that in an URL style specification the scheme @code{ldaps://}