mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
edit-key is now complete
This commit is contained in:
parent
1a80de41a5
commit
5ae562b41d
48 changed files with 2044 additions and 984 deletions
|
@ -1,3 +1,26 @@
|
|||
Wed Jul 29 12:53:03 1998 Werner Koch (wk@(none))
|
||||
|
||||
* free-packet.c (copy_signature): New.
|
||||
|
||||
* keygen.c (generate_subkeypair): rewritten
|
||||
* g10.c (aKeyadd): Removed option --add-key
|
||||
|
||||
Mon Jul 27 10:37:28 1998 Werner Koch (wk@(none))
|
||||
|
||||
* seckey-cert.c (do_check): Additional check on cipher blocksize.
|
||||
(protect_secret_key): Ditto.
|
||||
* encr-data.c: Support for other blocksizes.
|
||||
* cipher.c (write_header): Ditto.
|
||||
|
||||
Fri Jul 24 16:47:59 1998 Werner Koch (wk@(none))
|
||||
|
||||
* kbnode.c (insert_kbnode): Changed semantics and all callers.
|
||||
* keyedit.c : More or less a complete rewrite
|
||||
|
||||
Wed Jul 22 17:10:04 1998 Werner Koch (wk@(none))
|
||||
|
||||
* build-packet.c (write_sign_packet_header): New.
|
||||
|
||||
Tue Jul 21 14:37:09 1998 Werner Koch (wk@(none))
|
||||
|
||||
* import.c (import_one): Now creates a trustdb record.
|
||||
|
|
|
@ -48,7 +48,6 @@ common_source = \
|
|||
status.c \
|
||||
status.h \
|
||||
sign.c \
|
||||
keyedit.c \
|
||||
plaintext.c \
|
||||
encr-data.c \
|
||||
encode.c \
|
||||
|
@ -61,6 +60,7 @@ gpg_SOURCES = g10.c \
|
|||
$(common_source) \
|
||||
verify.c \
|
||||
decrypt.c \
|
||||
keyedit.c \
|
||||
keygen.c
|
||||
|
||||
|
||||
|
|
|
@ -57,3 +57,9 @@ compress-sigs
|
|||
# Normally, compressing of signatures does not make sense; so this
|
||||
# is disabled for detached signatures unless this option is used.
|
||||
|
||||
|
||||
emulate-pgp-sign-bug
|
||||
# PGP 2.x can only cope with 2 byte length headers of the
|
||||
# signature packets, this option forces.
|
||||
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ static int calc_header_length( u32 len );
|
|||
static int write_16(IOBUF inp, u16 a);
|
||||
static int write_32(IOBUF inp, u32 a);
|
||||
static int write_header( IOBUF out, int ctb, u32 len );
|
||||
static int write_sign_packet_header( IOBUF out, int ctb, u32 len );
|
||||
static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode );
|
||||
static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen );
|
||||
static int write_version( IOBUF out, int ctb );
|
||||
|
@ -669,7 +670,10 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
|
|||
for(i=0; i < n; i++ )
|
||||
mpi_write(a, sig->data[i] );
|
||||
|
||||
write_header(out, ctb, iobuf_get_temp_length(a) );
|
||||
if( is_RSA(sig->pubkey_algo) && sig->version < 4 )
|
||||
write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) );
|
||||
else
|
||||
write_header(out, ctb, iobuf_get_temp_length(a) );
|
||||
if( iobuf_write_temp( out, a ) )
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
|
||||
|
@ -747,6 +751,18 @@ write_header( IOBUF out, int ctb, u32 len )
|
|||
return write_header2( out, ctb, len, 0, 1 );
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
write_sign_packet_header( IOBUF out, int ctb, u32 len )
|
||||
{
|
||||
/* work around a bug in the pgp read function for signature packets,
|
||||
* which are not correctly coded and silently assume at some
|
||||
* point 2 byte length headers.*/
|
||||
iobuf_put(out, 0x89 );
|
||||
iobuf_put(out, len >> 8 );
|
||||
return iobuf_put(out, len ) == -1 ? -1:0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* if HDRLEN is > 0, try to build a header of this length.
|
||||
* we need this, so that we can hash packets without reading them again.
|
||||
|
|
16
g10/cipher.c
16
g10/cipher.c
|
@ -42,7 +42,8 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
|
|||
{
|
||||
PACKET pkt;
|
||||
PKT_encrypted ed;
|
||||
byte temp[10];
|
||||
byte temp[18];
|
||||
unsigned blocksize;
|
||||
|
||||
memset( &ed, 0, sizeof ed );
|
||||
ed.len = cfx->datalen;
|
||||
|
@ -52,15 +53,18 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
|
|||
pkt.pkt.encrypted = &ed;
|
||||
if( build_packet( a, &pkt ))
|
||||
log_bug("build_packet(ENCR_DATA) failed\n");
|
||||
randomize_buffer( temp, 8, 1 );
|
||||
temp[8] = temp[6];
|
||||
temp[9] = temp[7];
|
||||
blocksize = cipher_get_blocksize( cfx->dek->algo );
|
||||
if( blocksize < 8 || blocksize > 16 )
|
||||
log_fatal("unsupported blocksize %u\n", blocksize );
|
||||
randomize_buffer( temp, blocksize, 1 );
|
||||
temp[blocksize] = temp[blocksize-2];
|
||||
temp[blocksize+1] = temp[blocksize-1];
|
||||
cfx->cipher_hd = cipher_open( cfx->dek->algo, CIPHER_MODE_AUTO_CFB, 1 );
|
||||
cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen );
|
||||
cipher_setiv( cfx->cipher_hd, NULL );
|
||||
cipher_encrypt( cfx->cipher_hd, temp, temp, 10);
|
||||
cipher_encrypt( cfx->cipher_hd, temp, temp, blocksize+2);
|
||||
cipher_sync( cfx->cipher_hd );
|
||||
iobuf_write(a, temp, 10);
|
||||
iobuf_write(a, temp, blocksize+2);
|
||||
cfx->header=1;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,8 @@ decrypt_data( PKT_encrypted *ed, DEK *dek )
|
|||
decode_filter_ctx_t dfx;
|
||||
byte *p;
|
||||
int rc, c, i;
|
||||
byte temp[16];
|
||||
byte temp[32];
|
||||
unsigned blocksize;
|
||||
|
||||
if( opt.verbose ) {
|
||||
const char *s = cipher_algo_to_string( dek->algo );
|
||||
|
@ -60,7 +61,10 @@ decrypt_data( PKT_encrypted *ed, DEK *dek )
|
|||
}
|
||||
if( (rc=check_cipher_algo(dek->algo)) )
|
||||
return rc;
|
||||
if( ed->len && ed->len < 10 )
|
||||
blocksize = cipher_get_blocksize(dek->algo);
|
||||
if( !blocksize || blocksize > 16 )
|
||||
log_fatal("unsupported blocksize %u\n", blocksize );
|
||||
if( ed->len && ed->len < (blocksize+2) )
|
||||
log_bug("Nanu\n"); /* oops: found a bug */
|
||||
|
||||
dfx.cipher_hd = cipher_open( dek->algo, CIPHER_MODE_AUTO_CFB, 1 );
|
||||
|
@ -70,20 +74,20 @@ decrypt_data( PKT_encrypted *ed, DEK *dek )
|
|||
if( ed->len ) {
|
||||
iobuf_set_limit( ed->buf, ed->len );
|
||||
|
||||
for(i=0; i < 10 && ed->len; i++, ed->len-- )
|
||||
for(i=0; i < (blocksize+2) && ed->len; i++, ed->len-- )
|
||||
temp[i] = iobuf_get(ed->buf);
|
||||
}
|
||||
else {
|
||||
for(i=0; i < 10; i++ )
|
||||
for(i=0; i < (blocksize+2); i++ )
|
||||
if( (c=iobuf_get(ed->buf)) == -1 )
|
||||
break;
|
||||
else
|
||||
temp[i] = c;
|
||||
}
|
||||
cipher_decrypt( dfx.cipher_hd, temp, temp, 10);
|
||||
cipher_decrypt( dfx.cipher_hd, temp, temp, blocksize+2);
|
||||
cipher_sync( dfx.cipher_hd );
|
||||
p = temp;
|
||||
if( p[6] != p[8] || p[7] != p[9] ) {
|
||||
if( p[blocksize-2] != p[blocksize] || p[blocksize-1] != p[blocksize+1] ) {
|
||||
cipher_close(dfx.cipher_hd);
|
||||
return G10ERR_BAD_KEY;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ void
|
|||
free_seckey_enc( PKT_signature *sig )
|
||||
{
|
||||
int n, i;
|
||||
n = pubkey_get_nenc( sig->pubkey_algo );
|
||||
n = pubkey_get_nsig( sig->pubkey_algo );
|
||||
if( !n ) {
|
||||
m_free(sig->data[0]);
|
||||
sig->data[0] = NULL;
|
||||
|
@ -107,6 +107,20 @@ cp_fake_data( MPI a )
|
|||
return d;
|
||||
}
|
||||
|
||||
static void *
|
||||
cp_data_block( byte *s )
|
||||
{
|
||||
byte *d;
|
||||
u16 len;
|
||||
|
||||
if( !s )
|
||||
return NULL;
|
||||
len = (s[0] << 8) | s[1];
|
||||
d = m_alloc( len+2 );
|
||||
memcpy(d, s, len+2);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
PKT_public_key *
|
||||
copy_public_key( PKT_public_key *d, PKT_public_key *s )
|
||||
|
@ -126,6 +140,39 @@ copy_public_key( PKT_public_key *d, PKT_public_key *s )
|
|||
return d;
|
||||
}
|
||||
|
||||
|
||||
PKT_signature *
|
||||
copy_signature( PKT_signature *d, PKT_signature *s )
|
||||
{
|
||||
int n, i;
|
||||
|
||||
if( !d )
|
||||
d = m_alloc(sizeof *d);
|
||||
memcpy( d, s, sizeof *d );
|
||||
n = pubkey_get_nsig( s->pubkey_algo );
|
||||
if( !n )
|
||||
d->data[0] = cp_fake_data(s->data[0]);
|
||||
else {
|
||||
for(i=0; i < n; i++ )
|
||||
d->data[i] = mpi_copy( s->data[i] );
|
||||
}
|
||||
d->hashed_data = cp_data_block(s->hashed_data);
|
||||
d->unhashed_data = cp_data_block(s->unhashed_data);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
PKT_user_id *
|
||||
copy_user_id( PKT_user_id *d, PKT_user_id *s )
|
||||
{
|
||||
if( !d )
|
||||
d = m_alloc(sizeof *d + s->len - 1 );
|
||||
memcpy( d, s, sizeof *d + s->len - 1 );
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
release_secret_key_parts( PKT_secret_key *sk )
|
||||
{
|
||||
|
|
69
g10/g10.c
69
g10/g10.c
|
@ -68,11 +68,8 @@ static ARGPARSE_OPTS opts[] = {
|
|||
{ 558, "list-secret-keys", 256, N_("list secret keys")},
|
||||
#ifdef IS_G10
|
||||
{ 503, "gen-key", 256, N_("generate a new key pair")},
|
||||
{ 554, "add-key", 256, N_("add a subkey to a key pair")},
|
||||
{ 506, "sign-key" ,256, N_("make a signature on a key in the keyring")},
|
||||
{ 505, "delete-key",256, N_("remove key from the public keyring")},
|
||||
{ 524, "edit-key" ,256, N_("edit a key signature")},
|
||||
{ 525, "change-passphrase", 256, N_("change the passphrase of your secret keyring")},
|
||||
{ 524, "edit-key" ,256, N_("sign or edit a key")},
|
||||
{ 542, "gen-revoke",256, N_("generate a revocation certificate")},
|
||||
#endif
|
||||
{ 537, "export" , 256, N_("export keys") },
|
||||
|
@ -81,7 +78,8 @@ static ARGPARSE_OPTS opts[] = {
|
|||
{ 530, "import", 256 , N_("import/merge keys")},
|
||||
{ 521, "list-packets",256,N_("list only the sequence of packets")},
|
||||
#ifdef IS_G10MAINT
|
||||
{ 564, "list-ownertrust", 256, N_("list the ownertrust values")},
|
||||
{ 564, "export-ownertrust", 256, N_("export the ownertrust values")},
|
||||
{ 525, "import-ownertrust", 256 , N_("import ownertrust values")},
|
||||
{ 567, "check-trustdb",0 , N_("|[NAMES]|check the trust database")},
|
||||
{ 546, "dearmor", 256, N_("De-Armor a file or stdin") },
|
||||
{ 547, "enarmor", 256, N_("En-Armor a file or stdin") },
|
||||
|
@ -153,6 +151,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||
{ 504, "delete-secret-key",0, "@" },
|
||||
{ 524, "edit-sig" ,0, "@"}, /* alias for edit-key */
|
||||
{ 523, "passphrase-fd",1, "@" },
|
||||
{ 506, "sign-key" ,256, "@" }, /* alias for edit-key */
|
||||
#endif
|
||||
{ 532, "quick-random", 0, "@"},
|
||||
{ 526, "no-verbose", 0, "@"},
|
||||
|
@ -173,18 +172,18 @@ static ARGPARSE_OPTS opts[] = {
|
|||
{ 566, "compress-sigs",0, "@"},
|
||||
{ 559, "always-trust", 0, "@"},
|
||||
{ 562, "emulate-checksum-bug", 0, "@"},
|
||||
|
||||
/*554 is unused */
|
||||
{0} };
|
||||
|
||||
|
||||
enum cmd_values { aNull = 0,
|
||||
aSym, aStore, aEncr, aKeygen, aSign, aSignEncr,
|
||||
aSignKey, aClearsign, aListPackets, aEditKey, aDeleteKey, aDeleteSecretKey,
|
||||
aKMode, aKModeC, aChangePass, aImport, aVerify, aDecrypt, aListKeys,
|
||||
aListSigs, aKeyadd, aListSecretKeys,
|
||||
aExport, aExportSecret,
|
||||
aKMode, aKModeC, aImport, aVerify, aDecrypt, aListKeys,
|
||||
aListSigs, aListSecretKeys, aExport, aExportSecret,
|
||||
aCheckKeys, aGenRevoke, aPrimegen, aPrintMD, aPrintMDs,
|
||||
aCheckTrustDB, aListTrustDB, aListTrustPath, aListOwnerTrust,
|
||||
aCheckTrustDB, aListTrustDB, aListTrustPath,
|
||||
aExportOwnerTrust, aImportOwnerTrust,
|
||||
aDeArmor, aEnArmor, aGenRandom,
|
||||
aTest };
|
||||
|
||||
|
@ -521,7 +520,6 @@ main( int argc, char **argv )
|
|||
case 507: set_cmd( &cmd, aStore); break;
|
||||
case 523: set_passphrase_fd( pargs.r.ret_int ); break;
|
||||
case 524: set_cmd( &cmd, aEditKey); break;
|
||||
case 525: set_cmd( &cmd, aChangePass); break;
|
||||
case 527: def_cipher_string = m_strdup(pargs.r.ret_str); break;
|
||||
case 529: def_digest_string = m_strdup(pargs.r.ret_str); break;
|
||||
case 539: set_cmd( &cmd, aClearsign); break;
|
||||
|
@ -548,7 +546,8 @@ main( int argc, char **argv )
|
|||
case 546: set_cmd( &cmd, aDeArmor); break;
|
||||
case 547: set_cmd( &cmd, aEnArmor); break;
|
||||
case 555: set_cmd( &cmd, aPrintMD); break;
|
||||
case 564: set_cmd( &cmd, aListOwnerTrust); break;
|
||||
case 564: set_cmd( &cmd, aExportOwnerTrust); break;
|
||||
case 525: set_cmd( &cmd, aImportOwnerTrust); break;
|
||||
#endif /* IS_G10MAINT */
|
||||
|
||||
case 'o': opt.outfile = pargs.r.ret_str; break;
|
||||
|
@ -564,7 +563,7 @@ main( int argc, char **argv )
|
|||
case 510: opt.debug |= pargs.r.ret_ulong; break;
|
||||
case 511: opt.debug = ~0; break;
|
||||
case 512: set_status_fd( pargs.r.ret_int ); break;
|
||||
case 515: opt.fingerprint = 1; break;
|
||||
case 515: opt.fingerprint++; break;
|
||||
case 517: append_to_strlist( &sec_nrings, pargs.r.ret_str); break;
|
||||
case 518:
|
||||
/* config files may not be nested (silently ignore them) */
|
||||
|
@ -595,17 +594,17 @@ main( int argc, char **argv )
|
|||
case 551: set_cmd( &cmd, aListKeys); break;
|
||||
case 552: set_cmd( &cmd, aListSigs); break;
|
||||
case 553: opt.skip_verify=1; break;
|
||||
case 554: set_cmd( &cmd, aKeyadd); break;
|
||||
case 556: opt.def_compress_algo = pargs.r.ret_int; break;
|
||||
case 557: opt.compress_keys = 1; break;
|
||||
case 558: set_cmd( &cmd, aListSecretKeys); break;
|
||||
case 559: opt.always_trust = 1; break;
|
||||
case 560: register_cipher_extension(pargs.r.ret_str); break;
|
||||
case 561: opt.rfc1991 = 1; break;
|
||||
case 562: opt.emulate_bugs |= 1; break;
|
||||
case 561: opt.rfc1991 = 1; opt.no_comment = 1; break;
|
||||
case 562: opt.emulate_bugs |= EMUBUG_GPGCHKSUM; break;
|
||||
case 563: set_cmd( &cmd, aExportSecret); break;
|
||||
case 565: opt.do_not_export_rsa = 1; break;
|
||||
case 566: opt.compress_sigs = 1; break;
|
||||
case 554:
|
||||
default : errors++; pargs.err = configfp? 1:2; break;
|
||||
}
|
||||
}
|
||||
|
@ -722,7 +721,7 @@ main( int argc, char **argv )
|
|||
if( opt.with_colons ) /* need this to list the trust */
|
||||
rc = init_trustdb(1, trustdb_name );
|
||||
break;
|
||||
case aListOwnerTrust: rc = init_trustdb( 0, trustdb_name ); break;
|
||||
case aExportOwnerTrust: rc = init_trustdb( 0, trustdb_name ); break;
|
||||
case aListTrustDB: rc = init_trustdb( argc? 1:0, trustdb_name ); break;
|
||||
default: rc = init_trustdb(1, trustdb_name ); break;
|
||||
}
|
||||
|
@ -808,19 +807,10 @@ main( int argc, char **argv )
|
|||
|
||||
|
||||
case aSignKey: /* sign the key given as argument */
|
||||
if( argc != 1 )
|
||||
wrong_args(_("--sign-key username"));
|
||||
/* note: fname is the user id! */
|
||||
if( (rc = sign_key(fname, locusr)) )
|
||||
log_error("%s: sign key failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
|
||||
break;
|
||||
|
||||
case aEditKey: /* Edit a key signature */
|
||||
if( argc != 1 )
|
||||
wrong_args(_("--edit-key username"));
|
||||
/* note: fname is the user id! */
|
||||
if( (rc = edit_keysigs(fname)) )
|
||||
log_error("%s: edit signature failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
|
||||
keyedit_menu(fname, locusr );
|
||||
break;
|
||||
|
||||
case aDeleteSecretKey:
|
||||
|
@ -834,14 +824,6 @@ main( int argc, char **argv )
|
|||
log_error("%s: delete key failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
|
||||
break;
|
||||
|
||||
case aChangePass: /* Change the passphrase */
|
||||
if( argc > 1 ) /* no arg: use default, 1 arg use this one */
|
||||
wrong_args(_("--change-passphrase [username]"));
|
||||
/* note: fname is the user id! */
|
||||
if( (rc = change_passphrase(fname)) )
|
||||
log_error("%s: change passphrase failed: %s\n", print_fname_stdin(fname),
|
||||
g10_errstr(rc) );
|
||||
break;
|
||||
#endif /* IS_G10 */
|
||||
|
||||
case aCheckKeys:
|
||||
|
@ -880,11 +862,6 @@ main( int argc, char **argv )
|
|||
wrong_args("--gen-key");
|
||||
generate_keypair();
|
||||
break;
|
||||
case aKeyadd: /* add a subkey (interactive) */
|
||||
if( argc != 1 )
|
||||
wrong_args("--add-key userid");
|
||||
generate_subkeypair(*argv);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case aImport:
|
||||
|
@ -1049,10 +1026,16 @@ main( int argc, char **argv )
|
|||
list_trust_path( atoi(*argv), argv[1] );
|
||||
break;
|
||||
|
||||
case aListOwnerTrust:
|
||||
case aExportOwnerTrust:
|
||||
if( argc )
|
||||
wrong_args("--list-ownertrust");
|
||||
list_ownertrust();
|
||||
wrong_args("--export-ownertrust");
|
||||
export_ownertrust();
|
||||
break;
|
||||
|
||||
case aImportOwnerTrust:
|
||||
if( argc > 1 )
|
||||
wrong_args("--import-ownertrust [file]");
|
||||
import_ownertrust( argc? *argv:NULL );
|
||||
break;
|
||||
|
||||
#endif /* IS_G10MAINT */
|
||||
|
|
|
@ -851,7 +851,7 @@ merge_sigs( KBNODE dst, KBNODE src, int *n_sigs,
|
|||
* We add a clone to the original keyblock, because this
|
||||
* one is released first */
|
||||
n2 = clone_kbnode(n);
|
||||
insert_kbnode( dst, n2, PKT_USER_ID );
|
||||
insert_kbnode( dst, n2, PKT_SIGNATURE );
|
||||
n2->flag |= 1;
|
||||
n->flag |= 1;
|
||||
++*n_sigs;
|
||||
|
|
|
@ -94,7 +94,8 @@ add_kbnode( KBNODE root, KBNODE node )
|
|||
}
|
||||
|
||||
/****************
|
||||
* Insert NODE into the list after root but before a packet with type PKTTYPE
|
||||
* Insert NODE into the list after root but before a packet which is not of
|
||||
* type PKTTYPE
|
||||
* (only if PKTTYPE != 0)
|
||||
*/
|
||||
void
|
||||
|
@ -108,7 +109,7 @@ insert_kbnode( KBNODE root, KBNODE node, int pkttype )
|
|||
KBNODE n1;
|
||||
|
||||
for(n1=root; n1->next; n1 = n1->next)
|
||||
if( pkttype == n1->next->pkt->pkttype ) {
|
||||
if( pkttype != n1->next->pkt->pkttype ) {
|
||||
node->next = n1->next;
|
||||
n1->next = node;
|
||||
return;
|
||||
|
|
|
@ -133,6 +133,8 @@ unsigned nbits_from_sk( PKT_secret_key *sk );
|
|||
const char *datestr_from_pk( PKT_public_key *pk );
|
||||
const char *datestr_from_sk( PKT_secret_key *sk );
|
||||
const char *datestr_from_sig( PKT_signature *sig );
|
||||
const char *expirestr_from_pk( PKT_public_key *pk );
|
||||
const char *expirestr_from_sk( PKT_secret_key *sk );
|
||||
byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf, size_t *ret_len );
|
||||
byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
|
||||
|
||||
|
@ -149,6 +151,7 @@ KBNODE find_kbnode( KBNODE node, int pkttype );
|
|||
KBNODE walk_kbnode( KBNODE root, KBNODE *context, int all );
|
||||
void clear_kbnode_flags( KBNODE n );
|
||||
int commit_kbnode( KBNODE *root );
|
||||
void dump_kbnode( KBNODE node );
|
||||
|
||||
/*-- ringedit.c --*/
|
||||
int add_keyblock_resource( const char *filename, int force, int secret );
|
||||
|
|
1444
g10/keyedit.c
1444
g10/keyedit.c
File diff suppressed because it is too large
Load diff
169
g10/keygen.c
169
g10/keygen.c
|
@ -74,8 +74,8 @@ add_key_expire( PKT_signature *sig, void *opaque )
|
|||
* Add preference to the self signature packet.
|
||||
* This is only called for packets with version > 3.
|
||||
*/
|
||||
static int
|
||||
add_prefs( PKT_signature *sig, void *opaque )
|
||||
int
|
||||
keygen_add_std_prefs( PKT_signature *sig, void *opaque )
|
||||
{
|
||||
byte buf[8];
|
||||
|
||||
|
@ -134,7 +134,7 @@ write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk )
|
|||
|
||||
/* and make the signature */
|
||||
rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0,
|
||||
add_prefs, sk );
|
||||
keygen_add_std_prefs, sk );
|
||||
if( rc ) {
|
||||
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
|
||||
return rc;
|
||||
|
@ -444,25 +444,18 @@ ask_keysize( int algo )
|
|||
else if( nbits > 2048 ) {
|
||||
tty_printf(_("Keysizes larger than 2048 are not suggested because "
|
||||
"computations take REALLY long!\n"));
|
||||
answer = tty_get(_("Are you sure that you want this keysize? "));
|
||||
tty_kill_prompt();
|
||||
if( answer_is_yes(answer) ) {
|
||||
m_free(answer);
|
||||
if( tty_get_answer_is_yes(_(
|
||||
"Are you sure that you want this keysize? ")) ) {
|
||||
tty_printf(_("Okay, but keep in mind that your monitor "
|
||||
"and keyboard radiation is also very vulnerable "
|
||||
"to attacks!\n"));
|
||||
break;
|
||||
}
|
||||
m_free(answer);
|
||||
}
|
||||
else if( nbits > 1536 ) {
|
||||
answer = tty_get(_("Do you really need such a large keysize? "));
|
||||
tty_kill_prompt();
|
||||
if( answer_is_yes(answer) ) {
|
||||
m_free(answer);
|
||||
if( tty_get_answer_is_yes(_(
|
||||
"Do you really need such a large keysize? ")) )
|
||||
break;
|
||||
}
|
||||
m_free(answer);
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
@ -524,10 +517,7 @@ ask_valid_days()
|
|||
add_days_to_timestamp( make_timestamp(), valid_days )));
|
||||
}
|
||||
|
||||
m_free(answer);
|
||||
answer = tty_get(_("Is this correct (y/n)? "));
|
||||
tty_kill_prompt();
|
||||
if( answer_is_yes(answer) )
|
||||
if( tty_get_answer_is_yes(_("Is this correct (y/n)? ")) )
|
||||
break;
|
||||
}
|
||||
m_free(answer);
|
||||
|
@ -549,12 +539,13 @@ has_invalid_email_chars( const char *s )
|
|||
|
||||
|
||||
static char *
|
||||
ask_user_id()
|
||||
ask_user_id( int mode )
|
||||
{
|
||||
char *answer;
|
||||
char *aname, *acomment, *amail, *uid;
|
||||
|
||||
tty_printf( _("\n"
|
||||
if( !mode )
|
||||
tty_printf( _("\n"
|
||||
"You need a User-ID to identify your key; the software constructs the user id\n"
|
||||
"from Real Name, Comment and Email Address in this form:\n"
|
||||
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n\n") );
|
||||
|
@ -630,28 +621,37 @@ ask_user_id()
|
|||
tty_printf(_("You selected this USER-ID:\n \"%s\"\n\n"), uid);
|
||||
/* fixme: add a warning if this user-id already exists */
|
||||
for(;;) {
|
||||
answer = tty_get(_("Edit (N)ame, (C)omment, (E)mail or (O)kay? "));
|
||||
char *ansstr = N_("NnCcEeOoQq");
|
||||
answer = tty_get(_(
|
||||
"Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "));
|
||||
tty_kill_prompt();
|
||||
if( strlen(answer) > 1 )
|
||||
;
|
||||
else if( *answer == 'N' || *answer == 'n' ) {
|
||||
else if( *answer == ansstr[0] || *answer == ansstr[1] ) {
|
||||
m_free(aname); aname = NULL;
|
||||
break;
|
||||
}
|
||||
else if( *answer == 'C' || *answer == 'c' ) {
|
||||
else if( *answer == ansstr[2] || *answer == ansstr[3] ) {
|
||||
m_free(acomment); acomment = NULL;
|
||||
break;
|
||||
}
|
||||
else if( *answer == 'E' || *answer == 'e' ) {
|
||||
else if( *answer == ansstr[4] || *answer == ansstr[5] ) {
|
||||
m_free(amail); amail = NULL;
|
||||
break;
|
||||
}
|
||||
else if( *answer == 'O' || *answer == 'o' ) {
|
||||
else if( *answer == ansstr[6] || *answer == ansstr[7] ) {
|
||||
m_free(aname); aname = NULL;
|
||||
m_free(acomment); acomment = NULL;
|
||||
m_free(amail); amail = NULL;
|
||||
break;
|
||||
}
|
||||
else if( *answer == ansstr[8] || *answer == ansstr[9] ) {
|
||||
m_free(aname); aname = NULL;
|
||||
m_free(acomment); acomment = NULL;
|
||||
m_free(amail); amail = NULL;
|
||||
m_free(uid); uid = NULL;
|
||||
break;
|
||||
}
|
||||
m_free(answer);
|
||||
}
|
||||
m_free(answer);
|
||||
|
@ -685,7 +685,7 @@ ask_passphrase( STRING2KEY **ret_s2k )
|
|||
tty_printf(_(
|
||||
"You don't want a passphrase - this is probably a *bad* idea!\n"
|
||||
"I will do it anyway. You can change your passphrase at any time,\n"
|
||||
"using this program with the option \"--change-passphrase\".\n\n"));
|
||||
"using this program with the option \"--edit-key\".\n\n"));
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
@ -728,6 +728,27 @@ do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root,
|
|||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Generate a new user id packet, or return NULL if cancelled
|
||||
*/
|
||||
PKT_user_id *
|
||||
generate_user_id()
|
||||
{
|
||||
PKT_user_id *uid;
|
||||
char *p;
|
||||
size_t n;
|
||||
|
||||
p = ask_user_id( 1 );
|
||||
if( !p )
|
||||
return NULL;
|
||||
n = strlen(p);
|
||||
uid = m_alloc( sizeof *uid + n - 1 );
|
||||
uid->len = n;
|
||||
strcpy(uid->name, p);
|
||||
return uid;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Generate a keypair
|
||||
*/
|
||||
|
@ -762,7 +783,11 @@ generate_keypair()
|
|||
}
|
||||
nbits = ask_keysize( algo );
|
||||
ndays = ask_valid_days();
|
||||
uid = ask_user_id();
|
||||
uid = ask_user_id(0);
|
||||
if( !uid ) {
|
||||
log_error(_("Key generation cancelled.\n"));
|
||||
return;
|
||||
}
|
||||
dek = ask_passphrase( &s2k );
|
||||
|
||||
|
||||
|
@ -879,88 +904,29 @@ generate_keypair()
|
|||
|
||||
/****************
|
||||
* add a new subkey to an existing key.
|
||||
* Returns true if a new key has been generated and put into the keyblocks.
|
||||
*/
|
||||
void
|
||||
generate_subkeypair( const char *username )
|
||||
int
|
||||
generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
|
||||
{
|
||||
int rc=0;
|
||||
KBPOS pub_kbpos, sec_kbpos;
|
||||
KBNODE pub_keyblock = NULL;
|
||||
KBNODE sec_keyblock = NULL;
|
||||
int okay=0, rc=0;
|
||||
KBNODE node;
|
||||
PKT_secret_key *sk = NULL; /* this is the primary sk */
|
||||
u32 keyid[2];
|
||||
int v4, algo, ndays;
|
||||
unsigned nbits;
|
||||
char *passphrase = NULL;
|
||||
DEK *dek = NULL;
|
||||
STRING2KEY *s2k = NULL;
|
||||
|
||||
if( opt.batch || opt.answer_yes || opt.answer_no ) {
|
||||
log_error(_("Key generation can only be used in interactive mode\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* search the userid */
|
||||
rc = find_secret_keyblock_byname( &sec_kbpos, username );
|
||||
if( rc ) {
|
||||
log_error("user '%s' not found\n", username );
|
||||
goto leave;
|
||||
}
|
||||
rc = read_keyblock( &sec_kbpos, &sec_keyblock );
|
||||
if( rc ) {
|
||||
log_error("error reading the secret key: %s\n", g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
/* and the public key */
|
||||
rc = find_keyblock_byname( &pub_kbpos, username );
|
||||
if( rc ) {
|
||||
log_error("user '%s' not found in public ring\n", username );
|
||||
goto leave;
|
||||
}
|
||||
rc = read_keyblock( &pub_kbpos, &pub_keyblock );
|
||||
if( rc ) {
|
||||
log_error("error reading the public key: %s\n", g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* break out the primary key */
|
||||
/* break out the primary secret key */
|
||||
node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
|
||||
if( !node ) {
|
||||
log_error("Oops; secret key not found anymore!\n");
|
||||
rc = G10ERR_GENERAL;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* make a copy of the sk to keep the protected one in the keyblock */
|
||||
sk = copy_secret_key( NULL, node->pkt->pkt.secret_key );
|
||||
keyid_from_sk( sk, keyid );
|
||||
/* display primary and all secondary keys */
|
||||
tty_printf("sec %4u%c/%08lX %s ",
|
||||
nbits_from_sk( sk ),
|
||||
pubkey_letter( sk->pubkey_algo ),
|
||||
keyid[1], datestr_from_sk(sk) );
|
||||
{
|
||||
size_t n;
|
||||
char *p = get_user_id( keyid, &n );
|
||||
tty_print_string( p, n );
|
||||
m_free(p);
|
||||
tty_printf("\n");
|
||||
}
|
||||
for(node=sec_keyblock; node; node = node->next ) {
|
||||
if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
|
||||
PKT_secret_key *subsk = node->pkt->pkt.secret_key;
|
||||
keyid_from_sk( subsk, keyid );
|
||||
tty_printf("sub %4u%c/%08lX %s\n",
|
||||
nbits_from_sk( subsk ),
|
||||
pubkey_letter( subsk->pubkey_algo ),
|
||||
keyid[1], datestr_from_sk(subsk) );
|
||||
}
|
||||
}
|
||||
tty_printf("\n");
|
||||
|
||||
|
||||
|
||||
/* unprotect to get the passphrase */
|
||||
switch( is_secret_key_protected( sk ) ) {
|
||||
case -1:
|
||||
|
@ -984,6 +950,8 @@ generate_subkeypair( const char *username )
|
|||
assert(algo);
|
||||
nbits = ask_keysize( algo );
|
||||
ndays = ask_valid_days();
|
||||
if( !tty_get_answer_is_yes( _("Really create? ") ) )
|
||||
goto leave;
|
||||
|
||||
if( passphrase ) {
|
||||
s2k = m_alloc_secure( sizeof *s2k );
|
||||
|
@ -999,31 +967,18 @@ generate_subkeypair( const char *username )
|
|||
rc = write_keybinding(pub_keyblock, pub_keyblock, sk);
|
||||
if( !rc )
|
||||
rc = write_keybinding(sec_keyblock, pub_keyblock, sk);
|
||||
/* write back */
|
||||
if( !rc ) {
|
||||
rc = update_keyblock( &pub_kbpos, pub_keyblock );
|
||||
if( rc )
|
||||
log_error("update_public_keyblock failed\n" );
|
||||
}
|
||||
if( !rc ) {
|
||||
rc = update_keyblock( &sec_kbpos, sec_keyblock );
|
||||
if( rc )
|
||||
log_error("update_secret_keyblock failed\n" );
|
||||
}
|
||||
if( !rc )
|
||||
tty_printf(_("public and secret subkey created.\n") );
|
||||
|
||||
okay = 1;
|
||||
|
||||
leave:
|
||||
if( rc )
|
||||
tty_printf(_("Key generation failed: %s\n"), g10_errstr(rc) );
|
||||
log_error(_("Key generation failed: %s\n"), g10_errstr(rc) );
|
||||
m_free( passphrase );
|
||||
m_free( dek );
|
||||
m_free( s2k );
|
||||
if( sk ) /* release the copy of the (now unprotected) secret key */
|
||||
free_secret_key(sk);
|
||||
release_kbnode( sec_keyblock );
|
||||
release_kbnode( pub_keyblock );
|
||||
set_next_passphrase( NULL );
|
||||
return okay;
|
||||
}
|
||||
|
||||
|
|
31
g10/keyid.c
31
g10/keyid.c
|
@ -296,6 +296,37 @@ datestr_from_sig( PKT_signature *sig )
|
|||
}
|
||||
|
||||
|
||||
const char *
|
||||
expirestr_from_pk( PKT_public_key *pk )
|
||||
{
|
||||
static char buffer[11+5];
|
||||
struct tm *tp;
|
||||
time_t atime;
|
||||
|
||||
if( !pk->valid_days )
|
||||
return "never ";
|
||||
atime = add_days_to_timestamp( pk->timestamp, pk->valid_days );
|
||||
tp = gmtime( &atime );
|
||||
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char *
|
||||
expirestr_from_sk( PKT_secret_key *sk )
|
||||
{
|
||||
static char buffer[11+5];
|
||||
struct tm *tp;
|
||||
time_t atime;
|
||||
|
||||
if( !sk->valid_days )
|
||||
return "never ";
|
||||
atime = add_days_to_timestamp( sk->timestamp, sk->valid_days );
|
||||
tp = gmtime( &atime );
|
||||
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
/**************** .
|
||||
* Return a byte array with the fingerprint for the given PK/SK
|
||||
* The length of the array is returned in ret_len. Caller must free
|
||||
|
|
|
@ -202,6 +202,8 @@ list_one( const char *name, int secret )
|
|||
any = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
keyid_from_pk( pk2, keyid2 );
|
||||
if( opt.with_colons ) {
|
||||
printf("sub:%c:%u:%d:%08lX%08lX:%s:%u:",
|
||||
|
@ -224,6 +226,8 @@ list_one( const char *name, int secret )
|
|||
pubkey_letter( pk2->pubkey_algo ),
|
||||
(ulong)keyid2[1],
|
||||
datestr_from_pk( pk2 ) );
|
||||
if( opt.fingerprint > 1 )
|
||||
fingerprint( pk2, NULL );
|
||||
}
|
||||
else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
|
||||
u32 keyid2[2];
|
||||
|
@ -251,6 +255,9 @@ list_one( const char *name, int secret )
|
|||
pubkey_letter( sk2->pubkey_algo ),
|
||||
(ulong)keyid2[1],
|
||||
datestr_from_sk( sk2 ) );
|
||||
if( opt.fingerprint > 1 )
|
||||
fingerprint( NULL, sk2 );
|
||||
|
||||
}
|
||||
else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) {
|
||||
PKT_signature *sig = node->pkt->pkt.signature;
|
||||
|
|
|
@ -72,14 +72,13 @@ int clearsign_file( const char *fname, STRLIST locusr, const char *outfile );
|
|||
int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig );
|
||||
|
||||
/*-- keyedit.c --*/
|
||||
int sign_key( const char *username, STRLIST locusr );
|
||||
int edit_keysigs( const char *username );
|
||||
int delete_key( const char *username, int secure );
|
||||
int change_passphrase( const char *username );
|
||||
void keyedit_menu( const char *username, STRLIST locusr );
|
||||
|
||||
/*-- keygen.c --*/
|
||||
void generate_keypair(void);
|
||||
void generate_subkeypair(const char *userid);
|
||||
int keygen_add_std_prefs( PKT_signature *sig, void *opaque );
|
||||
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
||||
|
||||
/*-- openfile.c --*/
|
||||
int overwrite_filep( const char *fname );
|
||||
|
|
|
@ -520,6 +520,8 @@ list_node( CTX c, KBNODE node )
|
|||
}
|
||||
if( !any )
|
||||
putchar('\n');
|
||||
if( !mainkey && opt.fingerprint > 1 )
|
||||
print_fingerprint( pk, NULL );
|
||||
}
|
||||
else if( (mainkey = (node->pkt->pkttype == PKT_SECRET_KEY) )
|
||||
|| node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
|
||||
|
@ -583,6 +585,8 @@ list_node( CTX c, KBNODE node )
|
|||
}
|
||||
if( !any )
|
||||
putchar('\n');
|
||||
if( !mainkey && opt.fingerprint > 1 )
|
||||
print_fingerprint( NULL, sk );
|
||||
}
|
||||
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
|
||||
PKT_signature *sig = node->pkt->pkt.signature;
|
||||
|
|
|
@ -98,7 +98,7 @@ checksum_u16( unsigned n )
|
|||
u16 a;
|
||||
|
||||
a = (n >> 8) & 0xff;
|
||||
if( opt.emulate_bugs & 1 ) {
|
||||
if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) {
|
||||
a |= n & 0xff;
|
||||
log_debug("csum_u16 emulated for n=%u\n", n);
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ checksum_mpi( MPI a )
|
|||
* this stored value if it is still available.
|
||||
*/
|
||||
|
||||
if( opt.emulate_bugs & 1 )
|
||||
if( opt.emulate_bugs & EMUBUG_GPGCHKSUM )
|
||||
nbits = 0;
|
||||
else
|
||||
nbits = mpi_get_nbit_info(a);
|
||||
|
|
|
@ -50,10 +50,12 @@ struct {
|
|||
int compress_sigs;
|
||||
int always_trust;
|
||||
int rfc1991;
|
||||
unsigned emulate_bugs; /* bug emulation flags */
|
||||
unsigned emulate_bugs; /* bug emulation flags EMUBUG_xxxx */
|
||||
} opt;
|
||||
|
||||
|
||||
#define EMUBUG_GPGCHKSUM 1
|
||||
|
||||
#define DBG_PACKET_VALUE 1 /* debug packet reading/writing */
|
||||
#define DBG_MPI_VALUE 2 /* debug mpi details */
|
||||
#define DBG_CIPHER_VALUE 4 /* debug cipher handling */
|
||||
|
|
|
@ -258,7 +258,9 @@ void free_comment( PKT_comment *rem );
|
|||
void free_packet( PACKET *pkt );
|
||||
PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s );
|
||||
PKT_secret_key *copy_secret_key( PKT_secret_key *d, PKT_secret_key *s );
|
||||
int cmp_public_keys( PKT_public_key *a, PKT_public_key *b );
|
||||
PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s );
|
||||
PKT_user_id *copy_user_id( PKT_user_id *d, PKT_user_id *s );
|
||||
int cmp_public_keys( PKT_public_key *d, PKT_public_key *s );
|
||||
int cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk );
|
||||
int cmp_user_ids( PKT_user_id *a, PKT_user_id *b );
|
||||
|
||||
|
@ -298,4 +300,7 @@ int make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
|
|||
int (*mksubpkt)(PKT_signature *, void *),
|
||||
void *opaque );
|
||||
|
||||
/*-- keygen.c --*/
|
||||
PKT_user_id *generate_user_id(void);
|
||||
|
||||
#endif /*G10_PACKET_H*/
|
||||
|
|
|
@ -349,7 +349,7 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
|
|||
}
|
||||
|
||||
leave:
|
||||
if( rc == -1 && iobuf_error(inp) )
|
||||
if( !rc && iobuf_error(inp) )
|
||||
rc = G10ERR_INV_KEYRING;
|
||||
return rc;
|
||||
}
|
||||
|
@ -434,7 +434,8 @@ skip_rest( IOBUF inp, unsigned long pktlen )
|
|||
}
|
||||
else {
|
||||
for( ; pktlen; pktlen-- )
|
||||
iobuf_get(inp);
|
||||
if( iobuf_get(inp) == -1 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1048,6 +1049,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
|
|||
rc = G10ERR_INVALID_PACKET;
|
||||
goto leave;
|
||||
}
|
||||
/* fixme: Add support for other blocksizes */
|
||||
for(i=0; i < 8 && pktlen; i++, pktlen-- )
|
||||
temp[i] = iobuf_get_noeof(inp);
|
||||
if( list_mode ) {
|
||||
|
|
|
@ -53,6 +53,8 @@ do_check( PKT_secret_key *sk )
|
|||
BUG();
|
||||
if( check_cipher_algo( sk->protect.algo ) )
|
||||
return G10ERR_CIPHER_ALGO; /* unsupported protection algorithm */
|
||||
if( cipher_get_blocksize( sk->protect.algo ) != 8 )
|
||||
return G10ERR_CIPHER_ALGO; /* unsupported protection algorithm */
|
||||
keyid_from_sk( sk, keyid );
|
||||
dek = passphrase_to_dek( keyid, sk->protect.algo,
|
||||
&sk->protect.s2k, 0 );
|
||||
|
@ -76,7 +78,7 @@ do_check( PKT_secret_key *sk )
|
|||
csum += checksum_mpi( sk->skey[i] );
|
||||
m_free( buffer );
|
||||
}
|
||||
if( opt.emulate_bugs & 1 ) {
|
||||
if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) {
|
||||
csum = sk->csum;
|
||||
}
|
||||
cipher_close( cipher_hd );
|
||||
|
@ -180,6 +182,8 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
|
|||
|
||||
if( check_cipher_algo( sk->protect.algo ) )
|
||||
rc = G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
|
||||
else if( cipher_get_blocksize( sk->protect.algo ) != 8 )
|
||||
rc = G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
|
||||
else {
|
||||
cipher_hd = cipher_open( sk->protect.algo,
|
||||
CIPHER_MODE_AUTO_CFB, 1 );
|
||||
|
|
108
g10/sign.c
108
g10/sign.c
|
@ -650,4 +650,112 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
|
|||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Create a signature packet for the given public key certificate
|
||||
* and the user id and return it in ret_sig. User signature class SIGCLASS
|
||||
* user-id is not used (and may be NULL if sigclass is 0x20)
|
||||
* If digest_algo is 0 the function selects an appropriate one.
|
||||
*/
|
||||
int
|
||||
make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
|
||||
PKT_user_id *uid, PKT_public_key *subpk,
|
||||
PKT_secret_key *sk,
|
||||
int sigclass, int digest_algo,
|
||||
int (*mksubpkt)(PKT_signature *, void *), void *opaque
|
||||
)
|
||||
{
|
||||
PKT_signature *sig;
|
||||
int rc=0;
|
||||
MD_HANDLE md;
|
||||
|
||||
assert( (sigclass >= 0x10 && sigclass <= 0x13)
|
||||
|| sigclass == 0x20 || sigclass == 0x18 );
|
||||
if( !digest_algo ) {
|
||||
switch( sk->pubkey_algo ) {
|
||||
case PUBKEY_ALGO_DSA: digest_algo = DIGEST_ALGO_SHA1; break;
|
||||
case PUBKEY_ALGO_RSA_S:
|
||||
case PUBKEY_ALGO_RSA: digest_algo = DIGEST_ALGO_MD5; break;
|
||||
default: digest_algo = DIGEST_ALGO_RMD160; break;
|
||||
}
|
||||
}
|
||||
md = md_open( digest_algo, 0 );
|
||||
|
||||
/* hash the public key certificate and the user id */
|
||||
hash_public_key( md, pk );
|
||||
if( sigclass == 0x18 ) { /* subkey binding */
|
||||
hash_public_key( md, subpk );
|
||||
}
|
||||
else if( sigclass != 0x20 ) {
|
||||
if( sk->version >=4 ) {
|
||||
byte buf[5];
|
||||
buf[0] = 0xb4; /* indicates a userid packet */
|
||||
buf[1] = uid->len >> 24; /* always use 4 length bytes */
|
||||
buf[2] = uid->len >> 16;
|
||||
buf[3] = uid->len >> 8;
|
||||
buf[4] = uid->len;
|
||||
md_write( md, buf, 5 );
|
||||
}
|
||||
md_write( md, uid->name, uid->len );
|
||||
}
|
||||
/* and make the signature packet */
|
||||
sig = m_alloc_clear( sizeof *sig );
|
||||
sig->version = sk->version;
|
||||
keyid_from_sk( sk, sig->keyid );
|
||||
sig->pubkey_algo = sk->pubkey_algo;
|
||||
sig->digest_algo = digest_algo;
|
||||
sig->timestamp = make_timestamp();
|
||||
sig->sig_class = sigclass;
|
||||
if( sig->version >= 4 )
|
||||
build_sig_subpkt_from_sig( sig );
|
||||
|
||||
if( sig->version >= 4 && mksubpkt )
|
||||
rc = (*mksubpkt)( sig, opaque );
|
||||
|
||||
if( !rc ) {
|
||||
if( sig->version >= 4 )
|
||||
md_putc( md, sig->version );
|
||||
md_putc( md, sig->sig_class );
|
||||
if( sig->version < 4 ) {
|
||||
u32 a = sig->timestamp;
|
||||
md_putc( md, (a >> 24) & 0xff );
|
||||
md_putc( md, (a >> 16) & 0xff );
|
||||
md_putc( md, (a >> 8) & 0xff );
|
||||
md_putc( md, a & 0xff );
|
||||
}
|
||||
else {
|
||||
byte buf[6];
|
||||
size_t n;
|
||||
|
||||
md_putc( md, sig->pubkey_algo );
|
||||
md_putc( md, sig->digest_algo );
|
||||
if( sig->hashed_data ) {
|
||||
n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
|
||||
md_write( md, sig->hashed_data, n+2 );
|
||||
n += 6;
|
||||
}
|
||||
else
|
||||
n = 6;
|
||||
/* add some magic */
|
||||
buf[0] = sig->version;
|
||||
buf[1] = 0xff;
|
||||
buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */
|
||||
buf[3] = n >> 16;
|
||||
buf[4] = n >> 8;
|
||||
buf[5] = n;
|
||||
md_write( md, buf, 6 );
|
||||
|
||||
}
|
||||
md_final(md);
|
||||
|
||||
rc = complete_sig( sig, sk, md );
|
||||
}
|
||||
|
||||
md_close( md );
|
||||
if( rc )
|
||||
free_seckey_enc( sig );
|
||||
else
|
||||
*ret_sig = sig;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
|
522
g10/tdbio.c
522
g10/tdbio.c
|
@ -45,46 +45,8 @@ static char *db_name;
|
|||
static int db_fd = -1;
|
||||
|
||||
|
||||
|
||||
static void create_db( const char *fname );
|
||||
static void open_db(void);
|
||||
|
||||
/**************************************************
|
||||
************** read and write helpers ************
|
||||
**************************************************/
|
||||
|
||||
static void
|
||||
fwrite_8(FILE *fp, byte a)
|
||||
{
|
||||
if( putc( a & 0xff, fp ) == EOF )
|
||||
log_fatal("error writing byte to trustdb: %s\n", strerror(errno) );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fwrite_32( FILE*fp, ulong a)
|
||||
{
|
||||
putc( (a>>24) & 0xff, fp );
|
||||
putc( (a>>16) & 0xff, fp );
|
||||
putc( (a>> 8) & 0xff, fp );
|
||||
if( putc( a & 0xff, fp ) == EOF )
|
||||
log_fatal("error writing ulong to trustdb: %s\n", strerror(errno) );
|
||||
}
|
||||
|
||||
static void
|
||||
fwrite_zeros( FILE *fp, size_t n)
|
||||
{
|
||||
while( n-- )
|
||||
if( putc( 0, fp ) == EOF )
|
||||
log_fatal("error writing zeros to trustdb: %s\n", strerror(errno) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************
|
||||
************** read and write stuff **************
|
||||
**************************************************/
|
||||
|
||||
int
|
||||
tdbio_set_dbname( const char *new_dbname, int create )
|
||||
|
@ -101,7 +63,11 @@ tdbio_set_dbname( const char *new_dbname, int create )
|
|||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
if( create ) {
|
||||
FILE *fp;
|
||||
TRUSTREC rec;
|
||||
int rc;
|
||||
char *p = strrchr( fname, '/' );
|
||||
|
||||
assert(p);
|
||||
*p = 0;
|
||||
if( access( fname, F_OK ) ) {
|
||||
|
@ -119,7 +85,30 @@ tdbio_set_dbname( const char *new_dbname, int create )
|
|||
log_fatal_f(fname, _("directory does not exist!\n") );
|
||||
}
|
||||
*p = '/';
|
||||
create_db( fname );
|
||||
|
||||
fp =fopen( fname, "w" );
|
||||
if( !fp )
|
||||
log_fatal_f( fname, _("can't create: %s\n"), strerror(errno) );
|
||||
fclose(fp);
|
||||
m_free(db_name);
|
||||
db_name = fname;
|
||||
db_fd = open( db_name, O_RDWR );
|
||||
if( db_fd == -1 )
|
||||
log_fatal_f( db_name, _("can't open: %s\n"), strerror(errno) );
|
||||
|
||||
memset( &rec, 0, sizeof rec );
|
||||
rec.r.ver.version = 2;
|
||||
rec.r.ver.created = make_timestamp();
|
||||
rec.rectype = RECTYPE_VER;
|
||||
rec.recnum = 0;
|
||||
rc = tdbio_write_record( &rec );
|
||||
if( rc )
|
||||
log_fatal_f( fname, _("failed to create version record: %s"),
|
||||
g10_errstr(rc));
|
||||
/* and read again to check that we are okay */
|
||||
if( tdbio_read_record( 0, &rec, RECTYPE_VER ) )
|
||||
log_fatal_f( db_name, "invalid trust-db created\n" );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
m_free(db_name);
|
||||
|
@ -136,37 +125,6 @@ tdbio_get_dbname()
|
|||
|
||||
|
||||
|
||||
/****************
|
||||
* Create a new trustdb
|
||||
*/
|
||||
static void
|
||||
create_db( const char *fname )
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp =fopen( fname, "w" );
|
||||
if( !fp )
|
||||
log_fatal_f( fname, _("can't create %s: %s\n"), strerror(errno) );
|
||||
fwrite_8( fp, 1 ); /* record type */
|
||||
fwrite_8( fp, 'g' );
|
||||
fwrite_8( fp, 'p' );
|
||||
fwrite_8( fp, 'g' );
|
||||
fwrite_8( fp, 2 ); /* version */
|
||||
fwrite_zeros( fp, 3 ); /* reserved */
|
||||
fwrite_32( fp, 0 ); /* not locked */
|
||||
fwrite_32( fp, make_timestamp() ); /* created */
|
||||
fwrite_32( fp, 0 ); /* not yet modified */
|
||||
fwrite_32( fp, 0 ); /* not yet validated*/
|
||||
fwrite_32( fp, 0 ); /* reserved */
|
||||
fwrite_8( fp, 3 ); /* marginals needed */
|
||||
fwrite_8( fp, 1 ); /* completes needed */
|
||||
fwrite_8( fp, 4 ); /* max_cet_depth */
|
||||
fwrite_zeros( fp, 9 ); /* filler */
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
open_db()
|
||||
{
|
||||
|
@ -182,10 +140,221 @@ open_db()
|
|||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Return the record number of the keyhash tbl or create a new one.
|
||||
*/
|
||||
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 )
|
||||
keyhashtbl = vr.r.ver.keyhashtbl;
|
||||
else {
|
||||
TRUSTREC rec;
|
||||
off_t offset;
|
||||
ulong recnum;
|
||||
int i, n;
|
||||
|
||||
offset = lseek( db_fd, 0, SEEK_END );
|
||||
if( offset == -1 )
|
||||
log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) );
|
||||
recnum = offset / TRUST_RECORD_LEN;
|
||||
assert(recnum); /* this is will never be the first record */
|
||||
|
||||
keyhashtbl = recnum;
|
||||
/* Now write the records */
|
||||
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.recnum = recnum;
|
||||
rc = tdbio_write_record( &rec );
|
||||
if( rc )
|
||||
log_fatal_f(db_name,_("failed to create hashtable: %s\n"),
|
||||
g10_errstr(rc));
|
||||
}
|
||||
/* update the version record */
|
||||
vr.r.ver.keyhashtbl = keyhashtbl;
|
||||
rc = tdbio_write_record( &vr );
|
||||
if( rc )
|
||||
log_fatal_f( db_name, _("error updating version record: %s\n"),
|
||||
g10_errstr(rc));
|
||||
}
|
||||
return keyhashtbl;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Update the key hashtbl or create the table if it does not exist
|
||||
*/
|
||||
static int
|
||||
update_keyhashtbl( TRUSTREC *kr )
|
||||
{
|
||||
TRUSTREC lastrec, rec;
|
||||
ulong hashrec, item;
|
||||
int msb;
|
||||
int level=0;
|
||||
int rc, i;
|
||||
|
||||
hashrec = get_keyhashrec();
|
||||
next_level:
|
||||
msb = kr->r.key.fingerprint[level];
|
||||
hashrec += msb / ITEMS_PER_HTBL_RECORD;
|
||||
rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL );
|
||||
if( rc ) {
|
||||
log_error( db_name, "update_keyhashtbl read failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
|
||||
if( !item ) { /* insert new one */
|
||||
rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = kr->recnum;
|
||||
rc = tdbio_write_record( &rec );
|
||||
if( rc ) {
|
||||
log_error( db_name, "update_keyhashtbl write htbl failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
else if( item != kr->recnum ) { /* must do an update */
|
||||
lastrec = rec;
|
||||
rc = tdbio_read_record( item, &rec, 0 );
|
||||
if( rc ) {
|
||||
log_error( db_name, "update_keyhashtbl read item failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
if( rec.rectype == RECTYPE_HTBL ) {
|
||||
hashrec = item;
|
||||
level++;
|
||||
if( level >= kr->r.key.fingerprint_len ) {
|
||||
log_error( db_name, "keyhashtbl has invalid indirections\n");
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
goto next_level;
|
||||
}
|
||||
else if( rec.rectype == RECTYPE_HLST ) { /* extend list */
|
||||
/* see whether the key is already in this list */
|
||||
for(;;) {
|
||||
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
|
||||
if( rec.r.hlst.rnum[i] == kr->recnum ) {
|
||||
log_debug("HTBL: no update needed for keyrec %lu\n",
|
||||
kr->recnum );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if( rec.r.hlst.next ) {
|
||||
rc = tdbio_read_record( rec.r.hlst.next,
|
||||
&rec, RECTYPE_HLST);
|
||||
if( rc ) {
|
||||
log_error( db_name,
|
||||
"scan keyhashtbl read hlst failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
else
|
||||
break; /* not there */
|
||||
}
|
||||
/* find the next free entry and put it in */
|
||||
for(;;) {
|
||||
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
|
||||
if( !rec.r.hlst.rnum[i] ) {
|
||||
rec.r.hlst.rnum[i] = kr->recnum;
|
||||
rc = tdbio_write_record( &rec );
|
||||
if( rc )
|
||||
log_error( db_name,
|
||||
"update_keyhashtbl write hlst failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc; /* ready */
|
||||
}
|
||||
}
|
||||
if( rec.r.hlst.next ) {
|
||||
rc = tdbio_read_record( rec.r.hlst.next,
|
||||
&rec, RECTYPE_HLST );
|
||||
if( rc ) {
|
||||
log_error( db_name,
|
||||
"update_keyhashtbl read hlst failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
else { /* add a new list record */
|
||||
rec.r.hlst.next = item = tdbio_new_recnum();
|
||||
rc = tdbio_write_record( &rec );
|
||||
if( rc ) {
|
||||
log_error( db_name,
|
||||
"update_keyhashtbl write hlst failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
memset( &rec, 0, sizeof rec );
|
||||
rec.rectype = RECTYPE_HLST;
|
||||
rec.recnum = item;
|
||||
rec.r.hlst.rnum[0] = kr->recnum;
|
||||
if( rc )
|
||||
log_error( db_name,
|
||||
"update_keyhashtbl write ext hlst failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc; /* ready */
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( rec.rectype == RECTYPE_KEY ) { /* insert a list record */
|
||||
if( rec.recnum == kr->recnum ) {
|
||||
log_debug("HTBL: no update needed for keyrec %lu\n",
|
||||
kr->recnum );
|
||||
return 0;
|
||||
}
|
||||
item = rec.recnum; /* save number of key record */
|
||||
memset( &rec, 0, sizeof rec );
|
||||
rec.rectype = RECTYPE_HLST;
|
||||
rec.recnum = tdbio_new_recnum();
|
||||
rec.r.hlst.rnum[0] = item; /* old keyrecord */
|
||||
rec.r.hlst.rnum[1] = kr->recnum; /* and new one */
|
||||
rc = tdbio_write_record( &rec );
|
||||
if( rc ) {
|
||||
log_error( db_name,
|
||||
"update_keyhashtbl write new hlst failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
/* update the hashtable record */
|
||||
lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum;
|
||||
rc = tdbio_write_record( &lastrec );
|
||||
if( rc )
|
||||
log_error( db_name,
|
||||
"update_keyhashtbl update htbl failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc; /* ready */
|
||||
}
|
||||
else {
|
||||
log_error( db_name, "keyhashtbl %lu points to an invalid record\n",
|
||||
item);
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
tdbio_dump_record( TRUSTREC *rec, FILE *fp )
|
||||
{
|
||||
int i, any;
|
||||
int i;
|
||||
ulong rnum = rec->recnum;
|
||||
|
||||
fprintf(fp, "rec %5lu, ", rnum );
|
||||
|
@ -193,7 +362,8 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
|
|||
switch( rec->rectype ) {
|
||||
case 0: fprintf(fp, "free\n");
|
||||
break;
|
||||
case RECTYPE_VER: fprintf(fp, "version\n");
|
||||
case RECTYPE_VER: fprintf(fp, "version, keyhashtbl=%lu\n",
|
||||
rec->r.ver.keyhashtbl );
|
||||
break;
|
||||
case RECTYPE_DIR:
|
||||
fprintf(fp, "dir %lu, keys=%lu, uids=%lu, cach=%lu, ot=%02x",
|
||||
|
@ -213,11 +383,12 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
|
|||
putc('\n', fp);
|
||||
break;
|
||||
case RECTYPE_KEY:
|
||||
fprintf(fp, "key %lu, next=%lu, algo=%d, flen=%d",
|
||||
fprintf(fp, "key %lu, next=%lu, algo=%d, ",
|
||||
rec->r.key.lid,
|
||||
rec->r.key.next,
|
||||
rec->r.key.pubkey_algo,
|
||||
rec->r.key.fingerprint_len );
|
||||
rec->r.key.pubkey_algo );
|
||||
for(i=0; i < rec->r.key.fingerprint_len; i++ )
|
||||
fprintf(fp, "%02X", rec->r.key.fingerprint[i] );
|
||||
if( rec->r.key.keyflags & KEYF_REVOKED )
|
||||
fputs(", revoked", fp );
|
||||
putc('\n', fp);
|
||||
|
@ -239,29 +410,29 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
|
|||
rec->r.uid.next);
|
||||
break;
|
||||
case RECTYPE_SIG:
|
||||
fprintf(fp, "sig %lu, next=%lu\n",
|
||||
fprintf(fp, "sig %lu, next=%lu,",
|
||||
rec->r.sig.lid, rec->r.sig.next );
|
||||
for(i=any=0; i < SIGS_PER_RECORD; i++ ) {
|
||||
if( rec->r.sig.sig[i].lid ) {
|
||||
if( !any ) {
|
||||
putc('\t', fp);
|
||||
any++;
|
||||
}
|
||||
fprintf(fp, " %lu:%02x", rec->r.sig.sig[i].lid,
|
||||
for(i=0; i < SIGS_PER_RECORD; i++ ) {
|
||||
if( rec->r.sig.sig[i].lid )
|
||||
fprintf(fp, " %lu:%02x", rec->r.sig.sig[i].lid,
|
||||
rec->r.sig.sig[i].flag );
|
||||
}
|
||||
}
|
||||
if( any )
|
||||
putc('\n', fp);
|
||||
putc('\n', fp);
|
||||
break;
|
||||
case RECTYPE_CACH:
|
||||
fprintf(fp, "cach\n");
|
||||
break;
|
||||
case RECTYPE_HTBL:
|
||||
fprintf(fp, "htbl\n");
|
||||
fprintf(fp, "htbl,");
|
||||
for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ )
|
||||
fprintf(fp, " %lu", rec->r.htbl.item[i] );
|
||||
putc('\n', fp);
|
||||
break;
|
||||
case RECTYPE_HLST:
|
||||
fprintf(fp, "hlst\n");
|
||||
fprintf(fp, "hlst, next=%lu,", rec->r.hlst.next );
|
||||
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ )
|
||||
fprintf(fp, " %lu", rec->r.hlst.rnum[i] );
|
||||
putc('\n', fp);
|
||||
break;
|
||||
default:
|
||||
fprintf(fp, "unknown type %d\n", rec->rectype );
|
||||
|
@ -302,30 +473,29 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
|
|||
recnum, expected, rec->rectype );
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
p++;
|
||||
p++; /* skip reserved byte */
|
||||
switch( rec->rectype ) {
|
||||
case 0: /* unused record */
|
||||
case 0: /* unused (free) record */
|
||||
break;
|
||||
case RECTYPE_VER: /* version record */
|
||||
if( memcmp(buf+1, "gpg", 3 ) ) {
|
||||
log_error_f( db_name, _("not a trustdb file\n") );
|
||||
rc = G10ERR_TRUSTDB;
|
||||
}
|
||||
p += 2; /* skip magic */
|
||||
p += 2; /* skip "pgp" */
|
||||
rec->r.ver.version = *p++;
|
||||
rec->r.ver.locked = buftoulong(p); p += 4;
|
||||
p += 3; /* reserved bytes */
|
||||
p += 4; /* lock flags */
|
||||
rec->r.ver.created = buftoulong(p); p += 4;
|
||||
rec->r.ver.modified = buftoulong(p); p += 4;
|
||||
rec->r.ver.validated= buftoulong(p); p += 4;
|
||||
rec->r.ver.marginals_needed = *p++;
|
||||
rec->r.ver.completes_needed = *p++;
|
||||
rec->r.ver.max_cert_depth = *p++;
|
||||
rec->r.ver.keyhashtbl=buftoulong(p); p += 4;
|
||||
if( recnum ) {
|
||||
log_error_f( db_name, "version record with recnum %lu\n",
|
||||
(ulong)recnum );
|
||||
rc = G10ERR_TRUSTDB;
|
||||
}
|
||||
if( rec->r.ver.version != 2 ) {
|
||||
else if( rec->r.ver.version != 2 ) {
|
||||
log_error_f( db_name, "invalid file version %d\n",
|
||||
rec->r.ver.version );
|
||||
rc = G10ERR_TRUSTDB;
|
||||
|
@ -381,6 +551,17 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
|
|||
memcpy(rec->r.cache.blockhash, p, 20); p += 20;
|
||||
rec->r.cache.trustlevel = *p++;
|
||||
break;
|
||||
case RECTYPE_HTBL:
|
||||
for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
|
||||
rec->r.htbl.item[i] = buftoulong(p); p += 4;
|
||||
}
|
||||
break;
|
||||
case RECTYPE_HLST:
|
||||
rec->r.hlst.next = buftoulong(p); p += 4;
|
||||
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
|
||||
rec->r.hlst.rnum[i] = buftoulong(p); p += 4;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log_error_f( db_name, "invalid record type %d at recnum %lu\n",
|
||||
rec->rectype, (ulong)recnum );
|
||||
|
@ -412,8 +593,16 @@ tdbio_write_record( TRUSTREC *rec )
|
|||
switch( rec->rectype ) {
|
||||
case 0: /* unused record */
|
||||
break;
|
||||
case 1: /* version record */
|
||||
BUG();
|
||||
case RECTYPE_VER: /* version record */
|
||||
if( recnum )
|
||||
BUG();
|
||||
memcpy(p-1, "gpg", 3 ); p += 2;
|
||||
*p++ = rec->r.ver.version;
|
||||
p += 7; /* skip reserved bytes and lock flags */
|
||||
ulongtobuf(p, rec->r.ver.created); p += 4;
|
||||
ulongtobuf(p, rec->r.ver.modified); p += 4;
|
||||
ulongtobuf(p, rec->r.ver.validated); p += 4;
|
||||
ulongtobuf(p, rec->r.ver.keyhashtbl); p += 4;
|
||||
break;
|
||||
|
||||
case RECTYPE_DIR: /*directory record */
|
||||
|
@ -466,6 +655,19 @@ tdbio_write_record( TRUSTREC *rec )
|
|||
*p++ = rec->r.cache.trustlevel;
|
||||
break;
|
||||
|
||||
case RECTYPE_HTBL:
|
||||
for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
|
||||
ulongtobuf( p, rec->r.htbl.item[i]); p += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case RECTYPE_HLST:
|
||||
ulongtobuf( p, rec->r.hlst.next); p += 4;
|
||||
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
|
||||
ulongtobuf( p, rec->r.hlst.rnum[i]); p += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
@ -479,6 +681,8 @@ tdbio_write_record( TRUSTREC *rec )
|
|||
log_error(_("trustdb: write failed (n=%d): %s\n"), n, strerror(errno) );
|
||||
return G10ERR_WRITE_FILE;
|
||||
}
|
||||
else if( rec->rectype == RECTYPE_KEY )
|
||||
rc = update_keyhashtbl( rec );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -528,9 +732,6 @@ tdbio_new_recnum()
|
|||
/****************
|
||||
* Search the trustdb for a key which matches PK and return the dir record
|
||||
* The local_id of PK is set to the correct value
|
||||
*
|
||||
* Note: To increase performance, we could use a index search here.
|
||||
* tdbio_write_record shoudl create this index automagically
|
||||
*/
|
||||
int
|
||||
tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec )
|
||||
|
@ -540,32 +741,111 @@ tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec )
|
|||
byte *fingerprint;
|
||||
size_t fingerlen;
|
||||
int rc;
|
||||
ulong hashrec, item;
|
||||
int msb;
|
||||
int level=0;
|
||||
|
||||
keyid_from_pk( pk, keyid );
|
||||
fingerprint = fingerprint_from_pk( pk, NULL, &fingerlen );
|
||||
assert( fingerlen == 20 || fingerlen == 16 );
|
||||
|
||||
for(recnum=1; !(rc=tdbio_read_record( recnum, rec, 0)); recnum++ ) {
|
||||
if( rec->rectype != RECTYPE_KEY )
|
||||
continue;
|
||||
if( rec->r.key.pubkey_algo == pk->pubkey_algo
|
||||
&& !memcmp(rec->r.key.fingerprint, fingerprint, fingerlen) ) {
|
||||
/* found: read the dir record for this key */
|
||||
recnum = rec->r.key.lid;
|
||||
rc = tdbio_read_record( recnum, rec, RECTYPE_DIR);
|
||||
if( rc )
|
||||
break;
|
||||
if( pk->local_id && pk->local_id != recnum )
|
||||
log_error_f(db_name,
|
||||
"found record, but LID from memory does "
|
||||
"not match recnum (%lu,%lu)\n",
|
||||
pk->local_id, recnum );
|
||||
pk->local_id = recnum;
|
||||
return 0;
|
||||
}
|
||||
/* locate the key using the hash table */
|
||||
hashrec = get_keyhashrec();
|
||||
next_level:
|
||||
msb = fingerprint[level];
|
||||
hashrec += msb / ITEMS_PER_HTBL_RECORD;
|
||||
rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL );
|
||||
if( rc ) {
|
||||
log_error( db_name, "scan keyhashtbl failed: %s\n", g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
if( rc != -1 )
|
||||
log_error_f( db_name, _("search_db failed: %s\n"), g10_errstr(rc) );
|
||||
|
||||
item = rec->r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
|
||||
if( !item )
|
||||
return -1; /* not found */
|
||||
|
||||
rc = tdbio_read_record( item, rec, 0 );
|
||||
if( rc ) {
|
||||
log_error( db_name, "keyhashtbl read failed: %s\n", g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
if( rec->rectype == RECTYPE_HTBL ) {
|
||||
hashrec = item;
|
||||
level++;
|
||||
if( level >= fingerlen ) {
|
||||
log_error( db_name, "keyhashtbl has invalid indirections\n");
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
goto next_level;
|
||||
}
|
||||
else if( rec->rectype == RECTYPE_HLST ) {
|
||||
for(;;) {
|
||||
int i;
|
||||
|
||||
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
|
||||
if( rec->r.hlst.rnum[i] ) {
|
||||
TRUSTREC tmp;
|
||||
|
||||
rc = tdbio_read_record( rec->r.hlst.rnum[i],
|
||||
&tmp, RECTYPE_KEY );
|
||||
if( rc ) {
|
||||
log_error( db_name,
|
||||
"scan keyhashtbl read key failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
if( tmp.r.key.pubkey_algo == pk->pubkey_algo
|
||||
&& tmp.r.key.fingerprint_len == fingerlen
|
||||
&& !memcmp(tmp.r.key.fingerprint,
|
||||
fingerprint, fingerlen) ) {
|
||||
*rec = tmp;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( rec->r.hlst.next ) {
|
||||
rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST );
|
||||
if( rc ) {
|
||||
log_error( db_name,
|
||||
"scan keyhashtbl read hlst failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
else
|
||||
return -1; /* not found */
|
||||
}
|
||||
found:
|
||||
;
|
||||
}
|
||||
else if( rec->rectype == RECTYPE_KEY ) {
|
||||
/* must check that it is the requested key */
|
||||
if( rec->r.key.pubkey_algo != pk->pubkey_algo
|
||||
|| rec->r.key.fingerprint_len != fingerlen
|
||||
|| memcmp(rec->r.key.fingerprint, fingerprint, fingerlen) )
|
||||
return -1; /* no: not found */
|
||||
}
|
||||
else {
|
||||
log_error( db_name, "keyhashtbl %lu points to an invalid record\n",
|
||||
item);
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
|
||||
recnum = rec->r.key.lid;
|
||||
|
||||
if( pk->local_id && pk->local_id != recnum )
|
||||
log_error_f(db_name,
|
||||
"found record, but LID from memory does "
|
||||
"not match recnum (%lu,%lu)\n",
|
||||
pk->local_id, recnum );
|
||||
pk->local_id = recnum;
|
||||
|
||||
/* Now read the dir record */
|
||||
rc = tdbio_read_record( recnum, rec, RECTYPE_DIR);
|
||||
if( rc )
|
||||
log_error_f(db_name, "can't read dirrec %lu: %s\n",
|
||||
recnum, g10_errstr(rc) );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
14
g10/tdbio.h
14
g10/tdbio.h
|
@ -60,15 +60,12 @@ struct trust_record {
|
|||
int mark;
|
||||
ulong recnum;
|
||||
union {
|
||||
struct { /* version record: */
|
||||
byte version; /* should be 1 */
|
||||
ulong locked; /* pid of process which holds a lock */
|
||||
struct { /* version record: */
|
||||
byte version; /* should be 2 */
|
||||
ulong created; /* timestamp of trustdb creation */
|
||||
ulong modified; /* timestamp of last modification */
|
||||
ulong validated; /* timestamp of last validation */
|
||||
byte marginals_needed;
|
||||
byte completes_needed;
|
||||
byte max_cert_depth;
|
||||
ulong keyhashtbl;
|
||||
} ver;
|
||||
struct { /* directory record */
|
||||
ulong lid;
|
||||
|
@ -117,10 +114,7 @@ struct trust_record {
|
|||
} htbl;
|
||||
struct {
|
||||
ulong next;
|
||||
struct {
|
||||
byte hash;
|
||||
ulong rnum;
|
||||
} item[ITEMS_PER_HLST_RECORD];
|
||||
ulong rnum[ITEMS_PER_HLST_RECORD]; /* of a key record */
|
||||
} hlst;
|
||||
} r;
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -102,6 +103,9 @@ static ulong last_trust_web_key;
|
|||
static TRUST_SEG_LIST last_trust_web_tslist;
|
||||
|
||||
|
||||
#define HEXTOBIN(a) ( (a) >= '0' && (a) <= '9' ? ((a)-'0') : \
|
||||
(a) >= 'A' && (a) <= 'F' ? ((a)-'A'+10) : ((a)-'a'+10))
|
||||
|
||||
/**********************************************
|
||||
************* list helpers *******************
|
||||
**********************************************/
|
||||
|
@ -945,6 +949,7 @@ update_sigs( TRUSTREC *dir )
|
|||
}
|
||||
else {
|
||||
/* fixme: handle other sig classes here */
|
||||
/* FIXME: Revocations!!! */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1243,7 +1248,16 @@ list_trustdb( const char *username )
|
|||
{
|
||||
TRUSTREC rec;
|
||||
|
||||
if( username ) {
|
||||
if( username && *username == '#' ) {
|
||||
int rc;
|
||||
ulong lid = atoi(username+1);
|
||||
|
||||
if( (rc = list_records( lid)) )
|
||||
log_error("user '%s' read problem: %s\n", username, g10_errstr(rc));
|
||||
else if( (rc = list_sigs( lid )) )
|
||||
log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
|
||||
}
|
||||
else if( username ) {
|
||||
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
|
||||
int rc;
|
||||
|
||||
|
@ -1274,10 +1288,10 @@ list_trustdb( const char *username )
|
|||
}
|
||||
|
||||
/****************
|
||||
* make a list of all defined owner trust value.
|
||||
* Print a list of all defined owner trust value.
|
||||
*/
|
||||
void
|
||||
list_ownertrust()
|
||||
export_ownertrust()
|
||||
{
|
||||
TRUSTREC rec;
|
||||
TRUSTREC rec2;
|
||||
|
@ -1307,6 +1321,67 @@ list_ownertrust()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
import_ownertrust( const char *fname )
|
||||
{
|
||||
FILE *fp;
|
||||
int is_stdin=0;
|
||||
char line[256];
|
||||
char *p;
|
||||
size_t n, fprlen;
|
||||
unsigned otrust;
|
||||
|
||||
if( !fname || (*fname == '-' && !fname[1]) ) {
|
||||
fp = stdin;
|
||||
fname = "[stdin]";
|
||||
is_stdin = 1;
|
||||
}
|
||||
else if( !(fp = fopen( fname, "r" )) ) {
|
||||
log_error_f(fname, _("can't open file: %s\n"), strerror(errno) );
|
||||
return;
|
||||
}
|
||||
|
||||
while( fgets( line, DIM(line)-1, fp ) ) {
|
||||
if( !*line || *line == '#' )
|
||||
continue;
|
||||
n = strlen(line);
|
||||
if( line[n-1] != '\n' ) {
|
||||
log_error_f(fname, "line to long\n" );
|
||||
break; /* can't continue */
|
||||
}
|
||||
for(p = line; *p && *p != ':' ; p++ )
|
||||
if( !isxdigit(*p) )
|
||||
break;
|
||||
if( *p != ':' ) {
|
||||
log_error_f(fname, "error: missing colon\n" );
|
||||
continue;
|
||||
}
|
||||
fprlen = p - line;
|
||||
if( fprlen != 32 && fprlen != 40 ) {
|
||||
log_error_f(fname, "error: invalid fingerprint\n" );
|
||||
continue;
|
||||
}
|
||||
if( sscanf(p, ":%u:", &otrust ) != 1 ) {
|
||||
log_error_f(fname, "error: no otrust value\n" );
|
||||
continue;
|
||||
}
|
||||
if( !otrust )
|
||||
continue; /* no otrust defined - no need to update or insert */
|
||||
/* convert the ascii fingerprint to binary */
|
||||
for(p=line, fprlen=0; *p != ':'; p += 2 )
|
||||
line[fprlen++] = HEXTOBIN(p[0]) * 16 + HEXTOBIN(p[1]);
|
||||
line[fprlen] = 0;
|
||||
|
||||
log_hexdump("found: ", line, fprlen );
|
||||
}
|
||||
if( ferror(fp) )
|
||||
log_error_f(fname, _("read error: %s\n"), strerror(errno) );
|
||||
if( !is_stdin )
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
list_trust_path( int max_depth, const char *username )
|
||||
{
|
||||
|
@ -1405,7 +1480,17 @@ check_trustdb( const char *username )
|
|||
TRUSTREC rec;
|
||||
int rc;
|
||||
|
||||
if( username ) {
|
||||
if( username && *username == '#' ) {
|
||||
int rc;
|
||||
ulong lid = atoi(username+1);
|
||||
|
||||
if( (rc = update_sigs_by_lid( lid )) )
|
||||
log_error("lid %lu: check failed: %s\n",
|
||||
lid, g10_errstr(rc));
|
||||
else
|
||||
log_info("lid %lu: checked: %s\n", lid, g10_errstr(rc));
|
||||
}
|
||||
else if( username ) {
|
||||
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
|
||||
|
||||
if( (rc = get_pubkey_byname( pk, username )) )
|
||||
|
@ -1724,7 +1809,7 @@ insert_trust_record( PKT_public_key *orig_pk )
|
|||
BUG(); /* more than one primary key */
|
||||
keyid_from_pk( pk, keyid );
|
||||
}
|
||||
fingerprint = fingerprint_from_pk( orig_pk, NULL, &fingerlen );
|
||||
fingerprint = fingerprint_from_pk( pk, NULL, &fingerlen );
|
||||
rec = m_alloc_clear( sizeof *rec );
|
||||
rec->rectype = RECTYPE_KEY;
|
||||
rec->r.key.pubkey_algo = pk->pubkey_algo;
|
||||
|
|
|
@ -38,7 +38,8 @@
|
|||
/*-- trustdb.c --*/
|
||||
void list_trustdb(const char *username);
|
||||
void list_trust_path( int max_depth, const char *username );
|
||||
void list_ownertrust(void);
|
||||
void export_ownertrust(void);
|
||||
void import_ownertrust(const char *fname);
|
||||
void check_trustdb( const char *username );
|
||||
int init_trustdb( int level, const char *dbname );
|
||||
int check_trust( PKT_public_key *pk, unsigned *r_trustlevel );
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue