We have reached a state where we are able to import certs and
authorWerner Koch <wk@gnupg.org>
Tue, 13 Nov 2001 12:50:14 +0000 (12:50 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 13 Nov 2001 12:50:14 +0000 (12:50 +0000)
check the certification path.

25 files changed:
kbx/Makefile.am
kbx/kbxutil.c
kbx/keybox-blob.c
kbx/keybox-defs.h
kbx/keybox-dump.c
kbx/keybox-errors.c
kbx/keybox-file.c
kbx/keybox-init.c
kbx/keybox-search-desc.h [new file with mode: 0644]
kbx/keybox-search.c
kbx/keybox-update.c [new file with mode: 0644]
kbx/keybox.h
sm/Makefile.am
sm/certchain.c [new file with mode: 0644]
sm/certcheck.c [new file with mode: 0644]
sm/certdump.c [new file with mode: 0644]
sm/certpath.c [new file with mode: 0644]
sm/fingerprint.c [new file with mode: 0644]
sm/gpgsm.c
sm/gpgsm.h
sm/import.c
sm/keydb.c
sm/keydb.h
sm/misc.c
sm/util.h

index 81885f3..4c783fc 100644 (file)
@@ -27,13 +27,14 @@ noinst_LIBRARIES = libkeybox.a
 bin_PROGRAMS = kbxutil
 
 common_sources = \
-       keybox.h \
-       keybox-defs.h \
+       keybox.h keybox-defs.h keybox-search-desc.h \
        keybox-util.c \
        keybox-errors.c \
        keybox-init.c \
        keybox-blob.c \
        keybox-file.c \
+       keybox-search.c \
+       keybox-update.c \
        keybox-dump.c 
 
 
@@ -41,7 +42,8 @@ libkeybox_a_SOURCES = $(common_sources)
 
 kbxutil_SOURCES = kbxutil.c $(common_sources)
 kbxutil_LDADD   = ../jnlib/libjnlib.a  \
-                  ../../libgcrypt/src/.libs/libgcrypt.so.1
+                 ../../libksba/src/.libs/libksba.a \
+                  ../../libgcrypt/src/.libs/libgcrypt.so.1 
 
 keybox-errors.c : keybox.h mkerrors
        $(srcdir)/mkerrors < $(srcdir)/keybox.h > keybox-errors.c
index 8c3dee9..e8b015b 100644 (file)
@@ -234,8 +234,9 @@ main( int argc, char **argv )
   /*create_dotlock(NULL); register locking cleanup */
   i18n_init();
 
-  /* We need to use the gcry malloc function becuase jnlib does use them */
+  /* We need to use the gcry malloc function because jnlib does use them */
   keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
+  ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
 
 
   pargs.argc = &argc;
index 7db6216..84ebc90 100644 (file)
@@ -39,25 +39,29 @@ The first record of a plain KBX file has a special format:
  byte pgp_completes  ditto.
  byte pgp_cert_depth ditto.
 
-The OpenPGP KBX Blob looks like this:
+The OpenPGP and X.509 blob are verry similiar, things which are
+X.509 specific are noted like [X.509: xxx]
 
  u32  length of this blob (including these 4 bytes)
- byte Blob type (2)
+ byte Blob type (2) [X509: 3]
  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!)
+ u32  offset to the OpenPGP keyblock or X509 DER encoded certificate
+ u32  ant its length
+ u16  number of keys (at least 1!) [X509: always 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)
+        or 0 if not known which is the case opnly for X509.
    u16 special key flags
         bit 0 =
    u16 reserved
+ u16  size of serialnumber(may be zero) 
+   n  u16 (see above) bytes of serial number
  u16  number of user IDs
  u16  size of additional user ID information
  n times:
@@ -67,6 +71,8 @@ The OpenPGP KBX Blob looks like this:
         bit 0 =
    byte validity
    byte reserved
+   [For X509, the first user ID is the ISsuer, the second the subject
+   and the others are subjectAltNames]
  u16  number of signatures
  u16  size of signature information (4)
    u32 expiration time of signature with some special values:
@@ -75,8 +81,8 @@ The OpenPGP KBX Blob looks like this:
        0x00000002 = bad signature
        0x10000000 = valid and expires at some date in 1978.
        0xffffffff = valid and does not expire
- u8    assigned ownertrust
- u8    all_validity
+ u8    assigned ownertrust [X509: no used]
+ u8    all_validity        [X509: no used]
  u16   reserved
  u32   recheck_after
  u32   Newest timestamp in the keyblock (useful for KS syncronsiation?)
@@ -90,7 +96,9 @@ The OpenPGP KBX Blob looks like this:
 
     maybe we put a signature here later.
 
- b16   MD5 checksum  (useful for KS syncronisation)
+ b16   MD5 checksum  (useful for KS syncronisation), we might also want to use
+    a mac here.
+ b4    resevered
 
 */
 
@@ -103,8 +111,17 @@ The OpenPGP KBX Blob looks like this:
 #include <assert.h>
 #include <gcrypt.h>
 
+#ifdef KEYBOX_WITH_OPENPGP
+/* include stuff to parse the packets */
+#endif
+#ifdef KEYBOX_WITH_X509
+#include <ksba.h>
+#endif
+
 #include "keybox-defs.h"
 
+
+
 /* special values of the signature status */
 #define SF_NONE(a)  ( !(a) )
 #define SF_NOKEY(a) ((a) & (1<<0))
@@ -125,16 +142,17 @@ struct membuf {
 /*  #endif */
 
 struct keyboxblob_key {
-    char   fpr[20];
-    u32    off_kid;
-    ulong  off_kid_addr;
-    u16    flags;
+  char   fpr[20];
+  u32    off_kid;
+  ulong  off_kid_addr;
+  u16    flags;
 };
 struct keyboxblob_uid {
-    ulong  off_addr;
-    u32    len;
-    u16    flags;
-    byte   validity;
+  ulong  off_addr;
+  char   *name;     /* used only with x509 */
+  u32    len;
+  u16    flags;
+  byte   validity;
 };
 
 struct keyid_list {
@@ -155,6 +173,8 @@ struct keyboxblob {
   size_t bloblen;
   
   /* stuff used only by keybox_create_blob */
+  unsigned char *serial;
+  size_t seriallen;
   int nkeys;
   struct keyboxblob_key *keys;
   int nuids;
@@ -162,9 +182,11 @@ struct keyboxblob {
   int nsigs;
   u32  *sigs;
   struct fixup_list *fixups;
+  int fixup_out_of_core;
   
   struct keyid_list *temp_kids;
-  struct membuf *buf; /* temporary store for the blob */
+  struct membuf bufbuf; /* temporary store for the blob */
+  struct membuf *buf; 
 };
 
 
@@ -256,6 +278,28 @@ put32 (struct membuf *mb, u32 a )
 }
 
 \f
+/* Store a value in the fixup list */
+static void
+add_fixup (KEYBOXBLOB blob, u32 off, u32 val)
+{
+  struct fixup_list *fl;
+  
+  if (blob->fixup_out_of_core)
+    return;
+
+  fl = xtrycalloc(1, sizeof *fl);
+  if (!fl)
+    blob->fixup_out_of_core = 1;
+  else 
+    {
+      fl->off = off;
+      fl->val = val;
+      fl->next = blob->fixups;
+      blob->fixups = fl;
+    }
+}
+
+\f
 /*
  Some wrappers
 */
@@ -396,16 +440,7 @@ pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock)
   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;
-  }
+  add_fixup (blob, kbstart);
 
   for (n = 0, node = keyblock; node; node = node->next)
     {
@@ -420,28 +455,16 @@ pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock)
           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;
+          add_fixup (blob, blob->uids[n].off_addr, u->stored_at);
           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;
-  }
-
+  add_fixup (blob, a->len - kbstart);
   return 0;
 }
-
 #endif /*KEYBOX_WITH_OPENPGP*/
 
 \f
@@ -450,6 +473,27 @@ pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock)
    X.509 specific stuff
  */
 
+/* Write the raw certificate out */
+static int
+x509_create_blob_cert (KEYBOXBLOB blob, KsbaCert cert)
+{
+  struct membuf *a = blob->buf;
+  const unsigned char *image;
+  size_t length;
+  u32 kbstart = a->len;
+
+  /* Store our offset for later fixup */
+  add_fixup (blob, 8, kbstart);
+
+  image = ksba_cert_get_image (cert, &length);
+  if (!image)
+    return KEYBOX_General_Error;
+  put_membuf (a, image, length);
+
+  add_fixup (blob, 12, a->len - kbstart);
+  return 0;
+}
 #endif /*KEYBOX_WITH_X509*/
 
 /* Write a stored keyID out to the buffer */
@@ -509,6 +553,10 @@ create_blob_header (KEYBOXBLOB blob, int blobtype)
       put16 ( a, 0 ); /* reserved */
     }
 
+  put16 (a, blob->seriallen); /*fixme: check that it fits into 16 bits*/
+  if (blob->serial)
+    put_membuf (a, blob->serial+4, blob->seriallen);
+
   put16 ( a, blob->nuids );
   put16 ( a, 4 + 4 + 2 + 1 + 1 );  /* size of uid info */
   for (i=0; i < blob->nuids; i++)
@@ -537,31 +585,42 @@ create_blob_header (KEYBOXBLOB blob, int blobtype)
   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++ )
+  /* space where we write keyIDs and and other stuff so that the
+     pointers can actually point to somewhere */
+  if (blobtype == BLOBTYPE_PGP)
     {
-      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;
-       }
+      /* 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++ )
+        {
+          if (blob->keys[i].off_kid) 
+            { /* this is a v3 one */
+              add_fixup (blob, blob->keys[i].off_kid_addr, a->len);
+              write_stored_kid (blob, blob->keys[i].off_kid);
+            }
+          else
+            { /* the better v4 key IDs - just store an offset 8 bytes back */
+              add_fixup (blob, blob->keys[i].off_kid_addr,
+                         blob->keys[i].off_kid_addr - 8); 
+            }
+        }
     }
   
+  if (blobtype == BLOBTYPE_X509)
+    {
+      /* We don't want to point to ASN.1 encoded UserIDs (DNs) but to
+         the utf-8 string represenation of them */
+      for (i=0; i < blob->nuids; i++ )
+        {
+          if (blob->uids[i].name) 
+            { /* this is a v3 one */
+              add_fixup (blob, blob->uids[i].off_addr, a->len);
+              put_membuf (blob->buf, blob->uids[i].name, blob->uids[i].len);
+            }
+        }
+    }
+
     return 0;
 }
 
@@ -585,25 +644,21 @@ create_blob_finish (KEYBOXBLOB blob)
 
   /* write a placeholder for the checksum */
   for (i = 0; i < 16; i++ )
-    put32 (a, 0);
+    put32 (a, 0);  /* Hmmm: why put32() ?? */
   
   /* get the memory area */
-  p = a->buf;
-  n = a->len;
+  p = get_membuf (a, &n);
+  if (!p)
+    return KEYBOX_Out_Of_Core;
   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;
-  }
+  add_fixup (blob, 0, n);
 
   /* do the fixups */
+  if (blob->fixup_out_of_core)
+    return KEYBOX_Out_Of_Core;
+
   {
     struct fixup_list *fl;
     for (fl = blob->fixups; fl; fl = fl->next)
@@ -680,7 +735,8 @@ _keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock)
   if (rc)
     goto leave;
   
-  init_membuf (blob->buf, 1024);
+  init_membuf (&blob->bufbuf, 1024);
+  blob->buf = &blob->bufbuf;
   rc = create_blob_header (blob, BLOBTYPE_OPENPGP);
   if (rc)
     goto leave;
@@ -711,6 +767,101 @@ _keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock)
 }
 #endif /*KEYBOX_WITH_OPENPGP*/
 
+#ifdef KEYBOX_WITH_X509
+/* Note: We should move calculation of the digest into libksba and
+   remove that parameter */
+int
+_keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert,
+                          unsigned char *sha1_digest)
+{
+  int rc = 0;
+  KEYBOXBLOB blob;
+  unsigned char *p;
+
+  *r_blob = NULL;
+  blob = xtrycalloc (1, sizeof *blob);
+  if( !blob )
+    return KEYBOX_Out_Of_Core;
+
+  p = ksba_cert_get_serial (cert);
+  if (p)
+    {
+      size_t n = (p[0] << 24) | (p[1] << 16) | (p[2] <<8) | p[3];
+      blob->seriallen = n;
+      blob->serial = p;
+    }
+      
+
+  blob->nkeys = 1;
+  blob->nuids = 2; /* issuer and subject - fixme: count alternate names */
+  blob->nsigs = 1; 
+
+  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;
+    }
+
+  memcpy (blob->keys[0].fpr, sha1_digest, 20);
+  blob->keys[0].off_kid = 0; /* We don't have keyids */
+  blob->keys[0].flags = 0;
+
+  /* issuer */
+  p = ksba_cert_get_issuer (cert);
+  blob->uids[0].name = p;
+  blob->uids[0].len = p? (strlen(p)+1):0;
+  blob->uids[0].flags = 0;
+  blob->uids[0].validity = 0;
+
+  /* subject */
+  p = ksba_cert_get_subject (cert);
+  blob->uids[1].name = p;
+  blob->uids[1].len = p? (strlen(p)+1):0;
+  blob->uids[1].flags = 0;
+  blob->uids[1].validity = 0;
+
+  /* fixme: add alternate names */
+
+  /* signatures */
+  blob->sigs[0] = 0;   /* not yet checked */
+
+  /* Create a temporary buffer for further processing */
+  init_membuf (&blob->bufbuf, 1024);
+  blob->buf = &blob->bufbuf;
+  /* write out what we already have */
+  rc = create_blob_header (blob, BLOBTYPE_X509);
+  if (rc)
+    goto leave;
+  rc = x509_create_blob_cert (blob, cert);
+  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_X509*/
+
 
 \f
 int
