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

@ -65,7 +65,10 @@
</indexterm>
<function>gcry_md_open</function> creates the context required for
the message digest functions. The hash algorithm may optionally be
specified.
specified. It is possible to use these functions as MAC functons; therefore
the flag <literal/GCRY_MD_FLAG_HMAC/ must be given along with the
hash functions. Other MAC algorithms than HMAC are currently not
supported. The key for the MAC must be set using the gcry_md_setkey macro.
<function>gcry_md_close</function> releases all resources associated
with the context.
<function>gcry_md_enable</function> may be used to enable hash
@ -149,6 +152,7 @@
<refnamediv>
<refname>gcry_md_ctl</refname>
<refname>gcry_md_final</refname>
<refname>gcry_md_setkey</refname>
<refpurpose>perform special operations on a digest context</refpurpose>
</refnamediv>
@ -179,9 +183,18 @@
</para>
<para>
Currently defined values for <parameter>cmd</> are:
<literal>GCRYCTL_FINALIZE</> and the conevnience macro
</para>
<para>
<literal>GCRYCTL_FINALIZE</> and the convenience macro
<function>gcry_md_final(a)</>
</para>
<para>
<literal>GCRYCTL_SET_KEY</> and the convenience macro
<function>gcry_md_setkey(a)</>. This is used to turn these
hash functions into MAC functions. The key may be any string
of the speicified length. The type of the MAC is determined
by special flags set with the open function.
</para>
</refentry>
<!--**********************************************

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