See ChangeLog: Thu Mar 11 16:39:46 CET 1999 Werner Koch

This commit is contained in:
Werner Koch 1999-03-11 15:42:06 +00:00
parent 42ff4d53cb
commit e95a22a6d2
22 changed files with 1902 additions and 1614 deletions

View File

@ -74,12 +74,8 @@ Torbjorn Granlund <tege@noisy.tmg.se>.
The keybox implementation is based on GDBM 1.7.3 by Philip A. Nelson.
The file cipher/rndunix.c is based on Peter Gutmann's rndunix.c from
cryptlib. - He promised to add the GPL as an alternative license to
this and some other files. We don't have a disclaimer yet, but due
to the fact that this is only needed for non-free systems we can
easily remove this from the distribution and put it as an extra module
on the FTP server.
The file cipher/rndunix.c is based on rndunix.c from cryptlib.
Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999.
The files in debian/ are by James Troup who is the Debian maintainer
for GnuPG.

View File

@ -1,3 +1,7 @@
Thu Mar 11 16:39:46 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* configure.in: Remmoved the need for libtool
Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* configure.in (DLSYM_NEEDS_UNDERSCORE): Replaced.

7
NEWS
View File

@ -1,3 +1,10 @@
* New command "lsign" in the keyedit menu to create non-exportable
signatures. Removed --trusted-keys option.
* A bunch of changes to the key validation code.
Noteworthy changes in version 0.9.4
-----------------------------------

9
TODO
View File

@ -1,7 +1,10 @@
* Replace --trusted-keys by a local certificate (which does not get
exported).
* Finish the EGD module.
* Implement 256 bit key Twofish.
* Implement 256 bit key Twofish (wait until the 2nd AES conference).
* Check revocation and expire stuff. [I'm currently working on this.]
@ -19,7 +22,6 @@
* when decryptiong multiple key: print a warning only if no usable pubkey
encrypt package was found. Extension: display a list of all recipients.
* describe the Lim-Lee algorithms
Nice to have
------------
@ -28,7 +30,8 @@ Nice to have
* preferences of hash algorithms are not yet used.
* new menu to delete signatures and list signature in menu
* Replace the SIGUSR1 stuff by semaphores to avoid loss of a signal.
or use POSIX.4 realtime signals.
or use POSIX.4 realtime signals. Overhaul the interface and the
test program. Use it with the test suite?
* add test cases for invalid data (scrambled armor or other random data)
* add checking of armor trailers
* Burn the buffers used by fopen(), or use read(2). Does this

View File

@ -16,6 +16,11 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* ***********************************************************************
* The algorithm used to generate practically save primes is due to
* Lim and Lee as described in the CRYPTO '97 proceedings (ISBN3540633847)
* page 260.
*/
#include <config.h>

View File

@ -1,11 +1,50 @@
/****************************************************************************
* *
* BeOS Randomness-Gathering Code *
* Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1998 *
* Copyright (C) 1998, 1999 Werner Koch
* *
* Unix Randomness-Gathering Code *
* *
* Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999. *
* Heavily modified for GnuPG by Werner Koch *
* *
* *
****************************************************************************/
/* This module is part of the cryptlib continuously seeded pseudorandom
number generator. For usage conditions, see lib_rand.c
[Here is the notice from lib_rand.c:]
This module and the misc/rnd*.c modules represent the cryptlib
continuously seeded pseudorandom number generator (CSPRNG) as described in
my 1998 Usenix Security Symposium paper "The generation of random numbers
for cryptographic purposes".
The CSPRNG code is copyright Peter Gutmann (and various others) 1996,
1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG
modules and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice
and this permission notice in its entirety.
2. Redistributions in binary form must reproduce the copyright notice in
the documentation and/or other materials provided with the distribution.
3. A copy of any bugfixes or enhancements made must be provided to the
author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the
baseline version of the code.
ALTERNATIVELY, the code may be distributed under the terms of the GNU
General Public License, version 2 or any later version published by the
Free Software Foundation, in which case the provisions of the GNU GPL are
required INSTEAD OF the above restrictions.
Although not required under the terms of the GPL, it would still be nice if
you could make any changes available to the author to allow a consistent
code base to be maintained */
/* General includes */
#include <config.h>

View File

@ -118,7 +118,7 @@ AC_PROG_CC
AC_PROG_CPP
AC_ISC_POSIX
AC_PROG_INSTALL
AM_PROG_LIBTOOL
AC_PROG_RANLIB
MPI_OPT_FLAGS=""
if test "$GCC" = yes; then

View File

@ -131,6 +131,9 @@ Key generation
8) Continue with step 4 if we did not find a prime in step 7.
9) Find a generator for that prime.
This algorithm is based on Lim and Lee's suggestion from the
Crypto '97 proceedings p. 260.
Layout of the TrustDB
@ -158,7 +161,9 @@ Record type 1:
validity value from the dir record can be used.
1 u32 locked flags
1 u32 timestamp of trustdb creation
1 u32 timestamp of last modification
1 u32 timestamp of last modification which may affect the validity
of keys in the trustdb. This value is checked against the
validity timestamp in the dir records.
1 u32 timestamp of last validation
(Used to keep track of the time, when this TrustDB was checked
against the pubring)
@ -183,8 +188,9 @@ Record type 2: (directory record)
1 u32 cache record
1 byte ownertrust
1 byte dirflag
1 byte validity of the key calucalted over all user ids
19 byte reserved
1 byte maximum validity of all the user ids
4 byte time of last validity check.
15 byte reserved
Record type 3: (key record)
@ -247,7 +253,7 @@ Record type 6 (sigrec)
6 times
1 u32 Local_id of signators dir or shadow dir record
1 byte Flag: Bit 0 = checked: Bit 1 is valid (we have a real
directory record for this)
directory record for this)
1 = valid is set (but my be revoked)
@ -276,7 +282,7 @@ Record type 8: (shadow directory record)
Record type 9: (cache record)
Record type 9: (cache record) NOT USED
--------------
Used to bind the trustDB to the concrete instance of keyblock in
a pubring. This is used to cache information.
@ -298,13 +304,7 @@ Record type 9: (cache record)
1 byte number of marginal trusted signatures.
1 byte number of fully trusted signatures.
(255 is stored for all values greater than 254)
1 byte Trustlevel
0 = undefined (not calculated)
1 = unknown
2 = not trusted
3 = marginally trusted
4 = fully trusted
5 = ultimately trusted (have secret key too).
1 byte Trustlevel (see trustdb.h)
Record Type 10 (hash table)
@ -459,13 +459,6 @@ Other Notes
to keep them small.
Supported targets:
------------------
powerpc-unknown-linux-gnu (linuxppc)
hppa1.1-hp-hpux10.20

