summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2001-11-13 13:50:14 +0100
committerWerner Koch <wk@gnupg.org>2001-11-13 13:50:14 +0100
commit90d060c1997c6c0b9f26c9088020d62f91d450da (patch)
treeb2e7720d625699a49729b36286fb66a774c5faed
parentA Makefile is a pretty useful thing (diff)
downloadgnupg2-90d060c1997c6c0b9f26c9088020d62f91d450da.tar.xz
gnupg2-90d060c1997c6c0b9f26c9088020d62f91d450da.zip
We have reached a state where we are able to import certs and
check the certification path.
-rw-r--r--kbx/Makefile.am8
-rw-r--r--kbx/kbxutil.c3
-rw-r--r--kbx/keybox-blob.c314
-rw-r--r--kbx/keybox-defs.h34
-rw-r--r--kbx/keybox-dump.c94
-rw-r--r--kbx/keybox-errors.c6
-rw-r--r--kbx/keybox-file.c58
-rw-r--r--kbx/keybox-init.c103
-rw-r--r--kbx/keybox-search-desc.h69
-rw-r--r--kbx/keybox-search.c511
-rw-r--r--kbx/keybox-update.c390
-rw-r--r--kbx/keybox.h44
-rw-r--r--sm/Makefile.am7
-rw-r--r--sm/certchain.c131
-rw-r--r--sm/certcheck.c156
-rw-r--r--sm/certdump.c131
-rw-r--r--sm/certpath.c131
-rw-r--r--sm/fingerprint.c104
-rw-r--r--sm/gpgsm.c15
-rw-r--r--sm/gpgsm.h35
-rw-r--r--sm/import.c200
-rw-r--r--sm/keydb.c557
-rw-r--r--sm/keydb.h46
-rw-r--r--sm/misc.c54
-rw-r--r--sm/util.h8
25 files changed, 2482 insertions, 727 deletions
diff --git a/kbx/Makefile.am b/kbx/Makefile.am
index 81885f3ca..4c783fc1e 100644
--- a/kbx/Makefile.am
+++ b/kbx/Makefile.am
@@ -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
diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c
index 8c3dee97a..e8b015ba6 100644
--- a/kbx/kbxutil.c
+++ b/kbx/kbxutil.c
@@ -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;
diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c
index 7db62165a..84ebc904c 100644
--- a/kbx/keybox-blob.c
+++ b/kbx/keybox-blob.c
@@ -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 )
}
+/* 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;
+ }
+}
+
+
/*
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*/
@@ -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*/
+
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;
}
-
-
diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h
index 2adbdd22f..308c1fff3 100644
--- a/kbx/keybox-defs.h
+++ b/kbx/keybox-defs.h
@@ -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);
diff --git a/kbx/keybox-dump.c b/kbx/keybox-dump.c
index 6022900f2..d84ae7349 100644
--- a/kbx/keybox-dump.c
+++ b/kbx/keybox-dump.c
@@ -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 )
diff --git a/kbx/keybox-errors.c b/kbx/keybox-errors.c
index bd03cdff3..e75373c0b 100644
--- a/kbx/keybox-errors.c
+++ b/kbx/keybox-errors.c
@@ -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;
}
diff --git a/kbx/keybox-file.c b/kbx/keybox-file.c
index 66bca504f..715d3fbe2 100644
--- a/kbx/keybox-file.c
+++ b/kbx/keybox-file.c
@@ -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;
}
-
diff --git a/kbx/keybox-init.c b/kbx/keybox-init.c
index a4649d18c..1a4a587b9 100644
--- a/kbx/keybox-init.c
+++ b/kbx/keybox-init.c
@@ -23,44 +23,47 @@
#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
index 000000000..22bcba69b
--- /dev/null
+++ b/kbx/keybox-search-desc.h
@@ -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*/
diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c
index d2c61ff21..3468a8ecf 100644
--- a/kbx/keybox-search.c
+++ b/kbx/keybox-search.c
@@ -25,134 +25,417 @@
#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);
+}
+
+
+
+
+/*
+ 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));
+}
+
+
+
+/*
+
+ 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;
}
+
+/*
+ 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
index 000000000..d49c3d027
--- /dev/null
+++ b/kbx/keybox-update.c
@@ -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;
+}
+
+
diff --git a/kbx/keybox.h b/kbx/keybox.h
index 90088236a..645f1e715 100644
--- a/kbx/keybox.h
+++ b/kbx/keybox.h
@@ -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 *);
diff --git a/sm/Makefile.am b/sm/Makefile.am
index ec2c1b247..ab34f10b6 100644
--- a/sm/Makefile.am
+++ b/sm/Makefile.am
@@ -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
index 000000000..aef1612cc
--- /dev/null
+++ b/sm/certchain.c
@@ -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
index 000000000..a86aa2d9e
--- /dev/null
+++ b/sm/certcheck.c
@@ -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
index 000000000..5dfce2a02
--- /dev/null
+++ b/sm/certdump.c
@@ -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
index 000000000..aef1612cc
--- /dev/null
+++ b/sm/certpath.c
@@ -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
index 000000000..9453a6eab
--- /dev/null
+++ b/sm/fingerprint.c
@@ -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;
+}
+
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index 3ca58d3c8..39db2433e 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -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;
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index 1c66e1032..a4361dc1c 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -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*/
diff --git a/sm/import.c b/sm/import.c
index 7fde82327..8dc36c1ad 100644
--- a/sm/import.c
+++ b/sm/import.c
@@ -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);
}
+
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;
}
+
diff --git a/sm/keydb.c b/sm/keydb.c
index b12ba1df3..ef839edfb 100644
--- a/sm/keydb.c
+++ b/sm/keydb.c
@@ -28,19 +28,12 @@
#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: "";
}
-
+
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;
}
-
+
+#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*/
+
+
+
+/*
+ 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;
}
+
/*
* 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;
}
diff --git a/sm/keydb.h b/sm/keydb.h
index f67f7362e..71f457fef 100644
--- a/sm/keydb.h
+++ b/sm/keydb.h
@@ -21,53 +21,43 @@
#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*/
diff --git a/sm/misc.c b/sm/misc.c
index c1bc346d1..d3f0aabaf 100644
--- a/sm/misc.c
+++ b/sm/misc.c
@@ -29,13 +29,63 @@
#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;
+}
+
+
+
+
+
+
+
diff --git a/sm/util.h b/sm/util.h
index f3b4ab7b5..c0fc6667e 100644
--- a/sm/util.h
+++ b/sm/util.h
@@ -23,6 +23,10 @@
#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*/
+
+