mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-11 22:01:08 +02:00
We have reached a state where we are able to import certs and
check the certification path.
This commit is contained in:
parent
6dec3847d8
commit
90d060c199
@ -27,13 +27,14 @@ noinst_LIBRARIES = libkeybox.a
|
|||||||
bin_PROGRAMS = kbxutil
|
bin_PROGRAMS = kbxutil
|
||||||
|
|
||||||
common_sources = \
|
common_sources = \
|
||||||
keybox.h \
|
keybox.h keybox-defs.h keybox-search-desc.h \
|
||||||
keybox-defs.h \
|
|
||||||
keybox-util.c \
|
keybox-util.c \
|
||||||
keybox-errors.c \
|
keybox-errors.c \
|
||||||
keybox-init.c \
|
keybox-init.c \
|
||||||
keybox-blob.c \
|
keybox-blob.c \
|
||||||
keybox-file.c \
|
keybox-file.c \
|
||||||
|
keybox-search.c \
|
||||||
|
keybox-update.c \
|
||||||
keybox-dump.c
|
keybox-dump.c
|
||||||
|
|
||||||
|
|
||||||
@ -41,7 +42,8 @@ libkeybox_a_SOURCES = $(common_sources)
|
|||||||
|
|
||||||
kbxutil_SOURCES = kbxutil.c $(common_sources)
|
kbxutil_SOURCES = kbxutil.c $(common_sources)
|
||||||
kbxutil_LDADD = ../jnlib/libjnlib.a \
|
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
|
keybox-errors.c : keybox.h mkerrors
|
||||||
$(srcdir)/mkerrors < $(srcdir)/keybox.h > keybox-errors.c
|
$(srcdir)/mkerrors < $(srcdir)/keybox.h > keybox-errors.c
|
||||||
|
@ -234,8 +234,9 @@ main( int argc, char **argv )
|
|||||||
/*create_dotlock(NULL); register locking cleanup */
|
/*create_dotlock(NULL); register locking cleanup */
|
||||||
i18n_init();
|
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);
|
keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
|
||||||
|
ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
|
||||||
|
|
||||||
|
|
||||||
pargs.argc = &argc;
|
pargs.argc = &argc;
|
||||||
|
@ -39,25 +39,29 @@ The first record of a plain KBX file has a special format:
|
|||||||
byte pgp_completes ditto.
|
byte pgp_completes ditto.
|
||||||
byte pgp_cert_depth 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)
|
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)
|
byte version number of this blob type (1)
|
||||||
u16 Blob flags
|
u16 Blob flags
|
||||||
bit 0 = contains secret key material
|
bit 0 = contains secret key material
|
||||||
|
|
||||||
u32 offset to the OpenPGP keyblock
|
u32 offset to the OpenPGP keyblock or X509 DER encoded certificate
|
||||||
u32 length of the keyblock
|
u32 ant its length
|
||||||
u16 number of keys (at least 1!)
|
u16 number of keys (at least 1!) [X509: always 1]
|
||||||
u16 size of additional key information
|
u16 size of additional key information
|
||||||
n times:
|
n times:
|
||||||
b20 The keys fingerprint
|
b20 The keys fingerprint
|
||||||
(fingerprints are always 20 bytes, MD5 left padded with zeroes)
|
(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)
|
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
|
u16 special key flags
|
||||||
bit 0 =
|
bit 0 =
|
||||||
u16 reserved
|
u16 reserved
|
||||||
|
u16 size of serialnumber(may be zero)
|
||||||
|
n u16 (see above) bytes of serial number
|
||||||
u16 number of user IDs
|
u16 number of user IDs
|
||||||
u16 size of additional user ID information
|
u16 size of additional user ID information
|
||||||
n times:
|
n times:
|
||||||
@ -67,6 +71,8 @@ The OpenPGP KBX Blob looks like this:
|
|||||||
bit 0 =
|
bit 0 =
|
||||||
byte validity
|
byte validity
|
||||||
byte reserved
|
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 number of signatures
|
||||||
u16 size of signature information (4)
|
u16 size of signature information (4)
|
||||||
u32 expiration time of signature with some special values:
|
u32 expiration time of signature with some special values:
|
||||||
@ -75,8 +81,8 @@ The OpenPGP KBX Blob looks like this:
|
|||||||
0x00000002 = bad signature
|
0x00000002 = bad signature
|
||||||
0x10000000 = valid and expires at some date in 1978.
|
0x10000000 = valid and expires at some date in 1978.
|
||||||
0xffffffff = valid and does not expire
|
0xffffffff = valid and does not expire
|
||||||
u8 assigned ownertrust
|
u8 assigned ownertrust [X509: no used]
|
||||||
u8 all_validity
|
u8 all_validity [X509: no used]
|
||||||
u16 reserved
|
u16 reserved
|
||||||
u32 recheck_after
|
u32 recheck_after
|
||||||
u32 Newest timestamp in the keyblock (useful for KS syncronsiation?)
|
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.
|
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 <assert.h>
|
||||||
#include <gcrypt.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"
|
#include "keybox-defs.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* special values of the signature status */
|
/* special values of the signature status */
|
||||||
#define SF_NONE(a) ( !(a) )
|
#define SF_NONE(a) ( !(a) )
|
||||||
#define SF_NOKEY(a) ((a) & (1<<0))
|
#define SF_NOKEY(a) ((a) & (1<<0))
|
||||||
@ -125,16 +142,17 @@ struct membuf {
|
|||||||
/* #endif */
|
/* #endif */
|
||||||
|
|
||||||
struct keyboxblob_key {
|
struct keyboxblob_key {
|
||||||
char fpr[20];
|
char fpr[20];
|
||||||
u32 off_kid;
|
u32 off_kid;
|
||||||
ulong off_kid_addr;
|
ulong off_kid_addr;
|
||||||
u16 flags;
|
u16 flags;
|
||||||
};
|
};
|
||||||
struct keyboxblob_uid {
|
struct keyboxblob_uid {
|
||||||
ulong off_addr;
|
ulong off_addr;
|
||||||
u32 len;
|
char *name; /* used only with x509 */
|
||||||
u16 flags;
|
u32 len;
|
||||||
byte validity;
|
u16 flags;
|
||||||
|
byte validity;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct keyid_list {
|
struct keyid_list {
|
||||||
@ -155,6 +173,8 @@ struct keyboxblob {
|
|||||||
size_t bloblen;
|
size_t bloblen;
|
||||||
|
|
||||||
/* stuff used only by keybox_create_blob */
|
/* stuff used only by keybox_create_blob */
|
||||||
|
unsigned char *serial;
|
||||||
|
size_t seriallen;
|
||||||
int nkeys;
|
int nkeys;
|
||||||
struct keyboxblob_key *keys;
|
struct keyboxblob_key *keys;
|
||||||
int nuids;
|
int nuids;
|
||||||
@ -162,9 +182,11 @@ struct keyboxblob {
|
|||||||
int nsigs;
|
int nsigs;
|
||||||
u32 *sigs;
|
u32 *sigs;
|
||||||
struct fixup_list *fixups;
|
struct fixup_list *fixups;
|
||||||
|
int fixup_out_of_core;
|
||||||
|
|
||||||
struct keyid_list *temp_kids;
|
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);
|
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
|
Some wrappers
|
||||||
@ -396,16 +440,7 @@ pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock)
|
|||||||
int n;
|
int n;
|
||||||
u32 kbstart = a->len;
|
u32 kbstart = a->len;
|
||||||
|
|
||||||
{
|
add_fixup (blob, kbstart);
|
||||||
struct fixup_list *fl = xtrycalloc(1, sizeof *fl );
|
|
||||||
|
|
||||||
if (!fl)
|
|
||||||
return KEYBOX_Out_Of_Core;
|
|
||||||
fl->off = 8;
|
|
||||||
fl->val = kbstart;
|
|
||||||
fl->next = blob->fixups;
|
|
||||||
blob->fixups = fl;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (n = 0, node = keyblock; node; node = node->next)
|
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;
|
PKT_user_id *u = node->pkt->pkt.user_id;
|
||||||
/* build_packet has set the offset of the name into u ;
|
/* build_packet has set the offset of the name into u ;
|
||||||
* now we can do the fixup */
|
* now we can do the fixup */
|
||||||
struct fixup_list *fl = xcalloc(1, sizeof *fl ); /* fixme */
|
add_fixup (blob, blob->uids[n].off_addr, u->stored_at);
|
||||||
fl->off = blob->uids[n].off_addr;
|
|
||||||
fl->val = u->stored_at;
|
|
||||||
fl->next = blob->fixups;
|
|
||||||
blob->fixups = fl;
|
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert (n == blob->nuids);
|
assert (n == blob->nuids);
|
||||||
|
|
||||||
{
|
add_fixup (blob, a->len - kbstart);
|
||||||
struct fixup_list *fl = xcalloc(1, sizeof *fl ); /* fixme */
|
|
||||||
|
|
||||||
fl->off = 12;
|
|
||||||
fl->val = a->len - kbstart;
|
|
||||||
fl->next = blob->fixups;
|
|
||||||
blob->fixups = fl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*KEYBOX_WITH_OPENPGP*/
|
#endif /*KEYBOX_WITH_OPENPGP*/
|
||||||
|
|
||||||
|
|
||||||
@ -450,6 +473,27 @@ pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock)
|
|||||||
X.509 specific stuff
|
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*/
|
#endif /*KEYBOX_WITH_X509*/
|
||||||
|
|
||||||
/* Write a stored keyID out to the buffer */
|
/* 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, 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, blob->nuids );
|
||||||
put16 ( a, 4 + 4 + 2 + 1 + 1 ); /* size of uid info */
|
put16 ( a, 4 + 4 + 2 + 1 + 1 ); /* size of uid info */
|
||||||
for (i=0; i < blob->nuids; i++)
|
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 */
|
put32 ( a, 0 ); /* size of reserved space */
|
||||||
/* reserved space (which is currently of size 0) */
|
/* reserved space (which is currently of size 0) */
|
||||||
|
|
||||||
/* We need to store the keyids for all pgp v3 keys because those key
|
/* space where we write keyIDs and and other stuff so that the
|
||||||
IDs are not part of the fingerprint. While we are doing that, we
|
pointers can actually point to somewhere */
|
||||||
fixup all the keyID offsets */
|
if (blobtype == BLOBTYPE_PGP)
|
||||||
for (i=0; i < blob->nkeys; i++ )
|
|
||||||
{
|
{
|
||||||
struct fixup_list *fl = xtrycalloc(1, sizeof *fl );
|
/* 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
|
||||||
if (!fl)
|
fixup all the keyID offsets */
|
||||||
return KEYBOX_Out_Of_Core;
|
for (i=0; i < blob->nkeys; i++ )
|
||||||
|
{
|
||||||
fl->off = blob->keys[i].off_kid_addr;
|
if (blob->keys[i].off_kid)
|
||||||
fl->next = blob->fixups;
|
{ /* this is a v3 one */
|
||||||
blob->fixups = fl;
|
add_fixup (blob, blob->keys[i].off_kid_addr, a->len);
|
||||||
|
write_stored_kid (blob, blob->keys[i].off_kid);
|
||||||
if (blob->keys[i].off_kid)
|
}
|
||||||
{ /* this is a v3 one */
|
else
|
||||||
fl->val = a->len;
|
{ /* the better v4 key IDs - just store an offset 8 bytes back */
|
||||||
write_stored_kid (blob, blob->keys[i].off_kid);
|
add_fixup (blob, blob->keys[i].off_kid_addr,
|
||||||
}
|
blob->keys[i].off_kid_addr - 8);
|
||||||
else
|
}
|
||||||
{ /* the better v4 key IDs - just store an offset 8 bytes back */
|
}
|
||||||
fl->val = 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,25 +644,21 @@ create_blob_finish (KEYBOXBLOB blob)
|
|||||||
|
|
||||||
/* write a placeholder for the checksum */
|
/* write a placeholder for the checksum */
|
||||||
for (i = 0; i < 16; i++ )
|
for (i = 0; i < 16; i++ )
|
||||||
put32 (a, 0);
|
put32 (a, 0); /* Hmmm: why put32() ?? */
|
||||||
|
|
||||||
/* get the memory area */
|
/* get the memory area */
|
||||||
p = a->buf;
|
p = get_membuf (a, &n);
|
||||||
n = a->len;
|
if (!p)
|
||||||
|
return KEYBOX_Out_Of_Core;
|
||||||
assert (n >= 20);
|
assert (n >= 20);
|
||||||
|
|
||||||
/* fixup the length */
|
/* fixup the length */
|
||||||
{
|
add_fixup (blob, 0, n);
|
||||||
struct fixup_list *fl = xtrycalloc(1, sizeof *fl);
|
|
||||||
if (!fl)
|
|
||||||
return KEYBOX_Out_Of_Core;
|
|
||||||
fl->off = 0;
|
|
||||||
fl->val = n;
|
|
||||||
fl->next = blob->fixups;
|
|
||||||
blob->fixups = fl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do the fixups */
|
/* do the fixups */
|
||||||
|
if (blob->fixup_out_of_core)
|
||||||
|
return KEYBOX_Out_Of_Core;
|
||||||
|
|
||||||
{
|
{
|
||||||
struct fixup_list *fl;
|
struct fixup_list *fl;
|
||||||
for (fl = blob->fixups; fl; fl = fl->next)
|
for (fl = blob->fixups; fl; fl = fl->next)
|
||||||
@ -680,7 +735,8 @@ _keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock)
|
|||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
init_membuf (blob->buf, 1024);
|
init_membuf (&blob->bufbuf, 1024);
|
||||||
|
blob->buf = &blob->bufbuf;
|
||||||
rc = create_blob_header (blob, BLOBTYPE_OPENPGP);
|
rc = create_blob_header (blob, BLOBTYPE_OPENPGP);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -711,6 +767,101 @@ _keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock)
|
|||||||
}
|
}
|
||||||
#endif /*KEYBOX_WITH_OPENPGP*/
|
#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
|
int
|
||||||
@ -732,11 +883,14 @@ _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen)
|
|||||||
void
|
void
|
||||||
_keybox_release_blob (KEYBOXBLOB blob)
|
_keybox_release_blob (KEYBOXBLOB blob)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
if (!blob)
|
if (!blob)
|
||||||
return;
|
return;
|
||||||
/* if (blob->buf) */
|
/* hmmm: release membuf here?*/
|
||||||
/* iobuf_cancel( blob->buf ); */
|
|
||||||
xfree (blob->keys );
|
xfree (blob->keys );
|
||||||
|
xfree (blob->serial);
|
||||||
|
for (i=0; i < blob->nuids; i++)
|
||||||
|
xfree (blob->uids[i].name);
|
||||||
xfree (blob->uids );
|
xfree (blob->uids );
|
||||||
xfree (blob->sigs );
|
xfree (blob->sigs );
|
||||||
xfree (blob->blob );
|
xfree (blob->blob );
|
||||||
@ -751,5 +905,3 @@ _keybox_get_blob_image ( KEYBOXBLOB blob, size_t *n )
|
|||||||
*n = blob->bloblen;
|
*n = blob->bloblen;
|
||||||
return blob->blob;
|
return blob->blob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,6 +41,8 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct keyboxblob *KEYBOXBLOB;
|
||||||
|
|
||||||
|
|
||||||
typedef struct keybox_name *KB_NAME;
|
typedef struct keybox_name *KB_NAME;
|
||||||
typedef struct keybox_name const * CONST_KB_NAME;
|
typedef struct keybox_name const * CONST_KB_NAME;
|
||||||
@ -56,16 +58,13 @@ struct keybox_name {
|
|||||||
|
|
||||||
|
|
||||||
struct keybox_handle {
|
struct keybox_handle {
|
||||||
CONST_KB_NAME resource;
|
CONST_KB_NAME kb;
|
||||||
int secret; /* this is for a secret keybox */
|
int secret; /* this is for a secret keybox */
|
||||||
|
FILE *fp;
|
||||||
|
int eof;
|
||||||
|
int error;
|
||||||
struct {
|
struct {
|
||||||
CONST_KB_NAME kb;
|
KEYBOXBLOB blob;
|
||||||
/*IOBUF iobuf;*/
|
|
||||||
int eof;
|
|
||||||
int error;
|
|
||||||
} current;
|
|
||||||
struct {
|
|
||||||
CONST_KB_NAME kb;
|
|
||||||
off_t offset;
|
off_t offset;
|
||||||
size_t pk_no;
|
size_t pk_no;
|
||||||
size_t uid_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 --*/
|
/*-- 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);
|
int _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen);
|
||||||
void _keybox_release_blob (KEYBOXBLOB blob);
|
void _keybox_release_blob (KEYBOXBLOB blob);
|
||||||
const char *_keybox_get_blob_image (KEYBOXBLOB blob, size_t *n);
|
const char *_keybox_get_blob_image (KEYBOXBLOB blob, size_t *n);
|
||||||
|
|
||||||
/*-- keybox-file.c --*/
|
/*-- keybox-file.c --*/
|
||||||
int _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp);
|
int _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp);
|
||||||
|
int _keybox_write_blob (KEYBOXBLOB blob, FILE *fp);
|
||||||
|
|
||||||
/*-- keybox-dump.c --*/
|
/*-- keybox-dump.c --*/
|
||||||
int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp);
|
int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp);
|
||||||
|
@ -46,6 +46,35 @@ get16 (const byte *buffer)
|
|||||||
return a;
|
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
|
static int
|
||||||
dump_header_blob (const byte *buffer, size_t length, FILE *fp)
|
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 nuids, uidinfolen;
|
||||||
ulong nsigs, siginfolen;
|
ulong nsigs, siginfolen;
|
||||||
ulong rawdata_off, rawdata_len;
|
ulong rawdata_off, rawdata_len;
|
||||||
|
ulong nserial;
|
||||||
const byte *p;
|
const byte *p;
|
||||||
|
|
||||||
buffer = _keybox_get_blob_image (blob, &length);
|
buffer = _keybox_get_blob_image (blob, &length);
|
||||||
@ -128,19 +158,33 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
|
|||||||
int i;
|
int i;
|
||||||
ulong kidoff, kflags;
|
ulong kidoff, kflags;
|
||||||
|
|
||||||
fprintf (fp, "Key-%lu-Fpr: ", n );
|
fprintf (fp, "Key-Fpr[%lu]: ", n );
|
||||||
for (i=0; i < 20; i++ )
|
for (i=0; i < 20; i++ )
|
||||||
fprintf (fp, "%02X", p[i]);
|
fprintf (fp, "%02X", p[i]);
|
||||||
kidoff = get32 (p + 20);
|
kidoff = get32 (p + 20);
|
||||||
fprintf (fp, "\nKey-%lu-Kid-Off: %lu\n", n, kidoff );
|
fprintf (fp, "\nKey-Kid-Off[%lu]: %lu\n", n, kidoff );
|
||||||
fprintf (fp, "Key-%lu-Kid: ", n );
|
fprintf (fp, "Key-Kid[%lu]: ", n );
|
||||||
/* fixme: check bounds */
|
/* fixme: check bounds */
|
||||||
for (i=0; i < 8; i++ )
|
for (i=0; i < 8; i++ )
|
||||||
fprintf (fp, "%02X", buffer[kidoff+i] );
|
fprintf (fp, "%02X", buffer[kidoff+i] );
|
||||||
kflags = get16 (p + 24 );
|
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);
|
nuids = get16 (p);
|
||||||
fprintf (fp, "Uid-Count: %lu\n", nuids );
|
fprintf (fp, "Uid-Count: %lu\n", nuids );
|
||||||
uidinfolen = get16 (p + 2);
|
uidinfolen = get16 (p + 2);
|
||||||
@ -153,14 +197,42 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
|
|||||||
|
|
||||||
uidoff = get32( p );
|
uidoff = get32( p );
|
||||||
uidlen = get32( p+4 );
|
uidlen = get32( p+4 );
|
||||||
fprintf (fp, "Uid-%lu-Off: %lu\n", n, uidoff );
|
if (type == BLOBTYPE_X509 && !n)
|
||||||
fprintf (fp, "Uid-%lu-Len: %lu\n", n, uidlen );
|
{
|
||||||
fprintf (fp, "Uid-%lu: \"", n );
|
fprintf (fp, "Issuer-Off: %lu\n", uidoff );
|
||||||
/*print_string (fp, buffer+uidoff, uidlen, '\"');*/
|
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);
|
fputs ("\"\n", fp);
|
||||||
uflags = get16 (p + 8);
|
uflags = get16 (p + 8);
|
||||||
fprintf (fp, "Uid-%lu-Flags: %04lX\n", n, uflags );
|
if (type == BLOBTYPE_X509 && !n)
|
||||||
fprintf (fp, "Uid-%lu-Validity: %d\n", n, p[10] );
|
{
|
||||||
|
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);
|
nsigs = get16 (p);
|
||||||
@ -174,7 +246,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
|
|||||||
ulong sflags;
|
ulong sflags;
|
||||||
|
|
||||||
sflags = get32 (p);
|
sflags = get32 (p);
|
||||||
fprintf (fp, "Sig-%lu-Expire: ", n );
|
fprintf (fp, "Sig-Expire[%lu]: ", n );
|
||||||
if (!sflags)
|
if (!sflags)
|
||||||
fputs ("[not checked]", fp);
|
fputs ("[not checked]", fp);
|
||||||
else if (sflags == 1 )
|
else if (sflags == 1 )
|
||||||
|
@ -32,6 +32,12 @@ keybox_strerror (KeyboxError err)
|
|||||||
case KEYBOX_File_Error: s="file error"; break;
|
case KEYBOX_File_Error: s="file error"; break;
|
||||||
case KEYBOX_Blob_Too_Short: s="blob too short"; break;
|
case KEYBOX_Blob_Too_Short: s="blob too short"; break;
|
||||||
case KEYBOX_Blob_Too_Large: s="blob too large"; 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;
|
default: sprintf (buf, "ec=%d", err ); s=buf; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#include "keybox-defs.h"
|
#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
|
int
|
||||||
_keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
|
_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;
|
image[0] = c1; image[1] = c2; image[2] = c3; image[3] = c4;
|
||||||
if (fread (image+4, imagelen-4, 1, fp) != 1)
|
if (fread (image+4, imagelen-4, 1, fp) != 1)
|
||||||
{
|
{
|
||||||
|
xfree (image);
|
||||||
return KEYBOX_Read_Error;
|
return KEYBOX_Read_Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = _keybox_new_blob (r_blob, image, imagelen);
|
rc = r_blob? _keybox_new_blob (r_blob, image, imagelen) : 0;
|
||||||
if (rc)
|
if (rc || !r_blob)
|
||||||
xfree (image);
|
xfree (image);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write the block to the current file position */
|
||||||
|
int
|
||||||
|
_keybox_write_blob (KEYBOXBLOB blob, FILE *fp)
|
||||||
void
|
|
||||||
export_as_kbxfile(void)
|
|
||||||
{
|
{
|
||||||
#if 0
|
const char *image;
|
||||||
KBPOS kbpos;
|
size_t length;
|
||||||
KBNODE keyblock = NULL;
|
|
||||||
int rc=0;
|
|
||||||
|
|
||||||
rc = enum_keyblocks_begin( &kbpos, 0 );
|
image = _keybox_get_blob_image (blob, &length);
|
||||||
if( rc ) {
|
if (fwrite (image, length, 1, fp) != 1)
|
||||||
if( rc != -1 )
|
{
|
||||||
log_error("enum_keyblocks(open) failed: %s\n", gpg_errstr(rc) );
|
return KEYBOX_Write_Error;
|
||||||
goto leave;
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,44 +23,47 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "keybox-defs.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
|
Register a filename for plain keybox files. Returns a pointer to be
|
||||||
* be used to create a handles etc or NULL to indicate that it has
|
used to create a handles etc or NULL to indicate that it has already
|
||||||
* already been registered */
|
been registered */
|
||||||
void *
|
void *
|
||||||
keybox_register_file (const char *fname, int secret)
|
keybox_register_file (const char *fname, int secret)
|
||||||
{
|
{
|
||||||
return NULL;
|
KB_NAME kr;
|
||||||
#if 0
|
|
||||||
KB_NAME kr;
|
|
||||||
|
|
||||||
if (active_handles)
|
for (kr=kb_names; kr; kr = kr->next)
|
||||||
BUG (); /* We don't allow that */
|
{
|
||||||
|
if ( !compare_filenames (kr->fname, fname) )
|
||||||
for (kr=kb_names; kr; kr = kr->next) {
|
return NULL; /* already registered */
|
||||||
if ( !compare_filenames (kr->fname, fname) )
|
|
||||||
return NULL; /* already registered */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kr = m_alloc (sizeof *kr + strlen (fname));
|
kr = xtrymalloc (sizeof *kr + strlen (fname));
|
||||||
strcpy (kr->fname, fname);
|
if (!kr)
|
||||||
kr->secret = !!secret;
|
return NULL;
|
||||||
kr->lockhd = NULL;
|
strcpy (kr->fname, fname);
|
||||||
kr->is_locked = 0;
|
kr->secret = !!secret;
|
||||||
kr->did_full_scan = 0;
|
/* kr->lockhd = NULL;*/
|
||||||
/* keep a list of all issued pointers */
|
kr->is_locked = 0;
|
||||||
kr->next = kb_names;
|
kr->did_full_scan = 0;
|
||||||
kb_names = kr;
|
/* 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 (); */
|
||||||
|
|
||||||
/* create the offset table the first time a function here is used */
|
return kr;
|
||||||
if (!kb_offtbl)
|
|
||||||
kb_offtbl = new_offset_hash_table ();
|
|
||||||
|
|
||||||
return kr;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -70,4 +73,48 @@ keybox_is_writable (void *token)
|
|||||||
|
|
||||||
return r? !access (r->fname, W_OK) : 0;
|
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
69
kbx/keybox-search-desc.h
Normal 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*/
|
@ -25,134 +25,417 @@
|
|||||||
|
|
||||||
#include "keybox-defs.h"
|
#include "keybox-defs.h"
|
||||||
|
|
||||||
|
static ulong
|
||||||
|
get32 (const byte *buffer)
|
||||||
|
{
|
||||||
|
ulong a;
|
||||||
|
a = *buffer << 24;
|
||||||
|
a |= buffer[1] << 16;
|
||||||
|
a |= buffer[2] << 8;
|
||||||
|
a |= buffer[3];
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
/****************
|
static ulong
|
||||||
* Check whether the given fingerprint (20 bytes) is in the
|
get16 (const byte *buffer)
|
||||||
* given keyblob. fpr is always 20 bytes.
|
{
|
||||||
* Return: 0 = found
|
ulong a;
|
||||||
* -1 = not found
|
a = *buffer << 8;
|
||||||
other = error (fixme: do not always reurn gpgerr_general)
|
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
|
int
|
||||||
keybox_blob_has_fpr ( KEYBOXBLOB blob, const byte *fpr )
|
keybox_get_cert (KEYBOX_HANDLE hd, KsbaCert *r_cert)
|
||||||
{
|
{
|
||||||
ulong n, nkeys, keyinfolen;
|
const unsigned char *buffer;
|
||||||
const byte *p, *pend;
|
size_t length;
|
||||||
byte *buffer = blob->blob;
|
size_t cert_off, cert_len;
|
||||||
size_t buflen = blob->bloblen;
|
KsbaReader reader = NULL;
|
||||||
|
KsbaCert cert = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if ( buflen < 40 )
|
if (!hd)
|
||||||
return GPGERR_GENERAL; /* blob too short */
|
return KEYBOX_Invalid_Value;
|
||||||
n = get32( buffer );
|
if (!hd->found.blob)
|
||||||
if ( n > buflen )
|
return KEYBOX_Nothing_Found;
|
||||||
return GPGERR_GENERAL; /* blob larger than announced length */
|
|
||||||
buflen = n; /* ignore trailing stuff */
|
|
||||||
pend = buffer + n - 1;
|
|
||||||
|
|
||||||
if ( buffer[4] != 2 )
|
if (blob_get_type (hd->found.blob) != BLOBTYPE_X509)
|
||||||
return GPGERR_GENERAL; /* invalid blob type */
|
return KEYBOX_Wrong_Blob_Type;
|
||||||
if ( buffer[5] != 1 )
|
|
||||||
return GPGERR_GENERAL; /* invalid blob format version */
|
|
||||||
|
|
||||||
nkeys = get16( buffer + 16 );
|
buffer = _keybox_get_blob_image (hd->found.blob, &length);
|
||||||
keyinfolen = get16( buffer + 18 );
|
if (length < 40)
|
||||||
p = buffer + 20;
|
return KEYBOX_Blob_Too_Short;
|
||||||
for(n=0; n < nkeys; n++, p += keyinfolen ) {
|
cert_off = get32 (buffer+8);
|
||||||
if ( p+20 > pend )
|
cert_len = get32 (buffer+12);
|
||||||
return GPGERR_GENERAL; /* blob shorter than required */
|
if (cert_off+cert_len > length)
|
||||||
if (!memcmp ( p, fpr, 20 ) )
|
return KEYBOX_Blob_Too_Short;
|
||||||
return 0; /* found */
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
reader = ksba_reader_new ();
|
||||||
* Check whether the given keyID (20 bytes) is in the
|
if (!reader)
|
||||||
* given keyblob.
|
return KEYBOX_Out_Of_Core;
|
||||||
* Return: 0 = found
|
rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
|
||||||
* -1 = not found
|
if (rc)
|
||||||
other = error (fixme: do not always return gpgerr_general)
|
{
|
||||||
*/
|
ksba_reader_release (reader);
|
||||||
int
|
/* fixme: need to map the error codes */
|
||||||
keybox_blob_has_kid ( KEYBOXBLOB blob, const byte *keyidbuf, size_t keyidlen )
|
return KEYBOX_General_Error;
|
||||||
{
|
|
||||||
ulong n, nkeys, keyinfolen, off;
|
|
||||||
const byte *p, *pend;
|
|
||||||
byte *buffer = blob->blob;
|
|
||||||
size_t buflen = blob->bloblen;
|
|
||||||
|
|
||||||
if ( buflen < 40 )
|
|
||||||
return GPGERR_GENERAL; /* blob too short */
|
|
||||||
n = get32( buffer );
|
|
||||||
if ( n > buflen )
|
|
||||||
return GPGERR_GENERAL; /* blob larger than announced length */
|
|
||||||
buflen = n; /* ignore trailing stuff */
|
|
||||||
pend = buffer + n - 1;
|
|
||||||
|
|
||||||
if ( buffer[4] != 2 )
|
|
||||||
return GPGERR_GENERAL; /* invalid blob type */
|
|
||||||
if ( buffer[5] != 1 )
|
|
||||||
return GPGERR_GENERAL; /* invalid blob format version */
|
|
||||||
|
|
||||||
nkeys = get16( buffer + 16 );
|
|
||||||
keyinfolen = get16( buffer + 18 );
|
|
||||||
p = buffer + 20;
|
|
||||||
for(n=0; n < nkeys; n++, p += keyinfolen ) {
|
|
||||||
if ( p+24 > pend )
|
|
||||||
return GPGERR_GENERAL; /* blob shorter than required */
|
|
||||||
off = get32 ( p + 20 );
|
|
||||||
if (keyidlen < 8 ) /* actually keyidlen may either be 4 or 8 */
|
|
||||||
off +=4;
|
|
||||||
if ( off+keyidlen > buflen )
|
|
||||||
return GPGERR_GENERAL; /* offset out of bounds */
|
|
||||||
if ( !memcmp ( buffer+off, keyidbuf, keyidlen ) )
|
|
||||||
return 0; /* found */
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
keybox_blob_has_uid ( KEYBOXBLOB blob,
|
|
||||||
int (*cmp)(const byte *, size_t, void *), void *opaque )
|
|
||||||
{
|
|
||||||
ulong n, nuids, uidinfolen, off, len;
|
|
||||||
const byte *p, *pend;
|
|
||||||
byte *buffer = blob->blob;
|
|
||||||
size_t buflen = blob->bloblen;
|
|
||||||
|
|
||||||
if ( buflen < 40 )
|
|
||||||
return GPGERR_GENERAL; /* blob too short */
|
|
||||||
n = get32( buffer );
|
|
||||||
if ( n > buflen )
|
|
||||||
return GPGERR_GENERAL; /* blob larger than announced length */
|
|
||||||
buflen = n; /* ignore trailing stuff */
|
|
||||||
pend = buffer + n - 1;
|
|
||||||
|
|
||||||
if ( buffer[4] != 2 )
|
|
||||||
return GPGERR_GENERAL; /* invalid blob type */
|
|
||||||
if ( buffer[5] != 1 )
|
|
||||||
return GPGERR_GENERAL; /* invalid blob format version */
|
|
||||||
|
|
||||||
p = buffer + 20 + get16( buffer + 16 ) * get16( buffer + 18 );
|
|
||||||
if ( p+4 > pend )
|
|
||||||
return GPGERR_GENERAL; /* blob shorter than required */
|
|
||||||
|
|
||||||
nuids = get16( p ); p+= 2;
|
|
||||||
uidinfolen = get16( p ); p+=2;
|
|
||||||
for(n=0; n < nuids; n++, p += uidinfolen ) {
|
|
||||||
if ( p+8 > pend )
|
|
||||||
return GPGERR_GENERAL; /* blob shorter than required */
|
|
||||||
off = get32 ( p );
|
|
||||||
len = get32 ( p + 4 );
|
|
||||||
if ( off+len > buflen )
|
|
||||||
return GPGERR_GENERAL; /* offset out of bounds */
|
|
||||||
if ( (*cmp) ( buffer+off, len, opaque ) )
|
|
||||||
return 0; /* found */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
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
390
kbx/keybox-update.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
44
kbx/keybox.h
44
kbx/keybox.h
@ -27,6 +27,8 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "keybox-search-desc.h"
|
||||||
|
|
||||||
#define KEYBOX_WITH_OPENPGP 1
|
#define KEYBOX_WITH_OPENPGP 1
|
||||||
#define KEYBOX_WITH_X509 1
|
#define KEYBOX_WITH_X509 1
|
||||||
|
|
||||||
@ -51,8 +53,13 @@ typedef enum {
|
|||||||
KEYBOX_Write_Error = 6,
|
KEYBOX_Write_Error = 6,
|
||||||
KEYBOX_File_Error = 7,
|
KEYBOX_File_Error = 7,
|
||||||
KEYBOX_Blob_Too_Short = 8,
|
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;
|
} KeyboxError;
|
||||||
|
|
||||||
|
|
||||||
@ -60,24 +67,41 @@ typedef enum {
|
|||||||
typedef struct keybox_handle *KEYBOX_HANDLE;
|
typedef struct keybox_handle *KEYBOX_HANDLE;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-- keybox-init.c --*/
|
/*-- keybox-init.c --*/
|
||||||
void *keybox_register_file (const char *fname, int secret);
|
void *keybox_register_file (const char *fname, int secret);
|
||||||
int keybox_is_writable (void *token);
|
int keybox_is_writable (void *token);
|
||||||
|
|
||||||
|
|
||||||
/*-- --*/
|
|
||||||
|
|
||||||
KEYBOX_HANDLE keybox_new (void *token, int secret);
|
KEYBOX_HANDLE keybox_new (void *token, int secret);
|
||||||
void keybox_release (KEYBOX_HANDLE hd);
|
void keybox_release (KEYBOX_HANDLE hd);
|
||||||
const char *keybox_get_resource_name (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
|
#if 0
|
||||||
|
int keybox_lock (KEYBOX_HANDLE hd, int yes);
|
||||||
int keybox_get_keyblock (KEYBOX_HANDLE hd, KBNODE *ret_kb);
|
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_locate_writable (KEYBOX_HANDLE hd);
|
||||||
int keybox_delete_keyblock (KEYBOX_HANDLE hd);
|
|
||||||
int keybox_search_reset (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_search (KEYBOX_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
|
||||||
int keybox_rebuild_cache (void *);
|
int keybox_rebuild_cache (void *);
|
||||||
|
@ -28,10 +28,15 @@ BUILT_SOURCES = errors.c
|
|||||||
gpgsm_SOURCES = \
|
gpgsm_SOURCES = \
|
||||||
gpgsm.c gpgsm.h \
|
gpgsm.c gpgsm.h \
|
||||||
util.h misc.c errors.c \
|
util.h misc.c errors.c \
|
||||||
|
keydb.c keydb.h \
|
||||||
server.c \
|
server.c \
|
||||||
|
fingerprint.c \
|
||||||
|
certdump.c \
|
||||||
|
certcheck.c \
|
||||||
|
certpath.c \
|
||||||
import.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 \
|
../../libksba/src/.libs/libksba.a \
|
||||||
../../libgcrypt/src/.libs/libgcrypt.so.1
|
../../libgcrypt/src/.libs/libgcrypt.so.1
|
||||||
|
|
||||||
|
131
sm/certchain.c
Normal file
131
sm/certchain.c
Normal 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
156
sm/certcheck.c
Normal 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
131
sm/certdump.c
Normal 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
131
sm/certpath.c
Normal 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
104
sm/fingerprint.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
15
sm/gpgsm.c
15
sm/gpgsm.c
@ -29,7 +29,9 @@
|
|||||||
#include <gcrypt.h>
|
#include <gcrypt.h>
|
||||||
#include "gpgsm.h"
|
#include "gpgsm.h"
|
||||||
#include "../assuan/assuan.h" /* malloc hooks */
|
#include "../assuan/assuan.h" /* malloc hooks */
|
||||||
|
#include "../kbx/keybox.h" /* malloc hooks */
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
#include "keydb.h"
|
||||||
|
|
||||||
enum cmd_and_opt_values {
|
enum cmd_and_opt_values {
|
||||||
aNull = 0,
|
aNull = 0,
|
||||||
@ -441,7 +443,7 @@ set_debug(void)
|
|||||||
{
|
{
|
||||||
if (opt.debug & DBG_MPI_VALUE)
|
if (opt.debug & DBG_MPI_VALUE)
|
||||||
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2);
|
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);
|
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
|
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);
|
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 )
|
if (default_config )
|
||||||
configname = make_filename (opt.homedir, "gpgsm.conf", NULL);
|
configname = make_filename (opt.homedir, "gpgsm.conf", NULL);
|
||||||
@ -831,12 +834,10 @@ main ( int argc, char **argv)
|
|||||||
if (!cmd && opt.fingerprint && !with_fpr)
|
if (!cmd && opt.fingerprint && !with_fpr)
|
||||||
set_cmd (&cmd, aListKeys);
|
set_cmd (&cmd, aListKeys);
|
||||||
|
|
||||||
#if 0 /* fixme */
|
if (!nrings && default_keyring) /* add default keybox */
|
||||||
if (!nrings && default_keyring) /* add default ring */
|
keydb_add_resource ("pubcerts.kbx", 0, 0);
|
||||||
add_keyblock_resource ("pubcerts.gpg", 0, 0);
|
|
||||||
for (sl = nrings; sl; sl = sl->next)
|
for (sl = nrings; sl; sl = sl->next)
|
||||||
add_keyblock_resource( sl->d, 0, 0 );
|
keydb_add_resource (sl->d, 0, 0);
|
||||||
#endif
|
|
||||||
FREE_STRLIST(nrings);
|
FREE_STRLIST(nrings);
|
||||||
|
|
||||||
fname = argc? *argv : NULL;
|
fname = argc? *argv : NULL;
|
||||||
|
35
sm/gpgsm.h
35
sm/gpgsm.h
@ -21,6 +21,7 @@
|
|||||||
#ifndef GPGSM_H
|
#ifndef GPGSM_H
|
||||||
#define GPGSM_H
|
#define GPGSM_H
|
||||||
|
|
||||||
|
#include <ksba.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
/* Error numbers */
|
/* Error numbers */
|
||||||
@ -31,10 +32,15 @@ enum {
|
|||||||
GPGSM_Out_Of_Core = 2,
|
GPGSM_Out_Of_Core = 2,
|
||||||
GPGSM_Invalid_Value = 3,
|
GPGSM_Invalid_Value = 3,
|
||||||
GPGSM_IO_Error = 4,
|
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 */
|
/* A large struct name "opt" to keep global flags */
|
||||||
struct {
|
struct {
|
||||||
@ -77,14 +83,14 @@ struct {
|
|||||||
|
|
||||||
#define DBG_X509_VALUE 1 /* debug x.509 data reading/writing */
|
#define DBG_X509_VALUE 1 /* debug x.509 data reading/writing */
|
||||||
#define DBG_MPI_VALUE 2 /* debug mpi details */
|
#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_MEMORY_VALUE 32 /* debug memory allocation stuff */
|
||||||
#define DBG_CACHE_VALUE 64 /* debug the caching */
|
#define DBG_CACHE_VALUE 64 /* debug the caching */
|
||||||
#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
|
#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
|
||||||
#define DBG_HASHING_VALUE 512 /* debug hashing operations */
|
#define DBG_HASHING_VALUE 512 /* debug hashing operations */
|
||||||
|
|
||||||
#define DBG_X509 (opt.debug & DBG_X509_VALUE)
|
#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_MEMORY (opt.debug & DBG_MEMORY_VALUE)
|
||||||
#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
|
#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
|
||||||
#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
|
#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
|
||||||
@ -95,8 +101,31 @@ void gpgsm_exit (int rc);
|
|||||||
/*-- server.c --*/
|
/*-- server.c --*/
|
||||||
void gpgsm_server (void);
|
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 --*/
|
/*-- import.c --*/
|
||||||
int gpgsm_import (int in_fd);
|
int gpgsm_import (int in_fd);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-- errors.c (built) --*/
|
||||||
|
const char *gpgsm_strerror (int err);
|
||||||
|
|
||||||
|
|
||||||
#endif /*GPGSM_H*/
|
#endif /*GPGSM_H*/
|
||||||
|
202
sm/import.c
202
sm/import.c
@ -31,6 +31,8 @@
|
|||||||
#include <ksba.h>
|
#include <ksba.h>
|
||||||
|
|
||||||
#include "gpgsm.h"
|
#include "gpgsm.h"
|
||||||
|
#include "keydb.h"
|
||||||
|
#include "i18n.h"
|
||||||
|
|
||||||
struct reader_cb_parm_s {
|
struct reader_cb_parm_s {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
@ -68,199 +70,31 @@ reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_integer (unsigned char *p)
|
store_cert (KsbaCert cert)
|
||||||
{
|
{
|
||||||
unsigned long len;
|
KEYDB_HANDLE kh;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (!p)
|
kh = keydb_new (0);
|
||||||
fputs ("none", stdout);
|
if (!kh)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
len = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
|
log_error (_("failed to allocated keyDB handle\n"));
|
||||||
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;
|
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 = keydb_insert_cert (kh, cert);
|
||||||
rc = ksba_cert_hash (cert, gcry_md_write, md);
|
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc));
|
log_error (_("error storing certificate: %s\n"), gpgsm_strerror (rc));
|
||||||
gcry_md_close (md);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
gcry_md_final (md);
|
keydb_release (kh);
|
||||||
|
|
||||||
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));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
gpgsm_import (int in_fd)
|
gpgsm_import (int in_fd)
|
||||||
@ -311,9 +145,8 @@ gpgsm_import (int in_fd)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
print_cert (cert);
|
if ( !gpgsm_validate_path (cert) )
|
||||||
check_selfsigned_cert (cert);
|
store_cert (cert);
|
||||||
|
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
ksba_cert_release (cert);
|
ksba_cert_release (cert);
|
||||||
@ -323,3 +156,4 @@ gpgsm_import (int in_fd)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
555
sm/keydb.c
555
sm/keydb.c
@ -28,19 +28,12 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "gpgsm.h"
|
||||||
#include "options.h"
|
#include "../kbx/keybox.h"
|
||||||
#include "keybox.h"
|
|
||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
static struct {
|
#define DIRSEP_C '/'
|
||||||
const char *homedir;
|
|
||||||
int dry_run;
|
|
||||||
int quiet;
|
|
||||||
int verbose;
|
|
||||||
int preserve_permissions;
|
|
||||||
} keydbopt;
|
|
||||||
|
|
||||||
static int active_handles;
|
static int active_handles;
|
||||||
|
|
||||||
@ -87,25 +80,24 @@ keydb_add_resource (const char *url, int force, int secret)
|
|||||||
{
|
{
|
||||||
static int any_secret, any_public;
|
static int any_secret, any_public;
|
||||||
const char *resname = url;
|
const char *resname = url;
|
||||||
IOBUF iobuf = NULL;
|
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
|
KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
|
||||||
const char *created_fname = NULL;
|
/* const char *created_fname = NULL; */
|
||||||
|
|
||||||
/* Do we have an URL?
|
/* Do we have an URL?
|
||||||
* gnupg-ring:filename := this is a plain keybox
|
* gnupg-ring:filename := this is a plain keybox
|
||||||
* filename := See what is is, but create as plain keybox.
|
* filename := See what is is, but create as plain keybox.
|
||||||
*/
|
*/
|
||||||
if (strlen (resname) > 11) {
|
if (strlen (resname) > 11) {
|
||||||
if (!strncmp( resname, "gnupg-ring:", 11) ) {
|
if (!strncmp( resname, "gnupg-kbx:", 10) ) {
|
||||||
rt = KEYDB_RESOURCE_TYPE_KEYBOX;
|
rt = KEYDB_RESOURCE_TYPE_KEYBOX;
|
||||||
resname += 11;
|
resname += 11;
|
||||||
}
|
}
|
||||||
#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
|
#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
|
||||||
else if (strchr (resname, ':')) {
|
else if (strchr (resname, ':')) {
|
||||||
log_error ("invalid key resource URL `%s'\n", url );
|
log_error ("invalid key resource URL `%s'\n", url );
|
||||||
rc = G10ERR_GENERAL;
|
rc = GPGSM_General_Error;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
#endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
|
#endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
|
||||||
@ -115,59 +107,62 @@ keydb_add_resource (const char *url, int force, int secret)
|
|||||||
if (strchr(resname, DIRSEP_C) )
|
if (strchr(resname, DIRSEP_C) )
|
||||||
filename = make_filename (resname, NULL);
|
filename = make_filename (resname, NULL);
|
||||||
else
|
else
|
||||||
filename = make_filename (keydbopt.homedir, resname, NULL);
|
filename = make_filename (opt.homedir, resname, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
filename = m_strdup (resname);
|
filename = xstrdup (resname);
|
||||||
|
|
||||||
if (!force)
|
if (!force)
|
||||||
force = secret? !any_secret : !any_public;
|
force = secret? !any_secret : !any_public;
|
||||||
|
|
||||||
/* see whether we can determine the filetype */
|
/* see whether we can determine the filetype */
|
||||||
if (rt == KEYDB_RESOURCE_TYPE_NONE) {
|
if (rt == KEYDB_RESOURCE_TYPE_NONE) {
|
||||||
FILE *fp = fopen( filename, "rb" );
|
FILE *fp2 = fopen( filename, "rb" );
|
||||||
|
|
||||||
if (fp) {
|
if (fp2) {
|
||||||
u32 magic;
|
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)
|
if (magic == 0x13579ace || magic == 0xce9a5713)
|
||||||
; /* GDBM magic - no more support */
|
; /* GDBM magic - no more support */
|
||||||
else
|
else
|
||||||
rt = KEYDB_RESOURCE_TYPE_KEYBOX;
|
rt = KEYDB_RESOURCE_TYPE_KEYBOX;
|
||||||
}
|
}
|
||||||
else /* maybe empty: assume ring */
|
else /* maybe empty: assume ring */
|
||||||
rt = KEYDB_RESOURCE_TYPE_KEYBOX;
|
rt = KEYDB_RESOURCE_TYPE_KEYBOX;
|
||||||
fclose( fp );
|
fclose (fp2);
|
||||||
}
|
}
|
||||||
else /* no file yet: create ring */
|
else /* no file yet: create ring */
|
||||||
rt = KEYDB_RESOURCE_TYPE_KEYBOX;
|
rt = KEYDB_RESOURCE_TYPE_KEYBOX;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (rt) {
|
switch (rt) {
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
case KEYDB_RESOURCE_TYPE_NONE:
|
||||||
log_error ("unknown type of key resource `%s'\n", url );
|
log_error ("unknown type of key resource `%s'\n", url );
|
||||||
rc = G10ERR_GENERAL;
|
rc = GPGSM_General_Error;
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
||||||
iobuf = iobuf_open (filename);
|
#if 0
|
||||||
|
fp = fopen (filename);
|
||||||
if (!iobuf && !force) {
|
if (!iobuf && !force) {
|
||||||
rc = G10ERR_OPEN_FILE;
|
rc = G10ERR_OPEN_FILE;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!iobuf) {
|
if (!fp) {
|
||||||
char *last_slash_in_filename;
|
char *last_slash_in_filename;
|
||||||
|
|
||||||
last_slash_in_filename = strrchr (filename, DIRSEP_C);
|
last_slash_in_filename = strrchr (filename, DIRSEP_C);
|
||||||
*last_slash_in_filename = 0;
|
*last_slash_in_filename = 0;
|
||||||
|
|
||||||
if (access(filename, F_OK)) {
|
if (access(filename, F_OK)) {
|
||||||
/* on the first time we try to create the default homedir and
|
/* on the first time we try to create the default
|
||||||
* in this case the process will be terminated, so that on the
|
homedir and in this case the process will be
|
||||||
* next invocation it can read the options file in on startup
|
terminated, so that on the next invocation it can
|
||||||
*/
|
read the options file in on startup */
|
||||||
try_make_homedir (filename);
|
try_make_homedir (filename);
|
||||||
rc = G10ERR_OPEN_FILE;
|
rc = G10ERR_OPEN_FILE;
|
||||||
*last_slash_in_filename = DIRSEP_C;
|
*last_slash_in_filename = DIRSEP_C;
|
||||||
@ -185,7 +180,7 @@ keydb_add_resource (const char *url, int force, int secret)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#ifndef HAVE_DOSISH_SYSTEM
|
#ifndef HAVE_DOSISH_SYSTEM
|
||||||
if (secret && !keydbopt.preserve_permissionws) {
|
if (secret && !opt.preserve_permissionws) {
|
||||||
if (chmod (filename, S_IRUSR | S_IWUSR) ) {
|
if (chmod (filename, S_IRUSR | S_IWUSR) ) {
|
||||||
log_error (_("changing permission of "
|
log_error (_("changing permission of "
|
||||||
" `%s' failed: %s\n"),
|
" `%s' failed: %s\n"),
|
||||||
@ -195,7 +190,7 @@ keydb_add_resource (const char *url, int force, int secret)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!keydbopt.quiet)
|
if (!opt.quiet)
|
||||||
log_info (_("keybox `%s' created\n"), filename);
|
log_info (_("keybox `%s' created\n"), filename);
|
||||||
created_fname = filename;
|
created_fname = filename;
|
||||||
}
|
}
|
||||||
@ -204,12 +199,13 @@ keydb_add_resource (const char *url, int force, int secret)
|
|||||||
iobuf = NULL;
|
iobuf = NULL;
|
||||||
if (created_fname) /* must invalidate that ugly cache */
|
if (created_fname) /* must invalidate that ugly cache */
|
||||||
iobuf_ioctl (NULL, 2, 0, (char*)created_fname);
|
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)
|
if (!token)
|
||||||
; /* already registered - ignore it */
|
; /* already registered - ignore it */
|
||||||
else if (used_resources >= MAX_KEYDB_RESOURCES)
|
else if (used_resources >= MAX_KEYDB_RESOURCES)
|
||||||
rc = G10ERR_RESOURCE_LIMIT;
|
rc = GPGSM_Resource_Limit;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
all_resources[used_resources].type = rt;
|
all_resources[used_resources].type = rt;
|
||||||
@ -223,7 +219,7 @@ keydb_add_resource (const char *url, int force, int secret)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
log_error ("resource type of `%s' not supported\n", url);
|
log_error ("resource type of `%s' not supported\n", url);
|
||||||
rc = G10ERR_GENERAL;
|
rc = GPGSM_General_Error;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,12 +227,12 @@ keydb_add_resource (const char *url, int force, int secret)
|
|||||||
|
|
||||||
leave:
|
leave:
|
||||||
if (rc)
|
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)
|
else if (secret)
|
||||||
any_secret = 1;
|
any_secret = 1;
|
||||||
else
|
else
|
||||||
any_public = 1;
|
any_public = 1;
|
||||||
m_free (filename);
|
xfree (filename);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,7 +245,7 @@ keydb_new (int secret)
|
|||||||
KEYDB_HANDLE hd;
|
KEYDB_HANDLE hd;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
hd = m_alloc_clear (sizeof *hd);
|
hd = xcalloc (1, sizeof *hd);
|
||||||
hd->found = -1;
|
hd->found = -1;
|
||||||
|
|
||||||
assert (used_resources <= MAX_KEYDB_RESOURCES);
|
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].secret = all_resources[i].secret;
|
||||||
hd->active[j].u.kr = keybox_new (all_resources[i].token, secret);
|
hd->active[j].u.kr = keybox_new (all_resources[i].token, secret);
|
||||||
if (!hd->active[j].u.kr) {
|
if (!hd->active[j].u.kr) {
|
||||||
m_free (hd);
|
xfree (hd);
|
||||||
return NULL; /* fixme: release all previously allocated handles*/
|
return NULL; /* fixme: release all previously allocated handles*/
|
||||||
}
|
}
|
||||||
j++;
|
j++;
|
||||||
@ -283,95 +279,101 @@ keydb_new (int secret)
|
|||||||
void
|
void
|
||||||
keydb_release (KEYDB_HANDLE hd)
|
keydb_release (KEYDB_HANDLE hd)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (!hd)
|
||||||
|
return;
|
||||||
|
assert (active_handles > 0);
|
||||||
|
active_handles--;
|
||||||
|
|
||||||
if (!hd)
|
unlock_all (hd);
|
||||||
return;
|
for (i=0; i < hd->used; i++)
|
||||||
assert (active_handles > 0);
|
{
|
||||||
active_handles--;
|
switch (hd->active[i].type)
|
||||||
|
{
|
||||||
unlock_all (hd);
|
case KEYDB_RESOURCE_TYPE_NONE:
|
||||||
for (i=0; i < hd->used; i++) {
|
break;
|
||||||
switch (hd->active[i].type) {
|
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
keybox_release (hd->active[i].u.kr);
|
||||||
break;
|
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
|
||||||
* Return the name of the current resource. This is function first
|
looks for the last found found, then for the current search
|
||||||
* looks for the last found found, then for the current search
|
position, and last returns the first available resource. The
|
||||||
* position, and last returns the first available resource. The
|
returned string is only valid as long as the handle exists. This
|
||||||
* returned string is only valid as long as the handle exists. This
|
function does only return NULL if no handle is specified, in all
|
||||||
* function does only return NULL if no handle is specified, in all
|
other error cases an empty string is returned. */
|
||||||
* other error cases an empty string is returned.
|
|
||||||
*/
|
|
||||||
const char *
|
const char *
|
||||||
keydb_get_resource_name (KEYDB_HANDLE hd)
|
keydb_get_resource_name (KEYDB_HANDLE hd)
|
||||||
{
|
{
|
||||||
int idx;
|
int idx;
|
||||||
const char *s = NULL;
|
const char *s = NULL;
|
||||||
|
|
||||||
|
if (!hd)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (!hd)
|
if ( hd->found >= 0 && hd->found < hd->used)
|
||||||
return NULL;
|
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)
|
switch (hd->active[idx].type)
|
||||||
idx = hd->found;
|
{
|
||||||
else if ( hd->current >= 0 && hd->current < hd->used)
|
case KEYDB_RESOURCE_TYPE_NONE:
|
||||||
idx = hd->current;
|
s = NULL;
|
||||||
else
|
break;
|
||||||
idx = 0;
|
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
||||||
|
s = keybox_get_resource_name (hd->active[idx].u.kr);
|
||||||
switch (hd->active[idx].type) {
|
break;
|
||||||
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
|
static int
|
||||||
lock_all (KEYDB_HANDLE hd)
|
lock_all (KEYDB_HANDLE hd)
|
||||||
{
|
{
|
||||||
int i, rc = 0;
|
int i, rc = 0;
|
||||||
|
|
||||||
for (i=0; !rc && i < hd->used; i++) {
|
for (i=0; !rc && i < hd->used; i++)
|
||||||
switch (hd->active[i].type) {
|
{
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
switch (hd->active[i].type)
|
||||||
break;
|
{
|
||||||
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
case KEYDB_RESOURCE_TYPE_NONE:
|
||||||
rc = keybox_lock (hd->active[i].u.kr, 1);
|
break;
|
||||||
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 */
|
/* revert the already set locks */
|
||||||
for (i--; i >= 0; i--) {
|
for (i--; i >= 0; i--)
|
||||||
switch (hd->active[i].type) {
|
{
|
||||||
|
switch (hd->active[i].type)
|
||||||
|
{
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
case KEYDB_RESOURCE_TYPE_NONE:
|
||||||
break;
|
break;
|
||||||
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
||||||
keybox_lock (hd->active[i].u.kr, 0);
|
/* Fixme: keybox_lock (hd->active[i].u.kr, 0);*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
hd->locked = 1;
|
hd->locked = 1;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -379,24 +381,27 @@ lock_all (KEYDB_HANDLE hd)
|
|||||||
static void
|
static void
|
||||||
unlock_all (KEYDB_HANDLE hd)
|
unlock_all (KEYDB_HANDLE hd)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (!hd->locked)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!hd->locked)
|
for (i=hd->used-1; i >= 0; i--)
|
||||||
return;
|
{
|
||||||
|
switch (hd->active[i].type)
|
||||||
for (i=hd->used-1; i >= 0; i--) {
|
{
|
||||||
switch (hd->active[i].type) {
|
case KEYDB_RESOURCE_TYPE_NONE:
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
break;
|
||||||
break;
|
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
||||||
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
/* fixme: keybox_lock (hd->active[i].u.kr, 0);*/
|
||||||
keybox_lock (hd->active[i].u.kr, 0);
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hd->locked = 0;
|
hd->locked = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
/*
|
/*
|
||||||
* Return the last found keybox. Caller must free it.
|
* Return the last found keybox. Caller must free it.
|
||||||
* The returned keyblock has the kbode flag bit 0 set for the node with
|
* 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)
|
if ( hd->found < 0 || hd->found >= hd->used)
|
||||||
return -1; /* nothing found */
|
return -1; /* nothing found */
|
||||||
|
|
||||||
if( keydbopt.dry_run )
|
if( opt.dry_run )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
rc = lock_all (hd);
|
rc = lock_all (hd);
|
||||||
@ -473,7 +478,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
|
|||||||
if (!hd)
|
if (!hd)
|
||||||
return G10ERR_INV_ARG;
|
return G10ERR_INV_ARG;
|
||||||
|
|
||||||
if( keydbopt.dry_run )
|
if( opt.dry_run )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ( hd->found >= 0 && hd->found < hd->used)
|
if ( hd->found >= 0 && hd->found < hd->used)
|
||||||
@ -500,41 +505,157 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
|
|||||||
return rc;
|
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
|
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)
|
if (opt.dry_run)
|
||||||
return G10ERR_INV_ARG;
|
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;
|
||||||
|
|
||||||
if ( hd->found < 0 || hd->found >= hd->used)
|
rc = lock_all (hd);
|
||||||
return -1; /* nothing found */
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
if( keydbopt.dry_run )
|
gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
|
||||||
return 0;
|
|
||||||
|
|
||||||
rc = lock_all (hd);
|
switch (hd->active[idx].type)
|
||||||
if (rc)
|
{
|
||||||
return rc;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
switch (hd->active[hd->found].type) {
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
|
||||||
rc = G10ERR_GENERAL; /* oops */
|
/* update the current keyblock with KB */
|
||||||
break;
|
int
|
||||||
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
keydb_update_cert (KEYDB_HANDLE hd, KsbaCert cert)
|
||||||
rc = keybox_delete_keyblock (hd->active[hd->found].u.kr);
|
{
|
||||||
break;
|
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;
|
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
|
* 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;
|
int rc;
|
||||||
|
|
||||||
if (!hd)
|
if (!hd)
|
||||||
return G10ERR_INV_ARG;
|
return GPGSM_Invalid_Value;
|
||||||
|
|
||||||
rc = keydb_search_reset (hd); /* this does reset hd->current */
|
rc = keydb_search_reset (hd); /* this does reset hd->current */
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
|
for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
|
||||||
{
|
{
|
||||||
switch (hd->active[hd->current].type)
|
switch (hd->active[hd->current].type)
|
||||||
@ -576,7 +697,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
|
|||||||
void
|
void
|
||||||
keydb_rebuild_caches (void)
|
keydb_rebuild_caches (void)
|
||||||
{
|
{
|
||||||
int i, rc;
|
int i;
|
||||||
|
|
||||||
for (i=0; i < used_resources; i++)
|
for (i=0; i < used_resources; i++)
|
||||||
{
|
{
|
||||||
@ -587,10 +708,10 @@ keydb_rebuild_caches (void)
|
|||||||
case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
|
case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
|
||||||
break;
|
break;
|
||||||
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
||||||
rc = keybox_rebuild_cache (all_resources[i].token);
|
/* rc = keybox_rebuild_cache (all_resources[i].token); */
|
||||||
if (rc)
|
/* if (rc) */
|
||||||
log_error (_("failed to rebuild keybox cache: %s\n"),
|
/* log_error (_("failed to rebuild keybox cache: %s\n"), */
|
||||||
g10_errstr (rc));
|
/* g10_errstr (rc)); */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -604,27 +725,29 @@ keydb_rebuild_caches (void)
|
|||||||
int
|
int
|
||||||
keydb_search_reset (KEYDB_HANDLE hd)
|
keydb_search_reset (KEYDB_HANDLE hd)
|
||||||
{
|
{
|
||||||
int i, rc = 0;
|
int i, rc = 0;
|
||||||
|
|
||||||
|
if (!hd)
|
||||||
|
return GPGSM_Invalid_Value;
|
||||||
|
|
||||||
if (!hd)
|
hd->current = 0;
|
||||||
return G10ERR_INV_ARG;
|
hd->found = -1;
|
||||||
|
/* and reset all resources */
|
||||||
hd->current = 0;
|
for (i=0; !rc && i < hd->used; i++)
|
||||||
hd->found = -1;
|
{
|
||||||
/* and reset all resources */
|
switch (hd->active[i].type)
|
||||||
for (i=0; !rc && i < hd->used; i++) {
|
{
|
||||||
switch (hd->active[i].type) {
|
case KEYDB_RESOURCE_TYPE_NONE:
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
break;
|
||||||
break;
|
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
||||||
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
rc = keybox_search_reset (hd->active[i].u.kr);
|
||||||
rc = keybox_search_reset (hd->active[i].u.kr);
|
break;
|
||||||
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,
|
* Search through all keydb resources, starting at the current position,
|
||||||
* for a keyblock which contains one of the keys described in the DESC array.
|
* 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
|
int
|
||||||
keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
|
keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
|
||||||
{
|
{
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
|
|
||||||
|
if (!hd)
|
||||||
|
return GPGSM_Invalid_Value;
|
||||||
|
|
||||||
if (!hd)
|
while (rc == -1 && hd->current >= 0 && hd->current < hd->used)
|
||||||
return G10ERR_INV_ARG;
|
{
|
||||||
|
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:
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
BUG(); /* we should never see it here */
|
||||||
BUG(); /* we should never see it here */
|
break;
|
||||||
break;
|
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
||||||
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc);
|
||||||
rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc);
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (rc == -1) /* EOF -> switch to next resource */
|
if (rc == -1) /* EOF -> switch to next resource */
|
||||||
hd->current++;
|
hd->current++;
|
||||||
else if (!rc)
|
else if (!rc)
|
||||||
hd->found = hd->current;
|
hd->found = hd->current;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
keydb_search_first (KEYDB_HANDLE hd)
|
keydb_search_first (KEYDB_HANDLE hd)
|
||||||
{
|
{
|
||||||
KEYDB_SEARCH_DESC desc;
|
KEYDB_SEARCH_DESC desc;
|
||||||
|
|
||||||
memset (&desc, 0, sizeof desc);
|
memset (&desc, 0, sizeof desc);
|
||||||
desc.mode = KEYDB_SEARCH_MODE_FIRST;
|
desc.mode = KEYDB_SEARCH_MODE_FIRST;
|
||||||
return keydb_search (hd, &desc, 1);
|
return keydb_search (hd, &desc, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
keydb_search_next (KEYDB_HANDLE hd)
|
keydb_search_next (KEYDB_HANDLE hd)
|
||||||
{
|
{
|
||||||
KEYDB_SEARCH_DESC desc;
|
KEYDB_SEARCH_DESC desc;
|
||||||
|
|
||||||
memset (&desc, 0, sizeof desc);
|
memset (&desc, 0, sizeof desc);
|
||||||
desc.mode = KEYDB_SEARCH_MODE_NEXT;
|
desc.mode = KEYDB_SEARCH_MODE_NEXT;
|
||||||
return keydb_search (hd, &desc, 1);
|
return keydb_search (hd, &desc, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
|
keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
|
||||||
{
|
{
|
||||||
KEYDB_SEARCH_DESC desc;
|
KEYDB_SEARCH_DESC desc;
|
||||||
|
|
||||||
memset (&desc, 0, sizeof desc);
|
memset (&desc, 0, sizeof desc);
|
||||||
desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
|
desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
|
||||||
desc.u.kid[0] = kid[0];
|
/* desc.u.kid[0] = kid[0]; */
|
||||||
desc.u.kid[1] = kid[1];
|
/* desc.u.kid[1] = kid[1]; */
|
||||||
return keydb_search (hd, &desc, 1);
|
return keydb_search (hd, &desc, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
|
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);
|
int
|
||||||
desc.mode = KEYDB_SEARCH_MODE_FPR;
|
keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer)
|
||||||
memcpy (desc.u.fpr, fpr, MAX_FINGERPRINT_LEN);
|
{
|
||||||
return keydb_search (hd, &desc, 1);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
46
sm/keydb.h
46
sm/keydb.h
@ -21,53 +21,43 @@
|
|||||||
#ifndef GNUPG_KEYDB_H
|
#ifndef GNUPG_KEYDB_H
|
||||||
#define GNUPG_KEYDB_H
|
#define GNUPG_KEYDB_H
|
||||||
|
|
||||||
|
#include <ksba.h>
|
||||||
|
|
||||||
|
#include "../kbx/keybox-search-desc.h"
|
||||||
|
|
||||||
typedef struct keydb_handle *KEYDB_HANDLE;
|
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 --*/
|
/*-- keydb.c --*/
|
||||||
int keydb_add_resource (const char *url, int force, int secret);
|
int keydb_add_resource (const char *url, int force, int secret);
|
||||||
KEYDB_HANDLE keydb_new (int secret);
|
KEYDB_HANDLE keydb_new (int secret);
|
||||||
void keydb_release (KEYDB_HANDLE hd);
|
void keydb_release (KEYDB_HANDLE hd);
|
||||||
const char *keydb_get_resource_name (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_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb);
|
||||||
int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb);
|
int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb);
|
||||||
int keydb_insert_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);
|
int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved);
|
||||||
void keydb_rebuild_caches (void);
|
void keydb_rebuild_caches (void);
|
||||||
|
|
||||||
int keydb_search_reset (KEYDB_HANDLE hd);
|
int keydb_search_reset (KEYDB_HANDLE hd);
|
||||||
int keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
|
int keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
|
||||||
int keydb_search_first (KEYDB_HANDLE hd);
|
int keydb_search_first (KEYDB_HANDLE hd);
|
||||||
int keydb_search_next (KEYDB_HANDLE hd);
|
int keydb_search_next (KEYDB_HANDLE hd);
|
||||||
int keydb_search_kid (KEYDB_HANDLE hd, u32 *kid);
|
int keydb_search_kid (KEYDB_HANDLE hd, u32 *kid);
|
||||||
int keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr);
|
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*/
|
#endif /*GNUPG_KEYDB_H*/
|
||||||
|
54
sm/misc.c
54
sm/misc.c
@ -29,13 +29,63 @@
|
|||||||
#include <ksba.h>
|
#include <ksba.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "gpgsm.h"
|
||||||
|
|
||||||
|
|
||||||
/* Note: we might want to wrap this in a macro to get our hands on
|
/* 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
|
int
|
||||||
map_ksba_err (int err)
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,6 +23,10 @@
|
|||||||
|
|
||||||
#include <gcrypt.h> /* we need this for the memory function protos */
|
#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/logging.h"
|
||||||
#include "../jnlib/argparse.h"
|
#include "../jnlib/argparse.h"
|
||||||
#include "../jnlib/stringhelp.h"
|
#include "../jnlib/stringhelp.h"
|
||||||
@ -46,5 +50,9 @@
|
|||||||
|
|
||||||
/*-- misc.c --*/
|
/*-- misc.c --*/
|
||||||
int map_ksba_err (int err);
|
int map_ksba_err (int err);
|
||||||
|
int map_gcry_err (int err);
|
||||||
|
int map_kbx_err (int err);
|
||||||
|
|
||||||
#endif /*UTIL_H*/
|
#endif /*UTIL_H*/
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user