@@ -732,11 +883,14 @@ _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen)
 void
 _keybox_release_blob (KEYBOXBLOB blob)
 {
+  int i;
   if (!blob)
     return;
-/*    if (blob->buf) */
-/*      iobuf_cancel( blob->buf ); */
+  /* hmmm: release membuf here?*/
   xfree (blob->keys );
+  xfree (blob->serial);
+  for (i=0; i < blob->nuids; i++)
+    xfree (blob->uids[i].name);
   xfree (blob->uids );
   xfree (blob->sigs );
   xfree (blob->blob );
@@ -751,5 +905,3 @@ _keybox_get_blob_image ( KEYBOXBLOB blob, size_t *n )
     *n = blob->bloblen;
     return blob->blob;
 }
-
-
index 2adbdd2..308c1ff 100644 (file)
@@ -41,6 +41,8 @@ enum {
 };
 
 
+typedef struct keyboxblob *KEYBOXBLOB;
+
 
 typedef struct keybox_name *KB_NAME;
 typedef struct keybox_name const * CONST_KB_NAME;
@@ -56,16 +58,13 @@ struct keybox_name {
 
 
 struct keybox_handle {
-  CONST_KB_NAME resource;
+  CONST_KB_NAME kb;
   int secret;             /* this is for a secret keybox */
+  FILE *fp;
+  int eof;
+  int error;
   struct {
-    CONST_KB_NAME kb;
-    /*IOBUF iobuf;*/
-    int eof;
-    int error;
-  } current;
-  struct {
-    CONST_KB_NAME kb; 
+    KEYBOXBLOB blob;
     off_t offset;
     size_t pk_no;
     size_t uid_no;
@@ -78,17 +77,32 @@ struct keybox_handle {
 };
 
 
-typedef struct keyboxblob *KEYBOXBLOB;
-
+/* Don't know whether this is needed: */
+/*  static struct { */
+/*    const char *homedir; */
+/*    int dry_run; */
+/*    int quiet; */
+/*    int verbose; */
+/*    int preserve_permissions; */
+/*  } keybox_opt; */
 
 
 /*-- keybox-blob.c --*/
+#ifdef KEYBOX_WITH_OPENPGP
+  /* fixme */
+#endif /*KEYBOX_WITH_OPENPGP*/
+#ifdef KEYBOX_WITH_X509
+int _keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert,
+                              unsigned char *sha1_digest);
+#endif /*KEYBOX_WITH_X509*/
+
 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);
+int _keybox_write_blob (KEYBOXBLOB blob, FILE *fp);
 
 /*-- keybox-dump.c --*/
 int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp);
index 6022900..d84ae73 100644 (file)
@@ -46,6 +46,35 @@ get16 (const byte *buffer)
   return a;
 }
 
+void
+print_string (FILE *fp, const byte *p, size_t n, int delim)
+{
+  for ( ; n; n--, p++ )
+    {
+      if (*p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim)
+        {
+          putc('\\', fp);
+          if( *p == '\n' )
+            putc('n', fp);
+          else if( *p == '\r' )
+            putc('r', fp);
+          else if( *p == '\f' )
+            putc('f', fp);
+          else if( *p == '\v' )
+            putc('v', fp);
+          else if( *p == '\b' )
+            putc('b', fp);
+          else if( !*p )
+            putc('0', fp);
+          else
+            fprintf(fp, "x%02x", *p );
+       }
+      else
+        putc(*p, fp);
+    }
+}
+
+
 static int
 dump_header_blob (const byte *buffer, size_t length, FILE *fp)
 {
@@ -67,6 +96,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
   ulong nuids, uidinfolen;
   ulong nsigs, siginfolen;
   ulong rawdata_off, rawdata_len;
+  ulong nserial;
   const byte *p;
 
   buffer = _keybox_get_blob_image (blob, &length);
@@ -128,19 +158,33 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
       int i;
       ulong kidoff, kflags;
     
-      fprintf (fp, "Key-%lu-Fpr: ", n );
+      fprintf (fp, "Key-Fpr[%lu]: ", 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 );
+      fprintf (fp, "\nKey-Kid-Off[%lu]: %lu\n", n, kidoff );
+      fprintf (fp, "Key-Kid[%lu]: ", 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);
+      fprintf( fp, "\nKey-Flags[%lu]: %04lX\n", n, kflags);
     }
   
+  /* serial number */
+  fputs ("Serial-No: ", fp);
+  nserial = get16 (p);
+  p += 2;
+  if (!nserial)
+    fputs ("none", fp);
+  else
+    {
+      for (; nserial; nserial--, p++)
+        fprintf (fp, "%02X", *p);
+    }
+  putc ('\n', fp);
+
+  /* user IDs */
   nuids = get16 (p);
   fprintf (fp, "Uid-Count: %lu\n", nuids );
   uidinfolen = get16  (p + 2);
@@ -153,14 +197,42 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
       
       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, '\"');*/
+      if (type == BLOBTYPE_X509 && !n)
+        {
+          fprintf (fp, "Issuer-Off: %lu\n", uidoff );
+          fprintf (fp, "Issuer-Len: %lu\n", uidlen );
+          fprintf (fp, "Issuer: \"");
+        }
+      else if (type == BLOBTYPE_X509 && n == 1)
+        {
+          fprintf (fp, "Subject-Off: %lu\n", uidoff );
+          fprintf (fp, "Subject-Len: %lu\n", uidlen );
+          fprintf (fp, "Subject: \"");
+        }
+      else
+        {
+          fprintf (fp, "Uid-Off[%lu]: %lu\n", n, uidoff );
+          fprintf (fp, "Uid-Len[%lu]: %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] );
+      if (type == BLOBTYPE_X509 && !n)
+        {
+          fprintf (fp, "Issuer-Flags: %04lX\n", uflags );
+          fprintf (fp, "Issuer-Validity: %d\n", p[10] );
+        }
+      else if (type == BLOBTYPE_X509 && n == 1)
+        {
+          fprintf (fp, "Subject-Flags: %04lX\n", uflags );
+          fprintf (fp, "Subject-Validity: %d\n", p[10] );
+        }
+      else
+        {
+          fprintf (fp, "Uid-Flags[%lu]: %04lX\n", n, uflags );
+          fprintf (fp, "Uid-Validity[%lu]: %d\n", n, p[10] );
+        }
     }
   
   nsigs = get16 (p);
@@ -174,7 +246,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
       ulong sflags;
     
       sflags = get32 (p);
-      fprintf (fp, "Sig-%lu-Expire: ", n );
+      fprintf (fp, "Sig-Expire[%lu]: ", n );
       if (!sflags)
         fputs ("[not checked]", fp);
       else if (sflags == 1 )
index bd03cdf..e75373c 100644 (file)
@@ -32,6 +32,12 @@ keybox_strerror (KeyboxError err)
     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;
+    case KEYBOX_Invalid_Handle: s="invalid handle"; break;
+    case KEYBOX_File_Create_Error: s="file create error"; break;
+    case KEYBOX_File_Open_Error: s="file open error"; break;
+    case KEYBOX_File_Close_Error: s="file close error"; break;
+    case KEYBOX_Nothing_Found: s="nothing found"; break;
+    case KEYBOX_Wrong_Blob_Type: s="wrong blob type"; break;
     default:  sprintf (buf, "ec=%d", err ); s=buf; break;
     }
 
index 66bca50..715d3fb 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "keybox-defs.h"
 
-
+/* Read a block at the current postion ant return it in r_blocb.  r_blob may be NULL sto simply skip the current block */
 int
 _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
 {
@@ -58,56 +58,28 @@ _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
   image[0] = c1; image[1] = c2; image[2] = c3; image[3] = c4;
   if (fread (image+4, imagelen-4, 1, fp) != 1)
     {
+      xfree (image);
       return KEYBOX_Read_Error;
     }
   
-  rc = _keybox_new_blob (r_blob, image, imagelen);
-  if (rc)
-      xfree (image);
+  rc = r_blob? _keybox_new_blob (r_blob, image, imagelen) : 0;
+  if (rc || !r_blob)
+        xfree (image);
   return rc;
 }
 
 
-
-
-
-void
-export_as_kbxfile(void)
+/* Write the block to the current file position */
+int
+_keybox_write_blob (KEYBOXBLOB blob, FILE *fp)
 {
-#if 0
-    KBPOS kbpos;
-    KBNODE keyblock = NULL;
-    int rc=0;
+  const char *image;
+  size_t length;
 
-    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 );
+  image = _keybox_get_blob_image (blob, &length);
+  if (fwrite (image, length, 1, fp) != 1)
+    {
+      return KEYBOX_Write_Error;
     }
-
-    if( rc && rc != -1 )
-       log_error("enum_keyblocks(read) failed: %s\n", gpg_errstr(rc));
-
-  leave:
-    enum_keyblocks_end( kbpos );
-    release_kbnode( keyblock );
-#endif
+  return 0;
 }
-
index a4649d1..1a4a587 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <assert.h>
 
 #include "keybox-defs.h"
 
+#define compare_filenames strcmp
+
+static KB_NAME kb_names;
+
+
 /* 
- * 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 */
+  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;
+  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 */
+  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
+  kr = xtrymalloc (sizeof *kr + strlen (fname));
+  if (!kr)
+    return NULL;
+  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;
 }
 
 int
@@ -70,4 +73,48 @@ keybox_is_writable (void *token)
 
   return r? !access (r->fname, W_OK) : 0;
 }
+
     
+
+/* Create a new handle for the resource associated with TOKEN.  SECRET
+   is just a cross-check.
+   
+   The returned handle must be released using keybox_release (). */
+KEYBOX_HANDLE
+keybox_new (void *token, int secret)
+{
+  KEYBOX_HANDLE hd;
+  KB_NAME resource = token;
+
+  assert (resource && !resource->secret == !secret);
+  hd = xtrycalloc (1, sizeof *hd);
+  if (hd)
+    {
+      hd->kb = resource;
+      hd->secret = !!secret;
+    }
+  return hd;
+}
+
+void 
+keybox_release (KEYBOX_HANDLE hd)
+{
+  if (!hd)
+    return;
+  _keybox_release_blob (hd->found.blob);
+  xfree (hd->word_match.name);
+  xfree (hd->word_match.pattern);
+  xfree (hd);
+}
+
+
+const char *
+keybox_get_resource_name (KEYBOX_HANDLE hd)
+{
+  if (!hd || !hd->kb)
+    return NULL;
+  return hd->kb->fname;
+}
+
+
+
diff --git a/kbx/keybox-search-desc.h b/kbx/keybox-search-desc.h
new file mode 100644 (file)
index 0000000..22bcba6
--- /dev/null
@@ -0,0 +1,69 @@
+/* keybox-search-desc.h - Keybox serch description
+ *     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
+ */
+
+/* 
+   This file is a temporary kludge until we can come up with solution
+   to share this description between keybox and the application
+   specific keydb
+*/
+
+#ifndef KEYBOX_SEARCH_DESC_H
+#define KEYBOX_SEARCH_DESC_H 1
+
+typedef enum {
+  KEYDB_SEARCH_MODE_NONE,
+  KEYDB_SEARCH_MODE_EXACT,
+  KEYDB_SEARCH_MODE_SUBSTR,
+  KEYDB_SEARCH_MODE_MAIL,
+  KEYDB_SEARCH_MODE_MAILSUB,
+  KEYDB_SEARCH_MODE_MAILEND,
+  KEYDB_SEARCH_MODE_WORDS,
+  KEYDB_SEARCH_MODE_SHORT_KID,
+  KEYDB_SEARCH_MODE_LONG_KID,
+  KEYDB_SEARCH_MODE_FPR16,
+  KEYDB_SEARCH_MODE_FPR20,
+  KEYDB_SEARCH_MODE_FPR,
+  KEYDB_SEARCH_MODE_ISSUER,
+  KEYDB_SEARCH_MODE_ISSUER_SN,
+  KEYDB_SEARCH_MODE_FIRST,
+  KEYDB_SEARCH_MODE_NEXT
+} KeydbSearchMode;
+
+struct keydb_search_desc {
+  KeydbSearchMode mode;
+  int (*skipfnc)(void *,void*); /* used to be: void*, u32* */
+  void *skipfncvalue;
+  const unsigned char *sn; /* used only with _MODE_ISSUER_SN */
+  union {
+    const char *name;
+    char fpr[24];
+    /*fixme: u32  kid[2];*/
+  } u;
+};
+
+
+struct keydb_search_desc;
+typedef struct keydb_search_desc KEYDB_SEARCH_DESC;
+
+typedef struct keydb_search_desc KEYBOX_SEARCH_DESC;
+
+
+
+#endif /*KEYBOX_SEARCH_DESC_H*/
index d2c61ff..3468a8e 100644 (file)
 
 #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;
+}
 
