diff --git a/ChangeLog b/ChangeLog index 172dd0fe4..ce3d76967 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2003-09-23 Werner Koch + + Merged most of David Shaw's changes in 1.3 since 2003-06-03. + + * configure.ac: Drop all TIGER/192 support. + (uint64_t): Check for UINT64_C to go along with uint64_t. + (getaddrinfo): Check for it. + (sigset_t): Check for sigset_t and struct sigaction. This is for + Forte c89 on Solaris which seems to define only the function call + half of the two pairs by default. + (W32LIBS): Include wsock32 in W32LIBS. This is different from + NETLIBS so we don't need to force other platforms to pull in the + netlibs when they aren't actually needed. + 2003-09-06 Werner Koch Released 1.9.1. diff --git a/TODO b/TODO index fe81d0241..da337f247 100644 --- a/TODO +++ b/TODO @@ -63,3 +63,5 @@ might want to have an agent context for each service request * ALL ** Return IMPORT_OK status. + +* Where is http.c, regcomp.c, srv.c, w32reg.c ? diff --git a/common/ChangeLog b/common/ChangeLog index 66e935b28..caabdd4cf 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,11 @@ +2003-09-23 Werner Koch + + * iobuf.c (check_special_filename): Replaced is isdigit by digitp + to avoid passing negative values and potential locale problems. + Problem noted by Christian Biere. + + * util.h (ascii_isspace): New. + 2003-09-18 Werner Koch * ttyio.c (tty_fprintf): New. diff --git a/common/iobuf.c b/common/iobuf.c index 773e2993b..4d735397e 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -101,7 +101,7 @@ typedef struct close_cache_s *CLOSE_CACHE; static CLOSE_CACHE close_cache; #endif -#ifdef __MINGW32__ +#ifdef _WIN32 typedef struct { int sock; @@ -112,7 +112,7 @@ typedef struct char fname[1]; /* name of the file */ } sock_filter_ctx_t; -#endif /*__MINGW32__*/ +#endif /*_WIN32*/ /* The first partial length header block must be of size 512 * to make it easier (and efficienter) we use a min. block size of 512 @@ -580,7 +580,7 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf, return rc; } -#ifdef __MINGW32__ +#ifdef _WIN32 /* Becuase sockets are an special object under Lose32 we have to * use a special filter */ static int @@ -667,7 +667,7 @@ sock_filter (void *opaque, int control, iobuf_t chain, byte * buf, } return rc; } -#endif /*__MINGW32__*/ +#endif /*_WIN32*/ /**************** * This is used to implement the block write mode. @@ -1171,7 +1171,7 @@ check_special_filename (const char *fname) int i; fname += 2; - for (i = 0; isdigit (fname[i]); i++) + for (i = 0; digitp (fname+i); i++) ; if (!fname[i]) return atoi (fname); @@ -1262,7 +1262,7 @@ iobuf_t iobuf_sockopen (int fd, const char *mode) { iobuf_t a; -#ifdef __MINGW32__ +#ifdef _WIN32 sock_filter_ctx_t *scx; size_t len; @@ -1405,7 +1405,7 @@ iobuf_ioctl (iobuf_t a, int cmd, int intval, void *ptrval) b->keep_open = intval; return 0; } -#ifdef __MINGW32__ +#ifdef _WIN32 else if (!a->chain && a->filter == sock_filter) { sock_filter_ctx_t *b = a->filter_ov; @@ -1440,7 +1440,7 @@ iobuf_ioctl (iobuf_t a, int cmd, int intval, void *ptrval) b->no_cache = intval; return 0; } -#ifdef __MINGW32__ +#ifdef _WIN32 else if (!a->chain && a->filter == sock_filter) { sock_filter_ctx_t *b = a->filter_ov; @@ -2363,7 +2363,7 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer, int iobuf_translate_file_handle (int fd, int for_write) { -#ifdef __MINGW32__ +#ifdef _WIN32 { int x; @@ -2387,7 +2387,7 @@ iobuf_translate_file_handle (int fd, int for_write) static int translate_file_handle (int fd, int for_write) { -#ifdef __MINGW32__ +#ifdef _WIN32 #ifdef FILE_FILTER_USES_STDIO fd = iobuf_translate_file_handle (fd, for_write); #else diff --git a/common/ttyio.c b/common/ttyio.c index c77b4a85a..eab805e20 100644 --- a/common/ttyio.c +++ b/common/ttyio.c @@ -37,7 +37,7 @@ #define HAVE_TCGETATTR #endif #endif -#ifdef __MINGW32__ /* use the odd Win32 functions */ +#ifdef _WIN32 /* use the odd Win32 functions */ #include #ifdef HAVE_TCGETATTR #error mingw32 and termios @@ -51,7 +51,7 @@ #define CONTROL_D ('D' - 'A' + 1) -#ifdef __MINGW32__ /* use the odd Win32 functions */ +#ifdef _WIN32 /* use the odd Win32 functions */ static struct { HANDLE in, out; } con; @@ -124,7 +124,7 @@ init_ttyfp(void) if( initialized ) return; -#if defined(__MINGW32__) +#if defined(_WIN32) { SECURITY_ATTRIBUTES sa; @@ -194,7 +194,7 @@ tty_printf( const char *fmt, ... ) init_ttyfp(); va_start( arg_ptr, fmt ) ; -#ifdef __MINGW32__ +#ifdef _WIN32 { char *buf = NULL; int n; @@ -241,7 +241,7 @@ tty_fprintf (FILE *fp, const char *fmt, ... ) init_ttyfp(); va_start( arg_ptr, fmt ) ; -#ifdef __MINGW32__ +#ifdef _WIN32 { char *buf = NULL; int n; @@ -278,7 +278,7 @@ tty_print_string ( const byte *p, size_t n ) if( !initialized ) init_ttyfp(); -#ifdef __MINGW32__ +#ifdef _WIN32 /* not so effective, change it if you want */ for( ; n; n--, p++ ) if( iscntrl( *p ) ) { @@ -372,7 +372,7 @@ do_get( const char *prompt, int hidden ) buf = xmalloc((n=50)); i = 0; -#ifdef __MINGW32__ /* windoze version */ +#ifdef _WIN32 /* windoze version */ if( hidden ) SetConsoleMode(con.in, HID_INPMODE ); @@ -527,7 +527,7 @@ tty_kill_prompt() last_prompt_len = 0; if( !last_prompt_len ) return; -#ifdef __MINGW32__ +#ifdef _WIN32 tty_printf("\r%*s\r", last_prompt_len, ""); #else { diff --git a/common/util.h b/common/util.h index 045851481..78aa2f890 100644 --- a/common/util.h +++ b/common/util.h @@ -107,6 +107,10 @@ int asprintf (char **result, const char *format, ...); #define hexdigitp(a) (digitp (a) \ || (*(a) >= 'A' && *(a) <= 'F') \ || (*(a) >= 'a' && *(a) <= 'f')) + /* Note this isn't identical to a C locale isspace() without \f and + \v, but works for the purposes used here. */ +#define ascii_isspace(a) ((a)==' ' || (a)=='\n' || (a)=='\r' || (a)=='\t') + /* the atoi macros assume that the buffer has only valid digits */ #define atoi_1(p) (*(p) - '0' ) #define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1)) diff --git a/configure.ac b/configure.ac index 4ee1898b5..23baee44a 100644 --- a/configure.ac +++ b/configure.ac @@ -647,7 +647,17 @@ AC_CHECK_SIZEOF(unsigned short) AC_CHECK_SIZEOF(unsigned int) AC_CHECK_SIZEOF(unsigned long) AC_CHECK_SIZEOF(unsigned long long) -AC_CHECK_SIZEOF(uint64_t) +# Ensure that we have UINT64_C before we bother to check for uint64_t +# fixme: really needed in gnupg? I think it is only useful in libcgrypt. +AC_CACHE_CHECK([for UINT64_C],[gnupg_cv_uint64_c_works], + AC_COMPILE_IFELSE(AC_LANG_PROGRAM([#include +uint64_t foo=UINT64_C(42);]),gnupg_cv_uint64_c_works=yes,gnupg_cv_uint64_c_works=no)) +if test "$gnupg_cv_uint64_c_works" = "yes" ; then + AC_CHECK_SIZEOF(uint64_t) +fi + + + if test "$ac_cv_sizeof_unsigned_short" = "0" \ || test "$ac_cv_sizeof_unsigned_int" = "0" \ @@ -660,19 +670,8 @@ if test "$ac_cv_sizeof_unsigned_int" != "8" \ && test "$ac_cv_sizeof_unsigned_long" != "8" \ && test "$ac_cv_sizeof_unsigned_long_long" != "8" \ && test "$ac_cv_sizeof_uint64_t" != "8"; then - AC_MSG_WARN([No 64-bit types. Disabling TIGER/192, SHA-384, and SHA-512]) + AC_MSG_WARN([No 64-bit types. Disabling SHA-384, and SHA-512]) else - if test x"$use_tiger192" = xyes ; then - AC_SUBST(TIGER_O,tiger.o) - AC_DEFINE(USE_TIGER192,1,[Define to include the TIGER/192 digest]) - fi - - if test "$use_old_tiger192" = yes ; then - AC_SUBST(TIGER_O,tiger.o) - AC_DEFINE(USE_TIGER192,1,[Define to include the TIGER/192 digest]) - AC_DEFINE(USE_OLD_TIGER,1,[Define to use the old fake OID for TIGER/192 digest support]) - fi - if test x"$use_sha512" = xyes ; then AC_SUBST(SHA512_O,sha512.o) AC_DEFINE(USE_SHA512,1,[Define to include the SHA-384 and SHA-512 digests]) @@ -689,9 +688,11 @@ AC_CHECK_FUNCS(strerror stpcpy strsep strlwr tcgetattr strtoul mmap) AC_CHECK_FUNCS(strcasecmp strncasecmp ctermid times) AC_CHECK_FUNCS(memmove gettimeofday getrusage setrlimit clock_gettime) AC_CHECK_FUNCS(atexit raise getpagesize strftime nl_langinfo setlocale) -AC_CHECK_FUNCS(waitpid wait4 sigaction sigprocmask rand pipe stat) +AC_CHECK_FUNCS(waitpid wait4 sigaction sigprocmask rand pipe stat getaddrinfo) -# These are needed by libjnlib - fixme: we should have a macros for them +AC_CHECK_TYPES([struct sigaction, sigset_t],,,[#include ]) + +# These are needed by libjnlib - fixme: we should have macros for them AC_CHECK_FUNCS(memicmp stpcpy strlwr strtoul memmove stricmp strtol) AC_CHECK_FUNCS(getrusage setrlimit stat setlocale) AC_CHECK_FUNCS(flockfile funlockfile) @@ -703,6 +704,8 @@ AC_REPLACE_FUNCS(fseeko ftello) AC_REPLACE_FUNCS(isascii) AC_REPLACE_FUNCS(putc_unlocked) + + # # check for gethrtime and run a testprogram to see whether # it is broken. It has been reported that some Solaris and HP UX systems @@ -877,7 +880,7 @@ GNUPG_CHECK_GNUMAKE # mysterious reasons - the final link step should bail out. case "${target}" in *-*-mingw32*) - LIBS="$LIBS -lwsock32" + W32LIBS="-lwsock32" ;; *) ;; @@ -893,6 +896,7 @@ if test "$GCC" = yes; then fi AC_SUBST(NETLIBS) +AC_SUBST(W32LIBS) # We use jnlib, so tell other modules about it diff --git a/g10/ChangeLog b/g10/ChangeLog index 221961c4e..ac7a69468 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,267 @@ +2003-09-23 Werner Koch + + Merged most of David Shaw's changes in 1.3 since 2003-06-03. + + * Makefile.am: Include W32LIBS where appropriate. + + * armor.c (parse_hash_header,armor_filter): Drop TIGER/192 support. + * g10.c (print_hex,print_mds): Ditto. + * pkclist.c (algo_available): Ditto. + + * armor.c (armor_filter): Allow using --comment multiple times to + get multiple Comment header lines. --no-comments resets list. + * options.h, g10.c (main): Ditto. Deprecate --default-comment in + favor of --no-comments. + + * g10.c (main): Trim --help to commonly used options. Remove -f. + + * g10.c (main): Add --multifile as an alias to turn --encrypt into + --encrypt-files (plus --verify-files, --decrypt-files). Error out + if --multifile is used with the commands that don't support it yet. + + * encode.c (use_mdc), g10.c (main): Use RFC1991 and RFC2440 + directly to check for MDC usability. Do not set the force_mdc or + disable_mdc flags since there is no point any longer. + + * g10.c (main): Use "keyserver-url" instead of + "preferred-keyserver" for the sake of short and simple commands. + (add_keyserver_url): Clarify a few strings. It's a + "preferred keyserver URL". + * keyedit.c (keyedit_menu): Ditto. + * sign.c (mk_notation_policy_etc): Ditto. + + * main.h, keygen.c (keygen_add_keyserver_url): Signature callback + for adding a keyserver URL. + * keyedit.c (keyedit_menu, menu_set_keyserver_url): New command to + set preferred keyserver to specified (or all) user IDs. + * build-packet.c (build_sig_subpkt): Set preferred keyserver flag + while building a preferred keyserver subpacket. + + * keylist.c (show_policy_url, show_keyserver_url): URLs might be + UTF8. + + * keyedit.c (menu_addrevoker): Fix leaking a few bytes. + + * keyedit.c (show_key_with_all_names): Use list-option + show-long-keyid in main --edit-key display. + + * keyedit.c (print_and_check_one_sig): Use list-option + show-long-keyid in --edit-key "check" function. + + * passphrase.c (agent_send_all_options): Make use of $GPG_TTY. + + * g10.c (main): Disable use-agent if passphrase-fd is given + later. Suggested by Kurt Garloff. + + * exec.c, g10.c, gpgv.c, passphrase.c, photoid.c: + s/__MINGW32__/_WIN32/ to help building on native Windows + compilers. Requested by Brian Gladman. From Werner on stable + branch. + + * options.h, g10.c (main): Add list-option + list-preferred-keyserver. + + * keyedit.c (change_passphrase): When responding 'no' to the blank + passphrase question, re-prompt for a new passphrase. This is bug + #202. + + * mainproc.c (check_sig_and_print): Use two different preferred + keyserver displays - one if the key is not present (to tell the + user where to get the key), the other if it is present (to tell + the user where the key can be refreshed). + + * packet.h, parse-packet.c (parse_signature): Set flag if a + preferred keyserver is present. + + * keylist.c (list_keyblock_print): Show keyserver url in listings + with list-option show-keyserver-url. + + * mainproc.c (check_sig_and_print): Get the uid validity before + printing any sig results to avoid munging the output with trustdb + warnings. + + * g10.c (main): Don't include --show-keyring in --help as it is + deprecated. + + * options.skel: Note that keyserver.pgp.com isn't synchronized, + and explain the roundrobin a bit better. + + * sig-check.c (check_key_signature2), import.c (import_one, + import_revoke_cert, chk_self_sigs, delete_inv_parts, + collapse_uids, merge_blocks): Make much quieter during import of + slightly munged, but recoverable, keys. Use log_error for + unrecoverable import failures. + + * keyring.c (keyring_rebuild_cache): Comment. + + * sign.c (mk_notation_and_policy): Making a v3 signature with + notations or policy urls is an error, not an info (i.e. increment + the errorcount). Don't print the notation or policy url to stdout + since it can be mixed into the output stream when piping and munge + the stream. + + * packet.h, sig-check.c (signature_check2, do_check, + do_check_messages): Provide a signing-key-is-revoked flag. Change + all callers. + + * status.h, status.c (get_status_string): New REVKEYSIG status tag + for a good signature from a revoked key. + + * mainproc.c (do_check_sig, check_sig_and_print): Use it here. + + * import.c (import_revoke_cert, merge_blocks, merge_sigs): Compare + actual signatures on import rather than using keyid or class + matching. This does not change actual behavior with a key, but + does mean that all sigs are imported whether they will be used or + not. + + * parse-packet.c (parse_signature): Don't give "signature packet + without xxxx" warnings for experimental pk algorithms. An + experimental algorithm may not have a notion of (for example) a + keyid (i.e. PGP's x.509 stuff). + + * options.h, g10.c (main), keylist.c (list_keyblock_print), + keyedit.c (print_and_check_one_sig): New "show-sig-expire" + list-option to show signature expiration dates (if any). + + * options.h, g10.c (main, add_keyserver_url): Add + --sig-preferred-keyserver to implant a "where to get my key" + subpacket into a signature. + + * sign.c (mk_notation_and_policy): Rename to + mk_notation_policy_etc and add preferred keyserver support for + signatures. + + * keygen.c (do_add_key_flags): Don't set the certify flag for + subkeys. + (ask_algo): Provide key flags for DSA, Elgamal_e, and Elgamal + subkeys. + (generate_keypair): Provide key flags for the default DSA/Elgamal + keys. + + * sig-check.c (signature_check, signature_check2, + check_key_signature, check_key_signature2): Allow passing NULLs + for unused parameters in the x2 form of each function to avoid the + need for dummy variables. getkey.c, mainproc.c: Change all + callers. + + * trustdb.h, trustdb.c (read_trust_options): New. Returns items + from the trustdb version record. + * keylist.c (public_key_list): Use it here for the new "tru" + record. + * gpgv.c (read_trust_options): Stub. + + * keyedit.c (show_key_with_all_names): Use list-option + show-validity in --edit-key interface as well. + + * options.h, g10.c (main), mainproc.c (check_sig_and_print): Add + verify-options "show-validity" and "show-long-keyid" to show + trustdb validity and long keyids during (file) signature + verification. + + * packet.h, main.h, sig-check.c (signature_check2) + (check_key_signature2, do_check): If ret_pk is set, fill in the pk + used to verify the signature. Change all callers in getkey.c, + mainproc.c, and sig-check.c. + + * keylist.c (list_keyblock_colon): Use the ret_pk from above to + put the fingerprint of the signing key in "sig" records during a + --with-colons --check-sigs. This requires --no-sig-cache as well + since we don't cache fingerprints. + + * parse-packet.c (parse_signature): No need to reserve 8 bytes for + the unhashed signature cache any longer. + + * misc.c (pct_expando): Add two new expandos - signer's + fingerprint (%g), and signer's primary fingerprint (%p). + + * g10.c (main): Add --rfc2440 alias for --openpgp since in a few + months, they won't be the same thing. + + * keyserver.c (parse_keyserver_uri): Accept "http" as an alias for + "hkp", since it is occasionally written that way. + (keyserver_spawn): Use ascii_isspace to avoid locale issues. + + * keygen.c (ask_user_id): Make --allow-freeform-uid apply to the + email field as well as the name field, and allow mixing fields + when it is set. + + * trustdb.c (validate_one_keyblock): Certifications on revoked or + expired uids do not count in the web of trust. + + * signal.c (init_one_signal, pause_on_sigusr, do_block): Only use + sigprocmask() if we have sigset_t, and only use sigaction() if we + have struct sigaction. This is for Forte c89 on Solaris which + seems to define only the function call half of the two pairs by + default. + (pause_on_sigusr): Typo. + (do_block): If we can't use sigprocmask() and sigset_t, try to get + the number of signals from NSIG as well as MAXSIG, and if we + can't, fail with an explanation. + + * signal.c, tdbio.c: Comment out the transaction code. It was not + used in this version, and was causing some build problems on + quasi-posix platforms (Solaris and Forte c89). + + * keylist.c (list_keyblock_colon): Don't include validity values + when listing secret keys since they can be incorrect and/or + misleading. This is a temporary kludge, and will be handled + properly in 1.9/2.0. + + * mainproc.c (check_sig_and_print): Only show the "key available + from" preferred keyserver line if the key is not currently + present. + + * keyedit.c (sign_uids): Do not sign expired uids without --expert + (same behavior as revoked uids). Do not allow signing a user ID + without a self-signature. --expert overrides. Add additional + prompt to the signature level question. + (menu_expire): When changing expiration dates, don't replace + selfsigs on revoked uids since this would effectively unrevoke + them. There is also no point in replacing expired selfsigs. This + is bug #181 + + * g10.c (add_notation_data): Make sure that only ascii is passed + to iscntrl. Noted by Christian Biere. + * getkey.c (classify_user_id2): Replaced isspace by spacep + * keygen.c (ask_user_id): Ditto. + (get_parameter_algo): Ditto. + * keyedit.c (keyedit_menu): Ditto. + * tdbdump.c (import_ownertrust): Ditto. s/isxdigit/hexdigitp/. + * revoke.c (ask_revocation_reason): + * keyserver.c (keyserver_spawn): Dito. + + * parse-packet.c (parse): Disallow old style partial length for + all key material packets to avoid possible corruption of keyrings. + + * import.c (import_keys_internal): Invalidate the cache so that + the file descriptor gets closed. Fixes bug reported by Juan + F. Codagnone. + + * options.h, g10.c (main), main.h, keylist.c (show_keyserver_url), + mainproc.c (check_sig_and_print), parse-packet.c (dump_sig_subpkt, + parse_one_sig_subpkt, can_handle_critical): Add read-only support + for preferred keyserver subpackets. They're basically policy URLs + with a different name. Add a verify-option + "show-preferred-keyserver" to turn them on and off (on by default, + as per stable branch). + + * g10.c (main): Add "--set-notation" as alias to "--notation-data" + this is to make things consistent with --set-policy-url meaning + both sigs and certs. + + * options.h, g10.c (main), keylist.c (list_keyblock_print): Add + "show-validity" and "show-long-keyid" list-options. + + * gpgv.c (get_validity, trust_value_to_string): Stubs. + + * g10.c (main): Use SAFE_VERSION instead of VERSION in the + version-specific gpg.conf file so it can be overridden on RISCOS. + + * keyedit.c (show_key_with_all_names): Fix assertion failure when + using toggle to see a secret key. Reported by Maxim Britov. + + 2003-09-22 Timo Schulz * card-util.c (card_status): Free pk in case of an error diff --git a/g10/Makefile.am b/g10/Makefile.am index 59213d04b..ef2b0c3a8 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -109,7 +109,7 @@ gpgv2_SOURCES = gpgv.c \ # ks-db.h \ # $(common_source) -LDADD = $(needed_libs) @INTLLIBS@ @CAPLIBS@ @ZLIBS@ +LDADD = $(needed_libs) @INTLLIBS@ @CAPLIBS@ @ZLIBS@ @W32LIBS@ gpg2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error gpgv2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error diff --git a/g10/armor.c b/g10/armor.c index c6930e22a..121ec3a09 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -249,16 +249,12 @@ parse_hash_header( const char *line ) found |= 2; else if( !strncmp( s, "MD5", s2-s ) ) found |= 4; - else if( !strncmp( s, "TIGER192", s2-s ) ) - found |= 8; - else if( !strncmp( s, "TIGER", s2-s ) ) /* used by old versions */ - found |= 8; else if( !strncmp( s, "SHA256", s2-s ) ) - found |= 16; + found |= 8; else if( !strncmp( s, "SHA384", s2-s ) ) - found |= 32; + found |= 16; else if( !strncmp( s, "SHA512", s2-s ) ) - found |= 64; + found |= 32; else return 0; for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ ) @@ -899,12 +895,10 @@ armor_filter( void *opaque, int control, if( hashes & 4 ) buf[n++] = DIGEST_ALGO_MD5; if( hashes & 8 ) - buf[n++] = DIGEST_ALGO_TIGER; - if( hashes & 16 ) buf[n++] = DIGEST_ALGO_SHA256; - if( hashes & 32 ) + if( hashes & 16 ) buf[n++] = DIGEST_ALGO_SHA384; - if( hashes & 64 ) + if( hashes & 32 ) buf[n++] = DIGEST_ALGO_SHA512; buf[1] = n - 2; @@ -932,6 +926,7 @@ armor_filter( void *opaque, int control, else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) { if( !afx->status ) { /* write the header line */ const char *s; + STRLIST comment = opt.comments; if( afx->what >= DIM(head_strings) ) log_bug("afx->what=%d", afx->what); @@ -942,22 +937,24 @@ armor_filter( void *opaque, int control, iobuf_writestr(a, "Version: GnuPG v" VERSION " (" PRINTABLE_OS_NAME ")" LF ); - /* write the comment string or a default one */ - s = opt.comment_string; - if( s && *s ) { + /* Write the comment string. */ + for(s=comment? comment->d:NULL; comment; + comment=comment->next,s=comment->d) + { iobuf_writestr(a, "Comment: " ); - for( ; *s; s++ ) { + for ( ; *s; s++ ) + { if( *s == '\n' ) - iobuf_writestr(a, "\\n" ); + iobuf_writestr(a, "\\n" ); else if( *s == '\r' ) - iobuf_writestr(a, "\\r" ); + iobuf_writestr(a, "\\r" ); else if( *s == '\v' ) - iobuf_writestr(a, "\\v" ); + iobuf_writestr(a, "\\v" ); else - iobuf_put(a, *s ); - } + iobuf_put(a, *s ); + } iobuf_writestr(a, LF ); - } + } if ( afx->hdrlines ) { for ( s = afx->hdrlines; *s; s++ ) { diff --git a/g10/build-packet.c b/g10/build-packet.c index a24bdfcc6..d2c538477 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -756,6 +756,10 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, sig->flags.policy_url=1; break; + case SIGSUBPKT_PREF_KS: + sig->flags.pref_ks=1; + break; + case SIGSUBPKT_EXPORTABLE: if(buffer[0]) sig->flags.exportable=1; diff --git a/g10/encode.c b/g10/encode.c index 9fc00183f..7794bdb7c 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -122,6 +122,10 @@ use_mdc (PK_LIST pk_list,int algo) CIPHER_ALGO_TWOFISH }; int i; + + /* RFC-1991 and 2440 don't have MDC */ + if(RFC1991 || RFC2440) + return 0; /* --force-mdc overrides --disable-mdc */ if (opt.force_mdc) diff --git a/g10/exec.c b/g10/exec.c index f3b58aa3c..a49fe15d2 100644 --- a/g10/exec.c +++ b/g10/exec.c @@ -1,5 +1,5 @@ /* exec.c - generic call-a-program code - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -59,7 +59,7 @@ int set_exec_path(const char *path,int method) { return GPG_ERR_GENERAL; } char *mkdtemp(char *template); #endif -#if defined (__MINGW32__) +#if defined (_WIN32) /* This is a nicer system() for windows that waits for programs to return before returning control to the caller. I hate helpful computers. */ @@ -139,7 +139,7 @@ static int make_tempdir(struct exec_info *info) if(tmp==NULL) { -#if defined (__MINGW32__) +#if defined (_WIN32) tmp=xmalloc (256); if(GetTempPath(256,tmp)==0) strcpy(tmp,"c:\\windows\\temp"); @@ -176,7 +176,7 @@ static int make_tempdir(struct exec_info *info) sprintf(info->tempdir,"%s" DIRSEP_S "gpg-XXXXXX",tmp); -#if defined (__MINGW32__) +#if defined (_WIN32) xfree (tmp); #endif @@ -502,7 +502,7 @@ int exec_read(struct exec_info *info) if(DBG_EXTPROG) log_debug("system() command is %s\n",info->command); -#if defined (__MINGW32__) +#if defined (_WIN32) info->progreturn=win_system(info->command); #else info->progreturn=system(info->command); diff --git a/g10/g10.c b/g10/g10.c index 619832372..cdd10d845 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -59,7 +59,6 @@ enum cmd_and_opt_values { aNull = 0, aSym = 'c', aDecrypt = 'd', aEncr = 'e', - aEncrFiles, oInteractive = 'i', aListKeys = 'k', aListSecretKeys = 'K', @@ -73,12 +72,13 @@ enum cmd_and_opt_values { aNull = 0, oUser = 'u', oVerbose = 'v', oCompress = 'z', - oNotation = 'N', + oSetNotation = 'N', oBatch = 500, oSigNotation, oCertNotation, oShowNotation, oNoShowNotation, + aEncrFiles, aDecryptFiles, aClearsign, aStore, @@ -172,6 +172,7 @@ enum cmd_and_opt_values { aNull = 0, oLoadExtension, oGnuPG, oRFC1991, + oRFC2440, oOpenPGP, oPGP2, oPGP6, @@ -219,9 +220,11 @@ enum cmd_and_opt_values { aNull = 0, oCertPolicyURL, oShowPolicyURL, oNoShowPolicyURL, + oSigKeyserverURL, oUseEmbeddedFilename, oComment, oDefaultComment, + oNoComments, oThrowKeyid, oNoThrowKeyid, oShowPhotos, @@ -315,6 +318,7 @@ enum cmd_and_opt_values { aNull = 0, oMangleDosFilenames, oNoMangleDosFilenames, oEnableProgressFilter, + oMultifile, aTest }; @@ -326,17 +330,17 @@ static ARGPARSE_OPTS opts[] = { { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") }, { aDetachedSign, "detach-sign", 256, N_("make a detached signature")}, { aEncr, "encrypt", 256, N_("encrypt data")}, - { aEncrFiles, "encrypt-files", 256, N_("|[files]|encrypt files")}, + { aEncrFiles, "encrypt-files", 256, "@"}, { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")}, - { aStore, "store", 256, N_("store only")}, + { aStore, "store", 256, "@"}, { aDecrypt, "decrypt", 256, N_("decrypt data (default)")}, - { aDecryptFiles, "decrypt-files", 256, N_("|[files]|decrypt files")}, + { aDecryptFiles, "decrypt-files", 256, "@"}, { aVerify, "verify" , 256, N_("verify a signature")}, { aVerifyFiles, "verify-files" , 256, "@" }, { aListKeys, "list-keys", 256, N_("list keys")}, { aListKeys, "list-public-keys", 256, "@" }, { aListSigs, "list-sigs", 256, N_("list keys and signatures")}, - { aCheckKeys, "check-sigs",256, N_("check key signatures")}, + { aCheckKeys, "check-sigs",256, N_("list and check key signatures")}, { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")}, { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")}, { aKeygen, "gen-key", 256, N_("generate a new key pair")}, @@ -345,8 +349,8 @@ static ARGPARSE_OPTS opts[] = { N_("remove keys from the secret keyring")}, { aSignKey, "sign-key" ,256, N_("sign a key")}, { aLSignKey, "lsign-key" ,256, N_("sign a key locally")}, - { aNRSignKey, "nrsign-key" ,256, N_("sign a key non-revocably")}, - { aNRLSignKey, "nrlsign-key" ,256, N_("sign a key locally and non-revocably")}, + { aNRSignKey, "nrsign-key" ,256, "@"}, + { aNRLSignKey, "nrlsign-key" ,256, "@"}, { aEditKey, "edit-key" ,256, N_("sign or edit a key")}, { aGenRevoke, "gen-revoke",256, N_("generate a revocation certificate")}, { aDesigRevoke, "desig-revoke",256, "@" }, @@ -366,19 +370,15 @@ static ARGPARSE_OPTS opts[] = { { aCardEdit, "card-edit", 256, N_("change data on a card")}, { aChangePIN, "change-pin", 256, N_("change a card's PIN")}, - { aListPackets, "list-packets",256,N_("list only the sequence of packets")}, - { aExportOwnerTrust, - "export-ownertrust", 256, N_("export the ownertrust values")}, - { aImportOwnerTrust, - "import-ownertrust", 256, N_("import ownertrust values")}, - { aUpdateTrustDB, - "update-trustdb",0 , N_("update the trust database")}, - { aCheckTrustDB, - "check-trustdb",0 , N_("unattended trust database update")}, + { aListPackets, "list-packets",256, "@"}, + { aExportOwnerTrust, "export-ownertrust", 256, "@"}, + { aImportOwnerTrust, "import-ownertrust", 256, "@"}, + { aUpdateTrustDB, "update-trustdb",0 , N_("update the trust database")}, + { aCheckTrustDB, "check-trustdb",0 , "@"}, { aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")}, - { aDeArmor, "dearmor", 256, N_("De-Armor a file or stdin") }, + { aDeArmor, "dearmor", 256, "@" }, { aDeArmor, "dearmour", 256, "@" }, - { aEnArmor, "enarmor", 256, N_("En-Armor a file or stdin") }, + { aEnArmor, "enarmor", 256, "@" }, { aEnArmor, "enarmour", 256, "@" }, { aPrintMD, "print-md" , 256, N_("|algo [files]|print message digests")}, { aPrimegen, "gen-prime" , 256, "@" }, @@ -391,10 +391,8 @@ static ARGPARSE_OPTS opts[] = { { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")}, { oHiddenRecipient, "hidden-recipient", 2, "@" }, { oRecipient, "remote-user", 2, "@"}, /* old option name */ - { oDefRecipient, "default-recipient" ,2, - N_("|NAME|use NAME as default recipient")}, - { oDefRecipientSelf, "default-recipient-self" ,0, - N_("use the default key as default recipient")}, + { oDefRecipient, "default-recipient" ,2, "@" }, + { oDefRecipientSelf, "default-recipient-self" ,0, "@" }, { oNoDefRecipient, "no-default-recipient", 0, "@" }, { oTempDir, "temp-directory", 2, "@" }, { oExecPath, "exec-path", 2, "@" }, @@ -414,82 +412,82 @@ static ARGPARSE_OPTS opts[] = { { oNoAskCertExpire, "no-ask-cert-expire", 0, "@"}, { oOutput, "output", 2, N_("use as output file")}, { oVerbose, "verbose", 0, N_("verbose") }, - { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, - { oNoTTY, "no-tty", 0, N_("don't use the terminal at all") }, - { oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") }, - { oNoForceV3Sigs, "no-force-v3-sigs", 0, N_("do not force v3 signatures") }, - { oForceV4Certs, "force-v4-certs", 0, N_("force v4 key signatures") }, - { oNoForceV4Certs, "no-force-v4-certs", 0, N_("do not force v4 key signatures") }, - { oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") }, + { oQuiet, "quiet", 0, "@" }, + { oNoTTY, "no-tty", 0, "@" }, + { oForceV3Sigs, "force-v3-sigs", 0, "@" }, + { oNoForceV3Sigs, "no-force-v3-sigs", 0, "@" }, + { oForceV4Certs, "force-v4-certs", 0, "@" }, + { oNoForceV4Certs, "no-force-v4-certs", 0, "@" }, + { oForceMDC, "force-mdc", 0, "@" }, { oNoForceMDC, "no-force-mdc", 0, "@" }, - { oDisableMDC, "disable-mdc", 0, N_("never use a MDC for encryption") }, + { oDisableMDC, "disable-mdc", 0, "@" }, { oNoDisableMDC, "no-disable-mdc", 0, "@" }, { oDryRun, "dry-run", 0, N_("do not make any changes") }, { oInteractive, "interactive", 0, N_("prompt before overwriting") }, - { oUseAgent, "use-agent",0, N_("use the gpg-agent")}, + { oUseAgent, "use-agent",0, "@"}, { oNoUseAgent, "no-use-agent",0, "@"}, { oGpgAgentInfo, "gpg-agent-info",2, "@"}, - { oBatch, "batch", 0, N_("batch mode: never ask")}, - { oAnswerYes, "yes", 0, N_("assume yes on most questions")}, - { oAnswerNo, "no", 0, N_("assume no on most questions")}, - { oKeyring, "keyring" ,2, N_("add this keyring to the list of keyrings")}, + { oBatch, "batch", 0, "@"}, + { oAnswerYes, "yes", 0, "@"}, + { oAnswerNo, "no", 0, "@"}, + { oKeyring, "keyring" , 2, "@"}, { oPrimaryKeyring, "primary-keyring",2, "@" }, - { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")}, - { oShowKeyring, "show-keyring", 0, N_("show which keyring a listed key is on")}, - { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")}, - { oKeyServer, "keyserver",2, N_("|HOST|use this keyserver to lookup keys")}, + { oSecretKeyring, "secret-keyring" ,2, "@"}, + { oShowKeyring, "show-keyring", 0, "@"}, + { oDefaultKey, "default-key" , 2, "@"}, + { oKeyServer, "keyserver", 2, "@"}, { oKeyServerOptions, "keyserver-options",2,"@"}, { oImportOptions, "import-options",2,"@"}, { oExportOptions, "export-options",2,"@"}, { oListOptions, "list-options",2,"@"}, - { oCharset, "charset" , 2, N_("|NAME|set terminal charset to NAME") }, - { oOptions, "options" , 2, N_("read options from file")}, + { oVerifyOptions, "verify-options",2,"@"}, + { oCharset, "charset" , 2, "@" }, + { oOptions, "options" , 2, "@"}, { oDebug, "debug" ,4|16, "@"}, { oDebugAll, "debug-all" ,0, "@"}, - { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") }, + { oStatusFD, "status-fd" ,1, "@" }, #ifdef __riscos__ - { oStatusFile, "status-file" ,2, N_("|[file]|write status info to file") }, + { oStatusFile, "status-file" ,2, "@" }, #endif /* __riscos__ */ { oAttributeFD, "attribute-fd" ,1, "@" }, #ifdef __riscos__ { oAttributeFile, "attribute-file" ,2, "@" }, #endif /* __riscos__ */ - { oNoSKComments, "no-comment", 0, "@"}, { oNoSKComments, "no-sk-comments", 0, "@"}, { oSKComments, "sk-comments", 0, "@"}, { oCompletesNeeded, "completes-needed", 1, "@"}, { oMarginalsNeeded, "marginals-needed", 1, "@"}, { oMaxCertDepth, "max-cert-depth", 1, "@" }, - { oTrustedKey, "trusted-key", 2, N_("|KEYID|ultimately trust this key")}, - { oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")}, + { oTrustedKey, "trusted-key", 2, "@"}, + { oLoadExtension, "load-extension" ,2, "@"}, { oGnuPG, "gnupg", 0, "@"}, { oGnuPG, "no-pgp2", 0, "@"}, { oGnuPG, "no-pgp6", 0, "@"}, { oGnuPG, "no-pgp7", 0, "@"}, { oGnuPG, "no-pgp8", 0, "@"}, - { oRFC1991, "rfc1991", 0, N_("emulate the mode described in RFC1991")}, - { oOpenPGP, "openpgp", 0, N_("set all packet, cipher and digest options to OpenPGP behavior")}, - { oPGP2, "pgp2", 0, N_("set all packet, cipher and digest options to PGP 2.x behavior")}, + { oRFC1991, "rfc1991", 0, "@"}, + { oRFC2440, "rfc2440", 0, "@"}, + { oOpenPGP, "openpgp", 0, N_("use strict OpenPGP behavior")}, + { oPGP2, "pgp2", 0, N_("generate PGP 2.x compatible messages")}, { oPGP6, "pgp6", 0, "@"}, { oPGP7, "pgp7", 0, "@"}, { oPGP8, "pgp8", 0, "@"}, - { oS2KMode, "s2k-mode", 1, N_("|N|use passphrase mode N")}, - { oS2KDigest, "s2k-digest-algo",2, - N_("|NAME|use message digest algorithm NAME for passphrases")}, - { oS2KCipher, "s2k-cipher-algo",2, - N_("|NAME|use cipher algorithm NAME for passphrases")}, + { oS2KMode, "s2k-mode", 1, "@"}, + { oS2KDigest, "s2k-digest-algo",2, "@"}, + { oS2KCipher, "s2k-cipher-algo",2, "@"}, { oSimpleSKChecksum, "simple-sk-checksum", 0, "@"}, - { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")}, - { oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")}, + { oCipherAlgo, "cipher-algo", 2 , "@"}, + { oDigestAlgo, "digest-algo", 2 , "@"}, { oCertDigestAlgo, "cert-digest-algo", 2 , "@" }, - { oCompressAlgo,"compress-algo",2,N_("|NAME|use compression algorithm NAME")}, - { oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")}, + { oCompressAlgo,"compress-algo",2, "@"}, + { oThrowKeyid, "throw-keyid", 0, "@"}, { oNoThrowKeyid, "no-throw-keyid", 0, "@" }, { oShowPhotos, "show-photos", 0, "@" }, { oNoShowPhotos, "no-show-photos", 0, "@" }, { oPhotoViewer, "photo-viewer", 2, "@" }, - { oNotation, "notation-data", 2, "@" }, + { oSetNotation, "set-notation", 2, "@" }, + { oSetNotation, "notation-data", 2, "@" }, /* Alias */ { oSigNotation, "sig-notation", 2, "@" }, { oCertNotation, "cert-notation", 2, "@" }, @@ -556,8 +554,10 @@ static ARGPARSE_OPTS opts[] = { { oNoShowPolicyURL, "no-show-policy-url", 0, "@" }, { oShowNotation, "show-notation", 0, "@" }, { oNoShowNotation, "no-show-notation", 0, "@" }, + { oSigKeyserverURL, "sig-keyserver-url", 2, "@" }, { oComment, "comment", 2, "@" }, { oDefaultComment, "default-comment", 0, "@" }, + { oNoComments, "no-comments", 0, "@" }, { oEmitVersion, "emit-version", 0, "@"}, { oNoEmitVersion, "no-emit-version", 0, "@"}, { oNoEmitVersion, "no-version", 0, "@"}, /* alias */ @@ -625,6 +625,7 @@ static ARGPARSE_OPTS opts[] = { { oMangleDosFilenames, "mangle-dos-filenames", 0, "@" }, { oNoMangleDosFilenames, "no-mangle-dos-filenames", 0, "@" }, { oEnableProgressFilter, "enable-progress-filter", 0, "@" }, + { oMultifile, "multifile", 0, "@" }, {0} }; @@ -641,6 +642,7 @@ static void set_cmd( enum cmd_and_opt_values *ret_cmd, static void print_mds( const char *fname, int algo ); static void add_notation_data( const char *string, int which ); static void add_policy_url( const char *string, int which ); +static void add_keyserver_url( const char *string, int which ); static void emergency_cleanup (void); #ifdef __riscos__ @@ -1158,6 +1160,7 @@ main( int argc, char **argv ) char *pers_digest_list = NULL; char *pers_compress_list = NULL; int eyes_only=0; + int multifile=0; int pwfd = -1; int with_fpr = 0; /* make an option out of --fingerprint */ int any_explicit_recipient = 0; @@ -1222,12 +1225,13 @@ main( int argc, char **argv ) opt.keyserver_options.include_subkeys=1; opt.keyserver_options.include_revoked=1; opt.keyserver_options.try_dns_srv=1; - opt.verify_options=VERIFY_SHOW_POLICY|VERIFY_SHOW_NOTATION; + opt.verify_options= + VERIFY_SHOW_POLICY|VERIFY_SHOW_NOTATION|VERIFY_SHOW_KEYSERVER; opt.trust_model=TM_AUTO; opt.mangle_dos_filenames = 1; opt.use_agent = 1; -#if defined (__MINGW32__) +#if defined (_WIN32) set_homedir ( read_w32_registry_string( NULL, "Software\\GNU\\GnuPG", "HomeDir" )); #else @@ -1389,11 +1393,15 @@ main( int argc, char **argv ) case aDetachedSign: detached_sig = 1; set_cmd( &cmd, aSign ); break; case aSym: set_cmd( &cmd, aSym); break; + case aDecryptFiles: multifile=1; /* fall through */ case aDecrypt: set_cmd( &cmd, aDecrypt); break; - case aDecryptFiles: set_cmd( &cmd, aDecryptFiles); break; + case aEncrFiles: multifile=1; /* fall through */ case aEncr: set_cmd( &cmd, aEncr); break; - case aEncrFiles: set_cmd( &cmd, aEncrFiles ); break; + + case aVerifyFiles: multifile=1; /* fall through */ + case aVerify: set_cmd( &cmd, aVerify); break; + case aSign: set_cmd( &cmd, aSign ); break; case aKeygen: set_cmd( &cmd, aKeygen); greeting=1; break; case aSignKey: set_cmd( &cmd, aSignKey); break; @@ -1405,8 +1413,7 @@ main( int argc, char **argv ) case aClearsign: set_cmd( &cmd, aClearsign); break; case aGenRevoke: set_cmd( &cmd, aGenRevoke); break; case aDesigRevoke: set_cmd( &cmd, aDesigRevoke); break; - case aVerify: set_cmd( &cmd, aVerify); break; - case aVerifyFiles: set_cmd( &cmd, aVerifyFiles); break; + case aPrimegen: set_cmd( &cmd, aPrimegen); break; case aGenRandom: set_cmd( &cmd, aGenRandom); break; case aPrintMD: set_cmd( &cmd, aPrintMD); break; @@ -1564,7 +1571,7 @@ main( int argc, char **argv ) break; case oLoadExtension: #ifndef __riscos__ -#if defined(USE_DYNAMIC_LINKING) || defined(__MINGW32__) +#if defined(USE_DYNAMIC_LINKING) || defined(_WIN32) if(check_permissions(pargs.r.ret_str,2)) log_info(_("cipher extension \"%s\" not loaded due to " "unsafe permissions\n"),pargs.r.ret_str); @@ -1579,14 +1586,13 @@ main( int argc, char **argv ) case oRFC1991: opt.compliance = CO_RFC1991; opt.force_v4_certs = 0; - opt.disable_mdc = 1; opt.escape_from = 1; break; + case oRFC2440: case oOpenPGP: /* TODO: When 2440bis becomes a RFC, these may need changing. */ opt.compliance = CO_RFC2440; - opt.disable_mdc = 1; opt.allow_non_selfsigned_uid = 1; opt.allow_freeform_uid = 1; opt.pgp2_workarounds = 0; @@ -1627,9 +1633,19 @@ main( int argc, char **argv ) opt.list_options&=~LIST_SHOW_POLICY; opt.verify_options&=~VERIFY_SHOW_POLICY; break; + case oSigKeyserverURL: add_keyserver_url(pargs.r.ret_str,0); break; case oUseEmbeddedFilename: opt.use_embedded_filename = 1; break; - case oComment: opt.comment_string = pargs.r.ret_str; break; - case oDefaultComment: opt.comment_string = NULL; break; + + case oComment: add_to_strlist(&opt.comments,pargs.r.ret_str); break; + case oDefaultComment: + deprecated_warning(configname,configlineno, + "--default-comment","--no-comments",""); + /* fall through */ + case oNoComments: + free_strlist(opt.comments); + opt.comments=NULL; + break; + case oThrowKeyid: opt.throw_keyid = 1; break; case oNoThrowKeyid: opt.throw_keyid = 0; break; case oShowPhotos: @@ -1686,6 +1702,7 @@ main( int argc, char **argv ) case oCompress: opt.compress = pargs.r.ret_int; break; case oPasswdFD: pwfd = iobuf_translate_file_handle (pargs.r.ret_int, 0); + opt.use_agent = 0; break; #ifdef __riscos__ case oPasswdFile: @@ -1784,9 +1801,11 @@ main( int argc, char **argv ) {"show-photos",LIST_SHOW_PHOTOS}, {"show-policy-url",LIST_SHOW_POLICY}, {"show-notation",LIST_SHOW_NOTATION}, - {"show-keyring",LIST_SHOW_KEYRING}, + {"show-keyserver-url",LIST_SHOW_KEYSERVER}, {"show-validity",LIST_SHOW_VALIDITY}, {"show-long-keyid",LIST_SHOW_LONG_KEYID}, + {"show-keyring",LIST_SHOW_KEYRING}, + {"show-sig-expire",LIST_SHOW_SIG_EXPIRE}, {NULL,0} }; @@ -1807,6 +1826,9 @@ main( int argc, char **argv ) {"show-photos",VERIFY_SHOW_PHOTOS}, {"show-policy-url",VERIFY_SHOW_POLICY}, {"show-notation",VERIFY_SHOW_NOTATION}, + {"show-keyserver-url",VERIFY_SHOW_KEYSERVER}, + {"show-validity",VERIFY_SHOW_VALIDITY}, + {"show-long-keyid",VERIFY_SHOW_LONG_KEYID}, {NULL,0} }; @@ -1827,7 +1849,7 @@ main( int argc, char **argv ) else opt.exec_path_set=1; break; - case oNotation: + case oSetNotation: add_notation_data( pargs.r.ret_str, 0 ); add_notation_data( pargs.r.ret_str, 1 ); break; @@ -1931,6 +1953,7 @@ main( int argc, char **argv ) case oNoMangleDosFilenames: opt.mangle_dos_filenames = 0; break; case oEnableProgressFilter: opt.enable_progress_filter = 1; break; + case oMultifile: multifile=1; break; default : pargs.err = configfp? 1:2; break; } @@ -2053,8 +2076,6 @@ main( int argc, char **argv ) compliance_failure(); else { - opt.force_mdc = 0; - opt.disable_mdc = 1; opt.force_v4_certs = 0; opt.sk_comments = 0; opt.escape_from = 1; @@ -2073,8 +2094,6 @@ main( int argc, char **argv ) opt.escape_from=1; opt.force_v3_sigs=1; opt.ask_sig_expire=0; - opt.force_mdc=0; - opt.disable_mdc=1; } else if(PGP7) { @@ -2170,6 +2189,37 @@ main( int argc, char **argv ) keygen_set_std_prefs(pers_compress_list,PREFTYPE_ZIP)) log_error(_("invalid personal compress preferences\n")); + /* We don't support all possible commands with multifile yet */ + if(multifile) + { + char *cmdname; + + switch(cmd) + { + case aSign: + cmdname="--sign"; + break; + case aClearsign: + cmdname="--clearsign"; + break; + case aDetachedSign: + cmdname="--detach-sign"; + break; + case aSym: + cmdname="--symmetric"; + break; + case aStore: + cmdname="--store"; + break; + default: + cmdname=NULL; + break; + } + + if(cmdname) + log_error(_("%s does not yet work with %s\n"),cmdname,"--multifile"); + } + if( log_get_errorcount(0) ) g10_exit(2); @@ -2262,8 +2312,7 @@ main( int argc, char **argv ) if( cmd != aDeArmor && cmd != aEnArmor ) { if (cmd != aCheckKeys && cmd != aListSigs && cmd != aListKeys - && cmd != aVerify && cmd != aVerifyFiles - && cmd != aSym) + && cmd != aVerify && cmd != aSym) { if (!sec_nrings || default_keyring) /* add default secret rings */ keydb_add_resource ("secring" EXTSEP_S "gpg", 0, 1); @@ -2335,17 +2384,18 @@ main( int argc, char **argv ) break; case aEncr: /* encrypt the given file */ - if( argc > 1 ) - wrong_args(_("--encrypt [filename]")); - if( (rc = encode_crypt(fname,remusr)) ) - log_error("%s: encryption failed: %s\n", - print_fname_stdin(fname), gpg_strerror (rc) ); + if(multifile) + encode_crypt_files(argc, argv, remusr); + else + { + if( argc > 1 ) + wrong_args(_("--encrypt [filename]")); + if( (rc = encode_crypt(fname,remusr)) ) + log_error("%s: encryption failed: %s\n", + print_fname_stdin(fname), gpg_strerror (rc) ); + } break; - case aEncrFiles: /* encrypt the given files */ - encode_crypt_files(argc, argv, remusr); - break; - case aSign: /* sign the given file */ sl = NULL; if( detached_sig ) { /* sign all files */ @@ -2397,26 +2447,30 @@ main( int argc, char **argv ) break; case aVerify: - if( (rc = verify_signatures( argc, argv ) )) - log_error("verify signatures failed: %s\n", gpg_strerror (rc) ); - break; - - case aVerifyFiles: - if( (rc = verify_files( argc, argv ) )) - log_error("verify files failed: %s\n", gpg_strerror (rc) ); + if(multifile) + { + if( (rc = verify_files( argc, argv ) )) + log_error("verify files failed: %s\n", gpg_strerror (rc) ); + } + else + { + if( (rc = verify_signatures( argc, argv ) )) + log_error("verify signatures failed: %s\n", gpg_strerror (rc) ); + } break; case aDecrypt: - if( argc > 1 ) - wrong_args(_("--decrypt [filename]")); - if( (rc = decrypt_message( fname ) )) - log_error("decrypt_message failed: %s\n", gpg_strerror (rc) ); + if(multifile) + decrypt_messages(argc, argv); + else + { + if( argc > 1 ) + wrong_args(_("--decrypt [filename]")); + if( (rc = decrypt_message( fname ) )) + log_error("decrypt_message failed: %s\n", gpg_strerror (rc) ); + } break; - case aDecryptFiles: - decrypt_messages(argc, argv); - break; - case aSignKey: /* sign the key given as argument */ if( argc != 1 ) wrong_args(_("--sign-key user-id")); @@ -2900,8 +2954,6 @@ print_hex( MD_HANDLE md, int algo, const char *fname ) if(algo==DIGEST_ALGO_RMD160) indent+=printf("RMD160 = "); - else if(algo==DIGEST_ALGO_TIGER) - indent+=printf(" TIGER = "); else if(algo>0) indent+=printf("%6s = ", gcry_md_algo_name (algo)); else @@ -3018,9 +3070,6 @@ print_mds( const char *fname, int algo ) gcry_md_enable (md, GCRY_MD_MD5 ); gcry_md_enable (md, GCRY_MD_SHA1 ); gcry_md_enable (md, GCRY_MD_RMD160 ); -#ifdef USE_TIGER192 - gcry_md_enable (md, GCRY_MD_TIGER ); -#endif #ifdef USE_SHA256 gcry_md_enable (md, GCRY_MD_SHA256 ); #endif @@ -3043,9 +3092,6 @@ print_mds( const char *fname, int algo ) print_hashline( md, GCRY_MD_MD5, fname ); print_hashline( md, GCRY_MD_SHA1, fname ); print_hashline( md, GCRY_MD_RMD160, fname ); -#ifdef USE_TIGER192 - print_hashline( md, GCRY_MD_TIGER, fname ); -#endif #ifdef USE_SHA256 print_hashline( md, GCRY_MD_SHA256, fname ); #endif @@ -3062,9 +3108,6 @@ print_mds( const char *fname, int algo ) print_hex( md, GCRY_MD_MD5, fname ); print_hex( md, GCRY_MD_SHA1, fname ); print_hex( md, GCRY_MD_RMD160, fname ); -#ifdef USE_TIGER192 - print_hex( md, GCRY_MD_TIGER, fname ); -#endif #ifdef USE_SHA256 print_hex( md, GCRY_MD_SHA256, fname ); #endif @@ -3132,13 +3175,13 @@ add_notation_data( const char *string, int which ) /* we only support printable text - therefore we enforce the use * of only printable characters (an empty value is valid) */ for( s++; *s ; s++ ) { - if( iscntrl(*s) ) { + if( *s & 0x80 ) + highbit = 1; + else if( iscntrl(*s) ) { log_error(_("a notation value must not use " "any control characters\n") ); return; } - else if( *s & 0x80 ) - highbit = 1; } if( highbit ) /* must use UTF8 encoding */ @@ -3183,3 +3226,39 @@ add_policy_url( const char *string, int which ) if(critical) sl->flags |= 1; } + + +static void +add_keyserver_url( const char *string, int which ) +{ + int i,critical=0; + STRLIST sl; + + if(*string=='!') + { + string++; + critical=1; + } + + for(i=0;iflags |= 1; +} + diff --git a/g10/getkey.c b/g10/getkey.c index 7eda9384c..f51b8f2df 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -572,7 +572,7 @@ classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc ) memset (desc, 0, sizeof *desc); /* skip leading spaces. Fixme: what is with trailing spaces? */ - for(s = name; *s && isspace(*s); s++ ) + for(s = name; *s && spacep (s); s++ ) ; switch (*s) { @@ -653,7 +653,7 @@ classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc ) } /* check if a hexadecimal number is terminated by EOS or blank */ - if (hexlength && s[hexlength] && !isspace(s[hexlength])) { + if (hexlength && s[hexlength] && !spacep (s+hexlength)) { if (hexprefix) /* a "0x" prefix without correct */ return 0; /* termination is an error */ else /* The first chars looked like */ @@ -1593,8 +1593,6 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) else if ( k->pkt->pkttype == PKT_SIGNATURE && uidnode ) { PKT_signature *sig = k->pkt->pkt.signature; - u32 dummy; - int dum2; if(sig->keyid[0] != kid[0] || sig->keyid[1]!=kid[1]) { @@ -1610,7 +1608,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) ultimate trust flag. */ if(get_pubkey_fast(ultimate_pk,sig->keyid)==0 && check_key_signature2(keyblock,k,ultimate_pk, - NULL,&dummy,&dum2)==0 + NULL, NULL, NULL, NULL)==0 && get_ownertrust(ultimate_pk)==TRUST_ULTIMATE) { free_public_key(ultimate_pk); diff --git a/g10/gpgv.c b/g10/gpgv.c index fb96fad5c..596b09fcb 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -1,5 +1,6 @@ /* gpgv.c - The GnuPG signature verify utility - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -155,8 +156,9 @@ main( int argc, char **argv ) opt.trust_model = TM_ALWAYS; opt.batch = 1; -#if defined (__MINGW32__) - opt.homedir = read_w32_registry_string( NULL, "Software\\GNU\\GnuPG", "HomeDir" ); +#if defined (_WIN32) + opt.homedir = read_w32_registry_string( NULL, "Software\\GNU\\GnuPG", + "HomeDir" ); #else opt.homedir = getenv("GNUPGHOME"); #endif @@ -221,6 +223,14 @@ g10_exit( int rc ) } + +void +read_trust_options (byte *trust_model,ulong *created,ulong *nextcheck, + byte *marginals,byte *completes,byte *cert_depth) +{ +} + + /* Stub: * We have to override the trustcheck from pkclist.c becuase * this utility assumes that all keys in the keyring are trustworthy diff --git a/g10/import.c b/g10/import.c index 84d60a1b3..9c323243a 100644 --- a/g10/import.c +++ b/g10/import.c @@ -1,5 +1,6 @@ -/* import.c - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +/* import.c - Import OpenPGP key material + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -168,6 +169,8 @@ import_keys_internal( iobuf_t inp, char **fnames, int nnames, else { rc = import( inp2, fname, stats, options ); iobuf_close(inp2); + /* Must invalidate that ugly cache to actually close it. */ + iobuf_ioctl (NULL, 2, 0, (char*)fname); if( rc ) log_error("import from `%s' failed: %s\n", fname, gpg_strerror (rc) ); @@ -589,7 +592,8 @@ import_one( const char *fname, KBNODE keyblock, clear_kbnode_flags( keyblock ); - if((options&IMPORT_REPAIR_PKS_SUBKEY_BUG) && fix_pks_corruption(keyblock)) + if((options&IMPORT_REPAIR_PKS_SUBKEY_BUG) && fix_pks_corruption(keyblock) + && opt.verbose) log_info(_("key %08lX: PKS subkey corruption repaired\n"), (ulong)keyid[1]); @@ -611,11 +615,9 @@ import_one( const char *fname, KBNODE keyblock, } if( !delete_inv_parts( fname, keyblock, keyid, options ) ) { - if( !opt.quiet ) { - log_info( _("key %08lX: no valid user IDs\n"), - (ulong)keyid[1]); + log_error ( _("key %08lX: no valid user IDs\n"), (ulong)keyid[1]); + if( !opt.quiet ) log_info(_("this may be caused by a missing self-signature\n")); - } stats->no_user_id++; return 0; } @@ -979,8 +981,8 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) pk = xcalloc (1, sizeof *pk ); rc = get_pubkey( pk, keyid ); if( gpg_err_code (rc) == GPG_ERR_NO_PUBKEY ) { - log_info( _("key %08lX: no public key - " - "can't apply revocation certificate\n"), (ulong)keyid[1]); + log_error ( _("key %08lX: no public key - " + "can't apply revocation certificate\n"), (ulong)keyid[1]); rc = 0; goto leave; } @@ -1030,12 +1032,12 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) if( onode->pkt->pkttype == PKT_USER_ID ) break; else if( onode->pkt->pkttype == PKT_SIGNATURE - && onode->pkt->pkt.signature->sig_class == 0x20 - && keyid[0] == onode->pkt->pkt.signature->keyid[0] - && keyid[1] == onode->pkt->pkt.signature->keyid[1] ) { - rc = 0; - goto leave; /* yes, we already know about it */ - } + && !cmp_signatures(node->pkt->pkt.signature, + onode->pkt->pkt.signature)) + { + rc = 0; + goto leave; /* yes, we already know about it */ + } } @@ -1125,17 +1127,20 @@ chk_self_sigs( const char *fname, KBNODE keyblock, rc = check_key_signature( keyblock, n, NULL); if( rc ) { - char *p=utf8_to_native(unode->pkt->pkt.user_id->name, - strlen(unode->pkt->pkt.user_id->name),0); - log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? - _("key %08lX: unsupported public key " - "algorithm on user id \"%s\"\n"): - _("key %08lX: invalid self-signature " - "on user id \"%s\"\n"), - (ulong)keyid[1],p); - xfree (p); - } - else + if (opt.verbose) + { + char *p=utf8_to_native(unode->pkt->pkt.user_id->name, + strlen(unode->pkt->pkt.user_id->name),0); + log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? + _("key %08lX: unsupported public key " + "algorithm on user id \"%s\"\n"): + _("key %08lX: invalid self-signature " + "on user id \"%s\"\n"), + (ulong)keyid[1],p); + xfree (p); + } + } + else unode->flag |= 1; /* mark that signature checked */ } } @@ -1144,39 +1149,49 @@ chk_self_sigs( const char *fname, KBNODE keyblock, like the rest of gpg. If the standard gets revocation targets, this may need to be revised. */ - if( !knode ) { - log_info( _("key %08lX: no subkey for subkey " - "binding signature\n"),(ulong)keyid[1]); - n->flag |= 4; /* delete this */ - } - else { - rc = check_key_signature( keyblock, n, NULL); - if( rc ) { - log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? - _("key %08lX: unsupported public key algorithm\n"): + if( !knode ) + { + if (opt.verbose) + log_info( _("key %08lX: no subkey for subkey " + "binding signature\n"),(ulong)keyid[1]); + n->flag |= 4; /* delete this */ + } + else + { + rc = check_key_signature( keyblock, n, NULL); + if( rc ) + { + if (opt.verbose) + log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? + _("key %08lX: unsupported public key algorithm\n"): _("key %08lX: invalid subkey binding\n"), - (ulong)keyid[1]); - n->flag|=4; - } - else { - /* It's valid, so is it newer? */ - if(sig->timestamp>=bsdate) { - knode->flag |= 1; /* the subkey is valid */ - if(bsnode) { - bsnode->flag|=4; /* Delete the last binding - sig since this one is - newer */ - log_info(_("key %08lX: removed multiple subkey " - "binding\n"),(ulong)keyid[1]); - } - - bsnode=n; - bsdate=sig->timestamp; - } - else - n->flag|=4; /* older */ - } - } + (ulong)keyid[1]); + n->flag|=4; + } + else + { + /* It's valid, so is it newer? */ + if(sig->timestamp>=bsdate) + { + knode->flag |= 1; /* the subkey is valid */ + if(bsnode) + { + bsnode->flag|=4; /* Delete the last binding + sig since this one is + newer */ + if (opt.verbose) + log_info(_("key %08lX: removed multiple " + "subkey binding\n"), + (ulong)keyid[1]); + } + + bsnode=n; + bsdate=sig->timestamp; + } + else + n->flag|=4; /* older */ + } + } } else if( sig->sig_class == 0x28 ) { /* We don't actually mark the subkey as revoked right @@ -1186,14 +1201,16 @@ chk_self_sigs( const char *fname, KBNODE keyblock, See the comment in getkey.c:merge_selfsigs_subkey for more */ if( !knode ) { + if (opt.verbose) log_info( _("key %08lX: no subkey for subkey " "revocation signature\n"),(ulong)keyid[1]); - n->flag |= 4; /* delete this */ + n->flag |= 4; /* delete this */ } else { rc = check_key_signature( keyblock, n, NULL); if( rc ) { - log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? + if (opt.verbose) + log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? _("key %08lX: unsupported public key algorithm\n"): _("key %08lX: invalid subkey revocation\n"), (ulong)keyid[1]); @@ -1206,8 +1223,10 @@ chk_self_sigs( const char *fname, KBNODE keyblock, rsnode->flag|=4; /* Delete the last revocation sig since this one is newer */ - log_info(_("key %08lX: removed multiple subkey " - "revocation signatures\n"),(ulong)keyid[1]); + if (opt.verbose) + log_info(_("key %08lX: removed multiple subkey " + "revocation signatures\n"), + (ulong)keyid[1]); } rsnode=n; @@ -1291,23 +1310,25 @@ delete_inv_parts( const char *fname, KBNODE keyblock, !node->pkt->pkt.signature->flags.exportable && !(options&IMPORT_ALLOW_LOCAL_SIGS) && seckey_available( node->pkt->pkt.signature->keyid ) ) { - /* here we violate the rfc a bit by still allowing + /* Here we violate the rfc a bit by still allowing * to import non-exportable signature when we have the * the secret key used to create this signature - it - * seems that this makes sense */ + * seems that this makes sense. */ + if (opt.verbose) log_info( _("key %08lX: non exportable signature " "(class %02x) - skipped\n"), - (ulong)keyid[1], + (ulong)keyid[1], node->pkt->pkt.signature->sig_class ); - delete_kbnode( node ); + delete_kbnode( node ); } else if( node->pkt->pkttype == PKT_SIGNATURE && node->pkt->pkt.signature->sig_class == 0x20 ) { if( uid_seen ) { + if (opt.verbose) log_error( _("key %08lX: revocation certificate " - "at wrong place - skipped\n"), + "at wrong place - skipped\n"), (ulong)keyid[1]); - delete_kbnode( node ); + delete_kbnode( node ); } else { /* If the revocation cert is from a different key than @@ -1321,9 +1342,10 @@ delete_inv_parts( const char *fname, KBNODE keyblock, int rc = check_key_signature( keyblock, node, NULL); if( rc ) { - log_error( _("key %08lX: invalid revocation " - "certificate: %s - skipped\n"), - (ulong)keyid[1], gpg_strerror (rc)); + if (opt.verbose) + log_info ( _("key %08lX: invalid revocation " + "certificate: %s - skipped\n"), + (ulong)keyid[1], gpg_strerror (rc)); delete_kbnode( node ); } } @@ -1333,17 +1355,19 @@ delete_inv_parts( const char *fname, KBNODE keyblock, (node->pkt->pkt.signature->sig_class == 0x18 || node->pkt->pkt.signature->sig_class == 0x28) && !subkey_seen ) { - log_error( _("key %08lX: subkey signature " + if (opt.verbose) + log_info ( _("key %08lX: subkey signature " "in wrong place - skipped\n"), (ulong)keyid[1]); - delete_kbnode( node ); + delete_kbnode( node ); } else if( node->pkt->pkttype == PKT_SIGNATURE && !IS_CERT(node->pkt->pkt.signature)) { - log_error(_("key %08lX: unexpected signature class (0x%02X) -" - " skipped\n"),(ulong)keyid[1], - node->pkt->pkt.signature->sig_class); + if (opt.verbose) + log_info (_("key %08lX: unexpected signature class (0x%02X) -" + " skipped\n"),(ulong)keyid[1], + node->pkt->pkt.signature->sig_class); delete_kbnode(node); } else if( (node->flag & 4) ) /* marked for deletion */ @@ -1439,8 +1463,9 @@ collapse_uids( KBNODE *keyblock ) kid1 = keyid_from_sk( n->pkt->pkt.secret_key, NULL ); else kid1 = 0; - log_info(_("key %08lX: duplicated user ID detected - merged\n"), - (ulong)kid1); + if (!opt.quiet) + log_info (_("key %08lX: duplicated user ID detected - merged\n"), + (ulong)kid1); return 1; } @@ -1557,23 +1582,27 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock, break; else if( onode->pkt->pkttype == PKT_SIGNATURE && onode->pkt->pkt.signature->sig_class == 0x20 - && node->pkt->pkt.signature->keyid[0] - == onode->pkt->pkt.signature->keyid[0] - && node->pkt->pkt.signature->keyid[1] - == onode->pkt->pkt.signature->keyid[1] ) { - found = 1; - break; - } + && !cmp_signatures(onode->pkt->pkt.signature, + node->pkt->pkt.signature)) + { + found = 1; + break; + } } if( !found ) { - char *p=get_user_id_printable (keyid); KBNODE n2 = clone_kbnode(node); insert_kbnode( keyblock_orig, n2, 0 ); n2->flag |= 1; ++*n_sigs; - log_info(_("key %08lX: \"%s\" revocation certificate added\n"), - (ulong)keyid[1],p); - xfree (p); + + if (!opt.quiet) + { + char *p=get_user_id_printable (keyid); + log_info(_("key %08lX: \"%s\" " + "revocation certificate added\n"), + (ulong)keyid[1],p); + xfree (p); + } } } } @@ -1602,8 +1631,9 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock, insert_kbnode( keyblock_orig, n2, 0 ); n2->flag |= 1; ++*n_sigs; - log_info( _("key %08lX: direct key signature added\n"), - (ulong)keyid[1]); + if (!opt.quiet) + log_info( _("key %08lX: direct key signature added\n"), + (ulong)keyid[1]); } } } @@ -1771,20 +1801,12 @@ merge_sigs( KBNODE dst, KBNODE src, int *n_sigs, || n->pkt->pkt.signature->sig_class == 0x28 ) continue; /* skip signatures which are only valid on subkeys */ found = 0; - for(n2=dst->next; n2 && n2->pkt->pkttype != PKT_USER_ID; n2 = n2->next){ - if( n2->pkt->pkttype == PKT_SIGNATURE - && n->pkt->pkt.signature->keyid[0] - == n2->pkt->pkt.signature->keyid[0] - && n->pkt->pkt.signature->keyid[1] - == n2->pkt->pkt.signature->keyid[1] - && n->pkt->pkt.signature->timestamp - <= n2->pkt->pkt.signature->timestamp - && n->pkt->pkt.signature->sig_class - == n2->pkt->pkt.signature->sig_class ) { - found++; - break; - } - } + for(n2=dst->next; n2 && n2->pkt->pkttype != PKT_USER_ID; n2 = n2->next) + if(!cmp_signatures(n->pkt->pkt.signature,n2->pkt->pkt.signature)) + { + found++; + break; + } if( !found ) { /* This signature is new or newer, append N to DST. * We add a clone to the original keyblock, because this diff --git a/g10/keyedit.c b/g10/keyedit.c index 85f2b92e9..bd41772fd 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -56,6 +56,7 @@ static int menu_addrevoker( KBNODE pub_keyblock, static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ); static int menu_set_primary_uid( KBNODE pub_keyblock, KBNODE sec_keyblock ); static int menu_set_preferences( KBNODE pub_keyblock, KBNODE sec_keyblock ); +static int menu_set_keyserver_url (KBNODE pub_keyblock, KBNODE sec_keyblock ); static int menu_select_uid( KBNODE keyblock, int idx ); static int menu_select_key( KBNODE keyblock, int idx ); static int count_uids( KBNODE keyblock ); @@ -135,7 +136,7 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node, break; } if( sigrc != '?' || print_without_key ) { - tty_printf("%s%c%c %c%c%c%c%c%c %08lX %s ", + tty_printf("%s%c%c %c%c%c%c%c%c ", is_rev? "rev":"sig",sigrc, (sig->sig_class-0x10>0 && sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ', @@ -145,8 +146,15 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node, sig->flags.notation?'N':' ', sig->flags.expired?'X':' ', (sig->trust_depth>9)?'T': - (sig->trust_depth>0)?'0'+sig->trust_depth:' ', - (ulong)sig->keyid[1], datestr_from_sig(sig)); + (sig->trust_depth>0)?'0'+sig->trust_depth:' '); + if(opt.list_options&LIST_SHOW_LONG_KEYID) + tty_printf("%08lX%08lX",(ulong)sig->keyid[0],(ulong)sig->keyid[1]); + else + tty_printf("%08lX",(ulong)sig->keyid[1]); + tty_printf(" %s", datestr_from_sig(sig)); + if(opt.list_options&LIST_SHOW_SIG_EXPIRE) + tty_printf(" %s",expirestr_from_sig(sig)); + tty_printf(" "); if( sigrc == '%' ) tty_printf("[%s] ", gpg_strerror (rc) ); else if( sigrc == '?' ) @@ -168,6 +176,9 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node, if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATION)) show_notation(sig,3,0); + + if(sig->flags.pref_ks && (opt.list_options&LIST_SHOW_KEYSERVER)) + show_keyserver_url(sig,3,0); } return (sigrc == '!'); @@ -500,12 +511,47 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, tty_printf(_(" Unable to sign.\n")); } } - else if(!uidnode->pkt->pkt.user_id->created) + else if(uidnode->pkt->pkt.user_id->is_expired) { - tty_printf(_("WARNING: user ID \"%s\" is not " - "self-signed.\n"),user); - } + tty_printf(_("User ID \"%s\" is expired."),user); + if(opt.expert) + { + tty_printf("\n"); + /* No, so remove the mark and continue */ + if(!cpr_get_answer_is_yes("sign_uid.expire_okay", + _("Are you sure you " + "still want to sign " + "it? (y/N) "))) + uidnode->flag &= ~NODFLG_MARK_A; + } + else + { + uidnode->flag &= ~NODFLG_MARK_A; + tty_printf(_(" Unable to sign.\n")); + } + } + else if(!uidnode->pkt->pkt.user_id->created && !selfsig) + { + tty_printf(_("User ID \"%s\" is not self-signed."), + user); + + if(opt.expert) + { + tty_printf("\n"); + /* No, so remove the mark and continue */ + if(!cpr_get_answer_is_yes("sign_uid.nosig_okay", + _("Are you sure you " + "still want to sign " + "it? (y/N) "))) + uidnode->flag &= ~NODFLG_MARK_A; + } + else + { + uidnode->flag &= ~NODFLG_MARK_A; + tty_printf(_(" Unable to sign.\n")); + } + } xfree (user); } } @@ -739,7 +785,8 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, while(class==0) { - answer = cpr_get("sign_uid.class",_("Your selection? ")); + answer = cpr_get("sign_uid.class",_("Your selection? " + "(enter '?' for more information): ")); if(answer[0]=='\0') class=0x10+opt.def_cert_check_level; /* Default */ @@ -970,8 +1017,10 @@ change_passphrase( KBNODE keyblock ) " this is probably a *bad* idea!\n\n")); if( cpr_get_answer_is_yes("change_passwd.empty.okay", _("Do you really want to do this? "))) + { changed++; - break; + break; + } } else { /* okay */ rc = 0; @@ -1067,7 +1116,8 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY, cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, cmdUPDPREF, - cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST, cmdNOP }; + cmdPREFKS, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST, + cmdNOP }; static struct { const char *name; enum cmdids id; int need_sk; @@ -1108,10 +1158,14 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, { N_("toggle") , cmdTOGGLE , 1,0,0, N_("toggle between secret " "and public key listing") }, { N_("t" ) , cmdTOGGLE , 1,0,0, NULL }, - { N_("pref") , cmdPREF , 0,1,0, N_("list preferences (expert)") }, - { N_("showpref"), cmdSHOWPREF , 0,1,0, N_("list preferences (verbose)") }, + { N_("pref") , cmdPREF , 0,1,0, + N_("list preferences (expert)")}, + { N_("showpref"), cmdSHOWPREF , 0,1,0, + N_("list preferences (verbose)")}, { N_("setpref") , cmdSETPREF , 1,1,0, N_("set preference list") }, { N_("updpref") , cmdUPDPREF , 1,1,0, N_("updated preferences") }, + { N_("keyserver"),cmdPREFKS , 1,1,0, + N_("set preferred keyserver URL")}, { N_("passwd") , cmdPASSWD , 1,1,0, N_("change the passphrase") }, { N_("trust") , cmdTRUST , 0,1,0, N_("change the ownertrust") }, { N_("revsig") , cmdREVSIG , 0,1,0, N_("revoke signatures") }, @@ -1238,7 +1292,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, cmd = cmdLIST; else if( *answer == CONTROL_D ) cmd = cmdQUIT; - else if( isdigit( *answer ) ) { + else if( digitp( answer ) ) { cmd = cmdSELUID; arg_number = atoi(answer); } @@ -1565,6 +1619,14 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, } break; + case cmdPREFKS: + if( menu_set_keyserver_url ( keyblock, sec_keyblock ) ) { + merge_keys_and_selfsig( keyblock ); + modified = 1; + redisplay = 1; + } + break; + case cmdNOP: break; @@ -1950,6 +2012,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, int i, rc; int do_warn = 0; byte pk_version=0; + PKT_public_key *primary=NULL; if (opt.with_colons) { @@ -1979,7 +2042,8 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, do_warn = 1; } - pk_version=pk->version; + pk_version = pk->version; + primary = pk; } if(with_revoker) { @@ -2006,19 +2070,27 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, } } - tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"), - node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub", - (node->flag & NODFLG_SELKEY)? '*':' ', - nbits_from_pk( pk ), - pubkey_letter( pk->pubkey_algo ), - (ulong)keyid_from_pk(pk,NULL), - datestr_from_pk(pk), - expirestr_from_pk(pk) ); + keyid_from_pk(pk,NULL); + tty_printf("%s%c %4u%c/", + node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub", + (node->flag & NODFLG_SELKEY)? '*':' ', + nbits_from_pk( pk ), + pubkey_letter( pk->pubkey_algo )); + + if(opt.list_options&LIST_SHOW_LONG_KEYID) + tty_printf("%08lX",(ulong)pk->keyid[0]); + + tty_printf("%08lX ",(ulong)pk->keyid[1]); + tty_printf(_("created: %s expires: %s"), + datestr_from_pk(pk), + expirestr_from_pk(pk) ); tty_printf("\n"); if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { tty_printf(" "); + if(opt.list_options&LIST_SHOW_LONG_KEYID) + tty_printf(" "); tty_printf(_("trust: %-13s"), otrust); tty_printf(_("validity: %s"), trust ); tty_printf("\n"); @@ -2072,6 +2144,9 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, PKT_user_id *uid = node->pkt->pkt.user_id; ++i; if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){ + if(opt.list_options&LIST_SHOW_VALIDITY && primary) + tty_printf("[%8.8s] ", + trust_value_to_string(get_validity(primary,uid))); if( only_marked ) tty_printf(" "); else if( node->flag & NODFLG_SELUID ) @@ -2599,16 +2674,23 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) answer=cpr_get_utf8("keyedit.add_revoker", _("Enter the user ID of the designated revoker: ")); if(answer[0]=='\0' || answer[0]=='\004') - goto fail; - + { + xfree(answer); answer = NULL; + goto fail; + } + rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL,1); if(rc) { log_error (_("key `%s' not found: %s\n"),answer,gpg_strerror (rc)); + xfree (answer); answer = NULL; continue; } + xfree (answer); answer = NULL; + + fingerprint_from_pk(revoker_pk,revkey.fpr,&fprlen); if(fprlen!=20) { @@ -2788,7 +2870,8 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ) && ( mainkey || sub_pk ) ) { PKT_signature *sig = node->pkt->pkt.signature; if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] - && ( (mainkey && uid && (sig->sig_class&~3) == 0x10) + && ( (mainkey && uid + && uid->created && (sig->sig_class&~3) == 0x10) || (!mainkey && sig->sig_class == 0x18) ) ) { /* this is a selfsignature which is to be replaced */ PKT_signature *newsig; @@ -3084,6 +3167,101 @@ menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock ) } + +static int +menu_set_keyserver_url (KBNODE pub_keyblock, KBNODE sec_keyblock ) +{ + PKT_secret_key *sk; /* copy of the main sk */ + PKT_public_key *main_pk; + PKT_user_id *uid; + KBNODE node; + u32 keyid[2]; + int selected, select_all; + int modified = 0; + char *answer; + + no_primary_warning(pub_keyblock,1); + + answer=cpr_get_utf8("keyedit.add_keyserver", + _("Enter your preferred keyserver URL: ")); + if(answer[0]=='\0' || answer[0]=='\004') + { + xfree(answer); + return 0; + } + + select_all = !count_selected_uids (pub_keyblock); + + node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); + sk = copy_secret_key( NULL, node->pkt->pkt.secret_key); + + /* Now we can actually change the self signature(s) */ + main_pk = NULL; + uid = NULL; + selected = 0; + for ( node=pub_keyblock; node; node = node->next ) { + if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + break; /* ready */ + + if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) { + main_pk = node->pkt->pkt.public_key; + keyid_from_pk( main_pk, keyid ); + } + else if ( node->pkt->pkttype == PKT_USER_ID ) { + uid = node->pkt->pkt.user_id; + selected = select_all || (node->flag & NODFLG_SELUID); + } + else if ( main_pk && uid && selected + && node->pkt->pkttype == PKT_SIGNATURE ) { + PKT_signature *sig = node->pkt->pkt.signature; + if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] + && (uid && (sig->sig_class&~3) == 0x10) ) { + if( sig->version < 4 ) { + char *user=utf8_to_native(uid->name,strlen(uid->name),0); + + log_info(_("skipping v3 self-signature on user id \"%s\"\n"), + user); + xfree(user); + } + else { + /* This is a selfsignature which is to be replaced + * We have to ignore v3 signatures because they are + * not able to carry the preferences */ + PKT_signature *newsig; + PACKET *newpkt; + int rc; + + rc = update_keysig_packet (&newsig, sig, + main_pk, uid, NULL, + sk, + keygen_add_keyserver_url, + answer ); + if( rc ) { + log_error ("update_keysig_packet failed: %s\n", + gpg_strerror (rc)); + xfree(answer); + free_secret_key( sk ); + return 0; + } + /* replace the packet */ + newpkt = xcalloc (1, sizeof *newpkt ); + newpkt->pkttype = PKT_SIGNATURE; + newpkt->pkt.signature = newsig; + free_packet( node->pkt ); + xfree (node->pkt); + node->pkt = newpkt; + modified = 1; + } + } + } + } + + xfree(answer); + free_secret_key( sk ); + return modified; +} + + /**************** * Select one user id or remove all selection if index is 0. * Returns: True if the selection changed; diff --git a/g10/keygen.c b/g10/keygen.c index bc98cee17..38e9115b3 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -1,6 +1,6 @@ /* keygen.c - generate a key pair - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 - * Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -147,7 +147,12 @@ do_add_key_flags (PKT_signature *sig, unsigned int use) buf[0] = 0; if (use & PUBKEY_USAGE_SIG) - buf[0] |= 0x01 | 0x02; + { + if(sig->sig_class==0x18) + buf[0] |= 0x02; /* Don't set the certify flag for subkeys */ + else + buf[0] |= 0x01 | 0x02; + } if (use & PUBKEY_USAGE_ENC) buf[0] |= 0x04 | 0x08; if (use & PUBKEY_USAGE_AUTH) @@ -587,6 +592,18 @@ keygen_add_std_prefs( PKT_signature *sig, void *opaque ) return 0; } + +int +keygen_add_keyserver_url(PKT_signature *sig, void *opaque) +{ + const char *url=opaque; + + build_sig_subpkt(sig,SIGSUBPKT_PREF_KS,url,strlen(url)); + + return 0; +} + + int keygen_add_revkey(PKT_signature *sig, void *opaque) { @@ -1138,10 +1155,10 @@ gen_rsa(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, static int check_valid_days( const char *s ) { - if( !isdigit(*s) ) + if( !digitp(s) ) return 0; for( s++; *s; s++) - if( !isdigit(*s) ) + if( !digitp(s) ) break; if( !*s ) return 1; @@ -1219,15 +1236,18 @@ ask_algo (int addmode, unsigned int *r_usage) _("Create anyway? "))) { algo = PUBKEY_ALGO_ELGAMAL; + *r_usage = PUBKEY_USAGE_ENC | PUBKEY_USAGE_SIG; break; } } else if( algo == 3 && addmode ) { algo = PUBKEY_ALGO_ELGAMAL_E; + *r_usage = PUBKEY_USAGE_ENC; break; } else if( algo == 2 ) { algo = PUBKEY_ALGO_DSA; + *r_usage = PUBKEY_USAGE_SIG; break; } else @@ -1489,7 +1509,7 @@ ask_user_id( int mode ) if( strpbrk( aname, "<>" ) ) tty_printf(_("Invalid character in name\n")); - else if( isdigit(*aname) ) + else if( digitp(aname) ) tty_printf(_("Name may not start with a digit\n")); else if( strlen(aname) < 5 ) tty_printf(_("Name must be at least 5 characters long\n")); @@ -1503,7 +1523,7 @@ ask_user_id( int mode ) amail = cpr_get("keygen.email",_("Email address: ")); trim_spaces(amail); cpr_kill_prompt(); - if( !*amail ) + if( !*amail || opt.allow_freeform_uid ) break; /* no email address is okay */ else if( has_invalid_email_chars(amail) || count_chr(amail,'@') != 1 @@ -1551,7 +1571,8 @@ ask_user_id( int mode ) tty_printf(_("You selected this USER-ID:\n \"%s\"\n\n"), uid); /* fixme: add a warning if this user-id already exists */ - if( !*amail && (strchr( aname, '@' ) || strchr( acomment, '@'))) { + if( !*amail && !opt.allow_freeform_uid + && (strchr( aname, '@' ) || strchr( acomment, '@'))) { fail = 1; tty_printf(_("Please don't put the email address " "into the real name or the comment\n") ); @@ -1608,7 +1629,7 @@ ask_user_id( int mode ) } xfree (answer); if( !amail && !acomment && !amail ) - break; + break; xfree (uid); uid = NULL; } if( uid ) { @@ -1754,7 +1775,7 @@ get_parameter_algo( struct para_data_s *para, enum para_name key ) struct para_data_s *r = get_parameter( para, key ); if( !r ) return -1; - if( isdigit( *r->u.value ) ) + if( digitp( r->u.value ) ) i = atoi( r->u.value ); else i = openpgp_pk_map_name ( r->u.value ); @@ -2295,6 +2316,11 @@ generate_keypair( const char *fname ) strcpy( r->u.value, "1024" ); r->next = para; para = r; + r = xcalloc (1, sizeof *r + 20 ); + r->key = pKEYUSAGE; + strcpy( r->u.value, "sign" ); + r->next = para; + para = r; algo = PUBKEY_ALGO_ELGAMAL_E; r = xcalloc (1, sizeof *r + 20 ); @@ -2302,6 +2328,12 @@ generate_keypair( const char *fname ) sprintf( r->u.value, "%d", algo ); r->next = para; para = r; + r = xcalloc (1, sizeof *r + 20 ); + r->key = pSUBKEYUSAGE; + strcpy( r->u.value, "encrypt" ); + r->next = para; + r->next = para; + para = r; } else { diff --git a/g10/keylist.c b/g10/keylist.c index 081782785..f4344f204 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -1,6 +1,6 @@ -/* keylist.c - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 - * Free Software Foundation, Inc. +/* keylist.c - List all or selected keys + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -58,10 +58,46 @@ static FILE *attrib_fp=NULL; void public_key_list( STRLIST list ) { - if( !list ) - list_all(0); - else - list_one( list, 0 ); + if(opt.with_colons) + { + byte trust_model,marginals,completes,cert_depth; + ulong created,nextcheck; + + read_trust_options(&trust_model,&created,&nextcheck, + &marginals,&completes,&cert_depth); + + printf("tru:"); + + if(nextcheck && nextcheck <= make_timestamp()) + printf("o"); + if(trust_model!=opt.trust_model) + printf("t"); + if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC) + { + if(marginals!=opt.marginals_needed) + printf("m"); + if(completes!=opt.completes_needed) + printf("c"); + if(cert_depth!=opt.max_cert_depth) + printf("d"); + } + + printf(":%d:%lu:%lu",trust_model,created,nextcheck); + + /* Only show marginals, completes, and cert_depth in the classic + or PGP trust models since they are not meaningful + otherwise. */ + + if(trust_model==TM_PGP || trust_model==TM_CLASSIC) + printf(":%d:%d:%d",marginals,completes,cert_depth); + + printf("\n"); + } + + if( !list ) + list_all(0); + else + list_one( list, 0 ); } void @@ -152,7 +188,6 @@ show_policy_url(PKT_signature *sig,int indent,int mode) for(i=0;ihashed,SIGSUBPKT_PREF_KS,&len,&seq,&crit))) + { + if(mode!=2) + { + int i; + char *str; + + for(i=0;iflags.notation && (opt.list_options&LIST_SHOW_NOTATION)) show_notation(sig,3,0); + if(sig->flags.pref_ks && (opt.list_options&LIST_SHOW_KEYSERVER)) + show_keyserver_url(sig,3,0); + /* fixme: check or list other sigs here */ } } @@ -820,7 +900,7 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) pk = NULL; sk = node->pkt->pkt.secret_key; keyid_from_sk( sk, keyid ); - printf("sec:u:%u:%d:%08lX%08lX:%s:%s:::", + printf("sec::%u:%d:%08lX%08lX:%s:%s:::", nbits_from_sk( sk ), sk->pubkey_algo, (ulong)keyid[0],(ulong)keyid[1], @@ -886,13 +966,17 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) if( any ) { int i; char *str=uid->attrib_data?"uat":"uid"; - if ( uid->is_revoked ) + /* If we're listing a secret key, leave out the + validity values for now. FIXME: This should be + handled better in 1.9. */ + if ( sk ) + printf("%s:::::",str); + else if ( uid->is_revoked ) printf("%s:r::::",str); else if ( uid->is_expired ) printf("%s:e::::",str); - else if ( opt.no_expensive_trust_checks ) { + else if ( opt.no_expensive_trust_checks ) printf("%s:::::",str); - } else { int uid_validity; @@ -1010,8 +1094,10 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) } else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) { PKT_signature *sig = node->pkt->pkt.signature; - int sigrc; + int sigrc, fprokay=0; char *sigstr; + size_t fplen; + byte fparray[MAX_FINGERPRINT_LEN]; if( !any ) { /* no user id, (maybe a revocation follows)*/ if( sig->sig_class == 0x20 ) @@ -1045,8 +1131,14 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) continue; } if( opt.check_sigs ) { + PKT_public_key *signer_pk=NULL; + fflush(stdout); - rc = check_key_signature( keyblock, node, NULL ); + if(opt.no_sig_cache) + signer_pk = xcalloc (1, sizeof(PKT_public_key)); + + rc = check_key_signature2( keyblock, node, NULL, signer_pk, + NULL, NULL, NULL ); switch( gpg_err_code (rc) ) { case 0: sigrc = '!'; break; case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break; @@ -1054,6 +1146,16 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) case GPG_ERR_UNUSABLE_PUBKEY: sigrc = '?'; break; default: sigrc = '%'; break; } + + if(opt.no_sig_cache) + { + if(!rc) + { + fingerprint_from_pk (signer_pk, fparray, &fplen); + fprokay=1; + } + free_public_key(signer_pk); + } } else { rc = 0; @@ -1087,7 +1189,20 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) print_string( stdout, p, n, ':' ); xfree (p); } - printf(":%02x%c:\n", sig->sig_class,sig->flags.exportable?'x':'l'); + printf(":%02x%c:", sig->sig_class,sig->flags.exportable?'x':'l'); + if(opt.no_sig_cache && opt.check_sigs && fprokay) + { + size_t i; + + printf(":"); + + for (i=0; i < fplen ; i++ ) + printf ("%02X", fparray[i] ); + + printf(":"); + } + + printf("\n"); /* fixme: check or list other sigs here */ } } diff --git a/g10/keyring.c b/g10/keyring.c index 4639e9462..03a22667c 100644 --- a/g10/keyring.c +++ b/g10/keyring.c @@ -1382,6 +1382,13 @@ keyring_rebuild_cache (void *token) { if (node->pkt->pkttype == PKT_SIGNATURE) { + /* Note that this doesn't cache the result of a + revocation issued by a designated revoker. This is + because the pk in question does not carry the revkeys + as we haven't merged the key and selfsigs. It is + questionable whether this matters very much since + there are very very few designated revoker revocation + packets out there. */ check_key_signature (keyblock, node, NULL); sigcount++; } diff --git a/g10/keyserver.c b/g10/keyserver.c index e4f56ca3b..445c07620 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -170,7 +170,8 @@ parse_keyserver_uri(char *uri,const char *configname,unsigned int configlineno) opt.keyserver_scheme="hkp"; opt.keyserver_options.broken_http_proxy=1; } - else if(ascii_strcasecmp(opt.keyserver_scheme,"x-hkp")==0) + else if(ascii_strcasecmp(opt.keyserver_scheme,"x-hkp")==0 + || ascii_strcasecmp(opt.keyserver_scheme,"http")==0) { /* Canonicalize this to "hkp" so it works with both the internal and external keyserver interface. */ @@ -203,7 +204,7 @@ parse_keyserver_uri(char *uri,const char *configname,unsigned int configlineno) ch=opt.keyserver_port; while(*ch!='\0') { - if(!isdigit(*ch)) + if(!digitp(ch)) return GPG_ERR_BAD_URI; ch++; @@ -340,7 +341,7 @@ parse_keyrec(char *keystring) /* Remove trailing whitespace */ for(i=strlen(keystring);i>0;i--) - if(isspace(keystring[i-1])) + if(ascii_isspace(keystring[i-1])) keystring[i-1]='\0'; else break; @@ -978,7 +979,7 @@ keyserver_spawn(int action,STRLIST list, /* remove trailing whitespace */ plen=strlen(ptr); - while(plen>0 && isspace(ptr[plen-1])) + while(plen>0 && ascii_isspace(ptr[plen-1])) plen--; plen[ptr]='\0'; diff --git a/g10/main.h b/g10/main.h index 320a543de..76562fa91 100644 --- a/g10/main.h +++ b/g10/main.h @@ -151,7 +151,8 @@ int sign_symencrypt_file (const char *fname, STRLIST locusr); int check_revocation_keys (PKT_public_key *pk, PKT_signature *sig); int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ); int check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, - int *is_selfsig, u32 *r_expiredate, int *r_expired ); + PKT_public_key *ret_pk, int *is_selfsig, + u32 *r_expiredate, int *r_expired ); /*-- delkey.c --*/ int delete_keys( STRLIST names, int secret, int allow_both ); @@ -170,6 +171,7 @@ PKT_user_id *keygen_get_std_prefs (void); int keygen_add_key_expire( PKT_signature *sig, void *opaque ); int keygen_add_std_prefs( PKT_signature *sig, void *opaque ); int keygen_upd_std_prefs( PKT_signature *sig, void *opaque ); +int keygen_add_keyserver_url(PKT_signature *sig, void *opaque); int keygen_add_revkey(PKT_signature *sig, void *opaque); int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ); @@ -232,6 +234,7 @@ void reorder_keyblock (KBNODE keyblock); void list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque ); void print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode); void show_policy_url(PKT_signature *sig,int indent,int mode); +void show_keyserver_url(PKT_signature *sig,int indent,int mode); void show_notation(PKT_signature *sig,int indent,int mode); void dump_attribs(const PKT_user_id *uid, PKT_public_key *pk,PKT_secret_key *sk); diff --git a/g10/mainproc.c b/g10/mainproc.c index 3689525ef..40b9bd20a 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -668,15 +668,12 @@ proc_compressed( CTX c, PACKET *pkt ) * Returns: 0 = valid signature or an error code */ static int -do_check_sig( CTX c, KBNODE node, int *is_selfsig, int *is_expkey ) +do_check_sig( CTX c, KBNODE node, int *is_selfsig, + int *is_expkey, int *is_revkey ) { PKT_signature *sig; MD_HANDLE md = NULL, md2 = NULL; - int algo, rc, dum2; - u32 dummy; - - if(!is_expkey) - is_expkey=&dum2; + int algo, rc; assert( node->pkt->pkttype == PKT_SIGNATURE ); if( is_selfsig ) @@ -732,9 +729,9 @@ do_check_sig( CTX c, KBNODE node, int *is_selfsig, int *is_expkey ) } else return GPG_ERR_SIG_CLASS; - rc = signature_check2( sig, md, &dummy, is_expkey ); + rc = signature_check2( sig, md, NULL, is_expkey, is_revkey, NULL ); if( gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE && md2 ) - rc = signature_check2( sig, md2, &dummy, is_expkey ); + rc = signature_check2( sig, md2, NULL, is_expkey, is_revkey, NULL ); gcry_md_close (md); gcry_md_close (md2); @@ -958,7 +955,8 @@ list_node( CTX c, KBNODE node ) if( opt.check_sigs ) { fflush(stdout); switch( gpg_err_code (rc2=do_check_sig( c, node, - &is_selfsig, NULL )) ) { + &is_selfsig, + NULL, NULL )) ) { case 0: sigrc = '!'; break; case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break; case GPG_ERR_NO_PUBKEY: @@ -1217,7 +1215,7 @@ check_sig_and_print( CTX c, KBNODE node ) { PKT_signature *sig = node->pkt->pkt.signature; const char *astr, *tstr; - int rc, is_expkey=0; + int rc, is_expkey=0, is_revkey=0; if( opt.skip_verify ) { log_info(_("signature verification suppressed\n")); @@ -1281,19 +1279,51 @@ check_sig_and_print( CTX c, KBNODE node ) tstr = asctimestamp(sig->timestamp); astr = gcry_pk_algo_name (sig->pubkey_algo); - log_info(_("Signature made %.*s using %s key ID %08lX\n"), - (int)strlen(tstr), tstr, astr? astr: "?", (ulong)sig->keyid[1] ); + if(opt.verify_options&VERIFY_SHOW_LONG_KEYID) + { + log_info(_("Signature made %.*s\n"),(int)strlen(tstr), tstr); + log_info(_(" using %s key %08lX%08lX\n"), + astr? astr: "?",(ulong)sig->keyid[0],(ulong)sig->keyid[1] ); + } + else + log_info(_("Signature made %.*s using %s key ID %08lX\n"), + (int)strlen(tstr), tstr, astr? astr: "?", + (ulong)sig->keyid[1] ); - rc = do_check_sig(c, node, NULL, &is_expkey ); + rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); if( gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && opt.keyserver_scheme && opt.keyserver_options.auto_key_retrieve) { if( keyserver_import_keyid ( sig->keyid )==0 ) - rc = do_check_sig(c, node, NULL, &is_expkey ); + rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); } + + + /* If the key still isn't found, try to inform the user where it + can be found. */ + if(gpg_err_code (rc)==GPG_ERR_NO_PUBKEY && sig->flags.pref_ks) + { + const byte *p; + int seq=0; + size_t n; + + while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,&n,&seq,NULL))) + { + /* According to my favorite copy editor, in English + grammar, you say "at" if the key is located on a web + page, but "from" if it is located on a keyserver. I'm + not going to even try to make two strings here :) */ + log_info(_("Key available at: ") ); + print_string( log_get_stream(), p, n, 0 ); + putc( '\n', log_get_stream() ); + } + } + + if( !rc || gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE ) { KBNODE un, keyblock; int count=0, statno; char keyid_str[50]; + PKT_public_key *pk=NULL; if(rc) statno=STATUS_BADSIG; @@ -1301,6 +1331,8 @@ check_sig_and_print( CTX c, KBNODE node ) statno=STATUS_EXPSIG; else if(is_expkey) statno=STATUS_EXPKEYSIG; + else if(is_revkey) + statno=STATUS_REVKEYSIG; else statno=STATUS_GOODSIG; @@ -1311,6 +1343,13 @@ check_sig_and_print( CTX c, KBNODE node ) /* find and print the primary user ID */ for( un=keyblock; un; un = un->next ) { + int valid; + + if(un->pkt->pkttype==PKT_PUBLIC_KEY) + { + pk=un->pkt->pkt.public_key; + continue; + } if( un->pkt->pkttype != PKT_USER_ID ) continue; if ( !un->pkt->pkt.user_id->created ) @@ -1325,6 +1364,13 @@ check_sig_and_print( CTX c, KBNODE node ) if ( un->pkt->pkt.user_id->attrib_data ) continue; + assert(pk); + + /* Get it before we print anything to avoid interrupting + the output with the "please do a --check-trustdb" + line. */ + valid=get_validity(pk,un->pkt->pkt.user_id); + keyid_str[17] = 0; /* cut off the "[uncertain]" part */ write_status_text_and_buffer (statno, keyid_str, un->pkt->pkt.user_id->name, @@ -1336,7 +1382,11 @@ check_sig_and_print( CTX c, KBNODE node ) : _("Good signature from \"")); print_utf8_string( log_get_stream(), un->pkt->pkt.user_id->name, un->pkt->pkt.user_id->len ); - fputs("\"\n", log_get_stream() ); + if(opt.verify_options&VERIFY_SHOW_VALIDITY) + fprintf (log_get_stream(), + "\" [%s]\n",trust_value_to_string(valid)); + else + fputs("\"\n", log_get_stream() ); count++; } if( !count ) { /* just in case that we have no valid textual @@ -1380,10 +1430,7 @@ check_sig_and_print( CTX c, KBNODE node ) /* If we have a good signature and already printed * the primary user ID, print all the other user IDs */ if ( count && !rc ) { - PKT_public_key *pk=NULL; for( un=keyblock; un; un = un->next ) { - if(un->pkt->pkttype==PKT_PUBLIC_KEY) - pk=un->pkt->pkt.public_key; if( un->pkt->pkttype != PKT_USER_ID ) continue; if ( un->pkt->pkt.user_id->is_revoked ) @@ -1407,28 +1454,46 @@ check_sig_and_print( CTX c, KBNODE node ) log_info( _(" aka \"")); print_utf8_string( log_get_stream(), un->pkt->pkt.user_id->name, un->pkt->pkt.user_id->len ); - fputs("\"\n", log_get_stream() ); + if(opt.verify_options&VERIFY_SHOW_VALIDITY) + fprintf (log_get_stream(), "\" [%s]\n", + trust_value_to_string(get_validity(pk, + un->pkt-> + pkt.user_id))); + else + fputs("\"\n", log_get_stream() ); } } release_kbnode( keyblock ); if( !rc ) { - show_notation(sig,0,1); - show_policy_url(sig,0,1); - } + if(opt.verify_options&VERIFY_SHOW_POLICY) + show_policy_url(sig,0,1); + else + show_policy_url(sig,0,2); + + if(opt.verify_options&VERIFY_SHOW_KEYSERVER) + show_keyserver_url(sig,0,1); + else + show_keyserver_url(sig,0,2); + + if(opt.verify_options&VERIFY_SHOW_NOTATION) + show_notation(sig,0,1); + else + show_notation(sig,0,2); + } if( !rc && is_status_enabled() ) { /* print a status response with the fingerprint */ - PKT_public_key *pk = xcalloc (1, sizeof *pk ); + PKT_public_key *vpk = xcalloc (1, sizeof *vpk ); - if( !get_pubkey( pk, sig->keyid ) ) { + if( !get_pubkey( vpk, sig->keyid ) ) { byte array[MAX_FINGERPRINT_LEN], *p; char buf[MAX_FINGERPRINT_LEN*4+90], *bufp; size_t i, n; bufp = buf; - fingerprint_from_pk( pk, array, &n ); + fingerprint_from_pk( vpk, array, &n ); p = array; for(i=0; i < n ; i++, p++, bufp += 2) sprintf(bufp, "%02X", *p ); @@ -1442,27 +1507,27 @@ check_sig_and_print( CTX c, KBNODE node ) sig->version,sig->pubkey_algo,sig->digest_algo, sig->sig_class); bufp = bufp + strlen (bufp); - if (!pk->is_primary) { + if (!vpk->is_primary) { u32 akid[2]; - akid[0] = pk->main_keyid[0]; - akid[1] = pk->main_keyid[1]; - free_public_key (pk); - pk = xcalloc (1, sizeof *pk ); - if (get_pubkey (pk, akid)) { + akid[0] = vpk->main_keyid[0]; + akid[1] = vpk->main_keyid[1]; + free_public_key (vpk); + vpk = xcalloc (1, sizeof *vpk ); + if (get_pubkey (vpk, akid)) { /* impossible error, we simply return a zeroed out fpr */ n = MAX_FINGERPRINT_LEN < 20? MAX_FINGERPRINT_LEN : 20; memset (array, 0, n); } else - fingerprint_from_pk( pk, array, &n ); + fingerprint_from_pk( vpk, array, &n ); } p = array; for(i=0; i < n ; i++, p++, bufp += 2) sprintf(bufp, "%02X", *p ); write_status_text( STATUS_VALIDSIG, buf ); } - free_public_key( pk ); + free_public_key( vpk ); } if( !rc ) diff --git a/g10/misc.c b/g10/misc.c index 4abe75661..e122f0c5c 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -369,6 +369,8 @@ pct_expando(const char *string,struct expando_args *args) if(args->sk) keyid_from_sk(args->sk,sk_keyid); + /* This is used so that %k works in photoid command strings in + --list-secret-keys (which of course has a sk, but no pk). */ if(!args->pk && args->sk) keyid_from_sk(args->sk,pk_keyid); @@ -430,16 +432,37 @@ pct_expando(const char *string,struct expando_args *args) } break; - case 'f': /* fingerprint */ + case 'p': /* primary pk fingerprint of a sk */ + case 'f': /* pk fingerprint */ + case 'g': /* sk fingerprint */ { byte array[MAX_FINGERPRINT_LEN]; size_t len; int i; - if(args->pk) + if( ch[1]=='p' && args->sk) + { + if(args->sk->is_primary) + fingerprint_from_sk(args->sk,array,&len); + else if(args->sk->main_keyid[0] || args->sk->main_keyid[1]) + { + PKT_public_key *pk= xcalloc(1, sizeof(PKT_public_key)); + + if(get_pubkey_fast(pk,args->sk->main_keyid)==0) + fingerprint_from_pk(pk,array,&len); + else + memset(array,0,(len=MAX_FINGERPRINT_LEN)); + free_public_key(pk); + } + else + memset(array,0,(len=MAX_FINGERPRINT_LEN)); + } + else if( ch[1]=='f' && args->pk) fingerprint_from_pk(args->pk,array,&len); + else if( ch[1]=='g' && args->sk) + fingerprint_from_sk(args->sk,array,&len); else - memset(array,0, (len=MAX_FINGERPRINT_LEN)); + memset(array, 0, (len=MAX_FINGERPRINT_LEN)); if(idx+(len*2)unhashed = xmalloc (sizeof(*sig->unhashed) + n + 8 - 1 ); - sig->unhashed->size = n + 8; + sig->unhashed = xmalloc (sizeof(*sig->unhashed) + n - 1 ); + sig->unhashed->size = n; sig->unhashed->len = n; if( iobuf_read(inp, sig->unhashed->data, n ) != n ) { log_error("premature eof while reading " @@ -1259,17 +1280,19 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, } p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_CREATED, NULL ); - if( !p ) - log_error("signature packet without timestamp\n"); - else - sig->timestamp = buffer_to_u32(p); + if(p) + sig->timestamp = buffer_to_u32(p); + else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110)) + log_error("signature packet without timestamp\n"); + p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL ); - if( !p ) - log_error("signature packet without keyid\n"); - else { - sig->keyid[0] = buffer_to_u32(p); - sig->keyid[1] = buffer_to_u32(p+4); + if( p ) + { + sig->keyid[0] = buffer_to_u32(p); + sig->keyid[1] = buffer_to_u32(p+4); } + else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110)) + log_error("signature packet without keyid\n"); p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL); if(p) @@ -1281,6 +1304,10 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, if(p) sig->flags.policy_url=1; + p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,NULL); + if(p) + sig->flags.pref_ks=1; + p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,NULL); if(p) sig->flags.notation=1; diff --git a/g10/passphrase.c b/g10/passphrase.c index d00340109..ac7e71591 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -29,7 +29,7 @@ #include #include #endif -#if defined (__MINGW32__) || defined (__CYGWIN32__) +#if defined (_WIN32) || defined (__CYGWIN32__) # include #endif #include @@ -101,7 +101,7 @@ static char *fd_passwd = NULL; static char *next_pw = NULL; static char *last_pw = NULL; -#if defined (__MINGW32__) +#if defined (_WIN32) static int read_fd = 0; static int write_fd = 0; #endif @@ -191,7 +191,7 @@ read_passphrase_from_fd( int fd ) static int writen ( int fd, const void *buf, size_t nbytes ) { -#if defined (__MINGW32__) +#if defined (_WIN32) DWORD nwritten, nleft = nbytes; while (nleft > 0) { @@ -234,7 +234,7 @@ writen ( int fd, const void *buf, size_t nbytes ) static int readn ( int fd, void *buf, size_t buflen, size_t *ret_nread ) { -#if defined (__MINGW32__) +#if defined (_WIN32) DWORD nread, nleft = buflen; while (nleft > 0) { @@ -328,7 +328,7 @@ readline (int fd, char *buf, size_t buflen) #if !defined (__riscos__) -#if !defined (__MINGW32__) +#if !defined (_WIN32) /* For the new Assuan protocol we may have to send options */ static int agent_send_option (int fd, const char *name, const char *value) @@ -376,7 +376,11 @@ agent_send_all_options (int fd) } if (!opt.ttyname) - dft_ttyname = tty_get_ttyname (); + { + dft_ttyname = getenv ("GPG_TTY"); + if ((!dft_ttyname || !*dft_ttyname) && tty_get_ttyname ()) + dft_ttyname = tty_get_ttyname (); + } if (opt.ttyname || dft_ttyname) { if (agent_send_option (fd, "ttyname", @@ -433,7 +437,7 @@ agent_send_all_options (int fd) #endif return rc; } -#endif /*!__MINGW32__*/ +#endif /*!_WIN32*/ /* @@ -444,7 +448,7 @@ agent_send_all_options (int fd) static int agent_open (int *ret_prot) { -#if defined (__MINGW32__) +#if defined (_WIN32) int fd; char *infostr, *p; HANDLE h; @@ -589,7 +593,7 @@ agent_open (int *ret_prot) static void agent_close ( int fd ) { -#if defined (__MINGW32__) +#if defined (_WIN32) HANDLE h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent"); ResetEvent(h); #else diff --git a/g10/photoid.c b/g10/photoid.c index 1dd6edeca..00cc7a273 100644 --- a/g10/photoid.c +++ b/g10/photoid.c @@ -22,7 +22,7 @@ #include #include #include -#ifdef __MINGW32__ +#ifdef _WIN32 # include # ifndef VER_PLATFORM_WIN32_WINDOWS # define VER_PLATFORM_WIN32_WINDOWS 1 @@ -223,7 +223,7 @@ char *image_type_to_string(byte type,int style) #if !defined(FIXED_PHOTO_VIEWER) && !defined(DISABLE_PHOTO_VIEWER) static const char *get_default_photo_command(void) { -#if defined(__MINGW32__) +#if defined(_WIN32) OSVERSIONINFO osvi; memset(&osvi,0,sizeof(osvi)); diff --git a/g10/pkclist.c b/g10/pkclist.c index 5a4aa250f..71e6492e8 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -1164,10 +1164,6 @@ algo_available( preftype_t preftype, int algo, void *hint ) && algo != DIGEST_ALGO_SHA256)) return 0; - /* TIGER is not allowed any longer according to 2440bis. */ - if( RFC2440 && algo == DIGEST_ALGO_TIGER ) - return 0; - return algo && !gcry_md_test_algo( algo ); } else if( preftype == PREFTYPE_ZIP ) diff --git a/g10/revoke.c b/g10/revoke.c index cf1bfe17a..161bd2b82 100644 --- a/g10/revoke.c +++ b/g10/revoke.c @@ -608,7 +608,7 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint ) return NULL; /* cancel */ if( hint && !*answer ) n = hint; - else if(!isdigit( *answer ) ) + else if(!digitp( answer ) ) n = -1; else n = atoi(answer); diff --git a/g10/sig-check.c b/g10/sig-check.c index 4547c6e12..b0c89cba3 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -43,8 +43,9 @@ struct cmp_help_context_s { MD_HANDLE md; }; -static int do_check( PKT_public_key *pk, PKT_signature *sig, - MD_HANDLE digest, int *r_expired ); + +static int do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, + int *r_expired, int *r_revoked, PKT_public_key *ret_pk); /**************** * Check the signature which is contained in SIG. @@ -54,20 +55,16 @@ static int do_check( PKT_public_key *pk, PKT_signature *sig, int signature_check( PKT_signature *sig, MD_HANDLE digest ) { - u32 dummy; - int dum2; - return signature_check2( sig, digest, &dummy, &dum2 ); + return signature_check2( sig, digest, NULL, NULL, NULL, NULL ); } int -signature_check2( PKT_signature *sig, MD_HANDLE digest, - u32 *r_expiredate, int *r_expired ) +signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate, + int *r_expired, int *r_revoked, PKT_public_key *ret_pk ) { PKT_public_key *pk = xcalloc (1, sizeof *pk ); int rc=0; - *r_expiredate = 0; - /* Sanity check that the md has a context for the hash that the sig is expecting. This can happen if a onepass sig header does not match the actual sig, and also if the clearsign "Hash:" @@ -83,8 +80,9 @@ signature_check2( PKT_signature *sig, MD_HANDLE digest, rc=GPG_ERR_BAD_PUBKEY; /* you cannot have a good sig from an invalid subkey */ else { - *r_expiredate = pk->expiredate; - rc = do_check( pk, sig, digest, r_expired ); + if (r_expiredate) + *r_expiredate = pk->expiredate; + rc = do_check( pk, sig, digest, r_expired, r_revoked, ret_pk ); } free_public_key( pk ); @@ -135,11 +133,15 @@ signature_check2( PKT_signature *sig, MD_HANDLE digest, static int -do_check_messages( PKT_public_key *pk, PKT_signature *sig, int *r_expired ) +do_check_messages( PKT_public_key *pk, PKT_signature *sig, + int *r_expired, int *r_revoked ) { u32 cur_time; - *r_expired = 0; + if (r_expired) + *r_expired = 0; + if (r_revoked) + *r_revoked = 0; if( pk->version == 4 && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) { log_info(_("key %08lX: this is a PGP generated " "ElGamal key which is NOT secure for signatures!\n"), @@ -182,22 +184,26 @@ do_check_messages( PKT_public_key *pk, PKT_signature *sig, int *r_expired ) sprintf(buf,"%lu",(ulong)pk->expiredate); write_status_text(STATUS_KEYEXPIRED,buf); write_status(STATUS_SIGEXPIRED); - *r_expired = 1; + if (r_expired) + *r_expired = 1; } + if(pk->is_revoked && r_revoked) + *r_revoked=1; + return 0; } static int do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, - int *r_expired ) + int *r_expired, int *r_revoked, PKT_public_key *ret_pk ) { gcry_mpi_t result = NULL; int rc=0; struct cmp_help_context_s ctx; - if( (rc=do_check_messages(pk,sig,r_expired)) ) + if( (rc=do_check_messages(pk,sig,r_expired,r_revoked)) ) return rc; if( (rc=gcry_md_test_algo(sig->digest_algo)) ) return rc; @@ -280,6 +286,9 @@ do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, rc = gpg_error (GPG_ERR_BAD_SIGNATURE); } + if(!rc && ret_pk) + copy_public_key(ret_pk,pk); + return rc; } @@ -406,16 +415,19 @@ check_revocation_keys(PKT_public_key *pk,PKT_signature *sig) int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ) { - u32 dummy; - int dum2; - return check_key_signature2(root, node, NULL, is_selfsig, &dummy, &dum2 ); + return check_key_signature2(root, node, NULL, NULL, is_selfsig, NULL, NULL); } /* If check_pk is set, then use it to check the signature in node - rather than getting it from root or the keydb. */ + rather than getting it from root or the keydb. If ret_pk is set, + fill in the public key that was used to verify the signature. + ret_pk is only meaningful when the verification was successful. */ +/* TODO: add r_revoked here as well. It has the same problems as + r_expiredate and r_expired and the cache. */ int check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, - int *is_selfsig, u32 *r_expiredate, int *r_expired ) + PKT_public_key *ret_pk, int *is_selfsig, + u32 *r_expiredate, int *r_expired ) { MD_HANDLE md; PKT_public_key *pk; @@ -425,8 +437,10 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, if( is_selfsig ) *is_selfsig = 0; - *r_expiredate = 0; - *r_expired = 0; + if( r_expiredate ) + *r_expiredate = 0; + if( r_expired ) + *r_expired = 0; assert( node->pkt->pkttype == PKT_SIGNATURE ); assert( root->pkt->pkttype == PKT_PUBLIC_KEY ); @@ -444,7 +458,9 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) *is_selfsig = 1; } - if((rc=do_check_messages(pk,sig,r_expired))) + /* BUG: This is wrong for non-self-sigs. Needs to be the + actual pk */ + if((rc=do_check_messages(pk,sig,r_expired,NULL))) return rc; return sig->flags.valid? 0 : gpg_error (GPG_ERR_BAD_SIGNATURE); } @@ -464,7 +480,7 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, { gcry_md_open (&md, algo, 0 ); hash_public_key( md, pk ); - rc = do_check( pk, sig, md, r_expired ); + rc = do_check( pk, sig, md, r_expired, NULL, ret_pk ); cache_sig_result ( sig, rc ); gcry_md_close(md); } @@ -476,12 +492,12 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, gcry_md_open (&md, algo, 0 ); hash_public_key( md, pk ); hash_public_key( md, snode->pkt->pkt.public_key ); - rc = do_check( pk, sig, md, r_expired ); + rc = do_check( pk, sig, md, r_expired, NULL, ret_pk ); cache_sig_result ( sig, rc ); gcry_md_close(md); } else { - if (!opt.quiet) + if (opt.verbose) log_info (_("key %08lX: no subkey for subkey " "revocation signature\n"), (ulong)keyid_from_pk (pk, NULL)); @@ -502,7 +518,7 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, gcry_md_open (&md, algo, 0 ); hash_public_key( md, pk ); hash_public_key( md, snode->pkt->pkt.public_key ); - rc = do_check( pk, sig, md, r_expired ); + rc = do_check( pk, sig, md, r_expired, NULL, ret_pk ); cache_sig_result ( sig, rc ); gcry_md_close(md); } @@ -517,7 +533,7 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, else if( sig->sig_class == 0x1f ) { /* direct key signature */ gcry_md_open (&md, algo, 0 ); hash_public_key( md, pk ); - rc = do_check( pk, sig, md, r_expired ); + rc = do_check( pk, sig, md, r_expired, NULL, ret_pk ); cache_sig_result ( sig, rc ); gcry_md_close(md); } @@ -535,12 +551,13 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, { if( is_selfsig ) *is_selfsig = 1; - rc = do_check( pk, sig, md, r_expired ); + rc = do_check( pk, sig, md, r_expired, NULL, ret_pk ); } else if (check_pk) - rc=do_check(check_pk,sig,md,r_expired); + rc=do_check(check_pk,sig,md,r_expired, NULL, ret_pk); else - rc = signature_check2( sig, md, r_expiredate, r_expired ); + rc = signature_check2( sig, md, r_expiredate, r_expired, + NULL, ret_pk); cache_sig_result ( sig, rc ); gcry_md_close(md); diff --git a/g10/sign.c b/g10/sign.c index 493bfb4d9..640e36fe0 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -55,12 +55,12 @@ void __stdcall Sleep(ulong); static int recipient_digest_algo=0; /**************** - * Create a notation. It is assumed that the stings in STRLIST - * are already checked to contain only printable data and have a valid - * NAME=VALUE format. + * Create a notation. We assume thIt is assumed that the strings in + * the STRLISTs of the opt struct are already checked to contain only + * printable data and have a valid NAME=VALUE format. */ static void -mk_notation_and_policy( PKT_signature *sig, +mk_notation_policy_etc( PKT_signature *sig, PKT_public_key *pk, PKT_secret_key *sk ) { const char *string; @@ -74,18 +74,25 @@ mk_notation_and_policy( PKT_signature *sig, args.pk=pk; args.sk=sk; + /* It is actually impossible to get here when making a v3 key + signature since keyedit.c:sign_uids will automatically bump a + signature with a notation or policy url up to v4, but it is + good to do these checks anyway. */ + /* notation data */ if(IS_SIG(sig) && opt.sig_notation_data) { if(sig->version<4) - log_info("can't put notation data into v3 signatures\n"); + log_error(_("can't put notation data into v3 (PGP 2.x style) " + "signatures\n")); else nd=opt.sig_notation_data; } else if( IS_CERT(sig) && opt.cert_notation_data ) { if(sig->version<4) - log_info("can't put notation data into v3 key signatures\n"); + log_error(_("can't put notation data into v3 (PGP 2.x style) " + "key signatures\n")); else nd=opt.cert_notation_data; } @@ -125,21 +132,20 @@ mk_notation_and_policy( PKT_signature *sig, xfree (buf); } - if(opt.list_options&LIST_SHOW_NOTATION) - show_notation(sig,0,0); - /* set policy URL */ if( IS_SIG(sig) && opt.sig_policy_url ) { if(sig->version<4) - log_info("can't put a policy URL into v3 signatures\n"); + log_error(_("can't put a policy URL into v3 (PGP 2.x style) " + "signatures\n")); else pu=opt.sig_policy_url; } else if( IS_CERT(sig) && opt.cert_policy_url ) { if(sig->version<4) - log_info("can't put a policy URL into v3 key signatures\n"); + log_error(_("can't put a policy URL into v3 key (PGP 2.x style) " + "signatures\n")); else pu=opt.cert_policy_url; } @@ -163,8 +169,34 @@ mk_notation_and_policy( PKT_signature *sig, xfree (s); } - if(opt.list_options&LIST_SHOW_POLICY) - show_policy_url(sig,0,0); + /* preferred keyserver URL */ + if( IS_SIG(sig) && opt.sig_keyserver_url ) + { + if(sig->version<4) + log_info (_("can't put a preferred keyserver URL " + "into v3 signatures\n")); + else + pu=opt.sig_keyserver_url; + } + + for(;pu;pu=pu->next) + { + string = pu->d; + + s=pct_expando(string,&args); + if(!s) + { + log_error(_("WARNING: unable to %%-expand preferred keyserver URL" + " (too large). Using unexpanded.\n")); + s=xstrdup(string); + } + + build_sig_subpkt(sig,SIGSUBPKT_PREF_KS| + ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0), + s,strlen(s)); + + xfree(s); + } } @@ -621,7 +653,8 @@ write_signature_packets (SK_LIST sk_list, iobuf_t out, MD_HANDLE hash, sig = xcalloc (1,sizeof *sig); if(opt.force_v3_sigs || RFC1991) sig->version=3; - else if(duration || opt.sig_policy_url || opt.sig_notation_data) + else if(duration || opt.sig_policy_url + || opt.sig_notation_data || opt.sig_keyserver_url) sig->version=4; else sig->version=sk->version; @@ -640,7 +673,7 @@ write_signature_packets (SK_LIST sk_list, iobuf_t out, MD_HANDLE hash, if (sig->version >= 4) build_sig_subpkt_from_sig (sig); - mk_notation_and_policy (sig, NULL, sk); + mk_notation_policy_etc (sig, NULL, sk); hash_sigversion_to_magic (md, sig); gcry_md_final (md); @@ -1308,7 +1341,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, sig->sig_class = sigclass; if( sig->version >= 4 ) build_sig_subpkt_from_sig( sig ); - mk_notation_and_policy( sig, pk, sk ); + mk_notation_policy_etc ( sig, pk, sk ); /* Crucial that the call to mksubpkt comes LAST before the calls to finalize the sig as that makes it possible for the mksubpkt diff --git a/g10/signal.c b/g10/signal.c index 90c0841d8..9f50fbe3a 100644 --- a/g10/signal.c +++ b/g10/signal.c @@ -1,5 +1,5 @@ /* signal.c - signal handling - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -42,7 +42,7 @@ static void init_one_signal (int sig, RETSIGTYPE (*handler)(int), int check_ign ) { #ifndef HAVE_DOSISH_SYSTEM -#ifdef HAVE_SIGACTION +#if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION) struct sigaction oact, nact; if (check_ign) { @@ -132,7 +132,7 @@ void pause_on_sigusr( int which ) { #ifndef HAVE_DOSISH_SYSTEM -#ifdef HAVE_SIGPROCMASK +#if defined(HAVE_SIGPROCMASK) && defined(HAVE_SIGSET_T) sigset_t mask, oldmask; assert( which == 1 ); @@ -150,8 +150,8 @@ pause_on_sigusr( int which ) while (!caught_sigusr1) sigpause(SIGUSR1); caught_sigusr1 = 0; - sigrelse(SIGUSR1); ???? -#endif /*!HAVE_SIGPROCMASK*/ + sigrelse(SIGUSR1); +#endif /*!HAVE_SIGPROCMASK && HAVE_SISET_T*/ #endif } @@ -161,7 +161,7 @@ do_block( int block ) { #ifndef HAVE_DOSISH_SYSTEM static int is_blocked; -#ifdef HAVE_SIGPROCMASK +#if defined(HAVE_SIGPROCMASK) && defined(HAVE_SIGSET_T) static sigset_t oldmask; if( block ) { @@ -180,13 +180,22 @@ do_block( int block ) is_blocked = 0; } #else /*!HAVE_SIGPROCMASK*/ - static void (*disposition[MAXSIG])(); + +#if defined(NSIG) +# define SIGSMAX (NSIG) +#elif defined(MAXSIG) +# define SIGSMAX (MAXSIG+1) +#else +# error "define SIGSMAX to the number of signals on your platform plus one" +#endif + + static void (*disposition[SIGSMAX])(int); int sig; if( block ) { if( is_blocked ) log_bug("signals are already blocked\n"); - for (sig=1; sig < MAXSIG; sig++) { + for (sig=1; sig < SIGSMAX; sig++) { disposition[sig] = sigset (sig, SIG_HOLD); } is_blocked = 1; @@ -194,7 +203,7 @@ do_block( int block ) else { if( !is_blocked ) log_bug("signals are not blocked\n"); - for (sig=1; sig < MAXSIG; sig++) { + for (sig=1; sig < SIGSMAX; sig++) { sigset (sig, disposition[sig]); } is_blocked = 0; diff --git a/g10/status.c b/g10/status.c index 4414b33e9..aa55020be 100644 --- a/g10/status.c +++ b/g10/status.c @@ -129,6 +129,7 @@ get_status_string ( int no ) case STATUS_SIGEXPIRED : s = "SIGEXPIRED deprecated-use-keyexpired-instead"; break; case STATUS_EXPSIG : s = "EXPSIG"; break; case STATUS_EXPKEYSIG : s = "EXPKEYSIG"; break; + case STATUS_REVKEYSIG : s = "REVKEYSIG"; break; case STATUS_ATTRIBUTE : s = "ATTRIBUTE"; break; default: s = "?"; break; } diff --git a/g10/status.h b/g10/status.h index 4a0bcd45b..d8de81080 100644 --- a/g10/status.h +++ b/g10/status.h @@ -99,6 +99,7 @@ #define STATUS_ATTRIBUTE 67 #define STATUS_IMPORT_OK 68 #define STATUS_IMPORT_CHECK 69 +#define STATUS_REVKEYSIG 70 /*-- status.c --*/ void set_status_fd ( int fd ); diff --git a/g10/tdbdump.c b/g10/tdbdump.c index 3f9e8b388..5eb482959 100644 --- a/g10/tdbdump.c +++ b/g10/tdbdump.c @@ -154,7 +154,7 @@ import_ownertrust( const char *fname ) break; /* can't continue */ } for(p = line; *p && *p != ':' ; p++ ) - if( !isxdigit(*p) ) + if( !hexdigitp (p) ) break; if( *p != ':' ) { log_error (_("\b%s: error: missing colon\n"), fname ); diff --git a/g10/tdbio.c b/g10/tdbio.c index 39239be20..d1b5ed32a 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -337,6 +337,9 @@ tdbio_sync() } +#if 0 +/* The transaction code is disabled in the 1.2.x branch, as it is not + yet used. It will be enabled in 1.3.x. */ /**************** * Simple transactions system: @@ -408,6 +411,8 @@ tdbio_cancel_transaction() return 0; } +#endif /* transaction code */ + /******************************************************** diff --git a/g10/trustdb.c b/g10/trustdb.c index 16bd96e49..864334f4f 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -591,6 +591,31 @@ trustdb_pending_check(void) return pending_check_trustdb; } +void +read_trust_options(byte *trust_model,ulong *created,ulong *nextcheck, + byte *marginals,byte *completes,byte *cert_depth) +{ + TRUSTREC opts; + + init_trustdb(); + + read_record(0,&opts,RECTYPE_VER); + + if(trust_model) + *trust_model=opts.r.ver.trust_model; + if(created) + *created=opts.r.ver.created; + if(nextcheck) + *nextcheck=opts.r.ver.nextcheck; + if(marginals) + *marginals=opts.r.ver.marginals; + if(completes) + *completes=opts.r.ver.completes; + if(cert_depth) + *cert_depth=opts.r.ver.cert_depth; +} + + /*********************************************** *********** Ownertrust et al. **************** @@ -1573,10 +1598,14 @@ validate_one_keyblock (KBNODE kb, struct key_item *klist, signed (but not self-signed) uid does carry trust, of a sort, even if it is a statement being made by people other than the key owner "through" the uids on the key owner's key. I'm - going with the latter. -dshaw */ + going with the latter. However, if the user ID was + explicitly revoked, or passively allowed to expire, that + should stop validity through the user ID until it is + resigned. -dshaw */ - /* && node->pkt->pkt.user_id->created) */ - if (node->pkt->pkttype == PKT_USER_ID) + if (node->pkt->pkttype == PKT_USER_ID + && !node->pkt->pkt.user_id->is_revoked + && !node->pkt->pkt.user_id->is_expired) { if (uidnode && issigned) { @@ -1590,12 +1619,11 @@ validate_one_keyblock (KBNODE kb, struct key_item *klist, } uidnode = node; uid=uidnode->pkt->pkt.user_id; -#if 0 - /* If the selfsig is going to expire... This is disabled as - we do count un-self-signed uids in the web of trust. */ + + /* If the selfsig is going to expire... */ if(uid->expiredate && uid->expiredate<*next_expire) *next_expire = uid->expiredate; -#endif + issigned = 0; get_validity_counts(pk,uid); mark_usable_uid_certs (kb, uidnode, main_kid, klist, diff --git a/g10/trustdb.h b/g10/trustdb.h index 720385a06..414c37702 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -64,6 +64,9 @@ int enum_cert_paths( void **context, ulong *lid, void enum_cert_paths_print( void **context, FILE *fp, int refresh, ulong selected_lid ); +void read_trust_options(byte *trust_model,ulong *created,ulong *nextcheck, + byte *marginals,byte *completes,byte *cert_depth); + unsigned int get_ownertrust (PKT_public_key *pk); unsigned int get_min_ownertrust (PKT_public_key *pk); int get_ownertrust_info (PKT_public_key *pk); diff --git a/include/ChangeLog b/include/ChangeLog index 380d63b45..5b343f5a0 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,14 @@ +2003-09-04 David Shaw + + * cipher.h: Drop TIGER/192 support. + + * types.h: Prefer using uint64_t when creating a 64-bit unsigned + type. This avoids a warning on compilers that support but complain + about unsigned long long. + + * util.h: Make sure that only ascii is passed to isfoo + functions. (From Werner on stable branch). + 2003-09-04 Werner Koch * cipher.h (PUBKEY_USAGE_AUTH): Added. diff --git a/include/cipher.h b/include/cipher.h index 90cedb051..e7e36c6d5 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -53,7 +53,6 @@ #define DIGEST_ALGO_MD5 GCRY_MD_MD5 #define DIGEST_ALGO_SHA1 GCRY_MD_SHA1 #define DIGEST_ALGO_RMD160 GCRY_MD_RMD160 -#define DIGEST_ALGO_TIGER GCRY_MD_TIGER #define DIGEST_ALGO_SHA256 GCRY_MD_SHA256 #define DIGEST_ALGO_SHA384 GCRY_MD_SHA384 #define DIGEST_ALGO_SHA512 GCRY_MD_SHA512 diff --git a/include/types.h b/include/types.h index 838897aa5..dff512061 100644 --- a/include/types.h +++ b/include/types.h @@ -101,7 +101,11 @@ typedef unsigned long u32; */ #ifndef HAVE_U64_TYPEDEF #undef u64 /* maybe there is a macro with this name */ -#if SIZEOF_UNSIGNED_INT == 8 +#if SIZEOF_UINT64_T == 8 +typedef uint64_t u64; +#define U64_C(c) (UINT64_C(c)) +#define HAVE_U64_TYPEDEF +#elif SIZEOF_UNSIGNED_INT == 8 typedef unsigned int u64; #define U64_C(c) (c ## U) #define HAVE_U64_TYPEDEF @@ -113,10 +117,6 @@ typedef unsigned long u64; typedef unsigned long long u64; #define U64_C(c) (c ## ULL) #define HAVE_U64_TYPEDEF -#elif SIZEOF_UINT64_T == 8 -typedef uint64_t u64; -#define U64_C(c) (UINT64_C(c)) -#define HAVE_U64_TYPEDEF #endif #endif