1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-02 12:01:32 +01:00

We have reached a state where we are able to import certs and

check the certification path.
This commit is contained in:
Werner Koch 2001-11-13 12:50:14 +00:00
parent 6dec3847d8
commit 90d060c199
25 changed files with 2486 additions and 731 deletions

View File

@ -27,13 +27,14 @@ noinst_LIBRARIES = libkeybox.a
bin_PROGRAMS = kbxutil
common_sources = \
keybox.h \
keybox-defs.h \
keybox.h keybox-defs.h keybox-search-desc.h \
keybox-util.c \
keybox-errors.c \
keybox-init.c \
keybox-blob.c \
keybox-file.c \
keybox-search.c \
keybox-update.c \
keybox-dump.c
@ -41,6 +42,7 @@ libkeybox_a_SOURCES = $(common_sources)
kbxutil_SOURCES = kbxutil.c $(common_sources)
kbxutil_LDADD = ../jnlib/libjnlib.a \
../../libksba/src/.libs/libksba.a \
../../libgcrypt/src/.libs/libgcrypt.so.1
keybox-errors.c : keybox.h mkerrors

View File

@ -234,8 +234,9 @@ main( int argc, char **argv )
/*create_dotlock(NULL); register locking cleanup */
i18n_init();
/* We need to use the gcry malloc function becuase jnlib does use them */
/* We need to use the gcry malloc function because jnlib does use them */
keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
pargs.argc = &argc;

View File

@ -39,25 +39,29 @@ The first record of a plain KBX file has a special format:
byte pgp_completes ditto.
byte pgp_cert_depth ditto.
The OpenPGP KBX Blob looks like this:
The OpenPGP and X.509 blob are verry similiar, things which are
X.509 specific are noted like [X.509: xxx]
u32 length of this blob (including these 4 bytes)
byte Blob type (2)
byte Blob type (2) [X509: 3]
byte version number of this blob type (1)
u16 Blob flags
bit 0 = contains secret key material
u32 offset to the OpenPGP keyblock
u32 length of the keyblock
u16 number of keys (at least 1!)
u32 offset to the OpenPGP keyblock or X509 DER encoded certificate
u32 ant its length
u16 number of keys (at least 1!) [X509: always 1]
u16 size of additional key information
n times:
b20 The keys fingerprint
(fingerprints are always 20 bytes, MD5 left padded with zeroes)
u32 offset to the n-th key's keyID (a keyID is always 8 byte)
or 0 if not known which is the case opnly for X509.
u16 special key flags
bit 0 =
u16 reserved
u16 size of serialnumber(may be zero)
n u16 (see above) bytes of serial number
u16 number of user IDs
u16 size of additional user ID information
n times:
@ -67,6 +71,8 @@ The OpenPGP KBX Blob looks like this:
bit 0 =
byte validity
byte reserved
[For X509, the first user ID is the ISsuer, the second the subject
and the others are subjectAltNames]
u16 number of signatures
u16 size of signature information (4)
u32 expiration time of signature with some special values:
@ -75,8 +81,8 @@ The OpenPGP KBX Blob looks like this:
0x00000002 = bad signature
0x10000000 = valid and expires at some date in 1978.
0xffffffff = valid and does not expire
u8 assigned ownertrust
u8 all_validity
u8 assigned ownertrust [X509: no used]
u8 all_validity [X509: no used]
u16 reserved
u32 recheck_after
u32 Newest timestamp in the keyblock (useful for KS syncronsiation?)
@ -90,7 +96,9 @@ The OpenPGP KBX Blob looks like this:
maybe we put a signature here later.
b16 MD5 checksum (useful for KS syncronisation)
b16 MD5 checksum (useful for KS syncronisation), we might also want to use
a mac here.
b4 resevered
*/
@ -103,8 +111,17 @@ The OpenPGP KBX Blob looks like this:
#include <assert.h>
#include <gcrypt.h>
#ifdef KEYBOX_WITH_OPENPGP
/* include stuff to parse the packets */
#endif
#ifdef KEYBOX_WITH_X509
#include <ksba.h>
#endif
#include "keybox-defs.h"
/* special values of the signature status */
#define SF_NONE(a) ( !(a) )
#define SF_NOKEY(a) ((a) & (1<<0))
@ -132,6 +149,7 @@ struct keyboxblob_key {
};
struct keyboxblob_uid {
ulong off_addr;
char *name; /* used only with x509 */
u32 len;
u16 flags;
byte validity;
@ -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;
};
@ -255,6 +277,28 @@ put32 (struct membuf *mb, u32 a )
put_membuf (mb, tmp, 4);
}
/* 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,25 +455,13 @@ 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;
}
@ -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,28 +585,39 @@ create_blob_header (KEYBOXBLOB blob, int blobtype)
put32 ( a, 0 ); /* size of reserved space */
/* reserved space (which is currently of size 0) */
/* space where we write keyIDs and and other stuff so that the
pointers can actually point to somewhere */
if (blobtype == BLOBTYPE_PGP)
{
/* We need to store the keyids for all pgp v3 keys because those key
IDs are not part of the fingerprint. While we are doing that, we
fixup all the keyID offsets */
for (i=0; i < blob->nkeys; i++ )
{
struct fixup_list *fl = xtrycalloc(1, sizeof *fl );
if (!fl)
return KEYBOX_Out_Of_Core;
fl->off = blob->keys[i].off_kid_addr;
fl->next = blob->fixups;
blob->fixups = fl;
if (blob->keys[i].off_kid)
{ /* this is a v3 one */
fl->val = a->len;
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 */
fl->val = blob->keys[i].off_kid_addr - 8;
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);
}
}
}
@ -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;
}

