diff --git a/BUGS b/BUGS index a8ae7701e..bf3290199 100644 --- a/BUGS +++ b/BUGS @@ -34,16 +34,18 @@ and after about half a day in the rsync snapshots. keyblock resource `/home/jam/.gnupg/pubring.gpg': file open error OOPS in close enum_keyblocks - ignored [gdbm is experimental and will be replaced by the new keybox code] + FIX: 1999-07-22 (Fixed the second error, there will be no fix for + the first one, becuase GDBM is to be replaced) -[***] #6 1999-02-22 0.9.3 +[ **] #6 1999-02-22 0.9.3 Buserror on IRIX 6.4: Crash while doing a keygen. I think while creating the prime. Other buserrors are reported when doing a "gpg README" on sparc-solaris2.6. --> Solaris fixed. - --> IRIX bug still there + --> IRIX bug still there but someone should test this again! [ *] #18 1999-05-27 0.9.7 - rndunix hangs on hp/ux. The problme is related to my_plcose which is + rndunix hangs on hp/ux. The problem is related to my_plcose which is not always called. (I suggest to use EGD instead of rndunix.) [ **] #19 1999-06-11 @@ -51,5 +53,8 @@ and after about half a day in the rsync snapshots. FAEBD5FC. FIX: 1999-07-12 (less memory requirement and increased the limit) +[ *] #22 1999-07-22 + Solaris make has problems with the generated POTFILES - seems to be a + gettext bug. Use GNU gmake as a workaround. -Next #22 +Next #23 diff --git a/ChangeLog b/ChangeLog index 6866ecf52..e9f3eab89 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,17 +1,14 @@ Thu Jul 15 10:15:35 CEST 1999 Werner Koch - * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Fixed last modification. Wed Jul 7 13:08:40 CEST 1999 Werner Koch - * Makefile.am: Support for libtool. * configure.in: Ditto. Tue Jun 29 21:44:25 CEST 1999 Werner Koch - * configure.in (use_local_zlib): The lost dollar is back. * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Add EMX case. diff --git a/NEWS b/NEWS index 8dfc04a10..b0708c928 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,9 @@ * Enhanced info output in case of multiple recipients and fixed exit code. + * New option --allow-non-selfsigned-uid to work around a problem with + the German IN way of separating signing and encryption keys. + Noteworthy changes in version 0.9.8 ----------------------------------- diff --git a/TODO b/TODO index a02d7b45b..fe9d05094 100644 --- a/TODO +++ b/TODO @@ -1,21 +1,22 @@ - * add some status output put for signing and encryption. - replace the putc in primegen with some kind of status-fd outputs. + * Check that uids without a self signature don't become fully trusted and + print a warning when such a key is used. + + +Scheduled for 1.1 +----------------- + * With option -i prompt before adding a key to the keyring and show some + info what we are about to add. * Speed up calculation of key validation. + * Allow a replacement for the progress functions in ./cipher + + * add an option to use an OpenPGP packet as input (and don't build a literal + data packet) + * print a warning when a revoked/expired _secret_ key is used. - * Add NO_PUBKEY and NO_SECKEY status lines. - - * Solaris make has problems with the generated POTFILES - seems to be a - gettext bug. - - * find a way to allow the import of non-self-signed keys. This is needed - for the IN ENCR/SIGN hack. - - * add an option to use a OpenPGP packet as input (and don't build a literal - data packet) Nice to have ------------ diff --git a/cipher/ChangeLog b/cipher/ChangeLog index 73a42ba49..ae4b51e7c 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -148,7 +148,6 @@ Tue Jan 12 11:17:18 CET 1999 Werner Koch * tiger.c: Only compile if we have the u64 type - Sat Jan 9 16:02:23 CET 1999 Werner Koch * rndunix.c (gather_random): check for setuid. diff --git a/doc/gpg.sgml b/doc/gpg.sgml index 2c73715ae..344cefc67 100644 --- a/doc/gpg.sgml +++ b/doc/gpg.sgml @@ -696,6 +696,13 @@ Assume "yes" on most questions. Assume "no" on most questions. + +--always-trust + +Skip key validation and assume that used keys are always fully trusted. +You won't use this unless you have installed some external validation scheme. + + --keyserver &ParmName; @@ -1094,6 +1101,17 @@ code. This is always used with the newer cipher (those with a blocksize greater than 64 bit). + +--allow-non-self-signed-uid + +Allow the import of keys with user IDs which are not self-signed. +This is only allows the import - key validation will fail und you +have to check the validity of the key my other means. This hack is +needed for some German keys generated with pgp 2.6.3in. You should really +avoid using it, because OpenPGP has better mechanics to do separate signing +and encryption keys. + + --lock-once diff --git a/g10/ChangeLog b/g10/ChangeLog index 937677f47..5fa88ec54 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,11 +1,24 @@ -Thu Jul 15 10:15:35 CEST 1999 Werner Koch +Thu Jul 22 20:03:03 CEST 1999 Werner Koch + * ringedit.c (enum_keyblocks): Removed annoying error message in cases + when we have no keyring at all to enum. + + * getkey.c (classify_user_id): Rewrote to relax the recognition of + keyIDs and fingerprints (Michael). + + * mainproc.c (check_sig_and_print): Print status NO_PUBKEY. + (print_failed_pkenc): Print status NO_SECKEY. + + * import.c (mark_non_selfsigned_uids_valid): New. + * g10.c: New option --allow-non-selfsigned-uid. + +Thu Jul 15 10:15:35 CEST 1999 Werner Koch + * g10.c: New options --disable-{cipher,pubkey}-algo. Wed Jul 14 19:42:08 CEST 1999 Werner Koch - * status.h (STATUS_IMPORTED): New. * import.c (import): Print some status information (Holger Schurig). @@ -14,7 +27,6 @@ Wed Jul 14 19:42:08 CEST 1999 Werner Koch Tue Jul 13 17:39:25 CEST 1999 Werner Koch - * pkclist.c (do_edit_ownertrust): Changed the way help works. (build_pk_list): Implemented default recipient stuff. * g10.c: New options --default-recipient[-self] @@ -27,13 +39,11 @@ Tue Jul 13 17:39:25 CEST 1999 Werner Koch Mon Jul 12 18:45:57 CEST 1999 Werner Koch - * keyedit.c (keyedit_menu): Add arg sign_mode and changed callers * g10.c (main): New command --lsign-key. Mon Jul 12 14:55:34 CEST 1999 Werner Koch - * mainproc.c (kidlist_item): New. (release_list): Release failed pk-enc-list. (print_failed_pkenc): New @@ -62,7 +72,6 @@ Thu Jul 8 16:21:27 CEST 1999 Werner Koch Wed Jul 7 13:08:40 CEST 1999 Werner Koch - * Makefile.am: Support for libtool. * keygen.c (ask_expire_interval): Hack to allow for an expire date. @@ -79,7 +88,6 @@ Wed Jul 7 13:08:40 CEST 1999 Werner Koch Fri Jul 2 11:45:54 CEST 1999 Werner Koch - * g10.c (g10_exit): Dump random stats. * sig-check.c (check_key_signature,check_key_signature2): Enhanced diff --git a/g10/g10.c b/g10/g10.c index 0e0999fbb..c169420b2 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -174,6 +174,7 @@ enum cmd_and_opt_values { aNull = 0, oNoUtf8Strings, oDisableCipherAlgo, oDisablePubkeyAlgo, + oAllowNonSelfsignedUID, aTest }; @@ -332,6 +333,7 @@ static ARGPARSE_OPTS opts[] = { { oWithFingerprint, "with-fingerprint", 0, "@" }, { oDisableCipherAlgo, "disable-cipher-algo", 2, "@" }, { oDisablePubkeyAlgo, "disable-pubkey-algo", 2, "@" }, + { oAllowNonSelfsignedUID, "allow-non-selfsigned-uid", 0, "@" }, {0} }; @@ -843,6 +845,9 @@ main( int argc, char **argv ) case oDisablePubkeyAlgo: disable_pubkey_algo( string_to_pubkey_algo(pargs.r.ret_str) ); break; + case oAllowNonSelfsignedUID: + opt.allow_non_selfsigned_uid = 1; + break; default : pargs.err = configfp? 1:2; break; } diff --git a/g10/getkey.c b/g10/getkey.c index 4d747f8bc..a847d413f 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -539,104 +539,134 @@ int classify_user_id( const char *name, u32 *keyid, byte *fprint, const char **retstr, size_t *retlen ) { - const char *s; - int mode = 0; + const char * s; + int mode = 0; + int hexprefix = 0; + int hexlength; - /* check what kind of name it is */ + /* skip leading spaces. FIXME: what is with leading spaces? */ for(s = name; *s && isspace(*s); s++ ) ; - if( isdigit( *s ) ) { /* a keyid or a fingerprint */ - int i, j; - char buf[9]; - if( *s == '0' && s[1] == 'x' && isxdigit(s[2]) ) - s += 2; /*kludge to allow 0x034343434 */ - for(i=0; isxdigit(s[i]); i++ ) - ; - if( s[i] && !isspace(s[i]) ) /* not terminated by EOS or blank*/ + switch (*s) { + case 0: /* empty string is an error */ return 0; - else if( i == 8 || (i == 9 && *s == '0') ) { /* short keyid */ - if( i==9 ) - s++; - if( keyid ) { - keyid[0] = 0; - keyid[1] = strtoul( s, NULL, 16 ); + + case '.': /* an email address, compare from end */ + mode = 5; + s++; + break; + + case '<': /* an email address */ + mode = 3; + break; + + case '@': /* part of an email address */ + mode = 4; + s++; + break; + + case '=': /* exact compare */ + mode = 1; + s++; + break; + + case '*': /* case insensitive substring search */ + mode = 2; + s++; + break; + + case '+': /* compare individual words */ + mode = 6; + s++; + break; + + case '#': /* local user id */ + mode = 12; + s++; + if (keyid) { + if (keyid_from_lid(strtoul(s, NULL, 10), keyid)) + keyid[0] = keyid[1] = 0; } - mode = 10; - } - else if( i == 16 || (i == 17 && *s == '0') ) { /* complete keyid */ - if( i==17 ) - s++; - mem2str(buf, s, 9 ); - keyid[0] = strtoul( buf, NULL, 16 ); - keyid[1] = strtoul( s+8, NULL, 16 ); - mode = 11; - } - else if( i == 32 || ( i == 33 && *s == '0' ) ) { /* md5 fingerprint */ - if( i==33 ) - s++; - if( fprint ) { - memset(fprint+16, 4, 0); - for(j=0; j < 16; j++, s+=2 ) { - int c = hextobyte( s ); - if( c == -1 ) - return 0; - fprint[j] = c; + break; + + default: + if (s[0] == '0' && s[1] == 'x') { + hexprefix = 1; + s += 2; + } + + hexlength = strspn(s, "0123456789abcdefABCDEF"); + + /* check if a hexadecimal number is terminated by EOS or blank */ + if (hexlength && s[hexlength] && !isspace(s[hexlength])) { + if (hexprefix) /* a "0x" prefix without correct */ + return 0; /* termination is an error */ + else /* The first chars looked like */ + hexlength = 0; /* a hex number, but really were not. */ + } + + if (hexlength == 8 || (!hexprefix && hexlength == 9 && *s == '0')){ + /* short keyid */ + if (hexlength == 9) + s++; + if (keyid) { + keyid[0] = 0; + keyid[1] = strtoul( s, NULL, 16 ); } + mode = 10; } - mode = 16; - } - else if( i == 40 || ( i == 41 && *s == '0' ) ) { /* sha1/rmd160 fprint*/ - if( i==33 ) - s++; - if( fprint ) { - for(j=0; j < 20; j++, s+=2 ) { - int c = hextobyte( s ); - if( c == -1 ) - return 0; - fprint[j] = c; + else if (hexlength == 16 || (!hexprefix && hexlength == 17 + && *s == '0')) { + /* complete keyid */ + char buf[9]; + if (hexlength == 17) + s++; + mem2str(buf, s, 9 ); + keyid[0] = strtoul( buf, NULL, 16 ); + keyid[1] = strtoul( s+8, NULL, 16 ); + mode = 11; + } + else if (hexlength == 32 || (!hexprefix && hexlength == 33 + && *s == '0')) { + /* md5 fingerprint */ + int i; + if (hexlength == 33) + s++; + if (fprint) { + memset(fprint+16, 4, 0); + for (i=0; i < 16; i++, s+=2) { + int c = hextobyte(s); + if (c == -1) + return 0; + fprint[i] = c; + } } + mode = 16; + } + else if (hexlength == 40 || (!hexprefix && hexlength == 41 + && *s == '0')) { + /* sha1/rmd160 fingerprint */ + int i; + if (hexlength == 41) + s++; + if (fprint) { + for (i=0; i < 20; i++, s+=2) { + int c = hextobyte(s); + if (c == -1) + return 0; + fprint[i] = c; + } + } + mode = 20; + } + else { + if (hexprefix) /* This was a hex number with a prefix */ + return 0; /* and a wrong length */ + + mode = 2; /* Default is case insensitive substring search */ } - mode = 20; - } - else - return 0; } - else if( *s == '=' ) { /* exact search */ - mode = 1; - s++; - } - else if( *s == '*' ) { /* substring search */ - mode = 2; - s++; - } - else if( *s == '<' ) { /* an email address */ - mode = 3; - } - else if( *s == '@' ) { /* a part of an email address */ - mode = 4; - s++; - } - else if( *s == '.' ) { /* an email address, compare from end */ - mode = 5; - s++; - } - else if( *s == '+' ) { /* word match mode */ - mode = 6; - s++; - } - else if( *s == '#' ) { /* use local id */ - mode = 12; - s++; - if( keyid ) { - if( keyid_from_lid( strtoul( s, NULL, 10), keyid ) ) - keyid[0] = keyid[1] = 0; - } - } - else if( !*s ) /* empty string */ - return 0; - else - mode = 2; if( retstr ) *retstr = s; diff --git a/g10/import.c b/g10/import.c index 6511c8e01..023ce2964 100644 --- a/g10/import.c +++ b/g10/import.c @@ -59,6 +59,7 @@ static int import_secret_one( const char *fname, KBNODE keyblock ); static int import_revoke_cert( const char *fname, KBNODE node ); static int chk_self_sigs( const char *fname, KBNODE keyblock, PKT_public_key *pk, u32 *keyid ); +static void mark_non_selfsigned_uids_valid( KBNODE keyblock, u32 *kid ); static int delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid ); static int merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock, u32 *keyid, @@ -367,6 +368,9 @@ import_one( const char *fname, KBNODE keyblock, int fast ) if( rc ) return rc== -1? 0:rc; + if( opt.allow_non_selfsigned_uid ) + mark_non_selfsigned_uids_valid( keyblock, keyid ); + if( !delete_inv_parts( fname, keyblock, keyid ) ) { if( !opt.quiet ) { log_info( _("key %08lX: no valid user ids\n"), @@ -686,7 +690,7 @@ import_revoke_cert( const char *fname, KBNODE node ) * loop over the keyblock and check all self signatures. * Mark all user-ids with a self-signature by setting flag bit 0. * Mark all user-ids with an invalid self-signature by setting bit 1. - * This works allso for subkeys, here the subkey is marked. + * This works also for subkeys, here the subkey is marked. */ static int chk_self_sigs( const char *fname, KBNODE keyblock, @@ -726,7 +730,7 @@ chk_self_sigs( const char *fname, KBNODE keyblock, knode = find_prev_kbnode( keyblock, n, PKT_SECRET_SUBKEY ); - if( !knode ) { + if( !knode ) { log_error( _("key %08lX: no subkey for key binding\n"), (ulong)keyid[1]); n->flag |= 4; /* delete this */ @@ -749,6 +753,29 @@ chk_self_sigs( const char *fname, KBNODE keyblock, return 0; } + + +/**************** + * If a user ID has at least one signature, mark it as valid + */ +static void +mark_non_selfsigned_uids_valid( KBNODE keyblock, u32 *kid ) +{ + KBNODE node; + for(node=keyblock->next; node; node = node->next ) { + if( node->pkt->pkttype == PKT_USER_ID && !(node->flag & 1) ) { + if( node->next && node->next->pkt->pkttype == PKT_SIGNATURE ) { + node->flag |= 1; + log_info( _("key %08lX: accepted non self-signed userid '"), + (ulong)kid[1]); + print_string( log_stream(), node->pkt->pkt.user_id->name, + node->pkt->pkt.user_id->len, 0 ); + fputs("'\n", log_stream() ); + } + } + } +} + /**************** * delete all parts which are invalid and those signatures whose * public key algorithm is not available in this implemenation; diff --git a/g10/mainproc.c b/g10/mainproc.c index 1e06a78c8..99713f9a4 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -287,8 +287,15 @@ print_failed_pkenc( struct kidlist_item *list ) } free_public_key( pk ); - if( list->reason == G10ERR_NO_SECKEY ) + if( list->reason == G10ERR_NO_SECKEY ) { log_info(_("no secret key for decryption available\n")); + if( is_status_enabled() ) { + char buf[20]; + sprintf(buf,"%08lX%08lX", (ulong)list->kid[0], + (ulong)list->kid[1] ); + write_status_text( STATUS_NO_SECKEY, buf ); + } + } else log_error(_("public key decryption failed: %s\n"), g10_errstr(list->reason)); @@ -1101,6 +1108,10 @@ check_sig_and_print( CTX c, KBNODE node ) sig->pubkey_algo, sig->digest_algo, sig->sig_class, (ulong)sig->timestamp, rc ); write_status_text( STATUS_ERRSIG, buf ); + if( rc == G10ERR_NO_PUBKEY ) { + buf[16] = 0; + write_status_text( STATUS_NO_PUBKEY, buf ); + } log_error(_("Can't check signature: %s\n"), g10_errstr(rc) ); } return rc; diff --git a/g10/options.h b/g10/options.h index e03bd00cc..4278ff374 100644 --- a/g10/options.h +++ b/g10/options.h @@ -80,6 +80,7 @@ struct { STRLIST notation_data; const char *set_policy_url; int use_embedded_filename; + int allow_non_selfsigned_uid; } opt; diff --git a/g10/options.skel b/g10/options.skel index e4ea017c8..fa4ac3f28 100644 --- a/g10/options.skel +++ b/g10/options.skel @@ -20,15 +20,15 @@ $Id$ # If you have more than 1 secret key in your keyring, you may want # to uncomment the following option and set your preffered keyid -# default-key 621CC013 +#default-key 621CC013 # If you do not pass a recipient to gpg, it will ask for one. # Using this option you can encrypt to a default key. key validation # will not be done in this case. # The second form uses the default key as default recipient. -# default-recipient some-user-id -# default-recipient-self +#default-recipient some-user-id +#default-recipient-self # The next option is enabled because this one is needed for interoperation diff --git a/g10/ringedit.c b/g10/ringedit.c index 75baf8abd..3db60f245 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -816,10 +816,12 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root ) break; case rt_GDBM: break; - default: - log_error("OOPS in close enum_keyblocks - ignored\n"); + case rt_UNKNOWN: + /* this happens when we have no keyring at all */ return rc; - break; + + default: + BUG(); } /* release pending packet */ free_packet( kbpos->pkt );