1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

See ChangeLog: Thu May 25 18:39:11 CEST 2000 Werner Koch

This commit is contained in:
Werner Koch 2000-05-25 16:28:04 +00:00
parent da129a5124
commit d1648b4d7a
11 changed files with 1207 additions and 60 deletions

View file

@ -1,3 +1,10 @@
Thu May 25 18:39:11 CEST 2000 Werner Koch <wk@openit.de>
* kbxio.c: New.
* kbxfile.c (print_kbxfile): Add a loop
(do_print_kbxfile): Fixed passing to kbx_dump_blob.
Fri Mar 24 11:25:45 CET 2000 Werner Koch <wk@openit.de>
* gpg.c (print_mds): Add arg keys as a kludge to print hmacs

View file

@ -9,7 +9,7 @@ LDFLAGS = -static @LDFLAGS@ @DYNLINK_LDFLAGS@
needed_libs = ../util/libutil.la ../gcrypt/libgcrypt.la ../jnlib/libjnlib.la ../util/libutil.la
#noinst_PROGRAMS = gpgd
bin_PROGRAMS = gpg
bin_PROGRAMS = gpg kbxutil
common_source = \
build-packet.c \
@ -26,6 +26,7 @@ common_source = \
kbnode.c \
kbx.h \
kbxblob.c \
kbxio.c \
kbxfile.c \
main.h \
mainproc.c \
@ -73,6 +74,11 @@ gpg_SOURCES = gpg.c \
dearmor.c \
keygen.c
# fixme: remove unused sources from kbxutil
kbxutil_SOURCES = kbxutil.c \
$(common_source)
#gpgd_SOURCES = gpgd.c \
# ks-proto.h \
# ks-proto.c \

View file