View File

@ -41,6 +41,8 @@ enum {
};
typedef struct keyboxblob *KEYBOXBLOB;
typedef struct keybox_name *KB_NAME;
typedef struct keybox_name const * CONST_KB_NAME;
@ -56,16 +58,13 @@ struct keybox_name {
struct keybox_handle {
CONST_KB_NAME resource;
int secret; /* this is for a secret keybox */
struct {
CONST_KB_NAME kb;
/*IOBUF iobuf;*/
int secret; /* this is for a secret keybox */
FILE *fp;
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);

View File

@ -46,6 +46,35 @@ get16 (const byte *buffer)
return a;
}
void
print_string (FILE *fp, const byte *p, size_t n, int delim)
{
for ( ; n; n--, p++ )
{
if (*p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim)
{
putc('\\', fp);
if( *p == '\n' )
putc('n', fp);
else if( *p == '\r' )
putc('r', fp);
else if( *p == '\f' )
putc('f', fp);
else if( *p == '\v' )
putc('v', fp);
else if( *p == '\b' )
putc('b', fp);
else if( !*p )
putc('0', fp);
else
fprintf(fp, "x%02x", *p );
}
else
putc(*p, fp);
}
}
static int
dump_header_blob (const byte *buffer, size_t length, FILE *fp)
{
@ -67,6 +96,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
ulong nuids, uidinfolen;
ulong nsigs, siginfolen;
ulong rawdata_off, rawdata_len;
ulong nserial;
const byte *p;
buffer = _keybox_get_blob_image (blob, &length);
@ -128,19 +158,33 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
int i;
ulong kidoff, kflags;
fprintf (fp, "Key-%lu-Fpr: ", n );
fprintf (fp, "Key-Fpr[%lu]: ", n );
for (i=0; i < 20; i++ )
fprintf (fp, "%02X", p[i]);
kidoff = get32 (p + 20);
fprintf (fp, "\nKey-%lu-Kid-Off: %lu\n", n, kidoff );
fprintf (fp, "Key-%lu-Kid: ", n );
fprintf (fp, "\nKey-Kid-Off[%lu]: %lu\n", n, kidoff );
fprintf (fp, "Key-Kid[%lu]: ", n );
/* fixme: check bounds */
for (i=0; i < 8; i++ )
fprintf (fp, "%02X", buffer[kidoff+i] );
kflags = get16 (p + 24 );
fprintf( fp, "\nKey-%lu-Flags: %04lX\n", n, kflags);
fprintf( fp, "\nKey-Flags[%lu]: %04lX\n", n, kflags);
}
/* serial number */
fputs ("Serial-No: ", fp);
nserial = get16 (p);
p += 2;
if (!nserial)
fputs ("none", fp);
else
{
for (; nserial; nserial--, p++)
fprintf (fp, "%02X", *p);
}
putc ('\n', fp);
/* user IDs */
nuids = get16 (p);
fprintf (fp, "Uid-Count: %lu\n", nuids );
uidinfolen = get16 (p + 2);
@ -153,14 +197,42 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
uidoff = get32( p );
uidlen = get32( p+4 );
fprintf (fp, "Uid-%lu-Off: %lu\n", n, uidoff );
fprintf (fp, "Uid-%lu-Len: %lu\n", n, uidlen );
fprintf (fp, "Uid-%lu: \"", n );
/*print_string (fp, buffer+uidoff, uidlen, '\"');*/
if (type == BLOBTYPE_X509 && !n)
{
fprintf (fp, "Issuer-Off: %lu\n", uidoff );
fprintf (fp, "Issuer-Len: %lu\n", uidlen );
fprintf (fp, "Issuer: \"");
}
else if (type == BLOBTYPE_X509 && n == 1)
{
fprintf (fp, "Subject-Off: %lu\n", uidoff );
fprintf (fp, "Subject-Len: %lu\n", uidlen );
fprintf (fp, "Subject: \"");
}
else
{
fprintf (fp, "Uid-Off[%lu]: %lu\n", n, uidoff );
fprintf (fp, "Uid-Len[%lu]: %lu\n", n, uidlen );
fprintf (fp, "Uid[%lu]: \"", n );
}
print_string (fp, buffer+uidoff, uidlen, '\"');
fputs ("\"\n", fp);
uflags = get16 (p + 8);
fprintf (fp, "Uid-%lu-Flags: %04lX\n", n, uflags );
fprintf (fp, "Uid-%lu-Validity: %d\n", n, p[10] );
if (type == BLOBTYPE_X509 && !n)
{
fprintf (fp, "Issuer-Flags: %04lX\n", uflags );
fprintf (fp, "Issuer-Validity: %d\n", p[10] );
}
else if (type == BLOBTYPE_X509 && n == 1)
{
fprintf (fp, "Subject-Flags: %04lX\n", uflags );
fprintf (fp, "Subject-Validity: %d\n", p[10] );
}
else
{
fprintf (fp, "Uid-Flags[%lu]: %04lX\n", n, uflags );
fprintf (fp, "Uid-Validity[%lu]: %d\n", n, p[10] );
}
}
nsigs = get16 (p);
@ -174,7 +246,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
ulong sflags;
sflags = get32 (p);
fprintf (fp, "Sig-%lu-Expire: ", n );
fprintf (fp, "Sig-Expire[%lu]: ", n );
if (!sflags)
fputs ("[not checked]", fp);
else if (sflags == 1 )

