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

last local commit

This commit is contained in:
Werner Koch 1998-10-16 16:00:17 +00:00
parent 8477407e79
commit e81e0970f7
49 changed files with 1253 additions and 545 deletions

View file

@ -1,6 +1,35 @@
Fri Oct 16 10:24:47 1998 Werner Koch (wk@isil.d.shuttle.de)
* 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 (wk@isil.d.shuttle.de)
* 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.

View file

@ -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();

View file

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

View file

@ -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 */

View file

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

View file

@ -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;

View file

@ -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;

View file

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

View file

@ -37,16 +37,15 @@
#define MAX_PK_CACHE_ENTRIES 50
#define MAX_UID_CACHE_ENTRIES 50
typedef struct enum_seckey_context {
int eof;
STRLIST sl;
IOBUF iobuf;
} enum_seckey_context_t;
static struct {
int any;
int okay_count;
int nokey_count;
int error_count;
} lkup_stats[21];
static STRLIST keyrings;
static STRLIST secret_keyrings;
#if MAX_UNK_CACHE_ENTRIES
typedef struct keyid_list {
@ -89,92 +88,24 @@ 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 )
static void
print_stats()
{
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);
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( &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 )
{
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);
}
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] ) {

View file

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

View file

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

View file

@ -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 )

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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 */

View file

@ -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;

View file

@ -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 {
@ -96,30 +97,76 @@ check_pos( KBPOS *kbpos )
****************** public functions ****************************
****************************************************************/
/****************
* 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;

View file

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

View file

@ -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 */

View file

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

View file

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

View file

@ -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;

View file

@ -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,46 +1335,51 @@ 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 );
}
/****************
* Get the trustlevel for this PK.
@ -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;
}

View file

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