Minor cleanups.
authorWerner Koch <wk@gnupg.org>
Mon, 7 Apr 2008 19:31:12 +0000 (19:31 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 7 Apr 2008 19:31:12 +0000 (19:31 +0000)
Implemented key helper kdns

17 files changed:
ChangeLog
common/ChangeLog
common/Makefile.am
common/b64enc.c
common/pka.c
common/t-b64.c [new file with mode: 0644]
common/util.h
configure.ac
g10/ChangeLog
g10/getkey.c
g10/keyserver.c
g10/pkclist.c
keyserver/ChangeLog
keyserver/Makefile.am
keyserver/gpgkeys_kdns.c [new file with mode: 0644]
keyserver/no-libgcrypt.c
po/de.po

index f2f0af4..75f89cb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,13 @@
+2008-04-07  Werner Koch  <wk@g10code.com>
+
+       * configure.ac (ADNSLIBS): Test for adns.
+       (GPGKEYS_KDNS): New.
+
 2008-04-01  Werner Koch  <wk@g10code.com>
 
        * configure.ac: Require curl 7.10 (Oct 1 2002) or later as we use
        curl_version_info().
+       (AC_INIT): Fix quoting.
 
 2008-03-27  Werner Koch  <wk@g10code.com>
 
index 78baf7a..ab68709 100644 (file)
@@ -1,3 +1,12 @@
+2008-04-07  Werner Koch  <wk@g10code.com>
+
+       * b64enc.c (b64enc_start): Detect PGP mode.
+       (b64enc_finish): Write PGP CRC.
+       * util.h (struct b64state): Add field CRC.
+       * t-b64.c: New.
+
+       * pka.c (get_pka_info): Use xtrymalloc and check result.
+
 2008-03-25  Werner Koch  <wk@g10code.com>
 
        * localename.c: Strip all W32 code.  Include w32help.h.
        (atoi_1,atoi_2,atoi_4,xtoi_1,xtoi_2): New.
        
        
- Copyright 2001, 2002, 2003, 2004, 2005, 2006, 
-          2007 Free Software Foundation, Inc.
+ Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+          2008 Free Software Foundation, Inc.
 
  This file is free software; as a special exception the author gives
  unlimited permission to copy and/or distribute it, with or without
index e9c5325..f8283a6 100644 (file)
@@ -108,7 +108,7 @@ status-codes.h: Makefile mkstrtable.awk exstatus.awk status.h
 # Module tests
 #
 module_tests = t-convert t-gettime t-sysutils t-sexputil
-module_maint_tests = t-helpfile
+module_maint_tests = t-helpfile t-b64
 
 t_common_ldadd = libcommon.a ../jnlib/libjnlib.a ../gl/libgnu.a \
                  $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV)
@@ -118,4 +118,7 @@ t_gettime_LDADD = $(t_common_ldadd)
 t_sysutils_LDADD = $(t_common_ldadd)
 t_helpfile_LDADD = $(t_common_ldadd)
 t_sexputil_LDADD = $(t_common_ldadd)
+t_b64_LDADD = $(t_common_ldadd)
+
+
 
