1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

See ChangeLog: Wed Feb 10 17:15:39 CET 1999 Werner Koch

This commit is contained in:
Werner Koch 1999-02-10 16:22:40 +00:00
parent a16e15282a
commit 9a4f506a18
60 changed files with 2006 additions and 1340 deletions

View file

@ -1,3 +1,25 @@
Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* g10.c (main): check for development version now in configure
* tdbio.c (tdbio_write_record): Add uid.validity
(tdbio_read_record) : Ditto.
(tdbio_dump_record) : Ditto.
* keygen.c (keygen_add_std_prefs): Replaced Blowfish by Twofish,
removed MD5 and Tiger.
* pubkey-enc.c (get_it): Suppress warning about missing Blowfish
in preferences in certain cases.
* ringedit.c (lock_rentry,unlock_rentry): New.
* getkey.c (key_byname): Pass ret_kb down to lookup_xx.
* armor.c (armor_filter): No output of of empty comment lines.
Add option --no-version to suppress the output of the version string.
* getkey.c: Release the getkey context for auto context variables.
Sun Jan 24 18:16:26 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* getkey.c: Changed the internal design to allow simultaneous

View file

@ -876,23 +876,26 @@ armor_filter( void *opaque, int control,
iobuf_writestr(a, "-----");
iobuf_writestr(a, head_strings[afx->what] );
iobuf_writestr(a, "-----\n");
iobuf_writestr(a, "Version: GnuPG v" VERSION " ("
PRINTABLE_OS_NAME ")\n");
if( !opt.no_version )
iobuf_writestr(a, "Version: GnuPG v" VERSION " ("
PRINTABLE_OS_NAME ")\n");
if( opt.comment_string ) {
const char *s = opt.comment_string;
iobuf_writestr(a, "Comment: " );
for( ; *s; s++ ) {
if( *s == '\n' )
iobuf_writestr(a, "\\n" );
else if( *s == '\r' )
iobuf_writestr(a, "\\r" );
else if( *s == '\v' )
iobuf_writestr(a, "\\v" );
else
iobuf_put(a, *s );
if( *s ) {
iobuf_writestr(a, "Comment: " );
for( ; *s; s++ ) {
if( *s == '\n' )
iobuf_writestr(a, "\\n" );
else if( *s == '\r' )
iobuf_writestr(a, "\\r" );
else if( *s == '\v' )
iobuf_writestr(a, "\\v" );
else
iobuf_put(a, *s );
}
iobuf_put(a, '\n' );
}
iobuf_put(a, '\n' );
}
else
iobuf_writestr(a,

View file

@ -117,6 +117,7 @@ enum cmd_and_opt_values { aNull = 0,
oDebugAll,
oStatusFD,
oNoComment,
oNoVersion,
oCompletesNeeded,
oMarginalsNeeded,
oMaxCertDepth,
@ -307,6 +308,7 @@ static ARGPARSE_OPTS opts[] = {
{ oRunAsShmCP, "run-as-shm-coprocess", 4, "@" },
{ oSetFilename, "set-filename", 2, "@" },
{ oComment, "comment", 2, "@" },
{ oNoVersion, "no-version", 0, "@"},
{ oNotDashEscaped, "not-dash-escaped", 0, "@" },
{ oEscapeFrom, "escape-from-lines", 0, "@" },
{ oLockOnce, "lock-once", 0, "@" },
@ -716,6 +718,7 @@ main( int argc, char **argv )
opt.verbose = 0; opt.list_sigs=0; break;
case oQuickRandom: quick_random_gen(1); break;
case oNoComment: opt.no_comment=1; break;
case oNoVersion: opt.no_version=1; break;
case oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break;
case oMarginalsNeeded: opt.marginals_needed = pargs.r.ret_int; break;
case oMaxCertDepth: opt.max_cert_depth = pargs.r.ret_int; break;
@ -810,6 +813,9 @@ main( int argc, char **argv )
if( greeting ) {
tty_printf("%s %s; %s\n", strusage(11), strusage(13), strusage(14) );
tty_printf("%s\n", strusage(15) );
#ifdef IS_DEVELOPMENT_VERSION
log_info("NOTE: this is a development version!\n");
#endif
}
secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */
@ -859,12 +865,6 @@ main( int argc, char **argv )
log_error(_("invalid S2K mode; must be 0, 1 or 3\n"));
}
{ const char *p = strusage(13);
for( ; *p && (isdigit(*p) || *p=='.'); p++ )
;
if( *p )
log_info("NOTE: this is a development version!\n");
}
if( log_get_errorcount(0) )
g10_exit(2);

View file

@ -38,9 +38,9 @@
#define MAX_PK_CACHE_ENTRIES 50
#define MAX_UID_CACHE_ENTRIES 50
/* Aa map of the all characters valid used for word_match()
/* A map of the all characters valid used for word_match()
* Valid characters are in in this table converted to uppercase.
* becuase the upper 128 bytes have special meanin, we assume
* because the upper 128 bytes have special meaning, we assume
* that they are all valid.
* Note: We must use numerical values here in case that this program
* will be converted to those little blue HAL9000s with their strange
@ -95,6 +95,7 @@ struct getkey_ctx_s {
KBPOS kbpos;
int last_rc;
ulong count;
int not_allocated;
int nitems;
getkey_item_t items[1];
};
@ -322,11 +323,13 @@ get_pubkey( PKT_public_key *pk, u32 *keyid )
/* do a lookup */
{ struct getkey_ctx_s ctx;
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = 11;
ctx.items[0].keyid[0] = keyid[0];
ctx.items[0].keyid[1] = keyid[1];
rc = lookup_pk( &ctx, pk, NULL );
get_pubkey_end( &ctx );
}
if( !rc )
goto leave;
@ -371,11 +374,13 @@ get_seckey( PKT_secret_key *sk, u32 *keyid )
struct getkey_ctx_s ctx;
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = 11;
ctx.items[0].keyid[0] = keyid[0];
ctx.items[0].keyid[1] = keyid[1];
rc = lookup_sk( &ctx, sk, NULL );
get_seckey_end( &ctx );
if( !rc ) {
/* check the secret key (this may prompt for a passprase to
* unlock the secret key
@ -395,14 +400,18 @@ int
get_primary_seckey( PKT_secret_key *sk, u32 *keyid )
{
struct getkey_ctx_s ctx;
int rc;
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.primary = 1;
ctx.nitems = 1;
ctx.items[0].mode = 11;
ctx.items[0].keyid[0] = keyid[0];
ctx.items[0].keyid[1] = keyid[1];
return lookup_sk( &ctx, sk, NULL );
rc = lookup_sk( &ctx, sk, NULL );
get_seckey_end( &ctx );
return rc;
}
@ -421,11 +430,13 @@ seckey_available( u32 *keyid )
sk = m_alloc_clear( sizeof *sk );
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = 11;
ctx.items[0].keyid[0] = keyid[0];
ctx.items[0].keyid[1] = keyid[1];
rc = lookup_sk( &ctx, sk, NULL );
get_seckey_end( &ctx );
free_secret_key( sk );
return rc;
}
@ -653,9 +664,9 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
/* and call the lookup function */
ctx->primary = 1; /* we want to look for the primary key only */
if( sk )
rc = lookup_sk( ctx, sk, NULL );
rc = lookup_sk( ctx, sk, ret_kb );
else
rc = lookup_pk( ctx, pk, NULL );
rc = lookup_pk( ctx, pk, ret_kb );
if( retctx ) /* caller wants the context */
*retctx = ctx;
@ -733,7 +744,8 @@ get_pubkey_end( GETKEY_CTX ctx )
enum_keyblocks( 2, &ctx->kbpos, NULL ); /* close */
for(n=0; n < ctx->nitems; n++ )
m_free( ctx->items[n].namebuf );
m_free( ctx );
if( !ctx->not_allocated )
m_free( ctx );
}
}
@ -748,10 +760,12 @@ get_pubkey_byfprint( PKT_public_key *pk, const byte *fprint, size_t fprint_len)
if( fprint_len == 20 || fprint_len == 16 ) {
struct getkey_ctx_s ctx;
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = fprint_len;
memcpy( ctx.items[0].fprint, fprint, fprint_len );
rc = lookup_pk( &ctx, pk, NULL );
get_pubkey_end( &ctx );
}
else
rc = G10ERR_GENERAL; /* Oops */
@ -772,10 +786,12 @@ get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint,
if( fprint_len == 20 || fprint_len == 16 ) {
struct getkey_ctx_s ctx;
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = fprint_len;
memcpy( ctx.items[0].fprint, fprint, fprint_len );
rc = lookup_pk( &ctx, pk, ret_keyblock );
get_pubkey_end( &ctx );
}
else
rc = G10ERR_GENERAL; /* Oops */
@ -806,10 +822,12 @@ get_seckey_byname( PKT_secret_key *sk, const char *name, int unprotect )
struct getkey_ctx_s ctx;
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.primary = 1;
ctx.nitems = 1;
ctx.items[0].mode = 15;
rc = lookup_sk( &ctx, sk, NULL );
get_seckey_end( &ctx );
}
else {
add_to_strlist( &namelist, name );
@ -868,7 +886,8 @@ get_seckey_end( GETKEY_CTX ctx )
enum_keyblocks( 2, &ctx->kbpos, NULL ); /* close */
for(n=0; n < ctx->nitems; n++ )
m_free( ctx->items[n].namebuf );
m_free( ctx );
if( !ctx->not_allocated )
m_free( ctx );
}
}
@ -1600,7 +1619,7 @@ lookup_pk( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock )
k = find_first( ctx->keyblock, pk );
else if( item->mode == 16 || item->mode == 20 )
k = find_by_fpr( ctx->keyblock, pk,
item->name, item->mode );
item->fprint, item->mode );
else
BUG();
if( k ) {
@ -1687,7 +1706,7 @@ lookup_sk( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock )
k = find_first_sk( ctx->keyblock, sk );
else if( item->mode == 16 || item->mode == 20 )
k = find_by_fpr_sk( ctx->keyblock, sk,
item->name, item->mode );
item->fprint, item->mode );
else
BUG();
if( k ) {

View file

@ -83,15 +83,13 @@ keygen_add_std_prefs( PKT_signature *sig, void *opaque )
keygen_add_key_expire( sig, opaque );
buf[0] = CIPHER_ALGO_BLOWFISH;
buf[0] = CIPHER_ALGO_TWOFISH;
buf[1] = CIPHER_ALGO_CAST5;
build_sig_subpkt( sig, SIGSUBPKT_PREF_SYM, buf, 2 );
buf[0] = DIGEST_ALGO_RMD160;
buf[1] = DIGEST_ALGO_SHA1;
buf[2] = DIGEST_ALGO_TIGER;
buf[3] = DIGEST_ALGO_MD5;
build_sig_subpkt( sig, SIGSUBPKT_PREF_HASH, buf, 4 );
build_sig_subpkt( sig, SIGSUBPKT_PREF_HASH, buf, 2 );
buf[0] = 2;
buf[1] = 1;

View file

@ -169,6 +169,7 @@ list_keyblock( KBNODE keyblock, int secret )
node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY );
if( !node ) {
log_error("Oops; key lost!\n");
dump_kbnode( keyblock );
return;
}