View File

@ -75,7 +75,7 @@ B<-k> [I<username>] [I<keyring>]
B<-kvc> List fingerprints
B<-kvvc> List fingerprints and signatures
B<--list-keys> [I<names>]
B<--list-keys> [I<names>]
List all keys from the public keyrings, or just the
ones given on the command line.
@ -83,7 +83,7 @@ B<--list-secret-keys> [I<names>]
List all keys from the secret keyrings, or just the
ones given on the command line.
B<--list-sigs> [I<names>]
B<--list-sigs> [I<names>]
Same as B<--list-keys>, but the signatures are listed
too.
@ -117,6 +117,11 @@ B<--edit-key> I<name>
asks whether it should be signed. This
question is repeated for all users specified
with B<-u>.
B<lsign>
Same as B<sign> but the signature is marked as
non-exportbale and will therefore never be used
by others. This may be used to make keys valid
only in the local environment.
B<trust>
Change the owner trust value. This updates the
trust-db immediately and no save is required.
@ -129,7 +134,7 @@ B<--edit-key> I<name>
B<delkey>
Remove a subkey.
B<expire>
Change the key expiration time. If a key is
Change the key expiration time. If a key is
selected, the time of this key will be changed.
With no selection the key expiration of the
primary key is changed.
@ -200,7 +205,7 @@ B<--export-secret-keys> [I<names>]
This is normally not very useful.
B<--import>, B<--fast-import>
Import/merge keys. The fast version does not build
Import/merge keys. The fast version does not build
the trustdb; this can be done at any time with the
command B<--update-trustdb>.
@ -217,7 +222,7 @@ B<--import-ownertrust> [I<filename>]
Long options can be put in an options file (default F<~/.gnupg/options>).
Do not write the 2 dashes, but simply the name of the option and any
required arguments. Lines with a hash as the first non-white-space
required arguments. Lines with a hash as the first non-white-space
character are ignored. Commands may be put in this file too, but that
does not make sense.
@ -240,20 +245,7 @@ B<--default-key> I<name>
is not used the default user-id is the first user-id
from the secret keyring.
B<--trusted-key> I<keyid>
Assume that the key with the I<keyid> (which must be
a full (8 byte) keyid) is as trustworthy as one of
your own secret keys. This may be used to make keys
valid which are not directly certified by you but
by a CA you trust. The advantage of this option is
that it shortens the path of certification.
You may also use this option to skip the verification
of your own secret keys which is normally done every
time GnuPG starts up by using the I<keyid> of
your key.
B<-r> I<name>, B<--recipient> I<name>
B<-r> I<name>, B<--recipient> I<name>
Encrypt for user id I<name>. If this option is not
specified, GnuPG asks for the user id.
@ -523,11 +515,11 @@ a signature was bad, and other error codes for fatal errors.
=head1 EXAMPLES
-se -r Bob [file] sign and encrypt for user Bob
-sat [file] make a clear text signature
-sb [file] make a detached signature
-k [userid] show keys
-kc [userid] show fingerprint
-se -r Bob [file] sign and encrypt for user Bob
-sat [file] make a clear text signature
-sb [file] make a detached signature
-k [userid] show keys
-kc [userid] show fingerprint
=head1 ENVIRONMENT
@ -545,14 +537,14 @@ F<~/.gnupg/pubring.gpg.lock> and the lock file
F<~/.gnupg/trustdb.gpg> The trust database
F<~/.gnupg/trustdb.gpg.lock> and the lock file
F<~/.gnupg/options> May contain options
F<~/.gnupg/options> May contain options
F</usr[/local]/share/gnupg/options.skel> Skeleton file
F</usr[/local]/lib/gnupg/> Default location for extensions
=head1 SEE ALSO
gpg(1) gpgm(1)
gpg(1) gpgm(1)
=head1 WARNINGS

