[PATCH] dirmngr_ldap: support ldap secure connection(ldaps)
Dmitry Falko
dfalko at digiflak.com
Wed May 20 15:27:11 CEST 2015
Hello!
I encountered a problem connecting to the LDAP server via TLS and wrote
a small patch, send it as is.
* dirmngr.h (ldap_server_s): add schema field
* dirmngr_ldap.c (fetch_ldap): ldaps support
* ldap.c (make_url, start_cert_fetch_ldap): add schema
* ldapserver.c (ldapserver_parse_one): parse schema
* server.c (lookup_cert_by_pattern): additional log info
dirmngr_ldap can retrieve certificates from LDAP server
by TLS(using ldaps protocol). Protocol can be set in
dirmngr_ldapserver.conf:
hostname:port:username:password:base_dn:schema
If not set use ldap.By default dirmngr_ldap use
/etc/ssl/CA(dirmngr_ldap.c CA_CERT_DEFAULT) CA certificate,
user can set DIRMNGR_LDAP_CACERT env variable to
override this value.
---
dirmngr/dirmngr.h | 1 +
dirmngr/dirmngr_ldap.c | 61
+++++++++++++++++++++++++++++++++++++++++++++-----
dirmngr/ldap.c | 24 +++++++++++++++-----
dirmngr/ldapserver.c | 5 +++++
dirmngr/server.c | 3 ++-
5 files changed, 81 insertions(+), 13 deletions(-)
diff --git a/dirmngr/dirmngr.h b/dirmngr/dirmngr.h
index 4f037e7..3406494 100644
--- a/dirmngr/dirmngr.h
+++ b/dirmngr/dirmngr.h
@@ -46,6 +46,7 @@ struct ldap_server_s
char *user;
char *pass;
char *base;
+ char *schema;
};
typedef struct ldap_server_s *ldap_server_t;
diff --git a/dirmngr/dirmngr_ldap.c b/dirmngr/dirmngr_ldap.c
index 61a7e39..8bb739c 100644
--- a/dirmngr/dirmngr_ldap.c
+++ b/dirmngr/dirmngr_ldap.c
@@ -46,6 +46,8 @@
/* For OpenLDAP, to enable the API that we're using. */
# define LDAP_DEPRECATED 1
# include <ldap.h>
+ /* FIXME: use configure script to set this define */
+# define CA_CERT_DEFAULT ("/etc/ssl/CA")
#endif
@@ -571,9 +573,10 @@ fetch_ldap (my_opt_t myopt, const char *url, const
LDAPURLDesc *ludp)
LDAP *ld;
LDAPMessage *msg;
int rc = 0;
- char *host, *dn, *filter, *attrs[2], *attr;
+ char *host, *dn, *filter, *attrs[2], *attr, *ca_cert, *ldap_url;
int port;
int ret;
+ int err;
host = myopt->host? myopt->host : ludp->lud_host;
port = myopt->port? myopt->port : ludp->lud_port;
@@ -583,6 +586,17 @@ fetch_ldap (my_opt_t myopt, const char *url, const
LDAPURLDesc *ludp)
attrs[1] = NULL;
attr = attrs[0];
+ ca_cert = getenv("DIRMNGR_LDAP_CACERT");
+ if(!ca_cert)
+ {
+ if (myopt->verbose)
+ {
+ log_info("Using default CA certificate");
+ }
+
+ ca_cert = CA_CERT_DEFAULT;
+ }
+
if (!port)
port = (ludp->lud_scheme && !strcmp (ludp->lud_scheme, "ldaps"))?
636:389;
@@ -628,23 +642,58 @@ fetch_ldap (my_opt_t myopt, const char *url, const
LDAPURLDesc *ludp)
set_timeout (myopt);
+
+ ldap_url = alloca(4 + strlen(ludp->lud_scheme)
+ + strlen(host)
+ + 5); /* for port */
+ sprintf(ldap_url, "%s://%s:%d", ludp->lud_scheme, host, port);
+
npth_unprotect ();
- ld = my_ldap_init (host, port);
+ err = ldap_initialize(&ld, ldap_url) ;
npth_protect ();
- if (!ld)
+ if (err != LDAP_SUCCESS)
{
- log_error (_("LDAP init to '%s:%d' failed: %s\n"),
- host, port, strerror (errno));
+ log_error (_("LDAP init to '%s' failed: %s\n"),
+ ldap_url, ldap_err2string (errno));
return -1;
}
npth_unprotect ();
+
+ if(!strcmp (ludp->lud_scheme, "ldaps"))
+ {
+ /* Additional options for tls connection */
+ /*FIXME: LDAP_OPT_X_TLS_NEVER or LDAP_OPT_X_TLS_HARD, add option*/
+ int req_cert = LDAP_OPT_X_TLS_NEVER;
+
+ err = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
+ ca_cert);
+ npth_protect ();
+ if(err != LDAP_SUCCESS)
+ {
+ log_error (_("setting ca-certificate failed: %s\n"),
+ ldap_err2string (err));
+ return -1;
+ }
+ npth_unprotect ();
+ err=ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT,
+ &req_cert);
+ npth_protect ();
+ if(err != LDAP_SUCCESS)
+ {
+ log_error (_("setting require certificate failed: %s\n"),
+ ldap_err2string (err));
+ return -1;
+ }
+ npth_unprotect ();
+ }
+
/* Fixme: Can we use MYOPT->user or is it shared with other
theeads?. */
ret = my_ldap_simple_bind_s (ld, myopt->user, myopt->pass);
npth_protect ();
if (ret)
{
log_error (_("binding to '%s:%d' failed: %s\n"),
- host, port, strerror (errno));
+ host, port, ldap_err2string (errno));
ldap_unbind (ld);
return -1;
}
diff --git a/dirmngr/ldap.c b/dirmngr/ldap.c
index e4c6aa2..d4e0730 100644
--- a/dirmngr/ldap.c
+++ b/dirmngr/ldap.c
@@ -423,10 +423,10 @@ escape4url (const char *string)
need the host and port because this will be specified using the
override options. */
static gpg_error_t
-make_url (char **url, const char *dn, const char *filter)
+make_url (char **url, const char *dn, const char *filter, const char
*schema)
{
gpg_error_t err;
- char *u_dn, *u_filter;
+ char *u_dn, *u_filter, *u_schema;
char const attrs[] = (USERCERTIFICATE ","
/* USERSMIMECERTIFICATE "," */
CACERTIFICATE ","
@@ -434,6 +434,10 @@ make_url (char **url, const char *dn, const char
*filter)
*url = NULL;
+ u_schema = escape4url (schema);
+ if(!u_schema)
+ return gpg_error_from_errno (errno);
+
u_dn = escape4url (dn);
if (!u_dn)
return gpg_error_from_errno (errno);
@@ -445,7 +449,8 @@ make_url (char **url, const char *dn, const char
*filter)
xfree (u_dn);
return err;
}
- *url = malloc ( 8 + strlen (u_dn)
+ *url = malloc ( 4 + strlen (schema)
+ + strlen (u_dn)
+ 1 + strlen (attrs)
+ 5 + strlen (u_filter) + 1 );
if (!*url)
@@ -456,12 +461,14 @@ make_url (char **url, const char *dn, const char
*filter)
return err;
}
- stpcpy (stpcpy (stpcpy (stpcpy (stpcpy (stpcpy (*url, "ldap:///"),
+ stpcpy (stpcpy (stpcpy (stpcpy (stpcpy (stpcpy (stpcpy(*url, u_schema),
+ ":///"),
u_dn),
"?"),
attrs),
"?sub?"),
u_filter);
+ xfree (u_schema);
xfree (u_dn);
xfree (u_filter);
return 0;
@@ -525,6 +532,7 @@ start_cert_fetch_ldap (ctrl_t ctrl,
cert_fetch_context_t *context,
const char *user;
const char *pass;
const char *base;
+ const char *schema;
const char *argv[50];
int argc;
char portbuf[30], timeoutbuf[30];
@@ -538,6 +546,7 @@ start_cert_fetch_ldap (ctrl_t ctrl,
cert_fetch_context_t *context,
user = server->user;
pass = server->pass;
base = server->base;
+ schema = server->schema;
}
else /* Use a default server. */
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
@@ -545,6 +554,9 @@ start_cert_fetch_ldap (ctrl_t ctrl,
cert_fetch_context_t *context,
if (!base)
base = "";
+ if(!schema)
+ schema = "ldap";
+
argc = 0;
if (pass) /* Note: Must be the first item. */
{
@@ -606,9 +618,9 @@ start_cert_fetch_ldap (ctrl_t ctrl,
cert_fetch_context_t *context,
return gpg_error (GPG_ERR_INV_USER_ID);
}
if ((sl->flags & 1))
- err = make_url (&url, sl->d, "objectClass=*");
+ err = make_url (&url, sl->d, "objectClass=*", schema);
else
- err = make_url (&url, base, sl->d);
+ err = make_url (&url, base, sl->d, schema);
free_strlist (sl);
if (err)
{
diff --git a/dirmngr/ldapserver.c b/dirmngr/ldapserver.c
index 16e13e2..87c8b47 100644
--- a/dirmngr/ldapserver.c
+++ b/dirmngr/ldapserver.c
@@ -115,6 +115,11 @@ ldapserver_parse_one (char *line,
server->base = xstrdup (p);
break;
+ case 6:
+ if (*p)
+ server->schema = xstrdup (p);
+ break;
+
default:
/* (We silently ignore extra fields.) */
break;
diff --git a/dirmngr/server.c b/dirmngr/server.c
index 1b7e9e9..bcf83f9 100644
--- a/dirmngr/server.c
+++ b/dirmngr/server.c
@@ -1259,7 +1259,8 @@ lookup_cert_by_pattern (assuan_context_t ctx, char
*line,
ldap_server_t ldapserver = ldapserver_iter.server;
if (DBG_LOOKUP)
- log_debug ("cmd_lookup: trying %s:%d base=%s\n",
+ log_debug ("cmd_lookup: trying %s://%s:%d base=%s\n",
+ ldapserver->schema ? ldapserver->schema: "ldap",
ldapserver->host, ldapserver->port,
ldapserver->base?ldapserver->base : "[default]");
--
1.9.1
--
Best Regards!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/attachments/20150520/5c087749/attachment-0001.html>
More information about the Gnupg-devel
mailing list