1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-03 22:48:03 +02:00

Trust stuff works partly.

This commit is contained in:
Werner Koch 1998-01-24 16:32:27 +00:00
parent ea4b6f9db7
commit d71f8bce7e
18 changed files with 590 additions and 125 deletions

86
README
View File

@ -57,15 +57,10 @@
4) You end up with a binary "g10" in /usr/local/bin 4) You end up with a binary "g10" in /usr/local/bin
5) create a directory ".g10" under your hoem directory ("mkdir ~/.g10")
Resources
---------
G10 needs a directory "~/.g10" to store the default keyrings
and other files.
Key Generation Key Generation
-------------- --------------
@ -75,8 +70,9 @@
good random numbers for prime number generation, it uses a /dev/random good random numbers for prime number generation, it uses a /dev/random
which will emit only bytes if the kernel can gather enough entropy. which will emit only bytes if the kernel can gather enough entropy.
If you see no progress, you should start some other activities such If you see no progress, you should start some other activities such
as mouse moves or a "find /". Because we have no hardware device as mouse moves, "find /" or using the keyboard (on another window).
to generate random we have to use this method. Because we have no hardware device to generate random we have to use
this method.
Key generation shows progress by printing different characters to Key generation shows progress by printing different characters to
stderr: stderr:
@ -109,17 +105,18 @@
g10 --sign-key Donald g10 --sign-key Donald
To sign the key of of "Donald" with your default userid This let you sign the key of "Donald" with your default userid.
g10 --sign-key -u Karl -u Joe Donald g10 --sign-key -u Karl -u Joe Donald
To sign the key of of "Donald" with the userids of "Karl" and "Joe". This let you sign the key of of "Donald" with the userids of "Karl"
and "Joe".
All existing signatures are checked, if some are invalid, a menu is All existing signatures are checked, if some are invalid, a menu is
offered to delete some of them, and the you are asked for every user offered to delete some of them, and the you are asked for every user
wether you want to sign this key. wether you want to sign this key.
You may remove a signature at any time by usiing the option "--edit-sig", You may remove a signature at any time using the option "--edit-sig",
which also asks for the sigs to remove. which asks for the sigs to remove.
Sign Sign
@ -166,17 +163,6 @@
Ditto, but sign the file with the user id "Suttner" Ditto, but sign the file with the user id "Suttner"
Examine a data or key file
--------------------------
g10 --list-packets datafile
Use this to list the contents of a data file. If the file is encrypted
you are asked for the passphrase, so that G10 is able to look at the
inner structure of a encrypted packet.
Batch mode Batch mode
---------- ----------
If you use the option "--batch", G10 runs in non-interactive mode and If you use the option "--batch", G10 runs in non-interactive mode and
@ -185,7 +171,7 @@
you can use the option "--passhrase-fd n", which works like PGPs you can use the option "--passhrase-fd n", which works like PGPs
PGPPASSFD. PGPPASSFD.
Batch mode also causes PGP to terminate as soon as a BAD signature is Batch mode also causes G10 to terminate as soon as a BAD signature is
detected. detected.
@ -196,6 +182,56 @@
stderr to get detailed informations about the errors. stderr to get detailed informations about the errors.
Esoteric commands
-----------------
g10 --list-packets datafile
Use this to list the contents of a data file. If the file is encrypted
you are asked for the passphrase, so that G10 is able to look at the
inner structure of a encrypted packet.
--quick-random
Do not use the stroing random generator but a faster one. This can be
used to generate keys for tests; those are marked as insecure.
--list-trustdb
List the contents of the trustdb in a human readable format
--list-trustdb <usernames>
List the tree of certificates for the given usernames
--list-trust-path depth username
List the possible trust paths for the given username, up to the specified
depth. If depth is negative, duplicate introducers are not listed,
because those would increase the trust probabilty only minimal.
(you must use the special option "--" to stop option parsing when
using a negative number)
--print-mds filenames
List all available message digest values for the fiven filenames
--gen-prime n
Generate and print a simple prime number of size n
--gen-prime n q
Generate a prime number suitable for ElGamal signatures of size n with
a q as largest primefactor of n-1.
--gen-prime n q 1
Ditto, but calculate a generator too.
For more options/commands see the file g10/OPTIONS.
Debug Flags Debug Flags
----------- -----------
@ -213,7 +249,7 @@
32 memory allocation stuff 32 memory allocation stuff
64 caching 64 caching
128 show memory statistics at exit 128 show memory statistics at exit
256 trust verification stuff
Other Notes Other Notes

View File

@ -1 +1 @@
0.1.3 0.1.4

View File

@ -50,4 +50,20 @@
@BOTTOM@ @BOTTOM@
/* The AC_CHECK_SIZEOF() fails for some machines.
* we provide some fallback values here */
#if !SIZEOF_UNSIGNED_SHORT
#undef SIZEOF_UNSIGNED_SHORT
#define SIZEOF_UNSIGNED_SHORT 2
#endif
#if !SIZEOF_UNSIGNED_INT
#undef SIZEOF_UNSIGNED_INT
#define SIZEOF_UNSIGNED_INT 4
#endif
#if !SIZEOF_UNSIGNED_LONG
#undef SIZEOF_UNSIGNED_LONG
#define SIZEOF_UNSIGNED_LONG 4
#endif
#endif /*G10_CONFIG_H*/ #endif /*G10_CONFIG_H*/

View File

