diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c index ae967ddda..9298cad92 100644 --- a/dirmngr/dirmngr.c +++ b/dirmngr/dirmngr.c @@ -124,6 +124,7 @@ enum cmd_and_opt_values { oHTTPProxy, oLDAPProxy, oOnlyLDAPProxy, + oLDAPServer, oLDAPFile, oLDAPTimeout, oLDAPAddServers, @@ -209,6 +210,8 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (oOnlyLDAPProxy, "only-ldap-proxy", N_("do not use fallback hosts with --ldap-proxy")), + ARGPARSE_s_s (oLDAPServer, "ldapserver", + N_("|SPEC|use this keyserver to lookup keys")), ARGPARSE_s_s (oLDAPFile, "ldapserverlist-file", N_("|FILE|read LDAP server list from FILE")), ARGPARSE_s_n (oLDAPAddServers, "add-servers", @@ -344,6 +347,11 @@ static int network_activity_seen; /* A list of filenames registred with --hkp-cacert. */ static strlist_t hkp_cacert_filenames; +/* A flag used to clear the list of ldapservers iff --ldapserver is + * given on the command line or one of the conf files. In this case we + * want to clear all old specifications through the legacy + * dirmngr_ldapservers.conf. */ +static int ldapserver_list_needs_reset; /* The timer tick used for housekeeping stuff. The second constant is used when a shutdown is pending. */ #define TIMERTICK_INTERVAL (60) @@ -637,6 +645,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) set_dns_timeout (0); opt.connect_timeout = 0; opt.connect_quick_timeout = 0; + ldapserver_list_needs_reset = 1; return 1; } @@ -725,6 +734,30 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) case oStandardResolver: enable_standard_resolver (1); break; case oRecursiveResolver: enable_recursive_resolver (1); break; + case oLDAPServer: + { + ldap_server_t server; + char *p; + + p = pargs->r.ret_str; + if (!strncmp (p, "ldap:", 5) && !(p[5] == '/' && p[6] == '/')) + p += 5; + + server = ldapserver_parse_one (p, NULL, 0); + if (server) + { + if (ldapserver_list_needs_reset) + { + ldapserver_list_needs_reset = 0; + ldapserver_list_free (opt.ldapservers); + opt.ldapservers = NULL; + } + server->next = opt.ldapservers; + opt.ldapservers = server; + } + } + break; + case oKeyServer: if (*pargs->r.ret_str) add_to_strlist (&opt.keyserver, pargs->r.ret_str); @@ -1087,9 +1120,11 @@ main (int argc, char **argv) post_option_parsing (); - /* Get LDAP server list from file. */ + /* Get LDAP server list from file unless --ldapserver has been used. */ #if USE_LDAP - if (!ldapfile) + if (opt.ldapservers) + ; + else if (!ldapfile) { ldapfile = make_filename (gnupg_homedir (), "dirmngr_ldapservers.conf", diff --git a/dirmngr/ks-engine-ldap.c b/dirmngr/ks-engine-ldap.c index a8ea52baf..01f24fbbc 100644 --- a/dirmngr/ks-engine-ldap.c +++ b/dirmngr/ks-engine-ldap.c @@ -519,7 +519,9 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, const char *bindname; const char *password; const char *basedn_arg; +#ifndef HAVE_W32_SYSTEM char *tmpstr; +#endif if (r_basedn) *r_basedn = NULL; diff --git a/dirmngr/server.c b/dirmngr/server.c index d07323631..3aab5efe5 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -1140,11 +1140,13 @@ task_check_wkd_support (ctrl_t ctrl, const char *domain) static const char hlp_ldapserver[] = - "LDAPSERVER \n" + "LDAPSERVER [--clear] \n" "\n" "Add a new LDAP server to the list of configured LDAP servers.\n" "DATA is in the same format as expected in the configure file.\n" - "An optional prefix \"ldap:\" is allowed."; + "An optional prefix \"ldap:\" is allowed. With no args all\n" + "configured ldapservers are listed. Option --clear removes all\n" + "servers configured in this session."; static gpg_error_t cmd_ldapserver (assuan_context_t ctx, char *line) { @@ -1152,11 +1154,57 @@ cmd_ldapserver (assuan_context_t ctx, char *line) ctrl_t ctrl = assuan_get_pointer (ctx); ldap_server_t server; ldap_server_t *last_next_p; + int clear_flag; + clear_flag = has_option (line, "--clear"); + line = skip_options (line); while (spacep (line)) line++; - if (*line == '\0') - return leave_cmd (ctx, PARM_ERROR (_("ldapserver missing"))); + + if (clear_flag) + { +#if USE_LDAP + ldapserver_list_free (ctrl->server_local->ldapservers); +#endif /*USE_LDAP*/ + ctrl->server_local->ldapservers = NULL; + } + + if (!*line && clear_flag) + return leave_cmd (ctx, 0); + + if (!*line) + { + /* List all ldapservers. */ + struct ldapserver_iter ldapserver_iter; + char *tmpstr; + char portstr[20]; + + for (ldapserver_iter_begin (&ldapserver_iter, ctrl); + !ldapserver_iter_end_p (&ldapserver_iter); + ldapserver_iter_next (&ldapserver_iter)) + { + server = ldapserver_iter.server; + if (server->port) + snprintf (portstr, sizeof portstr, "%d", server->port); + else + *portstr = 0; + + tmpstr = xtryasprintf ("ldap:%s:%s:%s:%s:%s:%s%s:", + server->host? server->host : "", + portstr, + server->user? server->user : "", + server->pass? "[not_shown]": "", + server->base? server->base : "", + server->starttls ? "starttls" : + server->ldap_over_tls ? "ldaptls" : "none", + server->ntds ? ",ntds" : ""); + if (!tmpstr) + return leave_cmd (ctx, gpg_error_from_syserror ()); + dirmngr_status (ctrl, "LDAPSERVER", tmpstr, NULL); + xfree (tmpstr); + } + return leave_cmd (ctx, 0); + } /* Skip an "ldap:" prefix unless it is a valid ldap url. */ if (!strncmp (line, "ldap:", 5) && !(line[5] == '/' && line[6] == '/')) diff --git a/doc/dirmngr.texi b/doc/dirmngr.texi index f5a9a46a2..8ebfea848 100644 --- a/doc/dirmngr.texi +++ b/doc/dirmngr.texi @@ -14,7 +14,7 @@ @manpage dirmngr.8 @ifset manverb .B dirmngr -\- CRL and OCSP daemon +\- GnuPG's network access daemon @end ifset @mansect synopsis @@ -424,13 +424,13 @@ configured LDAP server if the connection using the "proxy" failed. @item --ldapserverlist-file @var{file} @opindex ldapserverlist-file -Read the list of LDAP servers to consult for CRLs and certificates from +Read the list of LDAP servers to consult for CRLs and X.509 certificates from file instead of the default per-user ldap server list file. The default value for @var{file} is @file{dirmngr_ldapservers.conf}. This server list file contains one LDAP server per line in the format -@sc{hostname:port:username:password:base_dn} +@sc{hostname:port:username:password:base_dn:flags} Lines starting with a @samp{#} are comments. @@ -440,7 +440,39 @@ encoded as Latin-1. There is no other solution here than to put such a password in the binary encoding into the file (i.e. non-ascii characters won't show up readable).@footnote{The @command{gpgconf} tool might be helpful for frontends as it enables editing this configuration file using -percent-escaped strings.} +percent-escaped strings.}jj + + +@item --ldapserver @var{spec} +@opindex ldapserver +This is an alternative way to specify LDAP servers for CRL and X.509 +certificate retrieval. If this option is used the servers configured +in @file{dirmngr_ldapservers.conf} (or the file given by +@option{--ldapserverlist-file}) are cleared. Reloading dirmngr will +consider these again will in no case use those from +@file{dirmngr_ldapservers.conf} again. The @var{spec} is either a +proper LDAP URL or a colon delimited list of the form + +@sc{hostname:port:username:password:base_dn:flags:} + +with an optional prefix of @code{ldap:} (but without the two slashes +which would turn this into a proper LDAP URL). @sc{flags} is a list +of one or more comma delimited keywords: +@table @code +@item plain +The default: Do not use a TLS secured connection at all; the default +port is 389. +@item starttls +Use STARTTLS to secure the connection; the default port is 389. +@item ldaptls +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. +@end table + +Note that in an URL style specification the scheme @code{ldaps://} +refers to STARTTLS and _not_ to LDAP-over-TLS. @item --ldaptimeout @var{secs}