index e886f94..4722bd1 100644 (file)
@@ -1,5 +1,5 @@
 /* b64enc.c - Simple Base64 encoder.
- *     Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2003, 2004, 2008 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
 #define B64ENC_DID_HEADER   1
 #define B64ENC_DID_TRAILER  2
 #define B64ENC_NO_LINEFEEDS 16
-
+#define B64ENC_USE_PGPCRC   32
 
 /* The base-64 character list */
 static unsigned char bintoasc[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 
                                     "abcdefghijklmnopqrstuvwxyz" 
                                     "0123456789+/"; 
 
+/* Stuff required to create the OpenPGP CRC.  This crc_table has been
+   created using this code:
+
+   #include <stdio.h>
+   #include <stdint.h>
+   
+   #define CRCPOLY 0x864CFB
+   
+   int
+   main (void)
+   {
+     int i, j;
+     uint32_t t;
+     uint32_t crc_table[256];
+   
+     crc_table[0] = 0;
+     for (i=j=0; j < 128; j++ )
+       {
+         t = crc_table[j];
+         if ( (t & 0x00800000) )
+           {
+             t <<= 1;
+             crc_table[i++] = t ^ CRCPOLY;
+             crc_table[i++] = t;
+       }
+         else
+           {
+             t <<= 1;
+             crc_table[i++] = t;
+             crc_table[i++] = t ^ CRCPOLY;
+       }
+       }
+   
+     puts ("static const u32 crc_table[256] = {");
+     for (i=j=0; i < 256; i++)
+       {
+         printf ("%s 0x%08lx", j? "":" ", (unsigned long)crc_table[i]);
+         if (i != 255)
+           {
+             putchar (',');
+             if ( ++j > 5)
+               {
+                 j = 0;
+                 putchar ('\n');
+               }
+           }
+       }
+     puts ("\n};");
+     return 0;
+   }
+*/
+#define CRCINIT 0xB704CE
+static const u32 crc_table[256] = {
+  0x00000000, 0x00864cfb, 0x018ad50d, 0x010c99f6, 0x0393e6e1, 0x0315aa1a,
+  0x021933ec, 0x029f7f17, 0x07a18139, 0x0727cdc2, 0x062b5434, 0x06ad18cf,
+  0x043267d8, 0x04b42b23, 0x05b8b2d5, 0x053efe2e, 0x0fc54e89, 0x0f430272,
+  0x0e4f9b84, 0x0ec9d77f, 0x0c56a868, 0x0cd0e493, 0x0ddc7d65, 0x0d5a319e,
+  0x0864cfb0, 0x08e2834b, 0x09ee1abd, 0x09685646, 0x0bf72951, 0x0b7165aa,
+  0x0a7dfc5c, 0x0afbb0a7, 0x1f0cd1e9, 0x1f8a9d12, 0x1e8604e4, 0x1e00481f,
+  0x1c9f3708, 0x1c197bf3, 0x1d15e205, 0x1d93aefe, 0x18ad50d0, 0x182b1c2b,
+  0x192785dd, 0x19a1c926, 0x1b3eb631, 0x1bb8faca, 0x1ab4633c, 0x1a322fc7,
+  0x10c99f60, 0x104fd39b, 0x11434a6d, 0x11c50696, 0x135a7981, 0x13dc357a,
+  0x12d0ac8c, 0x1256e077, 0x17681e59, 0x17ee52a2, 0x16e2cb54, 0x166487af,
+  0x14fbf8b8, 0x147db443, 0x15712db5, 0x15f7614e, 0x3e19a3d2, 0x3e9fef29,
+  0x3f9376df, 0x3f153a24, 0x3d8a4533, 0x3d0c09c8, 0x3c00903e, 0x3c86dcc5,
+  0x39b822eb, 0x393e6e10, 0x3832f7e6, 0x38b4bb1d, 0x3a2bc40a, 0x3aad88f1,
+  0x3ba11107, 0x3b275dfc, 0x31dced5b, 0x315aa1a0, 0x30563856, 0x30d074ad,
+  0x324f0bba, 0x32c94741, 0x33c5deb7, 0x3343924c, 0x367d6c62, 0x36fb2099,
+  0x37f7b96f, 0x3771f594, 0x35ee8a83, 0x3568c678, 0x34645f8e, 0x34e21375,
+  0x2115723b, 0x21933ec0, 0x209fa736, 0x2019ebcd, 0x228694da, 0x2200d821,
+  0x230c41d7, 0x238a0d2c, 0x26b4f302, 0x2632bff9, 0x273e260f, 0x27b86af4,
+  0x252715e3, 0x25a15918, 0x24adc0ee, 0x242b8c15, 0x2ed03cb2, 0x2e567049,
+  0x2f5ae9bf, 0x2fdca544, 0x2d43da53, 0x2dc596a8, 0x2cc90f5e, 0x2c4f43a5,
+  0x2971bd8b, 0x29f7f170, 0x28fb6886, 0x287d247d, 0x2ae25b6a, 0x2a641791,
+  0x2b688e67, 0x2beec29c, 0x7c3347a4, 0x7cb50b5f, 0x7db992a9, 0x7d3fde52,
+  0x7fa0a145, 0x7f26edbe, 0x7e2a7448, 0x7eac38b3, 0x7b92c69d, 0x7b148a66,
+  0x7a181390, 0x7a9e5f6b, 0x7801207c, 0x78876c87, 0x798bf571, 0x790db98a,
+  0x73f6092d, 0x737045d6, 0x727cdc20, 0x72fa90db, 0x7065efcc, 0x70e3a337,
+  0x71ef3ac1, 0x7169763a, 0x74578814, 0x74d1c4ef, 0x75dd5d19, 0x755b11e2,
+  0x77c46ef5, 0x7742220e, 0x764ebbf8, 0x76c8f703, 0x633f964d, 0x63b9dab6,
+  0x62b54340, 0x62330fbb, 0x60ac70ac, 0x602a3c57, 0x6126a5a1, 0x61a0e95a,
+  0x649e1774, 0x64185b8f, 0x6514c279, 0x65928e82, 0x670df195, 0x678bbd6e,
+  0x66872498, 0x66016863, 0x6cfad8c4, 0x6c7c943f, 0x6d700dc9, 0x6df64132,
+  0x6f693e25, 0x6fef72de, 0x6ee3eb28, 0x6e65a7d3, 0x6b5b59fd, 0x6bdd1506,
+  0x6ad18cf0, 0x6a57c00b, 0x68c8bf1c, 0x684ef3e7, 0x69426a11, 0x69c426ea,
+  0x422ae476, 0x42aca88d, 0x43a0317b, 0x43267d80, 0x41b90297, 0x413f4e6c,
+  0x4033d79a, 0x40b59b61, 0x458b654f, 0x450d29b4, 0x4401b042, 0x4487fcb9,
+  0x461883ae, 0x469ecf55, 0x479256a3, 0x47141a58, 0x4defaaff, 0x4d69e604,
+  0x4c657ff2, 0x4ce33309, 0x4e7c4c1e, 0x4efa00e5, 0x4ff69913, 0x4f70d5e8,
+  0x4a4e2bc6, 0x4ac8673d, 0x4bc4fecb, 0x4b42b230, 0x49ddcd27, 0x495b81dc,
+  0x4857182a, 0x48d154d1, 0x5d26359f, 0x5da07964, 0x5cace092, 0x5c2aac69,
+  0x5eb5d37e, 0x5e339f85, 0x5f3f0673, 0x5fb94a88, 0x5a87b4a6, 0x5a01f85d,
+  0x5b0d61ab, 0x5b8b2d50, 0x59145247, 0x59921ebc, 0x589e874a, 0x5818cbb1,
+  0x52e37b16, 0x526537ed, 0x5369ae1b, 0x53efe2e0, 0x51709df7, 0x51f6d10c,
+  0x50fa48fa, 0x507c0401, 0x5542fa2f, 0x55c4b6d4, 0x54c82f22, 0x544e63d9,
+  0x56d11cce, 0x56575035, 0x575bc9c3, 0x57dd8538
+};
+
+
 /* 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. */
+   If TITLE starts with "PGP " the OpenPGP CRC checksum will be
+   written as well.  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)
 {
@@ -53,9 +154,14 @@ b64enc_start (struct b64state *state, FILE *fp, const char *title)
     state->flags |= B64ENC_NO_LINEFEEDS;
   else if (title)
     {
+      if (!strncmp (title, "PGP ", 4))
+        {
+          state->flags |= B64ENC_USE_PGPCRC;
+          state->crc = CRCINIT;
+        }
       state->title = xtrystrdup (title);
       if (!state->title)
-        return  gpg_error_from_syserror ();
+        return gpg_error_from_syserror ();
     }
   return 0;
 }
