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
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
--------------
@ -75,8 +70,9 @@
good random numbers for prime number generation, it uses a /dev/random
which will emit only bytes if the kernel can gather enough entropy.
If you see no progress, you should start some other activities such
as mouse moves or a "find /". Because we have no hardware device
to generate random we have to use this method.
as mouse moves, "find /" or using the keyboard (on another window).
Because we have no hardware device to generate random we have to use
this method.
Key generation shows progress by printing different characters to
stderr:
@ -109,17 +105,18 @@
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
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
offered to delete some of them, and the you are asked for every user
wether you want to sign this key.
You may remove a signature at any time by usiing the option "--edit-sig",
which also asks for the sigs to remove.
You may remove a signature at any time using the option "--edit-sig",
which asks for the sigs to remove.
Sign
@ -166,17 +163,6 @@
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
----------
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
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.
@ -196,6 +182,56 @@
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
-----------
@ -213,7 +249,7 @@
32 memory allocation stuff
64 caching
128 show memory statistics at exit
256 trust verification stuff
Other Notes

View File

@ -1 +1 @@
0.1.3
0.1.4

View File

@ -50,4 +50,20 @@
@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*/

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 */
#ifndef RAND_MAX /* for SunOS */
#define RAND_MAX 32767
#endif
static void
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"
"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n");
initialized=1;
#ifdef HAVE_RAND
srand(make_timestamp()*getpid());
#else
srandom(make_timestamp()*getpid());
#endif
}
#ifdef HAVE_RAND
while( length-- )
*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

View File

@ -72,6 +72,9 @@
/* The number of bytes in a unsigned short. */
#undef SIZEOF_UNSIGNED_SHORT
/* Define if you have the rand function. */
#undef HAVE_RAND
/* Define if you have the stpcpy function. */
#undef HAVE_STPCPY
@ -81,6 +84,9 @@
/* Define if you have the strlwr function. */
#undef HAVE_STRLWR
/* Define if you have the strtoul function. */
#undef HAVE_STRTOUL
/* Define if you have the tcgetattr function. */
#undef HAVE_TCGETATTR
@ -91,4 +97,20 @@
#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*/

View File

@ -8,7 +8,7 @@ AC_CONFIG_AUX_DIR(scripts)
AC_CONFIG_HEADER(config.h)
VERSION=`cat ./VERSION`
VERSION=`cat $srcdir/VERSION`
PACKAGE=g10
AC_SUBST(VERSION)
AC_SUBST(PACKAGE)
@ -90,10 +90,6 @@ dnl Checks for libraries.
dnl Checks for header files.
AC_HEADER_STDC
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.
@ -150,12 +146,20 @@ AC_CHECK_SIZEOF(unsigned short, 2)
AC_CHECK_SIZEOF(unsigned int, 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.
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
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)
else
ac_cv_mpi_config_done=""
if test -f ./mpi/config.links ; then
. ./mpi/config.links
if test -f $srcdir/mpi/config.links ; then
. $srcdir/mpi/config.links
ac_cv_mpi_extra_asm_modules="$mpi_extra_modules"
AC_LINK_FILES( ${mpi_ln_src}, ${mpi_ln_dst} )
ac_cv_mpi_config_done="yes"
@ -198,11 +202,18 @@ fi
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
CIPHER_EXTRA_OBJS=""
CIPHER_EXTRA_DIST=""
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])
if test $ac_cv_have_rsa_cipher = yes; then
AC_DEFINE(HAVE_RSA_CIPHER)

View File

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

View File

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

View File

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

View File

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

View File