View File

@ -32,6 +32,12 @@ keybox_strerror (KeyboxError err)
case KEYBOX_File_Error: s="file error"; break;
case KEYBOX_Blob_Too_Short: s="blob too short"; break;
case KEYBOX_Blob_Too_Large: s="blob too large"; break;
case KEYBOX_Invalid_Handle: s="invalid handle"; break;
case KEYBOX_File_Create_Error: s="file create error"; break;
case KEYBOX_File_Open_Error: s="file open error"; break;
case KEYBOX_File_Close_Error: s="file close error"; break;
case KEYBOX_Nothing_Found: s="nothing found"; break;
case KEYBOX_Wrong_Blob_Type: s="wrong blob type"; break;
default: sprintf (buf, "ec=%d", err ); s=buf; break;
}

View File

@ -25,7 +25,7 @@
#include "keybox-defs.h"
/* Read a block at the current postion ant return it in r_blocb. r_blob may be NULL sto simply skip the current block */
int
_keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
{
@ -58,56 +58,28 @@ _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
image[0] = c1; image[1] = c2; image[2] = c3; image[3] = c4;
if (fread (image+4, imagelen-4, 1, fp) != 1)
{
xfree (image);
return KEYBOX_Read_Error;
}
rc = _keybox_new_blob (r_blob, image, imagelen);
if (rc)
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;
image = _keybox_get_blob_image (blob, &length);
if (fwrite (image, length, 1, fp) != 1)
{
return KEYBOX_Write_Error;
}
while( !(rc = enum_keyblocks_next( kbpos, 1, &keyblock )) ) {
KBXBLOB blob;
const char *p;
size_t n;
merge_keys_and_selfsig( keyblock );
rc = kbx_create_blob ( &blob, keyblock );
if( rc ) {
log_error("kbx_create_blob failed: %s\n", gpg_errstr(rc) );
goto leave;
}
p = kbx_get_blob_image ( blob, &n );
fwrite( p, n, 1, stdout );
kbx_release_blob ( blob );
}
if( rc && rc != -1 )
log_error("enum_keyblocks(read) failed: %s\n", gpg_errstr(rc));
leave:
enum_keyblocks_end( kbpos );
release_kbnode( keyblock );
#endif
return 0;
}