@@ -88,7 +194,11 @@ b64enc_write (struct b64state *state, const void *buffer, size_t nbytes)
                || fputs (state->title, fp) == EOF
                || fputs ("-----\n", fp) == EOF)
             goto write_error;
+          if ( (state->flags & B64ENC_USE_PGPCRC) 
+               && fputs ("\n", fp) == EOF)
+            goto write_error;
         }
+        
       state->flags |= B64ENC_DID_HEADER;
     }
 
@@ -96,7 +206,17 @@ b64enc_write (struct b64state *state, const void *buffer, size_t nbytes)
   quad_count = state->quad_count;
   assert (idx < 4);
   memcpy (radbuf, state->radbuf, idx);
-  
+
+  if ( (state->flags & B64ENC_USE_PGPCRC) )
+    {
+      size_t n;
+      u32 crc = state->crc;
+
+      for (p=buffer, n=nbytes; n; p++, n-- )
+        crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ *p];
+      state->crc = (crc & 0x00ffffff);
+    }
+
   for (p=buffer; nbytes; p++, nbytes--)
     {
       radbuf[idx++] = *p;
@@ -138,6 +258,7 @@ b64enc_finish (struct b64state *state)
   unsigned char radbuf[4];
   int idx, quad_count;
   FILE *fp;
+  char tmp[4];
 
   if (!(state->flags & B64ENC_DID_HEADER))
     goto cleanup;
@@ -151,8 +272,6 @@ b64enc_finish (struct b64state *state)
 
   if (idx)
     {
-      char tmp[4];
-      
       tmp[0] = bintoasc[(*radbuf>>2)&077];
       if (idx == 1)
         {
@@ -186,6 +305,26 @@ b64enc_finish (struct b64state *state)
       && !(state->flags & B64ENC_NO_LINEFEEDS)
       && fputs ("\n", fp) == EOF)
     goto write_error;
+  
+  if ( (state->flags & B64ENC_USE_PGPCRC) )
+    {
+      /* Write the CRC.  */
+      putc ('=', fp);
+      radbuf[0] = state->crc >>16;
+      radbuf[1] = state->crc >> 8;
+      radbuf[2] = state->crc;
+      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);
+      if (ferror (fp))
+        goto write_error;
+      if (!(state->flags & B64ENC_NO_LINEFEEDS)
+          && fputs ("\n", fp) == EOF)
+        goto write_error;
+    }
 
   if (state->title)
     {
index f592cb0..79a0bc3 100644 (file)
@@ -119,7 +119,9 @@ get_pka_info (const char *address, unsigned char *fpr)
   if (!domain || domain == address || !domain[1])
     return NULL; /* invalid mail address given. */
 
-  name = malloc (strlen (address) + 5 + 1);
+  name = xtrymalloc (strlen (address) + 5 + 1);
+  if (!name)
+    return NULL;
   memcpy (name, address, domain - address);
   strcpy (stpcpy (name + (domain-address), "._pka."), domain+1);
 
diff --git a/common/t-b64.c b/common/t-b64.c
new file mode 100644 (file)
index 0000000..0f26ab3
--- /dev/null
@@ -0,0 +1,87 @@
+/* t-b64.c - Module tests for b64enc.c and b64dec.c
+ *     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/>.
+ */
+
+/* 
+
+   As of now this is only a test program for manual tests.
+
+ */
+
+
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "util.h"
+
+#define pass()  do { ; } while(0)
+#define fail(a)  do { fprintf (stderr, "%s:%d: test %d failed\n",\
+                               __FILE__,__LINE__, (a));          \
+                     errcount++;                                 \
+                   } while(0)
+
+static int verbose;
+static int errcount;
+
+static void
+test_b64enc_pgp (const char *string)
+{
+  gpg_error_t err;
+  struct b64state state;
+
+  if (!string)
+    string = "a";
+
+  err = b64enc_start (&state, stdout, "PGP MESSAGE");
+  if (err)
+    fail (1);
+
+  err = b64enc_write (&state, string, strlen (string));
+  if (err)
+    fail (2);
+
+  err = b64enc_finish (&state);
+  if (err)
+    fail (3);
+
+  pass ();
+}
+
+
+
+
+
+
+int
+main (int argc, char **argv)
+{
+  if (argc)
+    { argc--; argv++; }
+  if (argc && !strcmp (argv[0], "--verbose"))
+    {
+      verbose = 1;
+      argc--; argv++;
+    }
+
+  test_b64enc_pgp (argc? *argv: NULL);
+
+  return !!errcount;
+}
+
index 53a56a3..e479cfc 100644 (file)
@@ -152,6 +152,7 @@ struct b64state
   FILE *fp;
   char *title;
   unsigned char radbuf[4];
