mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-13 22:21:09 +02:00
gpgsm: Allow sepcification of ldaps servers.
* sm/gpgsm.h (struct keyserver_spec): Add field use_ldaps. * sm/gpgsm.c (parse_keyserver_line): Parse flags. * sm/call-dirmngr.c (prepare_dirmngr): Send ldaps flag to the dirmngr. * dirmngr/dirmngr.h (struct ldap_server_s): Add field use_ldaps. * dirmngr/ldapserver.c (ldapserver_parse_one): Parse flags. * dirmngr/ldap.c (start_cert_fetch_ldap): Call wrapper with --tls. * dirmngr/dirmngr_ldap.c: New option --tls. (fetch_ldap): Make use of that option. -- There was no way to specify an LDAPS server in dirmngr_ldapserver.socnf or with gpgsm's --keyserver option. This patch fixes this. Eventually we should allow to replace host and port by a partial URI in the same way ldap_initialize does it. For backward compatibility we do not yet do that. Although the dirmngr code accepts an URL (eg. taken from a certificate), I can't see how the scheme was ever used. Thus the patch also detects an ldaps scheme and uses this. That part has not been tested, though. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
2b9d399cf0
commit
6e1c99bc39
@ -50,6 +50,7 @@ struct ldap_server_s
|
|||||||
char *user;
|
char *user;
|
||||||
char *pass;
|
char *pass;
|
||||||
char *base;
|
char *base;
|
||||||
|
unsigned int use_ldaps:1;
|
||||||
};
|
};
|
||||||
typedef struct ldap_server_s *ldap_server_t;
|
typedef struct ldap_server_s *ldap_server_t;
|
||||||
|
|
||||||
|
@ -123,6 +123,7 @@ enum
|
|||||||
oDN,
|
oDN,
|
||||||
oFilter,
|
oFilter,
|
||||||
oAttr,
|
oAttr,
|
||||||
|
oTls,
|
||||||
|
|
||||||
oOnlySearchTimeout,
|
oOnlySearchTimeout,
|
||||||
oLogWithPID
|
oLogWithPID
|
||||||
@ -138,6 +139,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
" a record oriented format")},
|
" a record oriented format")},
|
||||||
{ oProxy, "proxy", 2,
|
{ oProxy, "proxy", 2,
|
||||||
N_("|NAME|ignore host part and connect through NAME")},
|
N_("|NAME|ignore host part and connect through NAME")},
|
||||||
|
{ oTls, "tls", 0, N_("force a TLS connection")},
|
||||||
{ oHost, "host", 2, N_("|NAME|connect to host NAME")},
|
{ oHost, "host", 2, N_("|NAME|connect to host NAME")},
|
||||||
{ oPort, "port", 1, N_("|N|connect to port N")},
|
{ oPort, "port", 1, N_("|N|connect to port N")},
|
||||||
{ oUser, "user", 2, N_("|NAME|use user NAME for authentication")},
|
{ oUser, "user", 2, N_("|NAME|use user NAME for authentication")},
|
||||||
@ -163,6 +165,7 @@ struct my_opt_s
|
|||||||
my_ldap_timeval_t timeout;/* Timeout for the LDAP search functions. */
|
my_ldap_timeval_t timeout;/* Timeout for the LDAP search functions. */
|
||||||
unsigned int alarm_timeout; /* And for the alarm based timeout. */
|
unsigned int alarm_timeout; /* And for the alarm based timeout. */
|
||||||
int multi;
|
int multi;
|
||||||
|
int force_tls;
|
||||||
|
|
||||||
estream_t outstream; /* Send output to this stream. */
|
estream_t outstream; /* Send output to this stream. */
|
||||||
|
|
||||||
@ -287,6 +290,7 @@ ldap_wrapper_main (char **argv, estream_t outstream)
|
|||||||
myopt->pass = getenv ("DIRMNGR_LDAP_PASS");
|
myopt->pass = getenv ("DIRMNGR_LDAP_PASS");
|
||||||
break;
|
break;
|
||||||
case oProxy: myopt->proxy = pargs.r.ret_str; break;
|
case oProxy: myopt->proxy = pargs.r.ret_str; break;
|
||||||
|
case oTls: myopt->force_tls = 1; break;
|
||||||
case oHost: myopt->host = pargs.r.ret_str; break;
|
case oHost: myopt->host = pargs.r.ret_str; break;
|
||||||
case oPort: myopt->port = pargs.r.ret_int; break;
|
case oPort: myopt->port = pargs.r.ret_int; break;
|
||||||
case oDN: myopt->dn = pargs.r.ret_str; break;
|
case oDN: myopt->dn = pargs.r.ret_str; break;
|
||||||
@ -622,12 +626,19 @@ fetch_ldap (my_opt_t myopt, const char *url, const LDAPURLDesc *ludp)
|
|||||||
attrs[1] = NULL;
|
attrs[1] = NULL;
|
||||||
attr = attrs[0];
|
attr = attrs[0];
|
||||||
|
|
||||||
if (!port)
|
if (!port && myopt->force_tls)
|
||||||
|
port = 636;
|
||||||
|
else if (!port)
|
||||||
port = (ludp->lud_scheme && !strcmp (ludp->lud_scheme, "ldaps"))? 636:389;
|
port = (ludp->lud_scheme && !strcmp (ludp->lud_scheme, "ldaps"))? 636:389;
|
||||||
|
|
||||||
if (myopt->verbose)
|
if (myopt->verbose)
|
||||||
{
|
{
|
||||||
log_info (_("processing url '%s'\n"), url);
|
log_info (_("processing url '%s'\n"), url);
|
||||||
|
if (myopt->force_tls)
|
||||||
|
log_info ("forcing tls\n");
|
||||||
|
else
|
||||||
|
log_info ("not forcing tls\n");
|
||||||
|
|
||||||
if (myopt->user)
|
if (myopt->user)
|
||||||
log_info (_(" user '%s'\n"), myopt->user);
|
log_info (_(" user '%s'\n"), myopt->user);
|
||||||
if (myopt->pass)
|
if (myopt->pass)
|
||||||
@ -665,17 +676,48 @@ fetch_ldap (my_opt_t myopt, const char *url, const LDAPURLDesc *ludp)
|
|||||||
&& ludp->lud_attrs && ludp->lud_attrs[0] && ludp->lud_attrs[1])
|
&& ludp->lud_attrs && ludp->lud_attrs[0] && ludp->lud_attrs[1])
|
||||||
log_info (_("WARNING: using first attribute only\n"));
|
log_info (_("WARNING: using first attribute only\n"));
|
||||||
|
|
||||||
|
|
||||||
set_timeout (myopt);
|
set_timeout (myopt);
|
||||||
npth_unprotect ();
|
|
||||||
ld = my_ldap_init (host, port);
|
if (myopt->force_tls
|
||||||
npth_protect ();
|
|| (ludp->lud_scheme && !strcmp (ludp->lud_scheme, "ldaps")))
|
||||||
if (!ld)
|
|
||||||
{
|
{
|
||||||
log_error (_("LDAP init to '%s:%d' failed: %s\n"),
|
char *uri;
|
||||||
host, port, strerror (errno));
|
|
||||||
return -1;
|
uri = xtryasprintf ("ldaps://%s:%d", host, port);
|
||||||
|
if (!uri)
|
||||||
|
{
|
||||||
|
log_error (_("error allocating memory: %s\n"),
|
||||||
|
gpg_strerror (gpg_error_from_syserror ()));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ret = ldap_initialize (&ld, uri);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
log_error (_("LDAP init to '%s' failed: %s\n"),
|
||||||
|
uri, ldap_err2string (ret));
|
||||||
|
xfree (uri);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (myopt->verbose)
|
||||||
|
log_info (_("LDAP init to '%s' done\n"), uri);
|
||||||
|
xfree (uri);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Keep the old way so to avoid regressions. Eventually we
|
||||||
|
* should really consider the supplied scheme and use only
|
||||||
|
* ldap_initialize. */
|
||||||
|
npth_unprotect ();
|
||||||
|
ld = my_ldap_init (host, port);
|
||||||
|
npth_protect ();
|
||||||
|
if (!ld)
|
||||||
|
{
|
||||||
|
log_error (_("LDAP init to '%s:%d' failed: %s\n"),
|
||||||
|
host, port, strerror (errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
npth_unprotect ();
|
npth_unprotect ();
|
||||||
/* Fixme: Can we use MYOPT->user or is it shared with other theeads?. */
|
/* Fixme: Can we use MYOPT->user or is it shared with other theeads?. */
|
||||||
ret = my_ldap_simple_bind_s (ld, myopt->user, myopt->pass);
|
ret = my_ldap_simple_bind_s (ld, myopt->user, myopt->pass);
|
||||||
|
@ -525,7 +525,7 @@ start_cert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context,
|
|||||||
int argc = 0;
|
int argc = 0;
|
||||||
int argc_malloced = 0;
|
int argc_malloced = 0;
|
||||||
char portbuf[30], timeoutbuf[30];
|
char portbuf[30], timeoutbuf[30];
|
||||||
|
int use_ldaps = 0;
|
||||||
|
|
||||||
*context = NULL;
|
*context = NULL;
|
||||||
|
|
||||||
@ -554,7 +554,7 @@ start_cert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context,
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
base = server->base;
|
base = server->base;
|
||||||
|
use_ldaps = server->use_ldaps;
|
||||||
}
|
}
|
||||||
else /* Use a default server. */
|
else /* Use a default server. */
|
||||||
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||||
@ -587,6 +587,8 @@ start_cert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context,
|
|||||||
argv[argc++] = "--proxy";
|
argv[argc++] = "--proxy";
|
||||||
argv[argc++] = proxy;
|
argv[argc++] = proxy;
|
||||||
}
|
}
|
||||||
|
if (use_ldaps)
|
||||||
|
argv[argc++] = "--tls";
|
||||||
if (host)
|
if (host)
|
||||||
{
|
{
|
||||||
argv[argc++] = "--host";
|
argv[argc++] = "--host";
|
||||||
|
@ -55,6 +55,7 @@ ldapserver_list_free (ldap_server_t servers)
|
|||||||
3. field: Username
|
3. field: Username
|
||||||
4. field: Password
|
4. field: Password
|
||||||
5. field: Base DN
|
5. field: Base DN
|
||||||
|
6. field: Flags
|
||||||
|
|
||||||
FILENAME and LINENO are used for diagnostic purposes only.
|
FILENAME and LINENO are used for diagnostic purposes only.
|
||||||
*/
|
*/
|
||||||
@ -64,9 +65,11 @@ ldapserver_parse_one (char *line,
|
|||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
char *endp;
|
char *endp;
|
||||||
|
const char *s;
|
||||||
ldap_server_t server;
|
ldap_server_t server;
|
||||||
int fieldno;
|
int fieldno;
|
||||||
int fail = 0;
|
int fail = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* Parse the colon separated fields. */
|
/* Parse the colon separated fields. */
|
||||||
server = xcalloc (1, sizeof *server);
|
server = xcalloc (1, sizeof *server);
|
||||||
@ -115,6 +118,32 @@ ldapserver_parse_one (char *line,
|
|||||||
server->base = xstrdup (p);
|
server->base = xstrdup (p);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
{
|
||||||
|
char **flags = NULL;
|
||||||
|
|
||||||
|
flags = strtokenize (p, ",");
|
||||||
|
if (!flags)
|
||||||
|
log_fatal ("strtokenize failed: %s\n",
|
||||||
|
gpg_strerror (gpg_error_from_syserror ()));
|
||||||
|
|
||||||
|
for (i=0; (s = flags[i]); i++)
|
||||||
|
{
|
||||||
|
if (!*s)
|
||||||
|
;
|
||||||
|
else if (!ascii_strcasecmp (s, "ldaps"))
|
||||||
|
server->use_ldaps = 1;
|
||||||
|
else if (!ascii_strcasecmp (s, "ldap"))
|
||||||
|
server->use_ldaps = 0;
|
||||||
|
else
|
||||||
|
log_info (_("%s:%u: ignoring unknown flag '%s'\n"),
|
||||||
|
filename, lineno, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree (flags);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* (We silently ignore extra fields.) */
|
/* (We silently ignore extra fields.) */
|
||||||
break;
|
break;
|
||||||
|
@ -406,10 +406,14 @@ client for its session. The default value for @var{file} is
|
|||||||
|
|
||||||
This server list file contains one LDAP server per line in the format
|
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.
|
Lines starting with a @samp{#} are comments.
|
||||||
|
|
||||||
|
The only defined flag is @code{ldaps} to specify that a TLS
|
||||||
|
connections shall be used. Flags are comma delimited; unknown flags
|
||||||
|
are ignored.
|
||||||
|
|
||||||
Note that as usual all strings entered are expected to be UTF-8 encoded.
|
Note that as usual all strings entered are expected to be UTF-8 encoded.
|
||||||
Obviously this will lead to problems if the password has originally been
|
Obviously this will lead to problems if the password has originally been
|
||||||
encoded as Latin-1. There is no other solution here than to put such a
|
encoded as Latin-1. There is no other solution here than to put such a
|
||||||
|
@ -356,13 +356,27 @@ Note that the @command{dirmngr} can in addition be configured with a
|
|||||||
default list of LDAP servers to be used after those configured with
|
default list of LDAP servers to be used after those configured with
|
||||||
this option. The syntax of @var{string} is:
|
this option. The syntax of @var{string} is:
|
||||||
|
|
||||||
@sc{hostname:port:username:password:base_dn}
|
@sc{hostname:port:username:password:base_dn:flags}
|
||||||
|
|
||||||
|
The only defined flag is @code{ldaps} to specify that a TLS
|
||||||
|
connections shall be used. Flags are comma delimited; unknown flags
|
||||||
|
are ignored.
|
||||||
|
|
||||||
Note that all parts of that string are expected to be UTF-8 encoded.
|
Note that all parts of that string are expected to be UTF-8 encoded.
|
||||||
This may lead to problems if the @sc{password} has originally been
|
This may lead to problems if the @sc{password} has originally been
|
||||||
encoded as Latin-1; in such a case better configure this LDAP server
|
encoded as Latin-1; in such a case better configure tsuch an LDAP server
|
||||||
using the global configuration of @command{dirmngr}.
|
using the global configuration of @command{dirmngr}.
|
||||||
|
|
||||||
|
Here is an example which uses the default port, no username, no
|
||||||
|
password, and requests a TLS connection:
|
||||||
|
|
||||||
|
@c man:.RS
|
||||||
|
@example
|
||||||
|
--keyserver ldap.pca.dfn.de::::o=DFN-Verein,c=DE:ldaps
|
||||||
|
@end example
|
||||||
|
@c man:.RE
|
||||||
|
|
||||||
|
|
||||||
@item --policy-file @var{filename}
|
@item --policy-file @var{filename}
|
||||||
@opindex policy-file
|
@opindex policy-file
|
||||||
Change the default name of the policy file to @var{filename}. The
|
Change the default name of the policy file to @var{filename}. The
|
||||||
|
@ -223,8 +223,9 @@ prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err)
|
|||||||
char *pass = server->pass ? server->pass : "";
|
char *pass = server->pass ? server->pass : "";
|
||||||
char *base = server->base ? server->base : "";
|
char *base = server->base ? server->base : "";
|
||||||
|
|
||||||
snprintf (line, DIM (line), "LDAPSERVER %s:%i:%s:%s:%s",
|
snprintf (line, DIM (line), "LDAPSERVER %s:%i:%s:%s:%s:%s",
|
||||||
server->host, server->port, user, pass, base);
|
server->host, server->port, user, pass, base,
|
||||||
|
server->use_ldaps? "ldaps":"");
|
||||||
|
|
||||||
assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
/* The code below is not required because we don't return an error. */
|
/* The code below is not required because we don't return an error. */
|
||||||
|
36
sm/gpgsm.c
36
sm/gpgsm.c
@ -817,9 +817,17 @@ parse_keyserver_line (char *line,
|
|||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
char *endp;
|
char *endp;
|
||||||
|
const char *s;
|
||||||
struct keyserver_spec *server;
|
struct keyserver_spec *server;
|
||||||
int fieldno;
|
int fieldno;
|
||||||
int fail = 0;
|
int fail = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!filename)
|
||||||
|
{
|
||||||
|
filename = "[cmd]";
|
||||||
|
lineno = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse the colon separated fields. */
|
/* Parse the colon separated fields. */
|
||||||
server = xcalloc (1, sizeof *server);
|
server = xcalloc (1, sizeof *server);
|
||||||
@ -833,7 +841,7 @@ parse_keyserver_line (char *line,
|
|||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
if (*p)
|
if (*p)
|
||||||
server->host = xstrdup (p);
|
server->host = xstrdup (p);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_error (_("%s:%u: no hostname given\n"),
|
log_error (_("%s:%u: no hostname given\n"),
|
||||||
@ -868,6 +876,32 @@ parse_keyserver_line (char *line,
|
|||||||
server->base = xstrdup (p);
|
server->base = xstrdup (p);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
{
|
||||||
|
char **flags = NULL;
|
||||||
|
|
||||||
|
flags = strtokenize (p, ",");
|
||||||
|
if (!flags)
|
||||||
|
log_fatal ("strtokenize failed: %s\n",
|
||||||
|
gpg_strerror (gpg_error_from_syserror ()));
|
||||||
|
|
||||||
|
for (i=0; (s = flags[i]); i++)
|
||||||
|
{
|
||||||
|
if (!*s)
|
||||||
|
;
|
||||||
|
else if (!ascii_strcasecmp (s, "ldaps"))
|
||||||
|
server->use_ldaps = 1;
|
||||||
|
else if (!ascii_strcasecmp (s, "ldap"))
|
||||||
|
server->use_ldaps = 0;
|
||||||
|
else
|
||||||
|
log_info (_("%s:%u: ignoring unknown flag '%s'\n"),
|
||||||
|
filename, lineno, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree (flags);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* (We silently ignore extra fields.) */
|
/* (We silently ignore extra fields.) */
|
||||||
break;
|
break;
|
||||||
|
@ -48,6 +48,7 @@ struct keyserver_spec
|
|||||||
char *user;
|
char *user;
|
||||||
char *pass;
|
char *pass;
|
||||||
char *base;
|
char *base;
|
||||||
|
unsigned int use_ldaps:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user