-/****************
- * 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 )
+static ulong
+get16 (const byte *buffer)
+{
+  ulong a;
+  a =  *buffer << 8;
+  a |= buffer[1];
+  return a;
+}
+
+
+
+static int
+blob_get_type (KEYBOXBLOB blob)
+{
+  const unsigned char *buffer;
+  size_t length;
+
+  buffer = _keybox_get_blob_image (blob, &length);
+  if (length < 40)
+    return -1; /* blob too short */
+
+  return buffer[4];
+}
+
+
+static int
+blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn)
+{
+  size_t snlen;
+  const unsigned char *buffer;
+  size_t length;
+  size_t pos, off;
+  size_t nkeys, keyinfolen;
+  size_t nserial;
+
+  snlen = (sn[0] << 24) | (sn[1] << 16) | (sn[2] << 8) | sn[3];
+  sn += 4;
+
+  buffer = _keybox_get_blob_image (blob, &length);
+  if (length < 40)
+    return 0; /* blob too short */
+
+  /*keys*/
+  nkeys = get16 (buffer + 16);
+  keyinfolen = get16 (buffer + 18 );
+  if (keyinfolen < 28)
+    return 0; /* invalid blob */
+  pos = 20 + keyinfolen*nkeys;
+  if (pos+2 > length)
+    return 0; /* out of bounds */
+
+  /*serial*/
+  nserial = get16 (buffer+pos); 
+  off = pos + 2;
+  if (off+nserial > length)
+    return 0; /* out of bounds */
+
+  return nserial == snlen && !memcmp (buffer+off, sn, snlen);
+}
+
+static int
+blob_cmp_name (KEYBOXBLOB blob, int idx, const char *name, size_t namelen)
 {
-    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 */
+  const unsigned char *buffer;
+  size_t length;
+  size_t pos, off, len;
+  size_t nkeys, keyinfolen;
+  size_t nuids, uidinfolen;
+  size_t nserial;
+
+  buffer = _keybox_get_blob_image (blob, &length);
+  if (length < 40)
+    return 0; /* blob too short */
+
+  /*keys*/
+  nkeys = get16 (buffer + 16);
+  keyinfolen = get16 (buffer + 18 );
+  if (keyinfolen < 28)
+    return 0; /* invalid blob */
+  pos = 20 + keyinfolen*nkeys;
+  if (pos+2 > length)
+    return 0; /* out of bounds */
+
+  /*serial*/
+  nserial = get16 (buffer+pos); 
+  pos += 2 + nserial;
+  if (pos+4 > length)
+    return 0; /* out of bounds */
+
+  /* user ids*/
+  nuids = get16 (buffer + pos);  pos += 2;
+  uidinfolen = get16 (buffer + pos);  pos += 2;
+  if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
+    return 0; /* invalid blob */
+  if (pos + uidinfolen*nuids > length)
+    return 0; /* out of bounds */
+
+  if (idx > nuids)
+    return 0; /* no user ID with that idx */
+  pos += idx*uidinfolen;
+  off = get32 (buffer+pos);
+  len = get32 (buffer+pos+4);
+  if (off+len > length)
+    return 0; /* out of bounds */
+  if (len < 2)
+    return 0; /* empty name or 0 not stored */
+  len--;
+  
+  return len == namelen && !memcmp (buffer+off, name, len);
+}
+
+
+
+\f
+/*
+  The has_foo functions are used as helpers for search 
+*/
+#if 0
+static int
+has_short_kid (KEYBOXBLOB blob, u32 kid)
+{
+  return 0;
+}
+
+static int
+has_long_kid (KEYBOXBLOB blob, u32 *kid)
+{
+  return 0;
+}
+#endif
+
+static int
+has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
+{
+  return 0;
+}
+
+
+static int
+has_issuer (KEYBOXBLOB blob, const char *name)
+{
+  size_t namelen;
+
+  return_val_if_fail (name, 0);
+
+  if (blob_get_type (blob) != BLOBTYPE_X509)
+    return 0;
+
+  namelen = strlen (name);
+  return blob_cmp_name (blob, 0 /* issuer */, name, namelen);
+}
+
+static int
+has_issuer_sn (KEYBOXBLOB blob, const char *name, const unsigned char *sn)
+{
+  size_t namelen;
+
+  return_val_if_fail (name, 0);
+  return_val_if_fail (sn, 0);
+
+  if (blob_get_type (blob) != BLOBTYPE_X509)
+    return 0;
+
+  namelen = strlen (name);
+  
+  return (blob_cmp_sn (blob, sn)
+          && blob_cmp_name (blob, 0 /* issuer */, name, namelen));
+}
+
+
+\f
+/*
+
+  The search API
+
+*/
+
+int 
+keybox_search_reset (KEYBOX_HANDLE hd)
+{
+  if (!hd)
+    return KEYBOX_Invalid_Value;
+
+  if (hd->found.blob)
+    {
+      _keybox_release_blob (hd->found.blob);
+      hd->found.blob = NULL;
+    }
+
+  if (hd->fp)
+    {
+      fclose (hd->fp);
+      hd->fp = NULL;
     }
-    return -1;
+  hd->error = 0;
+  hd->eof = 0;
+  return 0;   
 }
 
-/****************
- * 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 )
+int 
+keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc)
 {
-    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 */
+  int rc;
+  size_t n;
+  int need_words, any_skip;
+  KEYBOXBLOB blob = NULL;
+
+  if (!hd)
+    return KEYBOX_Invalid_Value;
+
+  /* clear last found result */
+  if (hd->found.blob)
+    {
+      _keybox_release_blob (hd->found.blob);
+      hd->found.blob = NULL;
+    }
+
+  if (hd->error)  
+    return hd->error; /* still in error state */
+  if (hd->eof)  
+    return -1; /* still EOF */
+
+  /* figure out what information we need */
+  need_words = any_skip = 0;
+  for (n=0; n < ndesc; n++) 
+    {
+      switch (desc[n].mode) 
+        {
+        case KEYDB_SEARCH_MODE_WORDS: 
+          need_words = 1;
+          break;
+        case KEYDB_SEARCH_MODE_FIRST:
+          /* always restart the search in this mode */
+          keybox_search_reset (hd);
+          break;
+        default:
+          break;
+       }
+      if (desc[n].skipfnc) 
+        any_skip = 1;
+    }
+
+  if (!hd->fp)
+    {
+      hd->fp = fopen (hd->kb->fname, "rb");
+      if (!hd->fp)
+          return (hd->error = KEYBOX_File_Open_Error);
+    }
+
+
+  for (;;)
+    {
+      _keybox_release_blob (blob); blob = NULL;
+      rc = _keybox_read_blob (&blob, hd->fp);
+      if (rc)
+        break;
+
+      for (n=0; n < ndesc; n++) 
+        {
+          switch (desc[n].mode)
+            {
+            case KEYDB_SEARCH_MODE_NONE: 
+              never_reached ();
+              break;
+            case KEYDB_SEARCH_MODE_EXACT: 
+            case KEYDB_SEARCH_MODE_SUBSTR:
+            case KEYDB_SEARCH_MODE_MAIL:
+            case KEYDB_SEARCH_MODE_MAILSUB:
+            case KEYDB_SEARCH_MODE_MAILEND:
+            case KEYDB_SEARCH_MODE_WORDS: 
+              never_reached (); /* not yet implemented */
+              break;
+            case KEYDB_SEARCH_MODE_ISSUER:
+              if (has_issuer (blob, desc[n].u.name))
+                goto found;
+              break;
+            case KEYDB_SEARCH_MODE_ISSUER_SN:
+              if (has_issuer_sn (blob, desc[n].u.name, desc[n].sn))
+                goto found;
+              break;
+            case KEYDB_SEARCH_MODE_SHORT_KID: 
+/*                if (has_short_kid (blob, desc[n].u.kid[1])) */
+/*                  goto found; */
+              break;
+            case KEYDB_SEARCH_MODE_LONG_KID:
+/*                if (has_long_kid (blob, desc[n].u.kid)) */
+/*                  goto found; */
+              break;
+            case KEYDB_SEARCH_MODE_FPR:
+              if (has_fingerprint (blob, desc[n].u.fpr))
+                goto found;
+              break;
+            case KEYDB_SEARCH_MODE_FIRST: 
+              goto found;
+              break;
+            case KEYDB_SEARCH_MODE_NEXT: 
+              goto found;
+              break;
+            default: 
+              rc = KEYBOX_Invalid_Value;
+              goto found;
+            }
+       }
+      continue;
+    found:  
+      for (n=any_skip?0:ndesc; n < ndesc; n++) 
+        {
+/*            if (desc[n].skipfnc */
+/*                && desc[n].skipfnc (desc[n].skipfncvalue, aki)) */
+/*              break; */
+        }
+      if (n == ndesc)
+        break; /* got it */
+    }
+  
+  if (!rc)
+    {
+      hd->found.blob = blob;
+    }
+  else if (rc == -1)
+    {
+      _keybox_release_blob (blob);
+      hd->eof = 1;
+    }
+  else 
+    {
+      _keybox_release_blob (blob);
+      hd->error = rc;
     }
-    return -1;
+
+  return rc;
 }
 
 
 
+\f
+/*
+   Functions to return a certificate or a keyblock.  To be used after
+   a successful search operation.
+*/
+#ifdef KEYBOX_WITH_X509
+/*
+  Return the last found cert.  Caller must free it.
+ */
 int
-keybox_blob_has_uid ( KEYBOXBLOB blob,
-                  int (*cmp)(const byte *, size_t, void *), void *opaque )
+keybox_get_cert (KEYBOX_HANDLE hd, KsbaCert *r_cert)
 {
-    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 */
+  const unsigned char *buffer;
+  size_t length;
+  size_t cert_off, cert_len;
+  KsbaReader reader = NULL;
+  KsbaCert cert = NULL;
+  int rc;
+
+  if (!hd)
+    return KEYBOX_Invalid_Value;
+  if (!hd->found.blob)
+    return KEYBOX_Nothing_Found;
+
+  if (blob_get_type (hd->found.blob) != BLOBTYPE_X509)
+    return KEYBOX_Wrong_Blob_Type;
+
+  buffer = _keybox_get_blob_image (hd->found.blob, &length);
+  if (length < 40)
+    return KEYBOX_Blob_Too_Short;
+  cert_off = get32 (buffer+8);
+  cert_len = get32 (buffer+12);
+  if (cert_off+cert_len > length)
+    return KEYBOX_Blob_Too_Short;
+
+  reader = ksba_reader_new ();
+  if (!reader)
+    return KEYBOX_Out_Of_Core;
+  rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
+  if (rc)
+    {
+      ksba_reader_release (reader);
+      /* fixme: need to map the error codes */
+      return KEYBOX_General_Error;
     }
 
-    return -1;
-}
+  cert = ksba_cert_new ();
+  if (!cert)
+    {
+      ksba_reader_release (reader);
+      return KEYBOX_Out_Of_Core;
+    }
 
+  rc = ksba_cert_read_der (cert, reader);
+  if (rc)
+    {
+      ksba_cert_release (cert);
+      ksba_reader_release (reader);
+      /* fixme: need to map the error codes */
+      return KEYBOX_General_Error;
+    }
+
+  *r_cert = cert;
+  ksba_reader_release (reader);
+  return 0;
+}
 