View File

@ -23,32 +23,36 @@
#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;
if (active_handles)
BUG (); /* We don't allow that */
for (kr=kb_names; kr; kr = kr->next) {
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));
kr = xtrymalloc (sizeof *kr + strlen (fname));
if (!kr)
return NULL;
strcpy (kr->fname, fname);
kr->secret = !!secret;
kr->lockhd = NULL;
/* kr->lockhd = NULL;*/
kr->is_locked = 0;
kr->did_full_scan = 0;
/* keep a list of all issued pointers */
@ -56,11 +60,10 @@ keybox_register_file (const char *fname, int secret)
kb_names = kr;
/* create the offset table the first time a function here is used */
if (!kb_offtbl)
kb_offtbl = new_offset_hash_table ();
/* if (!kb_offtbl) */
/* kb_offtbl = new_offset_hash_table (); */
return kr;
#endif
}
int
@ -71,3 +74,47 @@ 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;
}

69
kbx/keybox-search-desc.h Normal file
View File

@ -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*/

View File

@ -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)
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)
{
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;
}
hd->error = 0;
hd->eof = 0;
return 0;
}
int
keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc)
{
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 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_fpr ( KEYBOXBLOB blob, const byte *fpr )
keybox_get_cert (KEYBOX_HANDLE hd, KsbaCert *r_cert)
{
ulong n, nkeys, keyinfolen;
const byte *p, *pend;
byte *buffer = blob->blob;
size_t buflen = blob->bloblen;
const unsigned char *buffer;
size_t length;
size_t cert_off, cert_len;
KsbaReader reader = NULL;
KsbaCert cert = NULL;
int rc;
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 (!hd)
return KEYBOX_Invalid_Value;
if (!hd->found.blob)
return KEYBOX_Nothing_Found;
if ( buffer[4] != 2 )
return GPGERR_GENERAL; /* invalid blob type */
if ( buffer[5] != 1 )
return GPGERR_GENERAL; /* invalid blob format version */
if (blob_get_type (hd->found.blob) != BLOBTYPE_X509)
return KEYBOX_Wrong_Blob_Type;
nkeys = get16( buffer + 16 );
keyinfolen = get16( buffer + 18 );
p = buffer + 20;
for(n=0; n < nkeys; n++, p += keyinfolen ) {
if ( p+20 > pend )
return GPGERR_GENERAL; /* blob shorter than required */
if (!memcmp ( p, fpr, 20 ) )
return 0; /* found */
}
return -1;
}
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;
/****************
* Check whether the given keyID (20 bytes) is in the
* given keyblob.
* Return: 0 = found
* -1 = not found
other = error (fixme: do not always return gpgerr_general)
*/
int
keybox_blob_has_kid ( KEYBOXBLOB blob, const byte *keyidbuf, size_t keyidlen )
{
ulong n, nkeys, keyinfolen, off;
const byte *p, *pend;
byte *buffer = blob->blob;
size_t buflen = blob->bloblen;
if ( buflen < 40 )
return GPGERR_GENERAL; /* blob too short */
n = get32( buffer );
if ( n > buflen )
return GPGERR_GENERAL; /* blob larger than announced length */
buflen = n; /* ignore trailing stuff */
pend = buffer + n - 1;
if ( buffer[4] != 2 )
return GPGERR_GENERAL; /* invalid blob type */
if ( buffer[5] != 1 )
return GPGERR_GENERAL; /* invalid blob format version */
nkeys = get16( buffer + 16 );
keyinfolen = get16( buffer + 18 );
p = buffer + 20;
for(n=0; n < nkeys; n++, p += keyinfolen ) {
if ( p+24 > pend )
return GPGERR_GENERAL; /* blob shorter than required */
off = get32 ( p + 20 );
if (keyidlen < 8 ) /* actually keyidlen may either be 4 or 8 */
off +=4;
if ( off+keyidlen > buflen )
return GPGERR_GENERAL; /* offset out of bounds */
if ( !memcmp ( buffer+off, keyidbuf, keyidlen ) )
return 0; /* found */
}
return -1;
}
int
keybox_blob_has_uid ( KEYBOXBLOB blob,
int (*cmp)(const byte *, size_t, void *), void *opaque )
{
ulong n, nuids, uidinfolen, off, len;
const byte *p, *pend;
byte *buffer = blob->blob;
size_t buflen = blob->bloblen;
if ( buflen < 40 )
return GPGERR_GENERAL; /* blob too short */
n = get32( buffer );
if ( n > buflen )
return GPGERR_GENERAL; /* blob larger than announced length */
buflen = n; /* ignore trailing stuff */
pend = buffer + n - 1;
if ( buffer[4] != 2 )
return GPGERR_GENERAL; /* invalid blob type */
if ( buffer[5] != 1 )
return GPGERR_GENERAL; /* invalid blob format version */
p = buffer + 20 + get16( buffer + 16 ) * get16( buffer + 18 );
if ( p+4 > pend )
return GPGERR_GENERAL; /* blob shorter than required */
nuids = get16( p ); p+= 2;
uidinfolen = get16( p ); p+=2;
for(n=0; n < nuids; n++, p += uidinfolen ) {
if ( p+8 > pend )
return GPGERR_GENERAL; /* blob shorter than required */
off = get32 ( p );
len = get32 ( p + 4 );
if ( off+len > buflen )
return GPGERR_GENERAL; /* offset out of bounds */
if ( (*cmp) ( buffer+off, len, opaque ) )
return 0; /* found */
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*/

390
kbx/keybox-update.c Normal file
View File

@ -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;
}

View File

@ -27,6 +27,8 @@ extern "C" {
#endif
#endif
#include "keybox-search-desc.h"
#define KEYBOX_WITH_OPENPGP 1
#define KEYBOX_WITH_X509 1
@ -51,8 +53,13 @@ typedef enum {
KEYBOX_Write_Error = 6,
KEYBOX_File_Error = 7,
KEYBOX_Blob_Too_Short = 8,
KEYBOX_Blob_Too_Large = 9
KEYBOX_Blob_Too_Large = 9,
KEYBOX_Invalid_Handle = 10,
KEYBOX_File_Create_Error = 11,
KEYBOX_File_Open_Error = 12,
KEYBOX_File_Close_Error = 13,
KEYBOX_Nothing_Found = 14,
KEYBOX_Wrong_Blob_Type = 15,
} KeyboxError;
@ -60,24 +67,41 @@ typedef enum {
typedef struct keybox_handle *KEYBOX_HANDLE;
/*-- keybox-init.c --*/
void *keybox_register_file (const char *fname, int secret);
int keybox_is_writable (void *token);
/*-- --*/
KEYBOX_HANDLE keybox_new (void *token, int secret);
void keybox_release (KEYBOX_HANDLE hd);
const char *keybox_get_resource_name (KEYBOX_HANDLE hd);
int keybox_lock (KEYBOX_HANDLE hd, int yes);
/*-- keybox-search.c --*/
#ifdef KEYBOX_WITH_X509
int keybox_get_cert (KEYBOX_HANDLE hd, KsbaCert *ret_cert);
#endif /*KEYBOX_WITH_X509*/
int keybox_search_reset (KEYBOX_HANDLE hd);
int keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc);
/*-- keybox-update.c --*/
#ifdef KEYBOX_WITH_X509
int keybox_insert_cert (KEYBOX_HANDLE hd, KsbaCert cert,
unsigned char *sha1_digest);
int keybox_update_cert (KEYBOX_HANDLE hd, KsbaCert cert,
unsigned char *sha1_digest);
#endif /*KEYBOX_WITH_X509*/
int keybox_delete (KEYBOX_HANDLE hd);
/*-- --*/
#if 0
int keybox_lock (KEYBOX_HANDLE hd, int yes);
int keybox_get_keyblock (KEYBOX_HANDLE hd, KBNODE *ret_kb);
int keybox_update_keyblock (KEYBOX_HANDLE hd, KBNODE kb);
int keybox_insert_keyblock (KEYBOX_HANDLE hd, KBNODE kb);
int keybox_locate_writable (KEYBOX_HANDLE hd);
int keybox_delete_keyblock (KEYBOX_HANDLE hd);
int keybox_search_reset (KEYBOX_HANDLE hd);
int keybox_search (KEYBOX_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
int keybox_rebuild_cache (void *);

View File

@ -28,10 +28,15 @@ BUILT_SOURCES = errors.c
gpgsm_SOURCES = \
gpgsm.c gpgsm.h \
util.h misc.c errors.c \
keydb.c keydb.h \
server.c \
fingerprint.c \
certdump.c \
certcheck.c \
certpath.c \
import.c
gpgsm_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a \
gpgsm_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a ../kbx/libkeybox.a \
../../libksba/src/.libs/libksba.a \
../../libgcrypt/src/.libs/libgcrypt.so.1

131
sm/certchain.c Normal file
View File

@ -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;
}

156
sm/certcheck.c Normal file
View File

@ -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);
}

131
sm/certdump.c Normal file
View File

@ -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);
}