View File

@ -1,3 +1,31 @@
Thu Mar 11 16:39:46 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* tdbdump.c: New
* trustdb.c (walk_sigrecs,do_list_sigs,list_sigs,
list_records,list_trustdb,export_ownertrust,import_ownertrust): Moved
to tdbdump.c
(init_trustdb): renamed to setup_trustdb. Changed all callers.
(do_init_trustdb): renamed to init_trustdb().
* trustdb.c (die_invalid_db): replaced by tdbio_invalid.
* tdbio.c (tdbio_invalid): New.
* import.c (delete_inv_parts): Skip non exportable signatures.
* keyedit.c (sign_uid_mk_attrib): New.
(sign_uids): Add the local argument.
(keyedit_menu): New "lsign" command.
* trustdb.c (register_trusted_key): Removed this and all related stuff.
* g10.c (oTrustedKey): Removed option.
* tdbio.h (dir.valcheck): New trustdb field.
* tdbio.c: Add support for this field
(tdbio_read_modify_stamp): New.
(tdbio_write_modify_stamp): New.
* trustdb.c (do_check): Check against this field. Removed cache update.
(verify_key): Add cache update.
(upd_uid_record): Some functional changes.
(upd_cert_record): Ditto
Wed Mar 10 11:26:18 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* keylist.c (list_keyblock): Fixed segv in uid. Print 'u' as

View File

@ -33,6 +33,7 @@ common_source = \
keyid.c \
trustdb.c \
trustdb.h \
tdbdump.c \
tdbio.c \
tdbio.h \
hkp.h \

View File