+#endif /*KEYBOX_WITH_X509*/
diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c
new file mode 100644 (file)
index 0000000..d49c3d0
--- /dev/null
@@ -0,0 +1,390 @@
+/* keybox-update.c - keybox update 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 <errno.h>
+#include <unistd.h>
+
+#include "keybox-defs.h"
+
+#define EXTSEP_S "."
+
+
+static int
+create_tmp_file (const char *template,
+                 char **r_bakfname, char **r_tmpfname, FILE **r_fp)
+{  
+  char *bakfname, *tmpfname;
+  
+  *r_bakfname = NULL;
+  *r_tmpfname = NULL;
+  
+# ifdef USE_ONLY_8DOT3
+  /* Here is another Windoze bug?:
+   * you cant rename("pubring.kbx.tmp", "pubring.kbx");
+   * but       rename("pubring.kbx.tmp", "pubring.aaa");
+   * works.  So we replace .kbx by .bak or .tmp
+   */
+  if (strlen (template) > 4
+      && !strcmp (template+strlen(template)-4, EXTSEP_S "kbx") )
+    {
+      bakfname = xtrymalloc (strlen (template) + 1);
+      if (!bakfname)
+        return KEYBOX_Out_Of_Core;
+      strcpy (bakfname, template);
+      strcpy (bakfname+strlen(template)-4, EXTSEP_S "bak");
+      
+      tmpfname = xtrymalloc (strlen (template) + 1);
+      if (!tmpfname)
+        {
+          xfree (bakfname);
+          return KEYBOX_Out_Of_Core;
+        }
+      strcpy (tmpfname,template);
+      strcpy (tmpfname + strlen (template)-4, EXTSEP_S "tmp");
+    }
+  else 
+    { /* file does not end with kbx; hmmm */
+      bakfname = xtrymalloc ( strlen (template) + 5);
+      if (!bakfname)
+        return KEYBOX_Out_Of_Core;
+      strcpy (stpcpy (bakfname, template), EXTSEP_S "bak");
+      
+      tmpfname = xtrymalloc ( strlen (template) + 5);
+      if (!tmpfname)
+        {
+          xfree (bakfname);
+          return KEYBOX_Out_Of_Core;
+        }
+      strcpy (stpcpy (tmpfname, template), EXTSEP_S "tmp");
+    }
+# else /* Posix file names */
+  bakfname = xtrymalloc (strlen (template) + 2);
+  if (!bakfname)
+    return KEYBOX_Out_Of_Core;
+  strcpy (stpcpy (bakfname,template),"~");
+  
+  tmpfname = xtrymalloc ( strlen (template) + 5);
+  if (!tmpfname)
+    {
+      xfree (bakfname);
+      return KEYBOX_Out_Of_Core;
+    }
+  strcpy (stpcpy (tmpfname,template), EXTSEP_S "tmp");
+# endif /* Posix filename */
+
+  *r_fp = fopen (tmpfname, "wb");
+  if (!*r_fp)
+    {
+      xfree (tmpfname);
+      xfree (bakfname);
+      return KEYBOX_File_Create_Error;
+    }
+  
+  *r_bakfname = bakfname;
+  *r_tmpfname = tmpfname;
+  return 0;
+}
+
+
+static int
+rename_tmp_file (const char *bakfname, const char *tmpfname,
+                 const char *fname, int secret )
+{
+  int rc=0;
+
+  /* restrict the permissions for secret keyboxs */
+#ifndef HAVE_DOSISH_SYSTEM
+/*    if (secret && !opt.preserve_permissions) */
+/*      { */
+/*        if (chmod (tmpfname, S_IRUSR | S_IWUSR) )  */
+/*          { */
+/*            log_debug ("chmod of `%s' failed: %s\n", */
+/*                       tmpfname, strerror(errno) ); */
+/*            return KEYBOX_Write_File; */
+/*     } */
+/*      } */
+#endif
+
+  /* fixme: invalidate close caches (not used with stdio)*/
+/*    iobuf_ioctl (NULL, 2, 0, (char*)tmpfname ); */
+/*    iobuf_ioctl (NULL, 2, 0, (char*)bakfname ); */
+/*    iobuf_ioctl (NULL, 2, 0, (char*)fname ); */
+
+  /* first make a backup file except for secret keyboxs */
+  if (!secret)
+    { 
+#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
+      remove (bakfname);
+#endif
+      if (rename (fname, bakfname) )
+        {
+          return KEYBOX_File_Error;
+       }
+    }
+  
+  /* then rename the file */
+#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
+  remove (fname);
+#endif
+  if (rename (tmpfname, fname) )
+    {
+      rc = KEYBOX_File_Error;
+      if (secret)
+        {
+/*            log_info ("WARNING: 2 files with confidential" */
+/*                       " information exists.\n"); */
+/*            log_info ("%s is the unchanged one\n", fname ); */
+/*            log_info ("%s is the new one\n", tmpfname ); */
+/*            log_info ("Please fix this possible security flaw\n"); */
+       }
+      return rc;
+    }
+  
+  return 0;
+}
+
+
+
+/* Perform insert/delete/update operation.
+    mode 1 = insert
+        2 = delete
+        3 = update
+*/
+static int
+blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob, 
+               int secret, off_t start_offset, unsigned int n_packets )
+{
+  FILE *fp, *newfp;
+  int rc=0;
+  char *bakfname = NULL;
+  char *tmpfname = NULL;
+  char buffer[4096];
+  int nread, nbytes;
+
+  /* Open the source file. Because we do a rename, we have to check the 
+     permissions of the file */
+  if (access (fname, W_OK))
+    return KEYBOX_Write_Error;
+
+  fp = fopen (fname, "rb");
+  if (mode == 1 && !fp && errno == ENOENT)
+    { /* insert mode but file does not exist: create a new keybox file */
+      newfp = fopen (fname, "wb");
+      if (!newfp )
+        {
+          return KEYBOX_File_Create_Error;
+       }
+
+      rc = _keybox_write_blob (blob, newfp);
+      if (rc)
+        {
+          return rc;
+        }
+      if ( fclose (newfp) )
+        {
+          return KEYBOX_File_Create_Error;
+       }
+
+/*        if (chmod( fname, S_IRUSR | S_IWUSR )) */
+/*          { */
+/*            log_debug ("%s: chmod failed: %s\n", fname, strerror(errno) ); */
+/*            return KEYBOX_File_Error; */
+/*          } */
+      return 0; /* ready */
+    }
+
+  if (!fp)
+    {
+      rc = KEYBOX_File_Open_Error;
+      goto leave;
+    }
+
+  /* create the new file */
+  rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
+  if (rc)
+    {
+      fclose(fp);
+      goto leave;
+    }
+  
+  /* prepare for insert */
+  if (mode == 1)
+    { 
+      /* copy everything to the new file */
+      while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
+        {
+          if (fwrite (buffer, nread, 1, newfp) != 1)
+            {
+              rc = KEYBOX_Write_Error;
+              goto leave;
+            }
+        }
+      if (ferror (fp))
+        {
+          rc = KEYBOX_Read_Error;
+          goto leave;
+        }
+    }
+  
+  /* prepare for delete or update */
+  if ( mode == 2 || mode == 3 ) 
+    { 
+      off_t current = 0;
+      
+      /* copy first part to the new file */
+      while ( current < start_offset )
+        {
+          nbytes = DIM(buffer);
+          if (current + nbytes > start_offset)
+              nbytes = start_offset - current;
+          nread = fread (buffer, 1, nbytes, fp);
+          if (!fread)
+            break;
+          current += nread;
+          
+          if (fwrite (buffer, nread, 1, newfp) != 1)
+            {
+              rc = KEYBOX_Write_Error;
+              goto leave;
+            }
+        }
+      if (ferror (fp))
+        {
+            rc = KEYBOX_Read_Error;
+            goto leave;
+        }
+      
+      /* skip this blob */
+      rc = _keybox_read_blob (NULL, fp);
+      if (rc)
+        return rc;
+    }
+  
+  /* Do an insert or update */
+  if ( mode == 1 || mode == 3 )
+    { 
+      rc = _keybox_write_blob (blob, newfp);
+      if (rc)
+          return rc;
+    }
+  
+  /* copy the rest of the packet for an delete or update */
+  if (mode == 2 || mode == 3)
+    { 
+      while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
+        {
+          if (fwrite (buffer, nread, 1, newfp) != 1)
+            {
+              rc = KEYBOX_Write_Error;
+              goto leave;
+            }
+        }
+      if (ferror (fp))
+        {
+          rc = KEYBOX_Read_Error;
+          goto leave;
+        }
+    }
+    
+  /* close both files */
+  if (fclose(fp))
+    {
+      rc = KEYBOX_File_Close_Error;
+      fclose (newfp);
+      goto leave;
+    }
+  if (fclose(newfp))
+    {
+      rc = KEYBOX_File_Close_Error;
+      goto leave;
+    }
+
+  rc = rename_tmp_file (bakfname, tmpfname, fname, secret);
+
+ leave:
+  xfree(bakfname);
+  xfree(tmpfname);
+  return rc;
+}
+
+
+
+
+#ifdef KEYBOX_WITH_X509 
+int
+keybox_insert_cert (KEYBOX_HANDLE hd, KsbaCert cert,
+                    unsigned char *sha1_digest)
+{
+  int rc;
+  const char *fname;
+  KEYBOXBLOB blob;
+
+  if (!hd)
+    return KEYBOX_Invalid_Handle; 
+  if (!hd->kb)
+    return KEYBOX_Invalid_Handle; 
+  fname = hd->kb->fname;
+  if (!fname)
+    return KEYBOX_Invalid_Handle; 
+
+  /* close this one otherwise we will mess up the position for a next
+     search.  Fixme: it would be better to adjust the position after
+     the write opertions.  */
+  if (hd->fp)
+    {
+      fclose (hd->fp);
+      hd->fp = NULL;
+    }
+
+  rc = _keybox_create_x509_blob (&blob, cert, sha1_digest);
+  if (!rc)
+    {
+      rc = blob_filecopy (1, fname, blob, hd->secret, 0, 0 );
+      _keybox_release_blob (blob);
+      /*    if (!rc && !hd->secret && kb_offtbl) */
+      /*      { */
+      /*        update_offset_hash_table_from_kb (kb_offtbl, kb, 0); */
+      /*      } */
+    }
+  return rc;
+}
+
+int
+keybox_update_cert (KEYBOX_HANDLE hd, KsbaCert cert,
+                    unsigned char *sha1_digest)
+{
+  return -1;
+}
+
+
+#endif /*KEYBOX_WITH_X509*/
+
+
+int
+keybox_delete (KEYBOX_HANDLE hd)
+{
+  return -1;
+}
+
+
index 9008823..645f1e7 100644 (file)
@@ -27,6 +27,8 @@ extern "C" {
 #endif
 #endif
 
+#include "keybox-search-desc.h"
+
 #define KEYBOX_WITH_OPENPGP 1 
 #define KEYBOX_WITH_X509 1
 
@@ -51,8 +53,13 @@ typedef enum {
   KEYBOX_Write_Error = 6,
   KEYBOX_File_Error = 7,
   KEYBOX_Blob_Too_Short = 8,
-  KEYBOX_Blob_Too_Large = 9
-
+  KEYBOX_Blob_Too_Large = 9,
+  KEYBOX_Invalid_Handle = 10,
+  KEYBOX_File_Create_Error = 11,
+  KEYBOX_File_Open_Error = 12,
+  KEYBOX_File_Close_Error = 13,
+  KEYBOX_Nothing_Found = 14,
+  KEYBOX_Wrong_Blob_Type = 15,
 } KeyboxError;
 
 
@@ -60,24 +67,41 @@ typedef enum {
 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);
+
+
+/*-- keybox-search.c --*/
+#ifdef KEYBOX_WITH_X509 
+int keybox_get_cert (KEYBOX_HANDLE hd, KsbaCert *ret_cert);
+#endif /*KEYBOX_WITH_X509*/
+
+int keybox_search_reset (KEYBOX_HANDLE hd);
+int keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc);
+
+
+/*-- keybox-update.c --*/
+#ifdef KEYBOX_WITH_X509 
+int keybox_insert_cert (KEYBOX_HANDLE hd, KsbaCert cert,
+                        unsigned char *sha1_digest);
+int keybox_update_cert (KEYBOX_HANDLE hd, KsbaCert cert,
+                        unsigned char *sha1_digest);
+#endif /*KEYBOX_WITH_X509*/
+
+int keybox_delete (KEYBOX_HANDLE hd);
+
+
+/*--  --*/
+
 #if 0
+int keybox_lock (KEYBOX_HANDLE hd, int yes);
 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 *);
index ec2c1b2..ab34f10 100644 (file)
@@ -28,10 +28,15 @@ BUILT_SOURCES = errors.c
 gpgsm_SOURCES = \
        gpgsm.c gpgsm.h \
        util.h misc.c errors.c \
+       keydb.c keydb.h \
        server.c \
+       fingerprint.c \
+       certdump.c \
+       certcheck.c \
+       certpath.c \
        import.c 
 
-gpgsm_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a \
+gpgsm_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a ../kbx/libkeybox.a \
               ../../libksba/src/.libs/libksba.a \
               ../../libgcrypt/src/.libs/libgcrypt.so.1
 