131
sm/certpath.c Normal file
View File

@ -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;
}

104
sm/fingerprint.c Normal file
View File

@ -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;
}

View File

@ -29,7 +29,9 @@
#include <gcrypt.h>
#include "gpgsm.h"
#include "../assuan/assuan.h" /* malloc hooks */
#include "../kbx/keybox.h" /* malloc hooks */
#include "i18n.h"
#include "keydb.h"
enum cmd_and_opt_values {
aNull = 0,
@ -441,7 +443,7 @@ set_debug(void)
{
if (opt.debug & DBG_MPI_VALUE)
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2);
if (opt.debug & DBG_CIPHER_VALUE )
if (opt.debug & DBG_CRYPTO_VALUE )
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
}
@ -562,8 +564,9 @@ main ( int argc, char **argv)
Now we are now working under our real uid
*/
ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
/* ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );*/
keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
if (default_config )
configname = make_filename (opt.homedir, "gpgsm.conf", NULL);
@ -831,12 +834,10 @@ main ( int argc, char **argv)
if (!cmd && opt.fingerprint && !with_fpr)
set_cmd (&cmd, aListKeys);
#if 0 /* fixme */
if (!nrings && default_keyring) /* add default ring */
add_keyblock_resource ("pubcerts.gpg", 0, 0);
if (!nrings && default_keyring) /* add default keybox */
keydb_add_resource ("pubcerts.kbx", 0, 0);
for (sl = nrings; sl; sl = sl->next)
add_keyblock_resource( sl->d, 0, 0 );
#endif
keydb_add_resource (sl->d, 0, 0);
FREE_STRLIST(nrings);
fname = argc? *argv : NULL;

