1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-02-01 16:33:02 +01:00

Revamped the trustDB

This commit is contained in:
Werner Koch 2001-09-24 16:03:14 +00:00
parent abdd248af9
commit a3af543617
24 changed files with 1682 additions and 3756 deletions

11
TODO
View File

@ -17,9 +17,6 @@
* Check that no secret temporary results are stored in the result parameter
of the mpi functions. We have already done this for mpi-mul.c
* check whether we can remove all the expire stuff in trustdb because this
is now done in getkey.
* We need another special packet at the end of a clearsign message to mark
it's end and allow for multiple signature for one message. And
add a real grammar to the code in mainproc.c
@ -35,16 +32,8 @@
* add some minor things vor VMS.
* Don't get the ultimately trusted keys from the secring but store
it permanently in the trustdb. This way we don't need a secring at all.
[ currently solved by re-introducing --trusted-key ] Eventually we
will have commands --{add,remove}-trusted-key which keeps them in
special trustdb records.
* Use DSA keys with the test suite (partly done)
* g10/trustdb.c (make_sig_records): fix the fixme.
* Fix the bug in the mips assembler code
* Add a way to show the fingerprint of an key signator's keys

View File

@ -1,3 +1,7 @@
2001-09-24 Werner Koch <wk@gnupg.org>
* gpg.sgml: Described --{update,check}-trustdb.
2001-09-03 Werner Koch <wk@gnupg.org>
* gpg.sgml, gpgv.sgml: Removed GDBM stuff.

View File

@ -469,7 +469,7 @@ the DB is always of type 1 and this is the only record of this type.
1 u32 record number of shadow directory hash table
It does not make sense to combine this table with the key table
because the keyid is not in every case a part of the fingerprint.
4 bytes reserved for version extension record
1 u32 record number of the trusthashtbale
Record type 2: (directory record)

View File

@ -505,7 +505,7 @@ not be expected to successfully import such a key.
<listitem><para>
Import/merge keys. This adds the given keys to the
keyring.
The fast version does not build
The fast version does not update
the trustdb; this can be done at any time with the
command --update-trustdb.
</para>
@ -527,10 +527,34 @@ give the name of this keyserver.
<varlistentry>
<term>--export-ownertrust</term>
<term>--recv-keys &ParmKeyIDs;</term>
<listitem><para>
List the assigned ownertrust values in ASCII format
for backup purposes.
Import the keys with the given key IDs from a HKP
keyserver. Option --keyserver must be used to
give the name of this keyserver.
</para></listitem></varlistentry>
<varlistentry>
<term>--update-trustdb</term>
<listitem><para>
Do trust DB maintenance. This command goes over all keys and builds
the Web-of-Trust. This is an intercative command because it may has to
ask for the "ownertrust" values of keys. The user has to give an
estimation in how far she trusts the owner of the displayed key to
correctly certify (sign) other keys. It does only ask for that value
if it has not yet been assigned to a key. Using the edit menu, that
value can be changed at any time later.
</para></listitem></varlistentry>
<varlistentry>
<term>--check-trustdb</term>
<listitem><para>
Do trust DB maintenance without user interaction. Form time to time
the trust database must be updated so that expired keys and resulting
changes in the Web-of_trust can be tracked. GnuPG tries to figure
when this is required and then does it implicitly; this command can be
used to force such a check. The processing is identically to that of
--update-trustdb but it skips keys with a not yet defined "ownertrust".
</para></listitem></varlistentry>
@ -1164,6 +1188,14 @@ However, due to the fact that the signature creation needs manual
interaction, this performance penalty does not matter in most settings.
</para></listitem></varlistentry>
<term>--no-auto-check-trustdb</term>
<listitem><para>
If GnuPG feels that its information about the Web-of-Trust has to be
updated, it automatically runs the --check-trustdb command
internally. As this is a time consuming process, this option allow to
disable the automatic invocation.
</para></listitem></varlistentry>
<varlistentry>
<term>--throw-keyid</term>
<listitem><para>

View File

@ -1,4 +1,29 @@
2001-09-20 Werner Koch <wk@gnupg.org>
2001-09-24 Werner Koch <wk@gnupg.org>
* g10.c, options.h: New option --no-auto-check-trustdb.
* keygen.c (do_generate_keypair): Set newly created keys to
ultimately trusted.
* tdbio.h, tdbio.c: Removed all support for records DIR, KEY, UID,
PREF, SIG, SDIR and CACH. Changed migration function to work
direct on the file.
(tdbio_read_nextcheck): New.
(tdbio_write_nextcheck): New.
2001-09-21 Werner Koch <wk@gnupg.org>
Revamped the entire key validation system.
* trustdb.c: Complete rewrite. No more validation on demand,
removed some functions, adjusted to all callers to use the new
and much simpler interface. Does not use the LID anymore.
* tdbio.c, tdbio.h: Add new record types trust and valid. Wrote a
migration function to convert to the new trustdb layout.
* getkey.c (classify_user_id2): Do not allow the use of the "#"
prefix.
* keydb.h: Removed the TDBIDX mode add a skipfnc to the
descriptor.
* keyring.c (keyring_search): Implemented skipfnc.
* passphrase.c (agent_open): Add missing bracket. Include windows.h.

View File

@ -224,6 +224,7 @@ enum cmd_and_opt_values { aNull = 0,
oFixedListMode,
oNoSigCache,
oNoSigCreateCheck,
oNoAutoCheckTrustDB,
oPreservePermissions,
oPreferenceList,
oEmu3DESS2KBug, /* will be removed in 1.1 */
@ -276,7 +277,7 @@ static ARGPARSE_OPTS opts[] = {
{ aUpdateTrustDB,
"update-trustdb",0 , N_("update the trust database")},
{ aCheckTrustDB,
"check-trustdb",0 , N_("|[NAMES]|check the trust database")},
"check-trustdb",0 , N_("unattended trust database update")},
{ aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")},
{ aDeArmor, "dearmor", 256, N_("De-Armor a file or stdin") },
{ aDeArmor, "dearmour", 256, "@" },
@ -433,6 +434,7 @@ static ARGPARSE_OPTS opts[] = {
{ oNoAutoKeyRetrieve, "no-auto-key-retrieve", 0, "@" },
{ oNoSigCache, "no-sig-cache", 0, "@" },
{ oNoSigCreateCheck, "no-sig-create-check", 0, "@" },
{ oNoAutoCheckTrustDB, "no-auto-check-trustdb", 0, "@"},
{ oMergeOnly, "merge-only", 0, "@" },
{ oAllowSecretKeyImport, "allow-secret-key-import", 0, "@" },
{ oTryAllSecrets, "try-all-secrets", 0, "@" },
@ -1083,6 +1085,7 @@ main( int argc, char **argv )
iobuf_enable_special_filenames (1);
break;
case oNoExpensiveTrustChecks: opt.no_expensive_trust_checks=1; break;
case oNoAutoCheckTrustDB: opt.no_auto_check_trustdb=1; break;
case oPreservePermissions: opt.preserve_permissions=1; break;
case oPreferenceList: preference_list = pargs.r.ret_str; break;
default : pargs.err = configfp? 1:2; break;
@ -1648,15 +1651,8 @@ main( int argc, char **argv )
break;
case aCheckTrustDB:
if( !argc )
check_trustdb(NULL);
else {
for( ; argc; argc--, argv++ ) {
username = make_username( *argv );
check_trustdb( username );
m_free(username);
}
}
/* Old versions allowed for arguments - ignore them */
check_trustdb();
break;
case aFixTrustDB:

View File

@ -528,6 +528,7 @@ hextobyte( const byte *s )
/****************
* Return the type of the user id:
*
* Please use the constants KEYDB_SERCH_MODE_xxx
* 0 = Invalid user ID
* 1 = exact match
* 2 = match a substring
@ -625,11 +626,7 @@ classify_user_id2( const char *name,
break;
case '#': /* local user id */
mode = KEYDB_SEARCH_MODE_TDBIDX;
s++;
if (keyid_from_lid(strtoul(s, NULL, 10), desc->u.kid))
desc->u.kid[0] = desc->u.kid[1] = 0;
break;
return 0; /* This is now obsolete and van't not be used anymore*/
case ':': /*Unified fingerprint */
{
@ -955,37 +952,6 @@ get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint,
}
/****************
* Search for a key with the given lid and return the entire keyblock
*/
int
get_keyblock_bylid( KBNODE *ret_keyblock, ulong lid )
{
int rc;
struct getkey_ctx_s ctx;
u32 kid[2];
if( keyid_from_lid( lid, kid ) )
kid[0] = kid[1] = 0;
memset( &ctx, 0, sizeof ctx );
ctx.exact = 1;
ctx.not_allocated = 1;
ctx.kr_handle = keydb_new (0);
ctx.nitems = 1;
ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID;
ctx.items[0].u.kid[0] = kid[0];
ctx.items[0].u.kid[1] = kid[1];
rc = lookup( &ctx, ret_keyblock, 0 );
get_pubkey_end( &ctx );
return rc;
}
/****************
* Get a secret key by name and store it into sk
* If NAME is NULL use the default key

View File

@ -229,21 +229,14 @@ check_signatures_trust( PKT_signature *sig )
* instead
*/
int
keyid_from_lid( ulong lid, u32 *keyid )
{
return G10ERR_TRUSTDB;
}
/* Stub: */
int
query_trust_info( PKT_public_key *pk, const byte *namehash )
get_validity_info (PKT_public_key *pk, const byte *namehash )
{
return '?';
}
/* Stub: */
int
get_ownertrust_info( ulong lid )
get_ownertrust_info (PKT_public_key *pk)
{
return '?';
}

View File

@ -203,11 +203,18 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = {
"self-signatures fill be advanced by one second.\n"
)},
{ "keyedit.trust.set_ultimate.okay", N_(
"To build the Web-of-Trust, GnuPG needs to know which keys are\n"
"ultimately trusted - those are usually the keys for which you have\n"
"access to the secret key. Answer \"yes\" to set this key to\n"
"ultimately trusted; if you choose not to do so, you will then be\n"
"taken to the regular ownertrust menu.\n"
)},
{ "passphrase.enter", N_(
""
"Please enter the passhrase; this is a secret sentence \n"
" Blurb, blurb,.... "
)},

View File

@ -158,8 +158,7 @@ import_keys( char **fnames, int nnames, int fast, void *stats_handle )
import_print_stats (stats);
import_release_stats_handle (stats);
}
if( !fast )
sync_trustdb();
}
int
@ -177,8 +176,7 @@ import_keys_stream( IOBUF inp, int fast, void *stats_handle )
import_print_stats (stats);
import_release_stats_handle (stats);
}
if( !fast )
sync_trustdb();
return rc;
}
@ -591,21 +589,8 @@ import_one( const char *fname, KBNODE keyblock, int fast,
}
keydb_release (hd); hd = NULL;
}
if( !rc && !fast ) {
rc = query_trust_record( new_key? pk : pk_orig );
if( rc && rc != -1 )
log_error("trustdb error: %s\n", g10_errstr(rc) );
else if( rc == -1 ) { /* not found trustdb */
rc = insert_trust_record( new_key? keyblock : keyblock_orig );
if( rc )
log_error("key %08lX: trustdb insert failed: %s\n",
(ulong)keyid[1], g10_errstr(rc) );
}
else if( mod_key )
rc = update_trust_record( keyblock_orig, 1, NULL );
else
rc = clear_trust_checked_flag( new_key? pk : pk_orig );
}
if (!rc)
revalidation_mark ();
leave:
release_kbnode( keyblock_orig );
@ -793,15 +778,7 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats )
log_info( _("key %08lX: revocation certificate imported\n"),
(ulong)keyid[1]);
stats->n_revoc++;
if( clear_trust_checked_flag( pk ) ) {
/* seems that we have to insert the record first */
rc = insert_trust_record( keyblock );
if( rc )
log_error("key %08lX: trustdb insert failed: %s\n",
(ulong)keyid[1], g10_errstr(rc) );
else
rc = clear_trust_checked_flag( pk );
}
revalidation_mark ();
leave:
keydb_release (hd);