@ -549,7 +549,7 @@ find_subpkt( byte *buffer, sigsubpkttype_t reqtype,
/****************
* Create or update a signature subpacket for SIG of TYPE.
* This functions know, where to put the data (hashed or unhashed).
* This functions knows where to put the data (hashed or unhashed).
* The function may move data from the unhased part to the hashed one.
* Note: All pointers into sig->[un]hashed are not valid after a call
* to this function. The data to but into the subpaket should be

View File

@ -35,10 +35,10 @@
#include "main.h"
#include "options.h"
#include "keydb.h"
#include "trustdb.h"
#include "mpi.h"
#include "cipher.h"
#include "filter.h"
#include "trustdb.h"
#include "ttyio.h"
#include "i18n.h"
#include "status.h"
@ -111,7 +111,6 @@ enum cmd_and_opt_values { aNull = 0,
oKeyring,
oSecretKeyring,
oDefaultKey,
oTrustedKey,
oOptions,
oDebug,
oDebugAll,
@ -250,7 +249,6 @@ static ARGPARSE_OPTS opts[] = {
{ oCompletesNeeded, "completes-needed", 1, N_("(default is 1)")},
{ oMarginalsNeeded, "marginals-needed", 1, N_("(default is 3)")},
{ oMaxCertDepth, "max-cert-depth", 1, "@" },
{ oTrustedKey, "trusted-key", 2, N_("|KEYID|ulimately trust this key")},
{ oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")},
{ oRFC1991, "rfc1991", 0, N_("emulate the mode described in RFC1991")},
{ oS2KMode, "s2k-mode", 1, N_("|N|use passphrase mode N")},
@ -730,7 +728,6 @@ main( int argc, char **argv )
case oMaxCertDepth: opt.max_cert_depth = pargs.r.ret_int; break;
case oTrustDBName: trustdb_name = pargs.r.ret_str; break;
case oDefaultKey: opt.def_secret_key = pargs.r.ret_str; break;
case oTrustedKey: register_trusted_key( pargs.r.ret_str ); break;
case oNoOptions: break; /* no-options */
case oHomedir: opt.homedir = pargs.r.ret_str; break;
case oNoBatch: opt.batch = 0; break;
@ -938,11 +935,11 @@ main( int argc, char **argv )
case aListSecretKeys:
case aCheckKeys:
if( opt.with_colons ) /* need this to list the trust */
rc = init_trustdb(1, trustdb_name );
rc = setup_trustdb(1, 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;
case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break;
case aListTrustDB: rc = setup_trustdb( argc? 1:0, trustdb_name ); break;
default: rc = setup_trustdb(1, trustdb_name ); break;
}
if( rc )
log_error(_("failed to initialize the TrustDB: %s\n"), g10_errstr(rc));

View File

@ -1,5 +1,5 @@
/* import.c
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -750,6 +750,7 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
{
KBNODE node;
int nvalid=0, uid_seen=0;
const char *p;
for(node=keyblock->next; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
@ -792,6 +793,16 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
&& check_pubkey_algo( node->pkt->pkt.signature->pubkey_algo)
&& node->pkt->pkt.signature->pubkey_algo != PUBKEY_ALGO_RSA )
delete_kbnode( node ); /* build_packet() can't handle this */
else if( node->pkt->pkttype == PKT_SIGNATURE
&& (p = parse_sig_subpkt2( node->pkt->pkt.signature,
SIGSUBPKT_EXPORTABLE, NULL ))
&& !*p ) {
log_info_f(fname, _("key %08lX: non exportable signature "
"(class %02x) - skipped\n"),
(ulong)keyid[1],
node->pkt->pkt.signature->sig_class );
delete_kbnode( node );
}
else if( node->pkt->pkttype == PKT_SIGNATURE
&& node->pkt->pkt.signature->sig_class == 0x20 ) {
if( uid_seen ) {

View File

@ -69,6 +69,13 @@ static int count_selected_keys( KBNODE keyblock );
#define NODFLG_SELKEY (1<<9) /* indicate the selected key */
struct sign_uid_attrib {
int non_exportable;
};
static int
get_keyblock_byname( KBNODE *keyblock, KBPOS *kbpos, const char *username )
{
@ -200,15 +207,31 @@ check_all_keysigs( KBNODE keyblock, int only_selected )
}
int
sign_uid_mk_attrib( PKT_signature *sig, void *opaque )
{
struct sign_uid_attrib *attrib = opaque;
byte buf[8];
if( attrib->non_exportable ) {
buf[0] = 0; /* not exportable */
build_sig_subpkt( sig, SIGSUBPKT_EXPORTABLE, buf, 1 );
}
return 0;
}
/****************
* Loop over all locusr and and sign the uids after asking.
* If no user id is marked, all user ids will be signed;
* if some user_ids are marked those will be signed.
*
* fixme: Add support for our proposed sign-all scheme
*/
static int
sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified )
sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, int local )
{
int rc = 0;
SK_LIST sk_list = NULL;
@ -279,6 +302,10 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified )
m_free(p); p = NULL;
tty_printf("\"\n\n");
if( local )
tty_printf(
_("The signature will be marked as non-exportable.\n\n"));
if( !cpr_get_answer_is_yes("sign_uid.okay", _("Really sign? ")) )
continue;;
/* now we can sign the user ids */
@ -291,14 +318,19 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified )
&& (node->flag & NODFLG_MARK_A) ) {
PACKET *pkt;
PKT_signature *sig;
struct sign_uid_attrib attrib;
assert( primary_pk );
memset( &attrib, 0, sizeof attrib );
attrib.non_exportable = local;
node->flag &= ~NODFLG_MARK_A;
rc = make_keysig_packet( &sig, primary_pk,
node->pkt->pkt.user_id,
NULL,
sk,
0x10, 0, NULL, NULL );
0x10, 0,
sign_uid_mk_attrib,
&attrib );
if( rc ) {
log_error(_("signing failed: %s\n"), g10_errstr(rc));
goto leave;
@ -479,6 +511,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
{
enum cmdids { cmdNONE = 0,
cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
cmdLSIGN,
cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY,
cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE,
cmdNOP };
@ -501,6 +534,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
{ N_("c") , cmdCHECK , 0, NULL },
{ N_("sign") , cmdSIGN , 0, N_("sign the key") },
{ N_("s") , cmdSIGN , 0, NULL },
{ N_("lsign") , cmdLSIGN , 0, N_("sign the key locally") },
{ N_("debug") , cmdDEBUG , 0, NULL },
{ N_("adduid") , cmdADDUID , 1, N_("add a user id") },
{ N_("deluid") , cmdDELUID , 0, N_("delete user id") },
@ -696,6 +730,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
break;
case cmdSIGN: /* sign (only the public key) */
case cmdLSIGN: /* sign (only the public key) */
if( count_uids(keyblock) > 1 && !count_selected_uids(keyblock) ) {
if( !cpr_get_answer_is_yes("keyedit.sign_all.okay",
_("Really sign all user ids? ")) ) {
@ -703,7 +738,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
break;
}
}
sign_uids( keyblock, locusr, &modified );
sign_uids( keyblock, locusr, &modified, cmd == cmdLSIGN );
break;
case cmdDEBUG:

View File

@ -52,9 +52,11 @@ escape-from-lines
# every time it is needed - normally this is not needed.
lock-once
# If you are not running one of the free operation systems
# you probably have to uncomment the next line:
# If you have configured GnuPG without a random gatherer,
# you have to uncomment one of the following lines.
#load-extension rndlinux
#load-extension rndunix
#load-extension rndegd
# GnuPG can import a key from a HKP keyerver if one is missing

522
g10/tdbdump.c Normal file
View File

@ -0,0 +1,522 @@
/* tdbdump.c
* Copyright (C) 1999 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "trustdb.h"
#include "options.h"
#include "packet.h"
#include "main.h"
#include "i18n.h"
#include "tdbio.h"
#define HEXTOBIN(a) ( (a) >= '0' && (a) <= '9' ? ((a)-'0') : \
(a) >= 'A' && (a) <= 'F' ? ((a)-'A'+10) : ((a)-'a'+10))
/****************
* Read a record but die if it does not exist
* fixme: duplicate: remove it
*/
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();
}
/****************
* Wirte a record but die on error
*/
static void
write_record( TRUSTREC *rec )
{
int rc = tdbio_write_record( rec );
if( !rc )
return;
log_error(_("trust record %lu, type %d: write failed: %s\n"),
rec->recnum, rec->rectype, g10_errstr(rc) );
tdbio_invalid();
}
/****************
* 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);
}
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;
}
/****************
* 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?
*/
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;
}
#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 complte trustdb or only the entries of one key.
*/
void
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( NULL, pk, username, 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 {
ulong recnum;
int i;
printf("TrustDB: %s\n", tdbio_get_dbname() );
for(i=9+strlen(tdbio_get_dbname()); i > 0; i-- )
putchar('-');
putchar('\n');
for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ )
tdbio_dump_record( &rec, stdout );
}
}
/****************
* Print a list of all defined owner trust value.
*/
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 \"gpgm --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"));
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++ )
printf("%02X", *p );
printf(":%u:\n", (unsigned)rec.r.dir.ownertrust );
}
}
}
void
import_ownertrust( const char *fname )
{
FILE *fp;
int is_stdin=0;
char line[256];
char *p;
size_t n, fprlen;
unsigned otrust;
init_trustdb();
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 ) ) {
TRUSTREC rec;
int rc;
if( !*line || *line == '#' )
continue;
n = strlen(line);
if( line[n-1] != '\n' ) {
log_error_f(fname, _("line too long\n") );
/* ... or last line does not have a LF */
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 ownertrust 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;
repeat:
rc = tdbio_search_dir_byfpr( line, fprlen, 0, &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 );
}
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( pk );
if( !rc )
goto repeat; /* update the ownertrust */
log_error_f(fname, _("insert trust record failed: %s\n"),
g10_errstr(rc) );
}
}
}
else /* error */
log_error_f(fname, _("error finding dir 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();
}

View File

@ -82,7 +82,6 @@ static int is_locked;
static int db_fd = -1;
static int in_transaction;
static void open_db(void);
@ -317,6 +316,7 @@ tdbio_sync()
if( !release_dotlock( lockhandle ) )
is_locked = 0;
}
return 0;
}
@ -608,6 +608,55 @@ 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.
*/
ulong
tdbio_read_modify_stamp( int modify_down )
{
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;
}
void
tdbio_write_modify_stamp( int down, int up )
{
TRUSTREC vr;
int rc;
ulong stamp;
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;
rc = tdbio_write_record( &vr );
if( !rc )
log_fatal( _("%s: error writing version record: %s\n"),
db_name, g10_errstr(rc) );
}
/****************
* Return the record number of the keyhash tbl or create a new one.
*/
@ -936,12 +985,14 @@ 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\n",
"version, kd=%lu, sd=%lu, free=%lu, m/c/d=%d/%d/%d down=%s",
rec->r.ver.keyhashtbl, rec->r.ver.sdirhashtbl,
rec->r.ver.firstfree,
rec->r.ver.marginals,
rec->r.ver.completes,
rec->r.ver.cert_depth );
rec->r.ver.cert_depth,
strtimestamp(rec->r.ver.mod_down) );
fprintf(fp, ", up=%s\n", strtimestamp(rec->r.ver.mod_up) );
break;
case RECTYPE_FREE: fprintf(fp, "free, next=%lu\n", rec->r.free.next );
break;
@ -951,8 +1002,9 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
rec->r.dir.keylist,
rec->r.dir.uidlist,
rec->r.dir.ownertrust );
if( rec->r.dir.dirflags & DIRF_VALVALID )
fprintf( fp, ", v=%02x", rec->r.dir.validity );
if( rec->r.dir.valcheck )
fprintf( fp, ", v=%02x/%s", rec->r.dir.validity,
strtimestamp(rec->r.dir.valcheck) );
if( rec->r.dir.dirflags & DIRF_CHECKED ) {
if( rec->r.dir.dirflags & DIRF_VALID )
fputs(", valid", fp );
@ -987,8 +1039,7 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
rec->r.uid.prefrec,
rec->r.uid.siglist,
rec->r.uid.namehash[18], rec->r.uid.namehash[19]);
if( rec->r.uid.uidflags & UIDF_VALVALID )
fprintf( fp, ", v=%02x", rec->r.uid.validity );
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 );
@ -1113,8 +1164,8 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
rec->r.ver.cert_depth = *p++;
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.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.firstfree =buftoulong(p); p += 4;
rec->r.ver.sdirhashtbl =buftoulong(p); p += 4;
@ -1140,6 +1191,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
rec->r.dir.ownertrust = *p++;
rec->r.dir.dirflags = *p++;
rec->r.dir.validity = *p++;
rec->r.dir.valcheck = buftoulong(p); p += 4;
switch( rec->r.dir.validity ) {
case 0:
case TRUST_UNDEFINED:
@ -1270,8 +1322,8 @@ 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.modified); p += 4;
ulongtobuf(p, rec->r.ver.validated); 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.firstfree ); p += 4;
ulongtobuf(p, rec->r.ver.sdirhashtbl ); p += 4;
@ -1289,6 +1341,7 @@ tdbio_write_record( TRUSTREC *rec )
*p++ = rec->r.dir.ownertrust;
*p++ = rec->r.dir.dirflags;
*p++ = rec->r.dir.validity;
ulongtobuf(p, rec->r.dir.valcheck); p += 4;
assert( rec->r.dir.lid == recnum );
break;
@ -1566,3 +1619,12 @@ tdbio_search_sdir( u32 *keyid, int pubkey_algo, TRUSTREC *rec )
}
void
tdbio_invalid(void)
{
log_error(_(
"The trustdb is corrupted; please run \"gpgm --fix-trustdb\".\n") );
g10_exit(2);
}