diff --git a/sm/certchain.c b/sm/certchain.c
new file mode 100644 (file)
index 0000000..aef1612
--- /dev/null
@@ -0,0 +1,131 @@
+/* certpath.c - path validation
+ *     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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h> 
+#include <time.h>
+#include <assert.h>
+
+#include <gcrypt.h>
+#include <ksba.h>
+
+#include "gpgsm.h"
+#include "keydb.h"
+#include "i18n.h"
+
+int
+gpgsm_validate_path (KsbaCert cert)
+{
+  int rc = 0, depth = 0;
+  char *issuer = NULL;
+  char *subject = NULL;
+  KEYDB_HANDLE kh = keydb_new (0);
+  KsbaCert subject_cert = NULL, issuer_cert = NULL;
+
+  if (!kh)
+    {
+      log_error (_("failed to allocated keyDB handle\n"));
+      rc = GPGSM_General_Error;
+      goto leave;
+    }
+
+  log_debug ("validate path for certificate:\n");
+  gpgsm_dump_cert (cert);
+
+  subject_cert = cert;
+
+  for (;;)
+    {
+      xfree (issuer);
+      xfree (subject);
+      issuer = ksba_cert_get_issuer (subject_cert);
+      subject = ksba_cert_get_subject (subject_cert);
+
+      if (!issuer)
+        {
+          if (DBG_X509)
+            log_debug ("ERROR: issuer missing\n");
+          rc = GPGSM_Bad_Certificate;
+          goto leave;
+        }
+
+      if (subject && !strcmp (issuer, subject))
+        {
+          if (gpgsm_check_cert_sig (subject_cert, subject_cert) )
+            {
+              log_debug ("selfsigned certificate has a BAD signatures\n");
+              rc = depth? GPGSM_Bad_Certificate_Path : GPGSM_Bad_Certificate;
+              goto leave;
+            }
+          log_debug ("selfsigned certificate is good\n");
+          break;  /* okay, a self-signed certicate is an end-point */
+        }
+      
+      depth++;
+      /* fixme: check against a maximum path length */
+
+      /* find the next cert up the tree */
+      keydb_search_reset (kh);
+      rc = keydb_search_issuer (kh, issuer);
+      if (rc)
+        {
+          log_debug ("failed to find issuer's certificate: rc=%d\n", rc);
+          rc = GPGSM_Missing_Certificate;
+          goto leave;
+        }
+
+      ksba_cert_release (issuer_cert); issuer_cert = NULL;
+      rc = keydb_get_cert (kh, &issuer_cert);
+      if (rc)
+        {
+          log_debug ("failed to get cert: rc=%d\n", rc);
+          rc = GPGSM_General_Error;
+          goto leave;
+        }
+
+      log_debug ("got issuer's certificate:\n");
+      gpgsm_dump_cert (issuer_cert);
+
+      if (gpgsm_check_cert_sig (issuer_cert, subject_cert) )
+        {
+          log_debug ("certificate has a BAD signatures\n");
+          rc = GPGSM_Bad_Certificate_Path;
+          goto leave;
+        }
+      log_debug ("certificate is good\n");
+      
+      keydb_search_reset (kh);
+      subject_cert = issuer_cert;
+      issuer_cert = NULL;
+    }
+  
+ leave:
+  xfree (issuer);
+  keydb_release (kh); 
+  ksba_cert_release (issuer_cert);
+  if (subject_cert != cert)
+    ksba_cert_release (subject_cert);
+  return rc;
+}
+
diff --git a/sm/certcheck.c b/sm/certcheck.c
new file mode 100644 (file)
index 0000000..a86aa2d
--- /dev/null
@@ -0,0 +1,156 @@
+/* certcheck.c - check one certificate
+ *     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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h> 
+#include <time.h>
+#include <assert.h>
+
+#include <gcrypt.h>
+#include <ksba.h>
+
+#include "gpgsm.h"
+#include "keydb.h"
+#include "i18n.h"
+
+static int
+do_encode_md (GCRY_MD_HD md, int algo, size_t len, unsigned nbits,
+             const byte *asn, size_t asnlen, GCRY_MPI *r_val)
+{
+  int nframe = (nbits+7) / 8;
+  byte *frame;
+  int i, n;
+  
+  if ( len + asnlen + 4  > nframe )
+    {
+      log_error ("can't encode a %d bit MD into a %d bits frame\n",
+                 (int)(len*8), (int)nbits);
+      return GPGSM_Internal_Error;
+    }
+  
+  /* We encode the MD in this way:
+   *
+   *      0  A PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
+   *
+   * PAD consists of FF bytes.
+   */
+  frame = xtrymalloc (nframe);
+  if (!frame)
+    return GPGSM_Out_Of_Core;
+  n = 0;
+  frame[n++] = 0;
+  frame[n++] = 1; /* block type */
+  i = nframe - len - asnlen -3 ;
+  assert ( i > 1 );
+  memset ( frame+n, 0xff, i ); n += i;
+  frame[n++] = 0;
+  memcpy ( frame+n, asn, asnlen ); n += asnlen;
+  memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len;
+  assert ( n == nframe );
+  gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, &nframe);
+  xfree (frame);
+  return 0;
+}
+
+
+/*
+  Check the signature on CERT using the ISSUER-CERT.  This function
+  does only test the cryptographic signature and nothing else.  It is
+  assumed that the ISSUER_CERT is valid. */
+int
+gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert)
+{
+  /* OID for MD5 as defined in PKCS#1 (rfc2313) */
+  static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 (md5) */
+  { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
+    0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
+  };
+
+  GCRY_MD_HD md;
+  int rc, algo;
+  GCRY_MPI frame;
+  char *p;
+  GCRY_SEXP s_sig, s_hash, s_pkey;
+
+  algo = ksba_cert_get_digest_algo (cert);
+  md = gcry_md_open (algo, 0);
+  if (!md)
+    {
+      log_error ("md_open failed: %s\n", gcry_strerror (-1));
+      return GPGSM_General_Error;
+    }
+
+  rc = ksba_cert_hash (cert, 1, HASH_FNC, md);
+  if (rc)
+    {
+      log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc));
+      gcry_md_close (md);
+      return map_ksba_err (rc);
+    }
+  gcry_md_final (md);
+
+  p = ksba_cert_get_sig_val (cert); /* fixme: check p*/
+  if (DBG_X509)
+    log_debug ("signature: %s\n", p);
+
+  rc = gcry_sexp_sscan ( &s_sig, NULL, p, strlen(p));
+  if (rc)
+    {
+      log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc));
+      return map_gcry_err (rc);
+    }
+  /*gcry_sexp_dump (s_sig);*/
+
+
+  /* FIXME: need to map the algo to the ASN OID - we assume a fixed
+     one for now */
+  rc = do_encode_md (md, algo, 16, 2048, asn, DIM(asn), &frame);
+  if (rc)
+    {
+      /* fixme: clean up some things */
+      return rc;
+    }
+  /* put hash into the S-Exp s_hash */
+  if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
+    BUG ();
+  /*fputs ("hash:\n", stderr); gcry_sexp_dump (s_hash);*/
+
+  p = ksba_cert_get_public_key (issuer_cert);
+  if (DBG_X509)
+    log_debug ("issuer public key: %s\n", p);
+
+  rc = gcry_sexp_sscan ( &s_pkey, NULL, p, strlen(p));
+  if (rc)
+    {
+      log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc));
+      return map_gcry_err (rc);
+    }
+  /*gcry_sexp_dump (s_pkey);*/
+  
+  rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
+  if (DBG_CRYPTO)
+      log_debug ("gcry_pk_verify: %s\n", gcry_strerror (rc));
+  return map_gcry_err (rc);
+}
+
diff --git a/sm/certdump.c b/sm/certdump.c
new file mode 100644 (file)
index 0000000..5dfce2a
--- /dev/null
@@ -0,0 +1,131 @@
+/* certdump.c - Dump a certificate for debugging
+ *     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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h> 
+#include <time.h>
+#include <assert.h>
+
+#include <gcrypt.h>
+#include <ksba.h>
+
+#include "gpgsm.h"
+#include "keydb.h"
+
+static void
+print_integer (unsigned char *p)
+{
+  unsigned long len;
+
+  if (!p)
+    fputs ("none", stdout);
+  else
+    {
+      len = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+      for (p+=4; len; len--, p++)
+        printf ("%02X", *p);
+    }
+}
+
+static void
+print_time (time_t t)
+{
+
+  if (!t)
+    fputs ("none", stdout);
+  else if ( t == (time_t)(-1) )
+    fputs ("error", stdout);
+  else
+    {
+      struct tm *tp;
+
+      tp = gmtime (&t);
+      printf ("%04d-%02d-%02d %02d:%02d:%02d",
+              1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
+              tp->tm_hour, tp->tm_min, tp->tm_sec);
+      assert (!tp->tm_isdst);
+    }
+}
+
+static void
+print_dn (char *p)
+{
+
+  if (!p)
+    fputs ("error", stdout);
+  else
+    printf ("`%s'", p);
+}
+
+
+void 
+gpgsm_dump_cert (KsbaCert cert)
+{
+  unsigned char *p;
+  char *dn;
+  time_t t;
+
+  if (!cert)
+    {
+      fputs ("[no certificate]\n", stdout);
+      return;
+    }
+    
+  p = ksba_cert_get_serial (cert);
+  fputs ("serial: ", stdout);
+  print_integer (p);
+  ksba_free (p);
+  putchar ('\n');
+
+  t = ksba_cert_get_validity (cert, 0);
+  fputs ("notBefore: ", stdout);
+  print_time (t);
+  putchar ('\n');
+  t = ksba_cert_get_validity (cert, 1);
+  fputs ("notAfter: ", stdout);
+  print_time (t);
+  putchar ('\n');
+    
+  dn = ksba_cert_get_issuer (cert);
+  fputs ("issuer: ", stdout);
+  print_dn (dn);
+  ksba_free (dn);
+  putchar ('\n');
+    
+  dn = ksba_cert_get_subject (cert);
+  fputs ("subject: ", stdout);
+  print_dn (dn);
+  ksba_free (dn);
+  putchar ('\n');
+
+  printf ("hash algo: %d\n", ksba_cert_get_digest_algo (cert));
+
+  p = gpgsm_get_fingerprint_string (cert, 0);
+  printf ("SHA1 Fingerprint=%s\n", p);
+  xfree (p);
+}
+
+
+
+
diff --git a/sm/certpath.c b/sm/certpath.c
new file mode 100644 (file)
index 0000000..aef1612
--- /dev/null
@@ -0,0 +1,131 @@
+/* certpath.c - path validation
+ *     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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h> 
+#include <time.h>
+#include <assert.h>
+
+#include <gcrypt.h>
+#include <ksba.h>
+
+#include "gpgsm.h"
+#include "keydb.h"
+#include "i18n.h"
+
+int
+gpgsm_validate_path (KsbaCert cert)
+{
+  int rc = 0, depth = 0;
+  char *issuer = NULL;
+  char *subject = NULL;
+  KEYDB_HANDLE kh = keydb_new (0);
+  KsbaCert subject_cert = NULL, issuer_cert = NULL;
+
+  if (!kh)
+    {
+      log_error (_("failed to allocated keyDB handle\n"));
+      rc = GPGSM_General_Error;
+      goto leave;
+    }
+
+  log_debug ("validate path for certificate:\n");
+  gpgsm_dump_cert (cert);
+
+  subject_cert = cert;
+
+  for (;;)
+    {
+      xfree (issuer);
+      xfree (subject);
+      issuer = ksba_cert_get_issuer (subject_cert);
+      subject = ksba_cert_get_subject (subject_cert);
+
+      if (!issuer)
+        {
+          if (DBG_X509)
+            log_debug ("ERROR: issuer missing\n");
+          rc = GPGSM_Bad_Certificate;
+          goto leave;
+        }
+
+      if (subject && !strcmp (issuer, subject))
+        {
+          if (gpgsm_check_cert_sig (subject_cert, subject_cert) )
+            {
+              log_debug ("selfsigned certificate has a BAD signatures\n");
+              rc = depth? GPGSM_Bad_Certificate_Path : GPGSM_Bad_Certificate;
+              goto leave;
+            }
+          log_debug ("selfsigned certificate is good\n");
+          break;  /* okay, a self-signed certicate is an end-point */
+        }
+      
+      depth++;
+      /* fixme: check against a maximum path length */
+
+      /* find the next cert up the tree */
+      keydb_search_reset (kh);
+      rc = keydb_search_issuer (kh, issuer);
+      if (rc)
+        {
+          log_debug ("failed to find issuer's certificate: rc=%d\n", rc);
+          rc = GPGSM_Missing_Certificate;
+          goto leave;
+        }
+
+      ksba_cert_release (issuer_cert); issuer_cert = NULL;
+      rc = keydb_get_cert (kh, &issuer_cert);
+      if (rc)
+        {
+          log_debug ("failed to get cert: rc=%d\n", rc);
+          rc = GPGSM_General_Error;
+          goto leave;
+        }
+
+      log_debug ("got issuer's certificate:\n");
+      gpgsm_dump_cert (issuer_cert);
+
+      if (gpgsm_check_cert_sig (issuer_cert, subject_cert) )
+        {
+          log_debug ("certificate has a BAD signatures\n");
+          rc = GPGSM_Bad_Certificate_Path;
+          goto leave;
+        }
+      log_debug ("certificate is good\n");
+      
+      keydb_search_reset (kh);
+      subject_cert = issuer_cert;
+      issuer_cert = NULL;
+    }
+  
+ leave:
+  xfree (issuer);
+  keydb_release (kh); 
+  ksba_cert_release (issuer_cert);
+  if (subject_cert != cert)
+    ksba_cert_release (subject_cert);
+  return rc;
+}
+
diff --git a/sm/fingerprint.c b/sm/fingerprint.c
new file mode 100644 (file)
index 0000000..9453a6e
--- /dev/null
@@ -0,0 +1,104 @@
+/* fingerprint.c - Get the fingerprint
+ *     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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h> 
+#include <time.h>
+#include <assert.h>
+
+#include <gcrypt.h>
+#include <ksba.h>
+
+#include "gpgsm.h"
+
+/* Return the fingerprint of the certificate (we can't put this into
+   libksba becuase we need libgcrypt support).  The caller must
+   provide an array of sufficient length or NULL so that the function
+   allocates the array.  If r_len is not NULL, the length of the
+   digest is return, well, this can also be done by using
+   gcry_md_get_algo_dlen().  If algo is 0, a SHA-1 will be used.
+   
+   If there is a problem , the function does never return NULL but a
+   digest of all 0xff.
+ */
+char *
+gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len)
+{
+  GCRY_MD_HD md;
+  int rc, len;
+  
+  if (!algo)
+    algo = GCRY_MD_SHA1;
+
+  len = gcry_md_get_algo_dlen (algo);
+  assert (len);
+  if (!array)
+    array = xmalloc (len);
+
+  if (r_len)
+    *r_len = len;
+
+  md = gcry_md_open (algo, 0);
+  if (!md)
+    {
+      log_error ("md_open failed: %s\n", gcry_strerror (-1));
+      memset (array, 0xff, len); /* better return an invalid fpr than NULL */
+      return array;
+    }
+
+  rc = ksba_cert_hash (cert, 0, HASH_FNC, md);
+  if (rc)
+    {
+      log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc));
+      gcry_md_close (md);
+      memset (array, 0xff, len); /* better return an invalid fpr than NULL */
+      return array;
+    }
+  gcry_md_final (md);
+  memcpy (array, gcry_md_read(md, algo), len );
+  return array;
+}
+
+
+/* Return an allocated buffer with the formatted fungerprint */
+char *
+gpgsm_get_fingerprint_string (KsbaCert cert, int algo)
+{
+  unsigned char digest[MAX_DIGEST_LEN];
+  char *buf;
+  int len, i;
+
+  if (!algo)
+    algo = GCRY_MD_SHA1;
+
+  len = gcry_md_get_algo_dlen (algo);
+  assert (len <= MAX_DIGEST_LEN );
+  gpgsm_get_fingerprint (cert, algo, digest, NULL);
+  buf = xmalloc (len*3+1);
+  *buf = 0;
+  for (i=0; i < len; i++ )
+    sprintf (buf+strlen(buf), i? ":%02X":"%02X", digest[i]);
+  return buf;
+}
+
index 3ca58d3..39db243 100644 (file)
@@ -29,7 +29,9 @@
 #include <gcrypt.h>
 #include "gpgsm.h"
 #include "../assuan/assuan.h" /* malloc hooks */
+#include "../kbx/keybox.h" /* malloc hooks */
 #include "i18n.h"