View file

@ -252,7 +252,11 @@ proc_plaintext( CTX c, PACKET *pkt )
free_md_filter_context( &c->mfx );
c->mfx.md = md_open( 0, 0);
/* fixme: we may need to push the textfilter if we have sigclass 1
* and no armoring - Not yet tested */
* and no armoring - Not yet tested
* Hmmm, why don't we need it at all if we have sigclass 1
* Should we assume that plaintext in mode 't' has always sigclass 1??
* See: Russ Allbery's mail 1999-02-09
*/
any = clearsig = 0;
for(n=c->list; n; n = n->next ) {
if( n->pkt->pkttype == PKT_ONEPASS_SIG ) {

View file

@ -47,6 +47,7 @@ struct {
int def_compress_algo;
const char *def_secret_key;
int no_comment;
int no_version;
int marginals_needed;
int completes_needed;
int max_cert_depth;

View file

@ -31,6 +31,7 @@
#include "trustdb.h"
#include "cipher.h"
#include "status.h"
#include "options.h"
#include "i18n.h"
static int get_it( PKT_pubkey_enc *k,
@ -179,9 +180,17 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
else if( !pk->local_id && query_trust_record(pk) )
log_error("can't check algorithm against preferences\n");
else if( dek->algo != CIPHER_ALGO_3DES
&& !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM, dek->algo ) )
log_info(_("NOTE: cipher algorithm %d not found in preferences\n"),
&& !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM, dek->algo ) ) {
/* Don't print a note while we are not on verbose mode,
* the cipher is blowfish and the preferences have twofish
* listed */
if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH
|| !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM,
CIPHER_ALGO_TWOFISH ) )
log_info(_(
"NOTE: cipher algorithm %d not found in preferences\n"),
dek->algo );
}
free_public_key( pk );
rc = 0;
}