View File

@ -52,7 +52,6 @@
/* 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_VALVALID 16 /* The validity field is valid */
#define KEYF_CHECKED 1 /* This key has been checked */
#define KEYF_VALID 2 /* This is a valid (sub)key */
@ -62,7 +61,6 @@
#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 UIDF_VALVALID 16 /* the validity field is valid */
#define SIGF_CHECKED 1 /* signature has been checked - bits 0..6 are valid */
#define SIGF_VALID 2 /* the signature is valid */
@ -83,8 +81,8 @@ struct trust_record {
byte completes;
byte cert_depth;
ulong created; /* timestamp of trustdb creation */
ulong modified; /* timestamp of last modification */
ulong validated; /* timestamp of last validation */
ulong mod_down; /* timestamp of last modification downward */
ulong mod_up; /* timestamp of last modification upward */
ulong keyhashtbl;
ulong firstfree;
ulong sdirhashtbl;
@ -99,7 +97,8 @@ struct trust_record {
ulong cacherec; /* the cache record */
byte ownertrust;
byte dirflags;
byte validity; /* calculated trustlevel over all uids */
byte validity; /* calculated trustlevel over all uids */
ulong valcheck; /* timestamp of last validation check */
} dir;
struct { /* primary public key record */
ulong lid;
@ -176,6 +175,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 down, int up );
int tdbio_is_dirty(void);
int tdbio_sync(void);
int tdbio_begin_transaction(void);
@ -188,5 +189,6 @@ int tdbio_search_dir_byfpr( const byte *fingerprint, size_t fingerlen,
int pubkey_algo, TRUSTREC *rec );
int tdbio_search_sdir( u32 *keyid, int pubkey_algo, TRUSTREC *rec );
void tdbio_invalid(void);
#endif /*G10_TDBIO_H*/

File diff suppressed because it is too large Load Diff

View File

@ -41,14 +41,12 @@
/*-- trustdb.c --*/
void list_trustdb(const char *username);
void list_trust_path( const char *username );
void export_ownertrust(void);
void import_ownertrust(const char *fname);
void register_trusted_key( const char *string );
void check_trustdb( const char *username );
void update_trustdb( void );
int init_trustdb( int level, const char *dbname );
int setup_trustdb( int level, const char *dbname );
void init_trustdb( void );
int check_trust( PKT_public_key *pk, unsigned *r_trustlevel, const byte* nh );
int query_trust_info( PKT_public_key *pk, const byte *nh );
int enum_cert_paths( void **context, ulong *lid,
@ -66,6 +64,12 @@ int clear_trust_checked_flag( PKT_public_key *pk );
int insert_trust_record( PKT_public_key *pk );
int update_trust_record( KBNODE keyblock, int fast, int *modified );
int update_ownertrust( ulong lid, unsigned new_trust );
int trust_letter( unsigned value );
/*-- tdbdump.c --*/
void list_trustdb(const char *username);
void export_ownertrust(void);
void import_ownertrust(const char *fname);
/*-- pkclist.c --*/
int edit_ownertrust( ulong lid, int mode );

View File

@ -7,6 +7,4 @@ missing
gnupg.spec.in
autogen.sh
ChangeLog
ltconfig
ltmain.sh