View File

@ -21,6 +21,7 @@
#ifndef GPGSM_H
#define GPGSM_H
#include <ksba.h>
#include "util.h"
/* Error numbers */
@ -31,10 +32,15 @@ enum {
GPGSM_Out_Of_Core = 2,
GPGSM_Invalid_Value = 3,
GPGSM_IO_Error = 4,
GPGSM_Resource_Limit = 5,
GPGSM_Internal_Error = 6,
GPGSM_Bad_Certificate = 7,
GPGSM_Bad_Certificate_Path = 8,
GPGSM_Missing_Certificate = 9,
};
#define MAX_DIGEST_LEN 24
/* A large struct name "opt" to keep global flags */
struct {
@ -77,14 +83,14 @@ struct {
#define DBG_X509_VALUE 1 /* debug x.509 data reading/writing */
#define DBG_MPI_VALUE 2 /* debug mpi details */
#define DBG_CIPHER_VALUE 4 /* debug cipher handling */
#define DBG_CRYPTO_VALUE 4 /* debug low level crypto */
#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */
#define DBG_CACHE_VALUE 64 /* debug the caching */
#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
#define DBG_HASHING_VALUE 512 /* debug hashing operations */
#define DBG_X509 (opt.debug & DBG_X509_VALUE)
#define DBG_CIPHER (opt.debug & DBG_CIPHER_VALUE)
#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE)
#define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE)
#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
@ -95,8 +101,31 @@ void gpgsm_exit (int rc);
/*-- server.c --*/
void gpgsm_server (void);
/*-- fingerprint --*/
char *gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len);
char *gpgsm_get_fingerprint_string (KsbaCert cert, int algo);
/*-- certdump.c --*/
void gpgsm_dump_cert (KsbaCert cert);
/*-- certcheck.c --*/
int gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert);
/*-- certpath.c --*/
int gpgsm_validate_path (KsbaCert cert);
/*-- import.c --*/
int gpgsm_import (int in_fd);
/*-- errors.c (built) --*/
const char *gpgsm_strerror (int err);
#endif /*GPGSM_H*/