View file

@ -72,12 +72,13 @@ struct resource_table_struct {
GDBM_FILE dbf;
#endif
enum resource_type rt;
DOTLOCK lockhd;
int is_locked;
};
typedef struct resource_table_struct RESTBL;
#define MAX_RESOURCES 10
static RESTBL resource_table[MAX_RESOURCES];
static const char *keyring_lock;
static int search( PACKET *pkt, KBPOS *kbpos, int secret );
@ -117,15 +118,40 @@ fatal_gdbm_error( const char *string )
#endif /* HAVE_LIBGDBM */
/****************
* Hmmm, how to avoid deadlock? They should not happen if everyone
* locks the key resources in the same order; but who knows.
* A solution is to use only one lock file in the gnupg homedir but
* what will happen with key resources which normally don't belong
* to the gpg homedir?
*/
static void
cleanup( void )
lock_rentry( RESTBL *rentry )
{
if( keyring_lock ) {
release_dotlock( keyring_lock );
keyring_lock = NULL;
if( !rentry->lockhd ) {
rentry->lockhd = create_dotlock( rentry->fname );
if( !rentry->lockhd )
log_fatal("can't allocate lock for `%s'\n", rentry->fname );
rentry->is_locked = 0;
}
if( !rentry->is_locked ) {
if( make_dotlock( rentry->lockhd, -1 ) )
log_fatal("can't lock `%s'\n", rentry->fname );
rentry->is_locked = 1;
}
}
static void
unlock_rentry( RESTBL *rentry )
{
if( opt.lock_once )
return;
if( !release_dotlock( rentry->lockhd ) )
rentry->is_locked = 0;
}
/****************************************************************
****************** public functions ****************************
****************************************************************/
@ -162,7 +188,6 @@ enum_keyblock_resources( int *sequence, int secret )
int
add_keyblock_resource( const char *url, int force, int secret )
{
static int initialized = 0;
static int any_secret, any_public;
const char *resname = url;
IOBUF iobuf = NULL;
@ -171,10 +196,6 @@ add_keyblock_resource( const char *url, int force, int secret )
int rc = 0;
enum resource_type rt = rt_UNKNOWN;
if( !initialized ) {
initialized = 1;
atexit( cleanup );
}
/* Do we have an URL?
* gnupg-gdbm:filename := this is a GDBM resource
@ -190,7 +211,7 @@ add_keyblock_resource( const char *url, int force, int secret )
rt = rt_GDBM;
resname += 11;
}
#ifndef __MINGW32__
#ifndef HAVE_DRIVE_LETTERS
else if( strchr( resname, ':' ) ) {
log_error("%s: invalid URL\n", url );
rc = G10ERR_GENERAL;
@ -264,7 +285,7 @@ add_keyblock_resource( const char *url, int force, int secret )
if( access(filename, F_OK) ) {
if( strlen(filename) >= 7
&& !strcmp(filename+strlen(filename)-7, "/.gnupg") ) {
#if __MINGW32__
#ifdef HAVE_DOSISH_SYSTEM
if( mkdir(filename) )
#else
if( mkdir(filename, S_IRUSR|S_IWUSR|S_IXUSR) )
@ -298,10 +319,10 @@ add_keyblock_resource( const char *url, int force, int secret )
else
log_info(_("%s: keyring created\n"), filename );
}
#if __MINGW32__ || 1
/* must close it again */
#if HAVE_DOSISH_SYSTEM || 1
iobuf_close( iobuf );
iobuf = NULL;
/* must close it again */
#endif
break;
@ -1039,7 +1060,7 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
kbpos->rt = rt_RING;
kbpos->valid = 0;
#if __MINGW32__ || 1
#if HAVE_DOSISH_SYSTEM || 1
assert(!iobuf);
iobuf = iobuf_open( fname );
if( !iobuf ) {
@ -1084,7 +1105,7 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
leave:
free_packet(&pkt);
set_packet_list_mode(save_mode);
#if __MINGW32__ || 1
#if HAVE_DOSISH_SYSTEM || 1
iobuf_close(iobuf);
#endif
return rc;
@ -1276,10 +1297,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
if( kbpos->fp )
BUG(); /* not allowed with such a handle */
if( !keyring_lock );
keyring_lock = make_dotlock( rentry->fname, -1 );
if( !keyring_lock )
log_fatal("can't lock `%s'\n", rentry->fname );
lock_rentry( rentry );
/* open the source file */
fp = iobuf_open( rentry->fname );
@ -1290,10 +1308,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
newfp = iobuf_create( rentry->fname );
if( !newfp ) {
log_error(_("%s: can't create: %s\n"), rentry->fname, strerror(errno));
if( !opt.lock_once ) {
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
unlock_rentry( rentry );
return G10ERR_OPEN_FILE;
}
else
@ -1305,28 +1320,19 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, g10_errstr(rc) );
iobuf_cancel(newfp);
if( !opt.lock_once ) {
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
unlock_rentry( rentry );
return G10ERR_WRITE_FILE;
}
}
if( iobuf_close(newfp) ) {
log_error("%s: close failed: %s\n", rentry->fname, strerror(errno));
if( !opt.lock_once ) {
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
unlock_rentry( rentry );
return G10ERR_CLOSE_FILE;
}
if( chmod( rentry->fname, S_IRUSR | S_IWUSR ) ) {
log_error("%s: chmod failed: %s\n",
rentry->fname, strerror(errno) );
if( !opt.lock_once ) {
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
unlock_rentry( rentry );
return G10ERR_WRITE_FILE;
}
return 0;
@ -1338,7 +1344,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
}
/* create the new file */
#ifdef __MINGW32__
#ifdef USE_ONLY_8DOT3
/* Here is another Windoze bug?:
* you cant rename("pubring.gpg.tmp", "pubring.gpg");
* but rename("pubring.gpg.tmp", "pubring.aaa");
@ -1451,7 +1457,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
goto leave;
}
/* if the new file is a secring, restrict the permissions */
#ifndef __MINGW32__
#ifndef HAVE_DOSISH_SYSTEM
if( rentry->secret ) {
if( chmod( tmpfname, S_IRUSR | S_IWUSR ) ) {
log_error("%s: chmod failed: %s\n",
@ -1464,7 +1470,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
/* rename and make backup file */
if( !rentry->secret ) { /* but not for secret keyrings */
#ifdef __MINGW32__
#ifdef HAVE_DOSISH_SYSTEM
remove( bakfname );
#endif
if( rename( rentry->fname, bakfname ) ) {
@ -1474,7 +1480,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
goto leave;
}
}
#ifdef __MINGW32__
#ifdef HAVE_DOSISH_SYSTEM
remove( rentry->fname );
#endif
if( rename( tmpfname, rentry->fname ) ) {
@ -1492,10 +1498,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
}
leave:
if( !opt.lock_once ) {
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
unlock_rentry( rentry );
m_free(bakfname);
m_free(tmpfname);
return rc;

View file

@ -70,7 +70,7 @@ got_usr_signal( int sig )
caught_sigusr1 = 1;
}
#ifndef __MINGW32__
#ifndef HAVE_DOSISH_SYSTEM
static void
do_sigaction( int sig, struct sigaction *nact )
{
@ -85,7 +85,7 @@ do_sigaction( int sig, struct sigaction *nact )
void
init_signals()
{
#ifndef __MINGW32__
#ifndef HAVE_DOSISH_SYSTEM
struct sigaction nact;
nact.sa_handler = got_fatal_signal;
@ -100,7 +100,7 @@ init_signals()
nact.sa_handler = got_usr_signal;
sigaction( SIGUSR1, &nact, NULL );
nact.sa_handler = SIG_IGN;
sigaction( SIGPIPE, &nact, NULL );
sigaction( SIGPIPE, &nact, NULL );
#endif
}
@ -108,7 +108,7 @@ init_signals()
void
pause_on_sigusr( int which )
{
#ifndef __MINGW32__
#ifndef HAVE_DOSISH_SYSTEM
sigset_t mask, oldmask;
assert( which == 1 );
@ -127,7 +127,7 @@ pause_on_sigusr( int which )
static void
do_block( int block )
{
#ifndef __MINGW32__
#ifndef HAVE_DOSISH_SYSTEM
static int is_blocked;
static sigset_t oldmask;
@ -146,7 +146,7 @@ do_block( int block )
sigprocmask( SIG_SETMASK, &oldmask, NULL );
is_blocked = 0;
}
#endif /*__MINGW32__*/
#endif /*HAVE_DOSISH_SYSTEM*/
}

View file

@ -77,7 +77,8 @@ struct cmp_sdir_struct {
static char *db_name;
static const char *lockname;
static DOTLOCK lockhandle;
static int is_locked;
static int db_fd = -1;
static int in_transaction;
@ -236,10 +237,12 @@ put_record_into_cache( ulong recno, const char *data )
int n = dirty_count / 5; /* discard some dirty entries */
if( !n )
n = 1;
if( !lockname )
lockname = make_dotlock( db_name, -1 );
if( !lockname )
log_fatal("can't get a lock - giving up\n");
if( !is_locked ) {
if( make_dotlock( lockhandle, -1 ) )
log_fatal("can't acquire lock - giving up\n");
else
is_locked = 1;
}
for( unused = NULL, r = cache_list; r; r = r->next ) {
if( r->flags.used && r->flags.dirty ) {
int rc = write_cache_item( r );
@ -254,8 +257,8 @@ put_record_into_cache( ulong recno, const char *data )
}
}
if( !opt.lock_once ) {
release_dotlock( lockname );
lockname=NULL;
if( !release_dotlock( lockhandle ) )
is_locked = 0;
}
assert( unused );
r = unused;
@ -287,17 +290,20 @@ tdbio_sync()
CACHE_CTRL r;
int did_lock = 0;
if( db_fd == -1 )
open_db();
if( in_transaction )
log_bug("tdbio: syncing while in transaction\n");
if( !cache_is_dirty )
return 0;
if( !lockname ) {
lockname = make_dotlock( db_name, -1 );
if( !is_locked ) {
if( make_dotlock( lockhandle, -1 ) )
log_fatal("can't acquire lock - giving up\n");
else
is_locked = 1;
did_lock = 1;
if( !lockname )
log_fatal("can't get a lock - giving up\n");
}
for( r = cache_list; r; r = r->next ) {
if( r->flags.used && r->flags.dirty ) {
@ -308,8 +314,8 @@ tdbio_sync()
}
cache_is_dirty = 0;
if( did_lock && !opt.lock_once ) {
release_dotlock( lockname );
lockname=NULL;
if( !release_dotlock( lockhandle ) )
is_locked = 0;
}
return 0;
}
@ -344,17 +350,19 @@ tdbio_end_transaction()
if( !in_transaction )
log_bug("tdbio: no active transaction\n");
if( !lockname )
lockname = make_dotlock( db_name, -1 );
if( !lockname )
log_fatal("can't get a lock - giving up\n");
if( !is_locked ) {
if( make_dotlock( lockhandle, -1 ) )
log_fatal("can't acquire lock - giving up\n");
else
is_locked = 1;
}
block_all_signals();
in_transaction = 0;
rc = tdbio_sync();
unblock_all_signals();
if( !opt.lock_once ) {
release_dotlock( lockname );
lockname=NULL;
if( !release_dotlock( lockhandle ) )
is_locked = 0;
}
return rc;
}
@ -392,9 +400,9 @@ tdbio_cancel_transaction()
static void
cleanup(void)
{
if( lockname ) {
release_dotlock(lockname);
lockname = NULL;
if( is_locked ) {
if( !release_dotlock(lockhandle) )
is_locked = 0;
}
}
@ -428,7 +436,7 @@ tdbio_set_dbname( const char *new_dbname, int create )
if( access( fname, F_OK ) ) {
if( strlen(fname) >= 7
&& !strcmp(fname+strlen(fname)-7, "/.gnupg" ) ) {
#if __MINGW32__
#if HAVE_DOSISH_SYSTEM
if( mkdir( fname ) )
#else
if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
@ -450,7 +458,7 @@ tdbio_set_dbname( const char *new_dbname, int create )
fclose(fp);
m_free(db_name);
db_name = fname;
#ifdef __MINGW32__
#ifdef HAVE_DOSISH_SYSTEM
db_fd = open( db_name, O_RDWR | O_BINARY );
#else
db_fd = open( db_name, O_RDWR );
@ -501,7 +509,10 @@ open_db()
TRUSTREC rec;
assert( db_fd == -1 );
#ifdef __MINGW32__
lockhandle = create_dotlock( db_name );
if( !lockhandle )
log_fatal( _("%s: can't create lock\n"), db_name );
#ifdef HAVE_DOSISH_SYSTEM
db_fd = open( db_name, O_RDWR | O_BINARY );
#else
db_fd = open( db_name, O_RDWR );
@ -970,6 +981,8 @@ 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 );
if( rec->r.uid.uidflags & UIDF_CHECKED ) {
if( rec->r.uid.uidflags & UIDF_VALID )
fputs(", valid", fp );
@ -1155,7 +1168,18 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
rec->r.uid.prefrec = buftoulong(p); p += 4;
rec->r.uid.siglist = buftoulong(p); p += 4;
rec->r.uid.uidflags = *p++;
p ++;
rec->r.uid.validity = *p++;
switch( rec->r.uid.validity ) {
case 0:
case TRUST_UNDEFINED:
case TRUST_NEVER:
case TRUST_MARGINAL:
case TRUST_FULLY:
case TRUST_ULTIMATE:
break;
default:
log_info("lid %lu: invalid validity value - cleared\n", recnum);
}
memcpy( rec->r.uid.namehash, p, 20);
break;
case RECTYPE_PREF: /* preference record */
@ -1278,7 +1302,7 @@ tdbio_write_record( TRUSTREC *rec )
ulongtobuf(p, rec->r.uid.prefrec); p += 4;
ulongtobuf(p, rec->r.uid.siglist); p += 4;
*p++ = rec->r.uid.uidflags;
p++;
*p++ = rec->r.uid.validity;
memcpy( p, rec->r.uid.namehash, 20 ); p += 20;
break;

View file

@ -59,9 +59,10 @@
#define KEYF_EXPIRED 4 /* this key is expired */
#define KEYF_REVOKED 8 /* this key has been revoked */
#define UIDF_CHECKED 1 /* user id has been checked - other bits are valid */
#define UIDF_VALID 2 /* this is a valid user id */
#define UIDF_REVOKED 8 /* this user id has been revoked */
#define 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 */
@ -98,7 +99,7 @@ struct trust_record {
ulong cacherec; /* the cache record */
byte ownertrust;
byte dirflags;
byte validity; /* calculated trustlevel */
byte validity; /* calculated trustlevel over all uids */
} dir;
struct { /* primary public key record */
ulong lid;
@ -114,6 +115,7 @@ struct trust_record {
ulong prefrec; /* recno of preference record */
ulong siglist; /* list of valid signatures (w/o self-sig)*/
byte uidflags;
byte validity; /* calculated trustlevel of this uid */
byte namehash[20]; /* ripemd hash of the username */
} uid;
struct { /* preference record */

View file

@ -104,6 +104,8 @@ static void release_lid_table( LOCAL_ID_TABLE tbl );
static int ins_lid_table_item( LOCAL_ID_TABLE tbl, ulong lid, unsigned flag );
static int qry_lid_table_flag( LOCAL_ID_TABLE tbl, ulong lid, unsigned *flag );
static void print_user_id( const char *text, u32 *keyid );
static void sort_tsl_list( TRUST_SEG_LIST *trust_seg_list );
static int list_sigs( ulong pubkey_id );
@ -839,42 +841,13 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
ulong rn, uidrn;
int marginal=0;
int fully=0;
LOCAL_ID_TABLE sigs_seen = NULL;
/*LOCAL_ID_TABLE sigs_seen = NULL;*/
if( depth >= max_depth ) /* max cert_depth reached */
return TRUST_UNDEFINED;
stack[depth].lid = drec->r.dir.lid;
stack[depth].otrust = drec->r.dir.ownertrust;
stack[depth].trust = 0;
{ int i;
for(i=0; i < depth; i++ )
if( stack[i].lid == drec->r.dir.lid )
return TRUST_UNDEFINED; /* closed (we already visited this lid) */
}
if( !qry_lid_table_flag( ultikey_table, drec->r.dir.lid, NULL ) ) {
/* we are at the end of a path */
TRUST_SEG_LIST tsl;
int i;
stack[depth].trust = TRUST_ULTIMATE;
stack[depth].otrust = TRUST_ULTIMATE;
if( trust_seg_head ) {
/* we can now put copy our current stack to the trust_seg_list */
tsl = m_alloc( sizeof *tsl + (depth+1)*sizeof( TRUST_INFO ) );
for(i=0; i <= depth; i++ )
tsl->path[i] = stack[i];
tsl->pathlen = i;
tsl->next = *trust_seg_head;
*trust_seg_head = tsl;
}
return TRUST_ULTIMATE;
}
/* loop over all user-ids */
if( !all )
sigs_seen = new_lid_table();
/*if( !all ) sigs_seen = new_lid_table();*/
for( rn = drec->r.dir.uidlist; rn; rn = uidrn ) {
TRUSTREC rec; /* used for uids and sigs */
ulong sigrn;
@ -888,7 +861,36 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
if( (rec.r.uid.uidflags & UIDF_REVOKED) )
continue; /* user id has been revoked */
/* loop over all signature records */
stack[depth].lid = drec->r.dir.lid;
stack[depth].otrust = drec->r.dir.ownertrust;
stack[depth].trust = 0;
{ int i;
for(i=0; i < depth; i++ )
if( stack[i].lid == drec->r.dir.lid )
return TRUST_UNDEFINED; /* closed (we already visited this lid) */
}
if( !qry_lid_table_flag( ultikey_table, drec->r.dir.lid, NULL ) ) {
/* we are at the end of a path */
TRUST_SEG_LIST tsl;
int i;
stack[depth].trust = TRUST_ULTIMATE;
stack[depth].otrust = TRUST_ULTIMATE;
if( trust_seg_head ) {
/* we can now put copy our current stack to the trust_seg_list */
tsl = m_alloc( sizeof *tsl + (depth+1)*sizeof( TRUST_INFO ) );
for(i=0; i <= depth; i++ )
tsl->path[i] = stack[i];
tsl->pathlen = i;
tsl->next = *trust_seg_head;
*trust_seg_head = tsl;
}
return TRUST_ULTIMATE;
}
/* loop over all signature records of this user id */
for( rn = rec.r.uid.siglist; rn; rn = sigrn ) {
int i;
@ -917,11 +919,11 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
}
/* visit every signer only once (a signer may have
* signed more than one user ID) */
if( sigs_seen && ins_lid_table_item( sigs_seen,
rec.r.sig.sig[i].lid, 0) )
continue; /* we already have this one */
* signed more than one user ID)
* if( sigs_seen && ins_lid_table_item( sigs_seen,
* rec.r.sig.sig[i].lid, 0) )
* continue; we already have this one
*/
read_record( rec.r.sig.sig[i].lid, &tmp, 0 );
if( tmp.rectype != RECTYPE_DIR ) {
if( tmp.rectype != RECTYPE_SDIR )
@ -945,8 +947,7 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
/* we have signed this key and only in this special case
* we assume that this one is fully trusted */
if( !all ) {
if( sigs_seen )
release_lid_table( sigs_seen );
/*if( sigs_seen ) release_lid_table( sigs_seen );*/
return (stack[depth].trust = TRUST_FULLY);
}
}
@ -962,16 +963,14 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
if( fully >= opt.completes_needed
|| marginal >= opt.marginals_needed ) {
if( !all ) {
if( sigs_seen )
release_lid_table( sigs_seen );
/*if( sigs_seen ) release_lid_table( sigs_seen );*/
return (stack[depth].trust = TRUST_FULLY);
}
}
}
}
}
if( sigs_seen )
release_lid_table( sigs_seen );
/*if( sigs_seen ) release_lid_table( sigs_seen ); */
if( all && ( fully >= opt.completes_needed
|| marginal >= opt.marginals_needed ) ) {
return (stack[depth].trust = TRUST_FULLY );
@ -983,6 +982,145 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
}
typedef struct {
ulong lid;
ulong uid;
} CERT_ITEM;
/* structure to hold certification chains. Item[nitems-1] is the
* ultimateley trusted key, item[0] is the key which
* is introduced, indices [1,(nitems-2)] are all introducers.
*/
typedef struct cert_chain *CERT_CHAIN;
struct cert_chain {
CERT_CHAIN next;
int dups;
int nitems;
CERT_ITEM items[1];
};
/****************
* Copy all items to the set SET_HEAD in a way that the requirements
* of a CERT_CHAIN are met.
*/
static void
add_cert_items_to_set( CERT_CHAIN *set_head, CERT_ITEM *items, int nitems )
{
CERT_CHAIN ac;
int i;
ac = m_alloc_clear( sizeof *ac + (nitems-1)*sizeof(CERT_ITEM) );
ac->nitems = nitems;
for(i=0; i < nitems; i++ )
ac->items[i] = items[i];
ac->next = *set_head;
*set_head = ac;
}
/****************
* Find all certification paths of a given LID.
* Limit the search to MAX_DEPTH. stack is a helper variable which
* should have been allocated with size max_depth, stack[0] should
* be setup to the key we are investigating, so the minimal depth
* we should ever see in this function is 1.
* Returns: -1 max_depth reached
* 0 no paths found
* 1 ultimately trusted key found
* certchain_set must be a valid set or point to NULL; this function
* may modifiy it.
*/
static int
find_cert_chain( ulong lid, int depth, int max_depth,
CERT_ITEM *stack, CERT_CHAIN *cert_chain_set )
{
TRUSTREC dirrec;
TRUSTREC uidrec;
ulong uidrno;
if( depth >= max_depth )
return -1;
stack[depth].lid = lid;
stack[depth].uid = 0;
if( !qry_lid_table_flag( ultikey_table, lid, NULL ) ) {
/* this is an ultimately trusted key;
* which means that we have found the end of the chain:
* copy the chain to the set */
add_cert_items_to_set( cert_chain_set, stack, depth+1 );
return 1;
}
read_record( lid, &dirrec, 0 );
if( dirrec.rectype != RECTYPE_DIR ) {
if( dirrec.rectype != RECTYPE_SDIR )
log_debug("lid %lu, has rectype %d"
" - skipped\n", lid, dirrec.rectype );
return 0;
}
/* Performance hint: add stuff to ignore this one when the
* assigned validity of the key is bad */
/* loop over all user ids */
for( uidrno = dirrec.r.dir.uidlist; uidrno; uidrno = uidrec.r.uid.next ) {
TRUSTREC sigrec;
ulong sigrno;
stack[depth].uid = uidrno;
read_record( uidrno, &uidrec, RECTYPE_UID );
if( !(uidrec.r.uid.uidflags & UIDF_CHECKED) )
continue; /* user id has not been checked */
if( !(uidrec.r.uid.uidflags & UIDF_VALID) )
continue; /* user id is not valid */
if( (uidrec.r.uid.uidflags & UIDF_REVOKED) )
continue; /* user id has been revoked */
/* loop over all signature records */
for(sigrno=uidrec.r.uid.siglist; sigrno; sigrno = sigrec.r.sig.next ) {
int i, j;
read_record( sigrno, &sigrec, RECTYPE_SIG );
for(i=0; i < SIGS_PER_RECORD; i++ ) {
if( !sigrec.r.sig.sig[i].lid )
continue; /* skip deleted sigs */
if( !(sigrec.r.sig.sig[i].flag & SIGF_CHECKED) )
continue; /* skip unchecked signatures */
if( !(sigrec.r.sig.sig[i].flag & SIGF_VALID) )
continue; /* skip invalid signatures */
if( (sigrec.r.sig.sig[i].flag & SIGF_EXPIRED) )
continue; /* skip expired signatures */
if( (sigrec.r.sig.sig[i].flag & SIGF_REVOKED) )
continue; /* skip revoked signatures */
for(j=0; j < depth; j++ ) {
if( stack[j].lid == sigrec.r.sig.sig[i].lid )
break;
}
if( j < depth )
continue; /* avoid cycles as soon as possible */
if( find_cert_chain( sigrec.r.sig.sig[i].lid,
depth+1, max_depth,
stack, cert_chain_set ) > 0 ) {
/* ultimately trusted key found:
* no need to check more signatures of this uid */
sigrec.r.sig.next = 0;
break;
}
}
} /* end loop over sig recs */
} /* end loop over user ids */
return 0;
}
/****************
* Given the directory record of a key, check whether we can
* find a path to an ultimately trusted key. We do this by
@ -1337,6 +1475,7 @@ void
list_trust_path( const char *username )
{
int rc;
ulong lid;
TRUSTREC rec;
TRUST_INFO *tmppath;
TRUST_SEG_LIST trust_seg_list, tsl, tsl2;
@ -1357,8 +1496,10 @@ list_trust_path( const char *username )
assert( pk->local_id );
}
}
lid = pk->local_id;
free_public_key( pk );
#if 0
/* collect the paths */
tmppath = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *tmppath );
trust_seg_list = NULL;
@ -1378,6 +1519,26 @@ list_trust_path( const char *username )
m_free( tsl );
}
trust_seg_list = NULL;
#else /* test code */
{
CERT_ITEM *stack;
CERT_CHAIN chains, r;
int i;
chains = NULL;
stack = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *stack );
find_cert_chain( lid, 0, opt.max_cert_depth, stack, &chains);
m_free( stack );
/* dump chains */
for(r=chains; r ; r = r->next ) {
printf("chain:" );
for(i=0; i < r->nitems; i++ )
printf(" %4lu/%-4lu", r->items[i].lid, r->items[i].uid );
putchar('\n');
}
}
#endif
}
@ -2719,15 +2880,17 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
continue; /* skip deleted sigs */
}
if( rec.r.sig.sig[i].lid == pk_lid ) {
#if 0 /* must take uid into account */
if( found_sig ) {
log_info( "sig %08lX.%lu/%02X%02X/%08lX: %s\n",
(ulong)keyid[1], lid, uidhash[18],
uidhash[19], (ulong)sig->keyid[1],
_("Duplicated certificate - deleted") );
_("duplicated certificate - deleted") );
rec.r.sig.sig[i].lid = 0;
rec.dirty = 1;
continue;
}
#endif
found_sig = 1;
}
if( !recheck && !revoke && (rec.r.sig.sig[i].flag & SIGF_CHECKED) )
@ -2811,7 +2974,7 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
}
}
if( found_sig )
if( found_sig ) /* fixme: uid stuff */
return;
/* at this point, we have verified, that the signature is not in