+  u32 crc;
 };
 gpg_error_t b64enc_start (struct b64state *state, FILE *fp, const char *title);
 gpg_error_t b64enc_write (struct b64state *state,
index 4f0881a..4ad65a6 100644 (file)
@@ -1,6 +1,6 @@
 # configure.ac - for GnuPG 2.0
 # Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-#               2006, 2007 Free Software Foundation, Inc.
+#               2006, 2007, 2008 Free Software Foundation, Inc.
 # 
 # This file is part of GnuPG.
 # 
@@ -30,7 +30,8 @@ m4_define([my_issvn], [yes])
 
 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([gnupg], my_version[]m4_if(my_issvn,[yes],[-svn[]svn_revision]),
+AC_INIT([gnupg], 
+        [my_version[]m4_if(my_issvn,[yes],[-svn[]svn_revision])],
         [bug-gnupg@gnupg.org])
 # Set development_version to yes if the minor number is odd or you
 # feel that the default check for a development version is not
@@ -69,6 +70,7 @@ have_libassuan=no
 have_ksba=no
 have_pth=no
 have_libusb=no
+have_adns=no
 
 use_bzip2=yes
 use_exec=yes
@@ -759,6 +761,7 @@ if test x"$use_dns_pka" = xyes || test x"$use_dns_srv" = xyes \
     # Make sure that the BIND 4 resolver interface is workable before
     # enabling any code that calls it.  At some point I'll rewrite the
     # code to use the BIND 8 resolver API.
+    # We might also want to use adns instead.
 
     AC_MSG_CHECKING([whether the resolver is usable])
     AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <sys/types.h>
@@ -822,6 +825,30 @@ AC_SUBST(DNSLIBS)
 
 AM_CONDITIONAL(USE_DNS_SRV, test x"$use_dns_srv" = xyes)
 
+
+#
+# Check for ADNS.
+#
+_cppflags="${CPPFLAGS}"
+_ldflags="${LDFLAGS}"
+AC_ARG_WITH(adns,
+            AC_HELP_STRING([--with-adns=DIR],
+                           [look for the adns library in DIR]),
+            [if test -d "$withval"; then
+               CPPFLAGS="${CPPFLAGS} -I$withval/include"
+               LDFLAGS="${LDFLAGS} -L$withval/lib"
+             fi])
+AC_CHECK_HEADERS(adns.h,
+                AC_CHECK_LIB(adns, adns_init,
+                             [have_adns=yes],
+                             [CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}]),
+                [CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}])
+if test "$have_adns" = "yes"; then
+  ADNSLIBS="-ladns" 
+fi
+AC_SUBST(ADNSLIBS)
+
+
 #
 # Check for LDAP
 #
@@ -1264,6 +1291,11 @@ estream_INIT
 #
 # Decide what to build
 #
+if test "$have_adns" = "yes"; then
+  AC_SUBST(GPGKEYS_KDNS, "gpg2keys_kdns$EXEEXT")
+fi
+
+
 missing_pth=no
 if test $have_ksba = no; then
   build_gpgsm=no