@ -196,7 +196,8 @@ static int
do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
{
write_header(out, ctb, uid->len);
uid->stored_at = iobuf_tell( out ); /* what a hack */
uid->stored_at = iobuf_get_temp_length ( out ); /* what a hack ... */
/* ... and it does only work when used with a temp iobuf */
if( iobuf_write( out, uid->name, uid->len ) )
return GPGERR_WRITE_FILE;
return 0;

View file

@ -1461,9 +1461,11 @@ main( int argc, char **argv )
break;
case aFixTrustDB:
log_error("this command ist not yet implemented.\"\n");
log_error("this command is not yet implemented.\"\n");
log_error("A workaround is to use \"--export-ownertrust\", remove\n");
log_error("the trustdb file and do an \"--import-ownertrust\".\n" );
#warning removed the next line
export_as_kbxfile();
break;
case aListTrustPath:

View file

@ -1,4 +1,4 @@
/* ggpd.c - The GnuPG daemon (keyserver)
/* gpg.c - The GnuPG daemon (keyserver)
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* This file is part of GnuPG.

View file

@ -23,10 +23,29 @@
#include "keydb.h"
/*-- kbxblob.c */
struct kbxblob;
typedef struct kbxblob *KBXBLOB;
int kbx_create_blob ( KBXBLOB *retkbx, KBNODE keyblock );
int kbx_new_blob ( KBXBLOB *r_blob, char *image, size_t imagelen );
int kbx_create_blob ( KBXBLOB *r_blob, KBNODE keyblock );
void kbx_release_blob ( KBXBLOB blob );
const char *kbx_get_blob_image ( KBXBLOB blob, size_t *n );
int kbx_dump_blob ( FILE *fp, KBXBLOB blob );
int kbx_blob_has_fpr ( KBXBLOB blob, const byte *fpr );
int kbx_blob_has_kid ( KBXBLOB blob, const byte *keyidbuf, size_t keyidlen );
int kbx_blob_has_uid ( KBXBLOB blob,
int (*cmp)(const byte *, size_t, void *), void *opaque );
/*-- kbxio.c --*/
int kbx_read_blob ( KBXBLOB *r_blob, FILE *a );
/*-- kbxfile.c --*/
int kbxfile_search_by_fpr( const char *filename, const byte *fpr );
int kbxfile_search_by_kid ( const char *filename, u32 *kid, int mode );
int kbxfile_search_by_uid ( const char *filename, const char *name );
void print_kbxfile( const char *filename );
#endif /*GPG_KBX_H*/

View file

@ -88,7 +88,7 @@ The standard KBX Blob looks like this:
Here comes the keyblock
maybe we put a sigture here later.
maybe we put a signature here later.
b16 MD5 checksum (useful for KS syncronisation)
*
@ -136,20 +136,31 @@ struct keyid_list {
byte kid[8];
};
struct fixup_list {
struct fixup_list *next;
u32 off;
u32 val;
};
struct kbxblob {
byte *blob;
size_t bloblen;
/* stuff used only by kbx_create_blob */
int nkeys;
struct kbxblob_key *keys;
int nuids;
struct kbxblob_uid *uids;
int nsigs;
u32 *sigs;
struct fixup_list *fixups;
struct keyid_list *temp_kids;
IOBUF buf; /* the KBX is stored here */
IOBUF buf; /* the KBX is temporarly stored here */
};
void kbx_release_blob ( KBXBLOB blob );
/* Note: this functions are only used for temportay iobufs and therefore
* they can't fail */
@ -183,28 +194,9 @@ putn ( IOBUF out, const byte *p, size_t n )
}
}
/****************
* special version of put 32, which is used to fixup a value at file offset OFF
*/
static void
put32at ( IOBUF out, u32 a, size_t pos )
{
size_t n;
byte *p;
iobuf_flush_temp ( out );
p = iobuf_get_temp_buffer( out );
n = iobuf_get_temp_length( out );
assert( n >= pos+4 );
p[0] = a >> 24 ;
p[1] = a >> 16 ;
p[2] = a >> 8 ;
p[3] = a ;
}
/****************
* We must store the keyid at some place becuase we can't calculate the
* We must store the keyid at some place because we can't calculate the
* offset yet. This is only used for v3 keyIDs. Function returns an index
* value for later fixupd; this must be a non-zero value
*/
@ -269,8 +261,10 @@ create_key_part( KBXBLOB blob, KBNODE keyblock )
if ( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
PKT_public_key *pk = node->pkt->pkt.public_key;
char tmp[20];
fingerprint_from_pk( pk, blob->keys[n].fpr, &fprlen );
fingerprint_from_pk( pk, tmp , &fprlen );
memcpy(blob->keys[n].fpr,tmp,20);
if ( fprlen != 20 ) { /*v3 fpr - shift right and fill with zeroes*/
assert( fprlen == 16 );
memmove( blob->keys[n].fpr+4, blob->keys[n].fpr, 16);
@ -346,10 +340,10 @@ create_blob_header( KBXBLOB blob )
put32 ( a, 0 ); /* length of the keyblock, needs fixup */
put16 ( a, blob->nkeys );
put16 ( a, 20 + 8 + 2 + 2 ); /* size of key info */
put16 ( a, 20 + 4 + 2 + 2 ); /* size of key info */
for ( i=0; i < blob->nkeys; i++ ) {
putn ( a, blob->keys[i].fpr, 20 );
blob->keys[i].off_kid_addr = iobuf_tell ( a );
blob->keys[i].off_kid_addr = iobuf_get_temp_length (a);
put32 ( a, 0 ); /* offset to keyid, fixed up later */
put16 ( a, blob->keys[i].flags );
put16 ( a, 0 ); /* reserved */
@ -358,7 +352,7 @@ create_blob_header( KBXBLOB blob )
put16 ( a, blob->nuids );
put16 ( a, 4 + 4 + 2 + 1 + 1 ); /* size of uid info */
for ( i=0; i < blob->nuids; i++ ) {
blob->uids[i].off_addr = iobuf_tell ( a );
blob->uids[i].off_addr = iobuf_get_temp_length ( a );
put32 ( a, 0 ); /* offset to userid, fixed up later */
put32 ( a, blob->uids[i].len );
put16 ( a, blob->uids[i].flags );
@ -385,13 +379,17 @@ create_blob_header( KBXBLOB blob )
* not part of the fingerprint. While we are doing that, we fixup all
* the keyID offsets */
for ( i=0; i < blob->nkeys; i++ ) {
struct fixup_list *fl = gcry_xcalloc(1, sizeof *fl );
fl->off = blob->keys[i].off_kid_addr;
fl->next = blob->fixups;
blob->fixups = fl;
if ( blob->keys[i].off_kid ) { /* this is a v3 one */
put32at ( a, iobuf_tell(a), blob->keys[i].off_kid_addr );
fl->val = iobuf_get_temp_length (a);
put_stored_kid ( blob, blob->keys[i].off_kid );
}
else { /* the better v4 key IDs - just store an offset 8 bytes back */
put32at ( a, blob->keys[i].off_kid_addr-8,
blob->keys[i].off_kid_addr );
fl->val = blob->keys[i].off_kid_addr-8;
}
}
@ -405,9 +403,17 @@ create_blob_keyblock( KBXBLOB blob, KBNODE keyblock )
IOBUF a = blob->buf;
KBNODE node;
int rc;
int nsig;
int n;
u32 kbstart = iobuf_get_temp_length ( a );
for ( nsig = 0, node = keyblock; node; node = node->next ) {
{
struct fixup_list *fl = gcry_xcalloc(1, sizeof *fl );
fl->off = 8;
fl->val = kbstart;
fl->next = blob->fixups;
blob->fixups = fl;
}
for ( n = 0, node = keyblock; node; node = node->next ) {
rc = build_packet ( a, node->pkt );
if ( rc ) {
gpg_log_error("build_packet(%d) for kbxblob failed: %s\n",
@ -418,11 +424,22 @@ create_blob_keyblock( KBXBLOB blob, KBNODE keyblock )
PKT_user_id *u = node->pkt->pkt.user_id;
/* build_packet has set the offset of the name into u ;
* now we can do the fixup */
put32at ( a, u->stored_at, blob->uids[nsig].off_addr );
nsig++;
struct fixup_list *fl = gcry_xcalloc(1, sizeof *fl );
fl->off = blob->uids[n].off_addr;
fl->val = u->stored_at;
fl->next = blob->fixups;
blob->fixups = fl;
n++;
}
}
assert( nsig == blob->nsigs );
assert( n == blob->nuids );
{
struct fixup_list *fl = gcry_xcalloc(1, sizeof *fl );
fl->off = 12;
fl->val = iobuf_get_temp_length (a) - kbstart;
fl->next = blob->fixups;
blob->fixups = fl;
}
return 0;
}
@ -438,10 +455,13 @@ create_blob_finish( KBXBLOB blob )
{
IOBUF a = blob->buf;
byte *p;
char *pp;
int i;
size_t n;
/* write a placeholder for the checksum */
put32( a, 0 ); put32( a, 0 ); put32( a, 0 ); put32( a, 0 );
for ( i = 0; i < 16; i++ )
put32( a, 0 );
/* get the memory area */
iobuf_flush_temp ( a );
p = iobuf_get_temp_buffer ( a );
@ -449,23 +469,48 @@ create_blob_finish( KBXBLOB blob )
assert( n >= 20 );
/* fixup the length */
put32at ( a, 0, n );
{
struct fixup_list *fl = gcry_xcalloc(1, sizeof *fl );
fl->off = 0;
fl->val = n;
fl->next = blob->fixups;
blob->fixups = fl;
}
/* do the fixups */
{
struct fixup_list *fl;
for ( fl = blob->fixups; fl; fl = fl->next ) {
assert( fl->off+4 <= n );
p[fl->off+0] = fl->val >> 24 ;
p[fl->off+1] = fl->val >> 16 ;
p[fl->off+2] = fl->val >> 8 ;
p[fl->off+3] = fl->val ;
}
}
/* calculate and store the MD5 checksum */
gcry_md_hash_buffer( GCRY_MD_MD5, p + n - 16, p, n - 16 );
pp = gcry_malloc ( n );
if ( !pp )
return GCRYERR_NO_MEM;
memcpy ( pp , p, n );
blob->blob = pp;
blob->bloblen = n;
return 0;
}
int
kbx_create_blob ( KBXBLOB *retkbx, KBNODE keyblock )
kbx_create_blob ( KBXBLOB *r_blob, KBNODE keyblock )
{
int rc = 0;
KBNODE node;
KBXBLOB blob;
*retkbx = NULL;
*r_blob = NULL;
blob = gcry_calloc (1, sizeof *blob );
if( !blob )
return GCRYERR_NO_MEM;
@ -484,9 +529,9 @@ kbx_create_blob ( KBXBLOB *retkbx, KBNODE keyblock )
default: break;
}
}
blob->keys = gcry_calloc ( blob->nkeys, sizeof ( blob->keys ) );
blob->uids = gcry_calloc ( blob->nuids, sizeof ( blob->uids ) );
blob->sigs = gcry_calloc ( blob->nsigs, sizeof ( blob->sigs ) );
blob->keys = gcry_calloc ( blob->nkeys, sizeof ( *blob->keys ) );
blob->uids = gcry_calloc ( blob->nuids, sizeof ( *blob->uids ) );
blob->sigs = gcry_calloc ( blob->nsigs, sizeof ( *blob->sigs ) );
if ( !blob->keys || !blob->uids || !blob->sigs ) {
rc = GCRYERR_NO_MEM;
goto leave;
@ -516,17 +561,44 @@ kbx_create_blob ( KBXBLOB *retkbx, KBNODE keyblock )
if( rc )
goto leave;
*retkbx = blob;
leave:
release_kid_list( blob->temp_kids );
blob->temp_kids = NULL;
if ( rc ) {
kbx_release_blob ( blob );
*r_blob = NULL;
}
else {
*r_blob = blob;
}
return rc;
}
int
kbx_new_blob ( KBXBLOB *r_blob, char *image, size_t imagelen )
{
KBXBLOB blob;
*r_blob = NULL;
blob = gcry_calloc (1, sizeof *blob );
if( !blob )
return GCRYERR_NO_MEM;
blob->blob = image;
blob->bloblen = imagelen;
*r_blob = blob;
return 0;
}
const char *
kbx_get_blob_image ( KBXBLOB blob, size_t *n )
{
*n = blob->bloblen;
return blob->blob;
}
void
kbx_release_blob ( KBXBLOB blob )
{
@ -537,6 +609,9 @@ kbx_release_blob ( KBXBLOB blob )
gcry_free( blob->keys );
gcry_free( blob->uids );
gcry_free( blob->sigs );
gcry_free ( blob->blob );
gcry_free( blob );
}
@ -556,17 +631,21 @@ get16( const byte *buffer )
{
ulong a;
a = *buffer << 8;
a |= buffer[0];
a |= buffer[1];
return a;
}
int
kbx_dump_blob ( FILE *fp, const byte* buffer, size_t length )
kbx_dump_blob ( FILE *fp, KBXBLOB blob )
{
#if 0
ulong n;
const byte *buffer = blob->blob;
size_t length = blob->bloblen;
ulong n, nkeys, keyinfolen;
ulong nuids, uidinfolen;
ulong nsigs, siginfolen;
ulong keyblock_off, keyblock_len;
const byte *p;
if( length < 40 ) {
fprintf( fp, "blob too short\n");
@ -579,8 +658,8 @@ kbx_dump_blob ( FILE *fp, const byte* buffer, size_t length )
else
length = n; /* ignore the rest */
fprintf( fp, "Length: %lu\n", n );
fprintf( fp, "Type: %d\n", buffer[4] ),
fprintf( fp, "Version: %d\n", buffer[5] ),
fprintf( fp, "Type: %d\n", buffer[4] );
fprintf( fp, "Version: %d\n", buffer[5] );
if( buffer[4] != 2 ) {
fprintf( fp, "can't dump this blob type\n" );
return 0;
@ -593,8 +672,224 @@ kbx_dump_blob ( FILE *fp, const byte* buffer, size_t length )
fprintf( fp, "Keyblock-Offset: %lu\n", keyblock_off );
fprintf( fp, "Keyblock-Length: %lu\n", keyblock_len );
#endif
nkeys = get16( buffer + 16 );
fprintf( fp, "Key-Count: %lu\n", nkeys );
keyinfolen = get16( buffer + 18 );
fprintf( fp, "Key-Info-Length: %lu\n", keyinfolen );
/* fixme: check bounds */
p = buffer + 20;
for(n=0; n < nkeys; n++, p += keyinfolen ) {
int i;
ulong kidoff, kflags;
fprintf( fp, "Key-%lu-Fpr: ", n );
for(i=0; i < 20; i++ )
fprintf( fp, "%02X", p[i] );
kidoff = get32( p + 20 );
fprintf( fp, "\nKey-%lu-Kid-Off: %lu\n", n, kidoff );
fprintf( fp, "Key-%lu-Kid: ", n );
/* fixme: check bounds */
for(i=0; i < 8; i++ )
fprintf( fp, "%02X", buffer[kidoff+i] );
kflags = get16( p + 24 );
fprintf( fp, "\nKey-%lu-Flags: %04lX\n", n, kflags );
}
nuids = get16( p );
fprintf( fp, "Uid-Count: %lu\n", nuids );
uidinfolen = get16( p + 2 );
fprintf( fp, "Uid-Info-Length: %lu\n", uidinfolen );
/* fixme: check bounds */
p += 4;
for(n=0; n < nuids; n++, p += uidinfolen ) {
ulong uidoff, uidlen, uflags;
uidoff = get32( p );
uidlen = get32( p+4 );
fprintf( fp, "Uid-%lu-Off: %lu\n", n, uidoff );
fprintf( fp, "Uid-%lu-Len: %lu\n", n, uidlen );
fprintf( fp, "Uid-%lu: \"", n );
print_string( fp, buffer+uidoff, uidlen, '\"' );
fputs("\"\n", fp );
uflags = get16( p + 8 );
fprintf( fp, "Uid-%lu-Flags: %04lX\n", n, uflags );
fprintf( fp, "Uid-%lu-Validity: %d\n", n, p[10] );
}
nsigs = get16( p );
fprintf( fp, "Sig-Count: %lu\n", nsigs );
siginfolen = get16( p + 2 );
fprintf( fp, "Sig-Info-Length: %lu\n", siginfolen );
/* fixme: check bounds */
p += 4;
for(n=0; n < nsigs; n++, p += siginfolen ) {
ulong sflags;
sflags = get32( p );
fprintf( fp, "Sig-%lu-Expire: ", n );
if( !sflags )
fputs( "[not checked]", fp );
else if( sflags == 1 )
fputs( "[missing key]", fp );
else if( sflags == 2 )
fputs( "[bad signature]", fp );
else if( sflags < 0x10000000 )
fprintf( fp, "[bad flag %0lx]", sflags );
else if( sflags == 0xffffffff )
fputs( "0", fp );
else
fputs( strtimestamp( sflags ), fp );
putc('\n', fp );
}
fprintf( fp, "Ownertrust: %d\n", p[0] );
fprintf( fp, "All-Validity: %d\n", p[1] );
p += 4;
n = get32( p ); p += 4;
fprintf( fp, "Recheck-After: %s\n", n? strtimestamp(n) : "0" );
n = get32( p ); p += 4;
fprintf( fp, "Latest-Timestamp: %s\n", strtimestamp(n) );
n = get32( p ); p += 4;
fprintf( fp, "Created-At: %s\n", strtimestamp(n) );
n = get32( p ); p += 4;
fprintf( fp, "Reserved-Space: %lu\n", n );
/* check that the keyblock is at the correct offset and other bounds */
fprintf( fp, "Blob-Checksum: [MD5-hash]\n" );
return 0;
}
/****************
* Check whether the given fingerprint (20 bytes) is in the
* given keyblob. fpr is always 20 bytes.
* Return: 0 = found
* -1 = not found
other = error (fixme: do not always reurn gpgerr_general)
*/
int
kbx_blob_has_fpr ( KBXBLOB blob, const byte *fpr )
{
ulong n, nkeys, keyinfolen;
const byte *p, *pend;
byte *buffer = blob->blob;
size_t buflen = blob->bloblen;
if ( buflen < 40 )
return GPGERR_GENERAL; /* blob too short */
n = get32( buffer );
if ( n > buflen )
return GPGERR_GENERAL; /* blob larger than announced length */
buflen = n; /* ignore trailing stuff */
pend = buffer + n - 1;
if ( buffer[4] != 2 )
return GPGERR_GENERAL; /* invalid blob type */
if ( buffer[5] != 1 )
return GPGERR_GENERAL; /* invalid blob format version */
nkeys = get16( buffer + 16 );
keyinfolen = get16( buffer + 18 );
p = buffer + 20;
for(n=0; n < nkeys; n++, p += keyinfolen ) {
if ( p+20 > pend )
return GPGERR_GENERAL; /* blob shorter than required */
if (!memcmp ( p, fpr, 20 ) )
return 0; /* found */
}
return -1;
}
/****************
* Check whether the given keyID (20 bytes) is in the
* given keyblob.
* Return: 0 = found
* -1 = not found
other = error (fixme: do not always return gpgerr_general)
*/
int
kbx_blob_has_kid ( KBXBLOB blob, const byte *keyidbuf, size_t keyidlen )
{
ulong n, nkeys, keyinfolen, off;
const byte *p, *pend;
byte *buffer = blob->blob;
size_t buflen = blob->bloblen;
if ( buflen < 40 )
return GPGERR_GENERAL; /* blob too short */
n = get32( buffer );
if ( n > buflen )
return GPGERR_GENERAL; /* blob larger than announced length */
buflen = n; /* ignore trailing stuff */
pend = buffer + n - 1;
if ( buffer[4] != 2 )
return GPGERR_GENERAL; /* invalid blob type */
if ( buffer[5] != 1 )
return GPGERR_GENERAL; /* invalid blob format version */
nkeys = get16( buffer + 16 );
keyinfolen = get16( buffer + 18 );
p = buffer + 20;
for(n=0; n < nkeys; n++, p += keyinfolen ) {
if ( p+24 > pend )
return GPGERR_GENERAL; /* blob shorter than required */
off = get32 ( p + 20 );
if (keyidlen < 8 ) /* actually keyidlen may either be 4 or 8 */
off +=4;
if ( off+keyidlen > buflen )
return GPGERR_GENERAL; /* offset out of bounds */
if ( !memcmp ( buffer+off, keyidbuf, keyidlen ) )
return 0; /* found */
}
return -1;
}
int
kbx_blob_has_uid ( KBXBLOB 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;
}

View file

@ -22,7 +22,7 @@
* We will change the whole system to use only KBX. This file here
* will implement the methods needed to operate on plain KBXfiles.
* Most stuff from getkey and ringedit will be replaced by stuff here.
* To make things even mor easier we will only allow one updateable kbxfile
* To make things even more easier we will only allow one updateable kbxfile
* and optionally some read-only files.
*/
@ -35,11 +35,298 @@
#include <gcrypt.h>
#include "kbx.h"
#include "options.h"
#include "util.h"
#include "i18n.h"
#include "main.h"
/****************
* Read the blob at the current fileposition and return an allocated
* pointer nto the blob if it was found.
* Fixme: return a blob object.
*/
static int
do_search_by_fpr ( const char *filename, FILE *a, const char *fpr,
KBXBLOB *r_blob )
{
KBXBLOB blob;
int rc;
*r_blob = NULL;
rc = kbx_read_blob ( &blob, a );
if ( rc && rc != -1 ) {
log_error (_("file `%s': error reading blob\n"), filename );
}
else if ( !rc ) {
rc = kbx_blob_has_fpr ( blob, fpr );
}
else
log_info ("eof\n");
if ( !rc ) {
*r_blob = blob;
}
else {
kbx_release_blob ( blob );
}
return rc;
}
int
kbxfile_search_by_fpr( void )
kbxfile_search_by_fpr( const char *filename, const byte *fpr )
{
FILE *fp;
KBXBLOB blob;
int rc;
fp = fopen ( filename, "rb" );
if( !fp ) {
log_error(_("can't open `%s': %s\n"), filename, strerror(errno) );
return 1;
}
while ( (rc=do_search_by_fpr ( filename, fp, fpr, &blob )) == -1 )
;
if ( !rc ) {
fputs ("FOUND\n", stderr );
kbx_dump_blob ( stderr, blob );
kbx_release_blob ( blob );
}
fclose (fp);
return -1;
}
/****************
* Read the blob at the current fileposition and return an allocated
* pointer nto the blob if it was found.
* Fixme: return a blob object.
*/
static int
do_search_by_keyid ( const char *filename, FILE *a,
const byte *keyidbuf, size_t keyidlen, KBXBLOB *r_blob )
{
KBXBLOB blob;
int rc;
*r_blob = NULL;
rc = kbx_read_blob ( &blob, a );
if ( rc && rc != -1 ) {
log_error (_("file `%s': error reading blob\n"), filename );
}
else if ( !rc ) {
rc = kbx_blob_has_kid ( blob, keyidbuf, keyidlen );
}
else
rc = GPGERR_GENERAL; /* eof */
if ( !rc ) {
*r_blob = blob;
}
else {
kbx_release_blob ( blob );
}
return rc;
}
/****************
* Look for a KBX described by an keyid. This function will in
* turn return each matching keyid because there may me duplicates
* (which can't happen for fingerprints)
* mode 10 = short keyid
* 11 = long keyid
*/
int
kbxfile_search_by_kid ( const char *filename, u32 *kid, int mode )
{
FILE *fp;
KBXBLOB blob;
int rc;
byte kbuf[8], *kbufptr;
int kbuflen;
fp = fopen ( filename, "rb" );
if( !fp ) {
log_error(_("can't open `%s': %s\n"), filename, strerror(errno) );
return 1;
}
kbuf[0] = kid[0] >> 24;
kbuf[1] = kid[0] >> 16;
kbuf[2] = kid[0] >> 8;
kbuf[3] = kid[0];
kbuf[4] = kid[1] >> 24;
kbuf[5] = kid[1] >> 16;
kbuf[6] = kid[1] >> 8;
kbuf[7] = kid[1];
if ( mode == 10 ) {
kbufptr=kbuf+4;
kbuflen = 4;
}
else if (mode == 11 ) {
kbufptr=kbuf;
kbuflen = 8;
}
else {
BUG();
}
do {
while ( (rc=do_search_by_keyid ( filename, fp,
kbufptr, kbuflen, &blob )) == -1 )
;
if ( !rc ) {
fputs ("FOUND:\n", stderr );
kbx_dump_blob ( stderr, blob );
kbx_release_blob ( blob );
}
} while ( !rc );
fclose (fp);
return -1;
}
static int
do_search_by_uid ( const char *filename, FILE *a,
int (*cmpfnc)(const byte*,size_t,void*), void *cmpdata,
KBXBLOB *r_blob )
{
KBXBLOB blob;
int rc;
*r_blob = NULL;
rc = kbx_read_blob ( &blob, a );
if ( rc && rc != -1 ) {
log_error (_("file `%s': error reading blob\n"), filename );
}
else if ( !rc ) {
rc = kbx_blob_has_uid ( blob, cmpfnc, cmpdata );
}
else
rc = GPGERR_GENERAL; /* eof */
if ( !rc ) {
*r_blob = blob;
}
else {
kbx_release_blob ( blob );
}
return rc;
}
static int
substr_compare ( const byte *buf, size_t buflen, void *opaque )
{
return !!memistr ( buf, buflen, opaque );
}
int
kbxfile_search_by_uid ( const char *filename, const char *name )
{
FILE *fp;
KBXBLOB blob;
int rc;
byte kbuf[8], *kbufptr;
int kbuflen;
fp = fopen ( filename, "rb" );
if( !fp ) {
log_error(_("can't open `%s': %s\n"), filename, strerror(errno) );
return 1;
}
do {
while ( (rc=do_search_by_uid ( filename, fp,
substr_compare, name, &blob )) == -1 )
;
if ( !rc ) {
fputs ("FOUND:\n", stderr );
kbx_dump_blob ( stderr, blob );
kbx_release_blob ( blob );
}
} while ( !rc );
fclose ( fp );
return -1;
}
void
export_as_kbxfile(void)
{
KBPOS kbpos;
KBNODE keyblock = NULL;
int rc=0;
rc = enum_keyblocks( 0, &kbpos, &keyblock );
if( rc ) {
if( rc != -1 )
log_error("enum_keyblocks(open) failed: %s\n", gpg_errstr(rc) );
goto leave;
}
while( !(rc = enum_keyblocks( 1, &kbpos, &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( 2, &kbpos, &keyblock ); /* close */
release_kbnode( keyblock );
}
static int
do_print_kbxfile( const char *filename, FILE *a )
{
KBXBLOB blob;
int rc;
rc = kbx_read_blob ( &blob, a );
if ( rc && rc != -1 ) {
log_error (_("file `%s': error reading blob\n"), filename );
}
else if ( ! rc )
kbx_dump_blob ( stdout, blob );
kbx_release_blob ( blob );
return rc;
}
void
print_kbxfile( const char *filename )
{
FILE *fp;
fp = fopen ( filename, "rb" );
if( !fp ) {
log_error(_("can't open `%s': %s\n"), filename, strerror(errno) );
return 1;
}
while ( !do_print_kbxfile( filename, fp ) )
;
fclose (fp);
}

75
g10/kbxio.c Normal file
View file

@ -0,0 +1,75 @@
/* kbxio.c - KBX I/O handling
* Copyright (C) 2000 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 <assert.h>
#include <gcrypt.h>
#include "iobuf.h"
#include "util.h"
#include "kbx.h"
int
kbx_read_blob ( KBXBLOB *r_blob, FILE *a )
{
char *image;
size_t imagelen = 0;
int c1, c2, c3, c4;
int rc;
*r_blob = NULL;
if ( (c1 = getc ( a )) == EOF
|| (c2 = getc ( a )) == EOF
|| (c3 = getc ( a )) == EOF
|| (c4 = getc ( a )) == EOF ) {
if ( c1 == EOF && !ferror ( a ) )
return -1;
return GPGERR_GENERAL;
}
imagelen = (c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4;
if ( imagelen > 500000 ) { /* sanity check:blob too large */
return GPGERR_GENERAL;
}
else if ( imagelen < 4 ) { /* blobtoo short */
return GPGERR_GENERAL;
}
image = gcry_malloc ( imagelen );
if ( !image ) {
return GPGERR_GENERAL;
}
image[0] = c1; image[1] = c2; image[2] = c3; image[3] = c4;
if ( fread ( image+4, imagelen-4, 1, a ) != 1 ) {
gcry_free ( image );
return GPGERR_GENERAL;
}
rc = kbx_new_blob ( r_blob, image, imagelen );
return rc;
}

442
g10/kbxutil.c Normal file
View file

@ -0,0 +1,442 @@
/* gpg.c - The GnuPG utility (main for gpg)
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <gcrypt.h>
#include "packet.h"
#include "iobuf.h"
#include "util.h"
#include "main.h"
#include "options.h"
#include "keydb.h"
#include "filter.h"
#include "ttyio.h"
#include "i18n.h"
#include "gnupg-defs.h"
#include "kbx.h"
enum cmd_and_opt_values { aNull = 0,
oArmor = 'a',
aDetachedSign = 'b',
aSym = 'c',
aDecrypt = 'd',
aEncr = 'e',
oInteractive = 'i',
oKOption = 'k',
oDryRun = 'n',
oOutput = 'o',
oQuiet = 'q',
oRecipient = 'r',
aSign = 's',
oTextmodeShort= 't',
oUser = 'u',
oVerbose = 'v',
oCompress = 'z',
oNotation = 'N',
oBatch = 500,
aClearsign,
aStore,
aKeygen,
aSignEncr,
aSignKey,
aLSignKey,
aListPackets,
aEditKey,
aDeleteKey,
aDeleteSecretKey,
aKMode,
aKModeC,
aImport,
aFastImport,
aVerify,
aListKeys,
aListSigs,
aListSecretKeys,
aSendKeys,
aRecvKeys,
aExport,
aExportAll,
aExportSecret,
aCheckKeys,
aGenRevoke,
aPrimegen,
aPrintMD,
aPrintHMAC,
aPrintMDs,
aCheckTrustDB,
aUpdateTrustDB,
aFixTrustDB,
aListTrustDB,
aListTrustPath,
aExportOwnerTrust,
aImportOwnerTrust,
aDeArmor,
aEnArmor,
aGenRandom,
oTextmode,
oFingerprint,
oWithFingerprint,
oAnswerYes,
oAnswerNo,
oKeyring,
oSecretKeyring,
oDefaultKey,
oDefRecipient,
oDefRecipientSelf,
oNoDefRecipient,
oOptions,
oDebug,
oDebugAll,
oStatusFD,
oNoComment,
oNoVersion,
oEmitVersion,
oCompletesNeeded,
oMarginalsNeeded,
oMaxCertDepth,
oLoadExtension,
oRFC1991,
oOpenPGP,
oCipherAlgo,
oDigestAlgo,
oCompressAlgo,
oPasswdFD,
oNoVerbose,
oTrustDBName,
oNoSecmemWarn,
oNoArmor,
oNoDefKeyring,
oNoGreeting,
oNoTTY,
oNoOptions,
oNoBatch,
oHomedir,
oWithColons,
oWithKeyData,
oSkipVerify,
oCompressKeys,
oCompressSigs,
oAlwaysTrust,
oEmuChecksumBug,
oRunAsShmCP,
oSetFilename,
oSetPolicyURL,
oUseEmbeddedFilename,
oComment,
oDefaultComment,
oThrowKeyid,
oForceV3Sigs,
oForceMDC,
oS2KMode,
oS2KDigest,
oS2KCipher,
oCharset,
oNotDashEscaped,
oEscapeFrom,
oLockOnce,
oLockMultiple,
oKeyServer,
oEncryptTo,
oNoEncryptTo,
oLoggerFD,
oUtf8Strings,
oNoUtf8Strings,
oDisableCipherAlgo,
oDisablePubkeyAlgo,
oAllowNonSelfsignedUID,
oNoLiteral,
oSetFilesize,
oEntropyDLLName,
aFindByFpr,
aFindByKid,
aFindByUid,
aTest };
static ARGPARSE_OPTS opts[] = {
{ 300, NULL, 0, N_("@Commands:\n ") },
{ aFindByFpr, "find-by-fpr", 0, "|FPR| find key using it's fingerprnt" },
{ aFindByKid, "find-by-kid", 0, "|KID| find key using it's keyid" },
{ aFindByUid, "find-by-uid", 0, "|NAME| find key by user name" },
{ 301, NULL, 0, N_("@\nOptions:\n ") },
{ oArmor, "armor", 0, N_("create ascii armored output")},
{ oArmor, "armour", 0, "@" },
{ oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") },
{ oOutput, "output", 2, N_("use as output file")},
{ oVerbose, "verbose", 0, N_("verbose") },
{ oQuiet, "quiet", 0, N_("be somewhat more quiet") },
{ oDryRun, "dry-run", 0, N_("do not make any changes") },
{ oOptions, "options" , 2, N_("read options from file")},
{ oDebug, "debug" ,4|16, N_("set debugging flags")},
{ oDebugAll, "debug-all" ,0, N_("enable full debugging")},
{0} };
int gpg_errors_seen = 0;
static const char *
my_strusage( int level )
{
const char *p;
switch( level ) {
case 11: p = "kbxutil (GnuPG)";
break;
case 13: p = VERSION; break;
case 17: p = PRINTABLE_OS_NAME; break;
case 19: p =
_("Please report bugs to <gnupg-bugs@gnu.org>.\n");
break;
case 1:
case 40: p =
_("Usage: kbxutil [options] [files] (-h for help)");
break;
case 41: p =
_("Syntax: kbxutil [options] [files]\n"
"list, export, import KBX data\n");
break;
default: p = NULL;
}
return p;
}
static void
i18n_init(void)
{
#ifdef USE_SIMPLE_GETTEXT
set_gettext_file( PACKAGE );
#else
#ifdef ENABLE_NLS
#ifdef HAVE_LC_MESSAGES
setlocale( LC_TIME, "" );
setlocale( LC_MESSAGES, "" );
#else
setlocale( LC_ALL, "" );
#endif
bindtextdomain( PACKAGE, GNUPG_LOCALEDIR );
textdomain( PACKAGE );
#endif
#endif
}
static void
wrong_args( const char *text )
{
log_error("usage: kbxutil %s\n", text);
gpg_exit ( 1 );
}
static int
hextobyte( const byte *s )
{
int c;
if( *s >= '0' && *s <= '9' )
c = 16 * (*s - '0');
else if( *s >= 'A' && *s <= 'F' )
c = 16 * (10 + *s - 'A');
else if( *s >= 'a' && *s <= 'f' )
c = 16 * (10 + *s - 'a');
else
return -1;
s++;
if( *s >= '0' && *s <= '9' )
c += *s - '0';
else if( *s >= 'A' && *s <= 'F' )
c += 10 + *s - 'A';
else if( *s >= 'a' && *s <= 'f' )
c += 10 + *s - 'a';
else
return -1;
return c;
}
static char *
format_fingerprint ( const char *s )
{
int i, c;
byte fpr[20];
for (i=0; i < 20 && *s; ) {
if ( *s == ' ' || *s == '\t' ) {
s++;
continue;
}
c = hextobyte(s);
if (c == -1) {
return NULL;
}
fpr[i++] = c;
s += 2;
}
return gcry_xstrdup ( fpr );
}
static int
format_keyid ( const char *s, u32 *kid )
{
char helpbuf[9];
switch ( strlen ( s ) ) {
case 8:
kid[0] = 0;
kid[1] = strtoul( s, NULL, 16 );
return 10;
case 16:
mem2str( helpbuf, s, 9 );
kid[0] = strtoul( helpbuf, NULL, 16 );
kid[1] = strtoul( s+8, NULL, 16 );
return 11;
}
return 0; /* error */
}
int
main( int argc, char **argv )
{
ARGPARSE_ARGS pargs;
enum cmd_and_opt_values cmd = 0;
set_strusage( my_strusage );
log_set_name("kbxutil");
/* check that the libraries are suitable. Do it here because
* the option parse may need services of the library */
if ( !gcry_check_version ( "1.1.0a" ) ) {
log_fatal(_("libgcrypt is too old (need %s, have %s)\n"),
VERSION, gcry_check_version(NULL) );
}
create_dotlock(NULL); /* register locking cleanup */
i18n_init();
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1; /* do not remove the args */
while( arg_parse( &pargs, opts) ) {
switch( pargs.r_opt ) {
case oVerbose:
opt.verbose++;
gcry_control( GCRYCTL_SET_VERBOSITY, (int)opt.verbose );
break;
case oDebug: opt.debug |= pargs.r.ret_ulong; break;
case oDebugAll: opt.debug = ~0; break;
case aFindByFpr:
case aFindByKid:
case aFindByUid:
cmd = pargs.r_opt;
break;
default : pargs.err = 2; break;
}
}
if( log_get_errorcount(0) )
gpg_exit(2);
if ( !cmd ) { /* default is to list a KBX file */
if( !argc ) {
print_kbxfile( NULL );
}
else {
for ( ; argc; argc--, argv++ ) {
print_kbxfile( *argv );
}
}
}
else if ( cmd == aFindByFpr ) {
char *fpr;
if ( argc != 2 )
wrong_args ("kbxfile foingerprint");
fpr = format_fingerprint ( argv[1] );
if ( !fpr )
log_error ("invalid formatted fingerprint\n");
else {
kbxfile_search_by_fpr ( argv[0], fpr );
gcry_free ( fpr );
}
}
else if ( cmd == aFindByKid ) {
u32 kid[2];
int mode;
if ( argc != 2 )
wrong_args ("kbxfile short-or-long-keyid");
mode = format_keyid ( argv[1], kid );
if ( !mode )
log_error ("invalid formatted keyID\n");
else {
kbxfile_search_by_kid ( argv[0], kid, mode );
}
}
else if ( cmd == aFindByUid ) {
if ( argc != 2 )
wrong_args ("kbxfile userID");
kbxfile_search_by_uid ( argv[0], argv[1] );
}
else
log_error ("unsupported action\n");
gpg_exit(0);
return 8; /*NEVER REACHED*/
}
void
gpg_exit( int rc )
{
if( opt.debug & DBG_MEMSTAT_VALUE ) {
gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
}
if( opt.debug )
gcry_control( GCRYCTL_DUMP_SECMEM_STATS );
rc = rc? rc : log_get_errorcount(0)? 2 :
gpg_errors_seen? 1 : 0;
exit(rc );
}