Started with keybox implementation by basing it on code from the GnuPG
authorWerner Koch <wk@gnupg.org>
Sat, 10 Nov 2001 18:06:11 +0000 (18:06 +0000)
committerWerner Koch <wk@gnupg.org>
Sat, 10 Nov 2001 18:06:11 +0000 (18:06 +0000)
devel branch.

kbx/kbxutil.c [new file with mode: 0644]
kbx/keybox-blob.c [new file with mode: 0644]
kbx/keybox-defs.h [new file with mode: 0644]
kbx/keybox-dump.c [new file with mode: 0644]
kbx/keybox-errors.c [new file with mode: 0644]
kbx/keybox-file.c [new file with mode: 0644]
kbx/keybox-init.c [new file with mode: 0644]
kbx/keybox-search.c [new file with mode: 0644]
kbx/keybox-util.c [new file with mode: 0644]
kbx/keybox.h [new file with mode: 0644]
kbx/mkerrors [new file with mode: 0755]

diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c
new file mode 100644 (file)
index 0000000..8c3dee9
--- /dev/null
@@ -0,0 +1,337 @@
+/* kbxutil.c - The Keybox utility
+ *     Copyright (C) 2000, 2001 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 <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include <gcrypt.h>
+
+#include "../jnlib/logging.h"
+#include "../jnlib/argparse.h"
+#include "../jnlib/stringhelp.h"
+#include "i18n.h"
+#include "keybox-defs.h"
+
+enum cmd_and_opt_values {
+  aNull = 0,
+  oArmor         = 'a',
+  oDryRun        = 'n',
+  oOutput        = 'o',
+  oQuiet         = 'q',
+  oVerbose       = 'v',
+  
+  aNoSuchCmd    = 500,   /* force other values not to be a letter */
+  aFindByFpr,
+  aFindByKid,
+  aFindByUid,
+
+  oDebug,
+  oDebugAll,
+
+  oNoArmor,
+  
+
+  aTest
+};
+
+
+static ARGPARSE_OPTS opts[] = {
+  { 300, NULL, 0, N_("@Commands:\n ") },
+
+  { aFindByFpr,  "find-by-fpr", 0, "|FPR| find key using it's fingerprnt" },
+  { aFindByKid,  "find-by-kid", 0, "|KID| find key using it's keyid" },
+  { aFindByUid,  "find-by-uid", 0, "|NAME| find key by user name" },
+  
+  { 301, NULL, 0, N_("@\nOptions:\n ") },
+  
+  { oArmor, "armor",     0, N_("create ascii armored output")},
+  { oArmor, "armour",     0, "@" },
+  { oOutput, "output",    2, N_("use as output file")},
+  { oVerbose, "verbose",   0, N_("verbose") },
+  { oQuiet,    "quiet",   0, N_("be somewhat more quiet") },
+  { oDryRun, "dry-run",   0, N_("do not make any changes") },
+  
+  { oDebug, "debug"     ,4|16, N_("set debugging flags")},
+  { oDebugAll, "debug-all" ,0, N_("enable full debugging")},
+
+  {0} /* end of list */
+};
+
+
+void myexit (int rc);
+
+int keybox_errors_seen = 0;
+
+
+static const char *
+my_strusage( int level )
+{
+    const char *p;
+    switch( level ) {
+      case 11: p = "kbxutil (GnuPG)";
+       break;
+      case 13: p = VERSION; break;
+      case 17: p = PRINTABLE_OS_NAME; break;
+      case 19: p =
+           _("Please report bugs to " PACKAGE_BUGREPORT ".\n");
+       break;
+      case 1:
+      case 40: p =
+           _("Usage: kbxutil [options] [files] (-h for help)");
+       break;
+      case 41: p =
+           _("Syntax: kbxutil [options] [files]\n"
+             "list, export, import Keybox data\n");
+       break;
+
+
+      default: p = NULL;
+    }
+    return p;
+}
+
+
+static void
+i18n_init(void)
+{
+  #ifdef USE_SIMPLE_GETTEXT
+    set_gettext_file( PACKAGE );
+  #else
+  #ifdef ENABLE_NLS
+    #ifdef HAVE_LC_MESSAGES
+       setlocale( LC_TIME, "" );
+       setlocale( LC_MESSAGES, "" );
+    #else
+       setlocale( LC_ALL, "" );
+    #endif
+    bindtextdomain( PACKAGE, GNUPG_LOCALEDIR );
+    textdomain( PACKAGE );
+  #endif
+  #endif
+}
+
+
+/*  static void */
+/*  wrong_args( const char *text ) */
+/*  { */
+/*      log_error("usage: kbxutil %s\n", text); */
+/*      myexit ( 1 ); */
+/*  } */
+
+
+#if 0
+static int
+hextobyte( const byte *s )
+{
+    int c;
+
+    if( *s >= '0' && *s <= '9' )
+       c = 16 * (*s - '0');
+    else if( *s >= 'A' && *s <= 'F' )
+       c = 16 * (10 + *s - 'A');
+    else if( *s >= 'a' && *s <= 'f' )
+       c = 16 * (10 + *s - 'a');
+    else
+       return -1;
+    s++;
+    if( *s >= '0' && *s <= '9' )
+       c += *s - '0';
+    else if( *s >= 'A' && *s <= 'F' )
+       c += 10 + *s - 'A';
+    else if( *s >= 'a' && *s <= 'f' )
+       c += 10 + *s - 'a';
+    else
+       return -1;
+    return c;
+}
+#endif
+
+#if 0
+static char *
+format_fingerprint ( const char *s )
+{
+    int i, c;
+    byte fpr[20];
+
+    for (i=0; i < 20 && *s; ) {
+       if ( *s == ' ' || *s == '\t' ) {
+           s++;
+           continue;
+       }
+       c = hextobyte(s);
+       if (c == -1) {
+           return NULL;
+       }
+       fpr[i++] = c;
+       s += 2;
+    }
+    return gcry_xstrdup ( fpr );
+}
+#endif
+
+#if 0
+static int
+format_keyid ( const char *s, u32 *kid )
+{
+    char helpbuf[9];
+    switch ( strlen ( s ) ) {
+      case 8:
+       kid[0] = 0;
+       kid[1] = strtoul( s, NULL, 16 );
+       return 10;
+
+      case 16:
+       mem2str( helpbuf, s, 9 );
+       kid[0] = strtoul( helpbuf, NULL, 16 );
+       kid[1] = strtoul( s+8, NULL, 16 );
+       return 11;
+    }
+    return 0; /* error */
+}
+#endif
+
+
+int
+main( int argc, char **argv )
+{
+  ARGPARSE_ARGS pargs;
+  enum cmd_and_opt_values cmd = 0;
+  
+  set_strusage( my_strusage );
+  /*log_set_name("kbxutil"); fixme */
+#if 0
+  /* check that the libraries are suitable.  Do it here because
+   * the option parse may need services of the library */
+  if ( !gcry_check_version ( "1.1.4" ) ) 
+    {
+      log_fatal(_("libgcrypt is too old (need %s, have %s)\n"),
+                "1.1.4", gcry_check_version(NULL) );
+    }
+#endif
+
+  /*create_dotlock(NULL); register locking cleanup */
+  i18n_init();
+
+  /* We need to use the gcry malloc function becuase jnlib does use them */
+  keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
+
+
+  pargs.argc = &argc;
+  pargs.argv = &argv;
+  pargs.flags=  1;  /* do not remove the args */
+  while (arg_parse( &pargs, opts) )
+    {
+      switch (pargs.r_opt)
+        {
+        case oVerbose:
+          /*opt.verbose++;*/
+          /*gcry_control( GCRYCTL_SET_VERBOSITY, (int)opt.verbose );*/
+          break;
+        case oDebug:
+          /*opt.debug |= pargs.r.ret_ulong; */
+          break;
+        case oDebugAll:
+          /*opt.debug = ~0;*/
+          break;
+
+        case aFindByFpr:
+        case aFindByKid:
+        case aFindByUid:
+          cmd = pargs.r_opt;
+          break;
+          
+        default:
+          pargs.err = 2;
+          break;
+       }
+    }
+  if (log_get_errorcount(0) )
+    myexit(2);
+  
+  if (!cmd)
+      { /* default is to list a KBX file */
+       if (!argc) 
+          _keybox_dump_file (NULL, stdout);
+       else
+          {
+           for (; argc; argc--, argv++) 
+              _keybox_dump_file (*argv, stdout);
+          }
+    }
+#if 0
+    else if ( cmd == aFindByFpr ) {
+       char *fpr;
+       if ( argc != 2 )
+           wrong_args ("kbxfile foingerprint");
+       fpr = format_fingerprint ( argv[1] );
+       if ( !fpr )
+           log_error ("invalid formatted fingerprint\n");
+       else {
+           kbxfile_search_by_fpr ( argv[0], fpr );
+           gcry_free ( fpr );
+       }
+    }
+    else if ( cmd == aFindByKid ) {
+       u32 kid[2];
+       int mode;
+
+       if ( argc != 2 )
+           wrong_args ("kbxfile short-or-long-keyid");
+       mode = format_keyid ( argv[1], kid );
+       if ( !mode )
+           log_error ("invalid formatted keyID\n");
+       else {
+           kbxfile_search_by_kid ( argv[0], kid, mode );
+       }
+    }
+    else if ( cmd == aFindByUid ) {
+       if ( argc != 2 )
+           wrong_args ("kbxfile userID");
+       kbxfile_search_by_uid ( argv[0], argv[1] );
+    }
+#endif
+    else
+       log_error ("unsupported action\n");
+
+    myexit(0);
+    return 8; /*NEVER REACHED*/
+}
+
+
+void
+myexit( int rc )
+{
+  /*    if( opt.debug & DBG_MEMSTAT_VALUE ) {*/
+/*     gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); */
+/*     gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); */
+  /*    }*/
+/*      if( opt.debug ) */
+/*     gcry_control( GCRYCTL_DUMP_SECMEM_STATS ); */
+    rc = rc? rc : log_get_errorcount(0)? 2 :
+                       keybox_errors_seen? 1 : 0;
+    exit(rc );
+}
+
+
diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c
new file mode 100644 (file)
index 0000000..7db6216
--- /dev/null
@@ -0,0 +1,755 @@
+/* keybox-blob.c - KBX Blob handling
+ *     Copyright (C) 2000, 2001 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
+ */
+
+
+/* The keybox data formats
+
+The KeyBox uses an augmented OpenPGP/X.509 key format.  This makes
+random access to a keyblock/Certificate easier and also gives the
+opportunity to store additional information (e.g. the fingerprint)
+along with the key.  All integers are stored in network byte order,
+offsets are counted from the beginning of the Blob.
+
+The first record of a plain KBX file has a special format:
+
+ u32  length of the first record
+ byte Blob type (1)
+ byte version number (1)
+ byte reserved
+ byte reserved
+ u32  magic 'KBXf'
+ byte pgp_marginals  used for validity calculation of this file
+ byte pgp_completes  ditto.
+ byte pgp_cert_depth ditto.
+
+The OpenPGP KBX Blob looks like this:
+
+ u32  length of this blob (including these 4 bytes)
+ byte Blob type (2)
+ byte version number of this blob type (1)
+ u16  Blob flags
+       bit 0 = contains secret key material
+
+ u32  offset to the OpenPGP keyblock
+ u32  length of the keyblock
+ u16  number of keys (at least 1!)
+ u16  size of additional key information
+ n times:
+   b20 The keys fingerprint
+       (fingerprints are always 20 bytes, MD5 left padded with zeroes)
+   u32 offset to the n-th key's keyID (a keyID is always 8 byte)
+   u16 special key flags
+        bit 0 =
+   u16 reserved
+ u16  number of user IDs
+ u16  size of additional user ID information
+ n times:
+   u32 offset to the n-th user ID
+   u32 length of this user ID.
+   u16 special user ID flags.
+        bit 0 =
+   byte validity
+   byte reserved
+ u16  number of signatures
+ u16  size of signature information (4)
+   u32 expiration time of signature with some special values:
+       0x00000000 = not checked
+       0x00000001 = missing key
+       0x00000002 = bad signature
+       0x10000000 = valid and expires at some date in 1978.
+       0xffffffff = valid and does not expire
+ u8    assigned ownertrust
+ u8    all_validity
+ u16   reserved
+ u32   recheck_after
+ u32   Newest timestamp in the keyblock (useful for KS syncronsiation?)
+ u32   Blob created at
+ u32   size of reserved space (not including this field)
+      reserved space
+
+    Here we might want to put other data
+
+    Here comes the keyblock
+
+    maybe we put a signature here later.
+
+ b16   MD5 checksum  (useful for KS syncronisation)
+
+*/
+
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <gcrypt.h>
+
+#include "keybox-defs.h"
+
+/* special values of the signature status */
+#define SF_NONE(a)  ( !(a) )
+#define SF_NOKEY(a) ((a) & (1<<0))
+#define SF_BAD(a)   ((a) & (1<<1))
+#define SF_VALID(a) ((a) & (1<<29))
+
+
+struct membuf {
+  size_t len;
+  size_t size;
+  char *buf;
+  int out_of_core;
+};
+
+
+/*  #if MAX_FINGERPRINT_LEN < 20 */
+/*    #error fingerprints are 20 bytes */
+/*  #endif */
+
+struct keyboxblob_key {
+    char   fpr[20];
+    u32    off_kid;
+    ulong  off_kid_addr;
+    u16    flags;
+};
+struct keyboxblob_uid {
+    ulong  off_addr;
+    u32    len;
+    u16    flags;
+    byte   validity;
+};
+
+struct keyid_list {
+    struct keyid_list *next;
+    int seqno;
+    byte kid[8];
+};
+
+struct fixup_list {
+    struct fixup_list *next;
+    u32 off;
+    u32 val;
+};
+
+
+struct keyboxblob {
+  byte *blob;
+  size_t bloblen;
+  
+  /* stuff used only by keybox_create_blob */
+  int nkeys;
+  struct keyboxblob_key *keys;
+  int nuids;
+  struct keyboxblob_uid *uids;
+  int nsigs;
+  u32  *sigs;
+  struct fixup_list *fixups;
+  
+  struct keyid_list *temp_kids;
+  struct membuf *buf; /* temporary store for the blob */
+};
+
+
+\f
+/* A simple implemnation of a dynamic buffer.  Use init_membuf() to
+   create a buffer, put_membuf to append bytes and get_membuf to
+   release and return the buffer.  Allocation errors are detected but
+   only returned at the final get_membuf(), this helps not to clutter
+   the code with out of core checks.  */
+
+static void
+init_membuf (struct membuf *mb, int initiallen)
+{
+  mb->len = 0;
+  mb->size = initiallen;
+  mb->out_of_core = 0;
+  mb->buf = xtrymalloc (initiallen);
+  if (!mb->buf)
+      mb->out_of_core = 1;
+}
+
+static void
+put_membuf (struct membuf *mb, const void *buf, size_t len)
+{
+  if (mb->out_of_core)
+    return;
+
+  if (mb->len + len >= mb->size)
+    {
+      char *p;
+      
+      mb->size += len + 1024;
+      p = xtryrealloc (mb->buf, mb->size);
+      if (!p)
+        {
+          mb->out_of_core = 1;
+          return;
+        }
+      mb->buf = p;
+    }
+  memcpy (mb->buf + mb->len, buf, len);
+  mb->len += len;
+}
+
+static void *
+get_membuf (struct membuf *mb, size_t *len)
+{
+  char *p;
+
+  if (mb->out_of_core)
+    {
+      xfree (mb->buf);
+      mb->buf = NULL;
+      return NULL;
+    }
+
+  p = mb->buf;
+  *len = mb->len;
+  mb->buf = NULL;
+  mb->out_of_core = 1; /* don't allow a reuse */
+  return p;
+}
+
+
+static void
+put8 (struct membuf *mb, byte a )
+{
+  put_membuf (mb, &a, 1);
+}
+
+static void
+put16 (struct membuf *mb, u16 a )
+{
+  unsigned char tmp[2];
+  tmp[0] = a>>8;
+  tmp[1] = a;
+  put_membuf (mb, tmp, 2);
+}
+
+static void
+put32 (struct membuf *mb, u32 a )
+{
+  unsigned char tmp[4];
+  tmp[0] = a>>24;
+  tmp[1] = a>>16;
+  tmp[2] = a>>8;
+  tmp[3] = a;
+  put_membuf (mb, tmp, 4);
+}
+
+\f
+/*
+ Some wrappers
+*/
+
+static u32
+make_timestamp (void)
+{
+  return time(NULL);
+}
+
+
+\f
+#ifdef KEYBOX_WITH_OPENPGP
+/*
+  OpenPGP specific stuff 
+*/
+
+
+/*
+  We must store the keyid at some place because we can't calculate the
+  offset yet. This is only used for v3 keyIDs.  Function returns an
+  index value for later fixup or -1 for out of core. The value must be
+  a non-zero value */
+static int
+pgp_temp_store_kid (KEYBOXBLOB blob, PKT_public_key *pk)
+{
+  struct keyid_list *k, *r;
+  
+  k = xtrymalloc (sizeof *k); 
+  if (!k)
+    return -1;
+  k->kid[0] = pk->keyid[0] >> 24 ;
+  k->kid[1] = pk->keyid[0] >> 16 ;
+  k->kid[2] = pk->keyid[0] >>  8 ;
+  k->kid[3] = pk->keyid[0]        ;
+  k->kid[4] = pk->keyid[0] >> 24 ;
+  k->kid[5] = pk->keyid[0] >> 16 ;
+  k->kid[6] = pk->keyid[0] >>  8 ;
+  k->kid[7] = pk->keyid[0]        ;
+  k->seqno = 0;
+  k->next = blob->temp_kids;
+  blob->temp_kids = k;
+  for (r=k; r; r = r->next) 
+    k->seqno++;
+  
+  return k->seqno;
+}
+
+static int
+pgp_create_key_part (KEYBOXBLOB blob, KBNODE keyblock)
+{
+  KBNODE node;
+  size_t fprlen;
+  int n;
+
+  for (n=0, node = keyblock; node; node = node->next)
+    {
+      if ( node->pkt->pkttype == PKT_PUBLIC_KEY
+           || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) 
+        {
+          PKT_public_key *pk = node->pkt->pkt.public_key;
+          char tmp[20];
+
+          fingerprint_from_pk (pk, tmp , &fprlen);
+          memcpy (blob->keys[n].fpr, tmp, 20);
+          if ( fprlen != 20 ) /*v3 fpr - shift right and fill with zeroes*/
+            {
+              assert (fprlen == 16);
+              memmove (blob->keys[n].fpr+4, blob->keys[n].fpr, 16);
+              memset (blob->keys[n].fpr, 0, 4);
+              blob->keys[n].off_kid = pgp_temp_store_kid (blob, pk);
+           }
+          else
+            {
+              blob->keys[n].off_kid = 0; /* will be fixed up later */
+           }
+          blob->keys[n].flags = 0;
+          n++;
+       }
+      else if ( node->pkt->pkttype == PKT_SECRET_KEY
+                 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) 
+        {
+          never_reached (); /* actually not yet implemented */
+       }
+    }
+  assert (n == blob->nkeys);
+  return 0;
+}
+
+static int
+pgp_create_uid_part (KEYBOXBLOB blob, KBNODE keyblock)
+{
+  KBNODE node;
+  int n;
+
+  for (n=0, node = keyblock; node; node = node->next)
+    {
+      if (node->pkt->pkttype == PKT_USER_ID)
+        {
+          PKT_user_id *u = node->pkt->pkt.user_id;
+          
+          blob->uids[n].len = u->len;
+          blob->uids[n].flags = 0;
+          blob->uids[n].validity = 0;
+          n++;
+       }
+    }
+  assert (n == blob->nuids);
+  return 0;
+}
+
+static int
+pgp_create_sig_part (KEYBOXBLOB blob, KBNODE keyblock)
+{
+  KBNODE node;
+  int n;
+  
+  for (n=0, node = keyblock; node; node = node->next)
+    {
+      if (node->pkt->pkttype == PKT_SIGNATURE)
+        {
+          PKT_signature *sig = node->pkt->pkt.signature;
+          
+          blob->sigs[n] = 0;   /* FIXME: check the signature here */
+          n++;
+       }
+    }
+  assert( n == blob->nsigs );
+  return 0;
+}
+
+static int
+pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock)
+{
+  struct membuf *a = blob->buf;
+  KBNODE node;
+  int rc;
+  int n;
+  u32 kbstart = a->len;
+
+  {
+    struct fixup_list *fl = xtrycalloc(1, sizeof *fl ); 
+    
+    if (!fl)
+      return KEYBOX_Out_Of_Core;
+    fl->off = 8;
+    fl->val = kbstart;
+    fl->next = blob->fixups;
+    blob->fixups = fl;
+  }
+
+  for (n = 0, node = keyblock; node; node = node->next)
+    {
+      rc = build_packet ( a, node->pkt );
+      if ( rc ) {
+        gpg_log_error ("build_packet(%d) for keyboxblob failed: %s\n",
+                      node->pkt->pkttype, gpg_errstr(rc) );
+        return GPGERR_WRITE_FILE;
+      }
+      if ( node->pkt->pkttype == PKT_USER_ID ) 
+        {
+          PKT_user_id *u = node->pkt->pkt.user_id;
+          /* build_packet has set the offset of the name into u ;
+           * now we can do the fixup */
+          struct fixup_list *fl = xcalloc(1, sizeof *fl ); /* fixme */
+          fl->off = blob->uids[n].off_addr;
+          fl->val = u->stored_at;
+          fl->next = blob->fixups;
+          blob->fixups = fl;
+          n++;
+       }
+    }
+  assert (n == blob->nuids);
+
+  {
+    struct fixup_list *fl = xcalloc(1, sizeof *fl ); /* fixme */
+
+    fl->off = 12;
+    fl->val = a->len - kbstart;
+    fl->next = blob->fixups;
+    blob->fixups = fl;
+  }
+
+  return 0;
+}
+
+#endif /*KEYBOX_WITH_OPENPGP*/
+
+\f
+#ifdef KEYBOX_WITH_X509
+/* 
+   X.509 specific stuff
+ */
+
+#endif /*KEYBOX_WITH_X509*/
+
+/* Write a stored keyID out to the buffer */
+static void
+write_stored_kid (KEYBOXBLOB blob, int seqno)
+{
+  struct keyid_list *r;
+  
+  for ( r = blob->temp_kids; r; r = r->next ) 
+    {
+      if (r->seqno == seqno )
+        {
+          put_membuf (blob->buf, r->kid, 8);
+          return;
+       }
+    }
+  never_reached ();
+}
+
+/* Release a list of key IDs */
+static void
+release_kid_list (struct keyid_list *kl)
+{
+  struct keyid_list *r, *r2;
+  
+  for ( r = kl; r; r = r2 ) 
+    {
+      r2 = r->next;
+      xfree (r);
+    }
+}
+
+
+
+static int
+create_blob_header (KEYBOXBLOB blob, int blobtype)
+{
+  struct membuf *a = blob->buf;
+  int i;
+
+  put32 ( a, 0 ); /* blob length, needs fixup */
+  put8 ( a, blobtype);  
+  put8 ( a, 1 );  /* blob type version */
+  put16 ( a, 0 ); /* blob flags */
+
+  put32 ( a, 0 ); /* offset to the raw data, needs fixup */
+  put32 ( a, 0 ); /* length of the raw data, needs fixup */
+
+  put16 ( a, blob->nkeys );
+  put16 ( a, 20 + 4 + 2 + 2 );  /* size of key info */
+  for ( i=0; i < blob->nkeys; i++ )
+    {
+      put_membuf (a, blob->keys[i].fpr, 20);
+      blob->keys[i].off_kid_addr = a->len;
+      put32 ( a, 0 ); /* offset to keyid, fixed up later */
+      put16 ( a, blob->keys[i].flags );
+      put16 ( a, 0 ); /* reserved */
+    }
+
+  put16 ( a, blob->nuids );
+  put16 ( a, 4 + 4 + 2 + 1 + 1 );  /* size of uid info */
+  for (i=0; i < blob->nuids; i++)
+    {
+      blob->uids[i].off_addr = a->len;
+      put32 ( a, 0 ); /* offset to userid, fixed up later */
+      put32 ( a, blob->uids[i].len );
+      put16 ( a, blob->uids[i].flags );
+      put8  ( a, 0 ); /* validity */
+      put8  ( a, 0 ); /* reserved */
+    }
+
+  put16 ( a, blob->nsigs );
+  put16 ( a, 4 );  /* size of sig info */
+  for (i=0; i < blob->nsigs; i++)
+    {
+      put32 ( a, blob->sigs[i]);
+    }
+
+  put8 ( a, 0 );  /* assigned ownertrust */
+  put8 ( a, 0 );  /* validity of all user IDs */
+  put16 ( a, 0 );  /* reserved */
+  put32 ( a, 0 );  /* time of next recheck */
+  put32 ( a, 0 );  /* newest timestamp (none) */
+  put32 ( a, make_timestamp() );  /* creation time */
+  put32 ( a, 0 );  /* size of reserved space */
+  /* reserved space (which is currently of size 0) */
+
+  /* We need to store the keyids for all pgp v3 keys because those key
+     IDs are not part of the fingerprint.  While we are doing that, we
+     fixup all the keyID offsets */
+  for (i=0; i < blob->nkeys; i++ )
+    {
+      struct fixup_list *fl = xtrycalloc(1, sizeof *fl ); 
+      
+      if (!fl)
+        return KEYBOX_Out_Of_Core;
+
+      fl->off = blob->keys[i].off_kid_addr;
+      fl->next = blob->fixups;
+      blob->fixups = fl;
+
+      if (blob->keys[i].off_kid) 
+        { /* this is a v3 one */
+          fl->val = a->len;
+          write_stored_kid (blob, blob->keys[i].off_kid);
+       }
+      else
+        { /* the better v4 key IDs - just store an offset 8 bytes back */
+          fl->val = blob->keys[i].off_kid_addr - 8;
+       }
+    }
+  
+    return 0;
+}
+
+
+
+static int
+create_blob_trailer (KEYBOXBLOB blob)
+{
+    return 0;
+}
+
+
+static int
+create_blob_finish (KEYBOXBLOB blob)
+{
+  struct membuf *a = blob->buf;
+  byte *p;
+  char *pp;
+  int i;
+  size_t n;
+
+  /* write a placeholder for the checksum */
+  for (i = 0; i < 16; i++ )
+    put32 (a, 0);
+  
+  /* get the memory area */
+  p = a->buf;
+  n = a->len;
+  assert (n >= 20);
+
+  /* fixup the length */
+  {
+    struct fixup_list *fl = xtrycalloc(1, sizeof *fl);
+    if (!fl)
+      return KEYBOX_Out_Of_Core;
+    fl->off = 0;
+    fl->val = n;
+    fl->next = blob->fixups;
+    blob->fixups = fl;
+  }
+
+  /* do the fixups */
+  {
+    struct fixup_list *fl;
+    for (fl = blob->fixups; fl; fl = fl->next)
+      {
+        assert (fl->off+4 <= n);
+        p[fl->off+0] = fl->val >> 24;
+        p[fl->off+1] = fl->val >> 16;
+        p[fl->off+2] = fl->val >>  8;
+        p[fl->off+3] = fl->val;
+      }
+  }
+
+  /* calculate and store the MD5 checksum */
+  gcry_md_hash_buffer (GCRY_MD_MD5, p + n - 16, p, n - 16);
+
+  pp = xtrymalloc (n);
+  if ( !pp )
+    return KEYBOX_Out_Of_Core;
+  memcpy (pp , p, n);
+  blob->blob = pp;
+  blob->bloblen = n;
+  
+  return 0;
+}
+
+\f
+#ifdef KEYBOX_WITH_OPENPGP
+
+int
+_keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock)
+{
+  int rc = 0;
+  KBNODE node;
+  KEYBOXBLOB blob;
+
+  *r_blob = NULL;
+  blob = xtrycalloc (1, sizeof *blob);
+  if( !blob )
+    return KEYBOX_Out_Of_Core;
+
+  /* fixme: Do some sanity checks on the keyblock */
+
+  /* count userids and keys so that we can allocate the arrays */
+  for (node = keyblock; node; node = node->next) 
+    {
+      switch (node->pkt->pkttype)
+        {
+        case PKT_PUBLIC_KEY:
+        case PKT_SECRET_KEY:
+        case PKT_PUBLIC_SUBKEY:
+        case PKT_SECRET_SUBKEY: blob->nkeys++; break;
+        case PKT_USER_ID:  blob->nuids++; break;
+        case PKT_SIGNATURE: blob->nsigs++; break;
+        default: break;
+       }
+    }
+
+  blob->keys = xtrycalloc (blob->nkeys, sizeof *blob->keys );
+  blob->uids = xtrycalloc (blob->nuids, sizeof *blob->uids );
+  blob->sigs = xtrycalloc (blob->nsigs, sizeof *blob->sigs );
+  if (!blob->keys || !blob->uids || !blob->sigs)
+    {
+      rc = KEYBOX_Out_Of_Core;
+      goto leave;
+    }
+
+  rc = pgp_create_key_part ( blob, keyblock );
+  if (rc)
+    goto leave;
+  rc = pgp_create_uid_part ( blob, keyblock );
+  if (rc)
+    goto leave;
+  rc = pgp_create_sig_part ( blob, keyblock );
+  if (rc)
+    goto leave;
+  
+  init_membuf (blob->buf, 1024);
+  rc = create_blob_header (blob, BLOBTYPE_OPENPGP);
+  if (rc)
+    goto leave;
+  rc = pgp_create_blob_keyblock (blob, keyblock);
+  if (rc)
+    goto leave;
+  rc = create_blob_trailer (blob);
+  if (rc)
+    goto leave;
+  rc = create_blob_finish ( blob );
+  if (rc)
+    goto leave;
+
+  
+ leave:
+  release_kid_list (blob->temp_kids);
+  blob->temp_kids = NULL;
+  if (rc)
+    {
+      keybox_release_blob (blob);
+      *r_blob = NULL;
+    }
+  else
+    {
+      *r_blob = blob;
+    }
+  return rc;
+}
+#endif /*KEYBOX_WITH_OPENPGP*/
+
+
+\f
+int
+_keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen)
+{
+  KEYBOXBLOB blob;
+  
+  *r_blob = NULL;
+  blob = xtrycalloc (1, sizeof *blob);
+  if (!blob)
+    return KEYBOX_Out_Of_Core;
+
+  blob->blob = image;
+  blob->bloblen = imagelen;
+  *r_blob = blob;
+  return 0;
+}
+
+void
+_keybox_release_blob (KEYBOXBLOB blob)
+{
+  if (!blob)
+    return;
+/*    if (blob->buf) */
+/*      iobuf_cancel( blob->buf ); */
+  xfree (blob->keys );
+  xfree (blob->uids );
+  xfree (blob->sigs );
+  xfree (blob->blob );
+  xfree (blob );
+}
+
+
+
+const char *
+_keybox_get_blob_image ( KEYBOXBLOB blob, size_t *n )
+{
+    *n = blob->bloblen;
+    return blob->blob;
+}
+
+
diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h
new file mode 100644 (file)
index 0000000..2adbdd2
--- /dev/null
@@ -0,0 +1,147 @@
+/* keybox-defs.h - interal Keybox defintions
+ *     Copyright (C) 2001 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
+ */
+
+#ifndef KEYBOX_DEFS_H
+#define KEYBOX_DEFS_H 1
+
+#include <sys/types.h> /* off_t */
+#include "keybox.h"
+
+#ifndef HAVE_BYTE_TYPEDEF
+typedef unsigned char byte; /* fixme */
+#endif
+#ifndef HAVE_U16_TYPEDEF
+typedef unsigned short u16; /* fixme */
+#endif
+#ifndef HAVE_U32_TYPEDEF
+typedef unsigned int u32; /* fixme */
+#endif
+
+enum {
+  BLOBTYPE_HEADER = 1,
+  BLOBTYPE_PGP = 2,
+  BLOBTYPE_X509 = 3
+};
+
+
+
+typedef struct keybox_name *KB_NAME;
+typedef struct keybox_name const * CONST_KB_NAME;
+struct keybox_name {
+  struct keybox_name *next;
+  int secret;
+  /*DOTLOCK lockhd;*/
+  int is_locked;
+  int did_full_scan;
+  char fname[1];
+};
+
+
+
+struct keybox_handle {
+  CONST_KB_NAME resource;
+  int secret;             /* this is for a secret keybox */
+  struct {
+    CONST_KB_NAME kb;
+    /*IOBUF iobuf;*/
+    int eof;
+    int error;
+  } current;
+  struct {
+    CONST_KB_NAME kb; 
+    off_t offset;
+    size_t pk_no;
+    size_t uid_no;
+    unsigned int n_packets; /*used for delete and update*/
+  } found;
+  struct {
+    char *name;
+    char *pattern;
+  } word_match;
+};
+
+
+typedef struct keyboxblob *KEYBOXBLOB;
+
+
+
+/*-- keybox-blob.c --*/
+int  _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen);
+void _keybox_release_blob (KEYBOXBLOB blob);
+const char *_keybox_get_blob_image (KEYBOXBLOB blob, size_t *n);
+
+/*-- keybox-file.c --*/
+int _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp);
+
+/*-- keybox-dump.c --*/
+int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp);
+int _keybox_dump_file (const char *filename, FILE *outfp);
+
+
+/*-- keybox-util.c --*/
+void *_keybox_malloc (size_t n);
+void *_keybox_calloc (size_t n, size_t m);
+void *_keybox_realloc (void *p, size_t n);
+void  _keybox_free (void *p);
+
+#define xtrymalloc(a)    _keybox_malloc ((a))
+#define xtrycalloc(a,b)  _keybox_calloc ((a),(b))
+#define xtryrealloc(a,b) _keybox_realloc((a),(b))
+#define xfree(a)         _keybox_free ((a))
+
+
+#define DIM(v) (sizeof(v)/sizeof((v)[0]))
+#define DIMof(type,member)   DIM(((type *)0)->member)
+#ifndef STR
+  #define STR(v) #v
+#endif
+#define STR2(v) STR(v)
+
+/*
+  a couple of handy macros 
+*/
+
+#define return_if_fail(expr) do {                        \
+    if (!(expr)) {                                       \
+        fprintf (stderr, "%s:%d: assertion `%s' failed\n", \
+                 __FILE__, __LINE__, #expr );            \
+        return;                                                 \
+    } } while (0)
+#define return_null_if_fail(expr) do {                   \
+    if (!(expr)) {                                       \
+        fprintf (stderr, "%s:%d: assertion `%s' failed\n", \
+                 __FILE__, __LINE__, #expr );            \
+        return NULL;                                    \
+    } } while (0)
+#define return_val_if_fail(expr,val) do {                \
+    if (!(expr)) {                                       \
+        fprintf (stderr, "%s:%d: assertion `%s' failed\n", \
+                 __FILE__, __LINE__, #expr );            \
+        return (val);                                   \
+    } } while (0)
+#define never_reached() do {                                   \
+        fprintf (stderr, "%s:%d: oops; should never get here\n", \
+                 __FILE__, __LINE__ );                         \
+    } while (0)
+
+
+#endif /*KEYBOX_DEFS_H*/
+
+
diff --git a/kbx/keybox-dump.c b/kbx/keybox-dump.c
new file mode 100644 (file)
index 0000000..6022900
--- /dev/null
@@ -0,0 +1,250 @@
+/* keybox-dump.c - Debug helpers
+ *     Copyright (C) 2001 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "keybox-defs.h"
+
+static ulong
+get32 (const byte *buffer)
+{
+  ulong a;
+  a =  *buffer << 24;
+  a |= buffer[1] << 16;
+  a |= buffer[2] << 8;
+  a |= buffer[3];
+  return a;
+}
+
+static ulong
+get16 (const byte *buffer)
+{
+  ulong a;
+  a =  *buffer << 8;
+  a |= buffer[1];
+  return a;
+}
+
+static int
+dump_header_blob (const byte *buffer, size_t length, FILE *fp)
+{
+  fprintf (fp, "Version: %d\n", buffer[5]);
+  if ( memcmp (buffer+8, "KBXf", 4))
+    fprintf (fp, "[Error: invalid magic number]\n");
+  return 0;
+}
+
+\f
+/* Dump one block to FP */
+int
+_keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
+{
+  const byte *buffer;
+  size_t length;
+  int type;
+  ulong n, nkeys, keyinfolen;
+  ulong nuids, uidinfolen;
+  ulong nsigs, siginfolen;
+  ulong rawdata_off, rawdata_len;
+  const byte *p;
+
+  buffer = _keybox_get_blob_image (blob, &length);
+  
+  if (length < 40)
+    {
+      fprintf (fp, "[blob too short]\n");
+      return -1;
+    }
+
+  n = get32( buffer );
+  if (n > length) 
+    fprintf (fp, "[blob larger than length - output truncated]\n");
+  else
+    length = n;  /* ignore the rest */
+
+  fprintf (fp, "Length: %lu\n", n );
+  type = buffer[4];
+  switch (type)
+    {
+    case BLOBTYPE_HEADER:
+      fprintf (fp, "Type:   Header\n");
+      return dump_header_blob (buffer, length, fp);
+    case BLOBTYPE_PGP:
+      fprintf (fp, "Type:   OpenPGP\n");
+      break;
+    case BLOBTYPE_X509:
+      fprintf (fp, "Type:   X.509\n");
+      break;
+    default:
+      fprintf (fp, "Type:   %d\n", type);
+      fprintf (fp, "[can't dump this blob type]\n");
+      return 0;
+    }
+  fprintf (fp, "Version: %d\n", buffer[5]);
+  
+  n = get16 (buffer + 6);
+  fprintf( fp, "Blob-Flags: %04lX\n", n);
+  
+  rawdata_off = get32 (buffer + 8);
+  rawdata_len = get32 (buffer + 12);
+
+  fprintf( fp, "Data-Offset: %lu\n", rawdata_off );
+  fprintf( fp, "Data-Length: %lu\n", rawdata_len );
+
+  nkeys = get16 (buffer + 16);
+  fprintf (fp, "Key-Count: %lu\n", nkeys );
+  if (!nkeys)
+    fprintf (fp, "[Error: no keys]\n");
+  if (nkeys > 1 && type == BLOBTYPE_X509)
+    fprintf (fp, "[Error: only one key allowed for X509]\n");
+
+  keyinfolen = get16 (buffer + 18 );
+  fprintf (fp, "Key-Info-Length: %lu\n", keyinfolen);
+  /* fixme: check bounds */
+  p = buffer + 20;
+  for (n=0; n < nkeys; n++, p += keyinfolen)
+    {
+      int i;
+      ulong kidoff, kflags;
+    
+      fprintf (fp, "Key-%lu-Fpr: ", n );
+      for (i=0; i < 20; i++ )
+        fprintf (fp, "%02X", p[i]);
+      kidoff = get32 (p + 20);
+      fprintf (fp, "\nKey-%lu-Kid-Off: %lu\n", n, kidoff );
+      fprintf (fp, "Key-%lu-Kid: ", n );
+      /* fixme: check bounds */
+      for (i=0; i < 8; i++ )
+        fprintf (fp, "%02X", buffer[kidoff+i] );
+      kflags = get16 (p + 24 );
+      fprintf( fp, "\nKey-%lu-Flags: %04lX\n", n, kflags);
+    }
+  
+  nuids = get16 (p);
+  fprintf (fp, "Uid-Count: %lu\n", nuids );
+  uidinfolen = get16  (p + 2);
+  fprintf (fp, "Uid-Info-Length: %lu\n", uidinfolen);
+  /* fixme: check bounds */
+  p += 4;
+  for (n=0; n < nuids; n++, p += uidinfolen)
+    {
+      ulong uidoff, uidlen, uflags;
+      
+      uidoff = get32( p );
+      uidlen = get32( p+4 );
+      fprintf (fp, "Uid-%lu-Off: %lu\n", n, uidoff );
+      fprintf (fp, "Uid-%lu-Len: %lu\n", n, uidlen );
+      fprintf (fp, "Uid-%lu: \"", n );
+      /*print_string (fp, buffer+uidoff, uidlen, '\"');*/
+      fputs ("\"\n", fp);
+      uflags = get16 (p + 8);
+      fprintf (fp, "Uid-%lu-Flags: %04lX\n", n, uflags );
+      fprintf (fp, "Uid-%lu-Validity: %d\n", n, p[10] );
+    }
+  
+  nsigs = get16 (p);
+  fprintf (fp, "Sig-Count: %lu\n", nsigs );
+  siginfolen = get16 (p + 2);
+  fprintf (fp, "Sig-Info-Length: %lu\n", siginfolen );
+  /* fixme: check bounds  */
+  p += 4;
+  for (n=0; n < nsigs; n++, p += siginfolen)
+    {
+      ulong sflags;
+    
+      sflags = get32 (p);
+      fprintf (fp, "Sig-%lu-Expire: ", n );
+      if (!sflags)
+        fputs ("[not checked]", fp);
+      else if (sflags == 1 )
+        fputs ("[missing key]", fp);
+      else if (sflags == 2 )
+        fputs ("[bad signature]", fp);
+      else if (sflags < 0x10000000)
+        fprintf (fp, "[bad flag %0lx]", sflags);
+      else if (sflags == 0xffffffff)
+        fputs ("0", fp );
+      else
+        fputs ("a time"/*strtimestamp( sflags )*/, fp );
+      putc ('\n', fp );
+    }
+
+  fprintf (fp, "Ownertrust: %d\n", p[0] );
+  fprintf (fp, "All-Validity: %d\n", p[1] );
+  p += 4;
+  n = get32 (p); p += 4;
+  fprintf (fp, "Recheck-After: %s\n", /*n? strtimestamp(n) :*/ "0" );
+  n = get32 (p ); p += 4;
+  fprintf( fp, "Latest-Timestamp: %s\n", "0"/*strtimestamp(n)*/ );
+  n = get32 (p ); p += 4;
+  fprintf (fp, "Created-At: %s\n", "0"/*strtimestamp(n)*/ );
+  n = get32 (p ); p += 4;
+  fprintf (fp, "Reserved-Space: %lu\n", n );
+
+  /* check that the keyblock is at the correct offset and other bounds */
+  /*fprintf (fp, "Blob-Checksum: [MD5-hash]\n");*/
+  return 0;
+}
+
+
+\f
+int
+_keybox_dump_file (const char *filename, FILE *outfp)
+{
+  FILE *fp;
+  KEYBOXBLOB blob;
+  int rc;
+  unsigned long count = 0;
+
+  if (!filename)
+    {
+      filename = "-";
+      fp = stdin;
+    }
+  else
+    fp = fopen (filename, "rb");
+  if (!fp)
+    {
+      fprintf (outfp, "can't open `%s': %s\n", filename, strerror(errno));
+      return KEYBOX_File_Error;
+    }
+
+  while ( !(rc = _keybox_read_blob (&blob, fp)) )
+    {
+      fprintf (outfp, "BEGIN-RECORD: %lu\n", count );
+      _keybox_dump_blob (blob, outfp);
+      _keybox_release_blob (blob);
+      fprintf (outfp, "END-RECORD\n");
+      count++;
+    }
+  if (rc == -1)
+    rc = 0;
+  if (rc)
+    fprintf (outfp, "error reading `%s': %s\n", filename,
+             rc == KEYBOX_Read_Error? keybox_strerror(rc):strerror (errno));
+  
+  if (fp != stdin)
+    fclose (fp);
+  return rc;
+}
diff --git a/kbx/keybox-errors.c b/kbx/keybox-errors.c
new file mode 100644 (file)
index 0000000..bd03cdf
--- /dev/null
@@ -0,0 +1,40 @@
+/* Generated automatically by mkerrors */
+/* Do not edit! */
+
+#include <stdio.h>
+#include "keybox-defs.h"
+
+/**
+ * keybox_strerror:
+ * @err:  Error code 
+ * 
+ * This function returns a textual representaion of the given
+ * errorcode. If this is an unknown value, a string with the value
+ * is returned (Beware: it is hold in a static buffer).
+ * 
+ * Return value: String with the error description.
+ **/
+const char *
+keybox_strerror (KeyboxError err)
+{
+  const char *s;
+  static char buf[25];
+
+  switch (err)
+    {
+    case KEYBOX_No_Error: s="no error"; break;
+    case KEYBOX_General_Error: s="general error"; break;
+    case KEYBOX_Out_Of_Core: s="out of core"; break;
+    case KEYBOX_Invalid_Value: s="invalid value"; break;
+    case KEYBOX_Timeout: s="timeout"; break;
+    case KEYBOX_Read_Error: s="read error"; break;
+    case KEYBOX_Write_Error: s="write error"; break;
+    case KEYBOX_File_Error: s="file error"; break;
+    case KEYBOX_Blob_Too_Short: s="blob too short"; break;
+    case KEYBOX_Blob_Too_Large: s="blob too large"; break;
+    default:  sprintf (buf, "ec=%d", err ); s=buf; break;
+    }
+
+  return s;
+}
+
diff --git a/kbx/keybox-file.c b/kbx/keybox-file.c
new file mode 100644 (file)
index 0000000..66bca50
--- /dev/null
@@ -0,0 +1,113 @@
+/* keybox-file.c - file oeprations
+ *     Copyright (C) 2001 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "keybox-defs.h"
+
+
+int
+_keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
+{
+  char *image;
+  size_t imagelen = 0;
+  int c1, c2, c3, c4;
+  int rc;
+
+  *r_blob = NULL;
+  if ((c1 = getc (fp)) == EOF
+      || (c2 = getc (fp)) == EOF
+      || (c3 = getc (fp)) == EOF
+      || (c4 = getc (fp)) == EOF ) {
+    if ( c1 == EOF && !ferror (fp) )
+      return -1; /* eof */
+    return KEYBOX_Read_Error;
+  }
+
+  imagelen = (c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4;
+  if (imagelen > 500000) /* sanity check */
+    return KEYBOX_Blob_Too_Large;
+  
+  if (imagelen < 4) 
+    return KEYBOX_Blob_Too_Short;
+    
+  image = xtrymalloc (imagelen);
+  if (!image) 
+    return KEYBOX_Out_Of_Core;
+
+  image[0] = c1; image[1] = c2; image[2] = c3; image[3] = c4;
+  if (fread (image+4, imagelen-4, 1, fp) != 1)
+    {
+      return KEYBOX_Read_Error;
+    }
+  
+  rc = _keybox_new_blob (r_blob, image, imagelen);
+  if (rc)
+      xfree (image);
+  return rc;
+}
+
+
+
+
+
+void
+export_as_kbxfile(void)
+{
+#if 0
+    KBPOS kbpos;
+    KBNODE keyblock = NULL;
+    int rc=0;
+
+    rc = enum_keyblocks_begin( &kbpos, 0 );
+    if( rc ) {
+       if( rc != -1 )
+           log_error("enum_keyblocks(open) failed: %s\n", gpg_errstr(rc) );
+       goto leave;
+    }
+
+    while( !(rc = enum_keyblocks_next( kbpos, 1, &keyblock )) ) {
+       KBXBLOB blob;
+       const char *p;
+       size_t n;
+
+       merge_keys_and_selfsig( keyblock );
+       rc = kbx_create_blob ( &blob, keyblock );
+       if( rc ) {
+           log_error("kbx_create_blob failed: %s\n", gpg_errstr(rc) );
+           goto leave;
+       }
+       p = kbx_get_blob_image ( blob, &n );
+       fwrite( p, n, 1, stdout );
+       kbx_release_blob ( blob );
+    }
+
+    if( rc && rc != -1 )
+       log_error("enum_keyblocks(read) failed: %s\n", gpg_errstr(rc));
+
+  leave:
+    enum_keyblocks_end( kbpos );
+    release_kbnode( keyblock );
+#endif
+}
+
diff --git a/kbx/keybox-init.c b/kbx/keybox-init.c
new file mode 100644 (file)
index 0000000..a4649d1
--- /dev/null
@@ -0,0 +1,73 @@
+/* keybox-init.c - Initalization of the library 
+ *     Copyright (C) 2001 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "keybox-defs.h"
+
+/* 
+ * Register a filename for plain keybox files.  Returns a pointer to
+ * be used to create a handles etc or NULL to indicate that it has
+ * already been registered */
+void *
+keybox_register_file (const char *fname, int secret)
+{
+  return NULL;
+#if 0
+    KB_NAME kr;
+
+    if (active_handles)
+        BUG (); /* We don't allow that */
+
+    for (kr=kb_names; kr; kr = kr->next) {
+        if ( !compare_filenames (kr->fname, fname) )
+            return NULL; /* already registered */
+    }
+
+    kr = m_alloc (sizeof *kr + strlen (fname));
+    strcpy (kr->fname, fname);
+    kr->secret = !!secret;
+    kr->lockhd = NULL;
+    kr->is_locked = 0;
+    kr->did_full_scan = 0;
+    /* keep a list of all issued pointers */
+    kr->next = kb_names;
+    kb_names = kr;
+
+    /* create the offset table the first time a function here is used */
+    if (!kb_offtbl)
+      kb_offtbl = new_offset_hash_table ();
+
+    return kr;
+#endif
+}
+
+int
+keybox_is_writable (void *token)
+{
+  KB_NAME r = token;
+
+  return r? !access (r->fname, W_OK) : 0;
+}
+    
diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c
new file mode 100644 (file)
index 0000000..d2c61ff
--- /dev/null
@@ -0,0 +1,158 @@
+/* keybox-search.c - Search operations
+ *     Copyright (C) 2001 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "keybox-defs.h"
+
+
+/****************
+ * Check whether the given fingerprint (20 bytes) is in the
+ * given keyblob.  fpr is always 20 bytes.
+ * Return: 0 = found
+ *        -1 = not found
+         other = error  (fixme: do not always reurn gpgerr_general)
+ */
+int
+keybox_blob_has_fpr ( KEYBOXBLOB blob, const byte *fpr )
+{
+    ulong n, nkeys, keyinfolen;
+    const byte *p, *pend;
+    byte *buffer = blob->blob;
+    size_t buflen = blob->bloblen;
+
+    if ( buflen < 40 )
+       return GPGERR_GENERAL; /* blob too short */
+    n = get32( buffer );
+    if ( n > buflen )
+       return GPGERR_GENERAL; /* blob larger than announced length */
+    buflen = n;  /* ignore trailing stuff */
+    pend = buffer + n - 1;
+
+    if ( buffer[4] != 2 )
+       return GPGERR_GENERAL; /* invalid blob type */
+    if ( buffer[5] != 1 )
+       return GPGERR_GENERAL; /* invalid blob format version */
+
+    nkeys = get16( buffer + 16 );
+    keyinfolen = get16( buffer + 18 );
+    p = buffer + 20;
+    for(n=0; n < nkeys; n++, p += keyinfolen ) {
+       if ( p+20 > pend )
+           return GPGERR_GENERAL; /* blob shorter than required */
+       if (!memcmp ( p, fpr, 20 ) )
+           return 0; /* found */
+    }
+    return -1;
+}
+
+/****************
+ * Check whether the given keyID (20 bytes) is in the
+ * given keyblob.
+ * Return: 0 = found
+ *        -1 = not found
+         other = error  (fixme: do not always return gpgerr_general)
+ */
+int
+keybox_blob_has_kid ( KEYBOXBLOB blob, const byte *keyidbuf, size_t keyidlen )
+{
+    ulong n, nkeys, keyinfolen, off;
+    const byte *p, *pend;
+    byte *buffer = blob->blob;
+    size_t buflen = blob->bloblen;
+
+    if ( buflen < 40 )
+       return GPGERR_GENERAL; /* blob too short */
+    n = get32( buffer );
+    if ( n > buflen )
+       return GPGERR_GENERAL; /* blob larger than announced length */
+    buflen = n;  /* ignore trailing stuff */
+    pend = buffer + n - 1;
+
+    if ( buffer[4] != 2 )
+       return GPGERR_GENERAL; /* invalid blob type */
+    if ( buffer[5] != 1 )
+       return GPGERR_GENERAL; /* invalid blob format version */
+
+    nkeys = get16( buffer + 16 );
+    keyinfolen = get16( buffer + 18 );
+    p = buffer + 20;
+    for(n=0; n < nkeys; n++, p += keyinfolen ) {
+       if ( p+24 > pend )
+           return GPGERR_GENERAL; /* blob shorter than required */
+       off = get32 ( p + 20 );
+       if (keyidlen < 8 ) /* actually keyidlen may either be 4 or 8 */
+           off +=4;
+       if ( off+keyidlen > buflen )
+           return GPGERR_GENERAL; /* offset out of bounds */
+       if ( !memcmp ( buffer+off, keyidbuf, keyidlen ) )
+           return 0; /* found */
+    }
+    return -1;
+}
+
+
+
+int
+keybox_blob_has_uid ( KEYBOXBLOB blob,
+                  int (*cmp)(const byte *, size_t, void *), void *opaque )
+{
+    ulong n, nuids, uidinfolen, off, len;
+    const byte *p, *pend;
+    byte *buffer = blob->blob;
+    size_t buflen = blob->bloblen;
+
+    if ( buflen < 40 )
+       return GPGERR_GENERAL; /* blob too short */
+    n = get32( buffer );
+    if ( n > buflen )
+       return GPGERR_GENERAL; /* blob larger than announced length */
+    buflen = n;  /* ignore trailing stuff */
+    pend = buffer + n - 1;
+
+    if ( buffer[4] != 2 )
+       return GPGERR_GENERAL; /* invalid blob type */
+    if ( buffer[5] != 1 )
+       return GPGERR_GENERAL; /* invalid blob format version */
+
+    p = buffer + 20 + get16( buffer + 16 ) * get16( buffer + 18 );
+    if ( p+4 > pend )
+       return GPGERR_GENERAL; /* blob shorter than required */
+
+    nuids = get16( p ); p+= 2;
+    uidinfolen = get16( p ); p+=2;
+    for(n=0; n < nuids; n++, p += uidinfolen ) {
+       if ( p+8 > pend )
+           return GPGERR_GENERAL; /* blob shorter than required */
+       off = get32 ( p );
+       len = get32 ( p + 4 );
+       if ( off+len > buflen )
+           return GPGERR_GENERAL; /* offset out of bounds */
+       if ( (*cmp) ( buffer+off, len, opaque ) )
+           return 0; /* found */
+    }
+
+    return -1;
+}
+
+
diff --git a/kbx/keybox-util.c b/kbx/keybox-util.c
new file mode 100644 (file)
index 0000000..ed5d93d
--- /dev/null
@@ -0,0 +1,72 @@
+/* keybox-util.c - Utility functions for Keybox 
+ *     Copyright (C) 2001 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "keybox-defs.h"
+
+
+static void *(*alloc_func)(size_t n) = malloc;
+static void *(*realloc_func)(void *p, size_t n) = realloc;
+static void (*free_func)(void*) = free;
+
+
+
+void
+keybox_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
+                          void *(*new_realloc_func)(void *p, size_t n),
+                          void (*new_free_func)(void*) )
+{
+  alloc_func       = new_alloc_func;
+  realloc_func      = new_realloc_func;
+  free_func        = new_free_func;
+}
+
+void *
+_keybox_malloc (size_t n)
+{
+  return alloc_func (n);
+}
+
+void *
+_keybox_realloc (void *a, size_t n)
+{
+  return realloc_func (a, n);
+}
+
+void *
+_keybox_calloc (size_t n, size_t m)
+{
+  void *p = _keybox_malloc (n*m);
+  if (p)
+    memset (p, 0, n* m);
+  return p;
+}
+
+void
+_keybox_free (void *p)
+{
+  if (p)
+    free_func (p);
+}
+
diff --git a/kbx/keybox.h b/kbx/keybox.h
new file mode 100644 (file)
index 0000000..9008823
--- /dev/null
@@ -0,0 +1,99 @@
+/* keybox.h - Keybox operations
+ *     Copyright (C) 2001 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
+ */
+
+#ifndef KEYBOX_H
+#define KEYBOX_H 1
+#ifdef __cplusplus
+extern "C" { 
+#if 0
+ }
+#endif
+#endif
+
+#define KEYBOX_WITH_OPENPGP 1 
+#define KEYBOX_WITH_X509 1
+
+
+#ifdef KEYBOX_WITH_OPENPGP
+#  undef KEYBOX_WITH_OPENPGP
+/*#include <lib-to-handle-gpg-data-structs.h>*/
+#endif
+
+#ifdef KEYBOX_WITH_X509
+# include <ksba.h>
+#endif
+
+
+typedef enum {
+  KEYBOX_No_Error = 0,
+  KEYBOX_General_Error = 1,
+  KEYBOX_Out_Of_Core = 2,
+  KEYBOX_Invalid_Value = 3,
+  KEYBOX_Timeout = 4,  
+  KEYBOX_Read_Error = 5,
+  KEYBOX_Write_Error = 6,
+  KEYBOX_File_Error = 7,
+  KEYBOX_Blob_Too_Short = 8,
+  KEYBOX_Blob_Too_Large = 9
+
+} KeyboxError;
+
+
+
+typedef struct keybox_handle *KEYBOX_HANDLE;
+
+
+
+/*-- keybox-init.c --*/
+void *keybox_register_file (const char *fname, int secret);
+int keybox_is_writable (void *token);
+
+
+/*--  --*/
+
+KEYBOX_HANDLE keybox_new (void *token, int secret);
+void keybox_release (KEYBOX_HANDLE hd);
+const char *keybox_get_resource_name (KEYBOX_HANDLE hd);
+int keybox_lock (KEYBOX_HANDLE hd, int yes);
+#if 0
+int keybox_get_keyblock (KEYBOX_HANDLE hd, KBNODE *ret_kb);
+int keybox_update_keyblock (KEYBOX_HANDLE hd, KBNODE kb);
+int keybox_insert_keyblock (KEYBOX_HANDLE hd, KBNODE kb);
+int keybox_locate_writable (KEYBOX_HANDLE hd);
+int keybox_delete_keyblock (KEYBOX_HANDLE hd);
+int keybox_search_reset (KEYBOX_HANDLE hd);
+int keybox_search (KEYBOX_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
+int keybox_rebuild_cache (void *);
+#endif
+
+
+/*-- keybox-util.c --*/
+void keybox_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
+                               void *(*new_realloc_func)(void *p, size_t n),
+                               void (*new_free_func)(void*) );
+
+/*-- keybox-errors.c (built) --*/
+const char *keybox_strerror (KeyboxError err);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*KEYBOX_H*/
diff --git a/kbx/mkerrors b/kbx/mkerrors
new file mode 100755 (executable)
index 0000000..5adb7bf
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/sh
+# mkerrors - Extract error strings from assuan.h
+#            and create C source for assuan_strerror
+#      Copyright (C) 2001 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
+
+cat <<EOF
+/* Generated automatically by mkerrors */
+/* Do not edit! */
+
+#include <stdio.h>
+#include "keybox-defs.h"
+
+/**
+ * keybox_strerror:
+ * @err:  Error code 
+ * 
+ * This function returns a textual representaion of the given
+ * errorcode. If this is an unknown value, a string with the value
+ * is returned (Beware: it is hold in a static buffer).
+ * 
+ * Return value: String with the error description.
+ **/
+const char *
+keybox_strerror (KeyboxError err)
+{
+  const char *s;
+  static char buf[25];
+
+  switch (err)
+    {
+EOF
+
+awk '
+/KEYBOX_No_Error/    { okay=1 }
+!okay              {next}
+/}/                { exit 0 }
+/KEYBOX_[A-Za-z_]*/ { print_code($1) }
+
+
+function print_code( s )
+{
+printf "    case %s: s=\"", s ;
+gsub(/_/, " ", s );
+printf "%s\"; break;\n", tolower(substr(s,8));
+}
+'
+
+cat <<EOF
+    default:  sprintf (buf, "ec=%d", err ); s=buf; break;
+    }
+
+  return s;
+}
+
+EOF