index b4f2720..f8f2225 100644 (file)
@@ -1,3 +1,9 @@
+2008-04-07  Werner Koch  <wk@g10code.com>
+
+       * keyserver.c (parse_keyserver_uri): Allow a default host name.
+
+       * getkey.c (get_pubkey_byname): Replace sprintf by bin2hex.
+
 2008-04-02  Werner Koch  <wk@g10code.com>
 
        * gpg.c (main): Do not allow DSA2 with a too old Libgcrypt.
index c1d21f1..47cf22e 100644 (file)
@@ -1012,9 +1012,8 @@ get_pubkey_byname (PKT_public_key *pk,
             requirement as the URL might point to a key put in by an
             attacker.  By forcing the use of the fingerprint, we
             won't use the attacker's key here. */
-         if(rc==0 && fpr)
+         if (!rc && fpr)
            {
-             int i;
              char fpr_string[MAX_FINGERPRINT_LEN*2+1];
 
              assert(fpr_len<=MAX_FINGERPRINT_LEN);
@@ -1022,9 +1021,8 @@ get_pubkey_byname (PKT_public_key *pk,
              free_strlist(namelist);
              namelist=NULL;
 
-             for(i=0;i<fpr_len;i++)
-               sprintf(fpr_string+2*i,"%02X",fpr[i]);
-
+              bin2hex (fpr, fpr_len, fpr_string);
+              
              if(opt.verbose)
                log_info("auto-key-locate found fingerprint %s\n",fpr_string);
 
index 9a4e084..12be4c2 100644 (file)
@@ -330,7 +330,15 @@ parse_keyserver_uri(const char *string,int require_scheme,
       keyserver->scheme=xstrdup("hkp");
     }
 
-  if(assume_hkp || (uri[0]=='/' && uri[1]=='/'))
+  if (uri[0]=='/' && uri[1]=='/' && uri[2] == '/')
+    {
+      /* Three slashes means network path with a default host name.
+         This is a hack because it does not crok all possible
+         combiantions.  We should better repalce all code bythe parser
+         from http.c.  */
+      keyserver->path = xstrdup (uri+2);
+    }
+  else if(assume_hkp || (uri[0]=='/' && uri[1]=='/'))
     {
       /* Two slashes means network path. */
 
index 6b74018..cb50ae2 100644 (file)
@@ -774,7 +774,6 @@ expand_group(strlist_t input)
      Bit 1: This is a hidden recipient.
 
    USE is the desired use for the key - usually PUBKEY_USAGE_ENC.
-   RET_PK_LIST.
 
    On success a list of keys is stored at the address RET_PK_LIST; the
    caller must free this list.  On error the value at this address is
index be26f21..8f47524 100644 (file)
@@ -1,3 +1,10 @@
+2008-04-07  Werner Koch  <wk@g10code.com>
+
+       * gpgkeys_kdns.c: New.
+       * Makefile.am: Support kdns. 
+
+       * no-libgcrypt.c (gcry_strdup): Fix.  It was not used.
+
 2008-03-25  Werner Koch  <wk@g10code.com>
 
        * gpgkeys_ldap.c (build_attrs): Take care of char defaulting to
index 103e82f..b25c294 100644 (file)
@@ -20,7 +20,8 @@
 # to gpg2keys_foo to allow for a non-conflicting installation of
 # gnupg1 and gnupg2.  Having the same names for the helpers would
 # otherwise lead to trouble when to uninstall one of them.
-EXTRA_PROGRAMS = gpg2keys_ldap gpg2keys_hkp gpg2keys_finger gpg2keys_curl
+EXTRA_PROGRAMS = gpg2keys_ldap gpg2keys_hkp gpg2keys_finger gpg2keys_curl \
+                gpg2keys_kdns
 EXTRA_SCRIPTS = gpg2keys_mailto
 
 AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/common -I$(top_srcdir)/intl 
@@ -30,7 +31,7 @@ AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS)
 include $(top_srcdir)/am/cmacros.am
 
 libexec_PROGRAMS = $(GPGKEYS_LDAP) $(GPGKEYS_HKP) $(GPGKEYS_FINGER) \
-                   $(GPGKEYS_CURL)
+                   $(GPGKEYS_CURL) $(GPGKEYS_KDNS)
 libexec_SCRIPTS = $(GPGKEYS_MAILTO)
 noinst_SCRIPTS = gpg2keys_test
 
@@ -47,6 +48,11 @@ gpg2keys_finger_CPPFLAGS = $(AM_CPPFLAGS)
 gpg2keys_finger_LDADD = $(common_libs) $(GPG_ERROR_LIBS) \
                         $(NETLIBS) $(other_libs)
 
+gpg2keys_kdns_SOURCES = gpgkeys_kdns.c ksutil.c ksutil.h no-libgcrypt.c
+gpg2keys_kdns_CPPFLAGS = $(AM_CPPFLAGS)
+gpg2keys_kdns_LDADD = $(common_libs) $(GPG_ERROR_LIBS) \
+                      $(ADNSLIBS) $(NETLIBS) $(other_libs)
+
 
 gpg2keys_curl_SOURCES = gpgkeys_curl.c ksutil.c ksutil.h no-libgcrypt.c
 gpg2keys_hkp_SOURCES  = gpgkeys_hkp.c ksutil.c ksutil.h no-libgcrypt.c
diff --git a/keyserver/gpgkeys_kdns.c b/keyserver/gpgkeys_kdns.c
new file mode 100644 (file)
index 0000000..522f1c8
--- /dev/null
@@ -0,0 +1,435 @@
+/* gpgkeys_kdns.c - Fetch a key via the GnuPG specific KDNS scheme.
+ * Copyright (C) 2008 g10 Code GmbH
+ *
+ * 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 <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef HAVE_GETOPT_H
+# include <getopt.h>
+#endif
+#include <assert.h>
+#ifdef HAVE_ADNS_H
+# include <adns.h>
+#endif
+
+#define INCLUDED_BY_MAIN_MODULE 1
+#include "util.h"
+#include "keyserver.h"
+#include "ksutil.h"
+
+/* Our own name.  */
+#define PGM "gpgkeys_kdns"
+
+/* getopt(3) requires declarion of some global variables.  */
+extern char *optarg;
+extern int optind;
+
+/* Convenience variables usually intialized withn std{in,out,err}.  */
+static FILE *input, *output, *console;
+
+/* Standard keyserver module options.  */
+static struct ks_options *opt;
+
+/* The flags we pass to adns_init: Do not allow any environment
+   variables and for now enable debugging.  */
+#define MY_ADNS_INITFLAGS  (adns_if_noenv)
+
+
+/* ADNS has no support for CERT yes. */
+#define my_adns_r_cert 37
+
+/* The root of the KDNS tree. */
+static const char *kdns_root;
+
+/* The replacement string for the at sign.  */
+static const char *kdns_at_repl;
+
+
+
+
+\f
+/* Retrieve one key.  ADDRESS should be an RFC-2822 addr-spec. */
+static int
+get_key (adns_state adns_ctx, char *address)
+{
+  int ret = KEYSERVER_INTERNAL_ERROR;
+  const char *domain;
+  char *name = NULL;
+  adns_answer *answer = NULL;
+  const unsigned char *data;
+  int datalen;
+  struct b64state b64state;
+  char *p;
+
+  domain = strrchr (address, '@');
+  if (!domain || domain == address || !domain[1])
+    {
+      fprintf (console, PGM": invalid mail address `%s'\n", address);
+      ret = KEYSERVER_GENERAL_ERROR;
+      goto leave;
+    }
+  name = xtrymalloc (strlen (address) + strlen (kdns_at_repl)
+                     + 1 + strlen (kdns_root) + 1);
+  if (!name)
+    goto leave;
+  memcpy (name, address, domain - address);
+  p = stpcpy (name + (domain-address), ".");
+  if (*kdns_at_repl)
+    p = stpcpy (stpcpy (p, kdns_at_repl), ".");
+  p = stpcpy (p, domain+1);
+  if (*kdns_root)
+    strcpy (stpcpy (p, "."), kdns_root);
+
+  fprintf (output,"NAME %s BEGIN\n", address);
+  if (opt->verbose > 2)
+    fprintf(console, PGM": looking up `%s'\n", name);
+
+
+  if ( adns_synchronous (adns_ctx, name, (adns_r_unknown | my_adns_r_cert),
+                         adns_qf_quoteok_query,
+                         &answer) )
+    {
+      fprintf (console, PGM": DNS query failed: %s\n", strerror (errno));
+      ret = KEYSERVER_KEY_NOT_FOUND;
+      goto leave;
+    }
+  if (answer->status != adns_s_ok) 
+    {
+      fprintf (console, PGM": DNS query returned: %s (%s)\n", 
+               adns_strerror (answer->status),
+               adns_errabbrev (answer->status));
+      ret = KEYSERVER_KEY_NOT_FOUND;
+      goto leave;
+    }
+  datalen = answer->rrs.byteblock->len;
+  data = answer->rrs.byteblock->data;
+
+  if ( opt->debug > 1 )
+    {
+      int i;
+
+      fprintf (console, "got %d  bytes of data:", datalen);
+      for (i=0; i < datalen; i++)
+        {
+          if (!(i % 32))
+            fprintf (console, "\n%08x  ", i);
+          fprintf (console, "%02x", data[i]);
+        }
+      putc ('\n', console);
+    }
+  if ( datalen < 5 )
+    {
+      fprintf (console, PGM": error: truncated CERT record\n"); 
+      ret = KEYSERVER_KEY_NOT_FOUND;
+      goto leave;
+    }
+
+  switch ( ((data[0]<<8)|data[1]) )
+    {
+    case 3: /* CERT type is PGP.  */
+      /* (key tag and algorithm fields are ignored for this CERT type). */
+      data += 5;
+      datalen -= 5;
+      if ( datalen < 11 )
+        {
+          /* Gpg checks for a minium length of 11, thus we do the same.  */
+          fprintf (console, PGM": error: OpenPGP data to short\n"); 
+          ret = KEYSERVER_KEY_NOT_FOUND;
+          goto leave;
+        }
+      if (b64enc_start (&b64state, output, "PGP PUBLIC KEY BLOCK")
+          || b64enc_write (&b64state, data, datalen)
+          || b64enc_finish (&b64state))
+        goto leave; /* Oops, base64 encoder failed.  */
+      break;
+
+    default:
+      fprintf (console, PGM": CERT type %d ignored\n", (data[0] <<8|data[1])); 
+      ret = KEYSERVER_KEY_NOT_FOUND;
+      goto leave;
+    }
+  
+  ret = 0; /* All fine.  */
+
+ leave:
+  if (ret)
+    fprintf (output, "\nNAME %s FAILED %d\n", address, ret);
+  else
+    fprintf (output, "\nNAME %s END\n", address);
+  free (answer);  /* (Right, this is free and not xfree.) */
+  xfree (name);
+  return ret;
+}
+
+
+/* Print some help.  */
+static void 
+show_help (FILE *fp)
+{
+  fputs (PGM" (GnuPG) " VERSION"\n\n", fp);
+  fputs (" -h\thelp\n"
+         " -V\tversion\n"
+         " -o\toutput to this file\n"
+         "\n", fp);
+  fputs ("This keyserver helper accepts URLs of the form:\n"
+         "  kdns://[NAMESERVER]/[ROOT][?at=[STRING]]\n"
+         "with\n"
+         "  NAMESERVER  used for queries (default: system standard)\n"
+         "  ROOT        a DNS name appended to the query (default: none)\n"
+         "  STRING      A string to replace the '@' (default: \".\")\n"
+         "\n", fp);
+  fputs ("Example:  A query for \"hacker@gnupg.org\" with\n"
+         "  kdns://10.0.0.1/example.net?at=_key?\n"
+         "setup as --auto-key-lookup does a CERT record query\n"
+         "with type PGP on the nameserver 10.0.0.1 for\n"
+         "  hacker._key_.gnupg.org.example.net\n"
+         "\n", fp);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  int arg;
+  int ret = KEYSERVER_INTERNAL_ERROR;
+  char line[MAX_LINE];
+  struct keylist *keylist = NULL;
+  struct keylist **keylist_tail = &keylist;
+  struct keylist *akey;
+  int failed = 0;
+  adns_state adns_ctx = NULL;
+  adns_initflags my_adns_initflags = MY_ADNS_INITFLAGS;
+  int tmprc;
+
+  /* The defaults for the KDNS name mangling.  */
+  kdns_root = "";
+  kdns_at_repl = "";
+
+  console = stderr;
+
+  /* Kludge to implement standard GNU options.  */
+  if (argc > 1 && !strcmp (argv[1], "--version"))
+    {
+      fputs (PGM" (GnuPG) " VERSION"\n", stdout);
+      return 0;
+    }
+  else if (argc > 1 && !strcmp (argv[1], "--help"))
+    {
+      show_help (stdout);
+      return 0;
+    }
+
+  while ( (arg = getopt (argc, argv, "hVo:")) != -1 )
+    {
+      switch(arg)
+        {
+        case 'V':
+          printf ("%d\n%s\n", KEYSERVER_PROTO_VERSION, VERSION);
+          return KEYSERVER_OK;
+
+        case 'o':
+          output = fopen (optarg,"w");
+          if (!output)
+            {
+              fprintf (console, PGM": cannot open output file `%s': %s\n",
+                       optarg, strerror(errno) );
+              return KEYSERVER_INTERNAL_ERROR;
+            }
+          break;
+
+        case 'h':
+        default:
+          show_help (console);
+          return KEYSERVER_OK;
+        }
+    }
+
+  if (argc > optind)
+    {
+      input = fopen (argv[optind], "r");
+      if (!input)
+       {
+         fprintf (console, PGM": cannot open input file `%s': %s\n",
+                   argv[optind], strerror(errno) );
+         return KEYSERVER_INTERNAL_ERROR;
+       }
+    }
+
+  if (!input)
+    input = stdin;
+
+  if (!output)
+    output = stdout;
+  
+  opt = init_ks_options();
+  if(!opt)
+    return KEYSERVER_NO_MEMORY;
+
+  /* Get the command and info block */
+  while ( fgets(line,MAX_LINE,input) )
+    {
+      int err;
+      
+      if(line[0]=='\n')
+       break;
+      
+      err = parse_ks_options (line, opt);
+      if (err > 0)
+       {
+         ret = err;
+         goto leave;
+       }
+      else if (!err)
+       continue;
+    }
+
+  if (opt->timeout && register_timeout() == -1 )
+    {
+      fprintf (console, PGM": unable to register timeout handler\n");
+      return KEYSERVER_INTERNAL_ERROR;
+    }
+
+  fprintf (console, PGM": HOST=%s\n", opt->host? opt->host:"(none)");
+  fprintf (console, PGM": PATH=%s\n", opt->path? opt->path:"(none)");
+  if (opt->path && *opt->path == '/')
+    {
+      char *p, *pend;
+
+      kdns_root = opt->path+1;
+      p = strchr (opt->path+1, '?');
+      if (p)
+        {
+          *p++ = 0;
+          do 
+            {
+              pend = strchr (p, '&');
+              if (pend)
+                *pend++ = 0;
+              if (!strncmp (p, "at=", 3))
+                {
+                  /* Found.  */
+                  kdns_at_repl = p+3;
+                  break;
+                }
+            }
+          while ((p = pend));
+        }
+    }
+  if (strchr (kdns_root, '/'))
+    {
+      fprintf (console, PGM": invalid character in KDNS root\n");
+      return KEYSERVER_GENERAL_ERROR;
+    }
+  if (!strcmp (kdns_at_repl, "."))
+    kdns_at_repl = "";
+  fprintf (console, PGM": kdns_root=%s\n", kdns_root);
+  fprintf (console, PGM": kdns_at=%s\n", kdns_at_repl);
+
+
+  if (opt->debug)
+    my_adns_initflags |= adns_if_debug;
+  if (opt->host)
+    {
+      char cfgtext[200];
+
+      snprintf (cfgtext, sizeof cfgtext, "nameserver %s\n", opt->host);
+      tmprc = adns_init_strcfg (&adns_ctx, my_adns_initflags, console,cfgtext);
+    }
+  else
+    tmprc = adns_init (&adns_ctx, my_adns_initflags, console);
+  if (tmprc)
+    {
+      fprintf (console, PGM": error initializing ADNS: %s\n",
+               strerror (errno));
+      goto leave;
+    }
+  
+  if (opt->action == KS_GETNAME)
+    {
+      while ( fgets (line,MAX_LINE,input) )
+        {
+          if (line[0]=='\n' || !line[0] )
+            break;
+          line[strlen(line)-1] = 0;  /* Trim the trailing LF. */
+          
+          akey = xtrymalloc (sizeof *akey);
+          if (!akey)
+            {
+              fprintf (console, 
+                       PGM": out of memory while building key list\n");
+              ret = KEYSERVER_NO_MEMORY;
+              goto leave;
+            }
+          assert (sizeof (akey->str) > strlen(line));
+          strcpy (akey->str, line);
+          akey->next = NULL;
+          *keylist_tail = akey;
+          keylist_tail = &akey->next;
+       }
+    }
+  else
+    {
+      fprintf (console,
+               PGM": this keyserver type only supports "
+               "key retrieval by name\n");
+      goto leave;
+    }
+  
+  /* Send the response */
+  fprintf (output, "VERSION %d\n", KEYSERVER_PROTO_VERSION);
+  fprintf (output, "PROGRAM %s\n\n", VERSION);
+
+  if (opt->verbose > 1)
+    {
+      if (opt->opaque)
+        fprintf (console, "User:\t\t%s\n", opt->opaque);
+      fprintf (console, "Command:\tGET\n");
+    }
+  
+  for (akey = keylist; akey; akey = akey->next)
+    {
+      set_timeout (opt->timeout);
+      if ( get_key (adns_ctx, akey->str) )
+        failed++;
+    }      
+  if (!failed)
+    ret = KEYSERVER_OK;
+
+
+ leave:
+  if (adns_ctx)
+    adns_finish (adns_ctx);
+  while (keylist)
+    {
+      akey = keylist->next;
+      xfree (keylist);
+      keylist = akey;
+    }
+  if (input != stdin)
+    fclose (input);
+  if (output != stdout)
+    fclose (output);
+  kdns_root = "";
+  kdns_at_repl = ".";
+  free_ks_options (opt);
+  return ret;
+}
index 690a366..2cce156 100644 (file)
@@ -49,7 +49,10 @@ gcry_xmalloc (size_t n)
 char *
 gcry_strdup (const char *string)
 {
-  return malloc (strlen (string)+1);
+  char *p = malloc (strlen (string)+1);
+  if (p)
+    strcpy (p, string);
+  return p;
 }
 
 
index 17fb2ce..45a56e1 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -10,7 +10,7 @@ msgstr ""
 "Project-Id-Version: gnupg-2.0.6\n"
 "Report-Msgid-Bugs-To: translations@gnupg.org\n"
 "POT-Creation-Date: 2008-03-27 13:41+0100\n"
-"PO-Revision-Date: 2008-03-26 09:56+0100\n"
+"PO-Revision-Date: 2008-04-02 17:50+0200\n"
 "Last-Translator: Walter Koch <koch@u32.de>\n"
 "Language-Team: German <de@li.org>\n"
 "MIME-Version: 1.0\n"
@@ -7084,7 +7084,7 @@ msgstr ""
 "des X.509 Zertifikats:\n"
 "\"%s\"\n"
 "S/N %s, ID 0x%08lX,\n"
-"gültig von %s bis %s\\n \n"
+"gültig von %s bis %s\n"
 "zu entsperren.\n"
 
 #: sm/certlist.c:122