@ -167,6 +167,10 @@ the OS a chance to collect more entropy! (Need %d more bytes)\n", length );
#else /* not HAVE_DEV_RANDOM */ #else /* not HAVE_DEV_RANDOM */
#ifndef RAND_MAX /* for SunOS */
#define RAND_MAX 32767
#endif
static void static void
fill_buffer( byte *buffer, size_t length, int level ) fill_buffer( byte *buffer, size_t length, int level )
{ {
@ -178,11 +182,20 @@ fill_buffer( byte *buffer, size_t length, int level )
"it compile - it is in no way a strong RNG!\n\n" "it compile - it is in no way a strong RNG!\n\n"
"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n"); "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n");
initialized=1; initialized=1;
#ifdef HAVE_RAND
srand(make_timestamp()*getpid()); srand(make_timestamp()*getpid());
#else
srandom(make_timestamp()*getpid());
#endif
} }
#ifdef HAVE_RAND
while( length-- ) while( length-- )
*buffer++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1); *buffer++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1);
#else
while( length-- )
*buffer++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
#endif
} }
#endif #endif

View File

@ -72,6 +72,9 @@
/* The number of bytes in a unsigned short. */ /* The number of bytes in a unsigned short. */
#undef SIZEOF_UNSIGNED_SHORT #undef SIZEOF_UNSIGNED_SHORT
/* Define if you have the rand function. */
#undef HAVE_RAND
/* Define if you have the stpcpy function. */ /* Define if you have the stpcpy function. */
#undef HAVE_STPCPY #undef HAVE_STPCPY
@ -81,6 +84,9 @@
/* Define if you have the strlwr function. */ /* Define if you have the strlwr function. */
#undef HAVE_STRLWR #undef HAVE_STRLWR
/* Define if you have the strtoul function. */
#undef HAVE_STRTOUL
/* Define if you have the tcgetattr function. */ /* Define if you have the tcgetattr function. */
#undef HAVE_TCGETATTR #undef HAVE_TCGETATTR
@ -91,4 +97,20 @@
#undef HAVE_ZLIB_H #undef HAVE_ZLIB_H
/* The AC_CHECK_SIZEOF() fails for some machines.
* we provide some fallback values here */
#if !SIZEOF_UNSIGNED_SHORT
#undef SIZEOF_UNSIGNED_SHORT
#define SIZEOF_UNSIGNED_SHORT 2
#endif
#if !SIZEOF_UNSIGNED_INT
#undef SIZEOF_UNSIGNED_INT
#define SIZEOF_UNSIGNED_INT 4
#endif
#if !SIZEOF_UNSIGNED_LONG
#undef SIZEOF_UNSIGNED_LONG
#define SIZEOF_UNSIGNED_LONG 4
#endif
#endif /*G10_CONFIG_H*/ #endif /*G10_CONFIG_H*/

View File