View File

@ -120,7 +120,6 @@ typedef enum {
KEYDB_SEARCH_MODE_WORDS,
KEYDB_SEARCH_MODE_SHORT_KID,
KEYDB_SEARCH_MODE_LONG_KID,
KEYDB_SEARCH_MODE_TDBIDX,
KEYDB_SEARCH_MODE_FPR16,
KEYDB_SEARCH_MODE_FPR20,
KEYDB_SEARCH_MODE_FPR,
@ -130,6 +129,8 @@ typedef enum {
struct keydb_search_desc {
KeydbSearchMode mode;
int (*skipfnc)(void *,u32*);
void *skipfncvalue;
union {
const char *name;
char fpr[MAX_FINGERPRINT_LEN];

View File

@ -373,7 +373,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, int local )
}
} /* end loop over signators */
if( upd_trust && primary_pk ) {
rc = clear_trust_checked_flag( primary_pk );
revalidation_mark ();
}
@ -793,11 +793,6 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
if( !sign_uids( keyblock, locusr, &modified, cmd == cmdLSIGN )
&& sign_mode )
goto do_cmd_save;
/* Actually we should do a update_trust_record() here so that
* the trust gets displayed correctly. however this is not possible
* because we would have to save the keyblock first - something
* we don't want to do without an explicit save command.
*/
break;
case cmdDEBUG:
@ -933,11 +928,22 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
case cmdTRUST:
show_key_with_all_names( keyblock, 0, 0, 1, 0 );
tty_printf("\n");
if( edit_ownertrust( find_kbnode( keyblock,
PKT_PUBLIC_KEY )->pkt->pkt.public_key->local_id, 1 ) )
if ( sec_keyblock
&& cpr_get_answer_is_yes(
"keyedit.trust.set_ultimate.okay",
_("Do you want to set this key to ultimately trusted? "))) {
PKT_public_key *pk = keyblock->pkt->pkt.public_key;
update_ownertrust (pk,
((get_ownertrust (pk) & ~TRUST_MASK)
| TRUST_ULTIMATE ));
redisplay = 1;
break;
}
if( edit_ownertrust( find_kbnode( keyblock,
PKT_PUBLIC_KEY )->pkt->pkt.public_key, 1 ) )
redisplay = 1;
/* we don't need to set modified here, as the trustvalues
* are updated immediately */
break;
case cmdPREF:
@ -1028,13 +1034,8 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
/* TODO: we should keep track whether we have changed
* something relevant to the trustdb */
if( !modified && sign_mode )
rc = 0; /* we can skip at least in this case */
else
rc = update_trust_record( keyblock, 0, NULL );
if( rc )
log_error(_("update of trustdb failed: %s\n"),
g10_errstr(rc) );
if( !(!modified && sign_mode) )
revalidation_mark ();
goto leave;
case cmdINVCMD:
@ -1143,8 +1144,9 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
/* do it here, so that debug messages don't clutter the
* output */
trust = query_trust_info(pk, NULL);
otrust = get_ownertrust_info( pk->local_id );
trust = get_validity_info (pk, NULL);
otrust = get_ownertrust_info (pk);
}
tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"),
@ -1158,7 +1160,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
tty_printf(_(" trust: %c/%c"), otrust, trust );
if( node->pkt->pkttype == PKT_PUBLIC_KEY
&& (get_ownertrust( pk->local_id )&TRUST_FLAG_DISABLED)) {
&& (get_ownertrust (pk)&TRUST_FLAG_DISABLED)) {
tty_printf("\n*** ");
tty_printf(_("This key has been disabled"));
}
@ -2127,7 +2129,7 @@ menu_revsig( KBNODE keyblock )
}
if( upd_trust )
clear_trust_checked_flag( primary_pk );
revalidation_mark ();
release_revocation_reason_info( reason );
return changed;
}
@ -2192,7 +2194,7 @@ menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
/*commit_kbnode( &sec_keyblock );*/
if( upd_trust )
clear_trust_checked_flag( mainpk );
revalidation_mark ();
release_revocation_reason_info( reason );
return changed;
@ -2202,20 +2204,17 @@ menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
static int
enable_disable_key( KBNODE keyblock, int disable )
{
ulong lid = find_kbnode( keyblock, PKT_PUBLIC_KEY )
->pkt->pkt.public_key->local_id;
PKT_public_key *pk = find_kbnode( keyblock, PKT_PUBLIC_KEY )
->pkt->pkt.public_key;
unsigned int trust, newtrust;
/* Note: Because the keys have beed displayed, we have
* ensured that local_id has been set */
trust = newtrust = get_ownertrust( lid );
trust = newtrust = get_ownertrust (pk);
newtrust &= ~TRUST_FLAG_DISABLED;
if( disable )
newtrust |= TRUST_FLAG_DISABLED;
if( trust == newtrust )
return 0; /* already in that state */
if( !update_ownertrust( lid, newtrust ) )
return 1;
update_ownertrust(pk, newtrust );
return 0;
}

View File