@ -34,16 +34,35 @@
#include "trustdb.h"
#include "ttyio.h"
/****************
* Returns true if a ownertrust has changed.
*/
static int
query_ownertrust( PKT_public_cert *pkc )
query_ownertrust( ulong lid )
{
char *p;
int rc;
size_t n;
u32 keyid[2];
PKT_public_cert *pkc ;
int changed=0;
keyid_from_pkc( pkc, keyid );
tty_printf("No ownertrust specified for:\n"
"%4u%c/%08lX %s \"",
rc = keyid_from_trustdb( lid, keyid );
if( rc ) {
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 ),
(ulong)keyid[1], datestr_from_pkc( pkc ) );
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");
}
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;
}
else if( *p == 's' || *p == 'S' ) {
@ -81,10 +109,53 @@ query_ownertrust( PKT_public_cert *pkc )
m_free(p); p = NULL;
}
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
@ -119,7 +190,15 @@ do_we_trust( PKT_public_cert *pkc, int trustlevel )
if( opt.batch || opt.answer_no )
log_info("no info to calculate a trust probability\n");
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 */
@ -137,7 +216,7 @@ do_we_trust( PKT_public_cert *pkc, int trustlevel )
return 1; /* yes */
case TRUST_ULTIMATE:
log_info("Our own key is always good.\n");
log_info("Our own keys is always good.\n");
return 1; /* yes */
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;
struct trust_seg_list {
TRUST_SEG_LIST next;
int nseg; /* number of segmens */
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 open_db(void);
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 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 );
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;
@ -147,6 +161,9 @@ static int db_fd = -1;
* which are the ones from our secrings */
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) | \
(*((byte*)(p)+2) << 8) | (*((byte*)(p)+3)))
#define buftoushort( p ) ((*((byte*)(p)) << 8) | (*((byte*)(p)+1)))
@ -642,13 +659,15 @@ void
list_trust_path( int max_depth, const char *username )
{
int rc;
int wipe=0;
int i;
TRUSTREC rec;
PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
if( max_depth < 0 )
max_depth = MAX_LIST_SIGS_DEPTH+1;
if( max_depth < 0 ) {
wipe = 1;
max_depth = -max_depth;
}
if( (rc = get_pubkey_byname( pkc, username )) )
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 )
log_error("user '%s' not in trustdb\n", username);
else {
LOCAL_ID_INFO *lids;
LOCAL_ID_INFO *work;
ulong stack[MAX_LIST_SIGS_DEPTH];
TRUST_SEG_LIST tsl, tslist = NULL;
lids = new_lid_table();
stack[0] = pkc->local_id;
rc = do_list_path( stack, 1, max_depth, lids, &tslist );
/* wipe out duplicates */
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], 0 ) ) {
tsl->dup = 1; /* mark as duplicate */
break;
}
}
if( !qry_lid_table_flag( ultikey_table, pkc->local_id, NULL ) ) {
tslist = m_alloc( sizeof *tslist );
tslist->nseg = 1;
tslist->dup = 0;
tslist->seg[0].lid = pkc->local_id;
tslist->seg[0].trust = 0;
tslist->next = NULL;
rc = 0;
}
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 )
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 ) {
int i;
if( tsl->dup )
continue;
printf("tslist segs:" );
printf("trust path:" );
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');
}
}
@ -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
* ultimately trusted.
* Verify, that all our public keys are in the trustDB.
*/
static int
verify_own_certs()
@ -866,7 +900,6 @@ verify_own_certs()
PKT_secret_cert *skc = m_alloc_clear( sizeof *skc );
PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
u32 keyid[2];
int trust;
while( !(rc=enum_secret_keys( &enum_context, skc) ) ) {
/* fixed: to be sure that it is a secret key of our own,
@ -895,23 +928,21 @@ verify_own_certs()
rc = G10ERR_GENERAL;
goto leave;
}
/* look into the trustdb */
rc = check_trust( pkc, &trust );
if( rc ) {
log_info("keyid %08lX: problem in trustdb: %s\n", (ulong)keyid[1],
g10_errstr(rc) );
goto leave;
}
if( trust == TRUST_UNKNOWN ) {
/* make sure that the pubkey is in the trustdb */
rc = query_trust_record( pkc );
if( rc == -1 ) { /* put it into the trustdb */
rc = insert_trust_record( pkc );
if( rc )
log_error("keyid %08lX: insert failed: %s\n",
(ulong)keyid[1], g10_errstr(rc) );
else
log_info("keyid %08lX: inserted\n", (ulong)keyid[1] );
if( rc ) {
log_error("keyid %08lX: can't put it into the trustdb\n",
(ulong)keyid[1] );
goto leave;
}
}
else {
/* FIXME: we should chek the other values */
else if( rc ) {
log_error("keyid %08lX: query record failed\n", (ulong)keyid[1] );
goto leave;
}
if( DBG_TRUST )
@ -921,6 +952,7 @@ verify_own_certs()
log_error("keyid %08lX: already in ultikey_table\n",
(ulong)keyid[1]);
release_secret_cert_parts( skc );
release_public_cert_parts( pkc );
}
@ -1042,7 +1074,7 @@ list_sigs( ulong pubkey_id )
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 )
{
SIGREC_CONTEXT sx;
@ -1057,12 +1089,13 @@ do_list_path( ulong *stack, int depth, int max_depth,
return 0;
}
memset( &sx, 0, sizeof sx );
sx.pubkey_id = stack[depth-1];
sx.pubkey_id = stack[depth-1].lid;
while( !(rc = walk_sigrecs( &sx )) ) {
TRUST_SEG_LIST tsl, t2, tl;
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) ) {
/*printf("%2lu/%d: marked\n", 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)*/;
else if( !qry_lid_table_flag( ultikey_table, sx.sig_id, NULL ) ) {
/* 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->dup = 0;
for(i=0; i <= depth; i++ )
@ -1268,19 +1301,110 @@ build_sigrecs( ulong pubkeyid )
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
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;
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 */
@ -1294,11 +1418,64 @@ do_check( ulong pubkeyid, int *trustlevel )
if( rc )
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;
}
/*********************************************************
**************** API Interface ************************
*********************************************************/
@ -1375,10 +1552,10 @@ init_trustdb( int level )
* is not necessary to check this if we use a local pubring. Hmmmm.
*/
int
check_trust( PKT_public_cert *pkc, int *r_trustlevel )
check_trust( PKT_public_cert *pkc, unsigned *r_trustlevel )
{
TRUSTREC rec;
int trustlevel = TRUST_UNKNOWN;
unsigned trustlevel = TRUST_UNKNOWN;
int rc=0;
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));
return rc;
}
if( !rec.r.pubkey.ownertrust )
trustlevel = TRUST_UNDEFINED;
else
trustlevel = TRUST_EXPIRED;
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
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;
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( 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;
}
}
else { /* no local_id: scan the trustdb */
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));
return rc;
}
else if( rc == -1 )
return rc;
}
*r_otrust = rec.r.pubkey.ownertrust;
return 0;
}
@ -1494,23 +1747,23 @@ insert_trust_record( PKT_public_cert *pkc )
int
update_trust_record( PKT_public_cert *pkc, int new_trust )
update_ownertrust( ulong lid, unsigned new_trust )
{
TRUSTREC rec;
ulong recnum;
assert( pkc->local_id );
if( read_record( pkc->local_id, &rec ) ) {
log_error("update_trust_record: read failed\n");
if( read_record( lid, &rec ) ) {
log_error("update_ownertrust: read failed\n");
return G10ERR_TRUSTDB;
}
/* check keyid, fingerprint etc ? */
if( rec.rectype != 2 ) {
log_error("update_ownertrust: invalid record type\n");
return G10ERR_TRUSTDB;
}
rec.r.pubkey.ownertrust = 0;
if( write_record( recnum, &rec ) ) {
log_error("insert_trust_record: write failed\n");
rec.r.pubkey.ownertrust = new_trust;
if( write_record( lid, &rec ) ) {
log_error("update_ownertrust: write failed\n");
return G10ERR_TRUSTDB;
}

View File

@ -36,9 +36,13 @@
void list_trustdb(const char *username);
void list_trust_path( int max_depth, const char *username );
int init_trustdb( int level );
int check_trust( PKT_public_cert *pkc, int *r_trustlevel );
int get_ownertrust( PKT_public_cert *pkc, int *r_otrust );
int check_trust( PKT_public_cert *pkc, unsigned *r_trustlevel );
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 update_ownertrust( ulong lid, unsigned new_trust );
int verify_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) */
int no, subno;
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 */
};

View File

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

View File

@ -1,4 +1,5 @@
/* 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.
@ -1440,6 +1441,7 @@ extern
const
#endif
unsigned char __clz_tab[];
#define MPI_INTERNAL_NEED_CLZ_TAB 1
#define count_leading_zeros(count, x) \
do { \
UWtype __xr = (x); \

View File

@ -26,6 +26,28 @@
#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.
*/

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 */
if( !isspace(c) ) {
i = 0;
keyword[i] = c;
keyword[i++] = c;
state = 4;
}
}