dirmngr (17 files)
cvs user wk
cvs at cvs.gnupg.org
Tue Nov 23 14:14:07 CET 2004
Date: Tuesday, November 23, 2004 @ 14:20:44
Author: wk
Path: /cvs/dirmngr/dirmngr
Added: src/b64enc.c
Modified: TODO src/ChangeLog src/Makefile.am src/certcache.c
src/crlfetch.c src/dirmngr-client.c src/dirmngr_ldap.c
src/ldap.c src/misc.c src/misc.h src/no-libgcrypt.c
src/no-libgcrypt.h src/ocsp.c src/ocsp.h src/server.c src/util.h
* dirmngr-client.c (do_lookup): New.
(main): New option --lookup.
(data_cb): New.
* b64enc.c: New. Taken from GnuPG 1.9.
* no-libgcrypt.c (gcry_strdup): Added.
* ocsp.c (ocsp_isvalid): New arg CERT and lookup the issuer
certificate using the standard methods.
* server.c (cmd_lookup): Truncation is now also an indication for
error.
(cmd_checkocsp): Implemented.
* dirmngr_ldap.c (fetch_ldap): Write an error marker for a
truncated search.
* ldap.c (add_server_to_servers): Reactivated.
(url_fetch_ldap): Call it here and try all configured servers in
case of a a failed lookup.
(fetch_next_cert_ldap): Detect the truncation error flag.
* misc.c (host_and_port_from_url, remove_percent_escapes): New.
----------------------+
TODO | 12 --
src/ChangeLog | 24 +++++
src/Makefile.am | 2
src/b64enc.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++++
src/certcache.c | 6 -
src/crlfetch.c | 31 -------
src/dirmngr-client.c | 106 ++++++++++++++++++++++--
src/dirmngr_ldap.c | 13 ++
src/ldap.c | 104 ++++++++++++++++++-----
src/misc.c | 104 +++++++++++++++++++++++
src/misc.h | 5 -
src/no-libgcrypt.c | 6 +
src/no-libgcrypt.h | 1
src/ocsp.c | 56 ++++++++----
src/ocsp.h | 3
src/server.c | 49 ++++++++++-
src/util.h | 17 +++
17 files changed, 644 insertions(+), 108 deletions(-)
Index: dirmngr/TODO
diff -u dirmngr/TODO:1.14 dirmngr/TODO:1.15
--- dirmngr/TODO:1.14 Tue Nov 16 19:24:36 2004
+++ dirmngr/TODO Tue Nov 23 14:20:44 2004
@@ -2,9 +2,6 @@
* Audit the code!
-* Dirmngr as system daemon
- We need to limit the length of inquires etc.
-
* Write a useful README
* Map LDAP error codes
@@ -15,15 +12,6 @@
This is the server where a baseDN has been given and that baseDN is
contained in the search pattern.
-* Properly parse LDAP attributes from the URL and remove the bad hack in crl_fetch.
-
-* Add --honor-http-proxy
-
* Properly use locks in crlcache.c
-* truncated
- Need to updated the code in ldap.c
-
-* In daemon mode we should put the cache files into /var/cache/dirmngr
-
Index: dirmngr/src/ChangeLog
diff -u dirmngr/src/ChangeLog:1.25 dirmngr/src/ChangeLog:1.26
--- dirmngr/src/ChangeLog:1.25 Mon Nov 22 22:30:50 2004
+++ dirmngr/src/ChangeLog Tue Nov 23 14:20:44 2004
@@ -1,3 +1,27 @@
+2004-11-23 Werner Koch <wk at g10code.com>
+
+ * dirmngr-client.c (do_lookup): New.
+ (main): New option --lookup.
+ (data_cb): New.
+ * b64enc.c: New. Taken from GnuPG 1.9.
+ * no-libgcrypt.c (gcry_strdup): Added.
+
+ * ocsp.c (ocsp_isvalid): New arg CERT and lookup the issuer
+ certificate using the standard methods.
+
+ * server.c (cmd_lookup): Truncation is now also an indication for
+ error.
+ (cmd_checkocsp): Implemented.
+
+ * dirmngr_ldap.c (fetch_ldap): Write an error marker for a
+ truncated search.
+ * ldap.c (add_server_to_servers): Reactivated.
+ (url_fetch_ldap): Call it here and try all configured servers in
+ case of a a failed lookup.
+ (fetch_next_cert_ldap): Detect the truncation error flag.
+
+ * misc.c (host_and_port_from_url, remove_percent_escapes): New.
+
2004-11-22 Werner Koch <wk at g10code.com>
* dirmngr_ldap.c (main): New option --proxy.
Index: dirmngr/src/Makefile.am
diff -u dirmngr/src/Makefile.am:1.19 dirmngr/src/Makefile.am:1.20
--- dirmngr/src/Makefile.am:1.19 Mon Nov 22 22:30:50 2004
+++ dirmngr/src/Makefile.am Tue Nov 23 14:20:44 2004
@@ -56,7 +56,7 @@
$(LDAP_LIBS)
-dirmngr_client_SOURCES = dirmngr-client.c i18n.h util.h maperror.c \
+dirmngr_client_SOURCES = dirmngr-client.c i18n.h util.h b64enc.c maperror.c \
no-libgcrypt.c no-libgcrypt.h
dirmngr_client_LDADD = ../jnlib/libjnlib.a $(LIBOBJS) $(LIBASSUAN_LIBS) \
$(GPG_ERROR_LIBS)
Index: dirmngr/src/b64enc.c
diff -u /dev/null dirmngr/src/b64enc.c:1.1
--- /dev/null Tue Nov 23 14:20:45 2004
+++ dirmngr/src/b64enc.c Tue Nov 23 14:20:44 2004
@@ -0,0 +1,213 @@
+/* b64enc.c - Simple Base64 encoder.
+ * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "i18n.h"
+#include "util.h"
+
+#define B64ENC_DID_HEADER 1
+#define B64ENC_DID_TRAILER 2
+#define B64ENC_NO_LINEFEEDS 16
+
+
+/* The base-64 character list */
+static unsigned char bintoasc[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+
+/* Prepare for base-64 writing to the stream FP. If TITLE is not NULL
+ and not an empty string, this string will be used as the title for
+ the armor lines, with TITLE being an empty string, we don't write
+ the header lines and furthermore even don't write any linefeeds.
+ With TITLE beeing NULL, we merely don't write header but make sure
+ that lines are not too long. Note, that we don't write any output
+ unless at least one byte get written using b64enc_write. */
+gpg_error_t
+b64enc_start (struct b64state *state, FILE *fp, const char *title)
+{
+ memset (state, 0, sizeof *state);
+ state->fp = fp;
+ if (title && !*title)
+ state->flags |= B64ENC_NO_LINEFEEDS;
+ else if (title)
+ {
+ state->title = xtrystrdup (title);
+ if (!state->title)
+ return gpg_error_from_errno (errno);
+ }
+ return 0;
+}
+
+
+/* Write NBYTES from BUFFER to the Base 64 stream identified by
+ STATE. With BUFFER and NBYTES being 0, merely do a fflush on the
+ stream. */
+gpg_error_t
+b64enc_write (struct b64state *state, const void *buffer, size_t nbytes)
+{
+ unsigned char radbuf[4];
+ int idx, quad_count;
+ const unsigned char *p;
+ FILE *fp = state->fp;
+
+
+ if (!nbytes)
+ {
+ if (buffer && fflush (fp))
+ goto write_error;
+ return 0;
+ }
+
+ if (!(state->flags & B64ENC_DID_HEADER))
+ {
+ if (state->title)
+ {
+ if ( fputs ("-----BEGIN ", fp) == EOF
+ || fputs (state->title, fp) == EOF
+ || fputs ("-----\n", fp) == EOF)
+ goto write_error;
+ }
+ state->flags |= B64ENC_DID_HEADER;
+ }
+
+ idx = state->idx;
+ quad_count = state->quad_count;
+ assert (idx < 4);
+ memcpy (radbuf, state->radbuf, idx);
+
+ for (p=buffer; nbytes; p++, nbytes--)
+ {
+ radbuf[idx++] = *p;
+ if (idx > 2)
+ {
+ char tmp[4];
+
+ tmp[0] = bintoasc[(*radbuf >> 2) & 077];
+ tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
+ tmp[2] = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
+ tmp[3] = bintoasc[radbuf[2]&077];
+ for (idx=0; idx < 4; idx++)
+ putc (tmp[idx], fp);
+ idx = 0;
+ if (ferror (fp))
+ goto write_error;
+ if (++quad_count >= (64/4))
+ {
+ quad_count = 0;
+ if (!(state->flags & B64ENC_NO_LINEFEEDS)
+ && fputs ("\n", fp) == EOF)
+ goto write_error;
+ }
+ }
+ }
+ memcpy (state->radbuf, radbuf, idx);
+ state->idx = idx;
+ state->quad_count = quad_count;
+ return 0;
+
+ write_error:
+ return gpg_error_from_errno (errno);
+}
+
+gpg_error_t
+b64enc_finish (struct b64state *state)
+{
+ gpg_error_t err = 0;
+ unsigned char radbuf[4];
+ int idx, quad_count;
+ FILE *fp;
+
+ if (!(state->flags & B64ENC_DID_HEADER))
+ goto cleanup;
+
+ /* Flush the base64 encoding */
+ fp = state->fp;
+ idx = state->idx;
+ quad_count = state->quad_count;
+ assert (idx < 4);
+ memcpy (radbuf, state->radbuf, idx);
+
+ if (idx)
+ {
+ char tmp[4];
+
+ tmp[0] = bintoasc[(*radbuf>>2)&077];
+ if (idx == 1)
+ {
+ tmp[1] = bintoasc[((*radbuf << 4) & 060) & 077];
+ tmp[2] = '=';
+ tmp[3] = '=';
+ }
+ else
+ {
+ tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
+ tmp[2] = bintoasc[((radbuf[1] << 2) & 074) & 077];
+ tmp[3] = '=';
+ }
+ for (idx=0; idx < 4; idx++)
+ putc (tmp[idx], fp);
+ idx = 0;
+ if (ferror (fp))
+ goto write_error;
+
+ if (++quad_count >= (64/4))
+ {
+ quad_count = 0;
+ if (!(state->flags & B64ENC_NO_LINEFEEDS)
+ && fputs ("\n", fp) == EOF)
+ goto write_error;
+ }
+ }
+
+ /* Finish the last line and write the trailer. */
+ if (quad_count
+ && !(state->flags & B64ENC_NO_LINEFEEDS)
+ && fputs ("\n", fp) == EOF)
+ goto write_error;
+
+ if (state->title)
+ {
+ if ( fputs ("-----END ", fp) == EOF
+ || fputs (state->title, fp) == EOF
+ || fputs ("-----\n", fp) == EOF)
+ goto write_error;
+ }
+
+ goto cleanup;
+
+ write_error:
+ err = gpg_error_from_errno (errno);
+
+ cleanup:
+ if (state->title)
+ {
+ xfree (state->title);
+ state->title = NULL;
+ }
+ state->fp = NULL;
+ return err;
+}
+
Index: dirmngr/src/certcache.c
diff -u dirmngr/src/certcache.c:1.5 dirmngr/src/certcache.c:1.6
--- dirmngr/src/certcache.c:1.5 Mon Nov 22 22:30:50 2004
+++ dirmngr/src/certcache.c Tue Nov 23 14:20:44 2004
@@ -709,9 +709,3 @@
return err;
}
-
-
-
-
-
-
Index: dirmngr/src/crlfetch.c
diff -u dirmngr/src/crlfetch.c:1.21 dirmngr/src/crlfetch.c:1.22
--- dirmngr/src/crlfetch.c:1.21 Mon Nov 22 22:30:50 2004
+++ dirmngr/src/crlfetch.c Tue Nov 23 14:20:44 2004
@@ -111,8 +111,6 @@
}
else /* Let the LDAP code try other schemes. */
{
- const char *s;
-
if (opt.disable_ldap)
{
log_error (_("CRL access not possible due to disabled %s\n"),
@@ -121,35 +119,6 @@
}
else
err = url_fetch_ldap (ctrl, url, NULL, 0, reader);
-
-/* if (err) */
-/* { */
-/* /\* If the function failed we try again using our default */
-/* host. *\/ */
-/* ldap_server_t server; */
-/* char *savehost; */
-/* int saveport; */
-
-/* if (DBG_LOOKUP) */
-/* log_debug ("no hostname in URL or query failed; " */
-/* "trying all default hostnames\n"); */
-/* savehost = ludp->lud_host; */
-/* saveport = ludp->lud_port; */
-/* for (server = opt.ldapservers; server; server = server->next) */
-/* { */
-/* ludp->lud_host = server->host; */
-/* ludp->lud_port = server->port; */
-/* err = url_fetch_ldap_internal (ludp, attr, value, valuelen); */
-/* if (!err) */
-/* break; */
-/* } */
-/* ludp->lud_host = savehost; */
-/* ludp->lud_port = saveport; */
-/* if (opt.add_new_ldapservers) */
-/* add_server_to_servers (ludp->lud_host, ludp->lud_port); */
-
-/* } */
-
}
if (free_this)
xfree (free_this);
Index: dirmngr/src/dirmngr-client.c
diff -u dirmngr/src/dirmngr-client.c:1.3 dirmngr/src/dirmngr-client.c:1.4
--- dirmngr/src/dirmngr-client.c:1.3 Fri Nov 19 16:27:28 2004
+++ dirmngr/src/dirmngr-client.c Tue Nov 23 14:20:44 2004
@@ -54,6 +54,7 @@
oPing,
oCacheCert,
oValidate,
+ oLookup,
oUseDaemon,
oDummy
};
@@ -68,6 +69,7 @@
{ oPing, "ping", 0, N_("check whether a dirmngr is running")},
{ oCacheCert,"cache-cert",0, N_("add a certificate to the cache")},
{ oValidate, "validate", 0, N_("validate a certificate")},
+ { oLookup, "lookup", 0, N_("lookup a certificate")},
{0}
};
@@ -105,6 +107,7 @@
const unsigned char *cert, size_t certlen);
static gpg_error_t do_validate (assuan_context_t ctx,
const unsigned char *cert, size_t certlen);
+static gpg_error_t do_lookup (assuan_context_t ctx, const char *pattern);
@@ -116,7 +119,7 @@
switch(level)
{
- case 11: p = "dirmngr-client";
+ case 11: p = "dirmngr-client (dirmngr)";
break;
case 13: p = VERSION; break;
case 14: p = "Copyright (C) 2004 g10 Code GmbH"; break;
@@ -126,10 +129,11 @@
break;
case 1:
case 40: p =
- _("Usage: dirmngr-client [options] [certfile] (-h for help)\n");
+ _("Usage: dirmngr-client [options] "
+ "[certfile|pattern] (-h for help)\n");
break;
case 41: p =
- _("Syntax: dirmngr-client [options] [certfile]\n"
+ _("Syntax: dirmngr-client [options] [certfile|pattern]\n"
"Test an X.509 certificate against a CRL or do an OCSP check\n"
"The process returns 0 if the certificate is valid, 1 if it is\n"
"not valid and other error codes for general failures\n");
@@ -163,11 +167,11 @@
assuan_context_t ctx;
gpg_error_t err;
unsigned char *certbuf;
- size_t certbuflen;
+ size_t certbuflen = 0;
int cmd_ping = 0;
- int use_daemon = 0;
int cmd_cache_cert = 0;
int cmd_validate = 0;
+ int cmd_lookup = 0;
set_strusage (my_strusage);
log_set_prefix ("dirmngr-client",
@@ -190,12 +194,12 @@
{
case oVerbose: opt.verbose++; break;
case oQuiet: opt.quiet++; break;
- case oUseDaemon: use_daemon = 1; break;
case oOCSP: opt.use_ocsp++; break;
case oPing: cmd_ping = 1; break;
case oCacheCert: cmd_cache_cert = 1; break;
case oValidate: cmd_validate = 1; break;
+ case oLookup: cmd_lookup = 1; break;
default : pargs.err = 2; break;
}
@@ -205,6 +209,12 @@
if (cmd_ping)
err = 0;
+ else if (cmd_lookup)
+ {
+ if (!argc)
+ usage (1);
+ err = 0;
+ }
else if (!argc)
{
err = read_certificate (NULL, &certbuf, &certbuflen);
@@ -234,12 +244,27 @@
exit (2);
}
- ctx = start_dirmngr (cmd_ping || use_daemon);
+ ctx = start_dirmngr (1);
if (!ctx)
exit (2);
if (cmd_ping)
;
+ else if (cmd_lookup)
+ {
+ int last_err = 0;
+
+ for (; argc; argc--, argv++)
+ {
+ err = do_lookup (ctx, *argv);
+ if (err)
+ {
+ log_error (_("lookup failed: %s\n"), gpg_strerror (err));
+ last_err = err;
+ }
+ }
+ err = last_err;
+ }
else if (cmd_cache_cert)
{
err = do_cache (ctx, certbuf, certbuflen);
@@ -264,6 +289,8 @@
log_info (_("a dirmngr daemon is up and running\n"));
return 0;
}
+ else if (cmd_lookup)
+ return err? 1:0;
else if (cmd_cache_cert)
{
if (err && gpg_err_code (err) == GPG_ERR_DUP_VALUE )
@@ -314,6 +341,24 @@
return 0;
}
+/* Print data as retrieved by the lookup function. */
+static assuan_error_t
+data_cb (void *opaque, const void *buffer, size_t length)
+{
+ gpg_error_t err;
+ struct b64state *state = opaque;
+
+ if (buffer)
+ {
+ err = b64enc_write (state, buffer, length);
+ if (err)
+ log_error (_("error writing base64 encoding: %s\n"),
+ gpg_strerror (err));
+ }
+ return 0;
+}
+
+
/* Try to connect to the dirmngr via socket or fork it off and work by
pipes. Handle the server's initial greeting */
static assuan_context_t
@@ -569,3 +614,50 @@
log_info ("response of dirmngr: %s\n", ae? assuan_strerror (ae): "okay");
return map_assuan_err (ae);
}
+
+static gpg_error_t
+do_lookup (assuan_context_t ctx, const char *pattern)
+{
+ gpg_error_t err;
+ assuan_error_t ae;
+ const unsigned char *s;
+ char *line, *p;
+ struct b64state state;
+
+ if (opt.verbose)
+ log_info (_("looking up `%s'\n"), pattern);
+
+ err = b64enc_start (&state, stdout, NULL);
+ if (err)
+ return err;
+
+ line = xmalloc (10 + strlen (pattern)*3 + 1);
+
+ p = stpcpy (line, "LOOKUP ");
+ for (s=pattern; *s; s++)
+ {
+ if (*s < ' ' || *s == '+')
+ {
+ sprintf (p, "%%%02X", *s);
+ p += 3;
+ }
+ else if (*s == ' ')
+ *p++ = '+';
+ else
+ *p++ = *s;
+ }
+ *p = 0;
+
+
+ ae = assuan_transact (ctx, line,
+ data_cb, &state,
+ NULL, NULL,
+ status_cb, NULL);
+ if (opt.verbose > 1)
+ log_info ("response of dirmngr: %s\n", ae? assuan_strerror (ae): "okay");
+
+ err = b64enc_finish (&state);
+
+ xfree (line);
+ return ae? map_assuan_err (ae) : err;
+}
Index: dirmngr/src/dirmngr_ldap.c
diff -u dirmngr/src/dirmngr_ldap.c:1.3 dirmngr/src/dirmngr_ldap.c:1.4
--- dirmngr/src/dirmngr_ldap.c:1.3 Mon Nov 22 22:30:50 2004
+++ dirmngr/src/dirmngr_ldap.c Tue Nov 23 14:20:44 2004
@@ -125,7 +125,7 @@
switch(level)
{
- case 11: p = "dirmngr_ldap";
+ case 11: p = "dirmngr_ldap (dirmngr)";
break;
case 13: p = VERSION; break;
case 14: p = "Copyright (C) 2004 g10 Code GmbH"; break;
@@ -466,7 +466,16 @@
ludp->lud_attrs:attrs,
0,
&opt.timeout, &msg);
- if (rc)
+ if (rc == LDAP_SIZELIMIT_EXCEEDED && opt.multi)
+ {
+ if (fwrite ("E\0\0\0\x09truncated", 14, 1, stdout) != 1)
+ {
+ log_error (_("error writing to stdout: %s\n"),
+ strerror (errno));
+ return -1;
+ }
+ }
+ else if (rc)
{
log_error (_("searching `%s' failed: %s\n"),
url, ldap_err2string (rc));
Index: dirmngr/src/ldap.c
diff -u dirmngr/src/ldap.c:1.36 dirmngr/src/ldap.c:1.37
--- dirmngr/src/ldap.c:1.36 Mon Nov 22 22:30:50 2004
+++ dirmngr/src/ldap.c Tue Nov 23 14:20:44 2004
@@ -58,6 +58,7 @@
ksba_reader_t reader; /* The reader used (shallow copy). */
unsigned char *tmpbuf; /* Helper buffer. */
size_t tmpbufsize; /* Allocated size of tmpbuf. */
+ int truncated; /* Flag to indicate a truncated output. */
};
@@ -91,7 +92,7 @@
static struct wrapper_context_s *wrapper_list;
-#if 0
+
/* Add HOST and PORT to our list of LDAP servers. Fixme: We should
better use an extra list of servers. */
static void
@@ -101,6 +102,9 @@
ldap_server_t last = NULL;
const char *s;
+ if (!port)
+ port = 389;
+
for (server=opt.ldapservers; server; server = server->next)
{
if (!strcmp (server->host, host) && server->port == port)
@@ -116,21 +120,25 @@
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"01234567890.-", *s))
{
- log_error (_("invalid char 0x%02x in host name"
- " - not added\n"), *s);
+ log_error (_("invalid char 0x%02x in host name - not added\n"), *s);
return;
}
log_info (_("adding `%s:%d' to the ldap server list\n"), host, port);
- server = xcalloc (1, sizeof *s);
- server->host = xstrdup (host);
- server->port = port;
- if (last)
- last->next = server;
+ server = xtrycalloc (1, sizeof *s);
+ if (!server)
+ log_error (_("malloc failed: %s\n"), strerror (errno));
else
- opt.ldapservers = server;
+ {
+ server->host = xstrdup (host);
+ server->port = port;
+ if (last)
+ last->next = server;
+ else
+ opt.ldapservers = server;
+ }
}
-#endif
+
/* Release the wrapper context and kill a running wrapper process. */
static void
@@ -745,13 +753,46 @@
NULL, NULL, NULL, url,
reader);
- return err;
/* FIXME: This option might be used for DoS attacks. Becuase it
will enlarge the list of servers to consult without a limit and
all LDAP queries w/o a host are will then try each host in
- turn. */
-/* if (opt.add_new_ldapservers) */
-/* add_server_to_servers (ludp->lud_host, ludp->lud_port); */
+ turn. */
+ if (!err && opt.add_new_ldapservers && !opt.ldap_proxy)
+ {
+ if (host)
+ add_server_to_servers (host, port);
+ else if (url)
+ {
+ char *tmp = host_and_port_from_url (url, &port);
+ add_server_to_servers (host, port);
+ xfree (tmp);
+ }
+ }
+
+ /* If the lookup failed and we are not only using the proxy, we try
+ again using our default list of servers. */
+ if (err && !(opt.ldap_proxy && opt.only_ldap_proxy))
+ {
+ ldap_server_t server;
+
+ if (DBG_LOOKUP)
+ log_debug ("no hostname in URL or query failed; "
+ "trying all default hostnames\n");
+
+ for (server = opt.ldapservers; err && server; server = server->next)
+ {
+ err = run_ldap_wrapper (ctrl,
+ NULL,
+ server->host, server->port,
+ NULL, NULL,
+ NULL, NULL, NULL, url,
+ reader);
+ if (!err)
+ break;
+ }
+ }
+
+ return err;
}
@@ -766,6 +807,9 @@
gpg_error_t err = gpg_error (GPG_ERR_CONFIGURATION);
*reader = NULL;
+
+ /* FIXME; we might want to look at the Base SN to try matching
+ servers first. */
for (server = opt.ldapservers; server; server = server->next)
{
err = run_ldap_wrapper (ctrl,
@@ -1087,9 +1131,10 @@
}
-/* Fetch the next certificate. Return 0 on success, GPG_ERR_EOF
- if no (more) certificates are available or any other error
- code. */
+/* Fetch the next certificate. Return 0 on success, GPG_ERR_EOF if no
+ (more) certificates are available or any other error
+ code. GPG_ERR_TRUNCATED may be returned to indicate tha the result
+ has been truncated. */
gpg_error_t
fetch_next_cert_ldap (cert_fetch_context_t context,
unsigned char **value, size_t *valuelen)
@@ -1099,7 +1144,6 @@
char *p, *pend;
int n;
int okay = 0;
- int truncated = 0;
*value = NULL;
*valuelen = 0;
@@ -1164,23 +1208,33 @@
okay = 0;
}
}
+ else if (*hdr == 'E')
+ {
+ p = context->tmpbuf;
+ p[n] = 0; /*(we allocated one extra byte for this.)*/
+ if (!strcmp (p, "truncated"))
+ {
+ context->truncated = 1;
+ log_info (_("ldap_search hit the size limit of"
+ " the server\n"));
+ }
+ }
}
}
-
+
if (err)
{
xfree (*value);
*value = NULL;
*valuelen = 0;
+ if (gpg_err_code (err) == GPG_ERR_EOF && context->truncated)
+ {
+ context->truncated = 0; /* So that the next call would return EOF. */
+ err = gpg_error (GPG_ERR_TRUNCATED);
+ }
}
return err;
-
-
-/* if (rc == LDAP_SIZELIMIT_EXCEEDED) */
-/* { */
- /* truncated = 1; */
-/* log_info (_("ldap_search hit the size limit of the server\n")); */
}
Index: dirmngr/src/misc.c
diff -u dirmngr/src/misc.c:1.8 dirmngr/src/misc.c:1.9
--- dirmngr/src/misc.c:1.8 Tue Nov 16 19:24:35 2004
+++ dirmngr/src/misc.c Tue Nov 23 14:20:44 2004
@@ -24,7 +24,9 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
+#include <errno.h>
+#include "util.h"
#include "misc.h"
#include "dirmngr.h"
@@ -569,3 +571,105 @@
}
log_debug ("END Certificate\n");
}
+
+
+/****************
+ * Remove all %xx escapes; this is done inplace.
+ * Returns: New length of the string.
+ */
+static int
+remove_percent_escapes (unsigned char *string)
+{
+ int n = 0;
+ unsigned char *p, *s;
+
+ for (p = s = string; *s; s++)
+ {
+ if (*s == '%')
+ {
+ if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
+ {
+ s++;
+ *p = xtoi_2 (s);
+ s++;
+ p++;
+ n++;
+ }
+ else
+ {
+ *p++ = *s++;
+ if (*s)
+ *p++ = *s++;
+ if (*s)
+ *p++ = *s++;
+ if (*s)
+ *p = 0;
+ return -1; /* Bad URI. */
+ }
+ }
+ else
+ {
+ *p++ = *s;
+ n++;
+ }
+ }
+ *p = 0; /* Always keep a string terminator. */
+ return n;
+}
+
+
+/* Return the host name and the port (0 if none was given) from the
+ URL. Return NULL on error or if host is not included in the
+ URL. */
+char *
+host_and_port_from_url (const char *url, int *port)
+{
+ const char *s, *s2;
+ char *buf, *p;
+ int n;
+
+ s = url;
+
+ *port = 0;
+
+ /* Find the scheme */
+ if ( !(s2 = strchr (s, ':')) || s2 == s )
+ return NULL; /* No scheme given. */
+ s = s2+1;
+
+ /* Find the hostname */
+ if (*s != '/')
+ return NULL; /* Does not start with a slash. */
+
+ s++;
+ if (*s != '/')
+ return NULL; /* No host name. */
+ s++;
+
+ buf = xtrystrdup (s);
+ if (!buf)
+ {
+ log_error (_("malloc failed: %s\n"), strerror (errno));
+ return NULL;
+ }
+ if ((p = strchr (buf, '/')))
+ *p++ = 0;
+ strlwr (buf);
+ if ((p = strchr (p, ':')))
+ {
+ *p++ = 0;
+ *port = atoi (p);
+ }
+
+ /* Remove quotes and make sure that no Nul has been encoded. */
+ if ((n = remove_percent_escapes (buf)) < 0
+ || n != strlen (p) )
+ {
+ log_error (_("bad URL encoding detected\n"));
+ xfree (buf);
+ return NULL;
+ }
+
+ return buf;
+}
+
Index: dirmngr/src/misc.h
diff -u dirmngr/src/misc.h:1.8 dirmngr/src/misc.h:1.9
--- dirmngr/src/misc.h:1.8 Tue Nov 16 19:24:35 2004
+++ dirmngr/src/misc.h Tue Nov 23 14:20:44 2004
@@ -100,7 +100,10 @@
TEXT. This is used for debugging. */
void dump_cert (const char *text, ksba_cert_t cert);
-
+/* Return the host name and the port (0 if none was given) from the
+ URL. Return NULL on error or if host is not included in the
+ URL. */
+char *host_and_port_from_url (const char *url, int *port);
#ifdef HAVE_FOPENCOOKIE
Index: dirmngr/src/no-libgcrypt.c
diff -u dirmngr/src/no-libgcrypt.c:1.1 dirmngr/src/no-libgcrypt.c:1.2
--- dirmngr/src/no-libgcrypt.c:1.1 Tue Nov 16 19:24:35 2004
+++ dirmngr/src/no-libgcrypt.c Tue Nov 23 14:20:44 2004
@@ -90,6 +90,12 @@
char *
+gcry_strdup (const char *string)
+{
+ return strdup (string);
+}
+
+char *
gcry_xstrdup (const char *string)
{
void *p = malloc (strlen (string)+1);
Index: dirmngr/src/no-libgcrypt.h
diff -u dirmngr/src/no-libgcrypt.h:1.1 dirmngr/src/no-libgcrypt.h:1.2
--- dirmngr/src/no-libgcrypt.h:1.1 Tue Nov 16 19:24:35 2004
+++ dirmngr/src/no-libgcrypt.h Tue Nov 23 14:20:44 2004
@@ -27,6 +27,7 @@
void *gcry_xrealloc (void *a, size_t n);
void *gcry_calloc (size_t n, size_t m);
void *gcry_xcalloc (size_t n, size_t m);
+char *gcry_strdup (const char *string);
char *gcry_xstrdup (const char *string);
void gcry_free (void *a);
Index: dirmngr/src/ocsp.c
diff -u dirmngr/src/ocsp.c:1.10 dirmngr/src/ocsp.c:1.11
--- dirmngr/src/ocsp.c:1.10 Mon Nov 22 22:30:50 2004
+++ dirmngr/src/ocsp.c Tue Nov 23 14:20:44 2004
@@ -28,6 +28,7 @@
#include "misc.h"
#include "http.h"
#include "validate.h"
+#include "certcache.h"
#include "ocsp.h"
@@ -386,12 +387,14 @@
}
+/* Check whether the certificate either given by fingerprint CERT_FPR
+ or directly through a the CERT object is valid by running an OCSP
+ transaction. */
gpg_error_t
-ocsp_isvalid (ctrl_t ctrl, const char *cert_fpr)
+ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr)
{
gpg_error_t err;
ksba_ocsp_t ocsp = NULL;
- ksba_cert_t cert = NULL;
ksba_cert_t issuer_cert = NULL;
ksba_sexp_t sigval = NULL;
gcry_sexp_t s_sig = NULL;
@@ -407,6 +410,38 @@
ksba_name_t name;
const char *default_signer = NULL;
+ /* Get the certificate. */
+ if (cert)
+ {
+ ksba_cert_ref (cert);
+
+ err = find_issuing_cert (ctrl, cert, &issuer_cert);
+ if (err)
+ {
+ log_error (_("issuer certificate not found: %s\n"),
+ gpg_strerror (err));
+ goto leave;
+ }
+ }
+ else
+ {
+ cert = get_cert_local (ctrl, cert_fpr);
+ if (!cert)
+ {
+ log_error (_("caller did not return the target certificate\n"));
+ err = gpg_error (GPG_ERR_GENERAL);
+ goto leave;
+ }
+ issuer_cert = get_issuing_cert_local (ctrl, NULL);
+ if (!issuer_cert)
+ {
+ log_error (_("caller did not return the issuing certificate\n"));
+ err = gpg_error (GPG_ERR_GENERAL);
+ goto leave;
+ }
+ }
+
+ /* Create an OCSP instance. */
err = ksba_ocsp_new (&ocsp);
if (err)
{
@@ -415,22 +450,7 @@
goto leave;
}
- /* We don't have any caching yet implemented thus we need to get the
- certificate right now. */
- cert = get_cert_local (ctrl, cert_fpr);
- if (!cert)
- {
- log_error (_("caller did not return the target certificate\n"));
- err = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
- issuer_cert = get_issuing_cert_local (ctrl, NULL);
- if (!issuer_cert)
- {
- log_error (_("caller did not return the issuing certificate\n"));
- err = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
+
/* Figure out the OCSP responder to use.
1. Try to get the reponder from the certificate.
Index: dirmngr/src/ocsp.h
diff -u dirmngr/src/ocsp.h:1.1 dirmngr/src/ocsp.h:1.2
--- dirmngr/src/ocsp.h:1.1 Thu Dec 11 12:25:25 2003
+++ dirmngr/src/ocsp.h Tue Nov 23 14:20:44 2004
@@ -21,7 +21,6 @@
#ifndef OCSP_H
#define OCSP_H
-gpg_error_t ocsp_isvalid (ctrl_t ctrl, const char *cert_fpr);
-
+gpg_error_t ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr);
#endif /*OCSP_H*/
Index: dirmngr/src/server.c
diff -u dirmngr/src/server.c:1.46 dirmngr/src/server.c:1.47
--- dirmngr/src/server.c:1.46 Mon Nov 22 22:30:50 2004
+++ dirmngr/src/server.c Tue Nov 23 14:20:44 2004
@@ -313,7 +313,7 @@
if (!opt.allow_ocsp)
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
else
- err = ocsp_isvalid (ctrl, NULL);
+ err = ocsp_isvalid (ctrl, NULL, NULL);
/* Fixme: If we got no ocsp response we should fall back to CRL
mode. Thus we need to clear OCSP_MODE, get the issuerhash
and the serialno from the current certificate and jump to
@@ -497,13 +497,55 @@
static int
cmd_checkocsp (assuan_context_t ctx, char *line)
{
-/* ctrl_t ctrl = assuan_get_pointer (ctx); */
+ ctrl_t ctrl = assuan_get_pointer (ctx);
gpg_error_t err;
+ unsigned char fprbuffer[20], *fpr;
+ ksba_cert_t cert;
- err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ fpr = get_fingerprint_from_line (line, fprbuffer);
+ cert = fpr? get_cert_byfpr (fpr) : NULL;
+
+ if (!cert)
+ {
+ /* We do not have this certificate yet or the fingerprint has
+ not been given. Inquire it from the client. */
+ assuan_error_t ae;
+ unsigned char *value = NULL;
+ size_t valuelen;
+
+ ae = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
+ &value, &valuelen, MAX_CERT_LENGTH);
+ if (ae)
+ {
+ log_error (_("assuan_inquire failed: %s\n"), assuan_strerror (ae));
+ err = map_assuan_err (ae);
+ goto leave;
+ }
+
+ if (!valuelen) /* No data returned; return a comprehensible error. */
+ err = gpg_error (GPG_ERR_MISSING_CERT);
+ else
+ {
+ err = ksba_cert_new (&cert);
+ if (!err)
+ err = ksba_cert_init_from_mem (cert, value, valuelen);
+ }
+ xfree (value);
+ if(err)
+ goto leave;
+ }
+
+ assert (cert);
+
+ if (!opt.allow_ocsp)
+ err = gpg_error (GPG_ERR_NOT_SUPPORTED);
+ else
+ err = ocsp_isvalid (ctrl, cert, NULL);
+ leave:
if (err)
log_error (_("command %s failed: %s\n"), "CHECKOCSP", gpg_strerror (err));
+ ksba_cert_release (cert);
return map_to_assuan_status (err);
}
@@ -583,6 +625,7 @@
{
truncated = 1;
err = 0;
+ break; /* Ready. */
}
if (gpg_err_code (err) == GPG_ERR_EOF)
{
Index: dirmngr/src/util.h
diff -u dirmngr/src/util.h:1.1 dirmngr/src/util.h:1.2
--- dirmngr/src/util.h:1.1 Tue Nov 16 19:24:35 2004
+++ dirmngr/src/util.h Tue Nov 23 14:20:44 2004
@@ -23,6 +23,23 @@
#include <gpg-error.h>
+/*-- b64enc.c --*/
+struct b64state
+{
+ unsigned int flags;
+ int idx;
+ int quad_count;
+ FILE *fp;
+ char *title;
+ unsigned char radbuf[4];
+};
+gpg_error_t b64enc_start (struct b64state *state, FILE *fp, const char *title);
+gpg_error_t b64enc_write (struct b64state *state,
+ const void *buffer, size_t nbytes);
+gpg_error_t b64enc_finish (struct b64state *state);
+
+
+
/*-- maperror.c --*/
gpg_error_t map_assuan_err (int err);
More information about the Gnupg-commits
mailing list