@ -8,7 +8,7 @@ AC_CONFIG_AUX_DIR(scripts)
AC_CONFIG_HEADER(config.h) AC_CONFIG_HEADER(config.h)
VERSION=`cat ./VERSION` VERSION=`cat $srcdir/VERSION`
PACKAGE=g10 PACKAGE=g10
AC_SUBST(VERSION) AC_SUBST(VERSION)
AC_SUBST(PACKAGE) AC_SUBST(PACKAGE)
@ -90,10 +90,6 @@ dnl Checks for libraries.
dnl Checks for header files. dnl Checks for header files.
AC_HEADER_STDC AC_HEADER_STDC
AC_CHECK_HEADERS(unistd.h) AC_CHECK_HEADERS(unistd.h)
AC_CHECK_HEADERS(zlib.h,
[LIBS="$LIBS -lz"],
AC_MSG_WARN([zlib missing - creating without ZLIB support!])
)
dnl Checks for typedefs, structures, and compiler characteristics. dnl Checks for typedefs, structures, and compiler characteristics.
@ -150,12 +146,20 @@ AC_CHECK_SIZEOF(unsigned short, 2)
AC_CHECK_SIZEOF(unsigned int, 4) AC_CHECK_SIZEOF(unsigned int, 4)
AC_CHECK_SIZEOF(unsigned long, 4) AC_CHECK_SIZEOF(unsigned long, 4)
if test "$ac_cv_sizeof_unsigned_short" = "0" \
|| test "$ac_cv_sizeof_unsigned_int" = "0" \
|| test "$ac_cv_sizeof_unsigned_long" = "0"; then
AC_MSG_WARN([Hmmm, something is wrong with the sizes - using defaults]);
fi
dnl Checks for library functions. dnl Checks for library functions.
AC_FUNC_VPRINTF AC_FUNC_VPRINTF
AC_CHECK_FUNCS(strerror stpcpy strlwr tcgetattr) AC_CHECK_FUNCS(strerror stpcpy strlwr tcgetattr rand strtoul)
dnl check wether we have a random device dnl check wether we have a random device
AC_CACHE_CHECK(for random device, ac_cv_have_dev_random, AC_CACHE_CHECK(for random device, ac_cv_have_dev_random,
@ -175,8 +179,8 @@ if test "$ac_cv_mpi_config_done" = yes; then
AC_MSG_RESULT(done) AC_MSG_RESULT(done)
else else
ac_cv_mpi_config_done="" ac_cv_mpi_config_done=""
if test -f ./mpi/config.links ; then if test -f $srcdir/mpi/config.links ; then
. ./mpi/config.links . $srcdir/mpi/config.links
ac_cv_mpi_extra_asm_modules="$mpi_extra_modules" ac_cv_mpi_extra_asm_modules="$mpi_extra_modules"
AC_LINK_FILES( ${mpi_ln_src}, ${mpi_ln_dst} ) AC_LINK_FILES( ${mpi_ln_src}, ${mpi_ln_dst} )
ac_cv_mpi_config_done="yes" ac_cv_mpi_config_done="yes"
@ -198,11 +202,18 @@ fi
AC_SUBST(MPI_EXTRA_ASM_OBJS) AC_SUBST(MPI_EXTRA_ASM_OBJS)
dnl Do we have zlib? Must do it here because Solaris failed
dnl when compiling a conftest (due to the "-lz" from LIBS).
AC_CHECK_HEADERS(zlib.h,
[LIBS="$LIBS -lz"],
AC_MSG_WARN([zlib missing - creating without ZLIB support!])
)
dnl checking whether we have other cipher source files dnl checking whether we have other cipher source files
CIPHER_EXTRA_OBJS="" CIPHER_EXTRA_OBJS=""
CIPHER_EXTRA_DIST="" CIPHER_EXTRA_DIST=""
AC_CACHE_CHECK(for extra cipher modules, ac_cv_have_rsa_cipher, AC_CACHE_CHECK(for extra cipher modules, ac_cv_have_rsa_cipher,
[if test -f cipher/rsa.c && test -f cipher/rsa.h; then [if test -f $srcdir/cipher/rsa.c && test -f $srcdir/cipher/rsa.h; then
ac_cv_have_rsa_cipher=yes; else ac_cv_have_rsa_cipher=no; fi]) ac_cv_have_rsa_cipher=yes; else ac_cv_have_rsa_cipher=no; fi])
if test $ac_cv_have_rsa_cipher = yes; then if test $ac_cv_have_rsa_cipher = yes; then
AC_DEFINE(HAVE_RSA_CIPHER) AC_DEFINE(HAVE_RSA_CIPHER)

View File

@ -147,9 +147,11 @@ calc_packet_length( PACKET *pkt )
static int static int
do_comment( IOBUF out, int ctb, PKT_comment *rem ) do_comment( IOBUF out, int ctb, PKT_comment *rem )
{ {
write_header(out, ctb, rem->len); if( !opt.no_comment ) {
if( iobuf_write( out, rem->data, rem->len ) ) write_header(out, ctb, rem->len);
return G10ERR_WRITE_FILE; if( iobuf_write( out, rem->data, rem->len ) )
return G10ERR_WRITE_FILE;
}
return 0; return 0;
} }

View File

@ -57,9 +57,10 @@ write_comment( IOBUF out, const char *s )
KBNODE KBNODE
make_comment_node( const char *s ) make_comment_node( const char *s )
{ {
PACKET *pkt = m_alloc_clear( sizeof *pkt ); PACKET *pkt;
size_t n = strlen(s); size_t n = strlen(s);
pkt = m_alloc_clear( sizeof *pkt );
pkt->pkttype = PKT_COMMENT; pkt->pkttype = PKT_COMMENT;
pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n - 1 ); pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n - 1 );
pkt->pkt.comment->len = n; pkt->pkt.comment->len = n;

View File

@ -190,6 +190,7 @@ main( int argc, char **argv )
{ 531, "list-trustdb",0 , "\r"}, { 531, "list-trustdb",0 , "\r"},
{ 532, "quick-random", 0, "\r"}, { 532, "quick-random", 0, "\r"},
{ 533, "list-trust-path",0, "\r"}, { 533, "list-trust-path",0, "\r"},
{ 534, "no-comment", 0, "do not write comment packets"},
{0} }; {0} };
ARGPARSE_ARGS pargs; ARGPARSE_ARGS pargs;
@ -336,6 +337,7 @@ main( int argc, char **argv )
case 531: set_cmd( &cmd, aListTrustDB); break; case 531: set_cmd( &cmd, aListTrustDB); break;
case 532: quick_random_gen(1); break; case 532: quick_random_gen(1); break;
case 533: set_cmd( &cmd, aListTrustPath); break; case 533: set_cmd( &cmd, aListTrustPath); break;
case 534: opt.no_comment=1; break;
default : errors++; pargs.err = configfp? 1:2; break; default : errors++; pargs.err = configfp? 1:2; break;
} }
} }

View File

