From fcfec25620c2cb04d96e7e0efbec1fb5f065a806 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Sat, 10 Nov 2001 18:06:11 +0000 Subject: [PATCH] Started with keybox implementation by basing it on code from the GnuPG devel branch. --- kbx/kbxutil.c | 337 ++++++++++++++++++++ kbx/keybox-blob.c | 755 ++++++++++++++++++++++++++++++++++++++++++++ kbx/keybox-defs.h | 147 +++++++++ kbx/keybox-dump.c | 250 +++++++++++++++ kbx/keybox-errors.c | 40 +++ kbx/keybox-file.c | 113 +++++++ kbx/keybox-init.c | 73 +++++ kbx/keybox-search.c | 158 +++++++++ kbx/keybox-util.c | 72 +++++ kbx/keybox.h | 99 ++++++ kbx/mkerrors | 71 +++++ 11 files changed, 2115 insertions(+) create mode 100644 kbx/kbxutil.c create mode 100644 kbx/keybox-blob.c create mode 100644 kbx/keybox-defs.h create mode 100644 kbx/keybox-dump.c create mode 100644 kbx/keybox-errors.c create mode 100644 kbx/keybox-file.c create mode 100644 kbx/keybox-init.c create mode 100644 kbx/keybox-search.c create mode 100644 kbx/keybox-util.c create mode 100644 kbx/keybox.h create mode 100755 kbx/mkerrors diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c new file mode 100644 index 000000000..8c3dee97a --- /dev/null +++ b/kbx/kbxutil.c @@ -0,0 +1,337 @@ +/* kbxutil.c - The Keybox utility + * Copyright (C) 2000, 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 +#include +#include +#include +#include +#include +#include + +#include + +#include "../jnlib/logging.h" +#include "../jnlib/argparse.h" +#include "../jnlib/stringhelp.h" +#include "i18n.h" +#include "keybox-defs.h" + +enum cmd_and_opt_values { + aNull = 0, + oArmor = 'a', + oDryRun = 'n', + oOutput = 'o', + oQuiet = 'q', + oVerbose = 'v', + + aNoSuchCmd = 500, /* force other values not to be a letter */ + aFindByFpr, + aFindByKid, + aFindByUid, + + oDebug, + oDebugAll, + + oNoArmor, + + + 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, "@" }, + { 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") }, + + { oDebug, "debug" ,4|16, N_("set debugging flags")}, + { oDebugAll, "debug-all" ,0, N_("enable full debugging")}, + + {0} /* end of list */ +}; + + +void myexit (int rc); + +int keybox_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 " PACKAGE_BUGREPORT ".\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 Keybox 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); */ +/* myexit ( 1 ); */ +/* } */ + + +#if 0 +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; +} +#endif + +#if 0 +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 ); +} +#endif + +#if 0 +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 */ +} +#endif + + +int +main( int argc, char **argv ) +{ + ARGPARSE_ARGS pargs; + enum cmd_and_opt_values cmd = 0; + + set_strusage( my_strusage ); + /*log_set_name("kbxutil"); fixme */ +#if 0 + /* 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.4" ) ) + { + log_fatal(_("libgcrypt is too old (need %s, have %s)\n"), + "1.1.4", gcry_check_version(NULL) ); + } +#endif + + /*create_dotlock(NULL); register locking cleanup */ + i18n_init(); + + /* We need to use the gcry malloc function becuase jnlib does use them */ + keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); + + + 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) ) + myexit(2); + + if (!cmd) + { /* default is to list a KBX file */ + if (!argc) + _keybox_dump_file (NULL, stdout); + else + { + for (; argc; argc--, argv++) + _keybox_dump_file (*argv, stdout); + } + } +#if 0 + 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] ); + } +#endif + else + log_error ("unsupported action\n"); + + myexit(0); + return 8; /*NEVER REACHED*/ +} + + +void +myexit( 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 : + keybox_errors_seen? 1 : 0; + exit(rc ); +} + + diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c new file mode 100644 index 000000000..7db62165a --- /dev/null +++ b/kbx/keybox-blob.c @@ -0,0 +1,755 @@ +/* keybox-blob.c - KBX Blob handling + * Copyright (C) 2000, 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 + */ + + +/* The keybox data formats + +The KeyBox uses an augmented OpenPGP/X.509 key format. This makes +random access to a keyblock/Certificate easier and also gives the +opportunity to store additional information (e.g. the fingerprint) +along with the key. All integers are stored in network byte order, +offsets are counted from the beginning of the Blob. + +The first record of a plain KBX file has a special format: + + u32 length of the first record + byte Blob type (1) + byte version number (1) + byte reserved + byte reserved + u32 magic 'KBXf' + byte pgp_marginals used for validity calculation of this file + byte pgp_completes ditto. + byte pgp_cert_depth ditto. + +The OpenPGP KBX Blob looks like this: + + u32 length of this blob (including these 4 bytes) + byte Blob type (2) + byte version number of this blob type (1) + u16 Blob flags + bit 0 = contains secret key material + + u32 offset to the OpenPGP keyblock + u32 length of the keyblock + u16 number of keys (at least 1!) + u16 size of additional key information + n times: + b20 The keys fingerprint + (fingerprints are always 20 bytes, MD5 left padded with zeroes) + u32 offset to the n-th key's keyID (a keyID is always 8 byte) + u16 special key flags + bit 0 = + u16 reserved + u16 number of user IDs + u16 size of additional user ID information + n times: + u32 offset to the n-th user ID + u32 length of this user ID. + u16 special user ID flags. + bit 0 = + byte validity + byte reserved + u16 number of signatures + u16 size of signature information (4) + u32 expiration time of signature with some special values: + 0x00000000 = not checked + 0x00000001 = missing key + 0x00000002 = bad signature + 0x10000000 = valid and expires at some date in 1978. + 0xffffffff = valid and does not expire + u8 assigned ownertrust + u8 all_validity + u16 reserved + u32 recheck_after + u32 Newest timestamp in the keyblock (useful for KS syncronsiation?) + u32 Blob created at + u32 size of reserved space (not including this field) + reserved space + + Here we might want to put other data + + Here comes the keyblock + + maybe we put a signature here later. + + b16 MD5 checksum (useful for KS syncronisation) + +*/ + + +#include +#include +#include +#include +#include +#include +#include + +#include "keybox-defs.h" + +/* special values of the signature status */ +#define SF_NONE(a) ( !(a) ) +#define SF_NOKEY(a) ((a) & (1<<0)) +#define SF_BAD(a) ((a) & (1<<1)) +#define SF_VALID(a) ((a) & (1<<29)) + + +struct membuf { + size_t len; + size_t size; + char *buf; + int out_of_core; +}; + + +/* #if MAX_FINGERPRINT_LEN < 20 */ +/* #error fingerprints are 20 bytes */ +/* #endif */ + +struct keyboxblob_key { + char fpr[20]; + u32 off_kid; + ulong off_kid_addr; + u16 flags; +}; +struct keyboxblob_uid { + ulong off_addr; + u32 len; + u16 flags; + byte validity; +}; + +struct keyid_list { + struct keyid_list *next; + int seqno; + byte kid[8]; +}; + +struct fixup_list { + struct fixup_list *next; + u32 off; + u32 val; +}; + + +struct keyboxblob { + byte *blob; + size_t bloblen; + + /* stuff used only by keybox_create_blob */ + int nkeys; + struct keyboxblob_key *keys; + int nuids; + struct keyboxblob_uid *uids; + int nsigs; + u32 *sigs; + struct fixup_list *fixups; + + struct keyid_list *temp_kids; + struct membuf *buf; /* temporary store for the blob */ +}; + + + +/* A simple implemnation of a dynamic buffer. Use init_membuf() to + create a buffer, put_membuf to append bytes and get_membuf to + release and return the buffer. Allocation errors are detected but + only returned at the final get_membuf(), this helps not to clutter + the code with out of core checks. */ + +static void +init_membuf (struct membuf *mb, int initiallen) +{ + mb->len = 0; + mb->size = initiallen; + mb->out_of_core = 0; + mb->buf = xtrymalloc (initiallen); + if (!mb->buf) + mb->out_of_core = 1; +} + +static void +put_membuf (struct membuf *mb, const void *buf, size_t len) +{ + if (mb->out_of_core) + return; + + if (mb->len + len >= mb->size) + { + char *p; + + mb->size += len + 1024; + p = xtryrealloc (mb->buf, mb->size); + if (!p) + { + mb->out_of_core = 1; + return; + } + mb->buf = p; + } + memcpy (mb->buf + mb->len, buf, len); + mb->len += len; +} + +static void * +get_membuf (struct membuf *mb, size_t *len) +{ + char *p; + + if (mb->out_of_core) + { + xfree (mb->buf); + mb->buf = NULL; + return NULL; + } + + p = mb->buf; + *len = mb->len; + mb->buf = NULL; + mb->out_of_core = 1; /* don't allow a reuse */ + return p; +} + + +static void +put8 (struct membuf *mb, byte a ) +{ + put_membuf (mb, &a, 1); +} + +static void +put16 (struct membuf *mb, u16 a ) +{ + unsigned char tmp[2]; + tmp[0] = a>>8; + tmp[1] = a; + put_membuf (mb, tmp, 2); +} + +static void +put32 (struct membuf *mb, u32 a ) +{ + unsigned char tmp[4]; + tmp[0] = a>>24; + tmp[1] = a>>16; + tmp[2] = a>>8; + tmp[3] = a; + put_membuf (mb, tmp, 4); +} + + +/* + Some wrappers +*/ + +static u32 +make_timestamp (void) +{ + return time(NULL); +} + + + +#ifdef KEYBOX_WITH_OPENPGP +/* + OpenPGP specific stuff +*/ + + +/* + 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 fixup or -1 for out of core. The value must be + a non-zero value */ +static int +pgp_temp_store_kid (KEYBOXBLOB blob, PKT_public_key *pk) +{ + struct keyid_list *k, *r; + + k = xtrymalloc (sizeof *k); + if (!k) + return -1; + k->kid[0] = pk->keyid[0] >> 24 ; + k->kid[1] = pk->keyid[0] >> 16 ; + k->kid[2] = pk->keyid[0] >> 8 ; + k->kid[3] = pk->keyid[0] ; + k->kid[4] = pk->keyid[0] >> 24 ; + k->kid[5] = pk->keyid[0] >> 16 ; + k->kid[6] = pk->keyid[0] >> 8 ; + k->kid[7] = pk->keyid[0] ; + k->seqno = 0; + k->next = blob->temp_kids; + blob->temp_kids = k; + for (r=k; r; r = r->next) + k->seqno++; + + return k->seqno; +} + +static int +pgp_create_key_part (KEYBOXBLOB blob, KBNODE keyblock) +{ + KBNODE node; + size_t fprlen; + int n; + + for (n=0, node = keyblock; node; node = node->next) + { + 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, 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); + memset (blob->keys[n].fpr, 0, 4); + blob->keys[n].off_kid = pgp_temp_store_kid (blob, pk); + } + else + { + blob->keys[n].off_kid = 0; /* will be fixed up later */ + } + blob->keys[n].flags = 0; + n++; + } + else if ( node->pkt->pkttype == PKT_SECRET_KEY + || node->pkt->pkttype == PKT_SECRET_SUBKEY ) + { + never_reached (); /* actually not yet implemented */ + } + } + assert (n == blob->nkeys); + return 0; +} + +static int +pgp_create_uid_part (KEYBOXBLOB blob, KBNODE keyblock) +{ + KBNODE node; + int n; + + for (n=0, node = keyblock; node; node = node->next) + { + if (node->pkt->pkttype == PKT_USER_ID) + { + PKT_user_id *u = node->pkt->pkt.user_id; + + blob->uids[n].len = u->len; + blob->uids[n].flags = 0; + blob->uids[n].validity = 0; + n++; + } + } + assert (n == blob->nuids); + return 0; +} + +static int +pgp_create_sig_part (KEYBOXBLOB blob, KBNODE keyblock) +{ + KBNODE node; + int n; + + for (n=0, node = keyblock; node; node = node->next) + { + if (node->pkt->pkttype == PKT_SIGNATURE) + { + PKT_signature *sig = node->pkt->pkt.signature; + + blob->sigs[n] = 0; /* FIXME: check the signature here */ + n++; + } + } + assert( n == blob->nsigs ); + return 0; +} + +static int +pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock) +{ + struct membuf *a = blob->buf; + KBNODE node; + int rc; + int n; + u32 kbstart = a->len; + + { + struct fixup_list *fl = xtrycalloc(1, sizeof *fl ); + + if (!fl) + return KEYBOX_Out_Of_Core; + fl->off = 8; + fl->val = kbstart; + fl->next = blob->fixups; + blob->fixups = fl; + } + + for (n = 0, node = keyblock; node; node = node->next) + { + rc = build_packet ( a, node->pkt ); + if ( rc ) { + gpg_log_error ("build_packet(%d) for keyboxblob failed: %s\n", + node->pkt->pkttype, gpg_errstr(rc) ); + return GPGERR_WRITE_FILE; + } + if ( node->pkt->pkttype == PKT_USER_ID ) + { + PKT_user_id *u = node->pkt->pkt.user_id; + /* build_packet has set the offset of the name into u ; + * now we can do the fixup */ + struct fixup_list *fl = xcalloc(1, sizeof *fl ); /* fixme */ + fl->off = blob->uids[n].off_addr; + fl->val = u->stored_at; + fl->next = blob->fixups; + blob->fixups = fl; + n++; + } + } + assert (n == blob->nuids); + + { + struct fixup_list *fl = xcalloc(1, sizeof *fl ); /* fixme */ + + fl->off = 12; + fl->val = a->len - kbstart; + fl->next = blob->fixups; + blob->fixups = fl; + } + + return 0; +} + +#endif /*KEYBOX_WITH_OPENPGP*/ + + +#ifdef KEYBOX_WITH_X509 +/* + X.509 specific stuff + */ + +#endif /*KEYBOX_WITH_X509*/ + +/* Write a stored keyID out to the buffer */ +static void +write_stored_kid (KEYBOXBLOB blob, int seqno) +{ + struct keyid_list *r; + + for ( r = blob->temp_kids; r; r = r->next ) + { + if (r->seqno == seqno ) + { + put_membuf (blob->buf, r->kid, 8); + return; + } + } + never_reached (); +} + +/* Release a list of key IDs */ +static void +release_kid_list (struct keyid_list *kl) +{ + struct keyid_list *r, *r2; + + for ( r = kl; r; r = r2 ) + { + r2 = r->next; + xfree (r); + } +} + + + +static int +create_blob_header (KEYBOXBLOB blob, int blobtype) +{ + struct membuf *a = blob->buf; + int i; + + put32 ( a, 0 ); /* blob length, needs fixup */ + put8 ( a, blobtype); + put8 ( a, 1 ); /* blob type version */ + put16 ( a, 0 ); /* blob flags */ + + put32 ( a, 0 ); /* offset to the raw data, needs fixup */ + put32 ( a, 0 ); /* length of the raw data, needs fixup */ + + put16 ( a, blob->nkeys ); + put16 ( a, 20 + 4 + 2 + 2 ); /* size of key info */ + for ( i=0; i < blob->nkeys; i++ ) + { + put_membuf (a, blob->keys[i].fpr, 20); + blob->keys[i].off_kid_addr = a->len; + put32 ( a, 0 ); /* offset to keyid, fixed up later */ + put16 ( a, blob->keys[i].flags ); + put16 ( a, 0 ); /* reserved */ + } + + 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 = a->len; + put32 ( a, 0 ); /* offset to userid, fixed up later */ + put32 ( a, blob->uids[i].len ); + put16 ( a, blob->uids[i].flags ); + put8 ( a, 0 ); /* validity */ + put8 ( a, 0 ); /* reserved */ + } + + put16 ( a, blob->nsigs ); + put16 ( a, 4 ); /* size of sig info */ + for (i=0; i < blob->nsigs; i++) + { + put32 ( a, blob->sigs[i]); + } + + put8 ( a, 0 ); /* assigned ownertrust */ + put8 ( a, 0 ); /* validity of all user IDs */ + put16 ( a, 0 ); /* reserved */ + put32 ( a, 0 ); /* time of next recheck */ + put32 ( a, 0 ); /* newest timestamp (none) */ + put32 ( a, make_timestamp() ); /* creation time */ + put32 ( a, 0 ); /* size of reserved space */ + /* reserved space (which is currently of size 0) */ + + /* We need to store the keyids for all pgp v3 keys because those key + IDs are not part of the fingerprint. While we are doing that, we + fixup all the keyID offsets */ + for (i=0; i < blob->nkeys; i++ ) + { + struct fixup_list *fl = xtrycalloc(1, sizeof *fl ); + + if (!fl) + return KEYBOX_Out_Of_Core; + + fl->off = blob->keys[i].off_kid_addr; + fl->next = blob->fixups; + blob->fixups = fl; + + if (blob->keys[i].off_kid) + { /* this is a v3 one */ + fl->val = a->len; + write_stored_kid (blob, blob->keys[i].off_kid); + } + else + { /* the better v4 key IDs - just store an offset 8 bytes back */ + fl->val = blob->keys[i].off_kid_addr - 8; + } + } + + return 0; +} + + + +static int +create_blob_trailer (KEYBOXBLOB blob) +{ + return 0; +} + + +static int +create_blob_finish (KEYBOXBLOB blob) +{ + struct membuf *a = blob->buf; + byte *p; + char *pp; + int i; + size_t n; + + /* write a placeholder for the checksum */ + for (i = 0; i < 16; i++ ) + put32 (a, 0); + + /* get the memory area */ + p = a->buf; + n = a->len; + assert (n >= 20); + + /* fixup the length */ + { + struct fixup_list *fl = xtrycalloc(1, sizeof *fl); + if (!fl) + return KEYBOX_Out_Of_Core; + fl->off = 0; + fl->val = n; + fl->next = blob->fixups; + blob->fixups = fl; + } + + /* 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 = xtrymalloc (n); + if ( !pp ) + return KEYBOX_Out_Of_Core; + memcpy (pp , p, n); + blob->blob = pp; + blob->bloblen = n; + + return 0; +} + + +#ifdef KEYBOX_WITH_OPENPGP + +int +_keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock) +{ + int rc = 0; + KBNODE node; + KEYBOXBLOB blob; + + *r_blob = NULL; + blob = xtrycalloc (1, sizeof *blob); + if( !blob ) + return KEYBOX_Out_Of_Core; + + /* fixme: Do some sanity checks on the keyblock */ + + /* count userids and keys so that we can allocate the arrays */ + for (node = keyblock; node; node = node->next) + { + switch (node->pkt->pkttype) + { + case PKT_PUBLIC_KEY: + case PKT_SECRET_KEY: + case PKT_PUBLIC_SUBKEY: + case PKT_SECRET_SUBKEY: blob->nkeys++; break; + case PKT_USER_ID: blob->nuids++; break; + case PKT_SIGNATURE: blob->nsigs++; break; + default: break; + } + } + + 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; + } + + rc = pgp_create_key_part ( blob, keyblock ); + if (rc) + goto leave; + rc = pgp_create_uid_part ( blob, keyblock ); + if (rc) + goto leave; + rc = pgp_create_sig_part ( blob, keyblock ); + if (rc) + goto leave; + + init_membuf (blob->buf, 1024); + rc = create_blob_header (blob, BLOBTYPE_OPENPGP); + if (rc) + goto leave; + rc = pgp_create_blob_keyblock (blob, keyblock); + 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_OPENPGP*/ + + + +int +_keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen) +{ + KEYBOXBLOB blob; + + *r_blob = NULL; + blob = xtrycalloc (1, sizeof *blob); + if (!blob) + return KEYBOX_Out_Of_Core; + + blob->blob = image; + blob->bloblen = imagelen; + *r_blob = blob; + return 0; +} + +void +_keybox_release_blob (KEYBOXBLOB blob) +{ + if (!blob) + return; +/* if (blob->buf) */ +/* iobuf_cancel( blob->buf ); */ + xfree (blob->keys ); + xfree (blob->uids ); + xfree (blob->sigs ); + xfree (blob->blob ); + xfree (blob ); +} + + + +const char * +_keybox_get_blob_image ( KEYBOXBLOB blob, size_t *n ) +{ + *n = blob->bloblen; + return blob->blob; +} + + diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h new file mode 100644 index 000000000..2adbdd22f --- /dev/null +++ b/kbx/keybox-defs.h @@ -0,0 +1,147 @@ +/* keybox-defs.h - interal Keybox defintions + * 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 + */ + +#ifndef KEYBOX_DEFS_H +#define KEYBOX_DEFS_H 1 + +#include /* off_t */ +#include "keybox.h" + +#ifndef HAVE_BYTE_TYPEDEF +typedef unsigned char byte; /* fixme */ +#endif +#ifndef HAVE_U16_TYPEDEF +typedef unsigned short u16; /* fixme */ +#endif +#ifndef HAVE_U32_TYPEDEF +typedef unsigned int u32; /* fixme */ +#endif + +enum { + BLOBTYPE_HEADER = 1, + BLOBTYPE_PGP = 2, + BLOBTYPE_X509 = 3 +}; + + + +typedef struct keybox_name *KB_NAME; +typedef struct keybox_name const * CONST_KB_NAME; +struct keybox_name { + struct keybox_name *next; + int secret; + /*DOTLOCK lockhd;*/ + int is_locked; + int did_full_scan; + char fname[1]; +}; + + + +struct keybox_handle { + CONST_KB_NAME resource; + int secret; /* this is for a secret keybox */ + struct { + CONST_KB_NAME kb; + /*IOBUF iobuf;*/ + int eof; + int error; + } current; + struct { + CONST_KB_NAME kb; + off_t offset; + size_t pk_no; + size_t uid_no; + unsigned int n_packets; /*used for delete and update*/ + } found; + struct { + char *name; + char *pattern; + } word_match; +}; + + +typedef struct keyboxblob *KEYBOXBLOB; + + + +/*-- keybox-blob.c --*/ +int _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen); +void _keybox_release_blob (KEYBOXBLOB blob); +const char *_keybox_get_blob_image (KEYBOXBLOB blob, size_t *n); + +/*-- keybox-file.c --*/ +int _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp); + +/*-- keybox-dump.c --*/ +int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp); +int _keybox_dump_file (const char *filename, FILE *outfp); + + +/*-- keybox-util.c --*/ +void *_keybox_malloc (size_t n); +void *_keybox_calloc (size_t n, size_t m); +void *_keybox_realloc (void *p, size_t n); +void _keybox_free (void *p); + +#define xtrymalloc(a) _keybox_malloc ((a)) +#define xtrycalloc(a,b) _keybox_calloc ((a),(b)) +#define xtryrealloc(a,b) _keybox_realloc((a),(b)) +#define xfree(a) _keybox_free ((a)) + + +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) +#ifndef STR + #define STR(v) #v +#endif +#define STR2(v) STR(v) + +/* + a couple of handy macros +*/ + +#define return_if_fail(expr) do { \ + if (!(expr)) { \ + fprintf (stderr, "%s:%d: assertion `%s' failed\n", \ + __FILE__, __LINE__, #expr ); \ + return; \ + } } while (0) +#define return_null_if_fail(expr) do { \ + if (!(expr)) { \ + fprintf (stderr, "%s:%d: assertion `%s' failed\n", \ + __FILE__, __LINE__, #expr ); \ + return NULL; \ + } } while (0) +#define return_val_if_fail(expr,val) do { \ + if (!(expr)) { \ + fprintf (stderr, "%s:%d: assertion `%s' failed\n", \ + __FILE__, __LINE__, #expr ); \ + return (val); \ + } } while (0) +#define never_reached() do { \ + fprintf (stderr, "%s:%d: oops; should never get here\n", \ + __FILE__, __LINE__ ); \ + } while (0) + + +#endif /*KEYBOX_DEFS_H*/ + + diff --git a/kbx/keybox-dump.c b/kbx/keybox-dump.c new file mode 100644 index 000000000..6022900f2 --- /dev/null +++ b/kbx/keybox-dump.c @@ -0,0 +1,250 @@ +/* keybox-dump.c - Debug helpers + * 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 +#include +#include +#include +#include + +#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 +get16 (const byte *buffer) +{ + ulong a; + a = *buffer << 8; + a |= buffer[1]; + return a; +} + +static int +dump_header_blob (const byte *buffer, size_t length, FILE *fp) +{ + fprintf (fp, "Version: %d\n", buffer[5]); + if ( memcmp (buffer+8, "KBXf", 4)) + fprintf (fp, "[Error: invalid magic number]\n"); + return 0; +} + + +/* Dump one block to FP */ +int +_keybox_dump_blob (KEYBOXBLOB blob, FILE *fp) +{ + const byte *buffer; + size_t length; + int type; + ulong n, nkeys, keyinfolen; + ulong nuids, uidinfolen; + ulong nsigs, siginfolen; + ulong rawdata_off, rawdata_len; + const byte *p; + + buffer = _keybox_get_blob_image (blob, &length); + + if (length < 40) + { + fprintf (fp, "[blob too short]\n"); + return -1; + } + + n = get32( buffer ); + if (n > length) + fprintf (fp, "[blob larger than length - output truncated]\n"); + else + length = n; /* ignore the rest */ + + fprintf (fp, "Length: %lu\n", n ); + type = buffer[4]; + switch (type) + { + case BLOBTYPE_HEADER: + fprintf (fp, "Type: Header\n"); + return dump_header_blob (buffer, length, fp); + case BLOBTYPE_PGP: + fprintf (fp, "Type: OpenPGP\n"); + break; + case BLOBTYPE_X509: + fprintf (fp, "Type: X.509\n"); + break; + default: + fprintf (fp, "Type: %d\n", type); + fprintf (fp, "[can't dump this blob type]\n"); + return 0; + } + fprintf (fp, "Version: %d\n", buffer[5]); + + n = get16 (buffer + 6); + fprintf( fp, "Blob-Flags: %04lX\n", n); + + rawdata_off = get32 (buffer + 8); + rawdata_len = get32 (buffer + 12); + + fprintf( fp, "Data-Offset: %lu\n", rawdata_off ); + fprintf( fp, "Data-Length: %lu\n", rawdata_len ); + + nkeys = get16 (buffer + 16); + fprintf (fp, "Key-Count: %lu\n", nkeys ); + if (!nkeys) + fprintf (fp, "[Error: no keys]\n"); + if (nkeys > 1 && type == BLOBTYPE_X509) + fprintf (fp, "[Error: only one key allowed for X509]\n"); + + 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 ("a time"/*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", "0"/*strtimestamp(n)*/ ); + n = get32 (p ); p += 4; + fprintf (fp, "Created-At: %s\n", "0"/*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; +} + + + +int +_keybox_dump_file (const char *filename, FILE *outfp) +{ + FILE *fp; + KEYBOXBLOB blob; + int rc; + unsigned long count = 0; + + if (!filename) + { + filename = "-"; + fp = stdin; + } + else + fp = fopen (filename, "rb"); + if (!fp) + { + fprintf (outfp, "can't open `%s': %s\n", filename, strerror(errno)); + return KEYBOX_File_Error; + } + + while ( !(rc = _keybox_read_blob (&blob, fp)) ) + { + fprintf (outfp, "BEGIN-RECORD: %lu\n", count ); + _keybox_dump_blob (blob, outfp); + _keybox_release_blob (blob); + fprintf (outfp, "END-RECORD\n"); + count++; + } + if (rc == -1) + rc = 0; + if (rc) + fprintf (outfp, "error reading `%s': %s\n", filename, + rc == KEYBOX_Read_Error? keybox_strerror(rc):strerror (errno)); + + if (fp != stdin) + fclose (fp); + return rc; +} diff --git a/kbx/keybox-errors.c b/kbx/keybox-errors.c new file mode 100644 index 000000000..bd03cdff3 --- /dev/null +++ b/kbx/keybox-errors.c @@ -0,0 +1,40 @@ +/* Generated automatically by mkerrors */ +/* Do not edit! */ + +#include +#include "keybox-defs.h" + +/** + * keybox_strerror: + * @err: Error code + * + * This function returns a textual representaion of the given + * errorcode. If this is an unknown value, a string with the value + * is returned (Beware: it is hold in a static buffer). + * + * Return value: String with the error description. + **/ +const char * +keybox_strerror (KeyboxError err) +{ + const char *s; + static char buf[25]; + + switch (err) + { + case KEYBOX_No_Error: s="no error"; break; + case KEYBOX_General_Error: s="general error"; break; + case KEYBOX_Out_Of_Core: s="out of core"; break; + case KEYBOX_Invalid_Value: s="invalid value"; break; + case KEYBOX_Timeout: s="timeout"; break; + case KEYBOX_Read_Error: s="read error"; break; + case KEYBOX_Write_Error: s="write error"; break; + case KEYBOX_File_Error: s="file error"; break; + case KEYBOX_Blob_Too_Short: s="blob too short"; break; + case KEYBOX_Blob_Too_Large: s="blob too large"; break; + default: sprintf (buf, "ec=%d", err ); s=buf; break; + } + + return s; +} + diff --git a/kbx/keybox-file.c b/kbx/keybox-file.c new file mode 100644 index 000000000..66bca504f --- /dev/null +++ b/kbx/keybox-file.c @@ -0,0 +1,113 @@ +/* keybox-file.c - file oeprations + * 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 +#include +#include +#include + +#include "keybox-defs.h" + + +int +_keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp) +{ + char *image; + size_t imagelen = 0; + int c1, c2, c3, c4; + int rc; + + *r_blob = NULL; + if ((c1 = getc (fp)) == EOF + || (c2 = getc (fp)) == EOF + || (c3 = getc (fp)) == EOF + || (c4 = getc (fp)) == EOF ) { + if ( c1 == EOF && !ferror (fp) ) + return -1; /* eof */ + return KEYBOX_Read_Error; + } + + imagelen = (c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4; + if (imagelen > 500000) /* sanity check */ + return KEYBOX_Blob_Too_Large; + + if (imagelen < 4) + return KEYBOX_Blob_Too_Short; + + image = xtrymalloc (imagelen); + if (!image) + return KEYBOX_Out_Of_Core; + + image[0] = c1; image[1] = c2; image[2] = c3; image[3] = c4; + if (fread (image+4, imagelen-4, 1, fp) != 1) + { + return KEYBOX_Read_Error; + } + + rc = _keybox_new_blob (r_blob, image, imagelen); + if (rc) + xfree (image); + return rc; +} + + + + + +void +export_as_kbxfile(void) +{ +#if 0 + KBPOS kbpos; + KBNODE keyblock = NULL; + int rc=0; + + rc = enum_keyblocks_begin( &kbpos, 0 ); + if( rc ) { + if( rc != -1 ) + log_error("enum_keyblocks(open) failed: %s\n", gpg_errstr(rc) ); + goto leave; + } + + while( !(rc = enum_keyblocks_next( kbpos, 1, &keyblock )) ) { + KBXBLOB blob; + const char *p; + size_t n; + + merge_keys_and_selfsig( keyblock ); + rc = kbx_create_blob ( &blob, keyblock ); + if( rc ) { + log_error("kbx_create_blob failed: %s\n", gpg_errstr(rc) ); + goto leave; + } + p = kbx_get_blob_image ( blob, &n ); + fwrite( p, n, 1, stdout ); + kbx_release_blob ( blob ); + } + + if( rc && rc != -1 ) + log_error("enum_keyblocks(read) failed: %s\n", gpg_errstr(rc)); + + leave: + enum_keyblocks_end( kbpos ); + release_kbnode( keyblock ); +#endif +} + diff --git a/kbx/keybox-init.c b/kbx/keybox-init.c new file mode 100644 index 000000000..a4649d18c --- /dev/null +++ b/kbx/keybox-init.c @@ -0,0 +1,73 @@ +/* keybox-init.c - Initalization of the library + * 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 +#include +#include +#include +#include + +#include "keybox-defs.h" + +/* + * Register a filename for plain keybox files. Returns a pointer to + * be used to create a handles etc or NULL to indicate that it has + * already been registered */ +void * +keybox_register_file (const char *fname, int secret) +{ + return NULL; +#if 0 + KB_NAME kr; + + if (active_handles) + BUG (); /* We don't allow that */ + + for (kr=kb_names; kr; kr = kr->next) { + if ( !compare_filenames (kr->fname, fname) ) + return NULL; /* already registered */ + } + + kr = m_alloc (sizeof *kr + strlen (fname)); + strcpy (kr->fname, fname); + kr->secret = !!secret; + kr->lockhd = NULL; + kr->is_locked = 0; + kr->did_full_scan = 0; + /* keep a list of all issued pointers */ + kr->next = kb_names; + kb_names = kr; + + /* create the offset table the first time a function here is used */ + if (!kb_offtbl) + kb_offtbl = new_offset_hash_table (); + + return kr; +#endif +} + +int +keybox_is_writable (void *token) +{ + KB_NAME r = token; + + return r? !access (r->fname, W_OK) : 0; +} + diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c new file mode 100644 index 000000000..d2c61ff21 --- /dev/null +++ b/kbx/keybox-search.c @@ -0,0 +1,158 @@ +/* keybox-search.c - Search 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 +#include +#include +#include + +#include "keybox-defs.h" + + +/**************** + * Check whether the given fingerprint (20 bytes) is in the + * given keyblob. fpr is always 20 bytes. + * Return: 0 = found + * -1 = not found + other = error (fixme: do not always reurn gpgerr_general) + */ +int +keybox_blob_has_fpr ( KEYBOXBLOB blob, const byte *fpr ) +{ + 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 +keybox_blob_has_kid ( KEYBOXBLOB blob, const byte *keyidbuf, size_t keyidlen ) +{ + ulong n, nkeys, keyinfolen, off; + const byte *p, *pend; + byte *buffer = blob->blob; + size_t buflen = blob->bloblen; + + if ( buflen < 40 ) + return GPGERR_GENERAL; /* blob too short */ + n = get32( buffer ); + if ( n > buflen ) + return GPGERR_GENERAL; /* blob larger than announced length */ + buflen = n; /* ignore trailing stuff */ + pend = buffer + n - 1; + + if ( buffer[4] != 2 ) + return GPGERR_GENERAL; /* invalid blob type */ + if ( buffer[5] != 1 ) + return GPGERR_GENERAL; /* invalid blob format version */ + + nkeys = get16( buffer + 16 ); + keyinfolen = get16( buffer + 18 ); + p = buffer + 20; + for(n=0; n < nkeys; n++, p += keyinfolen ) { + if ( p+24 > pend ) + return GPGERR_GENERAL; /* blob shorter than required */ + off = get32 ( p + 20 ); + if (keyidlen < 8 ) /* actually keyidlen may either be 4 or 8 */ + off +=4; + if ( off+keyidlen > buflen ) + return GPGERR_GENERAL; /* offset out of bounds */ + if ( !memcmp ( buffer+off, keyidbuf, keyidlen ) ) + return 0; /* found */ + } + return -1; +} + + + +int +keybox_blob_has_uid ( KEYBOXBLOB blob, + int (*cmp)(const byte *, size_t, void *), void *opaque ) +{ + ulong n, nuids, uidinfolen, off, len; + const byte *p, *pend; + byte *buffer = blob->blob; + size_t buflen = blob->bloblen; + + if ( buflen < 40 ) + return GPGERR_GENERAL; /* blob too short */ + n = get32( buffer ); + if ( n > buflen ) + return GPGERR_GENERAL; /* blob larger than announced length */ + buflen = n; /* ignore trailing stuff */ + pend = buffer + n - 1; + + if ( buffer[4] != 2 ) + return GPGERR_GENERAL; /* invalid blob type */ + if ( buffer[5] != 1 ) + return GPGERR_GENERAL; /* invalid blob format version */ + + p = buffer + 20 + get16( buffer + 16 ) * get16( buffer + 18 ); + if ( p+4 > pend ) + return GPGERR_GENERAL; /* blob shorter than required */ + + nuids = get16( p ); p+= 2; + uidinfolen = get16( p ); p+=2; + for(n=0; n < nuids; n++, p += uidinfolen ) { + if ( p+8 > pend ) + return GPGERR_GENERAL; /* blob shorter than required */ + off = get32 ( p ); + len = get32 ( p + 4 ); + if ( off+len > buflen ) + return GPGERR_GENERAL; /* offset out of bounds */ + if ( (*cmp) ( buffer+off, len, opaque ) ) + return 0; /* found */ + } + + return -1; +} + + diff --git a/kbx/keybox-util.c b/kbx/keybox-util.c new file mode 100644 index 000000000..ed5d93de0 --- /dev/null +++ b/kbx/keybox-util.c @@ -0,0 +1,72 @@ +/* keybox-util.c - Utility functions for Keybox + * 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 +#include +#include +#include + +#include "keybox-defs.h" + + +static void *(*alloc_func)(size_t n) = malloc; +static void *(*realloc_func)(void *p, size_t n) = realloc; +static void (*free_func)(void*) = free; + + + +void +keybox_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), + void *(*new_realloc_func)(void *p, size_t n), + void (*new_free_func)(void*) ) +{ + alloc_func = new_alloc_func; + realloc_func = new_realloc_func; + free_func = new_free_func; +} + +void * +_keybox_malloc (size_t n) +{ + return alloc_func (n); +} + +void * +_keybox_realloc (void *a, size_t n) +{ + return realloc_func (a, n); +} + +void * +_keybox_calloc (size_t n, size_t m) +{ + void *p = _keybox_malloc (n*m); + if (p) + memset (p, 0, n* m); + return p; +} + +void +_keybox_free (void *p) +{ + if (p) + free_func (p); +} + diff --git a/kbx/keybox.h b/kbx/keybox.h new file mode 100644 index 000000000..90088236a --- /dev/null +++ b/kbx/keybox.h @@ -0,0 +1,99 @@ +/* keybox.h - Keybox 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 + */ + +#ifndef KEYBOX_H +#define KEYBOX_H 1 +#ifdef __cplusplus +extern "C" { +#if 0 + } +#endif +#endif + +#define KEYBOX_WITH_OPENPGP 1 +#define KEYBOX_WITH_X509 1 + + +#ifdef KEYBOX_WITH_OPENPGP +# undef KEYBOX_WITH_OPENPGP +/*#include */ +#endif + +#ifdef KEYBOX_WITH_X509 +# include +#endif + + +typedef enum { + KEYBOX_No_Error = 0, + KEYBOX_General_Error = 1, + KEYBOX_Out_Of_Core = 2, + KEYBOX_Invalid_Value = 3, + KEYBOX_Timeout = 4, + KEYBOX_Read_Error = 5, + KEYBOX_Write_Error = 6, + KEYBOX_File_Error = 7, + KEYBOX_Blob_Too_Short = 8, + KEYBOX_Blob_Too_Large = 9 + +} KeyboxError; + + + +typedef struct keybox_handle *KEYBOX_HANDLE; + + + +/*-- keybox-init.c --*/ +void *keybox_register_file (const char *fname, int secret); +int keybox_is_writable (void *token); + + +/*-- --*/ + +KEYBOX_HANDLE keybox_new (void *token, int secret); +void keybox_release (KEYBOX_HANDLE hd); +const char *keybox_get_resource_name (KEYBOX_HANDLE hd); +int keybox_lock (KEYBOX_HANDLE hd, int yes); +#if 0 +int keybox_get_keyblock (KEYBOX_HANDLE hd, KBNODE *ret_kb); +int keybox_update_keyblock (KEYBOX_HANDLE hd, KBNODE kb); +int keybox_insert_keyblock (KEYBOX_HANDLE hd, KBNODE kb); +int keybox_locate_writable (KEYBOX_HANDLE hd); +int keybox_delete_keyblock (KEYBOX_HANDLE hd); +int keybox_search_reset (KEYBOX_HANDLE hd); +int keybox_search (KEYBOX_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc); +int keybox_rebuild_cache (void *); +#endif + + +/*-- keybox-util.c --*/ +void keybox_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), + void *(*new_realloc_func)(void *p, size_t n), + void (*new_free_func)(void*) ); + +/*-- keybox-errors.c (built) --*/ +const char *keybox_strerror (KeyboxError err); + + +#ifdef __cplusplus +} +#endif +#endif /*KEYBOX_H*/ diff --git a/kbx/mkerrors b/kbx/mkerrors new file mode 100755 index 000000000..5adb7bfdf --- /dev/null +++ b/kbx/mkerrors @@ -0,0 +1,71 @@ +#!/bin/sh +# mkerrors - Extract error strings from assuan.h +# and create C source for assuan_strerror +# 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 + +cat < +#include "keybox-defs.h" + +/** + * keybox_strerror: + * @err: Error code + * + * This function returns a textual representaion of the given + * errorcode. If this is an unknown value, a string with the value + * is returned (Beware: it is hold in a static buffer). + * + * Return value: String with the error description. + **/ +const char * +keybox_strerror (KeyboxError err) +{ + const char *s; + static char buf[25]; + + switch (err) + { +EOF + +awk ' +/KEYBOX_No_Error/ { okay=1 } +!okay {next} +/}/ { exit 0 } +/KEYBOX_[A-Za-z_]*/ { print_code($1) } + + +function print_code( s ) +{ +printf " case %s: s=\"", s ; +gsub(/_/, " ", s ); +printf "%s\"; break;\n", tolower(substr(s,8)); +} +' + +cat <