@ -32,6 +32,7 @@
#include "ttyio.h"
#include "options.h"
#include "keydb.h"
#include "trustdb.h"
#include "status.h"
#include "i18n.h"
@ -1934,9 +1935,19 @@ do_generate_keypair( struct para_data_s *para,
get_parameter_algo(para, pKEYTYPE) == PUBKEY_ALGO_RSA
&& get_parameter_uint( para, pKEYUSAGE )
&& !(get_parameter_uint( para,pKEYUSAGE) & PUBKEY_USAGE_ENC);
PKT_public_key *pk = find_kbnode (pub_root,
PKT_PUBLIC_KEY)->pkt->pkt.public_key;
update_ownertrust (pk,
((get_ownertrust (pk) & ~TRUST_MASK)
| TRUST_ULTIMATE ));
if (!opt.batch) {
tty_printf(_("public and secret key created and signed.\n") );
tty_printf(_("key marked as ultimately trusted.\n") );
}
if( !opt.batch )
tty_printf(_("public and secret key created and signed.\n") );
if( !opt.batch
&& ( get_parameter_algo( para, pKEYTYPE ) == PUBKEY_ALGO_DSA
|| no_enc_rsa )

View File

@ -433,7 +433,7 @@ list_keyblock_colon( KBNODE keyblock, int secret )
else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
;
else {
trustletter = query_trust_info( pk, NULL );
trustletter = get_validity_info ( pk, NULL );
if( trustletter == 'u' )
ulti_hack = 1;
putchar(trustletter);
@ -449,7 +449,7 @@ list_keyblock_colon( KBNODE keyblock, int secret )
putchar(':');
if( pk->local_id && !opt.fast_list_mode
&& !opt.no_expensive_trust_checks )
putchar( get_ownertrust_info( pk->local_id ) );
putchar( get_ownertrust_info(pk) );
putchar(':');
}
@ -490,7 +490,7 @@ list_keyblock_colon( KBNODE keyblock, int secret )
rmd160_hash_buffer( namehash,
node->pkt->pkt.user_id->name,
node->pkt->pkt.user_id->len );
trustletter = query_trust_info( pk, namehash );
trustletter = get_validity_info( pk, namehash );
}
else
trustletter = 'u';

View File

@ -678,7 +678,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
int save_mode;
off_t offset, main_offset;
size_t n;
int need_uid, need_words, need_keyid, need_fpr;
int need_uid, need_words, need_keyid, need_fpr, any_skip;
int pk_no, uid_no;
int initial_skip;
PKT_user_id *uid = NULL;
@ -686,7 +686,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
PKT_secret_key *sk = NULL;
/* figure out what information we need */
need_uid = need_words = need_keyid = need_fpr = 0;
need_uid = need_words = need_keyid = need_fpr = any_skip = 0;
for (n=0; n < ndesc; n++) {
switch (desc[n].mode) {
case KEYDB_SEARCH_MODE_EXACT:
@ -715,6 +715,10 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
break;
default: break;
}
if (desc[n].skipfnc) {
any_skip = 1;
need_keyid = 1;
}
}
rc = prepare_search (hd);
@ -797,9 +801,6 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
case KEYDB_SEARCH_MODE_NONE:
BUG ();
break;
case KEYDB_SEARCH_MODE_TDBIDX:
BUG();
break;
case KEYDB_SEARCH_MODE_EXACT:
case KEYDB_SEARCH_MODE_SUBSTR:
case KEYDB_SEARCH_MODE_MAIL:
@ -831,6 +832,9 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
goto found;
break;
case KEYDB_SEARCH_MODE_FIRST:
if (pk||sk)
goto found;
break;
case KEYDB_SEARCH_MODE_NEXT:
if (pk||sk)
goto found;
@ -840,10 +844,19 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
goto found;
}
}
free_packet (&pkt);
continue;
found:
for (n=any_skip?0:ndesc; n < ndesc; n++) {
if (desc[n].skipfnc
&& desc[n].skipfnc (desc[n].skipfncvalue, aki))
break;
}
if (n == ndesc)
goto real_found;
free_packet (&pkt);
}
found:
real_found:
if( !rc ) {
hd->found.offset = main_offset;
hd->found.kr = hd->current.kr;

Binary file not shown.

View File

@ -748,7 +748,7 @@ list_node( CTX c, KBNODE node )
if( mainkey ) {
c->local_id = pk->local_id;
c->trustletter = opt.fast_list_mode?
0 : query_trust_info( pk, NULL );
0 : get_validity_info( pk, NULL );
}
printf("%s:", mainkey? "pub":"sub" );
if( c->trustletter )
@ -762,8 +762,8 @@ list_node( CTX c, KBNODE node )
if( c->local_id )
printf("%lu", c->local_id );
putchar(':');
if( c->local_id && !opt.fast_list_mode )
putchar( get_ownertrust_info( c->local_id ) );
if( mainkey && !opt.fast_list_mode )
putchar( get_ownertrust_info (pk) );
putchar(':');
if( node->next && node->next->pkt->pkttype == PKT_RING_TRUST) {
putchar('\n'); any=1;

View File

@ -114,6 +114,7 @@ struct {
int no_expensive_trust_checks;
int no_sig_cache;
int no_sig_create_check;
int no_auto_check_trustdb;
int preserve_permissions;
int no_homedir_creation;
} opt;

View File

@ -149,8 +149,10 @@ show_revocation_reason( PKT_public_key *pk )
static void
show_paths( ulong lid, int only_first )
show_paths (const PKT_public_key *pk, int only_first )
{
#warning must change enum_cert_paths to use pk
#if 0
void *context = NULL;
unsigned otrust, validity;
int last_level, level;
@ -168,6 +170,7 @@ show_paths( ulong lid, int only_first )
last_level = level;
rc = keyid_from_lid( lid, keyid );
if( rc ) {
log_error("ooops: can't get keyid for lid %lu\n", lid);
return;
@ -206,6 +209,7 @@ show_paths( ulong lid, int only_first )
free_public_key( pk );
}
enum_cert_paths( &context, NULL, NULL, NULL ); /* release context */
#endif
tty_printf("\n");
}
@ -213,143 +217,144 @@ show_paths( ulong lid, int only_first )
/****************
* Returns true if an ownertrust has changed.
* mode: 0 = standard
* 1 = Without key info and additional menu option 'm'
* Returns:
* -2 = nothing changed - caller should show some additional info
* -1 = quit operation
* 0 = nothing changed
* 1 = new ownertrust now ion new_trust
*/
static int
do_edit_ownertrust( ulong lid, int mode, unsigned *new_trust, int defer_help )
do_edit_ownertrust (PKT_public_key *pk, int mode,
unsigned *new_trust, int defer_help )
{
char *p;
int rc;
size_t n;
u32 keyid[2];
PKT_public_key *pk ;
int changed=0;
int quit=0;
int show=0;
int did_help=defer_help;
char *p;
size_t n;
u32 keyid[2];
int changed=0;
int quit=0;
int show=0;
int did_help=defer_help;
rc = keyid_from_lid( lid, keyid );
if( rc ) {
log_error("ooops: can't get keyid for lid %lu\n", lid);
return 0;
}
keyid_from_pk (pk, keyid);
for(;;) {
/* a string with valid answers */
const char *ans = _("sSmMqQ");
pk = m_alloc_clear( sizeof *pk );
rc = get_pubkey( pk, keyid );
if( rc ) {
log_error("key %08lX: public key not found: %s\n",
(ulong)keyid[1], g10_errstr(rc) );
return 0;
}
for(;;) {
/* a string with valid answers */
const char *ans = _("sSmMqQ");
if( !did_help ) {
if( !mode ) {
tty_printf(_("No trust value assigned to %lu:\n"
"%4u%c/%08lX %s \""), lid,
nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ),
(ulong)keyid[1], datestr_from_pk( pk ) );
p = get_user_id( keyid, &n );
tty_print_utf8_string( p, n ),
m_free(p);
tty_printf("\"\n");
print_fingerprint (pk, NULL, 2);
tty_printf("\n");
}
tty_printf(_(
"Please decide how far you trust this user to correctly\n"
"verify other users' keys (by looking at passports,\n"
"checking fingerprints from different sources...)?\n\n"
" 1 = Don't know\n"
" 2 = I do NOT trust\n"
" 3 = I trust marginally\n"
" 4 = I trust fully\n"
" s = please show me more information\n") );
if( mode )
tty_printf(_(" m = back to the main menu\n"));
else
tty_printf(_(" q = quit\n"));
tty_printf("\n");
did_help = 1;
}
if( strlen(ans) != 6 )
BUG();
p = cpr_get("edit_ownertrust.value",_("Your decision? "));
trim_spaces(p);
cpr_kill_prompt();
if( !*p )
did_help = 0;
else if( *p && p[1] )
;
else if( !p[1] && (*p >= '1' && *p <= '4') ) {
unsigned trust;
switch( *p ) {
case '1': trust = TRUST_UNDEFINED; break;
case '2': trust = TRUST_NEVER ; break;
case '3': trust = TRUST_MARGINAL ; break;
case '4': trust = TRUST_FULLY ; break;
default: BUG();
}
*new_trust = trust;
changed = 1;
break;
}
else if( *p == ans[0] || *p == ans[1] ) {
tty_printf(_(
"Certificates leading to an ultimately trusted key:\n"));
show = 1;
break;
}
else if( mode && (*p == ans[2] || *p == ans[3] || *p == CONTROL_D ) ) {
break ; /* back to the menu */
}
else if( !mode && (*p == ans[4] || *p == ans[5] ) ) {
quit = 1;
break ; /* back to the menu */
}
m_free(p); p = NULL;
}
m_free(p);
m_free(pk);
return show? -2: quit? -1 : changed;
if( !did_help )
{
if( !mode )
{
tty_printf(_("No trust value assigned to:\n"
"%4u%c/%08lX %s \""),
nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ),
(ulong)keyid[1], datestr_from_pk( pk ) );
p = get_user_id( keyid, &n );
tty_print_utf8_string( p, n ),
m_free(p);
tty_printf("\"\n");
print_fingerprint (pk, NULL, 2);
tty_printf("\n");
}
tty_printf(_(
"Please decide how far you trust this user to correctly\n"
"verify other users' keys (by looking at passports,\n"
"checking fingerprints from different sources...)?\n\n"
" 1 = Don't know\n"
" 2 = I do NOT trust\n"
" 3 = I trust marginally\n"
" 4 = I trust fully\n"
" s = please show me more information\n") );
if( mode )
tty_printf(_(" m = back to the main menu\n"));
else
tty_printf(_(" q = quit\n"));
tty_printf("\n");
did_help = 1;
}
if( strlen(ans) != 6 )
BUG();
p = cpr_get("edit_ownertrust.value",_("Your decision? "));
trim_spaces(p);
cpr_kill_prompt();
if( !*p )
did_help = 0;
else if( *p && p[1] )
;
else if( !p[1] && (*p >= '1' && *p <= '4') )
{
unsigned trust;
switch( *p )
{
case '1': trust = TRUST_UNDEFINED; break;
case '2': trust = TRUST_NEVER ; break;
case '3': trust = TRUST_MARGINAL ; break;
case '4': trust = TRUST_FULLY ; break;
default: BUG();
}
*new_trust = trust;
changed = 1;
break;
}
else if( *p == ans[0] || *p == ans[1] )
{
tty_printf(_("Certificates leading to an ultimately trusted key:\n"));
show = 1;
break;
}
else if( mode && (*p == ans[2] || *p == ans[3] || *p == CONTROL_D ) )
{
break ; /* back to the menu */
}
else if( !mode && (*p == ans[4] || *p == ans[5] ) )
{
quit = 1;
break ; /* back to the menu */
}
m_free(p); p = NULL;
}
m_free(p);
return show? -2: quit? -1 : changed;
}
/*
* Display a menu to change the ownertrust of the key PK (which should
* be a primary key).
* For mode values see do_edit_ownertrust ()
*/
int
edit_ownertrust( ulong lid, int mode )
edit_ownertrust (PKT_public_key *pk, int mode )
{
unsigned int trust;
int no_help = 0;
unsigned int trust;
int no_help = 0;
for(;;) {
switch( do_edit_ownertrust( lid, mode, &trust, no_help ) ) {
case -1:
return 0;
case -2:
show_paths( lid, 1 );
no_help = 1;
break;
case 1:
trust &= ~TRUST_FLAG_DISABLED;
trust |= get_ownertrust( lid ) & TRUST_FLAG_DISABLED;
if( !update_ownertrust( lid, trust ) )
return 1;
return 0;
default:
return 0;
}
for(;;)
{
switch ( do_edit_ownertrust (pk, mode, &trust, no_help ) )
{
case -1: /* quit */
return 0;
case -2: /* show info */
show_paths(pk, 1);
no_help = 1;
break;
case 1: /* trust value set */
trust &= ~TRUST_FLAG_DISABLED;
trust |= get_ownertrust (pk) & TRUST_FLAG_DISABLED;
update_ownertrust (pk, trust );
return 0;
default:
return 0;
}
}
}
static int
add_ownertrust_cb( ulong lid )
add_ownertrust_cb (PKT_public_key *pk )
{
unsigned trust;
int rc = do_edit_ownertrust( lid, 0, &trust, 0 );
unsigned int trust;
int rc = do_edit_ownertrust (pk, 0, &trust, 0 );
if( rc == 1 )
return trust & TRUST_MASK;
@ -368,13 +373,14 @@ add_ownertrust( PKT_public_key *pk, int *quit, int *trustlevel )
int rc;
unsigned flags = 0;
#warning This function does not make sense anymore
*quit = 0;
*trustlevel = 0;
tty_printf(
_("Could not find a valid trust path to the key. Let's see whether we\n"
"can assign some missing owner trust values.\n\n"));
rc = check_trust( pk, trustlevel, NULL, add_ownertrust_cb, &flags );
*trustlevel = get_validity ( pk, NULL);
if( !(flags & 1) )
tty_printf(_("No path leading to one of our keys found.\n\n") );
@ -436,17 +442,8 @@ do_we_trust( PKT_public_key *pk, int *trustlevel )
switch( (*trustlevel & TRUST_MASK) ) {
case TRUST_UNKNOWN: /* No pubkey in trustDB: Insert and check again */
rc = insert_trust_record_by_pk( pk );
if( rc ) {
log_error("failed to insert it into the trustdb: %s\n",
g10_errstr(rc) );
return 0; /* no */
}
rc = check_trust( pk, trustlevel, NULL, NULL, NULL );
*trustlevel = get_validity (pk, NULL);
*trustlevel &= ~trustmask;
if( rc )
log_fatal("trust check after insert failed: %s\n",
g10_errstr(rc) );
if( *trustlevel == TRUST_UNKNOWN || *trustlevel == TRUST_EXPIRED ) {
log_debug("do_we_trust: oops at %d\n", __LINE__ );
return 0;
@ -587,11 +584,7 @@ check_signatures_trust( PKT_signature *sig )
goto leave;
}
rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
if( rc ) {
log_error("check trust failed: %s\n", g10_errstr(rc));
goto leave;
}
trustlevel = get_validity (pk, NULL);
retry:
if( (trustlevel & TRUST_FLAG_REVOKED) ) {
@ -609,16 +602,7 @@ check_signatures_trust( PKT_signature *sig )
switch( (trustlevel & TRUST_MASK) ) {
case TRUST_UNKNOWN: /* No pubkey in trustDB: Insert and check again */
rc = insert_trust_record_by_pk( pk );
if( rc ) {
log_error("failed to insert it into the trustdb: %s\n",
g10_errstr(rc) );
goto leave;
}
rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
if( rc )
log_fatal("trust check after insert failed: %s\n",
g10_errstr(rc) );
trustlevel = get_validity (pk, NULL);
if( trustlevel == TRUST_UNKNOWN || trustlevel == TRUST_EXPIRED )
BUG();
goto retry;
@ -851,13 +835,8 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
else {
int trustlevel;
rc = check_trust( pk, &trustlevel, pk->namehash,
NULL, NULL );
if( rc ) {
log_error("error checking pk of `%s': %s\n",
answer, g10_errstr(rc) );
}
else if( (trustlevel & TRUST_FLAG_DISABLED) ) {
trustlevel = get_validity (pk, NULL);
if( (trustlevel & TRUST_FLAG_DISABLED) ) {
tty_printf(_("Public key is disabled.\n") );
}
else if( do_we_trust_pre( pk, trustlevel ) ) {
@ -929,17 +908,8 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) {
int trustlevel;
rc = check_trust( pk, &trustlevel, pk->namehash, NULL, NULL );
if( rc ) {
free_public_key( pk ); pk = NULL;
log_error(_("%s: error checking key: %s\n"),
remusr->d, g10_errstr(rc) );
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
remusr->d,
strlen (remusr->d),
-1);
}
else if( (trustlevel & TRUST_FLAG_DISABLED) ) {
trustlevel = get_validity (pk, pk->namehash);
if( (trustlevel & TRUST_FLAG_DISABLED) ) {
free_public_key(pk); pk = NULL;
log_info(_("%s: skipped: public key is disabled\n"),
remusr->d);

View File

@ -46,22 +46,7 @@
#define HEXTOBIN(x) ( (x) >= '0' && (x) <= '9' ? ((x)-'0') : \
(x) >= 'A' && (x) <= 'F' ? ((x)-'A'+10) : ((x)-'a'+10))
/****************
* Read a record but die if it does not exist
* fixme: duplicate: remove it
*/
#if 0
static void
read_record( ulong recno, TRUSTREC *rec, int rectype )
{
int rc = tdbio_read_record( recno, rec, rectype );
if( !rc )
return;
log_error(_("trust record %lu, req type %d: read failed: %s\n"),
recno, rectype, g10_errstr(rc) );
tdbio_invalid();
}
#endif
/****************
* Wirte a record but die on error
*/
@ -77,256 +62,6 @@ write_record( TRUSTREC *rec )
}
/****************
* sync the db
*/
static void
do_sync(void)
{
int rc = tdbio_sync();
if( !rc )
return;
log_error(_("trustdb: sync failed: %s\n"), g10_errstr(rc) );
g10_exit(2);
}
#if 0
static int
print_sigflags( FILE *fp, unsigned flags )
{
if( flags & SIGF_CHECKED ) {
fprintf(fp,"%c%c%c",
(flags & SIGF_VALID) ? 'V':'-',
(flags & SIGF_EXPIRED) ? 'E':'-',
(flags & SIGF_REVOKED) ? 'R':'-');
}
else if( flags & SIGF_NOPUBKEY)
fputs("?--", fp);
else
fputs("---", fp);
return 3;
}
#endif
/****************
* Walk through the signatures of a public key.
* The caller must provide a context structure, with all fields set
* to zero, but the local_id field set to the requested key;
* This function does not change this field. On return the context
* is filled with the local-id of the signature and the signature flag.
* No fields should be changed (clearing all fields and setting
* pubkeyid is okay to continue with an other pubkey)
* Returns: 0 - okay, -1 for eof (no more sigs) or any other errorcode
* FIXME: Do we really need this large and complicated function?
*/
#if 0
static int
walk_sigrecs( SIGREC_CONTEXT *c )
{
TRUSTREC *r;
ulong rnum;
if( c->ctl.eof )
return -1;
r = &c->ctl.rec;
if( !c->ctl.init_done ) {
c->ctl.init_done = 1;
read_record( c->lid, r, 0 );
if( r->rectype != RECTYPE_DIR ) {
c->ctl.eof = 1;
return -1; /* return eof */
}
c->ctl.nextuid = r->r.dir.uidlist;
/* force a read */
c->ctl.index = SIGS_PER_RECORD;
r->r.sig.next = 0;
}
/* need a loop to skip over deleted sigs */
do {
if( c->ctl.index >= SIGS_PER_RECORD ) { /* read the record */
rnum = r->r.sig.next;
if( !rnum && c->ctl.nextuid ) { /* read next uid record */
read_record( c->ctl.nextuid, r, RECTYPE_UID );
c->ctl.nextuid = r->r.uid.next;
rnum = r->r.uid.siglist;
}
if( !rnum ) {
c->ctl.eof = 1;
return -1; /* return eof */
}
read_record( rnum, r, RECTYPE_SIG );
if( r->r.sig.lid != c->lid ) {
log_error(_("chained sigrec %lu has a wrong owner\n"), rnum );
c->ctl.eof = 1;
tdbio_invalid();
}
c->ctl.index = 0;
}
} while( !r->r.sig.sig[c->ctl.index++].lid );
c->sig_lid = r->r.sig.sig[c->ctl.index-1].lid;
c->sig_flag = r->r.sig.sig[c->ctl.index-1].flag;
return 0;
}
#endif
#if 0
static int
do_list_sigs( ulong root, ulong pk_lid, int depth,
LOCAL_ID_TABLE lids, unsigned *lineno )
{
SIGREC_CONTEXT sx;
int rc;
u32 keyid[2];
memset( &sx, 0, sizeof sx );
sx.lid = pk_lid;
for(;;) {
rc = walk_sigrecs( &sx ); /* should we replace it and use */
if( rc )
break;
rc = keyid_from_lid( sx.sig_lid, keyid );
if( rc ) {
printf("%6u: %*s????????.%lu:", *lineno, depth*4, "", sx.sig_lid );
print_sigflags( stdout, sx.sig_flag );
putchar('\n');
++*lineno;
}
else {
printf("%6u: %*s%08lX.%lu:", *lineno, depth*4, "",
(ulong)keyid[1], sx.sig_lid );
print_sigflags( stdout, sx.sig_flag );
putchar(' ');
/* check whether we already checked this pk_lid */
if( !qry_lid_table_flag( ultikey_table, sx.sig_lid, NULL ) ) {
print_user_id("[ultimately trusted]", keyid);
++*lineno;
}
else if( sx.sig_lid == pk_lid ) {
printf("[self-signature]\n");
++*lineno;
}
else if( sx.sig_lid == root ) {
printf("[closed]\n");
++*lineno;
}
else if( ins_lid_table_item( lids, sx.sig_lid, *lineno ) ) {
unsigned refline;
qry_lid_table_flag( lids, sx.sig_lid, &refline );
printf("[see line %u]\n", refline);
++*lineno;
}
else if( depth+1 >= MAX_LIST_SIGS_DEPTH ) {
print_user_id( "[too deeply nested]", keyid );
++*lineno;
}
else {
print_user_id( "", keyid );
++*lineno;
rc = do_list_sigs( root, sx.sig_lid, depth+1, lids, lineno );
if( rc )
break;
}
}
}
return rc==-1? 0 : rc;
}
#endif
/****************
* List all signatures of a public key
*/
static int
list_sigs( ulong pubkey_id )
{
int rc=0;
#if 0
u32 keyid[2];
LOCAL_ID_TABLE lids;
unsigned lineno = 1;
rc = keyid_from_lid( pubkey_id, keyid );
if( rc )
return rc;
printf("Signatures of %08lX.%lu ", (ulong)keyid[1], pubkey_id );
print_user_id("", keyid);
printf("----------------------\n");
lids = new_lid_table();
rc = do_list_sigs( pubkey_id, pubkey_id, 0, lids, &lineno );
putchar('\n');
release_lid_table(lids);
#endif
return rc;
}
/****************
* List all records of a public key
*/
static int
list_records( ulong lid )
{
int rc;
TRUSTREC dr, ur, rec;
ulong recno;
rc = tdbio_read_record( lid, &dr, RECTYPE_DIR );
if( rc ) {
log_error(_("lid %lu: read dir record failed: %s\n"),
lid, g10_errstr(rc));
return rc;
}
tdbio_dump_record( &dr, stdout );
for( recno=dr.r.dir.keylist; recno; recno = rec.r.key.next ) {
rc = tdbio_read_record( recno, &rec, 0 );
if( rc ) {
log_error(_("lid %lu: read key record failed: %s\n"),
lid, g10_errstr(rc));
return rc;
}
tdbio_dump_record( &rec, stdout );
}
for( recno=dr.r.dir.uidlist; recno; recno = ur.r.uid.next ) {
rc = tdbio_read_record( recno, &ur, RECTYPE_UID );
if( rc ) {
log_error(_("lid %lu: read uid record failed: %s\n"),
lid, g10_errstr(rc));
return rc;
}
tdbio_dump_record( &ur, stdout );
/* preference records */
for(recno=ur.r.uid.prefrec; recno; recno = rec.r.pref.next ) {
rc = tdbio_read_record( recno, &rec, RECTYPE_PREF );
if( rc ) {
log_error(_("lid %lu: read pref record failed: %s\n"),
lid, g10_errstr(rc));
return rc;
}
tdbio_dump_record( &rec, stdout );
}
/* sig records */
for(recno=ur.r.uid.siglist; recno; recno = rec.r.sig.next ) {
rc = tdbio_read_record( recno, &rec, RECTYPE_SIG );
if( rc ) {
log_error(_("lid %lu: read sig record failed: %s\n"),
lid, g10_errstr(rc));
return rc;
}
tdbio_dump_record( &rec, stdout );
}
}
/* add cache record dump here */
return rc;
}
/****************
* Dump the entire trustdb or only the entries of one key.
*/
@ -336,38 +71,8 @@ list_trustdb( const char *username )
TRUSTREC rec;
init_trustdb();
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;
if( (rc = get_pubkey_byname( pk, username, NULL, NULL )) )
log_error(_("user '%s' not found: %s\n"), username, g10_errstr(rc) );
else if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 )
log_error(_("problem finding '%s' in trustdb: %s\n"),
username, g10_errstr(rc));
else if( rc == -1 )
log_error(_("user '%s' not in trustdb\n"), username);
else if( (rc = list_records( pk->local_id)) )
log_error(_("user '%s' read problem: %s\n"),
username, g10_errstr(rc));
else if( (rc = list_sigs( pk->local_id )) )
log_error(_("user '%s' list problem: %s\n"),
username, g10_errstr(rc));
free_public_key( pk );
}
else {
/* for now we ignore the user ID */
if (1) {
ulong recnum;
int i;
@ -391,33 +96,22 @@ void
export_ownertrust()
{
TRUSTREC rec;
TRUSTREC rec2;
ulong recnum;
int i;
byte *p;
int rc;
init_trustdb();
printf(_("# List of assigned trustvalues, created %s\n"
"# (Use \"gpg --import-ownertrust\" to restore them)\n"),
asctimestamp( make_timestamp() ) );
for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
if( rec.rectype == RECTYPE_DIR ) {
if( !rec.r.dir.keylist ) {
log_error(_("directory record w/o primary key\n"));
if( rec.rectype == RECTYPE_TRUST ) {
if( !rec.r.trust.ownertrust )
continue;
}
if( !rec.r.dir.ownertrust )
continue;
rc = tdbio_read_record( rec.r.dir.keylist, &rec2, RECTYPE_KEY);
if( rc ) {
log_error(_("error reading key record: %s\n"), g10_errstr(rc));
continue;
}
p = rec2.r.key.fingerprint;
for(i=0; i < rec2.r.key.fingerprint_len; i++, p++ )
p = rec.r.trust.fingerprint;
for(i=0; i < 20; i++, p++ )
printf("%02X", *p );
printf(":%u:\n", (unsigned)rec.r.dir.ownertrust );
printf(":%u:\n", (unsigned int)rec.r.trust.ownertrust );
}
}
}
@ -431,7 +125,9 @@ import_ownertrust( const char *fname )
char line[256];
char *p;
size_t n, fprlen;
unsigned otrust;
unsigned int otrust;
byte fpr[20];
int any = 0;
init_trustdb();
if( !fname || (*fname == '-' && !fname[1]) ) {
@ -475,51 +171,45 @@ import_ownertrust( const char *fname )
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;
repeat:
rc = tdbio_search_dir_byfpr( line, fprlen, 0, &rec );
for(p=line, fprlen=0; fprlen < 20 && *p != ':'; p += 2 )
fpr[fprlen++] = HEXTOBIN(p[0]) * 16 + HEXTOBIN(p[1]);
while (fprlen < 20)
fpr[fprlen++] = 0;
rc = tdbio_search_trust_byfpr (fpr, &rec);
if( !rc ) { /* found: update */
if( rec.r.dir.ownertrust )
log_info("LID %lu: changing trust from %u to %u\n",
rec.r.dir.lid, rec.r.dir.ownertrust, otrust );
else
log_info("LID %lu: setting trust to %u\n",
rec.r.dir.lid, otrust );
rec.r.dir.ownertrust = otrust;
write_record( &rec );
if (rec.r.trust.ownertrust != otrust)
{
if( rec.r.trust.ownertrust )
log_info("changing ownertrust from %u to %u\n",
rec.r.trust.ownertrust, otrust );
else
log_info("setting ownertrust to %u\n", otrust );
rec.r.trust.ownertrust = otrust;
write_record (&rec );
any = 1;
}
}
else if( rc == -1 ) { /* not found; get the key from the ring */
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
log_info_f(fname, _("key not in trustdb, searching ring.\n"));
rc = get_pubkey_byfprint( pk, line, fprlen );
if( rc )
log_info_f(fname, _("key not in ring: %s\n"), g10_errstr(rc));
else {
rc = query_trust_record( pk ); /* only as assertion */
if( rc != -1 )
log_error_f(fname, _("Oops: key is now in trustdb???\n"));
else {
rc = insert_trust_record_by_pk( pk );
if( !rc )
goto repeat; /* update the ownertrust */
log_error_f(fname, _("insert trust record failed: %s\n"),
g10_errstr(rc) );
}
}
else if( rc == -1 ) { /* not found: insert */
log_info("inserting ownertrust of %u\n", otrust );
memset (&rec, 0, sizeof rec);
rec.recnum = tdbio_new_recnum ();
rec.rectype = RECTYPE_TRUST;
memcpy (rec.r.trust.fingerprint, fpr, 20);
rec.r.trust.ownertrust = otrust;
write_record (&rec );
any = 1;
}
else /* error */
log_error_f(fname, _("error finding dir record: %s\n"),
log_error_f(fname, _("error finding trust record: %s\n"),
g10_errstr(rc));
}
if( ferror(fp) )
log_error_f(fname, _("read error: %s\n"), strerror(errno) );
if( !is_stdin )
fclose(fp);
do_sync();
sync_trustdb();
if (any)
revalidation_mark ();
}

View File

@ -83,6 +83,8 @@ static int db_fd = -1;
static int in_transaction;
static void open_db(void);
static void migrate_from_v2 (void);
/*************************************
@ -406,6 +408,28 @@ cleanup(void)
}
}
static int
create_version_record (void)
{
TRUSTREC rec;
int rc;
memset( &rec, 0, sizeof rec );
rec.r.ver.version = 3;
rec.r.ver.created = make_timestamp();
rec.r.ver.marginals = opt.marginals_needed;
rec.r.ver.completes = opt.completes_needed;
rec.r.ver.cert_depth = opt.max_cert_depth;
rec.rectype = RECTYPE_VER;
rec.recnum = 0;
rc = tdbio_write_record( &rec );
if( !rc )
tdbio_sync();
return rc;
}
int
tdbio_set_dbname( const char *new_dbname, int create )
{
@ -469,17 +493,7 @@ tdbio_set_dbname( const char *new_dbname, int create )
log_fatal( _("%s: can't create lock\n"), db_name );
#endif /* !__riscos__ */
memset( &rec, 0, sizeof rec );
rec.r.ver.version = 2;
rec.r.ver.created = make_timestamp();
rec.r.ver.marginals = opt.marginals_needed;
rec.r.ver.completes = opt.completes_needed;
rec.r.ver.cert_depth = opt.max_cert_depth;
rec.rectype = RECTYPE_VER;
rec.recnum = 0;
rc = tdbio_write_record( &rec );
if( !rc )
tdbio_sync();
rc = create_version_record ();
if( rc )
log_fatal( _("%s: failed to create version record: %s"),
fname, g10_errstr(rc));
@ -510,31 +524,45 @@ tdbio_get_dbname()
static void
open_db()
{
TRUSTREC rec;
assert( db_fd == -1 );
byte buf[10];
int n;
TRUSTREC rec;
if( !lockhandle )
lockhandle = create_dotlock( db_name );
if( !lockhandle )
log_fatal( _("%s: can't create lock\n"), db_name );
assert( db_fd == -1 );
if (!lockhandle )
lockhandle = create_dotlock( db_name );
if (!lockhandle )
log_fatal( _("%s: can't create lock\n"), db_name );
#ifdef __riscos__
if( make_dotlock( lockhandle, -1 ) )
log_fatal( _("%s: can't make lock\n"), db_name );
if (make_dotlock( lockhandle, -1 ) )
log_fatal( _("%s: can't make lock\n"), db_name );
#endif /* __riscos__ */
#ifdef HAVE_DOSISH_SYSTEM
db_fd = open( db_name, O_RDWR | O_BINARY );
#else
db_fd = open( db_name, O_RDWR );
#endif
if( db_fd == -1 )
log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) );
if( tdbio_read_record( 0, &rec, RECTYPE_VER ) )
log_fatal( _("%s: invalid trustdb\n"), db_name );
#ifdef HAVE_DOSISH_SYSTEM
db_fd = open (db_name, O_RDWR | O_BINARY );
#else
db_fd = open (db_name, O_RDWR );
#endif
if ( db_fd == -1 )
log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) );
/* check whether we need to do a version migration */
do
n = read (db_fd, buf, 5);
while (n==-1 && errno == EINTR);
if (n == 5 && !memcmp (buf, "\x01gpg\x02", 5))
{
migrate_from_v2 ();
}
/* read the version record */
if (tdbio_read_record (0, &rec, RECTYPE_VER ) )
log_fatal( _("%s: invalid trustdb\n"), db_name );
}
/****************
* Make a hashtable: type 0 = key hash, 1 = sdir hash
* Make a hashtable: type 0 = trust hash
*/
static void
create_hashtable( TRUSTREC *vr, int type )
@ -551,9 +579,8 @@ create_hashtable( TRUSTREC *vr, int type )
assert(recnum); /* this is will never be the first record */
if( !type )
vr->r.ver.keyhashtbl = recnum;
else
vr->r.ver.sdirhashtbl = recnum;
vr->r.ver.trusthashtbl = recnum;
/* Now write the records */
n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD;
for(i=0; i < n; i++, recnum++ ) {
@ -612,50 +639,36 @@ tdbio_db_matches_options()
/****************
* Return the modifiy stamp.
* if modify_down is true, the modify_down stamp will be
* returned, otherwise the modify_up stamp.
* Return the nextstamp value.
*/
ulong
tdbio_read_modify_stamp( int modify_down )
tdbio_read_nextcheck ()
{
TRUSTREC vr;
int rc;
ulong mod;
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, g10_errstr(rc) );
mod = modify_down? vr.r.ver.mod_down : vr.r.ver.mod_up;
/* Always return at least 1 to make comparison easier;
* this is still far back in history (before Led Zeppelin III :-) */
return mod ? mod : 1;
return vr.r.ver.nextcheck;
}
void
tdbio_write_modify_stamp( int up, int down )
tdbio_write_nextcheck (ulong stamp)
{
TRUSTREC vr;
int rc;
ulong stamp;
if( !(up || down) )
return;
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, g10_errstr(rc) );
stamp = make_timestamp();
if( down )
vr.r.ver.mod_down = stamp;
if( up )
vr.r.ver.mod_up = stamp;
if (vr.r.ver.nextcheck == stamp)
return;
vr.r.ver.nextcheck = stamp;
rc = tdbio_write_record( &vr );
if( rc )
log_fatal( _("%s: error writing version record: %s\n"),
@ -663,15 +676,16 @@ tdbio_write_modify_stamp( int up, int down )
}
/****************
* Return the record number of the keyhash tbl or create a new one.
* Return the record number of the trusthash tbl or create a new one.
*/
static ulong
get_keyhashrec(void)
get_trusthashrec(void)
{
static ulong keyhashtbl; /* record number of the key hashtable */
static ulong trusthashtbl; /* record number of the trust hashtable */
if( !keyhashtbl ) {
if( !trusthashtbl ) {
TRUSTREC vr;
int rc;
@ -679,38 +693,14 @@ get_keyhashrec(void)
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, g10_errstr(rc) );
if( !vr.r.ver.keyhashtbl )
if( !vr.r.ver.trusthashtbl )
create_hashtable( &vr, 0 );
keyhashtbl = vr.r.ver.keyhashtbl;
trusthashtbl = vr.r.ver.trusthashtbl;
}
return keyhashtbl;
return trusthashtbl;
}
/****************
* Return the record number of the shadow direcory hash table
* or create a new one.
*/
static ulong
get_sdirhashrec(void)
{
static ulong sdirhashtbl; /* record number of the hashtable */
if( !sdirhashtbl ) {
TRUSTREC vr;
int rc;
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, g10_errstr(rc) );
if( !vr.r.ver.sdirhashtbl )
create_hashtable( &vr, 1 );
sdirhashtbl = vr.r.ver.sdirhashtbl;
}
return sdirhashtbl;
}
/****************
@ -827,9 +817,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
}
} /* end loop over hlst slots */
}
else if( rec.rectype == RECTYPE_KEY
|| rec.rectype == RECTYPE_DIR
|| rec.rectype == RECTYPE_SDIR ) { /* insert a list record */
else if( rec.rectype == RECTYPE_TRUST ) { /* insert a list record */
if( rec.recnum == newrecnum ) {
return 0;
}
@ -1036,57 +1024,16 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen,
}
/****************
* Update the key hashtbl or create the table if it does not exist
* Update the trust hashtbl or create the table if it does not exist
*/
static int
update_keyhashtbl( TRUSTREC *kr )
update_trusthashtbl( TRUSTREC *tr )
{
return upd_hashtable( get_keyhashrec(),
kr->r.key.fingerprint,
kr->r.key.fingerprint_len, kr->recnum );
return upd_hashtable( get_trusthashrec(),
tr->r.trust.fingerprint, 20, tr->recnum );
}
/****************
* Update the shadow dir hashtbl or create the table if it does not exist
*/
static int
update_sdirhashtbl( TRUSTREC *sr )
{
byte key[8];
u32tobuf( key , sr->r.sdir.keyid[0] );
u32tobuf( key+4 , sr->r.sdir.keyid[1] );
return upd_hashtable( get_sdirhashrec(), key, 8, sr->recnum );
}
/****************
* Drop the records from the key-hashtbl
*/
static int
drop_from_keyhashtbl( TRUSTREC *kr )
{
return drop_from_hashtable( get_keyhashrec(),
kr->r.key.fingerprint,
kr->r.key.fingerprint_len, kr->recnum );
}
/****************
* Drop record drom the shadow dir hashtbl
*/
static int
drop_from_sdirhashtbl( TRUSTREC *sr )
{
byte key[8];
u32tobuf( key , sr->r.sdir.keyid[0] );
u32tobuf( key+4 , sr->r.sdir.keyid[1] );
return drop_from_hashtable( get_sdirhashrec(), key, 8, sr->recnum );
}
void
@ -1094,7 +1041,6 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
{
int i;
ulong rnum = rec->recnum;
byte *p;
fprintf(fp, "rec %5lu, ", rnum );
@ -1102,116 +1048,18 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
case 0: fprintf(fp, "blank\n");
break;
case RECTYPE_VER: fprintf(fp,
"version, kd=%lu, sd=%lu, free=%lu, m/c/d=%d/%d/%d down=%s",
rec->r.ver.keyhashtbl, rec->r.ver.sdirhashtbl,
"version, td=%lu, f=%lu, m/c/d=%d/%d/%d nc=%lu (%s)\n",
rec->r.ver.trusthashtbl,
rec->r.ver.firstfree,
rec->r.ver.marginals,
rec->r.ver.completes,
rec->r.ver.cert_depth,
strtimestamp(rec->r.ver.mod_down) );
fprintf(fp, ", up=%s\n", strtimestamp(rec->r.ver.mod_up) );
rec->r.ver.nextcheck,
strtimestamp(rec->r.ver.nextcheck)
);
break;
case RECTYPE_FREE: fprintf(fp, "free, next=%lu\n", rec->r.free.next );
break;
case RECTYPE_DIR:
fprintf(fp, "dir %lu, keys=%lu, uids=%lu, t=%02x",
rec->r.dir.lid,
rec->r.dir.keylist,
rec->r.dir.uidlist,
rec->r.dir.ownertrust );
if( rec->r.dir.valcheck )
fprintf( fp, ", v=%02x/%s", rec->r.dir.validity,
strtimestamp(rec->r.dir.valcheck) );
if( rec->r.dir.checkat )
fprintf( fp, ", a=%s", strtimestamp(rec->r.dir.checkat) );
if( rec->r.dir.dirflags & DIRF_CHECKED ) {
if( rec->r.dir.dirflags & DIRF_VALID )
fputs(", valid", fp );
if( rec->r.dir.dirflags & DIRF_EXPIRED )
fputs(", expired", fp );
if( rec->r.dir.dirflags & DIRF_REVOKED )
fputs(", revoked", fp );
if( rec->r.dir.dirflags & DIRF_NEWKEYS )
fputs(", newkeys", fp );
}
putc('\n', fp);
break;
case RECTYPE_KEY:
fprintf(fp, "key %lu, n=%lu a=%d ",
rec->r.key.lid,
rec->r.key.next,
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_CHECKED ) {
if( rec->r.key.keyflags & KEYF_VALID )
fputs(", valid", fp );
if( rec->r.key.keyflags & KEYF_EXPIRED )
fputs(", expired", fp );
if( rec->r.key.keyflags & KEYF_REVOKED )
fputs(", revoked", fp );
}
putc('\n', fp);
break;
case RECTYPE_UID:
fprintf(fp, "uid %lu, next=%lu, pref=%lu, sig=%lu, hash=%02X%02X",
rec->r.uid.lid,
rec->r.uid.next,
rec->r.uid.prefrec,
rec->r.uid.siglist,
rec->r.uid.namehash[18], rec->r.uid.namehash[19]);
fprintf( fp, ", v=%02x", rec->r.uid.validity );
if( rec->r.uid.uidflags & UIDF_CHECKED ) {
if( rec->r.uid.uidflags & UIDF_VALID )
fputs(", valid", fp );
if( rec->r.uid.uidflags & UIDF_REVOKED )
fputs(", revoked", fp );
}
putc('\n', fp);
break;
case RECTYPE_PREF:
fprintf(fp, "pref %lu, next=%lu,",
rec->r.pref.lid, rec->r.pref.next);
for(i=0,p=rec->r.pref.data; i < ITEMS_PER_PREF_RECORD; i+=2,p+=2 ) {
if( *p )
fprintf(fp, " %c%d", *p == PREFTYPE_SYM ? 'S' :
*p == PREFTYPE_HASH ? 'H' :
*p == PREFTYPE_ZIP ? 'Z' : '?', p[1]);
}
putc('\n', fp);
break;
case RECTYPE_SIG:
fprintf(fp, "sig %lu, next=%lu,",
rec->r.sig.lid, rec->r.sig.next );
for(i=0; i < SIGS_PER_RECORD; i++ ) {
if( rec->r.sig.sig[i].lid ) {
fprintf(fp, " %lu:", rec->r.sig.sig[i].lid );
if( rec->r.sig.sig[i].flag & SIGF_CHECKED ) {
fprintf(fp,"%c%c%c",
(rec->r.sig.sig[i].flag & SIGF_VALID) ? 'V':
(rec->r.sig.sig[i].flag & SIGF_IGNORED) ? 'I':'-',
(rec->r.sig.sig[i].flag & SIGF_EXPIRED) ? 'E':'-',
(rec->r.sig.sig[i].flag & SIGF_REVOKED) ? 'R':'-');
}
else if( rec->r.sig.sig[i].flag & SIGF_NOPUBKEY)
fputs("?--", fp);
else
fputs("---", fp);
}
}
putc('\n', fp);
break;
case RECTYPE_SDIR:
fprintf(fp, "sdir %lu, keyid=%08lX%08lX, algo=%d, hint=%lu\n",
rec->r.sdir.lid,
(ulong)rec->r.sdir.keyid[0],
(ulong)rec->r.sdir.keyid[1],
rec->r.sdir.pubkey_algo,
(ulong)rec->r.sdir.hintlist );
break;
case RECTYPE_CACH:
fprintf(fp, "cach\n");
break;
case RECTYPE_HTBL:
fprintf(fp, "htbl,");
for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ )
@ -1224,6 +1072,20 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
fprintf(fp, " %lu", rec->r.hlst.rnum[i] );
putc('\n', fp);
break;
case RECTYPE_TRUST:
fprintf(fp, "trust ");
for(i=0; i < 20; i++ )
fprintf(fp, "%02X", rec->r.trust.fingerprint[i] );
fprintf (fp, ", ot=%d, d=%d, vl=%lu\n", rec->r.trust.ownertrust,
rec->r.trust.depth, rec->r.trust.validlist);
break;
case RECTYPE_VALID:
fprintf(fp, "valid ");
for(i=0; i < 20; i++ )
fprintf(fp, "%02X", rec->r.valid.namehash[i] );
fprintf (fp, ", v=%d, next=%lu\n", rec->r.valid.validity,
rec->r.valid.next);
break;
default:
fprintf(fp, "unknown type %d\n", rec->rectype );
break;
@ -1279,24 +1141,25 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
log_error( _("%s: not a trustdb file\n"), db_name );
rc = G10ERR_TRUSTDB;
}
p += 2; /* skip "pgp" */
p += 2; /* skip "gpg" */
rec->r.ver.version = *p++;
rec->r.ver.marginals = *p++;
rec->r.ver.completes = *p++;
rec->r.ver.cert_depth = *p++;
p += 4; /* lock flags */
rec->r.ver.created = buftoulong(p); p += 4;
rec->r.ver.mod_down = buftoulong(p); p += 4;
rec->r.ver.mod_up = buftoulong(p); p += 4;
rec->r.ver.keyhashtbl=buftoulong(p); p += 4;
rec->r.ver.nextcheck = buftoulong(p); p += 4;
p += 4;
p += 4;
rec->r.ver.firstfree =buftoulong(p); p += 4;
rec->r.ver.sdirhashtbl =buftoulong(p); p += 4;
p += 4;
rec->r.ver.trusthashtbl =buftoulong(p); p += 4;
if( recnum ) {
log_error( _("%s: version record with recnum %lu\n"), db_name,
(ulong)recnum );
rc = G10ERR_TRUSTDB;
}
else if( rec->r.ver.version != 2 ) {
else if( rec->r.ver.version != 3 ) {
log_error( _("%s: invalid file version %d\n"), db_name,
rec->r.ver.version );
rc = G10ERR_TRUSTDB;
@ -1305,95 +1168,6 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
case RECTYPE_FREE:
rec->r.free.next = buftoulong(p); p += 4;
break;
case RECTYPE_DIR: /*directory record */
rec->r.dir.lid = buftoulong(p); p += 4;
rec->r.dir.keylist = buftoulong(p); p += 4;
rec->r.dir.uidlist = buftoulong(p); p += 4;
rec->r.dir.cacherec = buftoulong(p); p += 4;
rec->r.dir.ownertrust = *p++;
rec->r.dir.dirflags = *p++;
rec->r.dir.validity = *p++;
rec->r.dir.valcheck = buftoulong(p); p += 4;
rec->r.dir.checkat = buftoulong(p); p += 4;
switch( rec->r.dir.validity ) {
case 0:
case TRUST_UNDEFINED:
case TRUST_NEVER:
case TRUST_MARGINAL:
case TRUST_FULLY:
case TRUST_ULTIMATE:
break;
default:
log_info("lid %lu: invalid validity value - cleared\n", recnum);
}
if( rec->r.dir.lid != recnum ) {
log_error( "%s: dir LID != recnum (%lu,%lu)\n",
db_name, rec->r.dir.lid, (ulong)recnum );
rc = G10ERR_TRUSTDB;
}
break;
case RECTYPE_KEY: /* public key record */
rec->r.key.lid = buftoulong(p); p += 4;
rec->r.key.next = buftoulong(p); p += 4;
p += 7;
rec->r.key.keyflags = *p++;
rec->r.key.pubkey_algo = *p++;
rec->r.key.fingerprint_len = *p++;
if( rec->r.key.fingerprint_len < 1 || rec->r.key.fingerprint_len > 20 )
rec->r.key.fingerprint_len = 20;
memcpy( rec->r.key.fingerprint, p, 20);
break;
case RECTYPE_UID: /* user id record */
rec->r.uid.lid = buftoulong(p); p += 4;
rec->r.uid.next = buftoulong(p); p += 4;
rec->r.uid.prefrec = buftoulong(p); p += 4;
rec->r.uid.siglist = buftoulong(p); p += 4;
rec->r.uid.uidflags = *p++;
rec->r.uid.validity = *p++;
switch( rec->r.uid.validity ) {
case 0:
case TRUST_UNDEFINED:
case TRUST_NEVER:
case TRUST_MARGINAL:
case TRUST_FULLY:
case TRUST_ULTIMATE:
break;
default:
log_info("lid %lu: invalid validity value - cleared\n", recnum);
}
memcpy( rec->r.uid.namehash, p, 20);
break;
case RECTYPE_PREF: /* preference record */
rec->r.pref.lid = buftoulong(p); p += 4;
rec->r.pref.next = buftoulong(p); p += 4;
memcpy( rec->r.pref.data, p, 30 );
break;
case RECTYPE_SIG:
rec->r.sig.lid = buftoulong(p); p += 4;
rec->r.sig.next = buftoulong(p); p += 4;
for(i=0; i < SIGS_PER_RECORD; i++ ) {
rec->r.sig.sig[i].lid = buftoulong(p); p += 4;
rec->r.sig.sig[i].flag = *p++;
}
break;
case RECTYPE_SDIR: /* shadow directory record */
rec->r.sdir.lid = buftoulong(p); p += 4;
rec->r.sdir.keyid[0]= buftou32(p); p += 4;
rec->r.sdir.keyid[1]= buftou32(p); p += 4;
rec->r.sdir.pubkey_algo = *p++;
p += 3;
rec->r.sdir.hintlist = buftoulong(p);
if( rec->r.sdir.lid != recnum ) {
log_error( "%s: sdir LID != recnum (%lu,%lu)\n",
db_name, rec->r.sdir.lid, (ulong)recnum );
rc = G10ERR_TRUSTDB;
}
break;
case RECTYPE_CACH: /* cache record */
rec->r.cache.lid = buftoulong(p); p += 4;
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;
@ -1405,6 +1179,18 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
rec->r.hlst.rnum[i] = buftoulong(p); p += 4;
}
break;
case RECTYPE_TRUST:
memcpy( rec->r.trust.fingerprint, p, 20); p+=20;
rec->r.trust.ownertrust = *p++;
rec->r.trust.depth = *p++;
p += 2;
rec->r.trust.validlist = buftoulong(p); p += 4;
break;
case RECTYPE_VALID:
memcpy( rec->r.valid.namehash, p, 20); p+=20;
rec->r.valid.validity = *p++;
rec->r.valid.next = buftoulong(p); p += 4;
break;
default:
log_error( "%s: invalid record type %d at recnum %lu\n",
db_name, rec->rectype, (ulong)recnum );
@ -1445,79 +1231,18 @@ tdbio_write_record( TRUSTREC *rec )
*p++ = rec->r.ver.cert_depth;
p += 4; /* skip lock flags */
ulongtobuf(p, rec->r.ver.created); p += 4;
ulongtobuf(p, rec->r.ver.mod_down); p += 4;
ulongtobuf(p, rec->r.ver.mod_up); p += 4;
ulongtobuf(p, rec->r.ver.keyhashtbl); p += 4;
ulongtobuf(p, rec->r.ver.nextcheck); p += 4;
p += 4;
p += 4;
ulongtobuf(p, rec->r.ver.firstfree ); p += 4;
ulongtobuf(p, rec->r.ver.sdirhashtbl ); p += 4;
p += 4;
ulongtobuf(p, rec->r.ver.trusthashtbl ); p += 4;
break;
case RECTYPE_FREE:
ulongtobuf(p, rec->r.free.next); p += 4;
break;
case RECTYPE_DIR: /*directory record */
ulongtobuf(p, rec->r.dir.lid); p += 4;
ulongtobuf(p, rec->r.dir.keylist); p += 4;
ulongtobuf(p, rec->r.dir.uidlist); p += 4;
ulongtobuf(p, rec->r.dir.cacherec); p += 4;
*p++ = rec->r.dir.ownertrust;
*p++ = rec->r.dir.dirflags;
*p++ = rec->r.dir.validity;
ulongtobuf(p, rec->r.dir.valcheck); p += 4;
ulongtobuf(p, rec->r.dir.checkat); p += 4;
assert( rec->r.dir.lid == recnum );
break;
case RECTYPE_KEY:
ulongtobuf(p, rec->r.key.lid); p += 4;
ulongtobuf(p, rec->r.key.next); p += 4;
p += 7;
*p++ = rec->r.key.keyflags;
*p++ = rec->r.key.pubkey_algo;
*p++ = rec->r.key.fingerprint_len;
memcpy( p, rec->r.key.fingerprint, 20); p += 20;
break;
case RECTYPE_UID: /* user id record */
ulongtobuf(p, rec->r.uid.lid); p += 4;
ulongtobuf(p, rec->r.uid.next); p += 4;
ulongtobuf(p, rec->r.uid.prefrec); p += 4;
ulongtobuf(p, rec->r.uid.siglist); p += 4;
*p++ = rec->r.uid.uidflags;
*p++ = rec->r.uid.validity;
memcpy( p, rec->r.uid.namehash, 20 ); p += 20;
break;
case RECTYPE_PREF:
ulongtobuf(p, rec->r.pref.lid); p += 4;
ulongtobuf(p, rec->r.pref.next); p += 4;
memcpy( p, rec->r.pref.data, 30 );
break;
case RECTYPE_SIG:
ulongtobuf(p, rec->r.sig.lid); p += 4;
ulongtobuf(p, rec->r.sig.next); p += 4;
for(i=0; i < SIGS_PER_RECORD; i++ ) {
ulongtobuf(p, rec->r.sig.sig[i].lid); p += 4;
*p++ = rec->r.sig.sig[i].flag;
}
break;
case RECTYPE_SDIR:
ulongtobuf( p, rec->r.sdir.lid); p += 4;
u32tobuf( p, rec->r.sdir.keyid[0] ); p += 4;
u32tobuf( p, rec->r.sdir.keyid[1] ); p += 4;
*p++ = rec->r.sdir.pubkey_algo;
p += 3;
ulongtobuf( p, rec->r.sdir.hintlist );
break;
case RECTYPE_CACH:
ulongtobuf(p, rec->r.cache.lid); p += 4;
memcpy(p, rec->r.cache.blockhash, 20); p += 20;
*p++ = rec->r.cache.trustlevel;
break;
case RECTYPE_HTBL:
for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
@ -1532,6 +1257,20 @@ tdbio_write_record( TRUSTREC *rec )
}
break;
case RECTYPE_TRUST:
memcpy( p, rec->r.trust.fingerprint, 20); p += 20;
*p++ = rec->r.trust.ownertrust;
*p++ = rec->r.trust.depth;
p += 2;
ulongtobuf( p, rec->r.trust.validlist); p += 4;
break;
case RECTYPE_VALID:
memcpy( p, rec->r.valid.namehash, 20); p += 20;
*p++ = rec->r.valid.validity;
ulongtobuf( p, rec->r.valid.next); p += 4;
break;
default:
BUG();
}
@ -1539,10 +1278,8 @@ tdbio_write_record( TRUSTREC *rec )
rc = put_record_into_cache( recnum, buf );
if( rc )
;
else if( rec->rectype == RECTYPE_KEY )
rc = update_keyhashtbl( rec );
else if( rec->rectype == RECTYPE_SDIR )
rc = update_sdirhashtbl( rec );
else if( rec->rectype == RECTYPE_TRUST )
rc = update_trusthashtbl( rec );
return rc;
}
@ -1557,10 +1294,10 @@ tdbio_delete_record( ulong recnum )
rc = tdbio_read_record( recnum, &rec, 0 );
if( rc )
;
else if( rec.rectype == RECTYPE_KEY )
rc = drop_from_keyhashtbl( &rec );
else if( rec.rectype == RECTYPE_SDIR )
rc = drop_from_sdirhashtbl( &rec );
else if( rec.rectype == RECTYPE_TRUST ) {
rc = drop_from_hashtable( get_trusthashrec(),
rec.r.trust.fingerprint, 20, rec.recnum );
}
if( rc )
return rc;
@ -1657,104 +1394,38 @@ 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
*/
static int
cmp_trec_fpr ( void *fpr, const TRUSTREC *rec )
{
return rec->rectype == RECTYPE_TRUST
&& !memcmp( rec->r.trust.fingerprint, fpr, 20);
}
int
tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec )
tdbio_search_trust_byfpr( const byte *fingerprint, TRUSTREC *rec )
{
int rc;
/* locate the trust record using the hash table */
rc = lookup_hashtable( get_trusthashrec(), fingerprint, 20,
cmp_trec_fpr, (void*)fingerprint, rec );
return rc;
}
int
tdbio_search_trust_bypk (PKT_public_key *pk, TRUSTREC *rec)
{
byte fingerprint[MAX_FINGERPRINT_LEN];
size_t fingerlen;
u32 keyid[2];
int rc;
keyid_from_pk( pk, keyid );
fingerprint_from_pk( pk, fingerprint, &fingerlen );
rc = tdbio_search_dir_byfpr( fingerprint, fingerlen,
pk->pubkey_algo, rec );
if( !rc ) {
if( pk->local_id && pk->local_id != rec->recnum )
log_error("%s: found record, but LID from memory does "
"not match recnum (%lu,%lu)\n",
db_name, pk->local_id, rec->recnum );
pk->local_id = rec->recnum;
}
return rc;
for (; fingerlen < 20; fingerlen++ )
fingerprint[fingerlen] = 0;
return tdbio_search_trust_byfpr (fingerprint, rec);
}
static int
cmp_krec_fpr( void *dataptr, const TRUSTREC *rec )
{
const struct cmp_krec_fpr_struct *d = dataptr;
return rec->rectype == RECTYPE_KEY
&& ( !d->pubkey_algo || rec->r.key.pubkey_algo == d->pubkey_algo )
&& rec->r.key.fingerprint_len == d->fprlen
&& !memcmp( rec->r.key.fingerprint, d->fpr, d->fprlen );
}
int
tdbio_search_dir_byfpr( const byte *fingerprint, size_t fingerlen,
int pubkey_algo, TRUSTREC *rec )
{
struct cmp_krec_fpr_struct cmpdata;
ulong recnum;
int rc;
assert( fingerlen == 20 || fingerlen == 16 );
/* locate the key using the hash table */
cmpdata.pubkey_algo = pubkey_algo;
cmpdata.fpr = fingerprint;
cmpdata.fprlen = fingerlen;
rc = lookup_hashtable( get_keyhashrec(), fingerprint, fingerlen,
cmp_krec_fpr, &cmpdata, rec );
if( !rc ) {
recnum = rec->r.key.lid;
/* Now read the dir record */
rc = tdbio_read_record( recnum, rec, RECTYPE_DIR);
if( rc )
log_error("%s: can't read dirrec %lu: %s\n",
db_name, recnum, g10_errstr(rc) );
}
return rc;
}
static int
cmp_sdir( void *dataptr, const TRUSTREC *rec )
{
const struct cmp_xdir_struct *d = dataptr;
return rec->rectype == RECTYPE_SDIR
&& ( !d->pubkey_algo || rec->r.sdir.pubkey_algo == d->pubkey_algo )
&& rec->r.sdir.keyid[0] == d->keyid[0]
&& rec->r.sdir.keyid[1] == d->keyid[1];
}
int
tdbio_search_sdir( u32 *keyid, int pubkey_algo, TRUSTREC *rec )
{
struct cmp_xdir_struct cmpdata;
int rc;
byte key[8];
/* locate the shadow dir record using the hash table */
u32tobuf( key , keyid[0] );
u32tobuf( key+4 , keyid[1] );
cmpdata.pubkey_algo = pubkey_algo;
cmpdata.keyid[0] = keyid[0];
cmpdata.keyid[1] = keyid[1];
rc = lookup_hashtable( get_sdirhashrec(), key, 8,
cmp_sdir, &cmpdata, rec );
return rc;
}
void
tdbio_invalid(void)
@ -1764,4 +1435,130 @@ tdbio_invalid(void)
g10_exit(2);
}
/*
* Migrate the trustdb as just up to gpg 1.0.6 (trustdb version 2)
* to the 2.1 version as used with 1.0.6b - This is pretty trivial as needs
* only to scan the tdb and insert new the new trust records. The old ones are
* obsolte from now on
*/
static void
migrate_from_v2 ()
{
TRUSTREC rec;
int i, n;
struct {
ulong keyrecno;
byte ot;
byte okay;
byte fpr[20];
} *ottable;
int ottable_size, ottable_used;
byte oldbuf[40];
ulong recno;
int count;
ottable_size = 5;
ottable = m_alloc (ottable_size * sizeof *ottable);
ottable_used = 0;
/* We have some restrictions here. We can't use the version record
* and we can't use any of the old hashtables because we dropped the
* code. So we first collect all ownertrusts and then use a second
* pass fo find the associated keys. We have to do this all without using
* the regular record read functions.
*/
/* get all the ownertrusts */
if (lseek (db_fd, 0, SEEK_SET ) == -1 )
log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno));
for (recno=0;;recno++)
{
do
n = read (db_fd, oldbuf, 40);
while (n==-1 && errno == EINTR);
if (!n)
break; /* eof */
if (n != 40)
log_fatal ("migrate_vfrom_v2: read error or short read\n");
if (*oldbuf != 2)
continue;
/* v2 dir record */
if (ottable_used == ottable_size)
{
ottable_size += 1000;
ottable = m_realloc (ottable, ottable_size * sizeof *ottable);
}
ottable[ottable_used].keyrecno = buftoulong (oldbuf+6);
ottable[ottable_used].ot = oldbuf[17];
ottable[ottable_used].okay = 0;
memset (ottable[ottable_used].fpr,0, 20);
if (ottable[ottable_used].keyrecno)
ottable_used++;
}
log_info ("found %d ownertrust records\n", ottable_used);
/* Read again and find the fingerprints */
if (lseek (db_fd, 0, SEEK_SET ) == -1 )
log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno));
for (recno=0;;recno++)
{
do
n = read (db_fd, oldbuf, 40);
while (n==-1 && errno == EINTR);
if (!n)
break; /* eof */
if (n != 40)
log_fatal ("migrate_from_v2: read error or short read\n");
if (*oldbuf != 3)
continue;
/* v2 key record */
for (i=0; i < ottable_used; i++)
{
if (ottable[i].keyrecno == recno)
{
memcpy (ottable[i].fpr, oldbuf+20, 20);
ottable[i].okay = 1;
break;
}
}
}
/* got everything - create the v3 trustdb */
if (ftruncate (db_fd, 0))
log_fatal ("can't truncate `%s': %s\n", db_name, strerror (errno) );
if (create_version_record ())
log_fatal ("failed to recreate version record of `%s'\n", db_name);
/* access the hash table, so it is store just after the version record,
* this is not needed put a dump is more pretty */
get_trusthashrec ();
/* And insert the old ownertrust values */
count = 0;
for (i=0; i < ottable_used; i++)
{
if (!ottable[i].okay)
continue;
memset (&rec, 0, sizeof rec);
rec.recnum = tdbio_new_recnum ();
rec.rectype = RECTYPE_TRUST;
memcpy(rec.r.trust.fingerprint, ottable[i].fpr, 20);
rec.r.trust.ownertrust = ottable[i].ot;
if (tdbio_write_record (&rec))
log_fatal ("failed to write trust record of `%s'\n", db_name);
count++;
}
revalidation_mark ();
tdbio_sync ();
log_info ("migrated %d version 2 ownertrusts\n", count);
m_free (ottable);
}