+#include "keydb.h"
 
 enum cmd_and_opt_values {
   aNull = 0,
@@ -441,7 +443,7 @@ set_debug(void)
 {
   if (opt.debug & DBG_MPI_VALUE)
     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2);
-  if (opt.debug & DBG_CIPHER_VALUE )
+  if (opt.debug & DBG_CRYPTO_VALUE )
     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
 }
 
@@ -562,8 +564,9 @@ main ( int argc, char **argv)
      Now we are now working under our real uid 
   */
 
+  ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
   assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
-  /*  ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );*/
+  keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
 
   if (default_config )
     configname = make_filename (opt.homedir, "gpgsm.conf", NULL);
@@ -831,12 +834,10 @@ main ( int argc, char **argv)
   if (!cmd && opt.fingerprint && !with_fpr)
     set_cmd (&cmd, aListKeys);
   
-#if 0 /* fixme */
-  if (!nrings && default_keyring)  /* add default ring */
-    add_keyblock_resource ("pubcerts.gpg", 0, 0);
+  if (!nrings && default_keyring)  /* add default keybox */
+    keydb_add_resource ("pubcerts.kbx", 0, 0);
   for (sl = nrings; sl; sl = sl->next)
-    add_keyblock_resource( sl->d, 0, 0 );
-#endif
+    keydb_add_resource (sl->d, 0, 0);
   FREE_STRLIST(nrings);
   
   fname = argc? *argv : NULL;
index 1c66e10..a4361dc 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef GPGSM_H
 #define GPGSM_H
 
+#include <ksba.h>
 #include "util.h"
 
 /* Error numbers */
@@ -31,10 +32,15 @@ enum {
   GPGSM_Out_Of_Core = 2,
   GPGSM_Invalid_Value = 3,
   GPGSM_IO_Error = 4,
-
+  GPGSM_Resource_Limit = 5,
+  GPGSM_Internal_Error = 6,
+  GPGSM_Bad_Certificate = 7,
+  GPGSM_Bad_Certificate_Path = 8,
+  GPGSM_Missing_Certificate = 9,
 
 };
 
+#define MAX_DIGEST_LEN 24 
 
 /* A large struct name "opt" to keep global flags */
 struct {
@@ -77,14 +83,14 @@ struct {
 
 #define DBG_X509_VALUE    1    /* debug x.509 data reading/writing */
 #define DBG_MPI_VALUE    2     /* debug mpi details */
-#define DBG_CIPHER_VALUE  4    /* debug cipher handling */
+#define DBG_CRYPTO_VALUE  4    /* debug low level crypto */
 #define DBG_MEMORY_VALUE  32   /* debug memory allocation stuff */
 #define DBG_CACHE_VALUE   64   /* debug the caching */
 #define DBG_MEMSTAT_VALUE 128  /* show memory statistics */
 #define DBG_HASHING_VALUE 512  /* debug hashing operations */
 
 #define DBG_X509    (opt.debug & DBG_X509_VALUE)
-#define DBG_CIPHER  (opt.debug & DBG_CIPHER_VALUE)
+#define DBG_CRYPTO  (opt.debug & DBG_CRYPTO_VALUE)
 #define DBG_MEMORY  (opt.debug & DBG_MEMORY_VALUE)
 #define DBG_CACHE   (opt.debug & DBG_CACHE_VALUE)
 #define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
@@ -95,8 +101,31 @@ void gpgsm_exit (int rc);
 /*-- server.c --*/
 void gpgsm_server (void);
 
+/*-- fingerprint --*/
+char *gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len);
+char *gpgsm_get_fingerprint_string (KsbaCert cert, int algo);
+
+/*-- certdump.c --*/
+void gpgsm_dump_cert (KsbaCert cert);
+
+/*-- certcheck.c --*/
+int gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert);
+
+
+/*-- certpath.c --*/
+int gpgsm_validate_path (KsbaCert cert);
+
+
+
 
 /*-- import.c --*/
 int gpgsm_import (int in_fd);
 
+
+
+
+/*-- errors.c (built) --*/
+const char *gpgsm_strerror (int err);
+
+
 #endif /*GPGSM_H*/
index 7fde823..8dc36c1 100644 (file)
@@ -31,6 +31,8 @@
 #include <ksba.h>
 
 #include "gpgsm.h"
+#include "keydb.h"
+#include "i18n.h"
 
 struct reader_cb_parm_s {
   FILE *fp;
@@ -68,199 +70,31 @@ reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
 
 
 static void
-print_integer (unsigned char *p)
+store_cert (KsbaCert cert)
 {
-  unsigned long len;
-
-  if (!p)
-    fputs ("none", stdout);
-  else
-    {
-      len = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
-      for (p+=4; len; len--, p++)
-        printf ("%02X", *p);
-    }
-}
-
-static void
-print_time (time_t t)
-{
-
-  if (!t)
-    fputs ("none", stdout);
-  else if ( t == (time_t)(-1) )
-    fputs ("error", stdout);
-  else
-    {
-      struct tm *tp;
-
-      tp = gmtime (&t);
-      printf ("%04d-%02d-%02d %02d:%02d:%02d",
-              1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
-              tp->tm_hour, tp->tm_min, tp->tm_sec);
-      assert (!tp->tm_isdst);
-    }
-}
-
-static void
-print_dn (char *p)
-{
-
-  if (!p)
-    fputs ("error", stdout);
-  else
-    printf ("`%s'", p);
-}
-
-static void 
-print_cert (KsbaCert cert)
-{
-  unsigned char *p;
-  char *dn;
-  time_t t;
-    
-  p = ksba_cert_get_serial (cert);
-  fputs ("serial: ", stdout);
-  print_integer (p);
-  ksba_free (p);
-  putchar ('\n');
-
-  t = ksba_cert_get_validity (cert, 0);
-  fputs ("notBefore: ", stdout);
-  print_time (t);
-  putchar ('\n');
-  t = ksba_cert_get_validity (cert, 1);
-  fputs ("notAfter: ", stdout);
-  print_time (t);
-  putchar ('\n');
-    
-  dn = ksba_cert_get_issuer (cert);
-  fputs ("issuer: ", stdout);
-  print_dn (dn);
-  ksba_free (dn);
-  putchar ('\n');
-    
-  dn = ksba_cert_get_subject (cert);
-  fputs ("subject: ", stdout);
-  print_dn (dn);
-  ksba_free (dn);
-  putchar ('\n');
-
-  printf ("hash algo: %d\n", ksba_cert_get_digest_algo (cert));
-}
-
-
-
-static MPI
-do_encode_md (GCRY_MD_HD md, int algo, size_t len, unsigned nbits,
-             const byte *asn, size_t asnlen)
-{
-    int nframe = (nbits+7) / 8;
-    byte *frame;
-    int i,n;
-    MPI a;
-
-    if( len + asnlen + 4  > nframe )
-       log_bug("can't encode a %d bit MD into a %d bits frame\n",
-                   (int)(len*8), (int)nbits);
-
-    /* We encode the MD in this way:
-     *
-     *    0  A PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
-     *
-     * PAD consists of FF bytes.
-     */
-    frame = xmalloc (nframe);
-    n = 0;
-    frame[n++] = 0;
-    frame[n++] = 1; /* block type */
-    i = nframe - len - asnlen -3 ;
-    assert( i > 1 );
-    memset( frame+n, 0xff, i ); n += i;
-    frame[n++] = 0;
-    memcpy( frame+n, asn, asnlen ); n += asnlen;
-    memcpy( frame+n, gcry_md_read(md, algo), len ); n += len;
-    assert( n == nframe );
-    gcry_mpi_scan ( &a, GCRYMPI_FMT_USG, frame, &nframe);
-    xfree(frame);
-    return a;
-}
-
-
-
-
-static void
-check_selfsigned_cert (KsbaCert cert)
-{
-  /* OID for MD5 as defined in PKCS#1 (rfc2313) */
-  static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 (md5) */
-  { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
-    0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
-  };
-
-  GCRY_MD_HD md;
-  int rc, algo;
-  GCRY_MPI frame;
-  char *p;
-  GCRY_SEXP s_sig, s_hash, s_pkey;
-
-  algo = ksba_cert_get_digest_algo (cert);
-  md = gcry_md_open (algo, 0);
-  if (!md)
-    {
-      log_error ("md_open failed: %s\n", gcry_strerror (-1));
-      return;
-    }
+  KEYDB_HANDLE kh;
+  int rc;
 
-  gcry_md_start_debug (md, "cert");
-  rc = ksba_cert_hash (cert, gcry_md_write, md);
-  if (rc)
+  kh = keydb_new (0);
+  if (!kh)
     {
-      log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc));
-      gcry_md_close (md);
+      log_error (_("failed to allocated keyDB handle\n"));
       return;
     }
-  gcry_md_final (md);
-
-  p = ksba_cert_get_sig_val (cert);
-  printf ("signature: %s\n", p);
-
-  rc = gcry_sexp_sscan ( &s_sig, NULL, p, strlen(p));
+  rc = keydb_locate_writable (kh, 0);
   if (rc)
-    {
-      log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc));
-      return;
-    }
-  /*gcry_sexp_dump (s_sig);*/
-
-
-  /* FIXME: need to map the algo to the ASN OID - we assume a fixed
-     one for now */
-  frame = do_encode_md (md, algo, 16, 2048, asn, DIM(asn));
+      log_error (_("error finding writable keyDB: %s\n"), gpgsm_strerror (rc));
 
-  /* put hash into the S-Exp s_hash */
-  if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
-    BUG ();
-  /*fputs ("hash:\n", stderr); gcry_sexp_dump (s_hash);*/
-  _gcry_log_mpidump ("hash", frame);
-
-  p = ksba_cert_get_public_key (cert);
-  printf ("public key: %s\n", p);
-
-  rc = gcry_sexp_sscan ( &s_pkey, NULL, p, strlen(p));
+  rc = keydb_insert_cert (kh, cert);
   if (rc)
     {
-      log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc));
-      return;
+      log_error (_("error storing certificate: %s\n"), gpgsm_strerror (rc));
     }
-  /*gcry_sexp_dump (s_pkey);*/
-  
-  rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
-  log_error ("gcry_pk_verify: %s\n", gcry_strerror (rc));
-
+  keydb_release (kh);               
 }
 
 
+
 \f
 int
 gpgsm_import (int in_fd)
@@ -311,9 +145,8 @@ gpgsm_import (int in_fd)
       goto leave;
     }
 
-  print_cert (cert);
-  check_selfsigned_cert (cert);
-
+  if ( !gpgsm_validate_path (cert) )
+    store_cert (cert);
 
  leave:
   ksba_cert_release (cert);
@@ -323,3 +156,4 @@ gpgsm_import (int in_fd)
   return rc;
 }
 
+
index b12ba1d..ef839ed 100644 (file)
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include "util.h"
-#include "options.h"
-#include "keybox.h"
+#include "gpgsm.h"
+#include "../kbx/keybox.h"
 #include "keydb.h" 
 #include "i18n.h"
 
-static struct {
-  const char *homedir;
-  int dry_run;
-  int quiet;
-  int verbose;
-  int preserve_permissions;
-} keydbopt;
+#define DIRSEP_C '/'
 
 static int active_handles;
 
@@ -87,25 +80,24 @@ keydb_add_resource (const char *url, int force, int secret)
 {
     static int any_secret, any_public;
     const char *resname = url;
-    IOBUF iobuf = NULL;
     char *filename = NULL;
-    int rc = 0;
+    int rc = 0; 
     KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
-    const char *created_fname = NULL;
+/*      const char *created_fname = NULL; */
 
     /* Do we have an URL?
      * gnupg-ring:filename  := this is a plain keybox
      * filename := See what is is, but create as plain keybox.
      */
     if (strlen (resname) > 11) {
-       if (!strncmp( resname, "gnupg-ring:", 11) ) {
+       if (!strncmp( resname, "gnupg-kbx:", 10) ) {
            rt = KEYDB_RESOURCE_TYPE_KEYBOX;
            resname += 11;
        }
       #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
        else if (strchr (resname, ':')) {
            log_error ("invalid key resource URL `%s'\n", url );
-           rc = G10ERR_GENERAL;
+           rc = GPGSM_General_Error;
            goto leave;
        }
       #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
@@ -115,59 +107,62 @@ keydb_add_resource (const char *url, int force, int secret)
        if (strchr(resname, DIRSEP_C) )
            filename = make_filename (resname, NULL);
        else
-           filename = make_filename (keydbopt.homedir, resname, NULL);
+           filename = make_filename (opt.homedir, resname, NULL);
     }
     else
-       filename = m_strdup (resname);
+       filename = xstrdup (resname);
 
     if (!force)
        force = secret? !any_secret : !any_public;
 
     /* see whether we can determine the filetype */
     if (rt == KEYDB_RESOURCE_TYPE_NONE) {
-       FILE *fp = fopen( filename, "rb" );
+       FILE *fp2 = fopen( filename, "rb" );
 
-       if (fp) {
+       if (fp2) {
            u32 magic;
 
-           if (fread( &magic, 4, 1, fp) == 1 ) {
+            /* FIXME: check for the keybox magic */
+           if (fread( &magic, 4, 1, fp2) == 1 ) 
+              {
                if (magic == 0x13579ace || magic == 0xce9a5713)
-                   ; /* GDBM magic - no more support */
+                  ; /* GDBM magic - no more support */
                else
-                   rt = KEYDB_RESOURCE_TYPE_KEYBOX;
-           }
+                  rt = KEYDB_RESOURCE_TYPE_KEYBOX;
+              }
            else /* maybe empty: assume ring */
-               rt = KEYDB_RESOURCE_TYPE_KEYBOX;
-           fclose( fp );
+              rt = KEYDB_RESOURCE_TYPE_KEYBOX;
+           fclose (fp2);
        }
        else /* no file yet: create ring */
-           rt = KEYDB_RESOURCE_TYPE_KEYBOX;
+          rt = KEYDB_RESOURCE_TYPE_KEYBOX;
     }
 
     switch (rt) {
       case KEYDB_RESOURCE_TYPE_NONE:
        log_error ("unknown type of key resource `%s'\n", url );
-       rc = G10ERR_GENERAL;
+       rc = GPGSM_General_Error;
        goto leave;
 
       case KEYDB_RESOURCE_TYPE_KEYBOX:
-       iobuf = iobuf_open (filename);
+#if 0
+       fp = fopen (filename);
        if (!iobuf && !force) {
            rc = G10ERR_OPEN_FILE;
            goto leave;
        }
 
-       if (!iobuf) {
+       if (!fp) {
            char *last_slash_in_filename;
 
            last_slash_in_filename = strrchr (filename, DIRSEP_C);
            *last_slash_in_filename = 0;
 
            if (access(filename, F_OK)) {
-               /* on the first time we try to create the default homedir and
-                * in this case the process will be terminated, so that on the
-                * next invocation it can read the options file in on startup
-                */
+               /* on the first time we try to create the default
+                   homedir and in this case the process will be
+                   terminated, so that on the next invocation it can
+                   read the options file in on startup */
                try_make_homedir (filename);
                rc = G10ERR_OPEN_FILE;
                *last_slash_in_filename = DIRSEP_C;
@@ -185,7 +180,7 @@ keydb_add_resource (const char *url, int force, int secret)
            }
            else {
              #ifndef HAVE_DOSISH_SYSTEM
-               if (secret && !keydbopt.preserve_permissionws) {
+               if (secret && !opt.preserve_permissionws) {
                    if (chmod (filename, S_IRUSR | S_IWUSR) ) {
                        log_error (_("changing permission of "
                                      " `%s' failed: %s\n"),
@@ -195,7 +190,7 @@ keydb_add_resource (const char *url, int force, int secret)
                    }
                }
              #endif
-               if (!keydbopt.quiet)
+               if (!opt.quiet)
                     log_info (_("keybox `%s' created\n"), filename);
                 created_fname = filename;
            }
@@ -204,12 +199,13 @@ keydb_add_resource (const char *url, int force, int secret)
        iobuf = NULL;
         if (created_fname) /* must invalidate that ugly cache */
             iobuf_ioctl (NULL, 2, 0, (char*)created_fname);
+#endif     
         {
-          void *token = keybox_register_filename (filename, secret);
+          void *token = keybox_register_file (filename, secret);
           if (!token)
             ; /* already registered - ignore it */
           else if (used_resources >= MAX_KEYDB_RESOURCES)
-              rc = G10ERR_RESOURCE_LIMIT;
+              rc = GPGSM_Resource_Limit;
           else 
             {
               all_resources[used_resources].type = rt;
@@ -223,7 +219,7 @@ keydb_add_resource (const char *url, int force, int secret)
 
       default:
        log_error ("resource type of `%s' not supported\n", url);
-       rc = G10ERR_GENERAL;
+       rc = GPGSM_General_Error;
        goto leave;
     }
 
@@ -231,12 +227,12 @@ keydb_add_resource (const char *url, int force, int secret)
 
   leave:
     if (rc)
-       log_error ("keyblock resource `%s': %s\n", filename, g10_errstr(rc));
+      log_error ("keyblock resource `%s': %s\n", filename, gpgsm_strerror(rc));
     else if (secret)
        any_secret = 1;
     else
        any_public = 1;
-    m_free (filename);
+    xfree (filename);
     return rc;
 }
 
@@ -249,7 +245,7 @@ keydb_new (int secret)
   KEYDB_HANDLE hd;
   int i, j;
   
-  hd = m_alloc_clear (sizeof *hd);
+  hd = xcalloc (1, sizeof *hd);
   hd->found = -1;
   
   assert (used_resources <= MAX_KEYDB_RESOURCES);
@@ -267,7 +263,7 @@ keydb_new (int secret)
           hd->active[j].secret = all_resources[i].secret;
           hd->active[j].u.kr = keybox_new (all_resources[i].token, secret);
           if (!hd->active[j].u.kr) {
-            m_free (hd);
+            xfree (hd);
             return NULL; /* fixme: release all previously allocated handles*/
           }
           j++;
@@ -283,95 +279,101 @@ keydb_new (int secret)
 void 
 keydb_release (KEYDB_HANDLE hd)
 {
-    int i;
-
-    if (!hd)
-        return;
-    assert (active_handles > 0);
-    active_handles--;
+  int i;
+  
+  if (!hd)
+    return;
+  assert (active_handles > 0);
+  active_handles--;
 
-    unlock_all (hd);
-    for (i=0; i < hd->used; i++) {
-        switch (hd->active[i].type) {
-          case KEYDB_RESOURCE_TYPE_NONE:
-            break;
-          case KEYDB_RESOURCE_TYPE_KEYBOX:
-            keybox_release (hd->active[i].u.kr);
-            break;
+  unlock_all (hd);
+  for (i=0; i < hd->used; i++)
+    {
+      switch (hd->active[i].type) 
+        {
+        case KEYDB_RESOURCE_TYPE_NONE:
+          break;
+        case KEYDB_RESOURCE_TYPE_KEYBOX:
+          keybox_release (hd->active[i].u.kr);
+          break;
         }
     }
 
-    m_free (hd);
+    xfree (hd);
 }
 
 
-/*
- * Return the name of the current resource.  This is function first
- * looks for the last found found, then for the current search
- * position, and last returns the first available resource.  The
- * returned string is only valid as long as the handle exists.  This
- * function does only return NULL if no handle is specified, in all
- * other error cases an empty string is returned.
- */
+/* Return the name of the current resource.  This is function first
+   looks for the last found found, then for the current search
+   position, and last returns the first available resource.  The
+   returned string is only valid as long as the handle exists.  This
+   function does only return NULL if no handle is specified, in all
+   other error cases an empty string is returned.  */
 const char *
 keydb_get_resource_name (KEYDB_HANDLE hd)
 {
-    int idx;
-    const char *s = NULL;
-
-    if (!hd) 
-        return NULL;
+  int idx;
+  const char *s = NULL;
+  
+  if (!hd) 
+    return NULL;
 
-    if ( hd->found >= 0 && hd->found < hd->used) 
-        idx = hd->found;
-    else if ( hd->current >= 0 && hd->current < hd->used) 
-        idx = hd->current;
-    else
-        idx = 0;
+  if ( hd->found >= 0 && hd->found < hd->used) 
+    idx = hd->found;
+  else if ( hd->current >= 0 && hd->current < hd->used) 
+    idx = hd->current;
+  else
+    idx = 0;
 
-    switch (hd->active[idx].type) {
-      case KEYDB_RESOURCE_TYPE_NONE:
-        s = NULL; 
-        break;
-      case KEYDB_RESOURCE_TYPE_KEYBOX:
-        s = keybox_get_resource_name (hd->active[idx].u.kr);
-        break;
+  switch (hd->active[idx].type) 
+    {
+    case KEYDB_RESOURCE_TYPE_NONE:
+      s = NULL; 
+      break;
+    case KEYDB_RESOURCE_TYPE_KEYBOX:
+      s = keybox_get_resource_name (hd->active[idx].u.kr);
+      break;
     }
-
-    return s? s: "";
+  
+  return s? s: "";
 }
 
 
-
+\f
 static int 
 lock_all (KEYDB_HANDLE hd)
 {
-    int i, rc = 0;
-
-    for (i=0; !rc && i < hd->used; i++) {
-        switch (hd->active[i].type) {
-          case KEYDB_RESOURCE_TYPE_NONE:
-            break;
-          case KEYDB_RESOURCE_TYPE_KEYBOX:
-            rc = keybox_lock (hd->active[i].u.kr, 1);
-            break;
+  int i, rc = 0;
+
+  for (i=0; !rc && i < hd->used; i++) 
+    {
+      switch (hd->active[i].type) 
+        {
+        case KEYDB_RESOURCE_TYPE_NONE:
+          break;
+        case KEYDB_RESOURCE_TYPE_KEYBOX:
+          /* FIXME  rc = keybox_lock (hd->active[i].u.kr, 1);*/
+          break;
         }
     }
 
-    if (rc) {
+    if (rc) 
+      {
         /* revert the already set locks */
-        for (i--; i >= 0; i--) {
-            switch (hd->active[i].type) {
+        for (i--; i >= 0; i--) 
+          {
+            switch (hd->active[i].type) 
+              {
               case KEYDB_RESOURCE_TYPE_NONE:
                 break;
               case KEYDB_RESOURCE_TYPE_KEYBOX:
-                keybox_lock (hd->active[i].u.kr, 0);
+                /* Fixme: keybox_lock (hd->active[i].u.kr, 0);*/
                 break;
-            }
-        }
-    }
+              }
+          }
+      }
     else
-        hd->locked = 1;
+      hd->locked = 1;
 
     return rc;
 }
@@ -379,24 +381,27 @@ lock_all (KEYDB_HANDLE hd)
 static void
 unlock_all (KEYDB_HANDLE hd)
 {
-    int i;
-
-    if (!hd->locked)
-        return;
-
-    for (i=hd->used-1; i >= 0; i--) {
-        switch (hd->active[i].type) {
-          case KEYDB_RESOURCE_TYPE_NONE:
-            break;
-          case KEYDB_RESOURCE_TYPE_KEYBOX:
-            keybox_lock (hd->active[i].u.kr, 0);
-            break;
+  int i;
+  
+  if (!hd->locked)
+    return;
+
+  for (i=hd->used-1; i >= 0; i--) 
+    {
+      switch (hd->active[i].type) 
+        {
+        case KEYDB_RESOURCE_TYPE_NONE:
+          break;
+        case KEYDB_RESOURCE_TYPE_KEYBOX:
+          /* fixme: keybox_lock (hd->active[i].u.kr, 0);*/
+          break;
         }
     }
-    hd->locked = 0;
+  hd->locked = 0;
 }
 
-
+\f
+#if 0
 /*
  * Return the last found keybox.  Caller must free it.
  * The returned keyblock has the kbode flag bit 0 set for the node with
@@ -440,7 +445,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
     if ( hd->found < 0 || hd->found >= hd->used) 
         return -1; /* nothing found */
 
-    if( keydbopt.dry_run )
+    if( opt.dry_run )
        return 0;
 
     rc = lock_all (hd);
@@ -473,7 +478,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
     if (!hd) 
         return G10ERR_INV_ARG;
 
-    if( keydbopt.dry_run )
+    if( opt.dry_run )
        return 0;
 
     if ( hd->found >= 0 && hd->found < hd->used) 
@@ -500,41 +505,157 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
     return rc;
 }
 
+#endif /*disabled code*/
+
+
+\f
+/*
+  Return the last found keybox.  Caller must free it.  The returned
+  keyblock has the kbode flag bit 0 set for the node with the public
+  key used to locate the keyblock or flag bit 1 set for the user ID
+  node.  */
+int
+keydb_get_cert (KEYDB_HANDLE hd, KsbaCert *r_cert)
+{
+  int rc = 0;
+
+  if (!hd)
+    return GPGSM_Invalid_Value;
+  
+  if ( hd->found < 0 || hd->found >= hd->used) 
+    return -1; /* nothing found */
+  
+  switch (hd->active[hd->found].type) 
+    {
+    case KEYDB_RESOURCE_TYPE_NONE:
+      rc = GPGSM_General_Error; /* oops */
+      break;
+    case KEYDB_RESOURCE_TYPE_KEYBOX:
+      rc = keybox_get_cert (hd->active[hd->found].u.kr, r_cert);
+      break;
+    }
+  
+  return rc;
+}
 
 /* 
- * The current keyblock will be deleted.
+ * Insert a new Certificate into one of the resources. 
  */
 int
-keydb_delete_keyblock (KEYDB_HANDLE hd)
+keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert)
 {
-    int rc = -1;
+  int rc = -1;
+  int idx;
+  char digest[20];
+  
+  if (!hd) 
+    return GPGSM_Invalid_Value;
 
-    if (!hd)
-        return G10ERR_INV_ARG;
+  if (opt.dry_run)
+    return 0;
+  
+  if ( hd->found >= 0 && hd->found < hd->used) 
+    idx = hd->found;
+  else if ( hd->current >= 0 && hd->current < hd->used) 
+    idx = hd->current;
+  else
+    return GPGSM_General_Error;
+
+  rc = lock_all (hd);
+  if (rc)
+    return rc;
 
-    if ( hd->found < 0 || hd->found >= hd->used) 
-        return -1; /* nothing found */
+  gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
 
-    if( keydbopt.dry_run )
-       return 0;
+  switch (hd->active[idx].type) 
+    {
+    case KEYDB_RESOURCE_TYPE_NONE:
+      rc = GPGSM_General_Error;
+      break;
+    case KEYDB_RESOURCE_TYPE_KEYBOX:
+      rc = keybox_insert_cert (hd->active[idx].u.kr, cert, digest);
+      break;
+    }
+  
+  unlock_all (hd);
+  return rc;
+}
 
-    rc = lock_all (hd);
-    if (rc)
-        return rc;
 
-    switch (hd->active[hd->found].type) {
-      case KEYDB_RESOURCE_TYPE_NONE:
-        rc = G10ERR_GENERAL; /* oops */
-        break;
-      case KEYDB_RESOURCE_TYPE_KEYBOX:
-        rc = keybox_delete_keyblock (hd->active[hd->found].u.kr);
-        break;
+
+/* update the current keyblock with KB */
+int
+keydb_update_cert (KEYDB_HANDLE hd, KsbaCert cert)
+{
+  int rc = 0;
+  char digest[20];
+  
+  if (!hd)
+    return GPGSM_Invalid_Value;
+
+  if ( hd->found < 0 || hd->found >= hd->used) 
+    return -1; /* nothing found */
+
+  if (opt.dry_run)
+    return 0;
+
+  rc = lock_all (hd);
+  if (rc)
+    return rc;
+
+  gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
+
+  switch (hd->active[hd->found].type) 
+    {
+    case KEYDB_RESOURCE_TYPE_NONE:
+      rc = GPGSM_General_Error; /* oops */
+      break;
+    case KEYDB_RESOURCE_TYPE_KEYBOX:
+      rc = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest);
+      break;
     }
 
-    unlock_all (hd);
+  unlock_all (hd);
+  return rc;
+}
+
+
+/* 
+ * The current keyblock or cert will be deleted.
+ */
+int
+keydb_delete (KEYDB_HANDLE hd)
+{
+  int rc = -1;
+  
+  if (!hd)
+    return GPGSM_Invalid_Value;
+
+  if ( hd->found < 0 || hd->found >= hd->used) 
+    return -1; /* nothing found */
+
+  if( opt.dry_run )
+    return 0;
+
+  rc = lock_all (hd);
+  if (rc)
     return rc;
+
+  switch (hd->active[hd->found].type)
+    {
+    case KEYDB_RESOURCE_TYPE_NONE:
+      rc = GPGSM_General_Error;
+      break;
+    case KEYDB_RESOURCE_TYPE_KEYBOX:
+      rc = keybox_delete (hd->active[hd->found].u.kr);
+      break;
+    }
+
+  unlock_all (hd);
+  return rc;
 }
 
+
 \f
 /*
  * Locate the default writable key resource, so that the next
@@ -547,12 +668,12 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
   int rc;
   
   if (!hd)
-    return G10ERR_INV_ARG;
+    return GPGSM_Invalid_Value;
   
   rc = keydb_search_reset (hd); /* this does reset hd->current */
   if (rc)
     return rc;
-
+  
   for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++) 
     {
       switch (hd->active[hd->current].type) 
@@ -576,7 +697,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
 void
 keydb_rebuild_caches (void)
 {
-  int i, rc;
+  int i;
   
   for (i=0; i < used_resources; i++)
     {
@@ -587,10 +708,10 @@ keydb_rebuild_caches (void)
         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
           break;
         case KEYDB_RESOURCE_TYPE_KEYBOX:
-          rc = keybox_rebuild_cache (all_resources[i].token);
-          if (rc)
-            log_error (_("failed to rebuild keybox cache: %s\n"),
-                       g10_errstr (rc));
+/*            rc = keybox_rebuild_cache (all_resources[i].token); */
+/*            if (rc) */
+/*              log_error (_("failed to rebuild keybox cache: %s\n"), */
+/*                         g10_errstr (rc)); */
           break;
         }
     }
@@ -604,27 +725,29 @@ keydb_rebuild_caches (void)
 int 
 keydb_search_reset (KEYDB_HANDLE hd)
 {
-    int i, rc = 0;
-
-    if (!hd)
-        return G10ERR_INV_ARG;
+  int i, rc = 0;
+  
+  if (!hd)
+    return GPGSM_Invalid_Value;
 
-    hd->current = 0; 
-    hd->found = -1;
-    /* and reset all resources */
-    for (i=0; !rc && i < hd->used; i++) {
-        switch (hd->active[i].type) {
-          case KEYDB_RESOURCE_TYPE_NONE:
-            break;
-          case KEYDB_RESOURCE_TYPE_KEYBOX:
-            rc = keybox_search_reset (hd->active[i].u.kr);
-            break;
+  hd->current = 0; 
+  hd->found = -1;
+  /* and reset all resources */
+  for (i=0; !rc && i < hd->used; i++) 
+    {
+      switch (hd->active[i].type) 
+        {
+        case KEYDB_RESOURCE_TYPE_NONE:
+          break;
+        case KEYDB_RESOURCE_TYPE_KEYBOX:
+          rc = keybox_search_reset (hd->active[i].u.kr);
+          break;
         }
     }
-    return rc; 
+  return rc; /* fixme: we need to map error codes or share them with
+                all modules*/
 }
 
-
 /* 
  * Search through all keydb resources, starting at the current position,
  * for a keyblock which contains one of the keys described in the DESC array.
@@ -632,71 +755,101 @@ keydb_search_reset (KEYDB_HANDLE hd)
 int 
 keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
 {
-    int rc = -1;
-
-    if (!hd)
-        return G10ERR_INV_ARG;
+  int rc = -1;
+  
+  if (!hd)
+    return GPGSM_Invalid_Value;
 
-    while (rc == -1 && hd->current >= 0 && hd->current < hd->used) {
-        switch (hd->active[hd->current].type) {
-          case KEYDB_RESOURCE_TYPE_NONE:
-            BUG(); /* we should never see it here */
-            break;
-          case KEYDB_RESOURCE_TYPE_KEYBOX:
-            rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc);
-            break;
+  while (rc == -1 && hd->current >= 0 && hd->current < hd->used) 
+    {
+      switch (hd->active[hd->current].type) 
+        {
+        case KEYDB_RESOURCE_TYPE_NONE:
+          BUG(); /* we should never see it here */
+          break;
+        case KEYDB_RESOURCE_TYPE_KEYBOX:
+          rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc);
+          break;
         }
-        if (rc == -1) /* EOF -> switch to next resource */
-            hd->current++; 
-        else if (!rc)
-            hd->found = hd->current;
+      if (rc == -1) /* EOF -> switch to next resource */
+        hd->current++; 
+      else if (!rc)
+        hd->found = hd->current;
     }
-
-    return rc; 
+  
+  return rc; 
 }
 
 
 int
 keydb_search_first (KEYDB_HANDLE hd)
 {
-    KEYDB_SEARCH_DESC desc;
-
-    memset (&desc, 0, sizeof desc);
-    desc.mode = KEYDB_SEARCH_MODE_FIRST;
-    return keydb_search (hd, &desc, 1);
+  KEYDB_SEARCH_DESC desc;
+  
+  memset (&desc, 0, sizeof desc);
+  desc.mode = KEYDB_SEARCH_MODE_FIRST;
+  return keydb_search (hd, &desc, 1);
 }
 
 int
 keydb_search_next (KEYDB_HANDLE hd)
 {
-    KEYDB_SEARCH_DESC desc;
-
-    memset (&desc, 0, sizeof desc);
-    desc.mode = KEYDB_SEARCH_MODE_NEXT;
-    return keydb_search (hd, &desc, 1);
+  KEYDB_SEARCH_DESC desc;
+  
+  memset (&desc, 0, sizeof desc);
+  desc.mode = KEYDB_SEARCH_MODE_NEXT;
+  return keydb_search (hd, &desc, 1);
 }
 
 int
 keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
 {
-    KEYDB_SEARCH_DESC desc;
-
-    memset (&desc, 0, sizeof desc);
-    desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
-    desc.u.kid[0] = kid[0];
-    desc.u.kid[1] = kid[1];
-    return keydb_search (hd, &desc, 1);
+  KEYDB_SEARCH_DESC desc;
+  
+  memset (&desc, 0, sizeof desc);
+  desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
+/*    desc.u.kid[0] = kid[0]; */
+/*    desc.u.kid[1] = kid[1]; */
+  return keydb_search (hd, &desc, 1);
 }
 
 int
 keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
 {
-    KEYDB_SEARCH_DESC desc;
+  KEYDB_SEARCH_DESC desc;
+  
+  memset (&desc, 0, sizeof desc);
+  desc.mode = KEYDB_SEARCH_MODE_FPR;
+  memcpy (desc.u.fpr, fpr, 20);
+  return keydb_search (hd, &desc, 1);
+}
 
-    memset (&desc, 0, sizeof desc);
-    desc.mode = KEYDB_SEARCH_MODE_FPR;
-    memcpy (desc.u.fpr, fpr, MAX_FINGERPRINT_LEN);
-    return keydb_search (hd, &desc, 1);
+int
+keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer)
+{
+  KEYDB_SEARCH_DESC desc;
+  int rc;
+  
+  memset (&desc, 0, sizeof desc);
+  desc.mode = KEYDB_SEARCH_MODE_ISSUER;
+  desc.u.name = issuer;
+  rc = keydb_search (hd, &desc, 1);
+  return rc;
+}
+
+int
+keydb_search_issuer_sn (KEYDB_HANDLE hd,
+                        const char *issuer, const unsigned char *serial)
+{
+  KEYDB_SEARCH_DESC desc;
+  int rc;
+  
+  memset (&desc, 0, sizeof desc);
+  desc.mode = KEYDB_SEARCH_MODE_ISSUER_SN;
+  desc.sn = serial;
+  desc.u.name = issuer;
+  rc = keydb_search (hd, &desc, 1);
+  return rc;
 }
 
 
index f67f736..71f457f 100644 (file)
 #ifndef GNUPG_KEYDB_H
 #define GNUPG_KEYDB_H
 
+#include <ksba.h>
+
+#include "../kbx/keybox-search-desc.h"
+
 typedef struct keydb_handle *KEYDB_HANDLE;
 
-typedef enum {
-    KEYDB_SEARCH_MODE_NONE,
-    KEYDB_SEARCH_MODE_EXACT,
-    KEYDB_SEARCH_MODE_SUBSTR,
-    KEYDB_SEARCH_MODE_MAIL,
-    KEYDB_SEARCH_MODE_MAILSUB,
-    KEYDB_SEARCH_MODE_MAILEND,
-    KEYDB_SEARCH_MODE_WORDS,
-    KEYDB_SEARCH_MODE_SHORT_KID,
-    KEYDB_SEARCH_MODE_LONG_KID,
-    KEYDB_SEARCH_MODE_FPR16,
-    KEYDB_SEARCH_MODE_FPR20,
-    KEYDB_SEARCH_MODE_FPR,
-    KEYDB_SEARCH_MODE_FIRST,
-    KEYDB_SEARCH_MODE_NEXT
-} KeydbSearchMode;
-
-struct keydb_search_desc {
-    KeydbSearchMode mode;
-    int (*skipfnc)(void *,u32*);
-    void *skipfncvalue;
-    union {
-        const char *name;
-        char fpr[MAX_FINGERPRINT_LEN];
-        u32  kid[2];
-    } u;
-};
 
 /*-- keydb.c --*/
 int keydb_add_resource (const char *url, int force, int secret);
 KEYDB_HANDLE keydb_new (int secret);
 void keydb_release (KEYDB_HANDLE hd);
 const char *keydb_get_resource_name (KEYDB_HANDLE hd);
+
+#if 0 /* pgp stuff */
 int keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb);
 int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb);
 int keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb);
-int keydb_delete_keyblock (KEYDB_HANDLE hd);
+#endif
+
+int keydb_get_cert (KEYDB_HANDLE hd, KsbaCert *r_cert);
+int keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert);
+int keydb_update_cert (KEYDB_HANDLE hd, KsbaCert cert);
+
+int keydb_delete (KEYDB_HANDLE hd);
+
 int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved);
 void keydb_rebuild_caches (void);
+
 int keydb_search_reset (KEYDB_HANDLE hd);
 int keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
 int keydb_search_first (KEYDB_HANDLE hd);
 int keydb_search_next (KEYDB_HANDLE hd);
 int keydb_search_kid (KEYDB_HANDLE hd, u32 *kid);
 int keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr);
+int keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer);
+int keydb_search_issuer_sn (KEYDB_HANDLE hd,
+                            const char *issuer, const unsigned char *serial);
 
 
 #endif /*GNUPG_KEYDB_H*/
index c1bc346..d3f0aab 100644 (file)
--- a/sm/misc.c
+++ b/sm/misc.c
 #include <ksba.h>
 
 #include "util.h"
+#include "gpgsm.h"
 
 
 /* Note: we might want to wrap this in a macro to get our hands on
-   the line and file wehre the error occired */
+   the line and file where the error occired */
 int
 map_ksba_err (int err)
 {
-  return -1;
+  switch (err)
+    {
+    case -1:
+    case 0:
+      break;
+      
+    default:
+      err = GPGSM_General_Error;
+      break;
+    }
+  return err;
 }
 
+
+int 
+map_gcry_err (int err)
+{
+  switch (err)
+    {
+    case -1:
+    case 0:
+      break;
+      
+    default:
+      err = GPGSM_General_Error;
+      break;
+    }
+  return err;
+}
+
+int 
+map_kbx_err (int err)
+{
+  switch (err)
+    {
+    case -1:
+    case 0:
+      break;
+      
+    default:
+      err = GPGSM_General_Error;
+      break;
+    }
+  return err;
+}
+
+
+
+
+
+
+
index f3b4ab7..c0fc666 100644 (file)
--- a/sm/util.h
+++ b/sm/util.h
 
 #include <gcrypt.h> /* we need this for the memory function protos */
 
+/* to pass the fucntion to libksba we need to cast it */
+#define HASH_FNC ((void (*)(void *, const byte*,size_t))gcry_md_write)
+
+
 #include "../jnlib/logging.h"
 #include "../jnlib/argparse.h"
 #include "../jnlib/stringhelp.h"
@@ -46,5 +50,9 @@
 
 /*-- misc.c --*/
 int map_ksba_err (int err);
+int map_gcry_err (int err);
+int map_kbx_err (int err);
 
 #endif /*UTIL_H*/
+
+