[svn] dirmngr - r300 - in trunk: . jnlib src
svn author wk
cvs at cvs.gnupg.org
Tue Jun 10 12:05:21 CEST 2008
Author: wk
Date: 2008-06-10 12:05:20 +0200 (Tue, 10 Jun 2008)
New Revision: 300
Added:
trunk/src/b64dec.c
Modified:
trunk/ChangeLog
trunk/NEWS
trunk/configure.ac
trunk/jnlib/ChangeLog
trunk/jnlib/argparse.c
trunk/src/ChangeLog
trunk/src/Makefile.am
trunk/src/crlfetch.c
trunk/src/util.h
Log:
Support PEM encoded CRLs via HTTP.
[The diff below has been truncated]
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2008-05-26 15:07:04 UTC (rev 299)
+++ trunk/ChangeLog 2008-06-10 10:05:20 UTC (rev 300)
@@ -1,3 +1,7 @@
+2008-04-01 Werner Koch <wk at g10code.com>
+
+ * configure.ac (AC_INIT): Fix quoting.
+
2008-02-21 Werner Koch <wk at g10code.com>
* configure.ac: Check for gcry_md_debug.
Modified: trunk/jnlib/ChangeLog
===================================================================
--- trunk/jnlib/ChangeLog 2008-05-26 15:07:04 UTC (rev 299)
+++ trunk/jnlib/ChangeLog 2008-06-10 10:05:20 UTC (rev 300)
@@ -1,3 +1,7 @@
+2008-02-22 Werner Koch <wk at g10code.com>
+
+ * argparse.c (strusage): Set copyright year to 2008.
+
2008-02-12 Marcus Brinkmann <marcus at g10code.de>
* logging.c (do_logv): Flush the logstream.
Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog 2008-05-26 15:07:04 UTC (rev 299)
+++ trunk/src/ChangeLog 2008-06-10 10:05:20 UTC (rev 300)
@@ -1,3 +1,17 @@
+2008-06-10 Werner Koch <wk at g10code.com>
+
+ Support PEM encoded CRLs. Fixes bug#927.
+
+ * crlfetch.c (struct reader_cb_context_s): New.
+ (struct file_reader_map_s): Replace FP by new context.
+ (register_file_reader, get_file_reader): Adjust accordingly.
+ (my_es_read): Detect Base64 encoded CRL and decode if needed.
+ (crl_fetch): Pass new context to the callback.
+ (crl_close_reader): Cleanup the new context.
+ * b64dec.c: New. Taken from GnuPG.
+ * util.h (struct b64state): Add new fields STOP_SEEN and
+ INVALID_ENCODING.
+
2008-05-26 Marcus Brinkmann <marcus at g10code.com>
* dirmngr.c (main) [HAVE_W32_SYSTEM]: Switch to system
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2008-05-26 15:07:04 UTC (rev 299)
+++ trunk/NEWS 2008-06-10 10:05:20 UTC (rev 300)
@@ -10,7 +10,9 @@
* Improved certificate chain construction.
+ * Support loading of PEM encoded CRLs via HTTP.
+
Noteworthy changes in version 1.0.1 (2007-08-16)
------------------------------------------------
Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac 2008-05-26 15:07:04 UTC (rev 299)
+++ trunk/configure.ac 2008-06-10 10:05:20 UTC (rev 300)
@@ -31,7 +31,8 @@
m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \
|| echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')]))
-AC_INIT([dirmngr], my_version[]m4_if(my_issvn,[yes],[-svn[]svn_revision]),
+AC_INIT([dirmngr],
+ [my_version[]m4_if(my_issvn,[yes],[-svn[]svn_revision])],
[bug-dirmngr at gnupg.org])
NEED_GPG_ERROR_VERSION=1.4
Modified: trunk/jnlib/argparse.c
===================================================================
--- trunk/jnlib/argparse.c 2008-05-26 15:07:04 UTC (rev 299)
+++ trunk/jnlib/argparse.c 2008-06-10 10:05:20 UTC (rev 300)
@@ -1,6 +1,6 @@
/* [argparse.c wk 17.06.97] Argument Parser for option handling
* Copyright (C) 1998, 1999, 2000, 2001, 2006
- * 2007 Free Software Foundation, Inc.
+ * 2007, 2008 Free Software Foundation, Inc.
*
* This file is part of JNLIB.
*
@@ -936,7 +936,7 @@
switch( level ) {
case 11: p = "foo"; break;
case 13: p = "0.0"; break;
- case 14: p = "Copyright (C) 2007 Free Software Foundation, Inc."; break;
+ case 14: p = "Copyright (C) 2008 Free Software Foundation, Inc."; break;
case 15: p =
"This program comes with ABSOLUTELY NO WARRANTY.\n"
"This is free software, and you are welcome to redistribute it\n"
Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am 2008-05-26 15:07:04 UTC (rev 299)
+++ trunk/src/Makefile.am 2008-06-10 10:05:20 UTC (rev 300)
@@ -42,7 +42,7 @@
dirmngr_SOURCES = \
dirmngr.c dirmngr.h server.c crlcache.c crlfetch.c \
- certcache.c certcache.h i18n.h util.h \
+ certcache.c certcache.h i18n.h util.h b64dec.c \
cdb.h cdblib.c ldap.c http.c http.h misc.c ocsp.c ocsp.h \
estream.c estream.h estream-printf.c estream-printf.h \
validate.c validate.h exechelp.h exechelp.c get-path.c
Added: trunk/src/b64dec.c
===================================================================
--- trunk/src/b64dec.c 2008-05-26 15:07:04 UTC (rev 299)
+++ trunk/src/b64dec.c 2008-06-10 10:05:20 UTC (rev 300)
@@ -0,0 +1,217 @@
+/* b64dec.c - Simple Base64 decoder.
+ * Copyright (C) 2008 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "i18n.h"
+#include "util.h"
+
+
+/* The reverse base-64 list used for base-64 decoding. */
+static unsigned char const asctobin[128] =
+ {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+ 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+ 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+
+enum decoder_states
+ {
+ s_init, s_idle, s_lfseen, s_begin,
+ s_b64_0, s_b64_1, s_b64_2, s_b64_3,
+ s_waitendtitle, s_waitend
+ };
+
+
+
+/* Initialize the context for the base64 decoder. If TITLE is NULL a
+ plain base64 decoding is done. If it is the empty string the
+ decoder will skip everything until a "-----BEGIN " line has been
+ seen, decoding ends at a "----END " line.
+
+ Not yet implemented: If TITLE is either "PGP" or begins with "PGP "
+ the PGP armor lines are skipped as well. */
+gpg_error_t
+b64dec_start (struct b64state *state, const char *title)
+{
+ memset (state, 0, sizeof *state);
+ if (title)
+ {
+ if (!strncmp (title, "PGP", 3) && (!title[3] || title[3] == ' '))
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ state->title = xtrystrdup (title);
+ if (!state->title)
+ return gpg_error_from_syserror ();
+ state->idx = s_init;
+ }
+ else
+ state->idx = s_b64_0;
+ return 0;
+}
+
+
+/* Do in-place decoding of base-64 data of LENGTH in BUFFER. Stores the
+ new length of the buffer at R_NBYTES. */
+gpg_error_t
+b64dec_proc (struct b64state *state, void *buffer, size_t length,
+ size_t *r_nbytes)
+{
+ enum decoder_states ds = state->idx;
+ unsigned char val = state->radbuf[0];
+ int pos = state->quad_count;
+ char *d, *s;
+
+ if (state->stop_seen)
+ {
+ *r_nbytes = 0;
+ return gpg_error (GPG_ERR_EOF);
+ }
+
+ for (s=d=buffer; length && !state->stop_seen; length--, s++)
+ {
+ switch (ds)
+ {
+ case s_idle:
+ if (*s == '\n')
+ {
+ ds = s_lfseen;
+ pos = 0;
+ }
+ break;
+ case s_init:
+ ds = s_lfseen;
+ case s_lfseen:
+ if (*s != "-----BEGIN "[pos])
+ ds = s_idle;
+ else if (pos == 10)
+ ds = s_begin;
+ else
+ pos++;
+ break;
+ case s_begin:
+ if (*s == '\n')
+ ds = s_b64_0;
+ break;
+ case s_b64_0:
+ case s_b64_1:
+ case s_b64_2:
+ case s_b64_3:
+ {
+ int c;
+
+ if (*s == '-' && state->title)
+ {
+ /* Not a valid Base64 character: assume end
+ header. */
+ ds = s_waitend;
+ }
+ else if (*s == '=')
+ {
+ /* Pad character: stop */
+ if (ds == s_b64_1)
+ *d++ = val;
+ ds = state->title? s_waitendtitle : s_waitend;
+ }
+ else if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t')
+ ; /* Skip white spaces. */
+ else if ( (*s & 0x80)
+ || (c = asctobin[*(unsigned char *)s]) == 255)
+ {
+ /* Skip invalid encodings. */
+ state->invalid_encoding = 1;
+ }
+ else if (ds == s_b64_0)
+ {
+ val = c << 2;
+ ds = s_b64_1;
+ }
+ else if (ds == s_b64_1)
+ {
+ val |= (c>>4)&3;
+ *d++ = val;
+ val = (c<<4)&0xf0;
+ ds = s_b64_2;
+ }
+ else if (ds == s_b64_2)
+ {
+ val |= (c>>2)&15;
+ *d++ = val;
+ val = (c<<6)&0xc0;
+ ds = s_b64_3;
+ }
+ else
+ {
+ val |= c&0x3f;
+ *d++ = val;
+ ds = s_b64_0;
+ }
+ }
+ break;
+ case s_waitendtitle:
+ if (*s == '-')
+ ds = s_waitend;
+ break;
+ case s_waitend:
+ if ( *s == '\n')
+ state->stop_seen = 1;
+ break;
+ default:
+ BUG();
+ }
+ }
+
+
+ state->idx = ds;
+ state->radbuf[0] = val;
+ state->quad_count = pos;
+ *r_nbytes = (d -(char*) buffer);
+ return 0;
+}
+
+
+/* This function needs to be called before releasing the decoder
+ state. It may return an error code in case an encoding error has
+ been found during decoding. */
+gpg_error_t
+b64dec_finish (struct b64state *state)
+{
+ xfree (state->title);
+ state->title = NULL;
+ return state->invalid_encoding? gpg_error(GPG_ERR_BAD_DATA): 0;
+}
+
Modified: trunk/src/crlfetch.c
===================================================================
--- trunk/src/crlfetch.c 2008-05-26 15:07:04 UTC (rev 299)
+++ trunk/src/crlfetch.c 2008-06-10 10:05:20 UTC (rev 300)
@@ -31,12 +31,25 @@
#include "estream.h"
-/* We need to associate a reader object with file streams. This table
- is used for it. */
+
+/* For detecting armored CRLs received via HTTP (yes, such CRLS really
+ exits, e.g. http://grid.fzk.de/ca/gridka-crl.pem at least in June
+ 2008) we need a context in the reader callback. */
+struct reader_cb_context_s
+{
+ estream_t fp; /* The stream used with the ksba reader. */
+ int checked:1; /* PEM/binary detection ahs been done. */
+ int is_pem:1; /* The file stream is PEM encoded. */
+ struct b64state b64state; /* The state used for Base64 decoding. */
+};
+
+
+/* We need to associate a reader object with the reader callback
+ context. This table is used for it. */
struct file_reader_map_s
{
ksba_reader_t reader;
- estream_t fp;
+ struct reader_cb_context_s *cb_ctx;
};
#define MAX_FILE_READER 50
static struct file_reader_map_s file_reader_map[MAX_FILE_READER];
@@ -44,7 +57,7 @@
/* Associate FP with READER. If the table is full wait until another
thread has removed an entry. */
static void
-register_file_reader (ksba_reader_t reader, estream_t fp)
+register_file_reader (ksba_reader_t reader, struct reader_cb_context_s *cb_ctx)
{
int i;
@@ -54,7 +67,7 @@
if (!file_reader_map[i].reader)
{
file_reader_map[i].reader = reader;
- file_reader_map[i].fp = fp;
+ file_reader_map[i].cb_ctx = cb_ctx;
return;
}
log_info (_("reader to file mapping table full - waiting\n"));
@@ -62,23 +75,23 @@
}
}
-/* Scan the table for an entry matching READER, emove tha entry and
+/* Scan the table for an entry matching READER, remove that entry and
return the associated file pointer. */
-static estream_t
+static struct reader_cb_context_s *
get_file_reader (ksba_reader_t reader)
{
- estream_t fp = NULL;
+ struct reader_cb_context_s *cb_ctx = NULL;
int i;
for (i=0; i < MAX_FILE_READER; i++)
if (file_reader_map[i].reader == reader)
{
- fp = file_reader_map[i].fp;
+ cb_ctx = file_reader_map[i].cb_ctx;
file_reader_map[i].reader = NULL;
- file_reader_map[i].fp = NULL;
+ file_reader_map[i].cb_ctx = NULL;
break;
}
- return fp;
+ return cb_ctx;
}
@@ -86,7 +99,43 @@
static int
my_es_read (void *opaque, char *buffer, size_t nbytes, size_t *nread)
{
- return es_read (opaque, buffer, nbytes, nread);
+ struct reader_cb_context_s *cb_ctx = opaque;
+ int result;
+
+ result = es_read (cb_ctx->fp, buffer, nbytes, nread);
+ if (result)
+ return result;
+
+ if (!cb_ctx->checked && *nread)
+ {
+ int c = *(unsigned char *)buffer;
+
+ cb_ctx->checked = 1;
+ if ( ((c & 0xc0) >> 6) == 0 /* class: universal */
+ && (c & 0x1f) == 16 /* sequence */
+ && (c & 0x20) /* is constructed */ )
+ ; /* Binary data. */
+ else
+ {
+ cb_ctx->is_pem = 1;
+ b64dec_start (&cb_ctx->b64state, "");
+ }
+ }
+ if (cb_ctx->is_pem && *nread)
+ {
+ size_t nread2;
+
+ if (b64dec_proc (&cb_ctx->b64state, buffer, *nread, &nread2))
+ {
+ /* EOF from decoder. */
+ *nread = 0;
+ result = gpg_error (GPG_ERR_EOF);
+ }
+ else
+ *nread = nread2;
+ }
+
+ return result;
}
@@ -147,10 +196,18 @@
case 200:
{
estream_t fp = http_get_read_ptr (hd);
-
- err = ksba_reader_new (reader);
+ struct reader_cb_context_s *cb_ctx;
+
+ cb_ctx = xtrycalloc (1, sizeof *cb_ctx);
+ if (!cb_ctx)
+ err = gpg_error_from_syserror ();
if (!err)
- err = ksba_reader_set_cb (*reader, &my_es_read, fp);
+ err = ksba_reader_new (reader);
+ if (!err)
+ {
+ cb_ctx->fp = fp;
+ err = ksba_reader_set_cb (*reader, &my_es_read, cb_ctx);
+ }
if (err)
{
log_error (_("error initializing reader object: %s\n"),
@@ -161,7 +218,13 @@
}
else
{
- register_file_reader (*reader, fp);
+ /* The ksba reader misses a user pointer thus we need
+ to come up with our own way of associating a file
+ pointer (or well the callback context) with the
+ reader. It is only required when closing the
+ reader thus there is no performance issue doing it
+ this way. */
+ register_file_reader (*reader, cb_ctx);
http_close (hd, 1);
}
}
@@ -384,16 +447,25 @@
void
crl_close_reader (ksba_reader_t reader)
{
- estream_t fp;
+ struct reader_cb_context_s *cb_ctx;
if (!reader)
return;
/* Check whether this is a HTTP one. */
- fp = get_file_reader (reader);
- if (fp) /* This is an HTTP context. */
- es_fclose (fp);
- else /* This is an ldap wrapper context. */
+ cb_ctx = get_file_reader (reader);
+ if (cb_ctx)
+ {
+ /* This is an HTTP context. */
+ if (cb_ctx->fp)
+ es_fclose (cb_ctx->fp);
+ /* Release the base64 decoder state. */
+ if (cb_ctx->is_pem)
+ b64dec_finish (&cb_ctx->b64state);
+ /* Release the callback context. */
+ xfree (cb_ctx);
+ }
+ else /* This is an ldap wrapper context (Currently not used). */
ldap_wrapper_release_context (reader);
/* Now get rid of the reader object. */
Modified: trunk/src/util.h
===================================================================
--- trunk/src/util.h 2008-05-26 15:07:04 UTC (rev 299)
+++ trunk/src/util.h 2008-06-10 10:05:20 UTC (rev 300)
@@ -1,5 +1,5 @@
/* util.h
- * Copyright (C) 2004 g10 Code GmbH
+ * Copyright (C) 2004, 2008 g10 Code GmbH
*
* This file is part of DirMngr.
*
@@ -14,8 +14,7 @@
* 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
More information about the Gnupg-commits
mailing list