View File

@ -35,41 +35,13 @@
#define RECTYPE_VER 1
#define RECTYPE_DIR 2
#define RECTYPE_KEY 3
#define RECTYPE_UID 4
#define RECTYPE_PREF 5
#define RECTYPE_SIG 6
#define RECTYPE_SDIR 8
#define RECTYPE_CACH 9
#define RECTYPE_HTBL 10
#define RECTYPE_HLST 11
#define RECTYPE_TRUST 12
#define RECTYPE_VALID 13
#define RECTYPE_FREE 254
#define DIRF_CHECKED 1 /* has been checked - bits 1,2,3 are valid */
#define DIRF_VALID 2 /* This key is valid: There is at least */
/* one uid with a selfsignature or an revocation */
#define DIRF_EXPIRED 4 /* the complete key has expired */
#define DIRF_REVOKED 8 /* the complete key has been revoked */
#define DIRF_NEWKEYS 128 /* new keys are available: we can check the sigs */
#define KEYF_CHECKED 1 /* This key has been checked */
#define KEYF_VALID 2 /* This is a valid (sub)key */
#define KEYF_EXPIRED 4 /* this key is expired */
#define KEYF_REVOKED 8 /* this key has been revoked */
#define UIDF_CHECKED 1 /* user id has been checked - other bits are valid */
#define UIDF_VALID 2 /* this is a valid user id */
#define UIDF_REVOKED 8 /* this user id has been revoked */
#define SIGF_CHECKED 1 /* signature has been checked - bits 0..6 are valid */
#define SIGF_VALID 2 /* the signature is valid */
#define SIGF_EXPIRED 4 /* the key of this signature has expired */
#define SIGF_REVOKED 8 /* this signature has been revoked */
#define SIGF_IGNORED 64 /* this signature is ignored by the system */
#define SIGF_NOPUBKEY 128 /* there is no pubkey for this sig */
struct trust_record {
int rectype;
int mark;
@ -78,73 +50,21 @@ struct trust_record {
ulong recnum;
union {
struct { /* version record: */
byte version; /* should be 2 */
byte version; /* should be 3 */
byte marginals;
byte completes;
byte cert_depth;
ulong created; /* timestamp of trustdb creation */
ulong mod_down; /* timestamp of last modification downward */
ulong mod_up; /* timestamp of last modification upward */
ulong keyhashtbl;
ulong nextcheck; /* timestamp of next scheduled check */
ulong reserved;
ulong reserved2;
ulong firstfree;
ulong sdirhashtbl;
ulong reserved3;
ulong trusthashtbl;
} ver;
struct { /* free record */
ulong next;
} free;
struct { /* directory record */
ulong lid;
ulong keylist; /* List of keys (the first is the primary key)*/
ulong uidlist; /* list of uid records */
ulong cacherec; /* the cache record */
byte ownertrust;
byte dirflags;
byte validity; /* calculated trustlevel over all uids */
ulong valcheck; /* timestamp of last validation check */
ulong checkat; /* Check key when this time has been reached*/
} dir;
struct { /* primary public key record */
ulong lid;
ulong next; /* next key */
byte keyflags;
byte pubkey_algo;
byte fingerprint_len;
byte fingerprint[20];
} key;
struct { /* user id reord */
ulong lid; /* point back to the directory record */
ulong next; /* points to next user id record */
ulong prefrec; /* recno of preference record */
ulong siglist; /* list of valid signatures (w/o self-sig)*/
byte uidflags;
byte validity; /* calculated trustlevel of this uid */
byte namehash[20]; /* ripemd hash of the username */
} uid;
struct { /* preference record */
ulong lid; /* point back to the directory record */
/* or 0 for a global pref record */
ulong next; /* points to next pref record */
byte data[ITEMS_PER_PREF_RECORD];
} pref; /* pref records are not anymore used! */
struct { /* signature record */
ulong lid;
ulong next; /* recnno of next record or NULL for last one */
struct {
ulong lid; /* of pubkey record of signator (0=unused) */
byte flag; /* SIGF_xxxxx */
} sig[SIGS_PER_RECORD];
} sig;
struct {
ulong lid;
u32 keyid[2];
byte pubkey_algo;
u32 hintlist;
} sdir;
struct { /* cache record */
ulong lid;
byte blockhash[20];
byte trustlevel; /* calculated trustlevel */
} cache;
struct {
ulong item[ITEMS_PER_HTBL_RECORD];
} htbl;
@ -152,25 +72,21 @@ struct trust_record {
ulong next;
ulong rnum[ITEMS_PER_HLST_RECORD]; /* of another record */
} hlst;
struct {
byte fingerprint[20];
byte ownertrust;
byte depth;
ulong validlist;
} trust;
struct {
byte namehash[20];
ulong next;
byte validity;
} valid;
} r;
};
typedef struct trust_record TRUSTREC;
typedef struct {
ulong lid; /* localid */
ulong sigrec;
ulong sig_lid; /* returned signatures LID */
unsigned sig_flag; /* returned signature record flag */
struct { /* internal data */
int init_done;
int eof;
TRUSTREC rec;
ulong nextuid;
int index;
} ctl;
} SIGREC_CONTEXT;
/*-- tdbio.c --*/
int tdbio_set_dbname( const char *new_dbname, int create );
const char *tdbio_get_dbname(void);
@ -178,8 +94,8 @@ 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_db_matches_options(void);
ulong tdbio_read_modify_stamp( int modify_down );
void tdbio_write_modify_stamp( int up, int down );
ulong tdbio_read_nextcheck (void);
void tdbio_write_nextcheck (ulong stamp);
int tdbio_is_dirty(void);
int tdbio_sync(void);
int tdbio_begin_transaction(void);
@ -187,11 +103,8 @@ int tdbio_end_transaction(void);
int tdbio_cancel_transaction(void);
int tdbio_delete_record( ulong recnum );
ulong tdbio_new_recnum(void);
int tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec );
int tdbio_search_dir_byfpr( const byte *fingerprint, size_t fingerlen,
int pubkey_algo, TRUSTREC *rec );
int tdbio_search_dir( u32 *keyid, int pubkey_algo, TRUSTREC *rec );
int tdbio_search_sdir( u32 *keyid, int pubkey_algo, TRUSTREC *rec );
int tdbio_search_trust_byfpr(const byte *fingerprint, TRUSTREC *rec );
int tdbio_search_trust_bypk(PKT_public_key *pk, TRUSTREC *rec );
void tdbio_invalid(void);

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@
/* Trust values must be sorted in ascending order */
#define TRUST_MASK 15
#define TRUST_UNKNOWN 0 /* o: not yet calculated */
#define TRUST_UNKNOWN 0 /* o: not yet calculated/assigned */
#define TRUST_EXPIRED 1 /* e: calculation may be invalid */
#define TRUST_UNDEFINED 2 /* q: not enough information for calculation */
#define TRUST_NEVER 3 /* n: never trust this pubkey */
@ -38,31 +38,31 @@
/*-- trustdb.c --*/
void list_trust_path( const char *username );
void register_trusted_key( const char *string );
void check_trustdb( const char *username );
void update_trustdb( void );
void check_trustdb (void);
void update_trustdb (void);
int setup_trustdb( int level, const char *dbname );
void init_trustdb( void );
void sync_trustdb( void );
int check_trust( PKT_public_key *pk, int *r_trustlevel,
const byte* nh, int (*add_fnc)(ulong), unsigned *retflgs );
int query_trust_info( PKT_public_key *pk, const byte *nh );
int trust_letter( unsigned value );
void revalidation_mark (void);
unsigned int get_validity (PKT_public_key *pk, const byte *namehash);
int get_validity_info (PKT_public_key *pk, const byte *namehash);
void list_trust_path( const char *username );
int enum_cert_paths( void **context, ulong *lid,
unsigned *ownertrust, unsigned *validity );
void enum_cert_paths_print( void **context, FILE *fp,
int refresh, ulong selected_lid );
unsigned get_ownertrust( ulong lid );
int get_ownertrust_info( ulong lid );
int keyid_from_lid( ulong lid, u32 *keyid );
ulong lid_from_keyblock( KBNODE keyblock );
int query_trust_record( PKT_public_key *pk );
int clear_trust_checked_flag( PKT_public_key *pk );
int update_trust_record( KBNODE keyblock, int fast, int *modified );
int insert_trust_record( KBNODE keyblock );
int insert_trust_record_by_pk( PKT_public_key *pk );
int update_ownertrust( ulong lid, unsigned new_trust );
int trust_letter( unsigned value );
unsigned int get_ownertrust (PKT_public_key *pk);
int get_ownertrust_info (PKT_public_key *pk);
void update_ownertrust (PKT_public_key *pk, unsigned int new_trust );
/*-- tdbdump.c --*/
void list_trustdb(const char *username);
@ -70,6 +70,6 @@ void export_ownertrust(void);
void import_ownertrust(const char *fname);
/*-- pkclist.c --*/
int edit_ownertrust( ulong lid, int mode );
int edit_ownertrust (PKT_public_key *pk, int mode );
#endif /*G10_TRUSTDB_H*/