dirmngr/src (ChangeLog dirmngr-client.c)
cvs user wk
cvs at cvs.gnupg.org
Mon Jan 3 21:36:30 CET 2005
Date: Monday, January 3, 2005 @ 21:42:46
Author: wk
Path: /cvs/dirmngr/dirmngr/src
Modified: ChangeLog dirmngr-client.c
(read_pem_certificate): New.
(read_certificate): Divert to it depending on pem option.
(squid_loop_body): New.
(main): New options --pem and --squid-mode.
------------------+
ChangeLog | 7 +
dirmngr-client.c | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 257 insertions(+), 4 deletions(-)
Index: dirmngr/src/ChangeLog
diff -u dirmngr/src/ChangeLog:1.39 dirmngr/src/ChangeLog:1.40
--- dirmngr/src/ChangeLog:1.39 Fri Dec 17 16:16:12 2004
+++ dirmngr/src/ChangeLog Mon Jan 3 21:42:46 2005
@@ -1,3 +1,10 @@
+2005-01-03 Werner Koch <wk at g10code.com>
+
+ * dirmngr-client.c (read_pem_certificate): New.
+ (read_certificate): Divert to it depending on pem option.
+ (squid_loop_body): New.
+ (main): New options --pem and --squid-mode.
+
2004-12-17 Werner Koch <wk at g10code.com>
* dirmngr.c (launch_ripper_thread): Renamed to launch_reaper_thread.
Index: dirmngr/src/dirmngr-client.c
diff -u dirmngr/src/dirmngr-client.c:1.6 dirmngr/src/dirmngr-client.c:1.7
--- dirmngr/src/dirmngr-client.c:1.6 Fri Dec 3 15:42:36 2004
+++ dirmngr/src/dirmngr-client.c Mon Jan 3 21:42:46 2005
@@ -55,7 +55,10 @@
oCacheCert,
oValidate,
oLookup,
- oLoadCRL
+ oLoadCRL,
+ oSquidMode,
+ oPEM,
+ oEscapedPEM,
};
@@ -69,7 +72,9 @@
{ oValidate, "validate", 0, N_("validate a certificate")},
{ oLookup, "lookup", 0, N_("lookup a certificate")},
{ oLoadCRL, "load-crl", 0, N_("load a CRL into the dirmngr")},
- {0}
+ { oSquidMode,"squid-mode",0, N_("special mode for use by Squid")},
+ { oPEM, "pem", 0, N_("certificates are expected in PEM format")},
+ { 0 }
};
#define DEFAULT_SOCKET_NAME "/var/run/dirmngr/socket"
@@ -81,6 +86,8 @@
int verbose;
const char *dirmngr_program;
int force_pipe_server;
+ int pem;
+ int escaped_pem; /* PEM is additional percent encoded. */
int use_ocsp;
@@ -96,6 +103,13 @@
};
+/* Base64 conversion tables. */
+static unsigned char bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+static unsigned char asctobin[256]; /* runtime initialized */
+
+
/* Prototypes. */
static assuan_context_t start_dirmngr (int only_daemon);
static gpg_error_t read_certificate (const char *fname,
@@ -108,6 +122,7 @@
const unsigned char *cert, size_t certlen);
static gpg_error_t do_loadcrl (assuan_context_t ctx, const char *filename);
static gpg_error_t do_lookup (assuan_context_t ctx, const char *pattern);
+static gpg_error_t squid_loop_body (assuan_context_t ctx);
@@ -173,6 +188,7 @@
int cmd_validate = 0;
int cmd_lookup = 0;
int cmd_loadcrl = 0;
+ int cmd_squid_mode = 0;
set_strusage (my_strusage);
log_set_prefix ("dirmngr-client",
@@ -202,6 +218,12 @@
case oValidate: cmd_validate = 1; break;
case oLookup: cmd_lookup = 1; break;
case oLoadCRL: cmd_loadcrl = 1; break;
+ case oPEM: opt.pem = 1; break;
+ case oSquidMode:
+ opt.pem = 1;
+ opt.escaped_pem = 1;
+ cmd_squid_mode = 1;
+ break;
default : pargs.err = 2; break;
}
@@ -209,6 +231,19 @@
if (log_get_errorcount (0))
exit (2);
+ /* Build the helptable for radix64 to bin conversion. */
+ if (opt.pem)
+ {
+ int i;
+ unsigned char *s;
+
+ for (i=0; i < 256; i++ )
+ asctobin[i] = 255; /* Used to detect invalid characters. */
+ for (s=bintoasc, i=0; *s; s++, i++)
+ asctobin[*s] = i;
+ }
+
+
if (cmd_ping)
err = 0;
else if (cmd_lookup || cmd_loadcrl)
@@ -217,6 +252,12 @@
usage (1);
err = 0;
}
+ else if (cmd_squid_mode)
+ {
+ err = 0;
+ if (argc)
+ usage (1);
+ }
else if (!argc)
{
err = read_certificate (NULL, &certbuf, &certbuflen);
@@ -252,6 +293,13 @@
if (cmd_ping)
;
+ else if (cmd_squid_mode)
+ {
+ while (!(err = squid_loop_body (ctx)))
+ ;
+ if (gpg_err_code (err) == GPG_ERR_EOF)
+ err = 0;
+ }
else if (cmd_lookup)
{
int last_err = 0;
@@ -307,7 +355,7 @@
log_info (_("a dirmngr daemon is up and running\n"));
return 0;
}
- else if (cmd_lookup||cmd_loadcrl)
+ else if (cmd_lookup||cmd_loadcrl||cmd_squid_mode)
return err? 1:0;
else if (cmd_cache_cert)
{
@@ -488,9 +536,159 @@
}
+/* Read the first PEM certificate from the file FNAME. If fname is
+ NULL the next certificate is read from stdin. The certificate is
+ returned in an alloced buffer whose address will be returned in
+ RBUF and its length in RBUFLEN. */
+static gpg_error_t
+read_pem_certificate (const char *fname, unsigned char **rbuf, size_t *rbuflen)
+{
+ FILE *fp;
+ int c;
+ int pos;
+ int value;
+ unsigned char *buf;
+ size_t bufsize, buflen;
+ enum {
+ s_init, s_idle, s_lfseen, s_begin,
+ s_b64_0, s_b64_1, s_b64_2, s_b64_3,
+ s_waitend
+ } state = s_init;
+
+ fp = fname? fopen (fname, "r") : stdin;
+ if (!fp)
+ return gpg_error_from_errno (errno);
+
+ pos = 0;
+ value = 0;
+ bufsize = 8192;
+ buf = xmalloc (bufsize);
+ buflen = 0;
+ while ((c=getc (fp)) != EOF)
+ {
+ if (opt.escaped_pem)
+ {
+ if (c == '%')
+ {
+ char tmp[2];
+ if ((c = getc(fp)) == EOF)
+ break;
+ tmp[0] = c;
+ if ((c = getc(fp)) == EOF)
+ break;
+ tmp[1] = c;
+ if (!hexdigitp (tmp) || !hexdigitp (tmp+1))
+ {
+ log_error ("invalid percent escape sequence\n");
+ state = s_idle; /* Force an error. */
+ break;
+ }
+ c = xtoi_2 (tmp);
+ }
+ else if (c == '\n')
+ goto ready; /* Ready. */
+ }
+ switch (state)
+ {
+ case s_idle:
+ if (c == '\n')
+ {
+ state = s_lfseen;
+ pos = 0;
+ }
+ break;
+ case s_init:
+ state = s_lfseen;
+ case s_lfseen:
+ if (c != "-----BEGIN "[pos])
+ state = s_idle;
+ else if (pos == 10)
+ state = s_begin;
+ else
+ pos++;
+ break;
+ case s_begin:
+ if (c == '\n')
+ state = s_b64_0;
+ break;
+ case s_b64_0:
+ case s_b64_1:
+ case s_b64_2:
+ case s_b64_3:
+ {
+ if (buflen >= bufsize)
+ {
+ bufsize += 8192;
+ buf = xrealloc (buf, bufsize);
+ }
+
+ if (c == '-')
+ state = s_waitend;
+ else if ((c = asctobin[c & 0xff]) == 255 )
+ ; /* Just skip invalid base64 characters. */
+ else if (state == s_b64_0)
+ {
+ value = c << 2;
+ state = s_b64_1;
+ }
+ else if (state == s_b64_1)
+ {
+ value |= (c>>4)&3;
+ buf[buflen++] = value;
+ value = (c<<4)&0xf0;
+ state = s_b64_2;
+ }
+ else if (state == s_b64_2)
+ {
+ value |= (c>>2)&15;
+ buf[buflen++] = value;
+ value = (c<<6)&0xc0;
+ state = s_b64_3;
+ }
+ else
+ {
+ value |= c&0x3f;
+ buf[buflen++] = value;
+ state = s_b64_0;
+ }
+ }
+ break;
+ case s_waitend:
+ /* Note that we do not check whether the END line really
+ follows, nor did we check that the base64 decoder was
+ left in the expected state. We assume that the PEM
+ header is just fine. */
+ if (c== '\n')
+ goto ready;
+ break;
+ default:
+ BUG();
+ }
+ }
+ ready:
+ if (fname)
+ fclose (fp);
+
+ if (state == s_init && c == EOF)
+ {
+ xfree (buf);
+ return gpg_error (GPG_ERR_EOF);
+ }
+ else if (state != s_waitend)
+ {
+ log_error ("no certificate or invalid encoded\n");
+ xfree (buf);
+ return gpg_error (GPG_ERR_INV_ARMOR);
+ }
+
+ *rbuf = buf;
+ *rbuflen = buflen;
+ return 0;
+}
+
/* Read a binary certificate from the file FNAME. If fname is NULL the
file is read from stdin. The certificate is returned in an alloced
- buffer whos address will be returned in RBUF and its length in
+ buffer whose address will be returned in RBUF and its length in
RBUFLEN. */
static gpg_error_t
read_certificate (const char *fname, unsigned char **rbuf, size_t *rbuflen)
@@ -500,6 +698,9 @@
unsigned char *buf;
size_t nread, bufsize, buflen;
+ if (opt.pem)
+ return read_pem_certificate (fname, rbuf, rbuflen);
+
fp = fname? fopen (fname, "rb") : stdin;
if (!fp)
return gpg_error_from_errno (errno);
@@ -733,3 +934,48 @@
xfree (line);
return ae? map_assuan_err (ae) : err;
}
+
+/* The body of an endless loop: Read a line from stdin, retrieve the
+ certificate from it, validate it and print "ERR" or "OK" to stdout.
+ Continue. */
+static gpg_error_t
+squid_loop_body (assuan_context_t ctx)
+{
+ gpg_error_t err;
+ unsigned char *certbuf;
+ size_t certbuflen = 0;
+
+ err = read_pem_certificate (NULL, &certbuf, &certbuflen);
+ if (gpg_err_code (err) == GPG_ERR_EOF)
+ return err;
+ if (err)
+ {
+ log_error (_("error reading certificate from stdin: %s\n"),
+ gpg_strerror (err));
+ puts ("ERROR");
+ return 0;
+ }
+
+ err = do_check (ctx, certbuf, certbuflen);
+ xfree (certbuf);
+ if (!err)
+ {
+ if (opt.verbose)
+ log_info (_("certificate is valid\n"));
+ puts ("OK");
+ }
+ else
+ {
+ if (!opt.quiet)
+ {
+ if (gpg_err_code (err) == GPG_ERR_CERT_REVOKED )
+ log_info (_("certificate has been revoked\n"));
+ else
+ log_error (_("certificate check failed: %s\n"),
+ gpg_strerror (err));
+ }
+ puts ("ERROR");
+ }
+
+ return 0;
+}
More information about the Gnupg-commits
mailing list