aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
Diffstat (limited to 'g10')
-rw-r--r--g10/ChangeLog22
-rw-r--r--g10/armor.c29
-rw-r--r--g10/g10.c12
-rw-r--r--g10/getkey.c37
-rw-r--r--g10/keygen.c6
-rw-r--r--g10/keylist.c1
-rw-r--r--g10/mainproc.c6
-rw-r--r--g10/options.h1
-rw-r--r--g10/pubkey-enc.c13
-rw-r--r--g10/ringedit.c91
-rw-r--r--g10/signal.c12
-rw-r--r--g10/tdbio.c78
-rw-r--r--g10/tdbio.h10
-rw-r--r--g10/trustdb.c253
14 files changed, 410 insertions, 161 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 8a09ff324..61551dc5d 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,25 @@
+Wed Feb 10 17:15:39 CET 1999 Werner Koch <[email protected]>
+
+ * 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 <[email protected]>
* getkey.c: Changed the internal design to allow simultaneous
diff --git a/g10/armor.c b/g10/armor.c
index 663e824a6..5aba3322a 100644
--- a/g10/armor.c
+++ b/g10/armor.c
@@ -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,
diff --git a/g10/g10.c b/g10/g10.c
index df0cd482c..df35870b7 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -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);
diff --git a/g10/getkey.c b/g10/getkey.c
index 770aa5811..f7558703d 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -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 ) {
diff --git a/g10/keygen.c b/g10/keygen.c
index 7431d8c61..12fa9422c 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -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;
diff --git a/g10/keylist.c b/g10/keylist.c
index 2a471b86c..0bfdb7725 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -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;
}
diff --git a/g10/mainproc.c b/g10/mainproc.c
index 2e5575dd8..0b3582c50 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -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 ) {
diff --git a/g10/options.h b/g10/options.h
index d7450dba8..39564fb2e 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -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;
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index f662c6206..af77a1e52 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -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;
}
diff --git a/g10/ringedit.c b/g10/ringedit.c
index 4a97f78f8..d5ac6ac77 100644
--- a/g10/ringedit.c
+++ b/g10/ringedit.c
@@ -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;
diff --git a/g10/signal.c b/g10/signal.c
index 364fb47a4..29f99c64b 100644
--- a/g10/signal.c
+++ b/g10/signal.c
@@ -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*/
}
diff --git a/g10/tdbio.c b/g10/tdbio.c
index b69d6c3f0..2eddb4b2d 100644
--- a/g10/tdbio.c
+++ b/g10/tdbio.c
@@ -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;
diff --git a/g10/tdbio.h b/g10/tdbio.h
index 925c7f93c..62148d361 100644
--- a/g10/tdbio.h
+++ b/g10/tdbio.h
@@ -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 */
diff --git a/g10/trustdb.c b/g10/trustdb.c
index 674240a7b..34890c2da 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -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