@ -39,7 +39,7 @@ struct {
int def_cipher_algo; int def_cipher_algo;
int def_pubkey_algo; int def_pubkey_algo;
int def_digest_algo; int def_digest_algo;
int reserved9; int no_comment;
int reserved10; int reserved10;
int reserved11; int reserved11;
int reserved12; int reserved12;

View File

@ -34,16 +34,35 @@
#include "trustdb.h" #include "trustdb.h"
#include "ttyio.h" #include "ttyio.h"
/****************
* Returns true if a ownertrust has changed.
*/
static int static int
query_ownertrust( PKT_public_cert *pkc ) query_ownertrust( ulong lid )
{ {
char *p; char *p;
int rc;
size_t n; size_t n;
u32 keyid[2]; u32 keyid[2];
PKT_public_cert *pkc ;
int changed=0;
keyid_from_pkc( pkc, keyid ); rc = keyid_from_trustdb( lid, keyid );
tty_printf("No ownertrust specified for:\n" if( rc ) {
"%4u%c/%08lX %s \"", log_error("ooops: can't get keyid for lid %lu\n", lid);
return 0;
}
pkc = m_alloc_clear( sizeof *pkc );
rc = get_pubkey( pkc, keyid );
if( rc ) {
log_error("keyid %08lX: pubkey not found: %s\n",
(ulong)keyid[1], g10_errstr(rc) );
return 0;
}
tty_printf("No ownertrust defined for %lu:\n"
"%4u%c/%08lX %s \"", lid,
nbits_from_pkc( pkc ), pubkey_letter( pkc->pubkey_algo ), nbits_from_pkc( pkc ), pubkey_letter( pkc->pubkey_algo ),
(ulong)keyid[1], datestr_from_pkc( pkc ) ); (ulong)keyid[1], datestr_from_pkc( pkc ) );
p = get_user_id( keyid, &n ); p = get_user_id( keyid, &n );
@ -72,7 +91,16 @@ query_ownertrust( PKT_public_cert *pkc )
"to do with the (implicitly created) web-of-certificates.\n"); "to do with the (implicitly created) web-of-certificates.\n");
} }
else if( !p[1] && (*p >= '1' && *p <= '4') ) { else if( !p[1] && (*p >= '1' && *p <= '4') ) {
/* okay */ 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();
}
if( !update_ownertrust( lid, trust ) )
changed++;
break; break;
} }
else if( *p == 's' || *p == 'S' ) { else if( *p == 's' || *p == 'S' ) {
@ -81,10 +109,53 @@ query_ownertrust( PKT_public_cert *pkc )
m_free(p); p = NULL; m_free(p); p = NULL;
} }
m_free(p); m_free(p);
return 0; m_free(pkc);
return changed;
} }
/****************
* Try to add some more owner trusts (interactive)
* Returns: -1 if no ownertrust were added.
*/
static int
add_ownertrust( PKT_public_cert *pkc )
{
int rc;
void *context = NULL;
ulong lid;
unsigned trust;
int any=0;
tty_printf(
"Could not find a valid trust path to the key. Lets see, wether we\n"
"can assign some missing owner trust values.\n\n");
rc = query_trust_record( pkc );
if( rc ) {
log_error("Ooops: not in trustdb\n");
return -1;
}
lid = pkc->local_id;
while( !(rc=enum_trust_web( &context, &lid )) ) {
rc = get_ownertrust( lid, &trust );
if( rc )
log_fatal("Ooops: couldn't get ownertrust for %lu\n", lid);
if( trust == TRUST_UNDEFINED || trust == TRUST_EXPIRED ||
trust == TRUST_UNKNOWN ) {
if( query_ownertrust( lid ) )
any=1;
}
}
if( rc == -1 )
rc = 0;
enum_trust_web( &context, NULL ); /* close */
return rc? rc : any? 0:-1;
}
/**************** /****************
* Check wether we can trust this pkc which has a trustlevel of TRUSTLEVEL * Check wether we can trust this pkc which has a trustlevel of TRUSTLEVEL
@ -119,7 +190,15 @@ do_we_trust( PKT_public_cert *pkc, int trustlevel )
if( opt.batch || opt.answer_no ) if( opt.batch || opt.answer_no )
log_info("no info to calculate a trust probability\n"); log_info("no info to calculate a trust probability\n");
else { else {
query_ownertrust( pkc ); rc = add_ownertrust( pkc );
if( !rc ) {
rc = check_trust( pkc, &trustlevel );
if( rc )
log_fatal("trust check after add_ownertrust failed: %s\n",
g10_errstr(rc) );
/* FIXME: this is recursive; we better should unroll it */
return do_we_trust( pkc, trustlevel );
}
} }
return 0; /* no */ return 0; /* no */
@ -137,7 +216,7 @@ do_we_trust( PKT_public_cert *pkc, int trustlevel )
return 1; /* yes */ return 1; /* yes */
case TRUST_ULTIMATE: case TRUST_ULTIMATE:
log_info("Our own key is always good.\n"); log_info("Our own keys is always good.\n");
return 1; /* yes */ return 1; /* yes */
default: BUG(); default: BUG();

View File