View File

@ -31,6 +31,8 @@
#include <ksba.h>
#include "gpgsm.h"
#include "keydb.h"
#include "i18n.h"
struct reader_cb_parm_s {
FILE *fp;
@ -68,199 +70,31 @@ reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
static void
print_integer (unsigned char *p)
store_cert (KsbaCert cert)
{
unsigned long len;
KEYDB_HANDLE kh;
int rc;
if (!p)
fputs ("none", stdout);
else
kh = keydb_new (0);
if (!kh)
{
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));
log_error (_("failed to allocated keyDB handle\n"));
return;
}
rc = keydb_locate_writable (kh, 0);
if (rc)
log_error (_("error finding writable keyDB: %s\n"), gpgsm_strerror (rc));
gcry_md_start_debug (md, "cert");
rc = ksba_cert_hash (cert, gcry_md_write, md);
rc = keydb_insert_cert (kh, cert);
if (rc)
{
log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc));
gcry_md_close (md);
return;
log_error (_("error storing certificate: %s\n"), gpgsm_strerror (rc));
}
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));
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));
/* 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));
if (rc)
{
log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc));
return;
}
/*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;
}

View File

@ -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;
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,22 +107,24 @@ 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 */
else
@ -138,7 +132,7 @@ keydb_add_resource (const char *url, int force, int secret)
}
else /* maybe empty: assume ring */
rt = KEYDB_RESOURCE_TYPE_KEYBOX;
fclose( fp );
fclose (fp2);
}
else /* no file yet: create ring */
rt = KEYDB_RESOURCE_TYPE_KEYBOX;
@ -147,27 +141,28 @@ keydb_add_resource (const char *url, int force, int secret)
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++;
@ -291,8 +287,10 @@ keydb_release (KEYDB_HANDLE hd)
active_handles--;
unlock_all (hd);
for (i=0; i < hd->used; i++) {
switch (hd->active[i].type) {
for (i=0; i < hd->used; i++)
{
switch (hd->active[i].type)
{
case KEYDB_RESOURCE_TYPE_NONE:
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
@ -301,18 +299,16 @@ keydb_release (KEYDB_HANDLE hd)
}
}
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)
{
@ -329,7 +325,8 @@ keydb_get_resource_name (KEYDB_HANDLE hd)
else
idx = 0;
switch (hd->active[idx].type) {
switch (hd->active[idx].type)
{
case KEYDB_RESOURCE_TYPE_NONE:
s = NULL;
break;
@ -342,30 +339,35 @@ keydb_get_resource_name (KEYDB_HANDLE hd)
}
static int
lock_all (KEYDB_HANDLE hd)
{
int i, rc = 0;
for (i=0; !rc && i < hd->used; i++) {
switch (hd->active[i].type) {
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);
/* 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;
}
}
@ -384,19 +386,22 @@ unlock_all (KEYDB_HANDLE hd)
if (!hd->locked)
return;
for (i=hd->used-1; i >= 0; i--) {
switch (hd->active[i].type) {
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);
/* fixme: keybox_lock (hd->active[i].u.kr, 0);*/
break;
}
}
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,34 +505,75 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
return rc;
}
#endif /*disabled code*/
/*
* The current keyblock will be deleted.
*/
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_delete_keyblock (KEYDB_HANDLE hd)
keydb_get_cert (KEYDB_HANDLE hd, KsbaCert *r_cert)
{
int rc = -1;
int rc = 0;
if (!hd)
return G10ERR_INV_ARG;
return GPGSM_Invalid_Value;
if ( hd->found < 0 || hd->found >= hd->used)
return -1; /* nothing found */
if( keydbopt.dry_run )
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;
}
/*
* Insert a new Certificate into one of the resources.
*/
int
keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert)
{
int rc = -1;
int idx;
char digest[20];
if (!hd)
return GPGSM_Invalid_Value;
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;
switch (hd->active[hd->found].type) {
gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
switch (hd->active[idx].type)
{
case KEYDB_RESOURCE_TYPE_NONE:
rc = G10ERR_GENERAL; /* oops */
rc = GPGSM_General_Error;
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
rc = keybox_delete_keyblock (hd->active[hd->found].u.kr);
rc = keybox_insert_cert (hd->active[idx].u.kr, cert, digest);
break;
}
@ -535,6 +581,81 @@ keydb_delete_keyblock (KEYDB_HANDLE hd)
return rc;
}
/* 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);
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,7 +668,7 @@ 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)
@ -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;
}
}
@ -607,13 +728,15 @@ keydb_search_reset (KEYDB_HANDLE hd)
int i, rc = 0;
if (!hd)
return G10ERR_INV_ARG;
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) {
for (i=0; !rc && i < hd->used; i++)
{
switch (hd->active[i].type)
{
case KEYDB_RESOURCE_TYPE_NONE:
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
@ -621,10 +744,10 @@ keydb_search_reset (KEYDB_HANDLE hd)
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.
@ -635,10 +758,12 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
int rc = -1;
if (!hd)
return G10ERR_INV_ARG;
return GPGSM_Invalid_Value;
while (rc == -1 && hd->current >= 0 && hd->current < hd->used) {
switch (hd->active[hd->current].type) {
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;
@ -683,8 +808,8 @@ keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
desc.u.kid[0] = kid[0];
desc.u.kid[1] = kid[1];
/* desc.u.kid[0] = kid[0]; */
/* desc.u.kid[1] = kid[1]; */
return keydb_search (hd, &desc, 1);
}
@ -695,9 +820,37 @@ keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_FPR;
memcpy (desc.u.fpr, fpr, MAX_FINGERPRINT_LEN);
memcpy (desc.u.fpr, fpr, 20);
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;
}

View File

@ -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*/

View File

@ -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;
}

View File

@ -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*/