aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
Diffstat (limited to 'g10')
-rw-r--r--g10/ChangeLog31
-rw-r--r--g10/armor.c40
-rw-r--r--g10/build-packet.c20
-rw-r--r--g10/encode.c5
-rw-r--r--g10/export.c22
-rw-r--r--g10/filter.h1
-rw-r--r--g10/free-packet.c4
-rw-r--r--g10/g10.c45
-rw-r--r--g10/getkey.c153
-rw-r--r--g10/import.c1
-rw-r--r--g10/keydb.h7
-rw-r--r--g10/keygen.c57
-rw-r--r--g10/keyid.c17
-rw-r--r--g10/keylist.c20
-rw-r--r--g10/mainproc.c8
-rw-r--r--g10/options.h6
-rw-r--r--g10/packet.h4
-rw-r--r--g10/parse-packet.c20
-rw-r--r--g10/ringedit.c83
-rw-r--r--g10/sig-check.c8
-rw-r--r--g10/sign.c2
-rw-r--r--g10/tdbio.c344
-rw-r--r--g10/tdbio.h1
-rw-r--r--g10/textfilter.c4
-rw-r--r--g10/trustdb.c382
-rw-r--r--g10/trustdb.h1
26 files changed, 855 insertions, 431 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 93a21e241..4bc222084 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,6 +1,35 @@
+Fri Oct 16 10:24:47 1998 Werner Koch ([email protected])
+
+ * trustdb.c: Rewrote most.
+ * tdbio.c: Add cache and generalized hash tables.
+
+ * options.h (ENABLE_COMMENT_PACKETS): New but undef'ed.
+ * encode.c, sign.c, keygen.c: Disabled comment packets.
+ * export.c (do_export): Comment packets are never exported,
+ except for those in the secret keyring.
+
+ * g10.c (main): Removed option do-no-export-rsa; should be
+ be replaced by a secpial tool.
+ * export.c (do_export): Removed the code for the above option.
+
+ * armor.c (find_header): Support for new only_keyblocks.
+ * import.c (import_keys): Only looks for keyblock armors.
+
+ * packet.h: replaced valid_days by expiredate and changed all users.
+ * build-packet.c (do_public_key): calculates valid-days
+ (do_secret_key): Ditto.
+ * parse-packet.c (parse_key): expiredate is calucated from the
+ valid_period in v3 packets.
+ * keyid.c (do_fingerprint_md): calculates valid_dates.
+
+ * keygen.c (add_key_expire): fixed key expiration time for v4 packets.
+
+ * armor.c (find_header): A LF in the first 28 bytes
+ was skipped for non-armored data.
+
Thu Oct 8 11:35:51 1998 Werner Koch ([email protected])
- * armor.c (is_armored): Ad test on old comment packets.
+ * armor.c (is_armored): Add test on old comment packets.
* tdbio.c (tdbio_search_dir_bypk): fixed memory leak.
diff --git a/g10/armor.c b/g10/armor.c
index df67712a4..aa5609018 100644
--- a/g10/armor.c
+++ b/g10/armor.c
@@ -109,7 +109,8 @@ static char *tail_strings[] = {
static fhdr_state_t find_header( fhdr_state_t state,
byte *buf, size_t *r_buflen,
IOBUF a, size_t n,
- unsigned *r_empty, int *r_hashes );
+ unsigned *r_empty, int *r_hashes,
+ int only_keyblocks );
static void
@@ -260,7 +261,8 @@ parse_hash_header( const char *line )
*/
static fhdr_state_t
find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
- IOBUF a, size_t n, unsigned *r_empty, int *r_hashes )
+ IOBUF a, size_t n, unsigned *r_empty, int *r_hashes,
+ int only_keyblocks )
{
int c=0, i;
const char *s;
@@ -273,7 +275,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
buflen = *r_buflen;
assert(buflen >= 100 );
- buflen -= 3; /* reserved room for CR,LF and one extra */
+ buflen -= 4; /* reserved room for CR,LF, and two extra */
do {
switch( state ) {
@@ -281,14 +283,17 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
/* read at least the first byte to check whether it is armored
* or not */
c = 0;
- for(n=0; n < 28 && (c=iobuf_get2(a)) != -1 && c != '\n'; )
+ for(n=0; n < 28 && (c=iobuf_get(a)) != -1 && c != '\n'; )
buf[n++] = c;
if( !n && c == '\n' )
state = fhdrCHECKBegin;
else if( !n || c == -1 )
state = fhdrNOArmor; /* too short */
- else if( !is_armored( buf ) )
+ else if( !is_armored( buf ) ) {
state = fhdrNOArmor;
+ if( c == '\n' )
+ buf[n++] = c;
+ }
else if( c == '\n' )
state = fhdrCHECKBegin;
else
@@ -299,7 +304,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
n = 0;
case fhdrINITCont: /* read more stuff into buffer */
c = 0;
- for(; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; )
+ for(; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
buf[n++] = c;
state = c == '\n' ? fhdrCHECKBegin :
c == -1 ? fhdrEOF : fhdrINITSkip;
@@ -309,21 +314,21 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
if( c == '\n' )
n = 0;
else {
- while( (c=iobuf_get2(a)) != -1 && c != '\n' )
+ while( (c=iobuf_get(a)) != -1 && c != '\n' )
;
}
state = c == -1? fhdrEOF : fhdrINIT;
break;
case fhdrSKIPHeader:
- while( (c=iobuf_get2(a)) != -1 && c != '\n' )
+ while( (c=iobuf_get(a)) != -1 && c != '\n' )
;
state = c == -1? fhdrEOF : fhdrWAITHeader;
break;
case fhdrWAITHeader: /* wait for Header lines */
c = 0;
- for(n=0; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; )
+ for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
buf[n++] = c;
buf[n] = 0;
if( n < buflen || c == '\n' ) {
@@ -388,7 +393,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
case fhdrWAITClearsig: /* skip the empty line (for clearsig) */
c = 0;
- for(n=0; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; )
+ for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
buf[n++] = c;
if( n < buflen || c == '\n' ) {
buf[n] = 0;
@@ -432,6 +437,9 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
break;
if( !s )
break; /* unknown begin line */
+ if( only_keyblocks && i != 1 && i != 5 && i != 6 )
+ break; /* not a keyblock armor */
+
/* found the begin line */
hdr_line = i;
state = fhdrWAITHeader;
@@ -448,7 +456,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
* we have to look for a header line or dashed escaped text*/
n = 0;
c = 0;
- while( n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n' )
+ while( n < buflen && (c=iobuf_get(a)) != -1 && c != '\n' )
buf[n++] = c;
buf[n] = 0;
if( c == -1 )
@@ -516,7 +524,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
* for dashed escaped text of headers */
c = 0;
n = 0;
- while( n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n' )
+ while( n < buflen && (c=iobuf_get(a)) != -1 && c != '\n' )
buf[n++] = c;
buf[n] = 0;
if( c == -1 )
@@ -534,7 +542,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
* counting spaces is not enough, because it may be a
* mix of different white space characters */
IOBUF b = iobuf_temp();
- while( (c=iobuf_get2(a)) != -1 && c != '\n' ) {
+ while( (c=iobuf_get(a)) != -1 && c != '\n' ) {
iobuf_put(b,c);
if( c != ' ' && c != '\t' && c != '\r' )
break;
@@ -622,7 +630,8 @@ check_input( armor_filter_context_t *afx, IOBUF a )
n = DIM(afx->helpbuf);
state = find_header( state, afx->helpbuf, &n, a,
- afx->helplen, &emplines, &afx->hashes);
+ afx->helplen, &emplines, &afx->hashes,
+ afx->only_keyblocks );
switch( state ) {
case fhdrNOArmor:
afx->inp_checked = 1;
@@ -708,7 +717,8 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
afx->helpidx = 0;
state = find_header( state, afx->helpbuf, &n, a,
state == fhdrNullClearsig? afx->helplen:0,
- &emplines, &afx->hashes );
+ &emplines, &afx->hashes,
+ afx->only_keyblocks );
switch( state) {
case fhdrERROR:
invalid_armor();
diff --git a/g10/build-packet.c b/g10/build-packet.c
index a877b7e3c..11edb33e6 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -209,8 +209,14 @@ do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
else
iobuf_put( a, pk->version );
write_32(a, pk->timestamp );
- if( pk->version < 4 )
- write_16(a, pk->valid_days );
+ if( pk->version < 4 ) {
+ u16 ndays;
+ if( pk->expiredate )
+ ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L);
+ else
+ ndays = 0;
+ write_16(a, 0 );
+ }
iobuf_put(a, pk->pubkey_algo );
n = pubkey_get_npkey( pk->pubkey_algo );
if( !n )
@@ -280,8 +286,14 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
else
iobuf_put( a, sk->version );
write_32(a, sk->timestamp );
- if( sk->version < 4 )
- write_16(a, sk->valid_days );
+ if( sk->version < 4 ) {
+ u16 ndays;
+ if( sk->expiredate )
+ ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L);
+ else
+ ndays = 0;
+ write_16(a, 0 );
+ }
iobuf_put(a, sk->pubkey_algo );
nskey = pubkey_get_nskey( sk->pubkey_algo );
npkey = pubkey_get_npkey( sk->pubkey_algo );
diff --git a/g10/encode.c b/g10/encode.c
index bc4742607..0d8a84c94 100644
--- a/g10/encode.c
+++ b/g10/encode.c
@@ -118,12 +118,14 @@ encode_simple( const char *filename, int mode )
if( opt.armor )
iobuf_push_filter( out, armor_filter, &afx );
+ #ifdef ENABLE_COMMENT_PACKETS
else {
write_comment( out, "#created by GNUPG v" VERSION " ("
PRINTABLE_OS_NAME ")");
if( opt.comment_string )
write_comment( out, opt.comment_string );
}
+ #endif
if( s2k && !opt.rfc1991 ) {
PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc );
enc->version = 4;
@@ -224,13 +226,14 @@ encode_crypt( const char *filename, STRLIST remusr )
if( opt.armor )
iobuf_push_filter( out, armor_filter, &afx );
+ #ifdef ENABLE_COMMENT_PACKETS
else {
write_comment( out, "#created by GNUPG v" VERSION " ("
PRINTABLE_OS_NAME ")");
if( opt.comment_string )
write_comment( out, opt.comment_string );
}
-
+ #endif
/* create a session key */
cfx.dek = m_alloc_secure( sizeof *cfx.dek );
if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
diff --git a/g10/export.c b/g10/export.c
index 301cb5ece..46413fff2 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -124,24 +124,10 @@ do_export( STRLIST users, int secret )
/* and write it */
for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) {
- if( opt.do_not_export_rsa ) {
- int algo;
- switch( node->pkt->pkttype ) {
- /* note: we can� do this for subkeys here */
- case PKT_PUBLIC_KEY:
- algo = node->pkt->pkt.public_key->pubkey_algo;
- break;
- case PKT_SECRET_KEY:
- algo = node->pkt->pkt.secret_key->pubkey_algo;
- break;
- case PKT_SIGNATURE:
- algo = node->pkt->pkt.signature->pubkey_algo;
- break;
- default: algo = 0;
- }
- if( is_RSA(algo) )
- continue;
- }
+ /* don't export any comment packets but those in the
+ * secret keyring */
+ if( !secret && node->pkt->pkttype == PKT_COMMENT )
+ continue;
if( (rc = build_packet( out, node->pkt )) ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, g10_errstr(rc) );
diff --git a/g10/filter.h b/g10/filter.h
index d48b75627..1cf8f8e42 100644
--- a/g10/filter.h
+++ b/g10/filter.h
@@ -31,6 +31,7 @@ typedef struct {
typedef struct {
int status;
int what;
+ int only_keyblocks; /* skip all headers but ".... key block" */
byte radbuf[4];
int idx, idx2;
u32 crc;
diff --git a/g10/free-packet.c b/g10/free-packet.c
index e6b228117..c3b516dbd 100644
--- a/g10/free-packet.c
+++ b/g10/free-packet.c
@@ -354,7 +354,7 @@ cmp_public_keys( PKT_public_key *a, PKT_public_key *b )
if( a->timestamp != b->timestamp )
return -1;
- if( a->valid_days != b->valid_days )
+ if( a->expiredate != b->expiredate )
return -1;
if( a->pubkey_algo != b->pubkey_algo )
return -1;
@@ -380,7 +380,7 @@ cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk )
if( pk->timestamp != sk->timestamp )
return -1;
- if( pk->valid_days != sk->valid_days )
+ if( pk->expiredate != sk->expiredate )
return -1;
if( pk->pubkey_algo != sk->pubkey_algo )
return -1;
diff --git a/g10/g10.c b/g10/g10.c
index 9195d21a8..569d4112d 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -1,4 +1,4 @@
-/* g10.c - The GNUPG utility (main for gpg)
+/* g10.c - The GnuPG utility (main for gpg)
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* This file is part of GNUPG.
@@ -88,6 +88,7 @@ enum cmd_and_opt_values { aNull = 0,
aPrintMD,
aPrintMDs,
aCheckTrustDB,
+ aUpdateTrustDB,
aFixTrustDB,
aListTrustDB,
aListTrustPath,
@@ -98,7 +99,6 @@ enum cmd_and_opt_values { aNull = 0,
aGenRandom,
oFingerprint,
- oDoNotExportRSA,
oAnswerYes,
oAnswerNo,
oKeyring,
@@ -172,13 +172,17 @@ static ARGPARSE_OPTS opts[] = {
#endif
{ aExport, "export" , 256, N_("export keys") },
{ aExportSecret, "export-secret-keys" , 256, "@" },
- { oDoNotExportRSA, "do-not-export-rsa", 0, "@" },
{ aImport, "import", 256 , N_("import/merge keys")},
{ aListPackets, "list-packets",256,N_("list only the sequence of packets")},
#ifdef IS_G10MAINT
- { aExportOwnerTrust, "export-ownertrust", 256, N_("export the ownertrust values")},
- { aImportOwnerTrust, "import-ownertrust", 256 , N_("import ownertrust values")},
- { aCheckTrustDB, "check-trustdb",0 , N_("|[NAMES]|check the trust database")},
+ { aExportOwnerTrust,
+ "export-ownertrust", 256, N_("export the ownertrust values")},
+ { aImportOwnerTrust,
+ "import-ownertrust", 256 , N_("import ownertrust values")},
+ { aUpdateTrustDB,
+ "update-trustdb",0 , N_("|[NAMES]|update the trust database")},
+ { aCheckTrustDB,
+ "check-trustdb",0 , N_("|[NAMES]|check the trust database")},
{ aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")},
{ aDeArmor, "dearmor", 256, N_("De-Armor a file or stdin") },
{ aEnArmor, "enarmor", 256, N_("En-Armor a file or stdin") },
@@ -302,9 +306,9 @@ strusage( int level )
switch( level ) {
case 11: p =
#ifdef IS_G10MAINT
- "gpgm (GNUPG)";
+ "gpgm (GnuPG)";
#else
- "gpg (GNUPG)";
+ "gpg (GnuPG)";
#endif
break;
case 13: p = VERSION; break;
@@ -323,7 +327,7 @@ strusage( int level )
case 41: p =
#ifdef IS_G10MAINT
_("Syntax: gpgm [options] [files]\n"
- "GNUPG maintenance utility\n");
+ "GnuPG maintenance utility\n");
#else
_("Syntax: gpg [options] [files]\n"
"sign, check, encrypt or decrypt\n"
@@ -638,6 +642,7 @@ main( int argc, char **argv )
case aPrintMDs: set_cmd( &cmd, aPrintMDs); break;
case aListTrustDB: set_cmd( &cmd, aListTrustDB); break;
case aCheckTrustDB: set_cmd( &cmd, aCheckTrustDB); break;
+ case aUpdateTrustDB: set_cmd( &cmd, aUpdateTrustDB); break;
case aFixTrustDB: set_cmd( &cmd, aFixTrustDB); break;
case aListTrustPath: set_cmd( &cmd, aListTrustPath); break;
case aDeArmor: set_cmd( &cmd, aDeArmor); break;
@@ -692,10 +697,12 @@ main( int argc, char **argv )
case oCompressKeys: opt.compress_keys = 1; break;
case aListSecretKeys: set_cmd( &cmd, aListSecretKeys); break;
case oAlwaysTrust: opt.always_trust = 1; break;
- case oLoadExtension: register_cipher_extension(pargs.r.ret_str); break;
+ case oLoadExtension:
+ register_cipher_extension(orig_argc? *orig_argv:NULL,
+ pargs.r.ret_str);
+ break;
case oRFC1991: opt.rfc1991 = 1; opt.no_comment = 1; break;
case oEmuChecksumBug: opt.emulate_bugs |= EMUBUG_GPGCHKSUM; break;
- case oDoNotExportRSA: opt.do_not_export_rsa = 1; break;
case oCompressSigs: opt.compress_sigs = 1; break;
case oRunAsShmCP:
#ifndef USE_SHM_COPROCESSING
@@ -835,13 +842,13 @@ main( int argc, char **argv )
&& !(cmd == aKMode && argc == 2 ) ) {
if( !sec_nrings || default_keyring ) /* add default secret rings */
- add_secret_keyring("secring.gpg");
+ add_keyblock_resource("secring.gpg", 0, 1);
for(sl = sec_nrings; sl; sl = sl->next )
- add_secret_keyring( sl->d );
+ add_keyblock_resource( sl->d, 0, 1 );
if( !nrings || default_keyring ) /* add default ring */
- add_keyring("pubring.gpg");
+ add_keyblock_resource("pubring.gpg", 0, 0);
for(sl = nrings; sl; sl = sl->next )
- add_keyring( sl->d );
+ add_keyblock_resource( sl->d, 0, 0 );
}
FREE_STRLIST(nrings);
FREE_STRLIST(sec_nrings);
@@ -996,7 +1003,7 @@ main( int argc, char **argv )
else {
/* add keyring (default keyrings are not registered in this
* special case */
- add_keyring( argv[1] );
+ add_keyblock_resource( argv[1], 0, 0 );
public_key_list( **argv?1:0, argv );
}
}
@@ -1160,6 +1167,12 @@ main( int argc, char **argv )
}
break;
+ case aUpdateTrustDB:
+ if( argc )
+ wrong_args("--update-trustdb");
+ update_trustdb();
+ break;
+
case aCheckTrustDB:
if( !argc )
check_trustdb(NULL);
diff --git a/g10/getkey.c b/g10/getkey.c
index 6e4c34592..90bd09a25 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -37,16 +37,15 @@
#define MAX_PK_CACHE_ENTRIES 50
#define MAX_UID_CACHE_ENTRIES 50
+static struct {
+ int any;
+ int okay_count;
+ int nokey_count;
+ int error_count;
+} lkup_stats[21];
-typedef struct enum_seckey_context {
- int eof;
- STRLIST sl;
- IOBUF iobuf;
-} enum_seckey_context_t;
-static STRLIST keyrings;
-static STRLIST secret_keyrings;
#if MAX_UNK_CACHE_ENTRIES
typedef struct keyid_list {
@@ -89,93 +88,25 @@ static int lookup( PKT_public_key *pk,
static int lookup_sk( PKT_secret_key *sk,
int mode, u32 *keyid, const char *name, int primary );
-/* note this function may be called before secure memory is
- * available
- * The first keyring which is added by this function is
- * created if it does not exist.
- */
-void
-add_keyring( const char *name )
-{
- STRLIST sl;
- int rc, force = !keyrings;
-
- if( *name != '/' ) { /* do tilde expansion etc */
- char *p ;
-
- if( strchr(name, '/') )
- p = make_filename(name, NULL);
- else
- p = make_filename(opt.homedir, name, NULL);
- sl = append_to_strlist( &keyrings, p );
- m_free(p);
- }
- else
- sl = append_to_strlist( &keyrings, name );
-
- /* fixme: We should remove much out of this module and
- * combine it with the keyblock stuff from ringedit.c
- * For now we will simple add the filename as keyblock resource
- */
- rc = add_keyblock_resource( sl->d, force, 0 );
- if( rc )
- log_error("keyblock resource '%s': %s\n", sl->d, g10_errstr(rc) );
-}
-/****************
- * Get the name of the keyrings, start with a sequence number of 0.
- */
-const char *
-get_keyring( int sequence )
-{
- STRLIST sl;
-
- for(sl = keyrings; sl && sequence; sl = sl->next, sequence-- )
- ;
- return sl? sl->d : NULL;
-}
-
-const char *
-get_secret_keyring( int sequence )
-{
- STRLIST sl;
-
- for(sl = secret_keyrings; sl && sequence; sl = sl->next, sequence-- )
- ;
- return sl? sl->d : NULL;
-}
-
-
-void
-add_secret_keyring( const char *name )
+static void
+print_stats()
{
- STRLIST sl;
- int rc, force = !secret_keyrings;
-
- if( *name != '/' ) { /* do tilde expansion etc */
- char *p ;
-
- if( strchr(name, '/') )
- p = make_filename(name, NULL);
- else
- p = make_filename(opt.homedir, name, NULL);
- sl = append_to_strlist( &secret_keyrings, p );
- m_free(p);
+ int i;
+ for(i=0; i < DIM(lkup_stats); i++ ) {
+ if( lkup_stats[i].any )
+ fprintf(stderr,
+ "lookup stats: mode=%-2d ok=%-6d nokey=%-6d err=%-6d\n",
+ i,
+ lkup_stats[i].okay_count,
+ lkup_stats[i].nokey_count,
+ lkup_stats[i].error_count );
}
- else
- sl = append_to_strlist( &secret_keyrings, name );
-
- /* fixme: We should remove much out of this module and
- * combine it with the keyblock stuff from ringedit.c
- * For now we will simple add the filename as keyblock resource
- */
- rc = add_keyblock_resource( sl->d, force, 1 );
- if( rc )
- log_error("secret keyblock resource '%s': %s\n", sl->d, g10_errstr(rc));
}
+
static void
cache_public_key( PKT_public_key *pk )
{
@@ -690,7 +621,7 @@ merge_one_pk_and_selfsig( KBNODE keyblock, KBNODE knode )
*/
const byte *p;
p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL );
- pk->valid_days = p? ((buffer_to_u32(p)+86399L)/86400L):0;
+ pk->expiredate = p? buffer_to_u32(p):0;
/* fixme: add usage etc. to pk */
break;
}
@@ -739,12 +670,12 @@ merge_keys_and_selfsig( KBNODE keyblock )
const byte *p;
p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL );
if( pk ) {
- pk->valid_days = p? ((buffer_to_u32(p)+86399L)/86400L):0;
+ pk->expiredate = p? buffer_to_u32(p):0;
/* fixme: add usage etc. */
pk = NULL; /* use only the first self signature */
}
else {
- sk->valid_days = p? ((buffer_to_u32(p)+86399L)/86400L):0;
+ sk->expiredate = p? buffer_to_u32(p):0;
sk = NULL; /* use only the first self signature */
}
}
@@ -756,7 +687,7 @@ merge_keys_and_selfsig( KBNODE keyblock )
/****************
- * Lookup a key by scanning all keyrings
+ * Lookup a key by scanning all keyresources
* mode 1 = lookup by NAME (exact)
* 2 = lookup by NAME (substring)
* 3 = lookup by NAME (email address)
@@ -949,6 +880,24 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid,
enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
release_kbnode( keyblock );
set_packet_list_mode(oldmode);
+ if( opt.debug & DBG_MEMSTAT_VALUE ) {
+ static int initialized;
+
+ if( !initialized ) {
+ initialized = 1;
+ atexit( print_stats );
+ }
+
+ assert( mode < DIM(lkup_stats) );
+ lkup_stats[mode].any = 1;
+ if( !rc )
+ lkup_stats[mode].okay_count++;
+ else if ( rc == G10ERR_NO_PUBKEY )
+ lkup_stats[mode].nokey_count++;
+ else
+ lkup_stats[mode].error_count++;
+ }
+
return rc;
}
@@ -1107,12 +1056,19 @@ enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys )
int rc=0;
PACKET pkt;
int save_mode;
- enum_seckey_context_t *c = *context;
+ struct {
+ int eof;
+ int sequence;
+ const char *name;
+ IOBUF iobuf;
+ } *c = *context;
+
if( !c ) { /* make a new context */
c = m_alloc_clear( sizeof *c );
*context = c;
- c->sl = secret_keyrings;
+ c->sequence = 0;
+ c->name = enum_keyblock_resources( &c->sequence, 1 );
}
if( !sk ) { /* free the context */
@@ -1126,10 +1082,11 @@ enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys )
if( c->eof )
return -1;
- for( ; c->sl; c->sl = c->sl->next ) {
+ /* FIXME: This assumes a plain keyring file */
+ for( ; c->name; c->name = enum_keyblock_resources( &c->sequence, 1 ) ) {
if( !c->iobuf ) {
- if( !(c->iobuf = iobuf_open( c->sl->d ) ) ) {
- log_error("enum_secret_keys: can't open '%s'\n", c->sl->d );
+ if( !(c->iobuf = iobuf_open( c->name ) ) ) {
+ log_error("enum_secret_keys: can't open '%s'\n", c->name );
continue; /* try next file */
}
}
@@ -1165,7 +1122,7 @@ get_user_id_string( u32 *keyid )
user_id_db_t r;
char *p;
int pass=0;
- /* try it two times; second pass reads from keyrings */
+ /* try it two times; second pass reads from key resources */
do {
for(r=user_id_db; r; r = r->next )
if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) {
@@ -1185,7 +1142,7 @@ get_user_id( u32 *keyid, size_t *rn )
user_id_db_t r;
char *p;
int pass=0;
- /* try it two times; second pass reads from keyrings */
+ /* try it two times; second pass reads from key resources */
do {
for(r=user_id_db; r; r = r->next )
if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) {
diff --git a/g10/import.c b/g10/import.c
index ccfbccaad..374843363 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -96,6 +96,7 @@ import_keys( const char *fname )
memset( &afx, 0, sizeof afx);
memset( &cfx, 0, sizeof cfx);
+ afx.only_keyblocks = 1;
/* open file */
inp = iobuf_open(fname);
diff --git a/g10/keydb.h b/g10/keydb.h
index c7fb26db1..efb371cec 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -106,10 +106,6 @@ void set_next_passphrase( const char *s );
char *get_last_passphrase(void);
/*-- getkey.c --*/
-void add_keyring( const char *name );
-const char *get_keyring( int sequence );
-const char *get_secret_keyring( int sequence );
-void add_secret_keyring( const char *name );
int get_pubkey( PKT_public_key *pk, u32 *keyid );
int get_pubkey_byname( PKT_public_key *pk, const char *name );
int get_seckey( PKT_secret_key *sk, u32 *keyid );
@@ -156,7 +152,8 @@ int commit_kbnode( KBNODE *root );
void dump_kbnode( KBNODE node );
/*-- ringedit.c --*/
-int add_keyblock_resource( const char *filename, int force, int secret );
+const char *enum_keyblock_resources( int *sequence, int secret );
+int add_keyblock_resource( const char *resname, int force, int secret );
const char *keyblock_resource_name( KBPOS *kbpos );
int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos );
int find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos );
diff --git a/g10/keygen.c b/g10/keygen.c
index 3a7582013..9f1d8df9f 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -58,8 +58,8 @@ add_key_expire( PKT_signature *sig, void *opaque )
byte buf[8];
u32 u;
- if( sk->valid_days ) {
- u = sk->valid_days * 86400L;
+ if( sk->expiredate ) {
+ u = sk->expiredate;
buf[0] = (u >> 24) & 0xff;
buf[1] = (u >> 16) & 0xff;
buf[2] = (u >> 8) & 0xff;
@@ -192,7 +192,7 @@ write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_key *sk )
static int
gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
- STRING2KEY *s2k, PKT_secret_key **ret_sk, u16 valid_days,
+ STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expiredate,
int version )
{
int rc;
@@ -214,7 +214,9 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
pk = m_alloc_clear( sizeof *pk );
sk->timestamp = pk->timestamp = make_timestamp();
sk->version = pk->version = version;
- sk->valid_days = pk->valid_days = valid_days;
+ if( expiredate && expiredate < sk->timestamp )
+ expiredate = sk->timestamp; /* key generatio may take long */
+ sk->expiredate = pk->expiredate = expiredate;
sk->pubkey_algo = pk->pubkey_algo = algo;
pk->pkey[0] = mpi_copy( skey[0] );
pk->pkey[1] = mpi_copy( skey[1] );
@@ -266,7 +268,7 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
*/
static int
gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
- STRING2KEY *s2k, PKT_secret_key **ret_sk, u16 valid_days )
+ STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expiredate )
{
int rc;
int i;
@@ -289,7 +291,9 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
pk = m_alloc_clear( sizeof *pk );
sk->timestamp = pk->timestamp = make_timestamp();
sk->version = pk->version = 4;
- sk->valid_days = pk->valid_days = valid_days;
+ if( expiredate && expiredate < pk->timestamp )
+ expiredate = pk->timestamp; /* key generation may take long */
+ sk->expiredate = pk->expiredate = expiredate;
sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA;
pk->pkey[0] = mpi_copy( skey[0] );
pk->pkey[1] = mpi_copy( skey[1] );
@@ -477,11 +481,12 @@ ask_keysize( int algo )
}
-static int
-ask_valid_days()
+static u32
+ask_expiredate()
{
char *answer;
int valid_days=0;
+ u32 expiredate = 0;
tty_printf(_("Please specify how long the key should be valid.\n"
" 0 = key does not expire\n"
@@ -513,12 +518,14 @@ ask_valid_days()
continue;
}
- if( !valid_days )
+ if( !valid_days ) {
tty_printf(_("Key does not expire at all\n"));
+ expiredate = 0;
+ }
else {
+ expiredate = make_timestamp() + valid_days * 86400L;
/* print the date when the key expires */
- tty_printf(_("Key expires at %s\n"), strtimestamp(
- add_days_to_timestamp( make_timestamp(), valid_days )));
+ tty_printf(_("Key expires at %s\n"), asctimestamp(expiredate) );
}
if( !cpr_enabled()
@@ -527,7 +534,7 @@ ask_valid_days()
break;
}
m_free(answer);
- return valid_days;
+ return expiredate;
}
@@ -713,7 +720,7 @@ ask_passphrase( STRING2KEY **ret_s2k )
static int
do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root,
- DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, int valid_days,
+ DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, u32 expiredate,
int v4_packet )
{
int rc=0;
@@ -726,11 +733,13 @@ do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root,
if( algo == PUBKEY_ALGO_ELGAMAL || algo == PUBKEY_ALGO_ELGAMAL_E )
rc = gen_elg(algo, nbits, pub_root, sec_root, dek, s2k,
- sk, valid_days, v4_packet? 4:3 );
+ sk, expiredate, v4_packet? 4:3 );
else if( algo == PUBKEY_ALGO_DSA )
- rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk, valid_days);
+ rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk, expiredate);
else
BUG();
+
+ #ifdef ENABLE_COMMENT_PACKETS
if( !rc ) {
add_kbnode( pub_root,
make_comment_node("#created by GNUPG v" VERSION " ("
@@ -739,6 +748,7 @@ do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root,
make_comment_node("#created by GNUPG v" VERSION " ("
PRINTABLE_OS_NAME ")"));
}
+ #endif
return rc;
}
@@ -781,7 +791,7 @@ generate_keypair()
STRING2KEY *s2k;
int rc;
int algo;
- int ndays;
+ u32 expiredate;
int v4;
int both = 0;
@@ -797,7 +807,7 @@ generate_keypair()
tty_printf(_("DSA keypair will have 1024 bits.\n"));
}
nbits = ask_keysize( algo );
- ndays = ask_valid_days();
+ expiredate = ask_expiredate();
uid = ask_user_id(0);
if( !uid ) {
log_error(_("Key generation cancelled.\n"));
@@ -824,10 +834,10 @@ generate_keypair()
if( both )
rc = do_create( PUBKEY_ALGO_DSA, 1024, pub_root, sec_root,
- dek, s2k, &sk, ndays, 1);
+ dek, s2k, &sk, expiredate, 1);
else
rc = do_create( algo, nbits, pub_root, sec_root,
- dek, s2k, &sk, ndays, v4);
+ dek, s2k, &sk, expiredate, v4);
if( !rc )
write_uid(pub_root, uid );
if( !rc )
@@ -839,7 +849,7 @@ generate_keypair()
if( both ) {
rc = do_create( algo, nbits, pub_root, sec_root,
- dek, s2k, NULL, ndays, 1 );
+ dek, s2k, NULL, expiredate, 1 );
if( !rc )
rc = write_keybinding(pub_root, pub_root, sk);
if( !rc )
@@ -927,7 +937,8 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
int okay=0, rc=0;
KBNODE node;
PKT_secret_key *sk = NULL; /* this is the primary sk */
- int v4, algo, ndays;
+ int v4, algo;
+ u32 expiredate;
unsigned nbits;
char *passphrase = NULL;
DEK *dek = NULL;
@@ -964,7 +975,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
algo = ask_algo( &v4, 1 );
assert(algo);
nbits = ask_keysize( algo );
- ndays = ask_valid_days();
+ expiredate = ask_expiredate();
if( !cpr_enabled() && !cpr_get_answer_is_yes(N_("keygen.sub.okay"),
_("Really create? ") ) )
goto leave;
@@ -978,7 +989,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
}
rc = do_create( algo, nbits, pub_keyblock, sec_keyblock,
- dek, s2k, NULL, ndays, v4 );
+ dek, s2k, NULL, expiredate, v4 );
if( !rc )
rc = write_keybinding(pub_keyblock, pub_keyblock, sk);
if( !rc )
diff --git a/g10/keyid.c b/g10/keyid.c
index 387c3fa9a..fa5b9237e 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -82,7 +82,12 @@ do_fingerprint_md( PKT_public_key *pk )
md_putc( md, a );
}
if( pk->version < 4 ) {
- u16 a = pk->valid_days;
+ u16 a;
+
+ if( pk->expiredate )
+ a = (u16)((pk->expiredate - pk->timestamp) / 86400L);
+ else
+ a = 0;
md_putc( md, a >> 8 );
md_putc( md, a );
}
@@ -108,7 +113,7 @@ do_fingerprint_md_sk( PKT_secret_key *sk )
pk.pubkey_algo = sk->pubkey_algo;
pk.version = sk->version;
pk.timestamp = sk->timestamp;
- pk.valid_days = sk->valid_days;
+ pk.expiredate = sk->expiredate;
pk.pubkey_algo = sk->pubkey_algo;
for( i=0; i < npkey; i++ )
pk.pkey[i] = sk->skey[i];
@@ -303,9 +308,9 @@ expirestr_from_pk( PKT_public_key *pk )
struct tm *tp;
time_t atime;
- if( !pk->valid_days )
+ if( !pk->expiredate )
return "never ";
- atime = add_days_to_timestamp( pk->timestamp, pk->valid_days );
+ atime = pk->expiredate;
tp = gmtime( &atime );
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
return buffer;
@@ -318,9 +323,9 @@ expirestr_from_sk( PKT_secret_key *sk )
struct tm *tp;
time_t atime;
- if( !sk->valid_days )
+ if( !sk->expiredate )
return "never ";
- atime = add_days_to_timestamp( sk->timestamp, sk->valid_days );
+ atime = sk->expiredate;
tp = gmtime( &atime );
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
return buffer;
diff --git a/g10/keylist.c b/g10/keylist.c
index 04d79b1ec..69e9b523b 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -74,7 +74,8 @@ list_all( int secret )
const char *s;
IOBUF a;
- while( (s=secret? get_secret_keyring(seq++):get_keyring(seq++)) ) {
+ /* FIXME: this assumes a keyring resource is a plain keyring file */
+ while( (s = enum_keyblock_resources( &seq, secret )) ) {
if( !(a = iobuf_open(s)) ) {
log_error(_("can't open %s: %s\n"), s, strerror(errno));
continue;
@@ -133,12 +134,12 @@ list_one( const char *name, int secret )
sk = node->pkt->pkt.secret_key;
keyid_from_sk( sk, keyid );
if( opt.with_colons )
- printf("sec::%u:%d:%08lX%08lX:%s:%u:::",
+ printf("sec::%u:%d:%08lX%08lX:%s:%s:::",
nbits_from_sk( sk ),
sk->pubkey_algo,
(ulong)keyid[0],(ulong)keyid[1],
datestr_from_sk( sk ),
- (unsigned)sk->valid_days
+ sk->expiredate? strtimestamp(sk->expiredate):""
/* fixme: add LID here */ );
else
printf("sec %4u%c/%08lX %s ", nbits_from_sk( sk ),
@@ -152,13 +153,14 @@ list_one( const char *name, int secret )
keyid_from_pk( pk, keyid );
if( opt.with_colons ) {
trustletter = query_trust_info( pk );
- printf("pub:%c:%u:%d:%08lX%08lX:%s:%u:",
+ printf("pub:%c:%u:%d:%08lX%08lX:%s:%s:",
trustletter,
nbits_from_pk( pk ),
pk->pubkey_algo,
(ulong)keyid[0],(ulong)keyid[1],
datestr_from_pk( pk ),
- (unsigned)pk->valid_days );
+ pk->expiredate? strtimestamp(pk->expiredate):""
+ );
if( pk->local_id )
printf("%lu", pk->local_id );
putchar(':');
@@ -206,13 +208,13 @@ list_one( const char *name, int secret )
keyid_from_pk( pk2, keyid2 );
if( opt.with_colons ) {
- printf("sub:%c:%u:%d:%08lX%08lX:%s:%u:",
+ printf("sub:%c:%u:%d:%08lX%08lX:%s:%s:",
trustletter,
nbits_from_pk( pk2 ),
pk2->pubkey_algo,
(ulong)keyid2[0],(ulong)keyid2[1],
datestr_from_pk( pk2 ),
- (unsigned)pk2->valid_days
+ pk2->expiredate? strtimestamp(pk2->expiredate):""
/* fixme: add LID and ownertrust here */
);
if( pk->local_id ) /* use the local_id of the main key??? */
@@ -242,12 +244,12 @@ list_one( const char *name, int secret )
keyid_from_sk( sk2, keyid2 );
if( opt.with_colons )
- printf("ssb::%u:%d:%08lX%08lX:%s:%u:::\n",
+ printf("ssb::%u:%d:%08lX%08lX:%s:%s:::\n",
nbits_from_sk( sk2 ),
sk2->pubkey_algo,
(ulong)keyid2[0],(ulong)keyid2[1],
datestr_from_sk( sk2 ),
- (unsigned)sk2->valid_days
+ sk2->expiredate? strtimestamp(sk2->expiredate):""
/* fixme: add LID */
);
else
diff --git a/g10/mainproc.c b/g10/mainproc.c
index a47885b74..dd1546c6b 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -471,14 +471,14 @@ list_node( CTX c, KBNODE node )
c->local_id = pk->local_id;
c->trustletter = query_trust_info( pk );
}
- printf("%s:%c:%u:%d:%08lX%08lX:%s:%u:",
+ printf("%s:%c:%u:%d:%08lX%08lX:%s:%s:",
mainkey? "pub":"sub",
c->trustletter,
nbits_from_pk( pk ),
pk->pubkey_algo,
(ulong)keyid[0],(ulong)keyid[1],
datestr_from_pk( pk ),
- (unsigned)pk->valid_days );
+ pk->expiredate? strtimestamp(pk->expiredate):"" );
if( c->local_id )
printf("%lu", c->local_id );
putchar(':');
@@ -541,13 +541,13 @@ list_node( CTX c, KBNODE node )
if( opt.with_colons ) {
u32 keyid[2];
keyid_from_sk( sk, keyid );
- printf("%s::%u:%d:%08lX%08lX:%s:%u:::",
+ printf("%s::%u:%d:%08lX%08lX:%s:%s:::",
mainkey? "sec":"ssb",
nbits_from_sk( sk ),
sk->pubkey_algo,
(ulong)keyid[0],(ulong)keyid[1],
datestr_from_sk( sk ),
- (unsigned)sk->valid_days
+ sk->expiredate? strtimestamp(sk->expiredate):""
/* fixme: add LID */ );
}
else
diff --git a/g10/options.h b/g10/options.h
index d674ada12..ac7629631 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -20,6 +20,10 @@
#ifndef G10_OPTIONS_H
#define G10_OPTIONS_H
+
+#undef ENABLE_COMMENT_PACKETS /* don't create comment packets */
+
+
struct {
int verbose;
unsigned debug;
@@ -37,7 +41,7 @@ struct {
int no_armor;
int list_packets; /* list-packets mode */
int def_cipher_algo;
- int do_not_export_rsa;
+ int reserved1;
int def_digest_algo;
int def_compress_algo;
const char *def_secret_key;
diff --git a/g10/packet.h b/g10/packet.h
index 5bb383c86..4898027a2 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -111,7 +111,7 @@ typedef struct {
*/
typedef struct {
u32 timestamp; /* key made */
- u16 valid_days; /* valid for this number of days */
+ u32 expiredate; /* expires at this date or 0 if not at all */
byte hdrbytes; /* number of header bytes */
byte version;
byte pubkey_algo; /* algorithm used for public key scheme */
@@ -124,7 +124,7 @@ typedef struct {
typedef struct {
u32 timestamp; /* key made */
- u16 valid_days; /* valid for this number of days */
+ u32 expiredate; /* expires at this date or 0 if not at all */
byte hdrbytes; /* number of header bytes */
byte version;
byte pubkey_algo; /* algorithm used for public key scheme */
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 41afe5b9a..c17f2c5c9 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -917,8 +917,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
{
int i, version, algorithm;
unsigned n;
- unsigned long timestamp;
- unsigned short valid_period;
+ unsigned long timestamp, expiredate;
int npkey, nskey;
int is_v4=0;
int rc=0;
@@ -956,25 +955,30 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
timestamp = read_32(inp); pktlen -= 4;
if( is_v4 )
- valid_period = 0;
+ expiredate = 0; /* have to get it from the selfsignature */
else {
- valid_period = read_16(inp); pktlen -= 2;
+ unsigned short ndays;
+ ndays = read_16(inp); pktlen -= 2;
+ if( ndays )
+ expiredate = timestamp + ndays * 86400L;
+ else
+ expiredate = 0;
}
algorithm = iobuf_get_noeof(inp); pktlen--;
if( list_mode )
printf(":%s key packet:\n"
- "\tversion %d, algo %d, created %lu, valid for %hu days\n",
+ "\tversion %d, algo %d, created %lu, expires %lu\n",
pkttype == PKT_PUBLIC_KEY? "public" :
pkttype == PKT_SECRET_KEY? "secret" :
pkttype == PKT_PUBLIC_SUBKEY? "public sub" :
pkttype == PKT_SECRET_SUBKEY? "secret sub" : "??",
- version, algorithm, timestamp, valid_period );
+ version, algorithm, timestamp, expiredate );
if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) {
PKT_secret_key *sk = pkt->pkt.secret_key;
sk->timestamp = timestamp;
- sk->valid_days = valid_period;
+ sk->expiredate = expiredate;
sk->hdrbytes = hdrlen;
sk->version = version;
sk->pubkey_algo = algorithm;
@@ -984,7 +988,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
PKT_public_key *pk = pkt->pkt.public_key;
pk->timestamp = timestamp;
- pk->valid_days = valid_period;
+ pk->expiredate = expiredate;
pk->hdrbytes = hdrlen;
pk->version = version;
pk->pubkey_algo = algorithm;
diff --git a/g10/ringedit.c b/g10/ringedit.c
index 677420e25..6b6f6c855 100644
--- a/g10/ringedit.c
+++ b/g10/ringedit.c
@@ -48,6 +48,7 @@
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <unistd.h> /* for truncate */
#include <assert.h>
#include "util.h"
#include "packet.h"
@@ -55,8 +56,8 @@
#include "mpi.h"
#include "iobuf.h"
#include "keydb.h"
+#include "options.h"
#include "i18n.h"
-#include <unistd.h> /* for truncate */
struct resource_table_struct {
@@ -97,29 +98,75 @@ check_pos( KBPOS *kbpos )
****************************************************************/
/****************
+ * Get the name of the keyrings, start with a sequence number pointing to a 0.
+ */
+const char *
+enum_keyblock_resources( int *sequence, int secret )
+{
+ int i = *sequence;
+ const char *name = NULL;
+
+ for(; i < MAX_RESOURCES; i++ )
+ if( resource_table[i].used && !resource_table[i].secret == !secret ) {
+ if( resource_table[i].fname ) {
+ name = resource_table[i].fname;
+ break;
+ }
+ }
+ *sequence = ++i;
+ return NULL; /* not found */
+}
+
+
+
+/****************
* Register a resource (which currently may only be a keyring file).
+ * The first keyring which is added by this function is
+ * created if it does not exist.
+ * Note: this function may be called before secure memory is
+ * available.
*/
int
-add_keyblock_resource( const char *filename, int force, int secret )
+add_keyblock_resource( const char *resname, int force, int secret )
{
+ static int any_secret, any_public;
IOBUF iobuf;
- int i;
+ int i, force;
+ char *filename;
+ int rc = 0;
+
+ if( *resname != '/' ) { /* do tilde expansion etc */
+ if( strchr(resname, '/') )
+ filename = make_filename(resname, NULL);
+ else
+ filename = make_filename(opt.homedir, resname, NULL);
+ }
+ else
+ filename = m_strdup( resname );
+
+ if( !force )
+ force = secret? !any_secret : !any_public;
for(i=0; i < MAX_RESOURCES; i++ )
if( !resource_table[i].used )
break;
- if( i == MAX_RESOURCES )
- return G10ERR_RESOURCE_LIMIT;
+ if( i == MAX_RESOURCES ) {
+ rc = G10ERR_RESOURCE_LIMIT;
+ goto leave;
+ }
- iobuf = iobuf_open( filename );
- if( !iobuf && !force )
- return G10ERR_OPEN_FILE;
+ iobuf = iobuf_fopen( filename, "rb" );
+ if( !iobuf && !force ) {
+ rc = G10ERR_OPEN_FILE;
+ goto leave;
+ }
if( !iobuf ) {
iobuf = iobuf_create( filename );
if( !iobuf ) {
log_error("%s: can't create: %s\n", filename, strerror(errno));
- return G10ERR_OPEN_FILE;
+ rc = G10ERR_OPEN_FILE;
+ goto leave;
}
else
log_info("%s: keyring created\n", filename );
@@ -135,7 +182,15 @@ add_keyblock_resource( const char *filename, int force, int secret )
resource_table[i].secret = !!secret;
resource_table[i].fname = m_strdup(filename);
resource_table[i].iobuf = iobuf;
- return 0;
+ leave:
+ if( rc )
+ log_error("keyblock resource '%s': %s\n", filename, g10_errstr(rc) );
+ else if( secret )
+ any_secret = 1;
+ else
+ any_public = 1;
+ m_free( filename );
+ return rc;
}
/****************
@@ -362,7 +417,7 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
return -1; /* no resources */
kbpos->resno = i;
rentry = check_pos( kbpos );
- kbpos->fp = iobuf_open( rentry->fname );
+ kbpos->fp = iobuf_fopen( rentry->fname, "rb" );
if( !kbpos->fp ) {
log_error("can't open '%s'\n", rentry->fname );
return G10ERR_OPEN_FILE;
@@ -528,7 +583,6 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
PKT_secret_key *sk = pkt.pkt.secret_key;
if( req_sk->timestamp == sk->timestamp
- && req_sk->valid_days == sk->valid_days
&& req_sk->pubkey_algo == sk->pubkey_algo
&& !cmp_seckey( req_sk, sk) )
break; /* found */
@@ -537,7 +591,6 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
PKT_public_key *pk = pkt.pkt.public_key;
if( req_pk->timestamp == pk->timestamp
- && req_pk->valid_days == pk->valid_days
&& req_pk->pubkey_algo == pk->pubkey_algo
&& !cmp_pubkey( req_pk, pk ) )
break; /* found */
@@ -572,7 +625,7 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
if( !(rentry=check_pos(kbpos)) )
return G10ERR_GENERAL;
- a = iobuf_open( rentry->fname );
+ a = iobuf_fopen( rentry->fname, "rb" );
if( !a ) {
log_error("can't open '%s'\n", rentry->fname );
return G10ERR_OPEN_FILE;
@@ -732,7 +785,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
BUG(); /* not allowed with such a handle */
/* open the source file */
- fp = iobuf_open( rentry->fname );
+ fp = iobuf_fopen( rentry->fname, "rb" );
if( mode == 1 && !fp && errno == ENOENT ) { /* no file yet */
KBNODE kbctx, node;
diff --git a/g10/sig-check.c b/g10/sig-check.c
index b983bb42c..fd476f767 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.c
@@ -166,11 +166,9 @@ do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest )
return G10ERR_TIME_CONFLICT;
}
- if( pk->valid_days && add_days_to_timestamp(pk->timestamp,
- pk->valid_days) < cur_time ) {
- log_info(_("warning: signature key expired %s\n"), strtimestamp(
- add_days_to_timestamp(pk->timestamp,
- pk->valid_days)));
+ if( pk->expiredate && pk->expiredate < cur_time ) {
+ log_info(_("warning: signature key expired %s\n"),
+ asctimestamp( pk->expiredate ) );
write_status(STATUS_SIGEXPIRED);
}
diff --git a/g10/sign.c b/g10/sign.c
index 349b2f34d..304843f59 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -225,12 +225,14 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
if( opt.armor && !outfile )
iobuf_push_filter( out, armor_filter, &afx );
+ #ifdef ENABLE_COMMENT_PACKETS
else {
write_comment( out, "#created by GNUPG v" VERSION " ("
PRINTABLE_OS_NAME ")");
if( opt.comment_string )
write_comment( out, opt.comment_string );
}
+ #endif
if( encrypt ) {
efx.pk_list = pk_list;
/* fixme: set efx.cfx.datalen if known */
diff --git a/g10/tdbio.c b/g10/tdbio.c
index 82b22b43a..425919338 100644
--- a/g10/tdbio.c
+++ b/g10/tdbio.c
@@ -39,6 +39,27 @@
#include "trustdb.h"
#include "tdbio.h"
+
+/****************
+ * Yes, this is a very simple implementation. We should really
+ * use a page aligned buffer and read complete pages.
+ * To implement a simple trannsaction system, this is sufficient.
+ */
+typedef struct cache_ctrl_struct *CACHE_CTRL;
+struct cache_ctrl_struct {
+ CACHE_CTRL next;
+ struct {
+ unsigned used:1;
+ unsigned dirty:1;
+ } flags;
+ ulong recno;
+ char data[TRUST_RECORD_LEN];
+};
+
+#define MAX_CACHE_ENTRIES 200
+static CACHE_CTRL cache_list;
+static int cache_entries;
+
/* a type used to pass infomation to cmp_krec_fpr */
struct cmp_krec_fpr_struct {
int pubkey_algo;
@@ -59,6 +80,184 @@ static int db_fd = -1;
static void open_db(void);
+
+/*************************************
+ ************* record cache **********
+ *************************************/
+
+/****************
+ * Get the data from therecord cache and return a
+ * pointer into that cache. Caller should copy
+ * the return data. NULL is returned on a cache miss.
+ */
+static const char *
+get_record_from_cache( ulong recno )
+{
+ CACHE_CTRL r;
+
+ for( r = cache_list; r; r = r->next ) {
+ if( r->flags.used && r->recno == recno )
+ return r->data;
+ }
+ return NULL;
+}
+
+
+static int
+write_cache_item( CACHE_CTRL r )
+{
+ int n;
+
+ if( lseek( db_fd, r->recno * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
+ log_error(_("trustdb rec %lu: lseek failed: %s\n"),
+ r->recno, strerror(errno) );
+ return G10ERR_WRITE_FILE;
+ }
+ n = write( db_fd, r->data, TRUST_RECORD_LEN);
+ if( n != TRUST_RECORD_LEN ) {
+ log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"),
+ r->recno, n, strerror(errno) );
+ return G10ERR_WRITE_FILE;
+ }
+ r->flags.dirty = 0;
+ return 0;
+}
+
+/****************
+ * Put data into the cache. This function may flush the
+ * some cache entries if there is not enough space available.
+ */
+int
+put_record_into_cache( ulong recno, const char *data )
+{
+ CACHE_CTRL r, unused;
+ int dirty_count = 0;
+ int clean_count = 0;
+
+ /* see whether we already cached this one */
+ for( unused = NULL, r = cache_list; r; r = r->next ) {
+ if( !r->flags.used ) {
+ if( !unused )
+ unused = r;
+ }
+ else if( r->recno == recno ) {
+ if( !r->flags.dirty ) {
+ /* Hmmm: should we use a a copy and compare? */
+ if( memcmp(r->data, data, TRUST_RECORD_LEN ) )
+ r->flags.dirty = 1;
+ }
+ memcpy( r->data, data, TRUST_RECORD_LEN );
+ return 0;
+ }
+ if( r->flags.used ) {
+ if( r->flags.dirty )
+ dirty_count++;
+ else
+ clean_count++;
+ }
+ }
+ /* not in the cache: add a new entry */
+ if( unused ) { /* reuse this entry */
+ r = unused;
+ r->flags.used = 1;
+ r->recno = recno;
+ memcpy( r->data, data, TRUST_RECORD_LEN );
+ r->flags.dirty = 1;
+ cache_entries++;
+ return 0;
+ }
+ /* see whether we reached the limit */
+ if( cache_entries < MAX_CACHE_ENTRIES ) { /* no */
+ r = m_alloc( sizeof *r );
+ r->flags.used = 1;
+ r->recno = recno;
+ memcpy( r->data, data, TRUST_RECORD_LEN );
+ r->flags.dirty = 1;
+ r->next = cache_list;
+ cache_list = r;
+ cache_entries++;
+ return 0;
+ }
+ /* cache is full: discard some clean entries */
+ if( clean_count ) {
+ int n = clean_count / 3; /* discard a third of the clean entries */
+ if( !n )
+ n = 1;
+ for( unused = NULL, r = cache_list; r; r = r->next ) {
+ if( r->flags.used && !r->flags.dirty ) {
+ if( !unused )
+ unused = r;
+ r->flags.used = 0;
+ cache_entries--;
+ if( !--n )
+ break;
+ }
+ }
+ assert( unused );
+ r = unused;
+ r->flags.used = 1;
+ r->recno = recno;
+ memcpy( r->data, data, TRUST_RECORD_LEN );
+ r->flags.dirty = 1;
+ cache_entries++;
+ return 0;
+ }
+ /* no clean entries: have to flush some dirty entries */
+ if( dirty_count ) {
+ int n = dirty_count / 5; /* discard some dirty entries */
+ if( !n )
+ n = 1;
+ for( unused = NULL, r = cache_list; r; r = r->next ) {
+ if( r->flags.used && r->flags.dirty ) {
+ int rc = write_cache_item( r );
+ if( rc )
+ return rc;
+ if( !unused )
+ unused = r;
+ r->flags.used = 0;
+ cache_entries--;
+ if( !--n )
+ break;
+ }
+ }
+ assert( unused );
+ r = unused;
+ r->flags.used = 1;
+ r->recno = recno;
+ memcpy( r->data, data, TRUST_RECORD_LEN );
+ r->flags.dirty = 1;
+ cache_entries++;
+ return 0;
+ }
+ BUG();
+}
+
+
+
+/****************
+ * Sync the cache to disk
+ */
+
+int
+tdbio_sync()
+{
+ CACHE_CTRL r;
+
+ for( r = cache_list; r; r = r->next ) {
+ if( r->flags.used && r->flags.dirty ) {
+ int rc = write_cache_item( r );
+ if( rc )
+ return rc;
+ }
+ }
+ return 0;
+}
+
+
+
+/********************************************************
+ **************** cached I/O functions ******************
+ ********************************************************/
int
tdbio_set_dbname( const char *new_dbname, int create )
@@ -118,6 +317,8 @@ tdbio_set_dbname( const char *new_dbname, int create )
rec.rectype = RECTYPE_VER;
rec.recnum = 0;
rc = tdbio_write_record( &rec );
+ if( !rc )
+ tdbio_sync();
if( rc )
log_fatal_f( fname, _("failed to create version record: %s"),
g10_errstr(rc));
@@ -185,7 +386,7 @@ create_hashtable( TRUSTREC *vr, int type )
n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD;
for(i=0; i < n; i++, recnum++ ) {
memset( &rec, 0, sizeof rec );
- rec.rectype = RECTYPE_HTBL; /* free record */
+ rec.rectype = RECTYPE_HTBL;
rec.recnum = recnum;
rc = tdbio_write_record( &rec );
if( rc )
@@ -194,6 +395,8 @@ create_hashtable( TRUSTREC *vr, int type )
}
/* update the version record */
rc = tdbio_write_record( vr );
+ if( !rc )
+ rc = tdbio_sync();
if( rc )
log_fatal_f( db_name, _("error updating version record: %s\n"),
g10_errstr(rc));
@@ -208,21 +411,21 @@ static ulong
get_keyhashrec()
{
static ulong keyhashtbl; /* record number of the key hashtable */
- TRUSTREC vr;
- int rc;
- if( keyhashtbl )
- return keyhashtbl;
-
- rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
- if( rc )
- log_fatal_f( db_name, _("error reading version record: %s\n"),
- g10_errstr(rc) );
- if( !vr.r.ver.keyhashtbl )
- create_hashtable( &vr, 0 );
+ if( !keyhashtbl ) {
+ TRUSTREC vr;
+ int rc;
+ rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
+ if( rc )
+ log_fatal_f( db_name, _("error reading version record: %s\n"),
+ g10_errstr(rc) );
+ if( !vr.r.ver.keyhashtbl )
+ create_hashtable( &vr, 0 );
- return vr.r.ver.keyhashtbl;
+ keyhashtbl = vr.r.ver.keyhashtbl;
+ }
+ return keyhashtbl;
}
/****************
@@ -233,20 +436,21 @@ static ulong
get_sdirhashrec()
{
static ulong sdirhashtbl; /* record number of the hashtable */
- TRUSTREC vr;
- int rc;
- if( sdirhashtbl )
- return sdirhashtbl;
+ if( !sdirhashtbl ) {
+ TRUSTREC vr;
+ int rc;
- rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
- if( rc )
- log_fatal_f( db_name, _("error reading version record: %s\n"),
- g10_errstr(rc) );
- if( !vr.r.ver.sdirhashtbl )
- create_hashtable( &vr, 1 );
+ rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
+ if( rc )
+ log_fatal_f( db_name, _("error reading version record: %s\n"),
+ g10_errstr(rc) );
+ if( !vr.r.ver.sdirhashtbl )
+ create_hashtable( &vr, 1 );
- return vr.r.ver.sdirhashtbl;
+ sdirhashtbl = vr.r.ver.sdirhashtbl;
+ }
+ return sdirhashtbl;
}
@@ -289,15 +493,16 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
lastrec = rec;
rc = tdbio_read_record( item, &rec, 0 );
if( rc ) {
- log_error( db_name, "upd_hashtable: read item failed: %s\n",
+ log_error( "upd_hashtable: read item failed: %s\n",
g10_errstr(rc) );
return rc;
}
+
if( rec.rectype == RECTYPE_HTBL ) {
hashrec = item;
level++;
if( level >= keylen ) {
- log_error( db_name, "hashtable has invalid indirections.\n");
+ log_error( "hashtable has invalid indirections.\n");
return G10ERR_TRUSTDB;
}
goto next_level;
@@ -314,8 +519,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
rc = tdbio_read_record( rec.r.hlst.next,
&rec, RECTYPE_HLST);
if( rc ) {
- log_error( db_name,
- "scan keyhashtbl read hlst failed: %s\n",
+ log_error( "scan keyhashtbl read hlst failed: %s\n",
g10_errstr(rc) );
return rc;
}
@@ -330,8 +534,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
rec.r.hlst.rnum[i] = newrecnum;
rc = tdbio_write_record( &rec );
if( rc )
- log_error( db_name,
- "upd_hashtable: write hlst failed: %s\n",
+ log_error( "upd_hashtable: write hlst failed: %s\n",
g10_errstr(rc) );
return rc; /* done */
}
@@ -340,8 +543,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
rc = tdbio_read_record( rec.r.hlst.next,
&rec, RECTYPE_HLST );
if( rc ) {
- log_error( db_name,
- "upd_hashtable: read hlst failed: %s\n",
+ log_error( "upd_hashtable: read hlst failed: %s\n",
g10_errstr(rc) );
return rc;
}
@@ -350,8 +552,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
rec.r.hlst.next = item = tdbio_new_recnum();
rc = tdbio_write_record( &rec );
if( rc ) {
- log_error( db_name,
- "upd_hashtable: write hlst failed: %s\n",
+ log_error( "upd_hashtable: write hlst failed: %s\n",
g10_errstr(rc) );
return rc;
}
@@ -361,14 +562,14 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
rec.r.hlst.rnum[0] = newrecnum;
rc = tdbio_write_record( &rec );
if( rc )
- log_error( db_name,
- "upd_hashtable: write ext hlst failed: %s\n",
+ log_error( "upd_hashtable: write ext hlst failed: %s\n",
g10_errstr(rc) );
return rc; /* done */
}
} /* end loop over hlst slots */
}
else if( rec.rectype == RECTYPE_KEY
+ || rec.rectype == RECTYPE_DIR
|| rec.rectype == RECTYPE_SDIR ) { /* insert a list record */
if( rec.recnum == newrecnum ) {
return 0;
@@ -381,8 +582,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
rec.r.hlst.rnum[1] = newrecnum; /* and new one */
rc = tdbio_write_record( &rec );
if( rc ) {
- log_error( db_name,
- "upd_hashtable: write new hlst failed: %s\n",
+ log_error( "upd_hashtable: write new hlst failed: %s\n",
g10_errstr(rc) );
return rc;
}
@@ -390,12 +590,12 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum;
rc = tdbio_write_record( &lastrec );
if( rc )
- log_error( db_name, "upd_hashtable: update htbl failed: %s\n",
+ log_error( "upd_hashtable: update htbl failed: %s\n",
g10_errstr(rc) );
return rc; /* ready */
}
else {
- log_error( db_name, "hashtbl %lu points to an invalid record\n",
+ log_error( "hashtbl %lu points to an invalid record\n",
item);
return G10ERR_TRUSTDB;
}
@@ -637,23 +837,29 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
int
tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
{
- byte buf[TRUST_RECORD_LEN], *p;
+ byte readbuf[TRUST_RECORD_LEN];
+ const byte *buf, *p;
int rc = 0;
int n, i;
if( db_fd == -1 )
open_db();
- if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
- log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) );
- return G10ERR_READ_FILE;
- }
- n = read( db_fd, buf, TRUST_RECORD_LEN);
- if( !n ) {
- return -1; /* eof */
- }
- else if( n != TRUST_RECORD_LEN ) {
- log_error(_("trustdb: read failed (n=%d): %s\n"), n, strerror(errno) );
- return G10ERR_READ_FILE;
+ buf = get_record_from_cache( recnum );
+ if( !buf ) {
+ if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
+ log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) );
+ return G10ERR_READ_FILE;
+ }
+ n = read( db_fd, readbuf, TRUST_RECORD_LEN);
+ if( !n ) {
+ return -1; /* eof */
+ }
+ else if( n != TRUST_RECORD_LEN ) {
+ log_error(_("trustdb: read failed (n=%d): %s\n"), n,
+ strerror(errno) );
+ return G10ERR_READ_FILE;
+ }
+ buf = readbuf;
}
rec->recnum = recnum;
rec->dirty = 0;
@@ -791,14 +997,12 @@ tdbio_write_record( TRUSTREC *rec )
{
byte buf[TRUST_RECORD_LEN], *p;
int rc = 0;
- int i, n;
+ int i;
ulong recnum = rec->recnum;
if( db_fd == -1 )
open_db();
-tdbio_dump_record( rec, stdout );
-
memset(buf, 0, TRUST_RECORD_LEN);
p = buf;
*p++ = rec->rectype; p++;
@@ -900,16 +1104,10 @@ tdbio_dump_record( rec, stdout );
BUG();
}
- if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
- log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) );
- return G10ERR_WRITE_FILE;
- }
- n = write( db_fd, buf, TRUST_RECORD_LEN);
- if( n != TRUST_RECORD_LEN ) {
- log_error(_("trustdb: write failed (n=%d): %s\n"), n, strerror(errno) );
- return G10ERR_WRITE_FILE;
- }
- else if( rec->rectype == RECTYPE_KEY )
+ rc = put_record_into_cache( recnum, buf );
+ if( rc )
+ ;
+ if( rec->rectype == RECTYPE_KEY )
rc = update_keyhashtbl( rec );
else if( rec->rectype == RECTYPE_SDIR )
rc = update_sdirhashtbl( rec );
@@ -990,7 +1188,21 @@ tdbio_new_recnum()
memset( &rec, 0, sizeof rec );
rec.rectype = 0; /* unused record */
rec.recnum = recnum;
- rc = tdbio_write_record( &rec );
+ rc = 0;
+ if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
+ log_error(_("trustdb rec %lu: lseek failed: %s\n"),
+ recnum, strerror(errno) );
+ rc = G10ERR_WRITE_FILE;
+ }
+ else {
+ int n = write( db_fd, &rec, TRUST_RECORD_LEN);
+ if( n != TRUST_RECORD_LEN ) {
+ log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"),
+ recnum, n, strerror(errno) );
+ rc = G10ERR_WRITE_FILE;
+ }
+ }
+
if( rc )
log_fatal_f(db_name,_("failed to append a record: %s\n"),
g10_errstr(rc));
diff --git a/g10/tdbio.h b/g10/tdbio.h
index 66579ad14..42bb4aa48 100644
--- a/g10/tdbio.h
+++ b/g10/tdbio.h
@@ -166,6 +166,7 @@ const char *tdbio_get_dbname(void);
void tdbio_dump_record( TRUSTREC *rec, FILE *fp );
int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected );
int tdbio_write_record( TRUSTREC *rec );
+int tdbio_sync(void);
int tdbio_delete_record( ulong recnum );
ulong tdbio_new_recnum(void);
int tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec );
diff --git a/g10/textfilter.c b/g10/textfilter.c
index 804b48505..fc81a9136 100644
--- a/g10/textfilter.c
+++ b/g10/textfilter.c
@@ -48,7 +48,7 @@ read_line( byte *buf, size_t *r_buflen, IOBUF a )
assert(buflen >= 20 );
buflen -= 3; /* leave some room for CR,LF and one extra */
- for(c=0, n=0; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; )
+ for(c=0, n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
buf[n++] = c;
buf[n] = 0;
if( c == -1 ) {
@@ -58,7 +58,7 @@ read_line( byte *buf, size_t *r_buflen, IOBUF a )
}
else if( c != '\n' ) {
IOBUF b = iobuf_temp();
- while( (c=iobuf_get2(a)) != -1 && c != '\n' ) {
+ while( (c=iobuf_get(a)) != -1 && c != '\n' ) {
iobuf_put(b,c);
if( c != ' ' && c != '\t' && c != '\r' )
break;
diff --git a/g10/trustdb.c b/g10/trustdb.c
index 18726f151..eb6ea3ca6 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -71,11 +71,6 @@ struct trust_seg_list {
};
-typedef struct {
- TRUST_SEG_LIST tsl;
- int index;
-} ENUM_TRUST_WEB_CONTEXT;
-
struct recno_list_struct {
struct recno_list_struct *next;
@@ -171,6 +166,19 @@ delete_record( ulong recno )
die_invalid_db();
}
+/****************
+ * sync the db
+ */
+static void
+do_sync( )
+{
+ int rc = tdbio_sync();
+ if( !rc )
+ return;
+ log_error("trust db: sync failed: %s\n", g10_errstr(rc) );
+ g10_exit(2);
+}
+
/**********************************************
@@ -425,15 +433,15 @@ verify_own_keys()
memset( pk, 0, sizeof *pk );
rc = get_pubkey( pk, keyid );
if( rc ) {
- log_error(_("key %08lX: secret key without public key\n"),
+ log_info(_("key %08lX: secret key without public key - skipped\n"),
(ulong)keyid[1] );
- goto leave;
+ goto skip;
}
+
if( cmp_public_secret_key( pk, sk ) ) {
- log_error(_("key %08lX: secret and public key don't match\n"),
+ log_info(_("key %08lX: secret and public key don't match\n"),
(ulong)keyid[1] );
- rc = G10ERR_GENERAL;
- goto leave;
+ goto skip;
}
/* make sure that the pubkey is in the trustdb */
@@ -443,12 +451,12 @@ verify_own_keys()
if( rc ) {
log_error(_("key %08lX: can't put it into the trustdb\n"),
(ulong)keyid[1] );
- goto leave;
+ goto skip;
}
}
else if( rc ) {
log_error(_("key %08lX: query record failed\n"), (ulong)keyid[1] );
- goto leave;
+ goto skip;
}
@@ -456,9 +464,12 @@ verify_own_keys()
log_debug("key %08lX.%lu: stored into ultikey_table\n",
(ulong)keyid[1], pk->local_id );
if( ins_lid_table_item( ultikey_table, pk->local_id, 0 ) )
- log_error(_("key %08lX: already in ultikey_table\n"),
+ log_error(_("key %08lX: already in secret key table\n"),
(ulong)keyid[1]);
-
+ else if( opt.verbose )
+ log_info(_("key %08lX: accepted as secret key.\n"),
+ (ulong)keyid[1]);
+ skip:
release_secret_key_parts( sk );
release_public_key_parts( pk );
}
@@ -467,7 +478,6 @@ verify_own_keys()
else
rc = 0;
- leave:
enum_secret_keys( &enum_context, NULL, 0 ); /* free context */
free_secret_key( sk );
free_public_key( pk );
@@ -695,6 +705,13 @@ do_list_path( TRUST_INFO *stack, int depth, int max_depth,
TRUST_SEG_LIST tsl, t2, tl;
int i;
+ if( !(sx.sig_flag & SIGF_CHECKED) )
+ continue; /* only checked sigs */
+ if( !(sx.sig_flag & SIGF_VALID) )
+ continue; /* and, of course, only valid sigs */
+ if( (sx.sig_flag & SIGF_REVOKED) )
+ continue; /* and skip revoked sigs */
+
stack[depth].lid = sx.sig_lid;
stack[depth].trust = 0;
if( qry_lid_table_flag( lids, sx.sig_lid, &last_depth) ) {
@@ -782,8 +799,13 @@ make_tsl( ulong lid, TRUST_SEG_LIST *ret_tslist )
release_lid_table(work);
*ret_tslist = tslist;
}
- else
- ; /* FIXME: release tslist */
+ else { /* error: release tslist */
+ while( tslist ) {
+ tsl = tslist->next;
+ m_free(tslist);
+ tslist = tsl;
+ }
+ }
release_lid_table(lids);
return rc;
}
@@ -865,7 +887,7 @@ do_check( TRUSTREC *dr, unsigned *trustlevel )
if( dr->r.dir.dirflags & DIRF_REVOKED )
tflags |= TRUST_FLAG_REVOKED;
- #if 0
+ #if 0 /* Do we still need this?? */
if( !rc && !dr->r.dir.siglist ) {
/* We do not have any signatures; check whether it is one of our
* secret keys */
@@ -1153,6 +1175,7 @@ import_ownertrust( const char *fname )
log_error_f(fname, _("read error: %s\n"), strerror(errno) );
if( !is_stdin )
fclose(fp);
+ do_sync();
}
@@ -1247,8 +1270,6 @@ list_trust_path( int max_depth, const char *username )
/****************
* Check the complete trustdb or only the entries for the given username.
- * Special hack: A username "REBUILD" inserts all records from the public
- * key rings into the trustdb.
*/
void
check_trustdb( const char *username )
@@ -1257,9 +1278,8 @@ check_trustdb( const char *username )
KBNODE keyblock = NULL;
KBPOS kbpos;
int rc;
- int rebuild = username && !strcmp(username, "REBUILD");
- if( username && !rebuild ) {
+ if( username ) {
rc = find_keyblock_byname( &kbpos, username );
if( !rc )
rc = read_keyblock( &kbpos, &keyblock );
@@ -1315,43 +1335,48 @@ check_trustdb( const char *username )
release_kbnode( keyblock ); keyblock = NULL;
}
}
- if( rebuild ) {
- log_info("adding new entries.\n");
-
- rc = enum_keyblocks( 0, &kbpos, &keyblock );
- if( !rc ) {
- while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) {
- rc = update_trust_record( keyblock );
- if( rc == -1 ) { /* not yet in trustdb: insert */
- PKT_public_key *pk =
- find_kbnode( keyblock, PKT_PUBLIC_KEY
- ) ->pkt->pkt.public_key;
- rc = insert_trust_record( pk );
- if( rc && !pk->local_id )
- log_error("lid ?: insert failed: %s\n",
- g10_errstr(rc) );
- else if( rc )
- log_error("lid %lu: insert failed: %s\n",
- pk->local_id, g10_errstr(rc) );
- else
- log_info("lid %lu: inserted\n", pk->local_id );
- }
- else if( rc )
- log_error("lid %lu: update failed: %s\n",
- lid_from_keyblock(keyblock), g10_errstr(rc) );
- else
- log_info("lid %lu: updated\n",
- lid_from_keyblock(keyblock) );
- }
- }
- if( rc && rc != -1 )
- log_error("enum_keyblocks failed: %s\n", g10_errstr(rc));
+ }
+}
- enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
- release_kbnode( keyblock );
- }
+void
+update_trustdb( )
+{
+ KBNODE keyblock = NULL;
+ KBPOS kbpos;
+ int rc;
+
+ rc = enum_keyblocks( 0, &kbpos, &keyblock );
+ if( !rc ) {
+ while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) {
+ rc = update_trust_record( keyblock );
+ if( rc == -1 ) { /* not yet in trustdb: insert */
+ PKT_public_key *pk =
+ find_kbnode( keyblock, PKT_PUBLIC_KEY
+ ) ->pkt->pkt.public_key;
+ rc = insert_trust_record( pk );
+ if( rc && !pk->local_id )
+ log_error("lid ?: insert failed: %s\n",
+ g10_errstr(rc) );
+ else if( rc )
+ log_error("lid %lu: insert failed: %s\n",
+ pk->local_id, g10_errstr(rc) );
+ else
+ log_info("lid %lu: inserted\n", pk->local_id );
+ }
+ else if( rc )
+ log_error("lid %lu: update failed: %s\n",
+ lid_from_keyblock(keyblock), g10_errstr(rc) );
+ else
+ log_info("lid %lu: updated\n",
+ lid_from_keyblock(keyblock) );
+ }
}
+ if( rc && rc != -1 )
+ log_error("enum_keyblocks failed: %s\n", g10_errstr(rc));
+
+ enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
+ release_kbnode( keyblock );
}
@@ -1418,12 +1443,10 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel )
return G10ERR_TIME_CONFLICT;
}
- if( pk->valid_days && add_days_to_timestamp(pk->timestamp,
- pk->valid_days) < cur_time ) {
+ if( pk->expiredate && pk->expiredate <= cur_time ) {
log_info(_("key %08lX.%lu: expired at %s\n"),
(ulong)keyid[1], pk->local_id,
- asctimestamp( add_days_to_timestamp(pk->timestamp,
- pk->valid_days)));
+ asctimestamp( pk->expiredate) );
trustlevel = TRUST_EXPIRED;
}
else {
@@ -1485,7 +1508,10 @@ query_trust_info( PKT_public_key *pk )
int
enum_trust_web( void **context, ulong *lid )
{
- ENUM_TRUST_WEB_CONTEXT *c = *context;
+ struct {
+ TRUST_SEG_LIST tsl;
+ int index;
+ } *c = *context;
if( !c ) { /* make a new context */
c = m_alloc_clear( sizeof *c );
@@ -1652,7 +1678,7 @@ query_trust_record( PKT_public_key *pk )
return get_dir_record( pk, &rec );
}
-
+/* FIXME: Brauchen wir das?? */
int
clear_trust_checked_flag( PKT_public_key *pk )
{
@@ -1669,6 +1695,7 @@ clear_trust_checked_flag( PKT_public_key *pk )
/* reset the flag */
rec.r.dir.dirflags &= ~DIRF_CHECKED;
write_record( &rec );
+ do_sync();
return 0;
}
@@ -1684,6 +1711,8 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash,
byte uhash[20];
int is_selfsig;
PKT_signature *sigpkt = NULL;
+ TRUSTREC tmp;
+ u32 sigkid[2];
if( sigrec->r.sig.sig[sigidx].flag & SIGF_CHECKED )
log_info(_("note: sig rec %lu[%d] in hintlist "
@@ -1694,6 +1723,23 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash,
"of %lu but not marked\n"),
sigrec->recnum, sigidx, hint_owner );
+ read_record( sigrec->r.sig.sig[sigidx].lid, &tmp, 0 );
+ if( tmp.rectype != RECTYPE_DIR ) {
+ /* we need the dir record */
+ log_error(_("sig rec %lu[%d] in hintlist "
+ "of %u does not point to a dir record\n"),
+ sigrec->recnum, sigidx, hint_owner );
+ return;
+ }
+ if( !tmp.r.dir.keylist ) {
+ log_error(_("lid %lu: no primary key\n"), tmp.r.dir.lid );
+ return;
+ }
+ read_record(tmp.r.dir.keylist, &tmp, RECTYPE_KEY );
+ keyid_from_fingerprint( tmp.r.key.fingerprint,
+ tmp.r.key.fingerprint_len, sigkid );
+
+
/* find the correct signature packet */
for( node=keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
@@ -1707,8 +1753,8 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash,
}
else if( state && node->pkt->pkttype == PKT_SIGNATURE ) {
sigpkt = node->pkt->pkt.signature;
- if( sigpkt->keyid[0] == keyid[0]
- && sigpkt->keyid[1] == keyid[1]
+ if( sigpkt->keyid[0] == sigkid[0]
+ && sigpkt->keyid[1] == sigkid[1]
&& (sigpkt->sig_class&~3) == 0x10 )
break; /* found */
}
@@ -1723,23 +1769,28 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash,
rc = check_key_signature( keyblock, node, &is_selfsig );
if( is_selfsig ) {
log_error(_("lid %lu: self-signature in hintlist\n"), lid );
- return ;
+ return;
}
if( !rc ) { /* valid signature */
+ if( opt.verbose )
+ log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: "
+ "good signature (3)\n"),
+ (ulong)keyid[1], lid, uhash[18], uhash[19],
+ (ulong)sigpkt->keyid[1] );
sigrec->r.sig.sig[sigidx].flag = SIGF_CHECKED | SIGF_VALID;
}
else if( rc == G10ERR_NO_PUBKEY ) {
- log_info(_("key %08lX.%lu, uid %02X%02X: "
- "very strange: no public key for signature %08lX\n"),
+ log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: "
+ "very strange: no public key\n"),
(ulong)keyid[1], lid, uhash[18], uhash[19],
(ulong)sigpkt->keyid[1] );
sigrec->r.sig.sig[sigidx].flag = SIGF_NOPUBKEY;
}
else {
- log_info(_("key %08lX.%lu, uid %02X%02X: "
+ log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: "
"invalid signature: %s\n"),
- (ulong)keyid[1], lid,
- uhash[18], uhash[19], g10_errstr(rc));
+ (ulong)keyid[1], lid, uhash[18], uhash[19],
+ (ulong)sigpkt->keyid[1], g10_errstr(rc) );
sigrec->r.sig.sig[sigidx].flag = SIGF_CHECKED;
}
sigrec->dirty = 1;
@@ -1930,7 +1981,7 @@ upd_uid_record( PKT_user_id *uid, TRUSTREC *drec, RECNO_LIST *recno_list,
static void
upd_pref_record( PKT_signature *sig, TRUSTREC *drec,
- u32 *keyid, ulong *uidrecno, byte *uidhash )
+ u32 *keyid, TRUSTREC *urec, byte *uidhash )
{
static struct {
sigsubpkttype_t subpkttype;
@@ -1941,7 +1992,7 @@ upd_pref_record( PKT_signature *sig, TRUSTREC *drec,
{ SIGSUBPKT_PREF_COMPR, PREFTYPE_COMPR },
{ 0, 0 }
};
- TRUSTREC urec, prec;
+ TRUSTREC prec;
const byte *s;
size_t n;
int k, i;
@@ -1949,13 +2000,10 @@ upd_pref_record( PKT_signature *sig, TRUSTREC *drec,
int recno_idx = 0;
ulong recno;
- /* we need the uid record */
- read_record( *uidrecno, &urec, RECTYPE_UID );
-
/* First delete all pref records
* This is much simpler than checking whether we have to
* do update the record at all - the record cache may care about it */
- for( recno=urec.r.uid.prefrec; recno; recno = prec.r.pref.next ) {
+ for( recno=urec->r.uid.prefrec; recno; recno = prec.r.pref.next ) {
read_record( recno, &prec, RECTYPE_PREF );
delete_record( recno );
}
@@ -1999,8 +2047,8 @@ upd_pref_record( PKT_signature *sig, TRUSTREC *drec,
write_record( &prec );
}
/* don't need to write the last one, but update the uid */
- urec.r.uid.prefrec = recno_idx? recno_tbl[0] : 0;
- write_record( &urec );
+ urec->r.uid.prefrec = recno_idx? recno_tbl[0] : 0;
+ urec->dirty = 1;
}
@@ -2014,25 +2062,41 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec,
u32 *keyid, ulong *uidrecno, byte *uidhash,
KBNODE keyblock, KBNODE signode )
{
+ TRUSTREC urec;
int rc;
ulong lid = drec->recnum;
+ if( !*uidrecno ) {
+ /* fixme: handle direct key signatures */
+ log_error("key %08lX: signature without user id\n", (ulong)keyid[1] );
+ return;
+ }
+ read_record( *uidrecno, &urec, RECTYPE_UID );
+
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) {
if( (sig->sig_class&~3) == 0x10 ) {
/* must verify this selfsignature here, so that we can
* build the preference record and validate the uid record
*/
- if( !*uidrecno ) {
- log_error("key %08lX: self-signature without user id\n",
- (ulong)keyid[1] );
- }
- else if( (rc = check_key_signature( keyblock, signode, NULL ))) {
- log_error("key %08lX, uid %02X%02X: "
- "invalid self-signature: %s\n", (ulong)keyid[1],
- uidhash[18], uidhash[19], g10_errstr(rc) );
- }
- else { /* valid sig (may be revoked, but that doesn't matter here) */
- upd_pref_record( sig, drec, keyid, uidrecno, uidhash );
+ if( !(urec.r.uid.uidflags & UIDF_CHECKED) ) {
+ rc = check_key_signature( keyblock, signode, NULL );
+ if( !rc ) {
+ if( opt.verbose )
+ log_info(_(
+ "key %08lX.%lu, uid %02X%02X: "
+ "good self-signature\n"),
+ (ulong)keyid[1], lid, uidhash[18],
+ uidhash[19] );
+ upd_pref_record( sig, drec, keyid, &urec, uidhash );
+ urec.r.uid.uidflags = UIDF_CHECKED | UIDF_VALID;
+ }
+ else {
+ log_error("key %08lX, uid %02X%02X: "
+ "invalid self-signature: %s\n", (ulong)keyid[1],
+ uidhash[18], uidhash[19], g10_errstr(rc) );
+ urec.r.uid.uidflags = UIDF_CHECKED;
+ }
+ urec.dirty = 1;
}
}
else {/* is revocation sig etc */
@@ -2051,18 +2115,43 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec,
* be converted to a dir record as soon as a new public key is
* inserted into the trustdb.
*/
- TRUSTREC urec, rec;
+ TRUSTREC rec;
ulong recno;
TRUSTREC delrec;
int delrecidx;
int newflag = 0;
ulong newlid = 0;
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
+ ulong pk_lid = 0;
+ int found_sig = 0;
+ int found_delrec = 0;
delrec.recnum = 0;
- /* we need the uid record */
- read_record( *uidrecno, &urec, RECTYPE_UID );
+ rc = get_pubkey( pk, sig->keyid );
+ if( !rc ) {
+ if( pk->local_id )
+ pk_lid = pk->local_id;
+ else {
+ rc = tdbio_search_dir_bypk( pk, &rec );
+ if( !rc )
+ pk_lid = rec.recnum;
+ else if( rc == -1 ) { /* see whether there is a sdir instead */
+ u32 akid[2];
+
+ keyid_from_pk( pk, akid );
+ rc = tdbio_search_sdir( akid, pk->pubkey_algo, &rec );
+ if( !rc )
+ pk_lid = rec.recnum;
+ }
+ }
+ }
+ free_public_key( pk ); pk = NULL;
+
+ /* Loop over all signatures just in case one is not correctly
+ * marked. If we see the correct signature, set a flag.
+ * delete duplicate signatures (should not happen but...)
+ */
for( recno = urec.r.uid.siglist; recno; recno = rec.r.sig.next ) {
int i;
@@ -2070,12 +2159,25 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec,
for(i=0; i < SIGS_PER_RECORD; i++ ) {
TRUSTREC tmp;
if( !rec.r.sig.sig[i].lid ) {
- if( !delrec.recnum ) {
+ if( !found_delrec && !delrec.recnum ) {
delrec = rec;
delrecidx = i;
+ found_delrec=1;
}
continue; /* skip deleted sigs */
}
+ if( rec.r.sig.sig[i].lid == pk_lid ) {
+ if( found_sig ) {
+ log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: "
+ "duplicated signature - deleted\n"),
+ (ulong)keyid[1], lid, uidhash[18],
+ uidhash[19], (ulong)sig->keyid[1] );
+ rec.r.sig.sig[i].lid = 0;
+ rec.dirty = 1;
+ }
+ else
+ found_sig = 1;
+ }
if( rec.r.sig.sig[i].flag & SIGF_CHECKED )
continue; /* we already checked this signature */
if( rec.r.sig.sig[i].flag & SIGF_NOPUBKEY )
@@ -2087,24 +2189,30 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec,
* the signature: */
rc = check_key_signature( keyblock, signode, NULL );
if( !rc ) { /* valid signature */
+ if( opt.verbose )
+ log_info(_(
+ "key %08lX.%lu, uid %02X%02X, sig %08lX: "
+ "good signature (1)\n"),
+ (ulong)keyid[1], lid, uidhash[18],
+ uidhash[19], (ulong)sig->keyid[1] );
rec.r.sig.sig[i].flag = SIGF_CHECKED | SIGF_VALID;
}
else if( rc == G10ERR_NO_PUBKEY ) {
- log_info(_("key %08lX.%lu, uid %02X%02X: "
- "weird: no public key for signature %08lX\n"),
+ log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: "
+ "weird: no public key\n"),
(ulong)keyid[1], lid, uidhash[18],
uidhash[19], (ulong)sig->keyid[1] );
rec.r.sig.sig[i].flag = SIGF_NOPUBKEY;
}
else {
- log_info(_("key %08lX.%lu, uid %02X%02X: "
+ log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: "
"invalid signature: %s\n"),
- (ulong)keyid[1], lid,
- uidhash[18], uidhash[19], g10_errstr(rc));
+ (ulong)keyid[1], lid, uidhash[18],
+ uidhash[19], (ulong)sig->keyid[1],
+ g10_errstr(rc));
rec.r.sig.sig[i].flag = SIGF_CHECKED;
}
- write_record( &rec );
- goto ready;
+ rec.dirty = 1;
}
else if( tmp.rectype == RECTYPE_SDIR ) {
/* must check that it is the right one */
@@ -2117,11 +2225,10 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec,
(ulong)keyid[1], lid,
uidhash[18], uidhash[19], tmp.recnum );
rec.r.sig.sig[i].flag = SIGF_NOPUBKEY;
- write_record( &rec );
+ rec.dirty = 1;
/* fixme: should we verify that the record is
* in the hintlist? - This case here should anyway
* never occur */
- goto ready;
}
}
else {
@@ -2130,48 +2237,52 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec,
die_invalid_db();
}
}
+ if( found_delrec && delrec.recnum ) {
+ delrec = rec;
+ found_delrec = 0; /* we onyl want the first one */
+ }
+ if( rec.dirty )
+ write_record( &rec );
}
+
+ if( found_sig )
+ goto leave;
+
/* at this point, we have verified, that the signature is not in
* our list of signatures. Add a new record with that signature
* and if the public key is there, check the signature. */
- rc = get_pubkey( pk, sig->keyid );
- if( !rc ) {
- /* check that we already have the record in the trustdb;
- * if not we should not check the signature, because we do
- * not have the lid of the signature and therefore can't add
- * a signature record. We will fake a no_pubkey error, so
- * that this is handled, like we do not have the publick key at
- * at all. The alternative would be a recursive insert of
- * records - but that is not good.
- */
- rc = query_trust_record( pk );
- if( rc == -1 )
- rc = G10ERR_NO_PUBKEY;
- else
- rc = check_key_signature( keyblock, signode, NULL );
- }
+
+ if( !pk_lid )
+ rc = G10ERR_NO_PUBKEY;
+ else
+ rc = check_key_signature( keyblock, signode, NULL );
+
if( !rc ) { /* valid signature */
- newlid = pk->local_id; /* this is the pk of the signature */
+ if( opt.verbose )
+ log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: "
+ "good signature (2)\n"),
+ (ulong)keyid[1], lid, uidhash[18],
+ uidhash[19], (ulong)sig->keyid[1] );
+ newlid = pk_lid; /* this is the pk of the signature */
if( !newlid )
BUG();
newflag = SIGF_CHECKED | SIGF_VALID;
}
else if( rc == G10ERR_NO_PUBKEY ) {
- if( opt.verbose )
- log_info(_("key %08lX.%lu, uid %02X%02X: "
- "no public key for signature %08lX\n"),
+ if( opt.verbose > 1 )
+ log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: "
+ "no public key\n"),
(ulong)keyid[1], lid, uidhash[18],
uidhash[19], (ulong)sig->keyid[1] );
newflag = SIGF_NOPUBKEY;
}
else {
- log_info(_("key %08lX.%lu, uid %02X%02X: "
+ log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: "
"invalid signature: %s\n"),
(ulong)keyid[1], lid, uidhash[18], uidhash[19],
- g10_errstr(rc));
+ (ulong)sig->keyid[1], g10_errstr(rc));
newflag = SIGF_CHECKED;
}
- free_public_key( pk );
if( !newlid ) { /* create a shadow dir record */
TRUSTREC sdir, hlst, tmphlst;
@@ -2250,16 +2361,17 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec,
tmp.r.sig.sig[0].flag= newflag;
write_record( &tmp );
urec.r.uid.siglist = tmp.recnum;
- write_record( &urec );
+ urec.dirty = 1;
}
- ready:
- ;
}
else {
/* handle other sig classes */
}
+ leave:
+ if( urec.dirty )
+ write_record( &urec );
}
@@ -2389,7 +2501,7 @@ update_trust_record( KBNODE keyblock )
else if( drec.dirty ) {
drec.r.dir.dirflags &= ~DIRF_CHECKED; /* reset flag */
write_record( &drec );
- /* fixme: commit_transaction */
+ do_sync();
}
rel_recno_list( &recno_list );
return rc;
@@ -2437,9 +2549,17 @@ insert_trust_record( PKT_public_key *pk )
/* check that we used the primary key (we are little bit paranoid) */
{ PKT_public_key *a_pk;
+ u32 akid[2], bkid[2];
+
node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
a_pk = node->pkt->pkt.public_key;
- if( cmp_public_keys( a_pk, pk ) ) {
+
+ /* we can't use cmp_public_keys here because some parts (expiredate)
+ * might not be set in pk <--- but why (fixme) */
+ keyid_from_pk( a_pk, akid );
+ keyid_from_pk( pk, bkid );
+
+ if( akid[0] != bkid[0] || akid[1] != bkid[1] ) {
log_error("did not use primary key for insert_trust_record()\n");
rc = G10ERR_GENERAL;
goto leave;
@@ -2492,6 +2612,7 @@ insert_trust_record( PKT_public_key *pk )
if( rc && hintlist )
; /* fixme: the hintlist is not anymore anchored */
release_kbnode( keyblock );
+ do_sync();
return rc;
}
@@ -2504,6 +2625,7 @@ update_ownertrust( ulong lid, unsigned new_trust )
read_record( lid, &rec, RECTYPE_DIR );
rec.r.dir.ownertrust = new_trust;
write_record( &rec );
+ do_sync();
return 0;
}
diff --git a/g10/trustdb.h b/g10/trustdb.h
index b0f39770f..8cdf50ec1 100644
--- a/g10/trustdb.h
+++ b/g10/trustdb.h
@@ -46,6 +46,7 @@ void list_trust_path( int max_depth, const char *username );
void export_ownertrust(void);
void import_ownertrust(const char *fname);
void check_trustdb( const char *username );
+void update_trustdb( void );
int init_trustdb( int level, const char *dbname );
int check_trust( PKT_public_key *pk, unsigned *r_trustlevel );
int query_trust_info( PKT_public_key *pk );