@ -110,15 +110,28 @@ struct local_id_info {
}; };
typedef struct trust_info TRUST_INFO;
struct trust_info {
ulong lid;
unsigned trust;
};
typedef struct trust_seg_list *TRUST_SEG_LIST; typedef struct trust_seg_list *TRUST_SEG_LIST;
struct trust_seg_list { struct trust_seg_list {
TRUST_SEG_LIST next; TRUST_SEG_LIST next;
int nseg; /* number of segmens */ int nseg; /* number of segmens */
int dup; int dup;
ulong seg[1]; /* segment list */ TRUST_INFO seg[1]; /* segment list */
}; };
typedef struct {
TRUST_SEG_LIST tsl;
int index;
} ENUM_TRUST_WEB_CONTEXT;
static void create_db( const char *fname ); static void create_db( const char *fname );
static void open_db(void); static void open_db(void);
static int read_record( ulong recnum, TRUSTREC *rec ); static int read_record( ulong recnum, TRUSTREC *rec );
@ -134,11 +147,12 @@ static int qry_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned *flag );
static void upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag ); static void upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag );
static void print_user_id( const char *text, u32 *keyid ); static void print_user_id( const char *text, u32 *keyid );
static int do_list_path( ulong *stack, int depth, int max_depth, static int do_list_path( TRUST_INFO *stack, int depth, int max_depth,
LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist ); LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist );
static int list_sigs( ulong pubkey_id ); static int list_sigs( ulong pubkey_id );
static int do_check( ulong pubkeyid, int *trustlevel ); static int propagate_trust( TRUST_SEG_LIST tslist );
static int do_check( ulong pubkeyid, unsigned *trustlevel );
static char *db_name; static char *db_name;
@ -147,6 +161,9 @@ static int db_fd = -1;
* which are the ones from our secrings */ * which are the ones from our secrings */
static LOCAL_ID_INFO *ultikey_table; static LOCAL_ID_INFO *ultikey_table;
static ulong last_trust_web_key;
static TRUST_SEG_LIST last_trust_web_tslist;
#define buftoulong( p ) ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \ #define buftoulong( p ) ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \
(*((byte*)(p)+2) << 8) | (*((byte*)(p)+3))) (*((byte*)(p)+2) << 8) | (*((byte*)(p)+3)))
#define buftoushort( p ) ((*((byte*)(p)) << 8) | (*((byte*)(p)+1))) #define buftoushort( p ) ((*((byte*)(p)) << 8) | (*((byte*)(p)+1)))
@ -642,13 +659,15 @@ void
list_trust_path( int max_depth, const char *username ) list_trust_path( int max_depth, const char *username )
{ {
int rc; int rc;
int wipe=0;
int i; int i;
TRUSTREC rec; TRUSTREC rec;
PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc ); PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
if( max_depth < 0 ) if( max_depth < 0 ) {
max_depth = MAX_LIST_SIGS_DEPTH+1; wipe = 1;
max_depth = -max_depth;
}
if( (rc = get_pubkey_byname( pkc, username )) ) if( (rc = get_pubkey_byname( pkc, username )) )
log_error("user '%s' not found: %s\n", username, g10_errstr(rc) ); log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
@ -658,37 +677,53 @@ list_trust_path( int max_depth, const char *username )
else if( rc == -1 ) else if( rc == -1 )
log_error("user '%s' not in trustdb\n", username); log_error("user '%s' not in trustdb\n", username);
else { else {
LOCAL_ID_INFO *lids;
LOCAL_ID_INFO *work;
ulong stack[MAX_LIST_SIGS_DEPTH];
TRUST_SEG_LIST tsl, tslist = NULL; TRUST_SEG_LIST tsl, tslist = NULL;
lids = new_lid_table(); if( !qry_lid_table_flag( ultikey_table, pkc->local_id, NULL ) ) {
stack[0] = pkc->local_id; tslist = m_alloc( sizeof *tslist );
rc = do_list_path( stack, 1, max_depth, lids, &tslist ); tslist->nseg = 1;
/* wipe out duplicates */ tslist->dup = 0;
work = new_lid_table(); tslist->seg[0].lid = pkc->local_id;
for( tsl=tslist; tsl; tsl = tsl->next ) { tslist->seg[0].trust = 0;
for(i=1; i < tsl->nseg-1; i++ ) { tslist->next = NULL;
if( ins_lid_table_item( work, tsl->seg[i], 0 ) ) { rc = 0;
tsl->dup = 1; /* mark as duplicate */
break;
}
}
} }
release_lid_table(work); else {
LOCAL_ID_INFO *lids = new_lid_table();
TRUST_INFO stack[MAX_LIST_SIGS_DEPTH];
release_lid_table(lids); stack[0].lid = pkc->local_id;
stack[0].trust = 0;
rc = do_list_path( stack, 1, max_depth, lids, &tslist );
if( wipe ) { /* wipe out duplicates */
LOCAL_ID_INFO *work;
work = new_lid_table();
for( tsl=tslist; tsl; tsl = tsl->next ) {
for(i=1; i < tsl->nseg-1; i++ ) {
if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) {
tsl->dup = 1; /* mark as duplicate */
break;
}
}
}
release_lid_table(work);
}
release_lid_table(lids);
}
if( rc ) if( rc )
log_error("user '%s' list problem: %s\n", username, g10_errstr(rc)); log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
rc = propagate_trust( tslist );
if( rc )
log_error("user '%s' trust problem: %s\n", username, g10_errstr(rc));
for(tsl = tslist; tsl; tsl = tsl->next ) { for(tsl = tslist; tsl; tsl = tsl->next ) {
int i; int i;
if( tsl->dup ) if( tsl->dup )
continue; continue;
printf("tslist segs:" ); printf("trust path:" );
for(i=0; i < tsl->nseg; i++ ) for(i=0; i < tsl->nseg; i++ )
printf(" %lu", tsl->seg[i]); printf(" %lu/%02x", tsl->seg[i].lid, tsl->seg[i].trust );
putchar('\n'); putchar('\n');
} }
} }
@ -855,8 +890,7 @@ keyid_from_local_id( ulong lid, u32 *keyid )
/**************** /****************
* Verify, that all our public keys are in the trustDB and marked as * Verify, that all our public keys are in the trustDB.
* ultimately trusted.
*/ */
static int static int
verify_own_certs() verify_own_certs()
@ -866,7 +900,6 @@ verify_own_certs()
PKT_secret_cert *skc = m_alloc_clear( sizeof *skc ); PKT_secret_cert *skc = m_alloc_clear( sizeof *skc );
PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc ); PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
u32 keyid[2]; u32 keyid[2];
int trust;
while( !(rc=enum_secret_keys( &enum_context, skc) ) ) { while( !(rc=enum_secret_keys( &enum_context, skc) ) ) {
/* fixed: to be sure that it is a secret key of our own, /* fixed: to be sure that it is a secret key of our own,
@ -895,23 +928,21 @@ verify_own_certs()
rc = G10ERR_GENERAL; rc = G10ERR_GENERAL;
goto leave; goto leave;
} }
/* look into the trustdb */
rc = check_trust( pkc, &trust ); /* make sure that the pubkey is in the trustdb */
if( rc ) { rc = query_trust_record( pkc );
log_info("keyid %08lX: problem in trustdb: %s\n", (ulong)keyid[1], if( rc == -1 ) { /* put it into the trustdb */
g10_errstr(rc) );
goto leave;
}
if( trust == TRUST_UNKNOWN ) {
rc = insert_trust_record( pkc ); rc = insert_trust_record( pkc );
if( rc ) if( rc ) {
log_error("keyid %08lX: insert failed: %s\n", log_error("keyid %08lX: can't put it into the trustdb\n",
(ulong)keyid[1], g10_errstr(rc) ); (ulong)keyid[1] );
else goto leave;
log_info("keyid %08lX: inserted\n", (ulong)keyid[1] ); }
} }
else { else if( rc ) {
/* FIXME: we should chek the other values */ log_error("keyid %08lX: query record failed\n", (ulong)keyid[1] );
goto leave;
} }
if( DBG_TRUST ) if( DBG_TRUST )
@ -921,6 +952,7 @@ verify_own_certs()
log_error("keyid %08lX: already in ultikey_table\n", log_error("keyid %08lX: already in ultikey_table\n",
(ulong)keyid[1]); (ulong)keyid[1]);
release_secret_cert_parts( skc ); release_secret_cert_parts( skc );
release_public_cert_parts( pkc ); release_public_cert_parts( pkc );
} }
@ -1042,7 +1074,7 @@ list_sigs( ulong pubkey_id )
static int static int
do_list_path( ulong *stack, int depth, int max_depth, do_list_path( TRUST_INFO *stack, int depth, int max_depth,
LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist ) LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist )
{ {
SIGREC_CONTEXT sx; SIGREC_CONTEXT sx;
@ -1057,12 +1089,13 @@ do_list_path( ulong *stack, int depth, int max_depth,
return 0; return 0;
} }
memset( &sx, 0, sizeof sx ); memset( &sx, 0, sizeof sx );
sx.pubkey_id = stack[depth-1]; sx.pubkey_id = stack[depth-1].lid;
while( !(rc = walk_sigrecs( &sx )) ) { while( !(rc = walk_sigrecs( &sx )) ) {
TRUST_SEG_LIST tsl, t2, tl; TRUST_SEG_LIST tsl, t2, tl;
int i; int i;
stack[depth] = sx.sig_id; stack[depth].lid = sx.sig_id;
stack[depth].trust = 0;
if( qry_lid_table_flag( lids, sx.sig_id, &last_depth) ) { if( qry_lid_table_flag( lids, sx.sig_id, &last_depth) ) {
/*printf("%2lu/%d: marked\n", sx.sig_id, depth );*/ /*printf("%2lu/%d: marked\n", sx.sig_id, depth );*/
ins_lid_table_item( lids, sx.sig_id, depth); ins_lid_table_item( lids, sx.sig_id, depth);
@ -1078,7 +1111,7 @@ do_list_path( ulong *stack, int depth, int max_depth,
/*printf("%2lu/%d: already visited\n", sx.sig_id, depth)*/; /*printf("%2lu/%d: already visited\n", sx.sig_id, depth)*/;
else if( !qry_lid_table_flag( ultikey_table, sx.sig_id, NULL ) ) { else if( !qry_lid_table_flag( ultikey_table, sx.sig_id, NULL ) ) {
/* found end of path; store it, ordered by path length */ /* found end of path; store it, ordered by path length */
tsl = m_alloc( sizeof *tsl + depth*sizeof(ulong) ); tsl = m_alloc( sizeof *tsl + depth*sizeof(TRUST_INFO) );
tsl->nseg = depth+1; tsl->nseg = depth+1;
tsl->dup = 0; tsl->dup = 0;
for(i=0; i <= depth; i++ ) for(i=0; i <= depth; i++ )
@ -1268,19 +1301,110 @@ build_sigrecs( ulong pubkeyid )
return rc; return rc;
} }
/****************
* Make a list of trust paths
*/
static int
make_tsl( ulong pubkey_id, TRUST_SEG_LIST *ret_tslist )
{
int i, rc;
LOCAL_ID_INFO *lids = new_lid_table();
TRUST_INFO stack[MAX_LIST_SIGS_DEPTH];
TRUST_SEG_LIST tsl, tslist;
int max_depth = 4;
tslist = *ret_tslist = NULL;
if( !qry_lid_table_flag( ultikey_table, pubkey_id, NULL ) ) {
tslist = m_alloc( sizeof *tslist );
tslist->nseg = 1;
tslist->dup = 0;
tslist->seg[0].lid = pubkey_id;
tslist->seg[0].trust = 0;
tslist->next = NULL;
rc = 0;
}
else {
stack[0].lid = pubkey_id;
stack[0].trust = 0;
rc = do_list_path( stack, 1, max_depth, lids, &tslist );
}
if( !rc ) { /* wipe out duplicates */
LOCAL_ID_INFO *work = new_lid_table();
for( tsl=tslist; tsl; tsl = tsl->next ) {
for(i=1; i < tsl->nseg-1; i++ ) {
if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) {
tsl->dup = 1; /* mark as duplicate */
break;
}
}
}
release_lid_table(work);
*ret_tslist = tslist;
}
else
; /* FIXME: release tslist */
release_lid_table(lids);
return rc;
}
/**************** /****************
* Given a trust segment list tslist, walk over all paths and fill in
* the trust information for each segment. What this function does is
* to assign a trustvalue to the first segment (which is the requested key)
* of each path.
* *
* FIXME: We have to do more thinks here. e.g. we should never increase
* the trust value.
*
* Do not do it for duplicates.
*/ */
static int static int
do_check( ulong pubkeyid, int *trustlevel ) propagate_trust( TRUST_SEG_LIST tslist )
{ {
int rc=0; int i, rc;
unsigned trust;
TRUST_SEG_LIST tsl;
for(tsl = tslist; tsl; tsl = tsl->next ) {
if( tsl->dup )
continue;
assert( tsl->nseg );
/* the last segment is always a ultimately trusted one, so we can
* assign a fully trust to the next one */
i = tsl->nseg-1;
tsl->seg[i].trust = TRUST_ULTIMATE;
trust = TRUST_FULLY;
for(i-- ; i >= 0; i-- ) {
tsl->seg[i].trust = trust;
if( i > 0 ) {
/* get the trust of this pubkey */
rc = get_ownertrust( tsl->seg[i].lid, &trust );
if( rc )
return rc;
}
}
}
return 0;
}
/****************
* we have the pubkey record but nothing more is known
*/
static int
do_check( ulong pubkeyid, unsigned *trustlevel )
{
int i, rc=0;
ulong rnum; ulong rnum;
TRUSTREC rec; TRUSTREC rec;
TRUST_SEG_LIST tsl, tsl2, tslist;
int marginal, fully;
int fully_needed = 4;
int marginal_needed = 6;
*trustlevel = TRUST_UNDEFINED;
/* verify the cache */ /* verify the cache */
@ -1294,11 +1418,64 @@ do_check( ulong pubkeyid, int *trustlevel )
if( rc ) if( rc )
return rc; /* error while looking for sigrec or building sigrecs */ return rc; /* error while looking for sigrec or building sigrecs */
/* fixme: take it from the cache if it is valid */
/* Make a list of all possible trust-paths */
rc = make_tsl( pubkeyid, &tslist );
if( rc )
return rc;
rc = propagate_trust( tslist );
if( rc )
return rc;
for(tsl = tslist; tsl; tsl = tsl->next ) {
if( tsl->dup )
continue;
log_debug("tslist segs:" );
for(i=0; i < tsl->nseg; i++ )
fprintf(stderr, " %lu/%02x", tsl->seg[i].lid, tsl->seg[i].trust );
putc('\n',stderr);
}
/* and look wether there is a trusted path.
* We only have to look at the first segment, because
* propagate_trust has investigated all other segments */
marginal = fully = 0;
for(tsl = tslist; tsl; tsl = tsl->next ) {
if( tsl->dup )
continue;
if( tsl->seg[0].trust == TRUST_ULTIMATE ) {
*trustlevel = TRUST_ULTIMATE; /* our own key */
break;
}
if( tsl->seg[0].trust == TRUST_FULLY ) {
marginal++;
fully++;
}
else if( tsl->seg[0].trust == TRUST_MARGINAL )
marginal++;
if( fully >= fully_needed ) {
*trustlevel = TRUST_FULLY;
break;
}
}
if( !tsl && marginal >= marginal_needed )
*trustlevel = TRUST_MARGINAL;
/* cache the tslist */
if( last_trust_web_key ) {
for( tsl = last_trust_web_tslist; tsl; tsl = tsl2 ) {
tsl2 = tsl->next;
m_free(tsl);
}
}
last_trust_web_key = pubkeyid;
last_trust_web_tslist = tslist;
return 0; return 0;
} }
/********************************************************* /*********************************************************
**************** API Interface ************************ **************** API Interface ************************
*********************************************************/ *********************************************************/
@ -1375,10 +1552,10 @@ init_trustdb( int level )
* is not necessary to check this if we use a local pubring. Hmmmm. * is not necessary to check this if we use a local pubring. Hmmmm.
*/ */
int int
check_trust( PKT_public_cert *pkc, int *r_trustlevel ) check_trust( PKT_public_cert *pkc, unsigned *r_trustlevel )
{ {
TRUSTREC rec; TRUSTREC rec;
int trustlevel = TRUST_UNKNOWN; unsigned trustlevel = TRUST_UNKNOWN;
int rc=0; int rc=0;
if( DBG_TRUST ) if( DBG_TRUST )
@ -1409,10 +1586,6 @@ check_trust( PKT_public_cert *pkc, int *r_trustlevel )
log_error("check_trust: do_check failed: %s\n", g10_errstr(rc)); log_error("check_trust: do_check failed: %s\n", g10_errstr(rc));
return rc; return rc;
} }
if( !rec.r.pubkey.ownertrust )
trustlevel = TRUST_UNDEFINED;
else
trustlevel = TRUST_EXPIRED;
leave: leave:
@ -1423,29 +1596,109 @@ check_trust( PKT_public_cert *pkc, int *r_trustlevel )
} }
/****************
* Enumerate all keys, which are needed to build all trust paths for
* the given key. This function dies not return the key itself or
* the ultimate key.
*
* 1) create a void pointer and initialize it to NULL
* 2) pass this void pointer by reference to this function.
* Set lid to the key you want to enumerate and pass it by reference.
* 3) call this function as long as it does not return -1
* to indicate EOF. LID does contain the next key used to build the web
* 4) Always call this function a last time with LID set to NULL,
* so that it can free it's context.
*/
int int
get_ownertrust( PKT_public_cert *pkc, int *r_otrust ) enum_trust_web( void **context, ulong *lid )
{
ENUM_TRUST_WEB_CONTEXT *c = *context;
if( !c ) { /* make a new context */
c = m_alloc_clear( sizeof *c );
*context = c;
if( *lid != last_trust_web_key )
log_bug("enum_trust_web: nyi\n");
c->tsl = last_trust_web_tslist;
c->index = 1;
}
if( !lid ) { /* free the context */
m_free( c );
*context = NULL;
return 0;
}
while( c->tsl ) {
if( !c->tsl->dup && c->index < c->tsl->nseg-1 ) {
*lid = c->tsl->seg[c->index].lid;
c->index++;
return 0;
}
c->index = 1;
c->tsl = c->tsl->next;
}
return -1; /* eof */
}
/****************
* Return the assigned ownertrust value for the given LID
*/
int
get_ownertrust( ulong lid, unsigned *r_otrust )
{ {
TRUSTREC rec; TRUSTREC rec;
int rc;
/* get the pubkey record */ if( read_record( lid, &rec ) ) {
log_error("get_ownertrust: read record failed\n");
return G10ERR_TRUSTDB;
}
if( r_otrust )
*r_otrust = rec.r.pubkey.ownertrust;
return 0;
}
int
keyid_from_trustdb( ulong lid, u32 *keyid )
{
TRUSTREC rec;
if( read_record( lid, &rec ) ) {
log_error("keyid_from_trustdb: read record failed\n");
return G10ERR_TRUSTDB;
}
if( keyid ) {
keyid[0] = rec.r.pubkey.keyid[0];
keyid[1] = rec.r.pubkey.keyid[1];
}
return 0;
}
int
query_trust_record( PKT_public_cert *pkc )
{
TRUSTREC rec;
int rc=0;
if( pkc->local_id ) { if( pkc->local_id ) {
if( read_record( pkc->local_id, &rec ) ) { if( read_record( pkc->local_id, &rec ) ) {
log_error("get_ownertrust: read record failed\n"); log_error("query_trust_record: read record failed\n");
return G10ERR_TRUSTDB; return G10ERR_TRUSTDB;
} }
} }
else { /* no local_id: scan the trustdb */ else { /* no local_id: scan the trustdb */
if( (rc=scan_record_by_pkc( pkc, &rec, 2 )) && rc != -1 ) { if( (rc=scan_record_by_pkc( pkc, &rec, 2 )) && rc != -1 ) {
log_error("get_ownertrust: scan_record_by_pkc(2) failed: %s\n", log_error("query_trust_record: scan_record_by_pkc(2) failed: %s\n",
g10_errstr(rc)); g10_errstr(rc));
return rc; return rc;
} }
else if( rc == -1 ) else if( rc == -1 )
return rc; return rc;
} }
*r_otrust = rec.r.pubkey.ownertrust;
return 0; return 0;
} }
@ -1494,23 +1747,23 @@ insert_trust_record( PKT_public_cert *pkc )
int int
update_trust_record( PKT_public_cert *pkc, int new_trust ) update_ownertrust( ulong lid, unsigned new_trust )
{ {
TRUSTREC rec; TRUSTREC rec;
ulong recnum;
if( read_record( lid, &rec ) ) {
assert( pkc->local_id ); log_error("update_ownertrust: read failed\n");
if( read_record( pkc->local_id, &rec ) ) {
log_error("update_trust_record: read failed\n");
return G10ERR_TRUSTDB; return G10ERR_TRUSTDB;
} }
/* check keyid, fingerprint etc ? */ /* check keyid, fingerprint etc ? */
if( rec.rectype != 2 ) {
log_error("update_ownertrust: invalid record type\n");
return G10ERR_TRUSTDB;
}
rec.r.pubkey.ownertrust = 0; rec.r.pubkey.ownertrust = new_trust;
if( write_record( recnum, &rec ) ) { if( write_record( lid, &rec ) ) {
log_error("insert_trust_record: write failed\n"); log_error("update_ownertrust: write failed\n");
return G10ERR_TRUSTDB; return G10ERR_TRUSTDB;
} }

View File

@ -36,9 +36,13 @@
void list_trustdb(const char *username); void list_trustdb(const char *username);
void list_trust_path( int max_depth, const char *username ); void list_trust_path( int max_depth, const char *username );
int init_trustdb( int level ); int init_trustdb( int level );
int check_trust( PKT_public_cert *pkc, int *r_trustlevel ); int check_trust( PKT_public_cert *pkc, unsigned *r_trustlevel );
int get_ownertrust( PKT_public_cert *pkc, int *r_otrust ); int enum_trust_web( void **context, ulong *lid );
int get_ownertrust( ulong lid, unsigned *r_otrust );
int keyid_from_trustdb( ulong lid, u32 *keyid );
int query_trust_record( PKT_public_cert *pkc );
int insert_trust_record( PKT_public_cert *pkc ); int insert_trust_record( PKT_public_cert *pkc );
int update_ownertrust( ulong lid, unsigned new_trust );
int verify_private_data(void); int verify_private_data(void);
int sign_private_data(void); int sign_private_data(void);

View File

@ -54,7 +54,7 @@ struct iobuf_struct {
IOBUF chain; /* next iobuf used for i/o if any (passed to filter) */ IOBUF chain; /* next iobuf used for i/o if any (passed to filter) */
int no, subno; int no, subno;
const char *desc; const char *desc;
void *opaque; /* can be used to old any information */ void *opaque; /* can be used to hold any information */
/* this value is copied to all instances */ /* this value is copied to all instances */
}; };

View File

@ -121,7 +121,9 @@ char *stpcpy(char *a,const char *b);
#ifndef HAVE_STRLWR #ifndef HAVE_STRLWR
char *strlwr(char *a); char *strlwr(char *a);
#endif #endif
#ifndef HAVE_STRTOUL
#define strtoul(a,b,c) ((unsigned long)strtol((a),(b),(c)))
#endif
/******** some macros ************/ /******** some macros ************/
#ifndef STR #ifndef STR

View File

@ -1,4 +1,5 @@
/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. /* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
Note: I added some stuff for use with g10
Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc. Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
@ -1440,6 +1441,7 @@ extern
const const
#endif #endif
unsigned char __clz_tab[]; unsigned char __clz_tab[];
#define MPI_INTERNAL_NEED_CLZ_TAB 1
#define count_leading_zeros(count, x) \ #define count_leading_zeros(count, x) \
do { \ do { \
UWtype __xr = (x); \ UWtype __xr = (x); \

View File

@ -26,6 +26,28 @@
#include "longlong.h" #include "longlong.h"
#ifdef MPI_INTERNAL_NEED_CLZ_TAB
unsigned char
__clz_tab[] =
{
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
};
#endif
/**************** /****************
* Return the number of bits in A. * Return the number of bits in A.
*/ */

View File

@ -286,7 +286,7 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
else if( state == 3 ) { /* skip leading spaces of the argument */ else if( state == 3 ) { /* skip leading spaces of the argument */
if( !isspace(c) ) { if( !isspace(c) ) {
i = 0; i = 0;
keyword[i] = c; keyword[i++] = c;
state = 4; state = 4;
} }
} }