diff --git a/Makefile.am b/Makefile.am index 567fccdd3..68b203a2e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,7 +53,7 @@ tobold-get: tobold:gnupg/ . tobold-put: - rsync -Cavuzb --excude scratch --exclude .deps \ + rsync -Cavuzb --exclude scratch --exclude .deps \ . tobold:gnupg/ diff --git a/NEWS b/NEWS index 17d0330e4..e1948f609 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,8 @@ * A Russian language file in the distribution (alternatives are in the contrib directory of the FTP servers) + * commandline option processing now works as expected for GNU programs + with the execption that you can't mix options and normal arguments. Noteworthy changes in version 0.4.2 diff --git a/PROJECTS b/PROJECTS index 10afb9976..47ed1eb93 100644 --- a/PROJECTS +++ b/PROJECTS @@ -8,3 +8,7 @@ of other keys (processing of the sdir hintlist). The signatures may then be verified by a maintainence pass. + * Not GnupG replated: What about option completion in bash? + Can "--dump-options" be used for this or should we place the + options in a special ELF segment? + diff --git a/THANKS b/THANKS index 88e7c2311..be08ddec1 100644 --- a/THANKS +++ b/THANKS @@ -12,9 +12,11 @@ Charles Levert charles@comm.polymtl.ca Christian von Roques roques@pond.sub.org Christopher Oliver oliver@fritz.traverse.net Daniel Eisenbud eisenbud@cs.swarthmore.edu +David Ellement ellement@sdd.hp.com Detlef Lannert lannert@lannert.rz.uni-duesseldorf.de Ed Boraas ecxjo@esperanto.org Ernst Molitor ernst.molitor@uni-bonn.de +Fabio Coatti cova@felix.unife.it Frank Heckenbach heckenb@mi.uni-erlangen.de Gaël Quéri gqueri@mail.dotcom.fr Greg Louis glouis@dynamicro.on.ca @@ -49,9 +51,11 @@ Paul D. Smith psmith@baynetworks.com Peter Gutmann pgut001@cs.auckland.ac.nz QingLong qinglong@bolizm.ihep.su Ralph Gillen gillen@theochem.uni-duesseldorf.de +Roddy Strachan roddy@satlink.com.au Roland Rosenfeld roland@spinnaker.rhein.de Serge Munhoven munhoven@mema.ucl.ac.be SL Baur steve@xemacs.org +Stefan Karrmann S.Karrmann@gmx.net Steffen Ullrich ccrlphr@xensei.com Steffen Zahn zahn@berlin.snafu.de Thomas Roessler roessler@guug.de diff --git a/TODO b/TODO index e891645ae..bd5e43f21 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,27 @@ + * rmove assert in random.c:160 4096 bit keys need more random. + + * list all matching user ids + + * use zlib 1.1.13 to avoid a bug with 13 bit windows + + * FreeBSD: +#define USE_DYNAMIC_LINKING +#define HAVE_DL_DLOPEN + +and the ld option -export-dynamic. + + * +Well, there was one thing extra I needed to do. While configure found the +gdbm library, it didn't add the path the the include file list. I had to +re-run configure with CPPFLAGS set: + + env CPPFLAGS='-I/usr/local/include' configure ... + + + * clearsig: keep lineendings as they are. Remember that trailings + blanks are not hashed. + * Fix ;) revocation and expire stuff. * check preferences (cipher and compress) @@ -11,13 +34,9 @@ * prefer a type 16 subkey for encryption because pgp cannot handle type 20? - * calculation of marginals never yields a completely trusted key. - * The critical bit of signature subpackets is not yet supported; i.e. it is ignored. - * Exportable Certification Flag is ignored - * We need a maintainence pass over the trustdb which flags signatures as expired if the key used to make the signature has expired. Maybe it is a good idea to store the exiration time @@ -58,6 +77,15 @@ * add an option to re-create a public key from a secret key; we can do this in trustdb.c:verify_own_keys. + * signature verification is done duplicated on import: in import.c and + tehn in trustdb.c too. Maybe we can use a flag to skip the actual + verification process (this should work if we use the same keyblock, + but I'm not sure how to accomplish that). Another way is to allow + the import of bogus data and let trustdb mark these keys as invalid; + I see an advantage in this that it may help to prevent a DoS on a + keyserver by sending him a lot of bogus signatures which he has + to check - Needs further investigation. + * change the fake_data stuff to mpi_set_opaque * Is it okay to use gettext for the help system? diff --git a/configure.in b/configure.in index a497b3da9..29a439581 100644 --- a/configure.in +++ b/configure.in @@ -44,9 +44,9 @@ else fi if test "$use_m_guard" = yes ; then AC_DEFINE(M_GUARD) - CFLAGS="-g -Wall" + CFLAGS="$CFLAGS -g -Wall" else - CFLAGS="-O2 -Wall" + CFLAGS="$CFLAGS -O2 -Wall" fi diff --git a/doc/gpg.1pod b/doc/gpg.1pod index 2b6724088..56d802b08 100644 --- a/doc/gpg.1pod +++ b/doc/gpg.1pod @@ -75,7 +75,7 @@ B<-k> [I] [I] B<-kvc> List fingerprints B<-kvvc> List fingerprints and signatures -B<--list-keys> [I] +B<--list-keys> [I] List all keys from the public keyrings, or just the ones given on the command line. @@ -83,7 +83,7 @@ B<--list-secret-keys> [I] List all keys from the secret keyrings, or just the ones given on the command line. -B<--list-sigs> [I] +B<--list-sigs> [I] Same as B<--list-keys>, but the signatures are listed too. @@ -129,7 +129,7 @@ B<--edit-key> I B Remove a subkey. B - Change the key expiration time. If a key is + Change the key expiration time. If a key is select, the time of this key will be changed. With no selection the key expiration of the primary key is changed. @@ -191,7 +191,7 @@ B<--export-secret-keys> [I This is normally not very useful. B<--import>, B<--fast-import> - Import/merge keys. The fast version does not build + Import/merge keys. The fast version does not build the trustdb; this can be deon at anytime with the command B<--update-trustdb>. @@ -208,7 +208,7 @@ B<--import-ownertrust> [I] Long options can be put in an options file (default F<~/.gnupg/options>); do not write the 2 dashes, but simply the name of the option and any -arguments if required. Lines with a hash as the first non-white-space +arguments if required. Lines with a hash as the first non-white-space character are ignored. Commands may be put in this file too, but that does not make sense. @@ -249,8 +249,12 @@ B<-z> I compression level of zlib (which is 6). B<-t>, B<--textmode> - Use canonical text mode. Used to make clear-text - signatures. + Use canonical text mode. If B<-t> (but not + B<--textmode>) is used together with armoring + and signing, this enables clearsigned messages. + This kludge is needed for PGP compatibility; + normally you would use B<--sign> or b<--clearsign> + to selected the type os signatures. B<-n>, B<--dry-run> Don't make any changes (not yet implemented). @@ -443,11 +447,11 @@ a signature was bad and other errorcode for fatal errors. =head1 EXAMPLES - -se -r Bob [file] sign and encrypt for user Bob - -sat [file] make a clear text signature - -sb [file] make a detached signature - -k [userid] show keys - -kc [userid] show fingerprint + -se -r Bob [file] sign and encrypt for user Bob + -sat [file] make a clear text signature + -sb [file] make a detached signature + -k [userid] show keys + -kc [userid] show fingerprint =head1 ENVIRONMENT @@ -462,13 +466,13 @@ F<~/.gnupg/pubring.gpg> The public keyring F<~/.gnupg/trustdb.gpg> The trust database -F<~/.gnupg/options> May contain options +F<~/.gnupg/options> May contain options F Default location for extensions =head1 SEE ALSO -gpg(1) gpgm(1) +gpg(1) gpgm(1) =head1 WARNINGS diff --git a/g10/ChangeLog b/g10/ChangeLog index 35afefa16..9109e6558 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,30 @@ +Tue Nov 3 16:19:21 1998 Werner Koch (wk@isil.d.shuttle.de) + + * keygen.c (ask_user_id): Now converted to UTF-8 + + * g10.c (main): Kludge for pgp clearsigs and textmode. + +Fri Oct 30 16:40:39 1998 me,,, (wk@tobold) + + * signal.c (block_all_signals): New. + (unblock_all_signals): New + * tdbio.c (tdbio_end_transaction): Now blocks all signals. + + * trustdb.c (new_lid_table): Changed the represenation of the + former local_lid_info stuff. + + * trustdb.c (update_trust_record): Reorganized the whole thing. + * sig-check.c (check_key_signature): Now handles class 0x28 + + +Wed Oct 28 18:56:33 1998 me,,, (wk@tobold) + + * export.c (do_export): Takes care of the exportable sig flag. + +Tue Oct 27 14:53:04 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c (update_trust_record): New "fast" parameter. + Sun Oct 25 19:32:05 1998 Werner Koch (wk@isil.d.shuttle.de) * openfile.c (copy_options_File): New. diff --git a/g10/export.c b/g10/export.c index 46413fff2..637f675f4 100644 --- a/g10/export.c +++ b/g10/export.c @@ -128,6 +128,15 @@ do_export( STRLIST users, int secret ) * secret keyring */ if( !secret && node->pkt->pkttype == PKT_COMMENT ) continue; + /* do not export packets which are marked as not exportable */ + if( node->pkt->pkttype == PKT_SIGNATURE ) { + const char *p; + p = parse_sig_subpkt2( node->pkt->pkt.signature, + SIGSUBPKT_EXPORTABLE, NULL ); + if( p && !*p ) + continue; /* not exportable */ + } + if( (rc = build_packet( out, node->pkt )) ) { log_error("build_packet(%d) failed: %s\n", node->pkt->pkttype, g10_errstr(rc) ); diff --git a/g10/g10.c b/g10/g10.c index 3df9121b5..9d4f20d79 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -60,7 +60,7 @@ enum cmd_and_opt_values { aNull = 0, oQuiet = 'q', oRemote = 'r', aSign = 's', - oTextmode = 't', + oTextmodeShort= 't', oUser = 'u', oVerbose = 'v', oCompress = 'z', @@ -100,6 +100,7 @@ enum cmd_and_opt_values { aNull = 0, aEnArmor, aGenRandom, + oTextmode, oFingerprint, oAnswerYes, oAnswerNo, @@ -205,6 +206,7 @@ static ARGPARSE_OPTS opts[] = { { oUser, "local-user",2, N_("use this user-id to sign or decrypt")}, { oRemote, "remote-user", 2, N_("use this user-id for encryption")}, { oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") }, + { oTextmodeShort, NULL, 0, "@"}, { oTextmode, "textmode", 0, N_("use canonical text mode")}, #endif { oOutput, "output", 2, N_("use as output file")}, @@ -734,6 +736,7 @@ main( int argc, char **argv ) sl->next = remusr; remusr = sl; break; + case oTextmodeShort: opt.textmode = 2; break; case oTextmode: opt.textmode=1; break; case oUser: /* store the local users */ sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str)); @@ -839,7 +842,7 @@ main( int argc, char **argv ) /* kludge to let -sat generate a clear text signature */ - if( opt.textmode && !detached_sig && opt.armor && cmd == aSign ) + if( opt.textmode == 2 && !detached_sig && opt.armor && cmd == aSign ) cmd = aClearsign; if( opt.verbose > 1 ) diff --git a/g10/import.c b/g10/import.c index 075ecd358..0cd1353ef 100644 --- a/g10/import.c +++ b/g10/import.c @@ -465,7 +465,7 @@ import_one( const char *fname, KBNODE keyblock, int fast ) (ulong)keyid[1], g10_errstr(rc) ); } else if( mod_key ) - rc = update_trust_record( keyblock_orig, NULL ); + rc = update_trust_record( keyblock_orig, 1, NULL ); else rc = clear_trust_checked_flag( new_key? pk : pk_orig ); } diff --git a/g10/keyedit.c b/g10/keyedit.c index 62921349c..a2b0a761f 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -647,7 +647,7 @@ keyedit_menu( const char *username, STRLIST locusr ) } else tty_printf(_("Key not changed so no update needed.\n")); - rc = update_trust_record( keyblock, NULL ); + rc = update_trust_record( keyblock, 0, NULL ); if( rc ) log_error(_("update of trust db failed: %s\n"), g10_errstr(rc) ); @@ -705,7 +705,7 @@ keyedit_menu( const char *username, STRLIST locusr ) sec_modified = modified = 1; /* must update the trustdb already here, so that preferences * get listed correctly */ - rc = update_trust_record( keyblock, NULL ); + rc = update_trust_record( keyblock, 0, NULL ); if( rc ) { log_error(_("update of trust db failed: %s\n"), g10_errstr(rc) ); diff --git a/g10/keygen.c b/g10/keygen.c index 6b04971ca..a17d47927 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -689,6 +689,11 @@ ask_user_id( int mode ) break; m_free(uid); uid = NULL; } + if( uid ) { + char *p = native_to_utf8( uid ); + m_free( uid ); + uid = p; + } return uid; } diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 542676ccd..1f19b05de 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -633,7 +633,8 @@ dump_sig_subpkt( int hashed, int type, int critical, printf("sig expires %s", strtimestamp( buffer_to_u32(buffer) ) ); break; case SIGSUBPKT_EXPORTABLE: - p = "exportable"; + if( length ) + printf("%sexportable", *buffer? "":"not "); break; case SIGSUBPKT_TRUST: p = "trust signature"; @@ -759,6 +760,10 @@ parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, size_t *ret_n ) if( n < 4 ) break; return buffer; + case SIGSUBPKT_EXPORTABLE: + if( !n ) + break; + return buffer; case SIGSUBPKT_ISSUER:/* issuer key ID */ if( n < 8 ) break; diff --git a/g10/sig-check.c b/g10/sig-check.c index fd476f767..da732c451 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -278,12 +278,27 @@ check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ) rc = do_check( pk, sig, md ); md_close(md); } + else if( sig->sig_class == 0x28 ) { /* subkey revocation */ + KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY ); + + if( snode ) { + md = md_open( algo, 0 ); + hash_public_key( md, pk ); + hash_public_key( md, snode->pkt->pkt.public_key ); + rc = do_check( pk, sig, md ); + md_close(md); + } + else { + log_error("no subkey for subkey revocation packet\n"); + rc = G10ERR_SIG_CLASS; + } + } else if( sig->sig_class == 0x18 ) { KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY ); if( snode ) { - if( is_selfsig ) { - u32 keyid[2]; + if( is_selfsig ) { /* does this make sense????? */ + u32 keyid[2]; /* it should always be a selfsig */ keyid_from_pk( pk, keyid ); if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) diff --git a/g10/signal.c b/g10/signal.c index d89b548b1..8a0f3feee 100644 --- a/g10/signal.c +++ b/g10/signal.c @@ -121,3 +121,42 @@ pause_on_sigusr( int which ) #endif } + +static void +do_block( int block ) +{ + #ifndef __MINGW32__ + static int is_blocked; + static sigset_t oldmask; + + if( block ) { + sigset_t newmask; + + if( is_blocked ) + log_bug("signals are already blocked\n"); + sigfillset( &newmask ); + sigprocmask( SIG_BLOCK, &newmask, &oldmask ); + is_blocked = 1; + } + else { + if( !is_blocked ) + log_bug("signals are not blocked\n"); + sigprocmask( SIG_SETMASK, &oldmask, NULL ); + is_blocked = 0; + } + #endif /*__MINGW32__*/ +} + + +void +block_all_signals() +{ + do_block(1); +} + +void +unblock_all_signals() +{ + do_block(0); +} + diff --git a/g10/tdbio.c b/g10/tdbio.c index 1954929ae..f4c97e85e 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -320,10 +320,15 @@ tdbio_begin_transaction() int tdbio_end_transaction() { + int rc; + if( !in_transaction ) log_bug("tdbio: no active transaction\n"); + block_all_signals(); in_transaction = 0; - return tdbio_sync(); + rc = tdbio_sync(); + unblock_all_signals(); + return rc; } int diff --git a/g10/trustdb.c b/g10/trustdb.c index 7a6ec3bd1..43903a996 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -47,27 +47,33 @@ #error Must change structure of trustdb #endif -typedef struct local_id_info *LOCAL_ID_INFO; -struct local_id_info { - LOCAL_ID_INFO next; +struct local_id_item { + struct local_id_item *next; ulong lid; unsigned flag; }; +struct local_id_table { + struct local_id_table *next; /* only used to keep a list of unused tables */ + struct local_id_item *items[16]; +}; + + +typedef struct local_id_table *LOCAL_ID_TABLE; + typedef struct trust_info TRUST_INFO; struct trust_info { ulong lid; - unsigned trust; + byte otrust; /* ownertrust (assigned trust) */ + byte trust; /* calculated trust (validity) */ }; - typedef struct trust_seg_list *TRUST_SEG_LIST; struct trust_seg_list { TRUST_SEG_LIST next; - int nseg; /* number of segments */ - int dup; - TRUST_INFO seg[1]; /* segment list */ + int pathlen; + TRUST_INFO path[1]; }; @@ -82,10 +88,10 @@ typedef struct recno_list_struct *RECNO_LIST; static int walk_sigrecs( SIGREC_CONTEXT *c ); -static LOCAL_ID_INFO *new_lid_table(void); -static void release_lid_table( LOCAL_ID_INFO *tbl ); -static int ins_lid_table_item( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag ); -static int qry_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned *flag ); +static LOCAL_ID_TABLE new_lid_table(void); +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 int list_sigs( ulong pubkey_id ); @@ -95,8 +101,11 @@ static int get_dir_record( PKT_public_key *pk, TRUSTREC *rec ); /* a table used to keep track of ultimately trusted keys * which are the ones from our secrings */ -static LOCAL_ID_INFO *ultikey_table; +static LOCAL_ID_TABLE ultikey_table; +/* list of unused lid items and tables */ +static LOCAL_ID_TABLE unused_lid_tables; +static struct local_id_item *unused_lid_items; #define HEXTOBIN(a) ( (a) >= '0' && (a) <= '9' ? ((a)-'0') : \ @@ -215,53 +224,67 @@ rel_recno_list( RECNO_LIST *head ) *head = NULL; } -static LOCAL_ID_INFO * +static LOCAL_ID_TABLE new_lid_table(void) { - return m_alloc_clear( 16 * sizeof(LOCAL_ID_INFO)); + LOCAL_ID_TABLE a; + + a = unused_lid_tables; + if( a ) { + unused_lid_tables = a->next; + a->next = NULL; + } + else + a = m_alloc_clear( sizeof *a ); + return a; } static void -release_lid_table( LOCAL_ID_INFO *tbl ) +release_lid_table( LOCAL_ID_TABLE tbl ) { - LOCAL_ID_INFO a, a2; + struct local_id_item *a, *a2; int i; for(i=0; i < 16; i++ ) { - for(a=tbl[i]; a; a = a2 ) { + for(a=tbl->items[i]; a; a = a2 ) { a2 = a->next; - m_free(a); + a->next = unused_lid_items; + unused_lid_items = a; } } - m_free(tbl); + tbl->next = unused_lid_tables; + unused_lid_tables = tbl; } /**************** * Add a new item to the table or return 1 if we already have this item - * fixme: maybe it's a good idea to take items from an unused item list. */ static int -ins_lid_table_item( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag ) +ins_lid_table_item( LOCAL_ID_TABLE tbl, ulong lid, unsigned flag ) { - LOCAL_ID_INFO a; + struct local_id_item *a; - for( a = tbl[lid & 0x0f]; a; a = a->next ) + for( a = tbl->items[lid & 0x0f]; a; a = a->next ) if( a->lid == lid ) return 1; - a = m_alloc( sizeof *a ); + a = unused_lid_items; + if( a ) + unused_lid_items = a->next; + else + a = m_alloc( sizeof *a ); a->lid = lid; a->flag = flag; - a->next = tbl[lid & 0x0f]; - tbl[lid & 0x0f] = a; + a->next = tbl->items[lid & 0x0f]; + tbl->items[lid & 0x0f] = a; return 0; } static int -qry_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned *flag ) +qry_lid_table_flag( LOCAL_ID_TABLE tbl, ulong lid, unsigned *flag ) { - LOCAL_ID_INFO a; + struct local_id_item *a; - for( a = tbl[lid & 0x0f]; a; a = a->next ) + for( a = tbl->items[lid & 0x0f]; a; a = a->next ) if( a->lid == lid ) { if( flag ) *flag = a->flag; @@ -493,7 +516,7 @@ print_user_id( const char *text, u32 *keyid ) m_free(p); } - +#if 0 static int print_keyid( FILE *fp, ulong lid ) { @@ -521,7 +544,7 @@ print_trust( FILE *fp, unsigned trust ) putc(c, fp); return 1; } - +#endif static int print_sigflags( FILE *fp, unsigned flags ) @@ -542,7 +565,7 @@ print_sigflags( FILE *fp, unsigned flags ) /* (a non-recursive algorithm would be easier) */ static int do_list_sigs( ulong root, ulong pk_lid, int depth, - LOCAL_ID_INFO *lids, unsigned *lineno ) + LOCAL_ID_TABLE lids, unsigned *lineno ) { SIGREC_CONTEXT sx; int rc; @@ -551,8 +574,8 @@ do_list_sigs( ulong root, ulong pk_lid, int depth, memset( &sx, 0, sizeof sx ); sx.lid = pk_lid; for(;;) { - rc = walk_sigrecs( &sx ); - if( rc ) + rc = walk_sigrecs( &sx ); /* should we replace it and use */ + if( rc ) /* use a loop like in collect_paths ??*/ break; rc = keyid_from_lid( sx.sig_lid, keyid ); if( rc ) { @@ -609,7 +632,7 @@ list_sigs( ulong pubkey_id ) { int rc; u32 keyid[2]; - LOCAL_ID_INFO *lids; + LOCAL_ID_TABLE lids; unsigned lineno = 1; rc = keyid_from_lid( pubkey_id, keyid ); @@ -692,233 +715,164 @@ list_records( ulong lid ) + +/**************** + * stack is an array of (max_path+1) elements. If trust_seg_head is not + * NULL it is a pointer to a variable which will receive a linked list + * of trust paths - The caller has to free the memory. + */ +static int +collect_paths( int depth, int max_depth, int all, TRUSTREC *drec, + TRUST_INFO *stack, TRUST_SEG_LIST *trust_seg_head ) +{ + ulong rn, uidrn; + int marginal=0; + int fully=0; + LOCAL_ID_TABLE sigs_seen = NULL; + + if( depth >= max_depth ) /* max cert_depth reached */ + return TRUST_UNDEFINED; + { 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) */ + } + + stack[depth].lid = drec->r.dir.lid; + stack[depth].otrust = drec->r.dir.ownertrust; + stack[depth].trust = 0; + 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; + 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(); + for( rn = drec->r.dir.uidlist; rn; rn = uidrn ) { + TRUSTREC rec; /* used for uids and sigs */ + ulong sigrn; + + read_record( rn, &rec, RECTYPE_UID ); + uidrn = rec.r.uid.next; + /* fixme: continue if the uidrec is not marked valid */ + + /* loop over all signature records */ + for( rn = rec.r.uid.siglist; rn; rn = sigrn ) { + int i; + + read_record( rn, &rec, RECTYPE_SIG ); + sigrn = rec.r.sig.next; + + for(i=0; i < SIGS_PER_RECORD; i++ ) { + TRUSTREC tmp; + int ot, nt; + + if( !rec.r.sig.sig[i].lid ) + continue; /* skip deleted sigs */ + if( !(rec.r.sig.sig[i].flag & SIGF_CHECKED) ) + continue; /* skip unchecked signatures */ + if( !(rec.r.sig.sig[i].flag & SIGF_VALID) ) + continue; /* skip invalid signatures */ + if( (rec.r.sig.sig[i].flag & SIGF_EXPIRED) ) + continue; /* skip expired signatures */ + if( (rec.r.sig.sig[i].flag & SIGF_REVOKED) ) + continue; /* skip revoked signatures */ + + /* visit every signer only once (a signer may have + * signed multizple user IDs */ + if( sigs_seen && ins_lid_table_item( sigs_seen, + rec.r.sig.sig[i].lid, 0) ) + continue; /* we alread have this one */ + + read_record( rec.r.sig.sig[i].lid, &tmp, 0 ); + if( tmp.rectype != RECTYPE_DIR ) { + log_info("oops: lid %lu: sig %lu has rectype %d" + " - skipped\n", + drec->r.dir.lid, tmp.recnum, tmp.rectype ); + continue; + } + ot = tmp.r.dir.ownertrust & TRUST_MASK; + if( ot >= TRUST_FULLY ) + ot = TRUST_FULLY; /* just in case */ + nt = collect_paths( depth+1, max_depth, all, &tmp, stack, + trust_seg_head ); + nt &= TRUST_MASK; + + if( nt < TRUST_MARGINAL ) { + continue; + } + + if( nt == TRUST_ULTIMATE ) { + /* 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 ); + return (stack[depth].trust = TRUST_FULLY); + } + } + + if( nt >= TRUST_FULLY ) + fully++; + if( nt >= TRUST_MARGINAL ) + marginal++; + + if( fully >= opt.completes_needed + || marginal >= opt.marginals_needed ) { + if( !all ) { + if( sigs_seen ) + release_lid_table( sigs_seen ); + return (stack[depth].trust = TRUST_FULLY); + } + } + } + } + } + if( sigs_seen ) + release_lid_table( sigs_seen ); + if( all && ( fully >= opt.completes_needed + || marginal >= opt.marginals_needed ) ) { + return (stack[depth].trust = TRUST_FULLY ); + } + if( marginal ) { + return (stack[depth].trust = TRUST_MARGINAL); + } + return (stack[depth].trust=TRUST_UNDEFINED); +} + + /**************** * Given the directory record of a key, check whether we can * find a path to an ultimately trusted key. We do this by * checking all key signatures up to a some depth. */ static int -verify_key( int depth, int max_depth, TRUSTREC *drec ) +verify_key( int max_depth, TRUSTREC *drec ) { - ulong rn, uidrn; - int marginal=0; - int fully=0; - size_t dbglen; + TRUST_INFO *tmppath = m_alloc_clear( (max_depth+1)* sizeof *tmppath ); + int tr; - /* Note: If used stack size is an issue, we could reuse the - * trustrec vars and reread them as needed */ - - dbglen = printf("verify_key: depth=%d %*s", depth, depth*3,"" ); - dbglen += print_keyid( stdout, drec->recnum ); - dbglen += printf(" ot="); - dbglen += print_trust(stdout, drec->r.dir.ownertrust ); - dbglen += printf(" -> "); - - if( depth >= max_depth ) { - /* max cert_depth reached */ - puts("undefined (too deep)"); - return TRUST_UNDEFINED; - } - if( !qry_lid_table_flag( ultikey_table, drec->r.dir.lid, NULL ) ) { - /* we are at the end of a path */ - puts("ultimate"); - return TRUST_ULTIMATE; - } - - /* loop over all user-ids */ - for( rn = drec->r.dir.uidlist; rn; rn = uidrn ) { - TRUSTREC rec; /* used for uids and sigs */ - ulong sigrn; - - read_record( rn, &rec, RECTYPE_UID ); - uidrn = rec.r.uid.next; - /* fixme: continue if the uidrec is not marked valid */ - - /* loop over all signature records */ - for( rn = rec.r.uid.siglist; rn; rn = sigrn ) { - int i; - - read_record( rn, &rec, RECTYPE_SIG ); - sigrn = rec.r.sig.next; - - for(i=0; i < SIGS_PER_RECORD; i++ ) { - TRUSTREC tmp; - int ot, nt; - - if( !rec.r.sig.sig[i].lid ) - continue; /* skip deleted sigs */ - if( !(rec.r.sig.sig[i].flag & SIGF_CHECKED) ) - continue; /* skip unchecked signatures */ - if( !(rec.r.sig.sig[i].flag & SIGF_VALID) ) - continue; /* skip invalid signatures */ - if( (rec.r.sig.sig[i].flag & SIGF_EXPIRED) ) - continue; /* skip expired signatures */ - if( (rec.r.sig.sig[i].flag & SIGF_REVOKED) ) - continue; /* skip revoked signatures */ - /* fixme: skip duplicates */ - - read_record( rec.r.sig.sig[i].lid, &tmp, RECTYPE_DIR ); - ot = tmp.r.dir.ownertrust & TRUST_MASK; - #if 0 /* Does not work, because the owner trust of our - * own keys is not always set - * -- fix this in verify_own_keys() ? */ - if( ot < TRUST_MARGINAL ) { - printf(". "); - continue; /* ownertrust is too low; don't need to check */ - } - #endif - if( ot >= TRUST_FULLY ) - ot = TRUST_FULLY; /* just in case */ - - puts(""); - nt = verify_key( depth+1, max_depth, &tmp ) & TRUST_MASK; - if( nt < TRUST_MARGINAL ) { - printf("%*s* ", dbglen, ""); - dbglen += 2; - continue; - } - - if( nt == TRUST_ULTIMATE ) { - /* we have signed this key and only in this special case - * we assume a completes-needed or marginals-needed of 1 */ - printf("%*s", dbglen, ""); - if( ot == TRUST_MARGINAL ) - puts("marginal (1st level)"); - else if( ot == TRUST_FULLY ) - puts("fully (1st level)"); - else - puts("????? (1st level)"); - return ot; - } - - if( nt >= TRUST_FULLY ) - fully++; - if( nt >= TRUST_MARGINAL ) - marginal++; - - if( fully >= opt.completes_needed - || marginal >= opt.marginals_needed ) { - printf("%*s", dbglen, ""); - puts("fully"); - return TRUST_FULLY; - } - } - } - } - printf("%*s", dbglen, ""); - if( marginal ) { - puts("marginal"); - return TRUST_MARGINAL; - } - puts("undefined"); - return TRUST_UNDEFINED; + tr = collect_paths( 0, max_depth, 0, drec, tmppath, NULL ); + m_free( tmppath ); + return tr; } -static int -list_paths( int depth, int max_depth, TRUSTREC *drec ) -{ - ulong rn, uidrn; - int marginal=0; - int fully=0; - size_t dbglen; - - if( depth >= max_depth ) { - /* max cert_depth reached */ - puts("undefined (too deep)"); - return TRUST_UNDEFINED; - } - if( !qry_lid_table_flag( ultikey_table, drec->r.dir.lid, NULL ) ) { - /* we are at the end of a path */ - puts("ultimate"); - return TRUST_ULTIMATE; - } - - /* loop over all user-ids */ - for( rn = drec->r.dir.uidlist; rn; rn = uidrn ) { - TRUSTREC rec; /* used for uids and sigs */ - ulong sigrn; - - read_record( rn, &rec, RECTYPE_UID ); - uidrn = rec.r.uid.next; - /* fixme: continue if the uidrec is not marked valid */ - - /* loop over all signature records */ - for( rn = rec.r.uid.siglist; rn; rn = sigrn ) { - int i; - - read_record( rn, &rec, RECTYPE_SIG ); - sigrn = rec.r.sig.next; - - for(i=0; i < SIGS_PER_RECORD; i++ ) { - TRUSTREC tmp; - int ot, nt; - - if( !rec.r.sig.sig[i].lid ) - continue; /* skip deleted sigs */ - if( !(rec.r.sig.sig[i].flag & SIGF_CHECKED) ) - continue; /* skip unchecked signatures */ - if( !(rec.r.sig.sig[i].flag & SIGF_VALID) ) - continue; /* skip invalid signatures */ - if( (rec.r.sig.sig[i].flag & SIGF_EXPIRED) ) - continue; /* skip expired signatures */ - if( (rec.r.sig.sig[i].flag & SIGF_REVOKED) ) - continue; /* skip revoked signatures */ - /* fixme: skip duplicates */ - - read_record( rec.r.sig.sig[i].lid, &tmp, RECTYPE_DIR ); - ot = tmp.r.dir.ownertrust & TRUST_MASK; - if( ot < TRUST_MARGINAL ) { - printf(". "); - continue; /* ownertrust is too low; don't need to check */ - } - - if( ot >= TRUST_FULLY ) - ot = TRUST_FULLY; /* just in case */ - - puts(""); - nt = verify_key( depth+1, max_depth, &tmp ) & TRUST_MASK; - if( nt < TRUST_MARGINAL ) { - printf("%*s* ", dbglen, ""); - dbglen += 2; - continue; - } - - if( nt == TRUST_ULTIMATE ) { - /* we have signed this key and only in this special case - * we assume a completes-needed or marginals-needed of 1 */ - printf("%*s", dbglen, ""); - if( ot == TRUST_MARGINAL ) - puts("marginal (1st level)"); - else if( ot == TRUST_FULLY ) - puts("fully (1st level)"); - else - puts("????? (1st level)"); - return ot; - } - - if( nt >= TRUST_FULLY ) - fully++; - if( nt >= TRUST_MARGINAL ) - marginal++; - - if( fully >= opt.completes_needed - || marginal >= opt.marginals_needed ) { - printf("%*s", dbglen, ""); - puts("fully"); - return TRUST_FULLY; - } - } - } - } - printf("%*s", dbglen, ""); - if( marginal ) { - puts("marginal"); - return TRUST_MARGINAL; - } - puts("undefined"); - return TRUST_UNDEFINED; -} /**************** @@ -937,7 +891,7 @@ do_check( TRUSTREC *dr, unsigned *trustlevel ) return G10ERR_TRUSTDB; } - *trustlevel = verify_key( 1, 5, dr ); + *trustlevel = verify_key( 5, dr ); if( dr->r.dir.dirflags & DIRF_REVOKED ) *trustlevel |= TRUST_FLAG_REVOKED; @@ -1092,6 +1046,7 @@ import_ownertrust( const char *fname ) n = strlen(line); if( line[n-1] != '\n' ) { log_error_f(fname, "line to long\n" ); + /* ... or last line does not have a LF */ break; /* can't continue */ } for(p = line; *p && *p != ':' ; p++ ) @@ -1161,20 +1116,44 @@ import_ownertrust( const char *fname ) } + + +static void +print_path( int pathlen, TRUST_INFO *path ) +{ + int rc, i; + u32 keyid[2]; + + fputs("path:", stdout); + for( i = 0; i < pathlen; i++ ) { + if( i && !(i%4) ) + fputs(" ", stdout ); + rc = keyid_from_lid( path[i].lid, keyid ); + if( rc ) + printf(" ????????.%lu:", path[i].lid ); + else + printf(" %08lX.%lu:", (ulong)keyid[1], path[i].lid ); + print_sigflags( stdout, path[i].otrust ); + } + putchar('\n'); +} + + + void list_trust_path( int max_depth, const char *username ) { int rc; int wipe=0; TRUSTREC rec; + TRUST_INFO *tmppath; + TRUST_SEG_LIST trust_seg_list, tsl, tsl2; PKT_public_key *pk = m_alloc_clear( sizeof *pk ); if( max_depth < 0 ) { wipe = 1; max_depth = -max_depth; } - if( max_depth < 1 ) - max_depth = 1; if( (rc = get_pubkey_byname( pk, username )) ) log_error("user '%s' not found: %s\n", username, g10_errstr(rc) ); @@ -1190,14 +1169,30 @@ list_trust_path( int max_depth, const char *username ) assert( pk->local_id ); } } - - free_public_key( pk ); + + /* collect the paths */ + tmppath = m_alloc_clear( (max_depth+1)* sizeof *tmppath ); + trust_seg_list = NULL; + collect_paths( 0, max_depth, 1, &rec, tmppath, &trust_seg_list ); + m_free( tmppath ); + /* and now print them */ + for(tsl = trust_seg_list; tsl; tsl = tsl->next ) { + print_path( tsl->pathlen, tsl->path ); + } + + /* release the list */ + for(tsl = trust_seg_list; tsl; tsl = tsl2 ) { + tsl2 = tsl->next; + m_free( tsl ); + } + trust_seg_list = NULL; } /**************** * Check the complete trustdb or only the entries for the given username. + * We check the complete database and recalculate all flags. */ void check_trustdb( const char *username ) @@ -1218,7 +1213,7 @@ check_trustdb( const char *username ) else { int modified; - rc = update_trust_record( keyblock, &modified ); + rc = update_trust_record( keyblock, 0, &modified ); if( rc == -1 ) { /* not yet in trustdb: insert */ rc = insert_trust_record( find_kbnode( keyblock, PKT_PUBLIC_KEY @@ -1265,7 +1260,7 @@ check_trustdb( const char *username ) continue; } - rc = update_trust_record( keyblock, &modified ); + rc = update_trust_record( keyblock, 0, &modified ); if( rc ) { log_error("lid %lu: update failed: %s\n", recnum, g10_errstr(rc) ); @@ -1295,6 +1290,10 @@ check_trustdb( const char *username ) } +/**************** + * Put new entries from the pubrings into the trustdb. + * This function honors the sig flags to speed up the check. + */ void update_trustdb( ) { @@ -1309,7 +1308,7 @@ update_trustdb( ) while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) { int modified; - rc = update_trust_record( keyblock, &modified ); + rc = update_trust_record( keyblock, 1, &modified ); if( rc == -1 ) { /* not yet in trustdb: insert */ PKT_public_key *pk = find_kbnode( keyblock, PKT_PUBLIC_KEY @@ -1904,13 +1903,34 @@ create_shadow_dir( PKT_signature *sig, ulong lid ) } +/**************** + * This function checks the given public key and inserts or updates + * the keyrecord from the trustdb. Revocation certificates + * are handled here and the keybinding of subkeys is checked. + * Hmmm: Should we check here, that the key has at least one valid + * user ID or do we allow keys w/o user ID? + * + * keyblock points to the first node in the keyblock, + * keynode is the node with the public key to check + * (either primary or secondary), keyid is the keyid of + * the primary key, drec is the directory record and recno_list + * is a list used to keep track of visited records. + * Existing keyflags are recalculated if recheck is true. + */ static void -upd_key_record( PKT_public_key *pk, TRUSTREC *drec, RECNO_LIST *recno_list ) +upd_key_record( KBNODE keyblock, KBNODE keynode, u32 *keyid, + TRUSTREC *drec, RECNO_LIST *recno_list, int recheck ) { TRUSTREC krec; + KBNODE node; + PKT_public_key *pk = keynode->pkt->pkt.public_key,; + ulon lid = drec->recnum; byte fpr[MAX_FINGERPRINT_LEN]; size_t fprlen; ulong recno, newrecno; + int keybind_seen = 0; + int revoke_seen = 0; + int rc; fingerprint_from_pk( pk, fpr, &fprlen ); /* do we already have this key? */ @@ -1924,9 +1944,10 @@ upd_key_record( PKT_public_key *pk, TRUSTREC *drec, RECNO_LIST *recno_list ) ins_recno_list( recno_list, recno, RECTYPE_KEY ); } else { /* no: insert this new key */ + recheck = 1; memset( &krec, 0, sizeof(krec) ); krec.rectype = RECTYPE_KEY; - krec.r.key.lid = drec->recnum; + krec.r.key.lid = lid; krec.r.key.pubkey_algo = pk->pubkey_algo; krec.r.key.fingerprint_len = fprlen; memcpy(krec.r.key.fingerprint, fpr, fprlen ); @@ -1939,23 +1960,127 @@ upd_key_record( PKT_public_key *pk, TRUSTREC *drec, RECNO_LIST *recno_list ) drec->r.dir.keylist = newrecno; drec->dirty = 1; } - else { /* we already have a key, append it to the list */ + else { /* we already have a key, append the new one */ + TRUSTREC save = krec; for( ; recno; recno = krec.r.key.next ) read_record( recno, &krec, RECTYPE_KEY ); krec.r.key.next = newrecno; write_record( &krec ); + krec = save; } } + + if( !recheck && (krec.r.key.keyflags & KEYF_CHECKED) ) + return; + + /* check keybindings and revocations */ + krec.r.key.keyflags = 0; + if( keynode->pkt->pkttype == PKT_PUBLIC_KEY ) { + /* we assume that a primary key is always valid + * and check later whether we have a revocation */ + krec.r.key.keyflags |= KEYF_CHECKED | KEYF_VALID; + } + + for( node=keynode->next; node; node = node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + break; /* ready */ + else if( node->pkt->pkttype == PKT_PUBLIC_SIGNATURE ) { + PKT_signature *sig = node->pkt->pkt.signature; + + if( keyid[0] != sig->keyid[0] || keyid[1] != sig->keyid[1] ) + continue; /* not a self signature */ + if( sig->sig_class == 0x18 && !keybind_seen ) { /* a keybinding */ + if( keynode->pkt->pkttype == PKT_PUBLIC_KEY ) + continue; /* oops, not for a main key */ + /* we check until we find a valid keybinding */ + rc = check_key_signature( keyblock, node, NULL ); + if( !rc ) { + if( opt.verbose ) + log_info(_( + "key %08lX.%lu: Good subkey binding\n"), + (ulong)keyid_from_pk(pk,NULL), lid ); + krec.r.key.keyflags |= KEYF_CHECKED | KEYF_VALID; + } + else { + log_info(_( + "key %08lX.%lu: Invalid subkey binding: %s\n"), + (ulong)keyid_from_pk(pk,NULL), lid, g10_errstr(rc) ); + krec.r.key.keyflags |= KEYF_CHECKED; + krec.r.key.keyflags &= ~KEYF_VALID; + } + keybind_seen = 1; + } + else if( sig->sig_class == 0x20 && !revoke_seen ) { + if( keynode->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + continue; /* a subkey is not expected here */ + /* This is a key revocation certificate: check it */ + rc = check_key_signature( keyblock, node, NULL ); + if( !rc ) { + if( opt.verbose ) + log_info(_( + "key %08lX.%lu: Valid key revocation\n"), + (ulong)keyid_from_pk(pk,NULL), lid ); + krec.r.key.keyflags |= KEYF_REVOKED; + } + else { + log_info(_( + "key %08lX.%lu: Invalid key revocation: %s\n"), + (ulong)keyid_from_pk(pk,NULL), lid, g10_errstr(rc) ); + } + revoke_seen = 1; + } + else if( sig->sig_class == 0x28 && !revoke_seen ) { + if( keynode->pkt->pkttype == PKT_PUBLIC_KEY ) + continue; /* a mainkey is not expected here */ + /* This is a subkey revocation certificate: check it */ + /* fixme: we should also check the revocation + * is newer tha the key (OpenPGP) */ + rc = check_key_signature( keyblock, node, NULL ); + if( !rc ) { + if( opt.verbose ) + log_info(_( + "key %08lX.%lu: Valid subkey revocation\n"), + (ulong)keyid_from_pk(pk,NULL), lid ); + krec.r.key.keyflags |= KEYF_REVOKED; + } + else { + log_info(_( + "key %08lX.%lu: Invalid subkey binding: %s\n"), + (ulong)keyid_from_pk(pk,NULL), lid, g10_errstr(rc) ); + } + revoke_seen = 1; + } + } /* end signature */ + } + + write_record( &krec ); } +/**************** + * This function checks the given user ID and inserts or updates + * the uid record of the trustdb. Revocation certificates + * are handled here. + * + * keyblock points to the first node in the keyblock, + * uidnode is the node with the user id to check + * keyid is the keyid of + * the primary key, drec is the directory record and recno_list + * is a list used to keep track of visited records. + * Existing uidflags are recalculated if recheck is true. + */ static void -upd_uid_record( PKT_user_id *uid, TRUSTREC *drec, RECNO_LIST *recno_list, - u32 *keyid, ulong *uidrecno, byte *uidhash ) +upd_uid_record( KBNODE keyblock, KBNODE uidnode, u32 *keyid, + TRUSTREC *drec, RECNO_LIST *recno_list, int recheck ) { + ulong lid = drec->recnum; + PKT_user_id *uid = uidnode->pkt->pkt.user_id; TRUSTREC urec; + byte uidhash[20]; ulong recno, newrecno; + /* see whether we already have an uid record */ + WORK WORK rmd160_hash_buffer( uidhash, uid->name, uid->len ); for( recno=drec->r.dir.uidlist; recno; recno = urec.r.uid.next ) { read_record( recno, &urec, RECTYPE_UID ); @@ -2014,7 +2139,7 @@ upd_pref_record( PKT_signature *sig, ulong lid, const u32 *keyid, /* First delete all pref records * This is much simpler than checking whether we have to * do update the record at all - the record cache may care about it - * FIXME: We never get correct statistics if we di it like this */ + * FIXME: We never get correct statistics if we do it like this */ for( recno=urec->r.uid.prefrec; recno; recno = prec.r.pref.next ) { read_record( recno, &prec, RECTYPE_PREF ); delete_record( recno ); @@ -2097,13 +2222,14 @@ upd_self_key_sigs( PKT_signature *sig, TRUSTREC *urec, } + /**************** * update non-self key signatures (class 0x10..0x13) */ static void upd_nonself_key_sigs( PKT_signature *sig, TRUSTREC *urec, ulong lid, const u32 *keyid, const byte *uidhash, - KBNODE keyblock, KBNODE signode) + KBNODE keyblock, KBNODE signode, int fast) { /* We simply insert the signature into the sig records but * avoid duplicate ones. We do not check them here because @@ -2178,9 +2304,9 @@ upd_nonself_key_sigs( PKT_signature *sig, TRUSTREC *urec, } found_sig = 1; } - if( rec.r.sig.sig[i].flag & SIGF_CHECKED ) + if( fast && (rec.r.sig.sig[i].flag & SIGF_CHECKED) ) continue; /* we already checked this signature */ - if( rec.r.sig.sig[i].flag & SIGF_NOPUBKEY ) + if( fast && (rec.r.sig.sig[i].flag & SIGF_NOPUBKEY) ) continue; /* we do not have the public key */ read_record( rec.r.sig.sig[i].lid, &tmp, 0 ); @@ -2197,10 +2323,11 @@ upd_nonself_key_sigs( PKT_signature *sig, TRUSTREC *urec, rec.r.sig.sig[i].flag = SIGF_CHECKED | SIGF_VALID; } else if( rc == G10ERR_NO_PUBKEY ) { - log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " - "weird: no public key\n"), - (ulong)keyid[1], lid, uidhash[18], - uidhash[19], (ulong)sig->keyid[1] ); + if( (rec.r.sig.sig[i].flag & SIGF_CHECKED) ) + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "public key lost\n"), + (ulong)keyid[1], lid, uidhash[18], + uidhash[19], (ulong)sig->keyid[1] ); rec.r.sig.sig[i].flag = SIGF_NOPUBKEY; } else { @@ -2219,8 +2346,9 @@ upd_nonself_key_sigs( PKT_signature *sig, TRUSTREC *urec, && tmp.r.sdir.keyid[1] == sig->keyid[1] && (!tmp.r.sdir.pubkey_algo || tmp.r.sdir.pubkey_algo == sig->pubkey_algo )) { - log_info(_("key %08lX.%lu, uid %02X%02X: " - "has shadow dir %lu but not yet marked.\n"), + if( !(rec.r.sig.sig[i].flag & SIGF_NOPUBKEY) ) + log_info(_("key %08lX.%lu, uid %02X%02X: " + "has shadow dir %lu but not yet marked.\n"), (ulong)keyid[1], lid, uidhash[18], uidhash[19], tmp.recnum ); rec.r.sig.sig[i].flag = SIGF_NOPUBKEY; @@ -2314,7 +2442,7 @@ upd_nonself_key_sigs( PKT_signature *sig, TRUSTREC *urec, static void upd_sig_record( PKT_signature *sig, TRUSTREC *drec, u32 *keyid, ulong *uidrecno, byte *uidhash, - KBNODE keyblock, KBNODE signode) + KBNODE keyblock, KBNODE signode, int fast) { TRUSTREC urec; ulong lid = drec->recnum; @@ -2342,9 +2470,6 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, keyblock, signode ); } else if( sig->sig_class == 0x18 ) { /* key binding */ - /* get the corresponding key */ - - /* FIXME */ } else if( sig->sig_class == 0x20 ) { /* key revocation */ /* FIXME */ @@ -2358,7 +2483,7 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, } else if( (sig->sig_class&~3) == 0x10 ) { upd_nonself_key_sigs( sig, &urec, lid, keyid, uidhash, - keyblock, signode ); + keyblock, signode, fast ); } else if( sig->sig_class == 0x18 ) { /* key binding */ log_info(_("key %08lX: bogus key binding by %08lX\n"), @@ -2387,11 +2512,11 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, * Update all the info from the public keyblock. * The key must already exist in the keydb. * This function is responsible for checking the signatures in cases - * where the public key is already available. If we no not have the public + * where the public key is already available. If we do not have the public * key, the check is done by some special code in insert_trust_record(). */ int -update_trust_record( KBNODE keyblock, int *modified ) +update_trust_record( KBNODE keyblock, int recheck, int *modified ) { PKT_public_key *primary_pk; KBNODE node; @@ -2421,44 +2546,31 @@ update_trust_record( KBNODE keyblock, int *modified ) keyid_from_pk( primary_pk, keyid ); + /* fixme: check that the keyblock has a valid structure */ + rc = tdbio_begin_transaction(); if( rc ) return rc; - /* now update keys and user ids */ + /* update the keys */ for( node=keyblock; node; node = node->next ) { - switch( node->pkt->pkttype ) { - case PKT_PUBLIC_KEY: - case PKT_PUBLIC_SUBKEY: - uidrecno = 0; - upd_key_record( node->pkt->pkt.public_key, &drec, &recno_list ); - break; - - case PKT_USER_ID: - if( drec.dirty ) { /* upd_pref_record may read the drec */ - write_record( &drec ); - drec.dirty = 0; - } - upd_uid_record( node->pkt->pkt.user_id, &drec, &recno_list, - keyid, &uidrecno, uidhash ); - break; - - case PKT_SIGNATURE: - if( drec.dirty ) { /* upd_sig_recory may read the drec */ - write_record( &drec ); - drec.dirty = 0; - } - upd_sig_record( node->pkt->pkt.signature, &drec, keyid, - &uidrecno, uidhash, keyblock, node ); - break; - - default: - break; - } - } /* end loop over all nodes */ + if( node->pkt->pkttype == PKT_PUBLIC_KEY + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + upd_key_record( keyblock, node, keyid, + &drec, &recno_list, recheck ); + } + /* update the user IDs */ + for( node=keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_USER_ID ) + upd_uid_record( keyblock, node, keyid, + &drec, &recno_list, recheck ); + } + WORk - WORK /* delete keyrecords from the trustdb which are not anymore used */ + /* should we really do this, or is it better to keep them and */ + /* mark as unused? */ lastrecno = 0; for( recno=drec.r.dir.keylist; recno; recno = krec.r.key.next ) { read_record( recno, &krec, RECTYPE_KEY ); @@ -2623,7 +2735,7 @@ insert_trust_record( PKT_public_key *pk ) } /* and put all the other stuff into the keydb */ - rc = update_trust_record( keyblock, NULL ); + rc = update_trust_record( keyblock, 0, NULL ); if( !rc ) process_hintlist( hintlist, dirrec.r.dir.lid ); diff --git a/g10/trustdb.h b/g10/trustdb.h index 01d3dab55..4dc8b2ccb 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -60,7 +60,7 @@ ulong lid_from_keyblock( KBNODE keyblock ); int query_trust_record( PKT_public_key *pk ); int clear_trust_checked_flag( PKT_public_key *pk ); int insert_trust_record( PKT_public_key *pk ); -int update_trust_record( KBNODE keyblock, int *modified ); +int update_trust_record( KBNODE keyblock, int fast, int *modified ); int update_ownertrust( ulong lid, unsigned new_trust ); /*-- pkclist.c --*/ diff --git a/include/util.h b/include/util.h index 5dd656e72..56098ae6e 100644 --- a/include/util.h +++ b/include/util.h @@ -152,6 +152,8 @@ const char *memistr( const char *buf, size_t buflen, const char *sub ); char *mem2str( char *, const void *, size_t); char *trim_spaces( char *string ); int string_count_chr( const char *string, int c ); +char *native_to_utf8( const char *string ); +char *utf8_to_native( const char *string ); #define stricmp(a,b) strcasecmp((a),(b)) diff --git a/mpi/ChangeLog b/mpi/ChangeLog index 73f296d69..893c4c28e 100644 --- a/mpi/ChangeLog +++ b/mpi/ChangeLog @@ -1,6 +1,10 @@ +Tue Oct 27 12:37:46 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links (freebsd): Fixes for FreeBSD 3.0 + Wed Oct 14 09:59:30 1998 Werner Koch (wk@isil.d.shuttle.de) - * config-links (freebsd): ELF patches from Jun Kuriyama. + * config.links (freebsd): ELF patches from Jun Kuriyama. Thu Oct 8 13:28:17 1998 Werner Koch (wk@isil.d.shuttle.de) diff --git a/mpi/config.links b/mpi/config.links index 5c3f960df..308733c21 100644 --- a/mpi/config.links +++ b/mpi/config.links @@ -10,12 +10,12 @@ test -d ./mpi || mkdir ./mpi echo '/* created by config.links - do not edit */' >./mpi/asm-syntax.h case "${target}" in - i[34]86*-*-freebsd*-elf) + i[34]86*-*-freebsd*-elf | i[34]86*-*-freebsd3*) echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h path="i386" ;; - i[56]86*-*-freebsd*-elf) + i[56]86*-*-freebsd*-elf | i[56]86*-*-freebsd3*) echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h path="i586 i386" diff --git a/po/ChangeLog b/po/ChangeLog index 5c4611e71..b9ec290d3 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,7 @@ +Fri Oct 30 20:03:17 1998 Werner Koch (wk@isil.d.shuttle.de) + + * fr.po: Imported new version + Mon Oct 12 09:08:09 1998 Werner Koch (wk@isil.d.shuttle.de) * it.po: Imported new version. diff --git a/po/fr.po b/po/fr.po index f6c2bc064..9bb50bee5 100644 --- a/po/fr.po +++ b/po/fr.po @@ -1,12 +1,12 @@ -# gnupg french translation +# GnuPG french translation # Copyright (C) 1998 Free Software Foundation, Inc. # Gaël Quéri , 1998. # msgid "" msgstr "" -"Project-Id-Version: gnupg-0.4.1\n" -"POT-Creation-Date: 1998-10-18 16:36+0200\n" -"PO-Revision-Date: 1998-10-11 00:21+0200\n" +"Project-Id-Version: gnupg-0.4.1a\n" +"POT-Creation-Date: 1998-10-29 17:30+0100\n" +"PO-Revision-Date: 1998-10-29 19:01+0100\n" "Last-Translator: Gaël Quéri \n" "Language-Team: French \n" "MIME-Version: 1.0\n" @@ -199,8 +199,8 @@ msgstr "Mauvaise cl #: util/logger.c:177 #, c-format -msgid "Ohhhh jeeee ... this is a bug (%s:%d:%s)\n" -msgstr "Ouais ... c'est un bug (%s:%d:%s)\n" +msgid "... this is a bug (%s:%d:%s)\n" +msgstr "... c'est un bug (%s:%d:%s)\n" #: util/logger.c:183 #, c-format @@ -237,7 +237,7 @@ msgstr "" "Il n'y a pas assez d'octets aléatoires disponibles. Faites autre chose\n" "pour que l'OS puisse amasser plus d'entropie! (il faut %d octets de plus)\n" -#: g10/g10.c:149 +#: g10/g10.c:151 msgid "" "@Commands:\n" " " @@ -245,124 +245,124 @@ msgstr "" "@Commandes:\n" " " -#: g10/g10.c:152 +#: g10/g10.c:154 msgid "|[file]|make a signature" msgstr "|[fichier]|faire une signature" -#: g10/g10.c:153 +#: g10/g10.c:155 msgid "|[file]|make a clear text signature" msgstr "|[fichier]|faire une signature en texte clair" -#: g10/g10.c:154 +#: g10/g10.c:156 msgid "make a detached signature" msgstr "faire une signature détachée" -#: g10/g10.c:155 +#: g10/g10.c:157 msgid "encrypt data" msgstr "crypter les données" -#: g10/g10.c:156 +#: g10/g10.c:158 msgid "encryption only with symmetric cipher" msgstr "chiffrement symétrique seumement" -#: g10/g10.c:157 +#: g10/g10.c:159 msgid "store only" msgstr "pas d'action" -#: g10/g10.c:158 +#: g10/g10.c:160 msgid "decrypt data (default)" msgstr "décrypter les données (défaut)" -#: g10/g10.c:159 +#: g10/g10.c:161 msgid "verify a signature" msgstr "vérifier une signature" -#: g10/g10.c:161 +#: g10/g10.c:163 msgid "list keys" msgstr "lister les clés" -#: g10/g10.c:162 +#: g10/g10.c:164 msgid "list keys and signatures" msgstr "lister les clés et les signatures" -#: g10/g10.c:163 +#: g10/g10.c:165 msgid "check key signatures" msgstr "vérifier les signatures des clés" -#: g10/g10.c:164 +#: g10/g10.c:166 msgid "list keys and fingerprints" msgstr "lister les clés et les empreintes" -#: g10/g10.c:165 +#: g10/g10.c:167 msgid "list secret keys" msgstr "lister les clés secrètes" -#: g10/g10.c:167 +#: g10/g10.c:169 msgid "generate a new key pair" msgstr "générer une nouvelle paire de clés" -#: g10/g10.c:169 +#: g10/g10.c:171 msgid "remove key from the public keyring" msgstr "enlever la clé du porte-clés public" -#: g10/g10.c:171 +#: g10/g10.c:173 msgid "sign or edit a key" msgstr "signer ou éditer une clé" -#: g10/g10.c:172 +#: g10/g10.c:174 msgid "generate a revocation certificate" msgstr "générer un certificat de révocation" -#: g10/g10.c:174 +#: g10/g10.c:176 msgid "export keys" msgstr "exporter les clés" -#: g10/g10.c:176 +#: g10/g10.c:178 msgid "import/merge keys" msgstr "importer/fusionner les clés" -#: g10/g10.c:177 +#: g10/g10.c:180 msgid "list only the sequence of packets" msgstr "ne lister qu'une suite de paquets" -#: g10/g10.c:180 +#: g10/g10.c:183 msgid "export the ownertrust values" msgstr "exporter les valeurs de confiance" -#: g10/g10.c:182 +#: g10/g10.c:185 msgid "import ownertrust values" msgstr "importer les valeurs de confiance" -#: g10/g10.c:184 -#, fuzzy +# +#: g10/g10.c:187 msgid "|[NAMES]|update the trust database" -msgstr "|[NOMS]|vérifier la base de confiance" +msgstr "|[NOMS]|mettre la base de confiance à jour" -#: g10/g10.c:186 +#: g10/g10.c:189 msgid "|[NAMES]|check the trust database" msgstr "|[NOMS]|vérifier la base de confiance" -#: g10/g10.c:187 +#: g10/g10.c:190 msgid "fix a corrupted trust database" msgstr "réparer une base de confiance corrompue" -#: g10/g10.c:188 +#: g10/g10.c:191 msgid "De-Armor a file or stdin" msgstr "Enlever l'armure d'un fichier ou de stdin" -#: g10/g10.c:189 +#: g10/g10.c:192 msgid "En-Armor a file or stdin" msgstr "Mettre une armure à un fichier ou à stdin" -#: g10/g10.c:190 +#: g10/g10.c:193 msgid "|algo [files]|print message digests" msgstr "|alg. [fich.]|indiquer les fonctions de hachage" -#: g10/g10.c:191 +#: g10/g10.c:194 msgid "print all message digests" msgstr "écrire toutes les fonctions de hachage" -#: g10/g10.c:198 +#: g10/g10.c:201 msgid "" "@\n" "Options:\n" @@ -372,129 +372,133 @@ msgstr "" "Options:\n" " " -#: g10/g10.c:200 +#: g10/g10.c:203 msgid "create ascii armored output" msgstr "créer une sortie ascii armurée" -#: g10/g10.c:202 +#: g10/g10.c:205 msgid "use this user-id to sign or decrypt" msgstr "utiliser ce nom pour signer ou décrypter" -#: g10/g10.c:203 +#: g10/g10.c:206 msgid "use this user-id for encryption" msgstr "utiliser ce nom d'utilisateur pour crypter" -#: g10/g10.c:204 +#: g10/g10.c:207 msgid "|N|set compress level N (0 disables)" msgstr "|N|niveau de compression N (0 désactive)" -#: g10/g10.c:205 +#: g10/g10.c:208 msgid "use canonical text mode" msgstr "utiliser le mode de texte canonique" -#: g10/g10.c:207 +#: g10/g10.c:210 msgid "use as output file" msgstr "utiliser comme fichier de sortie" -#: g10/g10.c:208 +#: g10/g10.c:211 msgid "verbose" msgstr "bavard" -#: g10/g10.c:209 -#, fuzzy +#: g10/g10.c:212 +msgid "be somewhat more quiet" +msgstr "devenir beaucoup plus silencieux" + +# +#: g10/g10.c:213 msgid "force v3 signatures" -msgstr "vérifier les signatures des clés" +msgstr "forcer les signatures en v3" #. { oDryRun, "dry-run", 0, N_("do not make any changes") }, -#: g10/g10.c:211 +#: g10/g10.c:215 msgid "batch mode: never ask" -msgstr "mode automatique: ne jamais demander" +msgstr "mode automatique: ne jamais rien demander" -#: g10/g10.c:212 +#: g10/g10.c:216 msgid "assume yes on most questions" msgstr "supposer oui à la plupart des questions" -#: g10/g10.c:213 +#: g10/g10.c:217 msgid "assume no on most questions" msgstr "supposer non à la plupart des questions" -#: g10/g10.c:214 +#: g10/g10.c:218 msgid "add this keyring to the list of keyrings" msgstr "ajouter ce porte-clés à la liste des porte-clés" -#: g10/g10.c:215 +#: g10/g10.c:219 msgid "add this secret keyring to the list" msgstr "ajouter ce porte-clés secret à la liste" -#: g10/g10.c:216 +#: g10/g10.c:220 msgid "|NAME|use NAME as default secret key" msgstr "|NOM|utiliser NOM comme clé secrète par défaut" -#: g10/g10.c:217 +#: g10/g10.c:221 msgid "read options from file" msgstr "lire les options du fichier" -#: g10/g10.c:219 +#: g10/g10.c:223 msgid "set debugging flags" msgstr "choisir les attributs de déboguage" -#: g10/g10.c:220 +#: g10/g10.c:224 msgid "enable full debugging" msgstr "permettre un déboguage complet" -#: g10/g10.c:221 +#: g10/g10.c:225 msgid "|FD|write status info to this FD" msgstr "|FD|écrire les informations d'état sur ce descripteur" -#: g10/g10.c:222 +#: g10/g10.c:226 msgid "do not write comment packets" msgstr "ne pas écrire de paquets de commentaire" -#: g10/g10.c:223 +#: g10/g10.c:227 msgid "(default is 1)" msgstr "(1 par défaut)" -#: g10/g10.c:224 +#: g10/g10.c:228 msgid "(default is 3)" msgstr "(3 par défaut)" -#: g10/g10.c:225 +#: g10/g10.c:229 msgid "|FILE|load extension module FILE" msgstr "|FICH|charger le module d'extension FICH" -#: g10/g10.c:226 +#: g10/g10.c:230 msgid "emulate the mode described in RFC1991" msgstr "émuler le mode décrit dans la RFC1991" -#: g10/g10.c:227 +#: g10/g10.c:231 msgid "|N|use passphrase mode N" msgstr "|N|utiliser le mode de mots de passe N" -#: g10/g10.c:229 +#: g10/g10.c:233 msgid "|NAME|use message digest algorithm NAME for passphrases" msgstr "|NOM|utiliser le hachage NOM pour les mots de passe" -#: g10/g10.c:231 +#: g10/g10.c:235 msgid "|NAME|use cipher algorithm NAME for passphrases" msgstr "|NOM|utiliser le cryptage NOM pour les mots de passe" -#: g10/g10.c:233 +#: g10/g10.c:237 msgid "|NAME|use cipher algorithm NAME" msgstr "|NOM|utiliser l'algorithme de cryptage NOM" -#: g10/g10.c:234 +#: g10/g10.c:238 msgid "|NAME|use message digest algorithm NAME" msgstr "|NOM|utiliser la fonction de hachage NOM" -#: g10/g10.c:235 +#: g10/g10.c:239 msgid "|N|use compress algorithm N" msgstr "|N|utiliser l'algorithme de compression N" -#: g10/g10.c:236 +#: g10/g10.c:240 msgid "throw keyid field of encrypted packets" msgstr "enlever l'identification des paquets cryptés" -#: g10/g10.c:244 +#: g10/g10.c:248 msgid "" "@\n" "Examples:\n" @@ -514,28 +518,28 @@ msgstr "" " --list-keys [utilisateur] montrer les clés\n" " --fingerprint [utilisateur] montrer les empreintes\n" -#: g10/g10.c:319 +#: g10/g10.c:323 msgid "Please report bugs to .\n" msgstr "Rapporter toutes anomalies à .\n" -#: g10/g10.c:324 +#: g10/g10.c:328 msgid "Usage: gpgm [options] [files] (-h for help)" msgstr "Utilisation: gpgm [options] [fichiers] (-h pour l'aide)" -#: g10/g10.c:326 +#: g10/g10.c:330 msgid "Usage: gpg [options] [files] (-h for help)" msgstr "Utilisation: gpg [options] [fichiers] (-h pour l'aide)" -#: g10/g10.c:331 -#, fuzzy +# +#: g10/g10.c:335 msgid "" "Syntax: gpgm [options] [files]\n" "GnuPG maintenance utility\n" msgstr "" "Syntaxe: gpgm [options] [fichiers]\n" -"utilitaire de maitenance de GNUPG\n" +"utilitaire de maitenance de GnuPG\n" -#: g10/g10.c:334 +#: g10/g10.c:338 msgid "" "Syntax: gpg [options] [files]\n" "sign, check, encrypt or decrypt\n" @@ -545,7 +549,7 @@ msgstr "" "signer, vérifier, crypter ou décrypter\n" "l'opération par défaut dépend des données entrées\n" -#: g10/g10.c:340 +#: g10/g10.c:344 msgid "" "\n" "Supported algorithms:\n" @@ -553,141 +557,141 @@ msgstr "" "\n" "Algorithmes supportés:\n" -#: g10/g10.c:415 +#: g10/g10.c:419 msgid "usage: gpgm [options] " msgstr "utilisation: gpgm [options] " -#: g10/g10.c:417 +#: g10/g10.c:421 msgid "usage: gpg [options] " msgstr "utilisation: gpg [options] " -#: g10/g10.c:458 +#: g10/g10.c:462 msgid "conflicting commands\n" msgstr "commandes en conflit\n" -#: g10/g10.c:596 +#: g10/g10.c:600 #, c-format msgid "note: no default option file '%s'\n" msgstr "note: pas de fichier d'options par défaut '%s'\n" -#: g10/g10.c:600 +#: g10/g10.c:604 #, c-format msgid "option file '%s': %s\n" msgstr "fichier d'options '%s' : %s\n" -#: g10/g10.c:607 +#: g10/g10.c:611 #, c-format msgid "reading options from '%s'\n" msgstr "lire les options de '%s'\n" -#: g10/g10.c:778 g10/g10.c:790 +#: g10/g10.c:784 g10/g10.c:796 msgid "selected cipher algorithm is invalid\n" msgstr "l'algorithme de cryptage sélectionné est invalide\n" -#: g10/g10.c:784 g10/g10.c:796 +#: g10/g10.c:790 g10/g10.c:802 msgid "selected digest algorithm is invalid\n" msgstr "la fonction de hachage sélectionnée est invalide\n" -#: g10/g10.c:799 +#: g10/g10.c:805 #, c-format msgid "compress algorithm must be in range %d..%d\n" msgstr "l'algorithme de compression doit faire partie de l'échelle %d..%d\n" -#: g10/g10.c:801 +#: g10/g10.c:807 msgid "completes-needed must be greater than 0\n" msgstr "le nombre de signatures complètes minimal doit être supérieur à 0\n" -#: g10/g10.c:803 +#: g10/g10.c:809 msgid "marginals-needed must be greater than 1\n" msgstr "le nombre de singatures marginales minimal doit être supérieur à 1\n" -#: g10/g10.c:806 +#: g10/g10.c:812 msgid "note: simple S2K mode (0) is strongly discouraged\n" msgstr "note: le mode S2K simple (0) est fortement déconseillé\n" -#: g10/g10.c:810 +#: g10/g10.c:816 msgid "invalid S2K mode; must be 0, 1 or 3\n" msgstr "mode S2K invalide; doit être 0, 1 ou 3\n" -#: g10/g10.c:886 +#: g10/g10.c:892 #, c-format msgid "failed to initialize the TrustDB: %s\n" msgstr "n'a pas pu initialiser la base de confiance: %s\n" -#: g10/g10.c:892 +#: g10/g10.c:898 msgid "--store [filename]" msgstr "--store [nom du fichier]" -#: g10/g10.c:900 +#: g10/g10.c:906 msgid "--symmetric [filename]" msgstr "--symmetric [nom du fichier]" -#: g10/g10.c:908 +#: g10/g10.c:914 msgid "--encrypt [filename]" msgstr "--encrypt [nom du fichier]" -#: g10/g10.c:921 +#: g10/g10.c:927 msgid "--sign [filename]" msgstr "--sign [nom du fichier]" -#: g10/g10.c:934 +#: g10/g10.c:940 msgid "--sign --encrypt [filename]" msgstr "--sign --encrypt [nom du fichier]" -#: g10/g10.c:948 +#: g10/g10.c:954 msgid "--clearsign [filename]" msgstr "--clearsign [nom du fichier]" -#: g10/g10.c:960 +#: g10/g10.c:966 msgid "--decrypt [filename]" msgstr "--decrypt [nom du fichier]" -#: g10/g10.c:969 +#: g10/g10.c:975 msgid "--edit-key username" msgstr "--edit-key utilisateur" -#: g10/g10.c:977 +#: g10/g10.c:983 msgid "--delete-secret-key username" msgstr "--delete-secret-key utilisateur" -#: g10/g10.c:980 +#: g10/g10.c:986 msgid "--delete-key username" msgstr "--delete-key utilisateur" -#: g10/encode.c:215 g10/g10.c:1003 g10/keylist.c:80 +#: g10/encode.c:216 g10/g10.c:1009 #, c-format msgid "can't open %s: %s\n" msgstr "ne peut ouvrir %s: %s\n" -#: g10/g10.c:1014 +#: g10/g10.c:1020 msgid "-k[v][v][v][c] [userid] [keyring]" msgstr "-k[v][v][v][c] [utilisateur] [porte-clés]" -#: g10/g10.c:1069 +#: g10/g10.c:1076 #, c-format msgid "dearmoring failed: %s\n" msgstr "suppression d'armure non réussie: %s\n" -#: g10/g10.c:1077 +#: g10/g10.c:1084 #, c-format msgid "enarmoring failed: %s\n" msgstr "mise d'armure non réussie:%s \n" -#: g10/g10.c:1138 +#: g10/g10.c:1145 #, c-format msgid "invalid hash algorithm '%s'\n" msgstr "algorithme de hachage invalide '%s'\n" -#: g10/g10.c:1220 +#: g10/g10.c:1227 msgid "[filename]" msgstr "[nom du fichier]" -#: g10/decrypt.c:59 g10/g10.c:1222 g10/verify.c:66 +#: g10/decrypt.c:59 g10/g10.c:1229 g10/verify.c:66 #, c-format msgid "can't open '%s'\n" msgstr "ne peut ouvrir '%s'\n" -#: g10/g10.c:1269 +#: g10/g10.c:1276 msgid "" "RSA keys are deprecated; please consider creating a new key and use this key " "in the future\n" @@ -1100,7 +1104,7 @@ msgstr "" msgid "Is this correct (y/n)? " msgstr "Est-ce correct (o/n)? " -#: g10/keygen.c:561 +#: g10/keygen.c:569 msgid "" "\n" "You need a User-ID to identify your key; the software constructs the user " @@ -1116,51 +1120,51 @@ msgstr "" " \"Heinrich Heine (Der Dichter) " msgstr "Commande> " -#: g10/keyedit.c:600 +#: g10/keyedit.c:602 msgid "Need the secret key to to this.\n" msgstr "Il faut la clé secrète pour faire cela.\n" -#: g10/keyedit.c:619 +#: g10/keyedit.c:621 msgid "keyedit.save.okay" msgstr "" -#: g10/keyedit.c:620 +#: g10/keyedit.c:622 msgid "Save changes? " msgstr "Enregistrer les changements? " -#: g10/keyedit.c:622 +#: g10/keyedit.c:624 msgid "keyedit.cancel.okay" msgstr "" -#: g10/keyedit.c:623 +#: g10/keyedit.c:625 msgid "Quit without saving? " msgstr "Quitter sans enregistrer? " -#: g10/keyedit.c:633 +#: g10/keyedit.c:635 #, c-format msgid "update failed: %s\n" msgstr "la mise à jour a échoué: %s\n" -#: g10/keyedit.c:640 +#: g10/keyedit.c:642 #, c-format msgid "update secret failed: %s\n" msgstr "la mise à jour de la clé secrète a échoué: %s\n" -#: g10/keyedit.c:647 +#: g10/keyedit.c:649 msgid "Key not changed so no update needed.\n" msgstr "La clé n'a pas changé donc la mise à jour est inutile.\n" -#: g10/keyedit.c:650 g10/keyedit.c:708 +#: g10/keyedit.c:652 g10/keyedit.c:710 #, c-format msgid "update of trust db failed: %s\n" msgstr "la mise à jour de la base de confiance a échoué: %s\n" -#: g10/keyedit.c:681 +#: g10/keyedit.c:683 msgid "keyedit.sign_all.okay" msgstr "" -#: g10/keyedit.c:682 +#: g10/keyedit.c:684 msgid "Really sign all user ids? " msgstr "Signer vraiment tous les utilisateurs? " -#: g10/keyedit.c:683 +#: g10/keyedit.c:685 msgid "Hint: Select the user ids to sign\n" msgstr "Aide: Sélectionner les utilisateurs à signer\n" -#: g10/keyedit.c:719 +#: g10/keyedit.c:721 msgid "You must select at least one user id.\n" msgstr "Vous devez sélectionner au moins un utilisateur.\n" -#: g10/keyedit.c:721 +#: g10/keyedit.c:723 msgid "You can't delete the last user id!\n" msgstr "Vous ne pouvez pas supprimer le dernier utilisateur!\n" -#: g10/keyedit.c:723 +#: g10/keyedit.c:725 msgid "keyedit.remove.uid.okay" msgstr "" -#: g10/keyedit.c:724 +#: g10/keyedit.c:726 msgid "Really remove all selected user ids? " msgstr "Enlever réellement tous les utilisateurs sélectionnés? " -#: g10/keyedit.c:725 +#: g10/keyedit.c:727 msgid "Really remove this user id? " msgstr "Enlever réellement cet utilisateur? " -#: g10/keyedit.c:748 +#: g10/keyedit.c:750 msgid "You must select at least one key.\n" msgstr "Vous devez sélectionner au moins une clé.\n" -#: g10/keyedit.c:750 +#: g10/keyedit.c:752 msgid "keyedit.remove.subkey.okay" msgstr "" -#: g10/keyedit.c:752 +#: g10/keyedit.c:754 msgid "Do you really want to delete the selected keys? " msgstr "Voulez-vous supprimer les clés sélectionnées? " -#: g10/keyedit.c:753 +#: g10/keyedit.c:755 msgid "Do you really want to delete this key? " msgstr "Voulez-vous vraiment supprimer cette clé? " -#: g10/keyedit.c:800 +#: g10/keyedit.c:802 msgid "Invalid command (try \"help\")\n" msgstr "Commande invalide (essayez \"help\")\n" -#: g10/keyedit.c:1178 +#: g10/keyedit.c:1180 msgid "Please remove selections from the secret keys.\n" -msgstr "" +msgstr "Enlevez les sélections des clés secrètes.\n" -#: g10/keyedit.c:1184 -#, fuzzy +#: g10/keyedit.c:1186 msgid "Please select at most one secondary key.\n" -msgstr "Vous devez sélectionner au moins une clé.\n" - -#: g10/keyedit.c:1188 -msgid "Changing exiration time for a secondary key.\n" -msgstr "" +msgstr "Vous devez sélectionner au plus une clé secondaire.\n" #: g10/keyedit.c:1190 +msgid "Changing exiration time for a secondary key.\n" +msgstr "Changer la date d'expiration d'une clé secondaire.\n" + +#: g10/keyedit.c:1192 msgid "Changing exiration time for the primary key.\n" -msgstr "" +msgstr "Changer la date d'expiration de la clé primaire.\n" -#: g10/keyedit.c:1234 +#: g10/keyedit.c:1236 msgid "No corresponding signature in secret ring\n" -msgstr "" +msgstr "Pas de signature correspondante dans le porte-clés secret\n" -#: g10/keyedit.c:1294 +#: g10/keyedit.c:1296 #, c-format msgid "No user id with index %d\n" msgstr "Pas d'utilisateur avec l'index %d\n" -#: g10/keyedit.c:1339 +#: g10/keyedit.c:1341 #, c-format msgid "No secondary key with index %d\n" msgstr "Pas de clé secondaire avec l'index %d\n" -#: g10/mainproc.c:200 +#: g10/mainproc.c:201 #, c-format msgid "public key decryption failed: %s\n" msgstr "le décryptage de la clé publique a échoué: %s\n" -#: g10/mainproc.c:230 +#: g10/mainproc.c:231 #, c-format msgid "decryption failed: %s\n" msgstr "le décryptage a échoué: %s\n" -#: g10/mainproc.c:247 +#: g10/mainproc.c:248 msgid "note: sender requested \"for-your-eyes-only\"\n" msgstr "note: l'expéditeur a demandé \"pour vos yeux seulement\"\n" -#: g10/mainproc.c:848 +#: g10/mainproc.c:842 #, c-format msgid "Signature made %.*s using %s key ID %08lX\n" msgstr "Signature faite %.*s avec %s clé ID %08lX\n" -#: g10/mainproc.c:856 +#: g10/mainproc.c:850 msgid "BAD signature from \"" msgstr "MAUVAISE signature de \"" -#: g10/mainproc.c:857 +#: g10/mainproc.c:851 msgid "Good signature from \"" msgstr "Bonne signature de \"" -#: g10/mainproc.c:868 +#: g10/mainproc.c:862 #, c-format msgid "Can't check signature: %s\n" msgstr "Ne peut vérifier la signature: %s\n" @@ -2049,193 +2108,237 @@ msgstr "" msgid "warning: signature key expired %s\n" msgstr "attention: la clé de signature a expiré le %s\n" -#: g10/trustdb.c:122 +#: g10/trustdb.c:115 msgid "The trust DB is corrupted; please run \"gpgm --fix-trust-db\".\n" msgstr "" "La base de confiance est corrompue; exécutez \"gpgm --fix-trust-db\".\n" -#: g10/trustdb.c:389 +#: g10/trustdb.c:379 #, c-format msgid "chained sigrec %lu has a wrong owner\n" msgstr "l'enregistrement de signature %lu a un mauvais propriétaire\n" -#: g10/trustdb.c:436 -#, fuzzy, c-format +#: g10/trustdb.c:426 +#, c-format msgid "key %08lX: secret key without public key - skipped\n" -msgstr "clé %08lX: clé secrète sans clé publique\n" +msgstr "clé %08lX: clé secrète sans clé publique - non prise en compte\n" -#: g10/trustdb.c:442 +#: g10/trustdb.c:432 #, c-format msgid "key %08lX: secret and public key don't match\n" msgstr "clé %08lX: les clés secrète et publique ne correspondent pas\n" -#: g10/trustdb.c:452 +#: g10/trustdb.c:442 #, c-format msgid "key %08lX: can't put it into the trustdb\n" msgstr "clé %08lX: ne peut mettre cela dans la base de confiance\n" -#: g10/trustdb.c:458 +#: g10/trustdb.c:448 #, c-format msgid "key %08lX: query record failed\n" msgstr "clé %08lX: l'enregistrement de requête a échoué\n" -#: g10/trustdb.c:467 -#, fuzzy, c-format +#: g10/trustdb.c:457 +#, c-format msgid "key %08lX: already in secret key table\n" -msgstr "clé %08lX: déjà dans le porte-clés secret\n" +msgstr "clé %08lX: déjà dans la table des clés secrètes\n" -#: g10/trustdb.c:470 -#, fuzzy, c-format +#: g10/trustdb.c:460 +#, c-format msgid "key %08lX: accepted as secret key.\n" -msgstr "clé %08lX: déjà dans le porte-clés secret\n" +msgstr "clé %08lX: acceptée comme clé secrète.\n" -#: g10/trustdb.c:477 +#: g10/trustdb.c:467 #, c-format msgid "enum_secret_keys failed: %s\n" msgstr "enum_secret_keys a échoué: %s\n" -#: g10/trustdb.c:1428 +#: g10/trustdb.c:1287 g10/trustdb.c:1351 +#, c-format +msgid "%lu keys processed\n" +msgstr "%lu clés traitées\n" + +#: g10/trustdb.c:1289 +#, c-format +msgid "\t%lu keys skipped\n" +msgstr "\t%lu clés non prises en compte\n" + +#: g10/trustdb.c:1291 g10/trustdb.c:1353 +#, c-format +msgid "\t%lu keys with errors\n" +msgstr "\t%lu clés avec erreurs\n" + +#: g10/trustdb.c:1293 g10/trustdb.c:1355 +#, c-format +msgid "\t%lu keys updated\n" +msgstr "\t%lu clés mises à jour\n" + +#: g10/trustdb.c:1357 +#, c-format +msgid "\t%lu keys inserted\n" +msgstr "\t%lu clés insérées\n" + +#: g10/trustdb.c:1412 #, c-format msgid "key %08lX: insert trust record failed: %s\n" msgstr "clé %08lX: l'insertion d'enregistrement de confiance a échoué: %s\n" -#: g10/trustdb.c:1432 +#: g10/trustdb.c:1416 #, c-format msgid "key %08lX.%lu: inserted into trustdb\n" msgstr "clé %08lX.%lu: insérée dans la base de confiance\n" -#: g10/trustdb.c:1440 +#: g10/trustdb.c:1424 #, c-format msgid "key %08lX.%lu: created in future (time warp or clock problem)\n" msgstr "clé %08lX.%lu: créée dans le futur (problème d'horloge)\n" -#: g10/trustdb.c:1447 +#: g10/trustdb.c:1431 #, c-format msgid "key %08lX.%lu: expired at %s\n" msgstr "clé %08lX.%lu: a expiré le %s\n" -#: g10/trustdb.c:1455 +#: g10/trustdb.c:1439 #, c-format msgid "key %08lX.%lu: trust check failed: %s\n" msgstr "clé %08lX.%lu: la vérification de confiance a échoué: %s\n" -#: g10/trustdb.c:1718 +#: g10/trustdb.c:1656 #, c-format msgid "note: sig rec %lu[%d] in hintlist of %lu but marked as checked\n" msgstr "" +"note: enregistrement de signature %lu[%d] dans la liste d'aide de %lu mais\n" +"mais marqué comme vérifié\n" -#: g10/trustdb.c:1722 +#: g10/trustdb.c:1660 #, c-format msgid "note: sig rec %lu[%d] in hintlist of %lu but not marked\n" msgstr "" +"note: enregistrement de signature %lu[%d] dans la liste d'aide de %lu mais\n" +"non marqué\n" #. we need the dir record -#: g10/trustdb.c:1729 +#: g10/trustdb.c:1667 #, c-format msgid "sig rec %lu[%d] in hintlist of %u does not point to a dir record\n" msgstr "" +"l'enregistrement de signature %lu[%d] dans la liste d'aide de %u ne pointe\n" +"pas vers un enregistrement de répertoire\n" -#: g10/trustdb.c:1735 +#: g10/trustdb.c:1673 #, c-format msgid "lid %lu: no primary key\n" -msgstr "" +msgstr "lid %lu: pas de clé primaire\n" -#: g10/trustdb.c:1764 -#, fuzzy, c-format +#: g10/trustdb.c:1705 +#, c-format msgid "lid %lu: user id not found in keyblock\n" -msgstr "%s: utilisateur non trouvé\n" +msgstr "lid %lu: utilisateur non trouvé dans le bloc de clés\n" -#: g10/trustdb.c:1771 +#: g10/trustdb.c:1709 +#, c-format +msgid "lid %lu: user id without signature\n" +msgstr "lid %lu: utilisateur sans signature\n" + +#: g10/trustdb.c:1716 #, c-format msgid "lid %lu: self-signature in hintlist\n" -msgstr "" +msgstr "lid %lu: auto-signature dans la liste d'aide\n" -#: g10/trustdb.c:1776 -#, fuzzy, c-format -msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: good signature (3)\n" -msgstr "clé %08lXi.%lu, uid %02X%02X: %ssignature invalide: %s\n" +#: g10/trustdb.c:1721 +#, c-format +msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: Good signature (3)\n" +msgstr "clé %08lX.%lu, uid %02X%02X, sig %08lX: Bonne signature (3)\n" -#: g10/trustdb.c:1783 -#, fuzzy, c-format +#: g10/trustdb.c:1728 +#, c-format msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: very strange: no public key\n" msgstr "" -"clé %08lX.%lu, uid %02X%02X: pas de clé publique pour la signature %08lX\n" +"clé %08lX.%lu, uid %02X%02X, sig %08lX: très étrange: pas de clé publique\n" -#: g10/trustdb.c:1790 g10/trustdb.c:2225 g10/trustdb.c:2297 -#, fuzzy, c-format -msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: invalid signature: %s\n" -msgstr "clé %08lXi.%lu, uid %02X%02X: %ssignature invalide: %s\n" +#: g10/trustdb.c:1735 g10/trustdb.c:2207 g10/trustdb.c:2280 +#, c-format +msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: %s\n" +msgstr "clé %08lX.%lu, uid %02X%02X, sig %08lX: %s\n" -#: g10/trustdb.c:1835 +#: g10/trustdb.c:1779 #, c-format msgid "hintlist %lu[%d] of %lu does not point to a dir record\n" msgstr "" +"la liste d'aide de %lu[%d] de %lu ne pointe pas vers un enregistrement\n" +"de répertoire\n" -#: g10/trustdb.c:1841 +#: g10/trustdb.c:1785 #, c-format msgid "lid %lu does not have a key\n" -msgstr "" +msgstr "la lid %lu n'a pas de clé\n" -#: g10/trustdb.c:1851 -#, fuzzy, c-format +#: g10/trustdb.c:1795 +#, c-format msgid "lid %lu: can't get keyblock: %s\n" -msgstr "ne peut écrire le bloc de clés: %s\n" +msgstr "lid %lu: ne peut obtenir le bloc de clés: %s\n" -#: g10/trustdb.c:2096 -#, fuzzy, c-format -msgid "key %08lX.%lu, uid %02X%02X: good self-signature\n" -msgstr "clé %08lXi.%lu, uid %02X%02X: %ssignature invalide: %s\n" +#: g10/trustdb.c:2085 +#, c-format +msgid "key %08lX.%lu, uid %02X%02X: Good self-signature\n" +msgstr "clé %08lX.%lu, uid %02X%02X: Bonne auto-signature\n" -#: g10/trustdb.c:2188 -#, fuzzy, c-format +#: g10/trustdb.c:2091 +#, c-format +msgid "key %08lX, uid %02X%02X: Invalid self-signature: %s\n" +msgstr "clé %08lX.%lu, uid %02X%02X: Auto-signature invalide: %s\n" + +#: g10/trustdb.c:2171 +#, c-format msgid "" "key %08lX.%lu, uid %02X%02X, sig %08lX: duplicated signature - deleted\n" -msgstr "clé %08lXi.%lu, uid %02X%02X: %ssignature invalide: %s\n" +msgstr "" +"clé %08lX.%lu, uid %02X%02X, sig %08lX: signature dupliquée - effacée\n" -#: g10/trustdb.c:2211 -#, fuzzy, c-format -msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: good signature (1)\n" -msgstr "clé %08lXi.%lu, uid %02X%02X: %ssignature invalide: %s\n" +#: g10/trustdb.c:2193 +#, c-format +msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: Good signature (1)\n" +msgstr "clé %08lX.%lu, uid %02X%02X, sig %08lX: Bonne signature (1)\n" -#: g10/trustdb.c:2218 -#, fuzzy, c-format +#: g10/trustdb.c:2200 +#, c-format msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: weird: no public key\n" -msgstr "" -"clé %08lX.%lu, uid %02X%02X: pas de clé publique pour la signature %08lX\n" +msgstr "clé %08lX.%lu, uid %02X%02X, sig %08lX: bizarre: pas de clé publique\n" -#: g10/trustdb.c:2240 -#, fuzzy, c-format +#: g10/trustdb.c:2222 +#, c-format msgid "key %08lX.%lu, uid %02X%02X: has shadow dir %lu but not yet marked.\n" -msgstr "clé %08lXi.%lu, uid %02X%02X: %ssignature invalide: %s\n" - -#: g10/trustdb.c:2279 -#, fuzzy, c-format -msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: good signature (2)\n" -msgstr "clé %08lXi.%lu, uid %02X%02X: %ssignature invalide: %s\n" - -#: g10/trustdb.c:2290 -#, fuzzy, c-format -msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: no public key\n" msgstr "" -"clé %08lX.%lu, uid %02X%02X: pas de clé publique pour la signature %08lX\n" +"clé %08lX.%lu, uid %02X%02X: possède une ombre %lu mais pas encore\n" +"marquée.\n" + +#: g10/trustdb.c:2263 +#, c-format +msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: Good signature (2)\n" +msgstr "clé %08lX.%lu, uid %02X%02X, sig %08lX: Bonne signature (2)\n" + +#: g10/trustdb.c:2272 +#, c-format +msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: no public key\n" +msgstr "clé %08lX.%lu, uid %02X%02X, sig %08lX: pas de clé publique\n" #. key binding -#: g10/trustdb.c:2386 -#, fuzzy, c-format +#: g10/trustdb.c:2364 +#, c-format msgid "key %08lX: bogus key binding by %08lX\n" -msgstr "clé %08lX: pas de nom d'utilisateur\n" +msgstr "clé %08lX: mauvaise association avec %08lX\n" #. key revocation -#: g10/trustdb.c:2390 -#, fuzzy, c-format +#: g10/trustdb.c:2368 +#, c-format msgid "key %08lX: bogus key revocation by %08lX\n" -msgstr "clé %08lX: clé publique pas trouvée: %s\n" +msgstr "clé %08lX: mauvaise révocation de clé par %08lX\n" #. subkey revocation -#: g10/trustdb.c:2394 -#, fuzzy, c-format +#: g10/trustdb.c:2372 +#, c-format msgid "key %08lX: bogus subkey revocation by %08lX\n" -msgstr "clé %08lX: clé publique pas trouvée: %s\n" +msgstr "clé %08lX: mauvaise révocation de sous-clé par %08lX\n" #: g10/status.c:246 msgid "No help available" @@ -2275,6 +2378,25 @@ msgstr "" msgid "Overwrite (y/N)? " msgstr "Réécrire (o/N)? " +#: g10/openfile.c:85 +msgid "writing to stdout\n" +msgstr "écriture vers la sortie standard\n" + +#: g10/openfile.c:101 g10/openfile.c:165 +#, c-format +msgid "%s: can't create: %s\n" +msgstr "%s: ne peut créer: %s\n" + +#: g10/openfile.c:134 +#, c-format +msgid "assuming signed data in '%s'\n" +msgstr "les données signées sont supposées être dans '%s'\n" + +#: g10/openfile.c:181 +#, c-format +msgid "%s: new options file created\n" +msgstr "%s: nouveau fichier d'options créé\n" + #: g10/encr-data.c:74 msgid "" "Warning: Message was encrypted with a weak key in the symmetric cipher.\n" @@ -2284,7 +2406,7 @@ msgstr "" #: g10/seskey.c:52 msgid "weak key created - retrying\n" -msgstr "mauvais clé générée - nouvel essai\n" +msgstr "mauvaise clé générée - nouvel essai\n" #: g10/seskey.c:57 #, c-format @@ -2292,6 +2414,3 @@ msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" msgstr "" "ne peut éviter une mauvaise clé pour le chiffrement symétrique: \n" "%d essais ont eu lieu!\n" - -#~ msgid "key %08lX: already in ultikey_table\n" -#~ msgstr "clé %08lX: déja dans ultikey_table\n" diff --git a/util/ChangeLog b/util/ChangeLog index c58f9f7e8..af18ddce5 100644 --- a/util/ChangeLog +++ b/util/ChangeLog @@ -1,3 +1,17 @@ +Tue Nov 3 16:17:56 1998 Werner Koch (wk@isil.d.shuttle.de) + + * strgutil.c (native_to_utf8): New. + (utf8_to_native): New, but only as a stub. + + * argparse.c (optfile_parse): Trimmed spaces from args. + + +Wed Oct 28 08:01:49 1998 me,,, (wk@tobold) + + * argparse.c (find_long_option): New. + (arg_parse): option=value is now allowed. Add a new internal + option "--dump-options". + Thu Oct 22 16:25:49 1998 Michael Roth (mroth@nessie.de) * fileutil.c (make_basename): New. diff --git a/util/argparse.c b/util/argparse.c index 766d461f9..a75ef3467 100644 --- a/util/argparse.c +++ b/util/argparse.c @@ -1,13 +1,13 @@ /* [argparse.c wk 17.06.97] Argument Parser for option handling * Copyright (C) 1998 Free Software Foundation, Inc. - * This file is part of WkLib. + * This file is part of GnuPG. * - * WkLib is free software; you can redistribute it and/or modify + * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * WkLib is distributed in the hope that it will be useful, + * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. @@ -73,8 +73,8 @@ * Bit 4 : Do not skip the first arg. * Bit 5 : allow usage of long option with only one dash * Bit 6 : ignore --version - * all other bits must be set to zero, this value is modified by the function - * so assume this is write only. + * all other bits must be set to zero, this value is modified by the + * function, so assume this is write only. * Local flags (for each option): * Bit 2-0 : 0 = does not take an argument * 1 = takes int argument @@ -83,8 +83,8 @@ * 4 = takes ulong argument * Bit 3 : argument is optional (r_type will the be set to 0) * Bit 4 : allow 0x etc. prefixed values. - * Bit 7 : this is an command and not an option - * If can stop the option processing by setting opts to NULL, the function will + * Bit 7 : this is a command and not an option + * You stop the option processing by setting opts to NULL, the function will * then return 0. * @Return Value * Returns the args.r_opt or 0 if ready @@ -167,8 +167,14 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno ) else { if( arg->r_opt == -3 ) s = "Missing argument for option \"%.50s\"\n"; + else if( arg->r_opt == -6 ) + s = "Option \"%.50s\" does not expect an argument\n"; else if( arg->r_opt == -7 ) s = "Invalid command \"%.50s\"\n"; + else if( arg->r_opt == -8 ) + s = "Option \"%.50s\" is ambiguous\n"; + else if( arg->r_opt == -9 ) + s = "Command \"%.50s\" is ambiguous\n"; else s = "Invalid option \"%.50s\"\n"; log_error(s, arg->internal.last? arg->internal.last:"[??]" ); @@ -186,10 +192,15 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno ) * Lines starting with '#' are comment lines. * Syntax is simply a keyword and the argument. * Valid keywords are all keywords from the long_opt list without - * the leading dashes. The special keywords help, warranty and version + * the leading dashes. The special keywords "help", "warranty" and "version" * are not valid here. * Caller must free returned strings. * If called with FP set to NULL command line args are parse instead. + * + * Q: Should we allow the syntax + * keyword = value + * and accept for boolean options a value of 1/0, yes/no or true/false? + * Note: Abbreviation of options is here not allowed. */ int optfile_parse( FILE *fp, const char *filename, unsigned *lineno, @@ -229,7 +240,7 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno, arg->r_opt = (opts[index].flags & 256)? -7:-2; else if( (opts[index].flags & 8) ) /* no argument */ arg->r_opt = -3; /* error */ - else /* no or optiona argument */ + else /* no or optional argument */ arg->r_type = 0; /* okay */ break; } @@ -253,6 +264,7 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno, else buffer[i] = 0; + trim_spaces( buffer ); if( !set_opt_arg(arg, opts[index].flags, buffer) ) m_free(buffer); } @@ -331,6 +343,37 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno, +static int +find_long_option( ARGPARSE_OPTS *opts, const char *keyword ) +{ + int i; + size_t n; + + /* Would be better if we can do a binary search, but it is not + possible to reorder our option table because we would mess + up our help strings - What we can do is: Build a nice option + lookup table wehn this function is first invoked */ + if( !*keyword ) + return -1; + for(i=0; opts[i].short_opt; i++ ) + if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) ) + return i; + /* not found, see whether it is an abbreviation */ + n = strlen( keyword ); + for(i=0; opts[i].short_opt; i++ ) { + if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) { + int j; + for(j=i+1; opts[j].short_opt; j++ ) { + if( opts[j].long_opt + && !strncmp( opts[j].long_opt, keyword, n ) ) + return -2; /* abbreviation is ambiguous */ + } + return i; + } + } + return -1; +} + int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) { @@ -369,6 +412,8 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) goto leave; } else if( *s == '-' && s[1] == '-' ) { /* long option */ + char *argpos; + arg->internal.inarg = 0; if( !s[2] && !(arg->flags & (1<<3)) ) { /* stop option processing */ arg->internal.stopped = 1; @@ -376,37 +421,57 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) goto next_one; } - for(i=0; opts[i].short_opt; i++ ) - if( opts[i].long_opt && !strcmp( opts[i].long_opt, s+2) ) - break; + argpos = strchr( s+2, '=' ); + if( argpos ) + *argpos = 0; + i = find_long_option( opts, s+2 ); + if( argpos ) + *argpos = '='; - if( !opts[i].short_opt && !strcmp( "help", s+2) ) + if( i < 0 && !strcmp( "help", s+2) ) show_help(opts, arg->flags); - else if( !opts[i].short_opt && !strcmp( "version", s+2) ) { + else if( i < 0 && !strcmp( "version", s+2) ) { if( !(arg->flags & (1<<6)) ) { show_version(); exit(0); } } - else if( !opts[i].short_opt && !strcmp( "warranty", s+2) ) { + else if( i < 0 && !strcmp( "warranty", s+2) ) { puts( strusage(16) ); exit(0); } + else if( i < 0 && !strcmp( "dump-options", s+2) ) { + for(i=0; opts[i].short_opt; i++ ) + if( opts[i].long_opt ) + printf( "--%s\n", opts[i].long_opt ); + exit(0); + } - arg->r_opt = opts[i].short_opt; - if( !opts[i].short_opt ) { + if( i == -2 ) /* ambiguous option */ + arg->r_opt = (opts[i].flags & 256)? -9:-8; + else if( i == -1 ) { arg->r_opt = (opts[i].flags & 256)? -7:-2; arg->r.ret_str = s+2; } + else + arg->r_opt = opts[i].short_opt; + if( i < 0 ) + ; else if( (opts[i].flags & 7) ) { - s2 = argv[1]; + if( argpos ) { + s2 = argpos+1; + if( !*s2 ) + s2 = NULL; + } + else + s2 = argv[1]; if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/ arg->r_type = 0; /* because it is optional */ } else if( !s2 ) { arg->r_opt = -3; /* missing argument */ } - else if( *s2 == '-' && (opts[i].flags & 8) ) { + else if( !argpos && *s2 == '-' && (opts[i].flags & 8) ) { /* the argument is optional and the next seems to be * an option. We do not check this possible option * but assume no argument */ @@ -414,11 +479,16 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) } else { set_opt_arg(arg, opts[i].flags, s2); - argc--; argv++; index++; /* skip one */ + if( !argpos ) { + argc--; argv++; index++; /* skip one */ + } } } else { /* does not take an argument */ - arg->r_type = 0; + if( argpos ) + arg->r_type = -6; /* argument not expected */ + else + arg->r_type = 0; } argc--; argv++; index++; /* set to next one */ } diff --git a/util/strgutil.c b/util/strgutil.c index 809b0c3f2..217b64043 100644 --- a/util/strgutil.c +++ b/util/strgutil.c @@ -179,6 +179,52 @@ string_count_chr( const char *string, int c ) return count; } + +/**************** + * Convert string, which is in native encoding to UTF8 and return the + * new allocated UTF8 string. + * This code assumes that native is iso-8859-1. + */ +char * +native_to_utf8( const char *string ) +{ + const byte *s; + char *buffer; + byte *p; + size_t length=0; + + for(s=string; *s; s++ ) { + length++; + if( *s & 0x80 ) + length++; + } + buffer = m_alloc( length + 1 ); + for(p=buffer, s=string; *s; s++ ) { + if( *s & 0x80 ) { + *p++ = 0xc0 | ((*s >> 6) & 3); + *p++ = 0x80 | ( *s & 0x3f ); + } + else + *p++ = *s; + } + *p = 0; + return buffer; +} + + +/**************** + * Convert string, which is in UTF8 to native encoding. Replace + * illegal encodings by some "\xnn". + * This code assumes that native is iso-8859-1. + */ +char * +utf8_to_native( const char *string ) +{ + /* FIXME: Not yet done */ + return m_strdup(string); +} + + /********************************************* ********** missing string functions ********* *********************************************/