Update head to match stable 1.0
authorDavid Shaw <dshaw@jabberwocky.com>
Sat, 29 Jun 2002 13:46:34 +0000 (13:46 +0000)
committerDavid Shaw <dshaw@jabberwocky.com>
Sat, 29 Jun 2002 13:46:34 +0000 (13:46 +0000)
155 files changed:
g10/ChangeLog
g10/Makefile.am
g10/armor.c
g10/build-packet.c
g10/cipher.c
g10/comment.c
g10/compress.c
g10/dearmor.c
g10/decrypt.c
g10/delkey.c
g10/encode.c
g10/encr-data.c
g10/exec.c [new file with mode: 0644]
g10/exec.h [new file with mode: 0644]
g10/export.c
g10/filter.h
g10/free-packet.c
g10/g10.c [moved from g10/gpg.c with 52% similarity]
g10/getkey.c
g10/global.h [moved from g10/basicdefs.h with 63% similarity]
g10/gpgd.c
g10/gpgv.c [new file with mode: 0644]
g10/helptext.c
g10/hkp.c
g10/hkp.h
g10/import.c
g10/kbnode.c
g10/kbx.h [deleted file]
g10/kbxblob.c [deleted file]
g10/kbxfile.c [deleted file]
g10/kbxio.c [deleted file]
g10/kbxutil.c [deleted file]
g10/keydb.c [new file with mode: 0644]
g10/keydb.h
g10/keyedit.c
g10/keygen.c
g10/keyid.c
g10/keylist.c
g10/keyring.c [new file with mode: 0644]
g10/keyring.h [new file with mode: 0644]
g10/keyserver-internal.h [new file with mode: 0644]
g10/keyserver.c [new file with mode: 0644]
g10/ks-proto.c
g10/ks-proto.h
g10/main.h
g10/mainproc.c
g10/mdfilter.c
g10/misc.c
g10/mkdtemp.c [new file with mode: 0644]
g10/openfile.c
g10/options.h
g10/options.skel
g10/packet.h
g10/parse-packet.c
g10/passphrase.c
g10/photoid.c [new file with mode: 0644]
g10/photoid.h [new file with mode: 0644]
g10/pipemode.c [new file with mode: 0644]
g10/pkclist.c
g10/plaintext.c
g10/pubkey-enc.c
g10/revoke.c
g10/ringedit.c [deleted file]
g10/seckey-cert.c
g10/seskey.c
g10/sig-check.c
g10/sign.c
g10/signal.c
g10/skclist.c
g10/status.c
g10/status.h
g10/tdbdump.c
g10/tdbio.c
g10/tdbio.h
g10/textfilter.c
g10/trustdb.c
g10/trustdb.h
g10/verify.c
po/ChangeLog
po/Makefile.in.in
po/POTFILES.in
po/cs.po [new file with mode: 0644]
po/da.po
po/de.glo
po/de.po
po/el.po [new file with mode: 0644]
po/eo.po
po/es.po [moved from po/es_ES.po with 53% similarity]
po/et.po [new file with mode: 0644]
po/fr.po
po/gl.po [new file with mode: 0644]
po/id.po
po/it.po
po/ja.po
po/nl.po
po/pl.po
po/pt.po [moved from po/pt_PT.po with 56% similarity]
po/pt_BR.po
po/ru.po [deleted file]
po/sv.po
po/tr.po [new file with mode: 0644]
scripts/ChangeLog
scripts/autogen.sh
scripts/build-riscos [new file with mode: 0644]
scripts/build-w32 [new file with mode: 0755]
scripts/conf-riscos/Makefile [new file with mode: 0644]
scripts/conf-riscos/cipher/construct.c [new file with mode: 0644]
scripts/conf-riscos/cipher/constructv.c [new file with mode: 0644]
scripts/conf-riscos/include/config.h [new file with mode: 0644]
scripts/conf-riscos/include/g10defs.h [new file with mode: 0644]
scripts/config.guess
scripts/config.sub
scripts/db2html.in [deleted file]
scripts/distfiles
scripts/gnupg.spec.in
scripts/gnupgbug [new file with mode: 0644]
scripts/install-sh
scripts/mail-to-translators [new file with mode: 0755]
scripts/missing
scripts/mk-w32-dist [new file with mode: 0755]
scripts/mkdiff
scripts/mkinstalldirs
scripts/mksnapshot
scripts/mkwebpage
tools/ChangeLog
tools/Makefile.am
tools/bftest.c
tools/clean-sat.c
tools/crlf.c
tools/gpgsplit.c [new file with mode: 0644]
tools/lspgpot
tools/mail-signed-keys
tools/mk-tdata.c
tools/mpicalc.c
tools/ring-a-party
tools/shmtest.c
util/ChangeLog
util/Makefile.am
util/README [deleted file]
util/argparse.c [new file with mode: 0644]
util/dotlock.c [new file with mode: 0644]
util/errors.c
util/fileutil.c
util/g10u.c [new file with mode: 0644]
util/http.c
util/iobuf.c
util/logger.c
util/memory.c [new file with mode: 0644]
util/miscutil.c
util/riscos.c [new file with mode: 0644]
util/secmem.c [new file with mode: 0644]
util/simple-gettext.c
util/strgutil.c
util/ttyio.c
util/w32reg.c

index 9c5acd8..21c44df 100644 (file)
-2000-11-13  Werner Koch  <wk@gnupg.org>
+2002-06-21  Stefan Bellon  <sbellon@sbellon.de>
+
+       * g10.c [__riscos__]: Moved RISC OS specific stuff to util/riscos.c
+       and include/util.h.
+
+       * gpgv.c [__riscos__]: Likewise.
+
+2002-06-20  David Shaw  <dshaw@jabberwocky.com>
+
+       * keydb.h, pkclist.c (select_algo_from_prefs): Allow passing a
+       suggested algorithm which will be used if available.
+
+       * encode.c (encode_crypt, encrypt_filter), sign.c (sign_file): Use
+       new select_algo_from_prefs feature to check if forcing an
+       algorithm would violate the recipient preferences.
+
+       * photoid.c (get_default_photo_command, show_photos): Use
+       different default viewers on different platforms.  Currently we
+       have Win 9x, Win NT (2k, xp), Mac OSX, RISC OS, and "everybody
+       else".  These are #ifdefs as much as possible to avoid clutter.
+
+       * g10.c (strusage, build_list), keyedit.c (show_prefs), main.h,
+       misc.c (compress_algo_to_string, check_compress_algo), pkclist.c
+       (algo_available), keygen.c (keygen_set_std_prefs): New
+       algo_to_string and check functions for compress algorithms.
+
+2002-06-20  Werner Koch  <wk@gnupg.org>
+
+       * misc.c (setsysinfo): Removed a #warning for Alpha's uniligedn
+       trap disabling - it is quite possible that this is a debug relict.
+
+2002-06-20  Stefan Bellon  <sbellon@sbellon.de>
+
+       * g10.c [__riscos__]: Added image file system feature.
+
+       * gpgv.c [__riscos__]: Added image file system feature.
+
+       * photoid.c (show_photos) [__riscos__]: Set RISC OS filetype of
+       photo id according to MIME type.
+
+2002-06-19  David Shaw  <dshaw@jabberwocky.com>
+
+       * hkp.c (parse_hkp_index): Don't leak memory when failing out of a
+       bad HKP keyserver.
+
+       * g10.c (add_notation_data): Relax slightly the rules as to what
+       can go into a notation name - 2440 allows "@", for example.
+
+2002-06-17  David Shaw  <dshaw@jabberwocky.com>
+
+       * import.c (clean_subkeys, import_one): Only allow at most 1
+       binding sig and at most 1 revocation sig on a subkey, as per
+       2440:11.1.
+
+       * hkp.c (parse_hkp_index, hkp_search): Error if the keyserver
+       returns an unparseable HKP response.
+
+2002-06-15  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyedit.c (show_key_with_all_names), keylist.c
+       (list_keyblock_print): Show "[expired]" before expired uids.
+
+       * keyedit.c (show_key_with_all_names_colon), mainproc.c
+       (list_node), keylist.c (list_keyblock_colon): Show flag 'e' for
+       expired user ids.  Use "uat" for user attribute packets instead of
+       "uid".  Also use '<count> <length>' rather than the fake user id
+       string on attributes.
+
+       * keygen.c (keygen_add_revkey): Remove unused code.
+
+       * misc.c (check_permissions): Check directory permissions
+       properly - they are not special files.
+
+       * pkclist.c (expand_id, expand_group, build_pk_list): When
+       expanding groups before building a pk list, inherit flags from the
+       original pre-expanded string.
+
+       * pubkey-enc.c (is_algo_in_prefs): Don't use prefs from expired
+       uids.
+
+2002-06-14  David Shaw  <dshaw@jabberwocky.com>
+
+       * free-packet.c (copy_signature): Properly copy a signature that
+       carries a revocation key on it.
+
+       * pkclist.c (expand_id, expand_group, build_pk_list): Groups now
+       work properly when used in the "Enter the user ID" prompt.
+
+2002-06-14  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyedit.c (show_key_with_all_names): Display warning if a user
+       tries to show prefs on a v3 key with a v3 selfsig.
+
+       * kbnode.c (dump_kbnode): Show if a uid is expired.
+
+       * import.c (merge_blocks, import_revoke_cert): Show user ID
+       receiving a revocation certificate.
+
+       * free-packet.c (cmp_user_ids): Properly compare attribute ids.
+
+       * pkclist.c (expand_groups): Maintain the strlist flags while
+       expanding.  Members of an expansion inherit their flags from the
+       expansion key.
+
+       * options.h, cipher.c (write_header), g10.c (main), keygen.c
+       (keygen_set_std_prefs): remove the personal_mdc flag.  It no
+       longer serves a purpose now that the personal preference lists are
+       split into cipher/digest/zip.
+
+2002-06-14  Timo Schulz  <ts@winpt.org>
+
+       * skclist.c (is_insecure): Implemented.
+       
+2002-06-12  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyserver.c (keyserver_spawn): Properly handle PROGRAM responses
+       when they have a CRLF ending.  Noted by Keith Ray.
+
+       * keyserver.c (keyserver_spawn): Handle CRLF endings from
+       keyserver helpers.  Also don't leak the last line worth of memory
+       from the keyserver response.
+
+       * main.h, misc.c (deprecated_warning): New function to warn about
+       deprecated options and commands.
+
+       * g10.c (main), keyserver-internal.h, keyserver.c
+       (parse_keyserver_uri): Use new deprecated function to warn about
+       honor-http-proxy, auto-key-retrieve, and x-broken-hkp.
+
+2002-06-11  David Shaw  <dshaw@jabberwocky.com>
+
+       * Makefile.am: link gpg with NETLIBS for the built-in HKP access.
+
+2002-06-10  David Shaw  <dshaw@jabberwocky.com>
+
+       * options.h, keyserver.c (keyserver_opts), g10.c (main): New
+       keyserver option "include-subkeys".  This feature already existed,
+       but now can be turned off.  It defaults to on.
+
+       * options.h, keyserver.c (parse_keyserver_options,
+       keyserver_spawn): There are now enough options to justify making a
+       structure for the keyserver options rather than a page of
+       if-then-else-if-then-etc.
+
+       * getkey.c (merge_keys_and_selfsig, merge_selfsigs_main): Fix bug
+       in calculating key expiration dates.
+
+2002-06-09  David Shaw  <dshaw@jabberwocky.com>
+
+       * keydb.h, getkey.c (get_user_id_native), import.c (import_one):
+       Display user ID while importing a key.  Note this applies to both
+       --import and keyserver --recv-keys.
+
+       * exec.c (exec_finish): Log unnatural exit (core dump, killed
+       manually, etc) for fork/exec/pipe child processes.
+
+2002-06-08  Timo Schulz  <ts@winpt.org>
+
+       * encode.c (encode_symmetric): Disable the compat flag
+       when the expert mode is enabled.
+       
+2002-06-07  David Shaw  <dshaw@jabberwocky.com>
+
+       * options.skel, options.h, main.h, keydb.h, pkclist.c
+       (build_pk_list, expand_groups), g10.c (main, add_group): Add new
+       "group" command to allow one name to expand into multiple keys.
+       For simplicity, and to avoid potential loops, we only expand once
+       - you can't make an alias that points to an alias.
+
+       * main.h, g10.c (main), keygen.c (build_personal_digest_list):
+       Simplify the default digest list - there is really no need for the
+       other hashes since they will never be used after SHA-1 in the
+       list.
+
+       * options.skel, options.h, g10.c (main), hkp.c (hkp_ask_import,
+       hkp_export, hkp_search), keyserver.c (parse_keyserver_options,
+       parse_keyserver_uri, keyserver_work, keyserver_refresh): Make the
+       "x-broken-hkp" keyserver scheme into keyserver-option
+       "broken-http-proxy".  Move honor_http_proxy into
+       keyserver_options.  Canonicalize the three variations of "hkp",
+       "x-hkp", and "x-broken-hkp" into "hkp".
+
+2002-06-07  Stefan Bellon  <sbellon@sbellon.de>
+
+       * g10.c [__riscos__]: Added --attribute-file to do the same as
+       --attribute-fd, but with a filename not a fd as argument.
+       Added magic symbol for RISC OS to use different memory management.
+
+       * gpgv.c [__riscos__]: Added magic symbol for RISC OS to use
+       different memory management.
+
+2002-06-06  David Shaw  <dshaw@jabberwocky.com>
+
+       * main.h, g10.c (main), keygen.c (build_personal_digest_list): Put
+       in a default digest preference list consisting of SHA-1, followed
+       by every other installed digest except MD5.  Note this is the same
+       as having no digest preference at all except for SHA-1 being
+       favored.
+
+       * options.h, g10.c (main), keygen.c (keygen_set_std_prefs),
+       pkclist.c (select_algo_from_prefs): Split
+       --personal-preference-list into three:
+       --personal-{cipher|digest|compress}-preferences.  This allows a
+       user to set one without affecting another (i.e. setting only a
+       digest pref doesn't imply an empty cipher pref).
+
+       * exec.c (exec_read): This is a safer way of guessing the return
+       value of system().  Noted by Stefan Bellon.
+
+2002-06-05  David Shaw  <dshaw@jabberwocky.com>
+
+       * hkp.c (parse_hkp_index): Be more robust with keyservers
+       returning very unparseable responses.
+
+       * exec.c (exec_read): Catch and display an error when the remote
+       process exits unnaturally (i.e. segfault) so the user knows what
+       happened.  Also fix exec_write stub which has a different number
+       of arguments now.
+
+2002-06-05  Timo Schulz  <ts@winpt.org>
+
+       * encode.c (encode_simple): Ignore the new mode for RFC1991.
+       * mainproc.c (symkey_decrypt_sesskey): Better check for weird
+       keysizes.
+       
+2002-06-05  Timo Schulz  <ts@winpt.org>
+
+       * encode.c (encode_sesskey): New.
+       (encode_simple): Use it here. But by default we use the compat
+       mode which supress to generate encrypted session keys.
+       
+2002-06-05  Timo Schulz  <ts@winpt.org>
+
+       * mainproc.c (symkey_decrypt_sesskey): New.
+       (proc_symkey_enc): Support for encrypted session keys.
+       
+2002-06-04  David Shaw  <dshaw@jabberwocky.com>
+
+       * sign.c (hash_for, sign_file): When encrypting and signing at the
+       same time, consult the various hash prefs to pick a hash algorithm
+       to use.  Pass in a 160-bit hint if any of the signing keys are
+       DSA.
+
+       * keydb.h, pkclist.c (select_algo_from_prefs, algo_available):
+       Pass a "hints" opaque pointer in to let the caller give hints as
+       to what algorithms would be acceptable.  The only current hint is
+       for PREFTYPE_HASH to require a 160-bit hash for DSA.  Change all
+       callers in encode.c (encode_crypt, encrypt_filter) and sign.c
+       (sign_file).  If we settle on MD5 as the best algorithm based
+       solely on recepient keys and SHA1 is also a possibility, use SHA1
+       unless the user intentionally chose MD5.  This is as per 2440:13.
+
+       * exec.c (make_tempdir): Fix duplicated filename problem.
+
+2002-06-03  David Shaw  <dshaw@jabberwocky.com>
+
+       * packet.h, parse-packet.c (enum_sig_subpkt): Report back from
+       enum_sig_subpkt when a subpacket is critical and change all
+       callers in keylist.c (show_policy_url, show_notation), mainproc.c
+       (print_notation_data), and pkclist.c (do_show_revocation_reason).
+
+       * keylist.c (show_policy_url, show_notation): Display if the
+       policy or notation is critical.
+       
+2002-06-03  David Shaw  <dshaw@jabberwocky.com>
+
+       * main.h, g10.c (main), keylist.c (dump_attribs, set_attrib_fd,
+       list_keyblock_print, list_keyblock_colon), status.h, status.c
+       (get_status_string): New --attribute-fd feature to dump the
+       contents of attribute subpackets for frontends.  If --status-fd is
+       also used, then a new status tag ATTRIBUTE is provided for each
+       subpacket.
+
+       * packet.h, getkey.c (fixup_uidnode, merge_selfsigs_main,
+       merge_selfsigs_subkey), parse-packet.c (setup_user_id): Keep track
+       of the expiration time of a user ID, and while we're at it, use
+       the expired flag from the selfsig rather than reparsing the
+       SIG_EXPIRE subpacket.
+
+       * photoid.c (generate_photo_id): When adding a new photo ID,
+       showing the photo for confirmation is not safe when noninteractive
+       since the "user" may not be able to dismiss a viewer window.
+       Noted by Timo Schulz.
+       
+2002-06-03  David Shaw  <dshaw@jabberwocky.com>
+
+       * options.skel: Sample photo viewers for Win32.
+
+       * misc.c (pct_expando): Use the seckey for %k/%K if the pubkey is
+       not available.
+
+       * photoid.h, photoid.c (show_photos): Include the seckey in case a
+       user tries to view a photo on a secret key, and change all callers
+       in keyedit.c (menu_showphoto), keylist.c (list_keyblock_print),
+       and photoid.c (generate_photo_id).
+
+2002-06-02  David Shaw  <dshaw@jabberwocky.com>
+
+       * photoid.c (show_photos): Work properly when not called with a
+       public key.
+
+2002-05-31  David Shaw  <dshaw@jabberwocky.com>
+
+       * sign.c (mk_notation_and_policy): Free unneeded buffer.
+
+       * hkp.c (parse_hkp_index): Properly handle the '&' character
+       (i.e. "&amp;") in HKP responses.
+
+       * getkey.c (merge_selfsigs_main): Fix reversed expiration time
+       check with self-sigs.
+
+       * keyedit.c (sign_uids): When making a new self-sig on a v3 key,
+       make a v3 self-sig unless it is currently a v3 self-sig being
+       promoted to v4.
+
+2002-05-31  Timo Schulz  <ts@winpt.org>
+
+       * pkclist.c (do_show_revocation_reason): Don't use capital
+       letters for non-interactive output.
+       (show_revocation_reason): Now it is global.
+       * pubkey-enc.c (get_it): Show if the key has been revoked.
+       
+2002-05-30  David Shaw  <dshaw@jabberwocky.com>
+
+       * sign.c (write_signature_packets, sign_file, clearsign_file,
+       sign_symencrypt_file): Make a v4 signature if a policy URL or
+       notation is set, unless v3 sigs are forced via rfc1991 or
+       force-v3-sigs.  Also remove some doubled code and clarify an error
+       message (we don't sign in PGP2 mode - just detach-sign).
+
+       * parse-packet.c (parse_one_sig_subpkt): Add KS_FLAGS to the "any
+       size" section.
+
+2002-05-29  David Shaw  <dshaw@jabberwocky.com>
+
+       * keygen.c (keygen_set_std_prefs, add_feature_mdc): Use "mdc" and
+       "no-mdc" in the prefs string to allow switching on and off the MDC
+       feature.  This is needed to properly export a key from GnuPG for
+       use on PGP which does not support MDC - without this, MDC-capable
+       implementations will still try and generate MDCs which will break
+       PGP.
+
+       * keygen.c (keygen_get_std_prefs): Show "[mdc]" in prefs string if
+       it is enabled.
+
+       * options.h, g10.c (main), cipher.c (write_header), keygen.c
+       (keygen_set_std_prefs): For consistency, allow the user to specify
+       mdc/no-mdc in the --personal-preference-list.  If disabled, it
+       acts just like --disable-mdc.
+
+2002-05-29  David Shaw  <dshaw@jabberwocky.com>
+
+       * options.h, exec.c: Add some debugging info, using the 1024 debug
+       flag.
+
+       * exec.c (win_system): New system()-like function for win32 that
+       does not return until the child process terminates.  Of course,
+       this doesn't help if the process itself exits before it is
+       finished.
+
+2002-05-29  Werner Koch  <wk@gnupg.org>
+
+       * encode.c (encode_simple): Intialize PKT when --no-literal is used.
+
+       * keyedit.c (show_key_with_all_names_colon): Renamed the record
+       for revocation keys to "rvk".
+
+2002-05-27  Werner Koch  <wk@gnupg.org>
+
+       * keyedit.c (show_key_with_all_names_colon): New.
+       (show_key_with_all_names): Divert to new function when required.
+       Sanitize printing of revoker name.
+
+2002-05-27  David Shaw  <dshaw@jabberwocky.com>
+
+       * build-packet.c (build_sig_subpkt): Handle setting sig flags for
+       certain subpacket types (notation, policy url, exportable,
+       revocable).  keyedit.c (sign_mk_attrib): Flags no longer need to
+       be set here.
+
+       * packet.h, parse-packet.c (parse_one_sig_subpkt), build-packet.c
+       (build_sig_subpkt): Call parse_one_sig_subpkt to sanity check
+       buffer lengths before building a sig subpacket.
+
+2002-05-26  David Shaw  <dshaw@jabberwocky.com>
+
+       * sign.c (mk_notation_and_policy): Include secret key to enable %s
+       expandos, and pass notations through pct_expando as well.
+
+       * main.h, misc.c (pct_expando): Add %s and %S expandos for
+       signer's keyid.
+
+2002-05-25  David Shaw  <dshaw@jabberwocky.com>
+
+       * g10.c (strusage, build_list): Add compress algorithms to
+       --version list.  Show algorithm numbers when --verbose --version
+       is done.
+
+2002-05-22  David Shaw  <dshaw@jabberwocky.com>
+
+       * options.h, main.h, keygen.c (keygen_set_set_prefs,
+       keygen_get_std_prefs, keygen_upd_std_prefs), keyedit.c
+       (keyedit_menu), g10.c (main), pkclist.c (select_algo_from_prefs):
+       Add --personal-preference-list which allows the user to factor in
+       their own preferred algorithms when the preference lists are
+       consulted.  Obviously, this does not let the user violate a
+       recepient's preferences (and the RFC) - this only influences the
+       ranking of the agreed-on (and available) algorithms from the
+       recepients.  Suggested by David Hollenberg.
+
+       * options.h, keygen.c (keygen_set_std_prefs), g10.c (main): Rename
+       --preference-list to --default-preference-list (as that is what it
+       really is), and make it a true default in that if the user selects
+       "default" they get this list and not the compiled-in list.
+
+2002-05-22  Werner Koch  <wk@gnupg.org>
+
+       * g10.c (main): Add missing LF in a info printout and made it
+       translatable.  Noted by Michael Tokarev.
+
+2002-05-21  Werner Koch  <wk@gnupg.org>
+
+       * g10.c (main): Removed the undef of USE_SHM_COPROCESSING which
+       was erroneously introduced on 2002-01-09.
+
+       * signal.c (got_fatal_signal): Don't write the Nul to stderr.
+       Reported by David Hollenberg.
+
+2002-05-18  David Shaw  <dshaw@jabberwocky.com>
+
+       * main.h, g10.c (main), revoke.c (gen_desig_revoke): Generate a
+       designated revocation via --desig-revoke
+
+       * keyedit.c (keyedit_menu, menu_addrevoker): New "addrevoker"
+       command to add a designated revoker to a key.
+
+2002-05-17  David Shaw  <dshaw@jabberwocky.com>
+
+       * gpgv.c: Add stub for get_ownertrust().
+
+       * g10.c (main): --allow-freeform-uid should be implied by
+       OpenPGP.  Add --no-allow-freeform-uid.
+
+       * keyedit.c (sign_uids): Issue a warning when signing a
+       non-selfsigned uid.
+
+       * getkey.c (merge_selfsigs_main): If a key has no selfsigs, and
+       allow-non-selfsigned-uid is not set, still try and make the key
+       valid by checking all uids for a signature from an ultimately
+       trusted key.
+
+2002-05-16  David Shaw  <dshaw@jabberwocky.com>
+
+       * main.h, keygen.c (keygen_add_revkey): Add revocation key
+       subpackets to a signature (callable by
+       make_keysig_packet). (write_direct_sig): Write a 1F direct key
+       signature. (parse_revocation_key): Parse a string in
+       algo:fpr:sensitive format into a revocation
+       key. (get_parameter_revkey, do_generate_keypair): Call above
+       functions when prompted from a batch key generation file.
+
+       * build-packet.c (build_sig_subpkt): Allow multiple revocation key
+       subpackets in a single sig.
+
+       * keydb.h, getkey.c (get_seckey_byfprint): Same as
+       get_pubkey_byfprint, except for secret keys.  We only know the
+       fingerprint of a revocation key, so this is needed to retrieve the
+       secret key needed to issue a revokation.
+
+       * packet.h, parse-packet.c (parse_signature, parse_revkeys): Split
+       revkey parsing off into a new function that can be used to reparse
+       after manipulating the revkey list.
+
+       * sign.c (make_keysig_packet): Ability to make 1F direct key
+       signatures.
+
+2002-05-15  David Shaw  <dshaw@jabberwocky.com>
+
+       * options.skel: keyserver.pgp.com is gone, so list pgp.surfnet.nl
+       as a sample LDAP server instead.
+
+       * getkey.c (merge_selfsigs_main): Properly handle multiple
+       revocation keys in a single packet.  Properly handle revocation
+       keys that are in out-of-order packets.  Remove duplicates in
+       revocation key list.
+
+2002-05-14  Timo Schulz   <ts@winpt.org>
+
+       * exec.c (make_tempdir) [MINGW32]: Added missing '\'.
+       
+2002-05-14  Stefan Bellon  <sbellon@sbellon.de>
+
+       * exec.c (make_tempdir): Make use of EXTSEP_S instead of hardcoded
+       dot as extension separator.
+
+2002-05-13  David Shaw  <dshaw@jabberwocky.com>
+
+       * photoid.c (show_photos): Use the long keyid as the filename for
+       the photo.  Use the short keyid as the filename on 8.3 systems.
+
+       * exec.h, exec.c (make_tempdir, exec_write, exec_finish): Allow
+       caller to specify filename.  This should make things easier on
+       windows and macs where the file extension is required, but a whole
+       filename is even better.
+
+       * keyedit.c (show_key_with_all_names, show_prefs): Show proper
+       prefs for a v4 key uid with no selfsig at all.
+
+       * misc.c (check_permissions): Don't check permissions on
+       non-normal files (pipes, character devices, etc.)
+
+2002-05-11  Werner Koch  <wk@gnupg.org>
+
+       * mainproc.c (proc_symkey_enc): Avoid segv in case the parser
+       encountered an invalid packet.
+
+       * keyserver.c (keyserver_export): Get confirmation before sending
+       all keys.
+
+2002-05-10  Stefan Bellon  <sbellon@sbellon.de>
+
+       * g10.c, hkp.c, keyedit.c, keyserver.c: Replaced all occurrances
+       of strcasecmp with ascii_strcasecmp and all occurrances of
+       strncasecmp with ascii_memcasecmp.
+
+2002-05-10  David Shaw  <dshaw@jabberwocky.com>
+
+       * packet.h, getkey.c (fixup_uidnode), keyedit.c (show_prefs): Show
+       assumed prefs for hash and compression as well as the cipher pref.
+       Show assumed prefs if there are no prefs at all on a v4
+       self-signed key.
+
+       * options.h, g10.c (main), sign.c (make_keysig_packet): New
+       --cert-digest-algo function to override the default key signing
+       hash algorithm.
+
+2002-05-09  David Shaw  <dshaw@jabberwocky.com>
+
+       * getkey.c (merge_selfsigs_main): Make sure the revocation key
+       list starts clean as this function may be called more than once
+       (e.g. from functions in --edit).
+
+       * g10.c, encode.c (encode_crypt), sign.c (sign_file,
+       sign_symencrypt_file): Make --compress-algo work like the
+       documentation says.  It should be like --cipher-algo and
+       --digest-algo in that it can override the preferences calculation
+       and impose the setting the user wants.  No --compress-algo setting
+       allows the usual preferences calculation to take place.
+
+       * main.h, compress.c (compress_filter): use new
+       DEFAULT_COMPRESS_ALGO define, and add a sanity check for compress
+       algo value.
+
+2002-05-08  David Shaw  <dshaw@jabberwocky.com>
+
+       * pkclist.c (select_algo_from_prefs): There is an assumed
+       compression preference for uncompressed data.
+
+2002-05-07  David Shaw  <dshaw@jabberwocky.com>
+
+       * options.h, g10.c (main), getkey.c (finish_lookup), pkclist.c
+       (algo_available): --pgp7, identical to --pgp6 except that it
+       permits a few algorithms that PGP 7 added: AES128, AES192, AES256,
+       and TWOFISH.  Any more of these --pgpX flags, and it'll be time to
+       start looking at a generic --emulate-pgp X option.
+
+       * export.c (do_export_stream): Warn the user when exporting a
+       secret key if it or any of its secret subkeys are protected with
+       SHA1 while simple_sk_checksum is set.
+
+       * parse-packet.c (parse_key): Show when the SHA1 protection is
+       used in --list-packets.
+
+       * options.h, build-packet.c (do_comment), g10.c (main): Rename
+       --no-comment as --sk-comments/--no-sk-comments (--no-comment still
+       works) and make the default be --no-sk-comments.
+
+2002-05-07  Werner Koch  <wk@gnupg.org>
+
+       * keygen.c (get_parameter_algo): Never allow generation of the
+       deprecated RSA-E or RSA-S flavors of PGP RSA.
+       (ask_algo): Allow generation of RSA sign and encrypt in expert
+       mode.  Don't allow ElGamal S+E unless in expert mode.
+       * helptext.c: Added entry keygen.algo.rsa_se.
+
+2002-05-07  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyedit.c (sign_uids): If --expert is set, allow re-signing a
+       uid to promote a v3 self-sig to a v4 one.  This essentially
+       deletes the old v3 self-sig and replaces it with a v4 one.
+
+       * packet.h, parse-packet.c (parse_key), getkey.c
+       (merge_keys_and_selfsig, merge_selfsigs_main): a v3 key with a v4
+       self-sig must never let the v4 self-sig express a key expiration
+       time that extends beyond the original v3 expiration time.
+
+2002-05-06  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyedit.c (sign_uids): When making a self-signature via "sign"
+       don't ask about sig level or expiration, and include the usual
+       preferences and such for v4 self-sigs.  (menu_set_preferences):
+       Convert uids from UTF8 to native before printing.
+
+       * keyedit.c (sign_uids): Convert uids from UTF8 to native before
+       printing.  (menu_set_primary_uid): Show error if the user tries to
+       make a uid with a v3 self-sig primary.
+
+2002-05-05  David Shaw  <dshaw@jabberwocky.com>
+
+       * import.c (import_one): When merging with a key we already have,
+       don't let a key conflict (same keyid but different key) stop the
+       import: just skip the bad key and continue.
+
+       * exec.c (make_tempdir): Under Win32, don't try environment
+       variables for temp directories - GetTempDir tries environment
+       variables internally, and it's better not to second-guess it in
+       case MS adds some sort of temp dir handling to Windows at some
+       point.
+
+2002-05-05  Timo Schulz  <ts@winpt.org>
+
+        * mainproc.c (proc_symkey_enc): Don't ask for a passphrase
+        in the list only mode.
+       
+2002-05-05  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyserver.c (keyserver_refresh): --refresh-keys implies
+       --merge-only so as not to import keys with keyids that match the
+       ones being refreshed.  Noted by Florian Weimer.
+
+2002-05-04  Stefan Bellon  <sbellon@sbellon.de>
+
+       * free-packet.c (copy_public_key): Don't call m_alloc(0), therefore
+       added consistency check for revkey and numrefkeys.
+
+       * getkey.c (check_revocation_keys): Added consistency check for
+       revkey and numrefkeys.
+
+       * keyedit.c (show_key_with_all_names): Likewise.
+
+2002-05-03  David Shaw  <dshaw@jabberwocky.com>
+
+       * photoid.c: Provide default image viewer for Win32.
+
+       * misc.c (pct_expando): %t means extension, not name ("jpg", not
+       "jpeg").
+
+       * keyserver.c (keyserver_spawn), photoid.c (show_photos), exec.h,
+       exec.c: Allow the caller to determine the temp file extension when
+       starting an exec_write and change all callers.
+
+       * keyedit.c (sign_uids): Nonrevocable key signatures cause an
+       automatic promotion to v4.
+
+       * exec.c: Provide stubs for exec_ functions when NO_EXEC is
+       defined.
+
+2002-05-02  David Shaw  <dshaw@jabberwocky.com>
+
+       * photoid.h, photoid.c (parse_image_header, image_type_to_string):
+       Useful functions to return data about an image.
+
+       * packet.h, parse-packet.c (make_attribute_uidname,
+       parse_attribute_subpkts, parse_attribute), photoid.h, photoid.c
+       (show_photos): Handle multiple images in a single attribute
+       packet.
+
+       * main.h, misc.c (pct_expando), sign.c (mk_notation_and_policy),
+       photoid.c (show_photos): Simpler expando code that does not
+       require using compile-time string sizes.  Call
+       image_type_to_string to get image strings (i.e. "jpg",
+       "image/jpeg").  Change all callers.
+
+       * keyedit.c (menu_showphoto), keylist.c (list_keyblock_print):
+       Allow viewing multiple images within a single attribute packet.
+
+       * gpgv.c: Various stubs for link happiness.
+
+2002-05-02  David Shaw  <dshaw@jabberwocky.com>
+
+       * build-packet.c (build_sig_subpkt), keyedit.c (sign_uids),
+       options.h, sign.c (mk_notation_and_policy), g10.c (main,
+       add_notation_data, add_policy_url (new), check_policy_url
+       (removed)): Allow multiple policy URLs on a given signature.
+       Split "--notation-data" into "--cert-notation" and
+       "--sig-notation" so the user can set different policies for key
+       and data signing.  For backwards compatibility, "--notation-data"
+       sets both, as before.
+
+2002-05-02  Werner Koch  <wk@gnupg.org>
+
+       * options.skel: Removed the comment on trusted-keys because this
+       option is now deprecated.
+
+2002-05-01  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyedit.c (menu_adduid): 2440bis04 says that multiple attribute
+       packets on a given key are legal.
+
+       * keyserver.c (keyserver_refresh): the fake v3 keyid hack applies
+       to "mailto" URLs as well since they are also served by pksd.
+
+2002-04-29  Werner Koch  <wk@gnupg.org>
+
+       Added a copyright year for files changed this year.
+
+2002-04-25  Werner Koch  <wk@gnupg.org>
+
+       * g10.c, options.h: New options --display, --ttyname, --ttytype,
+       --lc-ctype, --lc-messages to be used with future versions of the
+       gpg-agent. 
+       * passphrase.c (agent_send_option,agent_send_all_options): New.
+       (agent_open): Send options to the agent.
+
+       * trustdb.c (update_ownertrust, clear_ownertrust): Do an explicit
+       do_sync because revalidation_mark does it only if when the
+       timestamp actually changes.
+
+2002-04-23  David Shaw  <dshaw@jabberwocky.com>
+
+       * main.h, keygen.c (do_generate_keypair), keylist.c
+       (print_signature_stats, list_all, list_one, list_keyblock,
+       list_keyblock_print, list_keyblock_colon): After generating a new
+       key, show the key information (name, keyid, fingerprint, etc.)
+       Also do not print uncheckable signatures (missing key..) in
+       --check-sigs.  Print statistics (N missing keys, etc.) after
+       --check-sigs.
+
+       * keyedit.c (sign_uids): When signing a key with an expiration
+       date on it, the "Do you want your signature to expire at the same
+       time?" question should default to YES.
+
+2002-04-22  David Shaw  <dshaw@jabberwocky.com>
+
+       * parse-packet.c (parse_plaintext), packet.h, plaintext.c
+       (handle_plaintext): Fix bug in handling literal packets with
+       zero-length data (no data was being confused with partial body
+       length).
+
+       * misc.c (pct_expando), options.skel: %t means extension ("jpg").
+       %T means MIME type ("image/jpeg").
+
+       * import.c (import_one): Only trigger trust update if the keyring
+       is actually changed.
+
+       * export.c (do_export_stream): Missing a m_free.
+
+2002-04-22  Stefan Bellon  <sbellon@sbellon.de>
+
+       * keyid.c (expirestr_from_sk, expirestr_from_sig): Added _() to
+       string constant.
+
+       * exec.c (make_tempdir) [__riscos__]: Better placement of
+       temporary file.
+
+2002-04-20  David Shaw  <dshaw@jabberwocky.com>
+
+       * keygen.c (generate_subkeypair): 2440bis04 adds that creating
+       subkeys on v3 keys is a MUST NOT.
+
+       * getkey.c (finish_lookup): The --pgp6 "use the primary key"
+       behavior should only apply while data signing and not encryption.
+       Noted by Roger Sondermann.
+
+2002-04-19  Werner Koch  <wk@gnupg.org>
+
+       * keygen.c (keygen_set_std_prefs): Put back 3DES because the RFC
+       says it is good form to do so.
+
+2002-04-19  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyedit.c (menu_deluid): Only cause a trust update if we delete
+       a non-revoked user id.
+
+       * hkp.c (hkp_ask_import), keyserver.c (parse_keyserver_options,
+       keyserver_spawn), options.h: Remove fast-import keyserver option
+       (no longer meaningful).
+
+       * g10.c (main), keyedit.c (sign_uids), options.h: Change
+       --default-check-level to --default-cert-check-level as it makes
+       clear what it operates on.
+
+       * g10.c (main): --pgp6 also implies --no-ask-sig-expire.
+
+       * delkey.c (do_delete_key): Comment.
+
+       * keyedit.c (sign_uids, keyedit_menu, menu_deluid, menu_delsig,
+       menu_expire, menu_revsig, menu_revkey): Only force a trustdb check
+       if we did something that changes it.
+
+       * g10.c: add "--auto-check-trustdb" to override a
+       "--no-auto-check-trustdb"
+
+2002-04-19  Werner Koch  <wk@gnupg.org>
+
+       * tdbio.c (tdbio_write_nextcheck): Return a status whether the
+       stamp was actually changed.
+       * trustdb.c (revalidation_mark): Sync the changes.  Removed the
+       sync operation done by its callers.
+       (get_validity): Add logic for maintaining a pending_check flag.
+       (clear_ownertrust): New.
+       
+       * keyedit.c (sign_uids): Don't call revalidation_mark depending on
+       primary_pk.
+       (keyedit_menu): Call revalidation_mark after "trust".
+       (show_key_with_all_names): Print a warning on the wrong listed key
+       validity.
+
+       * delkey.c (do_delete_key): Clear the owenertrust information when
+       deleting a public key.
+       
+2002-04-18  Werner Koch  <wk@gnupg.org>
+
+       * seskey.c (encode_md_value): Print an error message if a wrong
+       digest algorithm is used with DSA.  Changed all callers to cope
+       with a NULL return.  Problem noted by Imad R. Faiad.
+
+2002-04-18  David Shaw  <dshaw@jabberwocky.com>
+
+       * trustdb.c (mark_usable_uid_certs): Properly handle nonrevocable
+       signatures that can expire.  In short, the only thing that can
+       override an unexpired nonrevocable signature is another unexpired
+       nonrevocable signature.
+
+       * getkey.c (finish_lookup): Always use primary signing key for
+       signatures when --pgp6 is on since pgp6 and 7 do not understand
+       signatures made by signing subkeys.
+
+2002-04-18  Werner Koch  <wk@gnupg.org>
+
+       * trustdb.c (validate_keys): Never schedule a nextcheck into the
+       past.
+       (validate_key_list): New arg curtime use it to set next_expire.
+       (validate_one_keyblock): Take the current time from the caller.
+       (clear_validity, reset_unconnected_keys): New.
+       (validate_keys): Reset all unconnected keys.
+
+       * getkey.c (premerge_public_with_secret): Fixed 0x12345678! syntax
+       for use with secret keys.
+       (lookup): Advance the searchmode after a search FIRST.
+
+       * seckey-cert.c (do_check): Always calculate the old checksum for
+       use after unprotection.
+
+       * g10.c, options.skel: New option --no-escape-from.  Made
+       --escape-from and --force-v3-sigs the default and removed them
+       from the options skeleton.
+
+2002-04-16  Werner Koch  <wk@gnupg.org>
+
+       * parse-packet.c (parse_key): Support a SHA1 checksum as per
+       draft-rfc2440-bis04.
+       * packet.h (PKT_secret_key): Add field sha1chk.
+       * seckey-cert.c (do_check): Check the SHA1 checksum
+       (protect_secret_key): And create it.
+       * build-packet.c (do_secret_key): Mark it as sha-1 protected.
+       * g10.c, options.h: New option --simple-sk-checksum.
+
+2002-04-13  David Shaw  <dshaw@jabberwocky.com>
+
+       * parse-packet.c (parse_signature): Minor fix - signatures should
+       expire at their expiration time and not one second later.
+
+       * keygen.c (proc_parameter_file): Allow specifying preferences
+       string (i.e. "s5 s2 z1 z2", etc) in a batchmode key generation
+       file.
+
+       * keyedit.c (keyedit_menu): Print standard error message when
+       signing a revoked key (no new translation).
+
+       * getkey.c (merge_selfsigs): Get the default set of key prefs from
+       the real (not attribute) primary uid.
+
+2002-04-12  David Shaw  <dshaw@jabberwocky.com>
+
+       * pkclist.c (build_pk_list): Fix bug that allowed a key to be
+       selected twice in batch mode if one instance was the default
+       recipient and the other was an encrypt-to.  Noted by Stefan
+       Bellon.
+
+       * parse-packet.c (dump_sig_subpkt): Show data in trust and regexp
+       sig subpackets.
+
+       * keyedit.c (keyedit_menu): Use new function real_uids_left to
+       prevent deleting the last real (i.e. non-attribute) uid.  Again,
+       according to the attribute draft. (menu_showphoto): Make another
+       string translatable.
+
+2002-04-11  David Shaw  <dshaw@jabberwocky.com>
+
+       * build-packet.c (build_sig_subpkt): Delete subpackets from both
+       hashed and unhashed area on update.  (find_subpkt): No longer
+       needed.
+
+       * keyedit.c (sign_uids): With --pgp2 on, refuse to sign a v3 key
+       with a v4 signature.  As usual, --expert overrides.  Try to tweak
+       some strings to a closer match so they can all be translated in
+       one place.  Use different helptext keys to allow different help
+       text for different questions.
+
+       * keygen.c (keygen_upd_std_prefs): Remove preferences from both
+       hashed and unhashed areas if they are not going to be used.
+
+2002-04-10  David Shaw  <dshaw@jabberwocky.com>
+
+       * misc.c (pct_expando), options.skel: Use %t to indicate type of a
+       photo ID (in this version, it's always "jpeg").  Also tweak string
+       expansion loop to minimize reallocs.
+
+       * mainproc.c (do_check_sig): Variable type fix.
+
+       * keyedit.c (menu_set_primary_uid): Differentiate between true
+       user IDs and attribute user IDs when making one of them primary.
+       That is, if we are making a user ID primary, we alter user IDs.
+       If we are making an attribute packet primary, we alter attribute
+       packets.  This matches the language in the latest attribute packet
+       draft.
+
+       * keyedit.c (sign_uids): No need for the empty string hack.
+
+       * getkey.c (fixup_uidnode): Only accept preferences from the
+       hashed segment of the self-sig.
+
+2002-04-10  Werner Koch  <wk@gnupg.org>
+
+       * tdbio.c (migrate_from_v2): Fixed the offset to read the old
+       ownertrust value and only add entries to the table if we really
+       have a value.
+
+2002-04-08  David Shaw  <dshaw@jabberwocky.com>
+
+       * status.h, status.c (get_status_string): Add KEYEXPIRED, EXPSIG,
+       and EXPKEYSIG.  Add "deprecated-use-keyexpired-instead" to
+       SIGEXPIRED.
+
+       * sig-check.c (do_check): Start transition from SIGEXPIRED to
+       KEYEXPIRED, since the actual event is signature verification by an
+       expired key and not an expired signature. (do_signature_check,
+       packet.h): Rename as signature_check2, make public, and change all
+       callers.
+
+       * mainproc.c (check_sig_and_print, do_check_sig): Use status
+       EXPSIG for an expired, but good, signature.  Add the expiration
+       time (or 0) to the VALIDSIG status line.  Use status KEYEXPSIG for
+       a good signature from an expired key.
+
+       * g10.c (main): remove checks for no arguments now that argparse
+       does it.
+
+2002-04-06  Werner Koch  <wk@gnupg.org>
+
+       * keyring.c (keyring_get_keyblock): Disable the keylist mode here.
+
+       * encode.c (encode_simple, encode_crypt): Only test on compressed
+       files if a compress level was not explicity set.
+
+       * keygen.c (keygen_set_std_prefs): Removed Blowfish and Twofish
+       from the list of default preferences, swapped the preferences of
+       RMD160 and SHA1.  Don't include a preference to 3DES unless the
+       IDEA kludge gets used.
+
+       * free-packet.c (free_packet): call free_encrypted also for
+       PKT_ENCRYPTED_MDC.
+
+       * compress.c (release_context): New.
+       (handle_compressed): Allocate the context and setup a closure to
+       release the context.  This is required because there is no
+       guarabntee that the filter gets popped from the chain at the end
+       of the function.  Problem noted by Timo and probably also the
+       cause for a couple of other reports.
+       (compress_filter): Use the release function if set.
+
+       * tdbio.c [__CYGWIN32__]: Don't rename ftruncate.  Noted by
+       Disastry.
+
+       * parse-packet.c (parse_signature): Put parens around a bit test.
+
+       * exec.c (make_tempdir): Double backslash for TMP directory
+       creation under Windows.  Better strlen the DIRSEP_S constants for
+       allocation measurements.
+
+       * decrypt.c (decrypt_messages): Release the passphrase aquired
+       by get_last_passphrase.
+
+2002-04-02  Werner Koch  <wk@gnupg.org>
+
+       * Makefile.am (EXTRA_DIST): Removed OPTIONS an pubring.asc - they
+       are no longer of any use. 
+
+2002-04-03  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyserver.c (parse_keyserver_options): fix auto-key-retrieve to
+       actually work as a keyserver-option (noted by Roger Sondermann).
+
+       * keylist.c (reorder_keyblock): do not reorder the primary
+       attribute packet - the first user ID must be a genuine one.
+
+2002-03-31  David Shaw  <dshaw@jabberwocky.com>
+
+       * keylist.c (list_keyblock_colon): Fix ownertrust display with
+       --with-colons.
+
+       * keygen.c (generate_user_id), photoid.c (generate_photo_id):
+       Properly initialize the user ID refcount.  A few more "y/n" ->
+       "y/N" in photoid.c.
+
+       * keyedit.c (ask_revoke_sig): Warn the user if they are about to
+       revoke an expired sig (not a problem, but they should know).  Also
+       tweak a few prompts to change "y/n" to "y/N", which is how most
+       other prompts are written.
+
+       * keyserver.c (keyserver_search_prompt): Control-d escapes the
+       keyserver search prompt.
+
+       * pkclist.c (show_revocation_reason & callers): If a subkey is
+       considered revoked solely because the parent key is revoked, print
+       the revocation reason from the parent key.
+
+       * trustdb.c (get_validity): Allow revocation/expiration to apply
+       to a uid/key with no entry in the trustdb.
+
+2002-03-29  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyserver.c (printunquoted): unquote backslashes from keyserver
+       searches
+
+       * hkp.c (write_quoted): quote backslashes from keyserver searches
+
+2002-03-26  Werner Koch  <wk@gnupg.org>
+
+       * keygen.c (ask_keysize): Removed the warning for key sizes > 1536.
+
+2002-03-25  Werner Koch  <wk@gnupg.org>
+
+       * keyedit.c (sign_uids): Use 2 strings and not a %s so that
+       translations can be done the right way.
+       * helptext.c: Fixed small typo.
+
+2002-03-23  David Shaw  <dshaw@jabberwocky.com>
+
+       * import.c (append_uid, merge_sigs): it is okay to import
+       completely non-signed uids now (with --allow-non-selfsigned-uid).
+
+       * getkey.c (get_primary_uid, merge_selfsigs_main): do not choose
+       an attribute packet (i.e. photo) as primary uid.  This prevents
+       oddities like "Good signature from [image of size 2671]".  This is
+       still not perfect (one can still select an attribute packet as
+       primary in --edit), but is closer to the way the draft is going.
+
+       * g10.c (build_list): algorithms should include 110.
+
+       * g10.c (main): --pgp2 implies --no-ask-sig-expire and
+       --no-ask-cert-expire as those would cause a v4 sig/cert.
+
+       * armor.c (is_armor_header): be more lenient in what constitutes a
+       valid armor header (i.e. -----BEGIN blah blah-----) as some
+       Windows programs seem to add spaces at the end.  --openpgp makes
+       it strict again.
+
+2002-03-18  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyserver.c (keyserver_search_prompt): Properly handle a "no
+       keys found" case from the internal HKP code (external HKP is ok).
+       Also, make a COUNT -1 (i.e. streamed) keyserver response a little
+       more efficient.
+
+       * g10.c (main): Add --no-allow-non-selfsigned-uid
+
+2002-03-17  David Shaw  <dshaw@jabberwocky.com>
+
+       * g10.c (main): --openpgp implies --allow-non-selfsigned-uid.
+
+       * getkey.c (merge_selfsigs_main): If none of the uids are primary
+       (because none are valid) then pick the first to be primary (but
+       still invalid).  This is for cosmetics in case some display needs
+       to print a user ID from a non-selfsigned key.  Also use
+       --allow-non-selfsigned-uid to make such a key valid and not
+       --always-trust.  The key is *not* automatically trusted via
+       --allow-non-selfsigned-uid.
+
+       * mainproc.c (check_sig_and_print): Make sure non-selfsigned uids
+       print [uncertain] on verification even though one is primary now.
+
+       * getkey.c (merge_selfsigs): If the main key is not valid, then
+       neither are the subkeys.
+
+       * import.c (import_one): Allow --allow-non-selfsigned-uid to work
+       on completely unsigned keys.  Print the uids in UTF8.  Remove
+       mark_non_selfsigned_uids_valid().
+
+       * keyedit.c (show_key_with_all_names): Show revocation key as
+       UTF8.
+
+       * sign.c (clearsign_file): Allow --not-dash-escaped to work with
+       v3 keys.
+
+2002-03-14  Werner Koch  <wk@gnupg.org>
+
+       * main.h: Changed the default algorithms to CAST5 and SHA1.
+
+2002-03-13  David Shaw  <dshaw@jabberwocky.com>
+
+       * import.c (chk_self_sigs): Show which user ID a bad self-sig
+       (invald sig or unsupported public key algorithm) resides on.
+
+       * import.c (chk_self_sigs): any valid self-sig should mark a user
+       ID or subkey as valid - otherwise, an attacker could DoS the user
+       by inventing a bogus invalid self-signature.
+
+2002-03-07  David Shaw  <dshaw@jabberwocky.com>
+
+       * g10.c (main): make a few more strings translatable.
+
+       * options.h, options.skel, g10.c (main), gpgv.c, mainproc.c
+       (check_sig_and_print), keyserver.c (parse_keyserver_options):
+       --auto-key-retrieve should really be a keyserver-option variable.
+
+       * import.c (revocation_present): new function to print a warning
+       if a key is imported that has been revoked by designated revoker,
+       but the designated revoker is not present to verify the
+       revocation.  If keyserver-options auto-key-retrieve is set, try
+       and fetch the designated revoker from the keyserver.
+
+       * import.c (import_one): call revocation_present after importing a
+       new key.  Note that this applies to --import, --recv-keys, and
+       --search-keys.
+       
+       * keyserver-internal.h, keyserver.c (keyserver_import_fprint):
+       import via fingerprint (for revocation keys).
+
+       * keyserver.c (keyserver_import_keyid): much simpler
+       implementation now that we're using KEYDB_SEARCH_DESC internally.
+
+2002-03-04  David Shaw  <dshaw@jabberwocky.com>
+
+       * revoke.c (gen_revoke): do not prompt for revocation reason for
+       v3 revocations (unless force-v4-certs is on) since they wouldn't
+       be used anyway.
+
+       * keyedit.c (menu_revsig): show the status of the sigs
+       (exportable? revocable?) to the user before prompting for which
+       sig to revoke.  Also, make sure that local signatures get local
+       revocations.
+
+       * keyedit.c (ask_revoke_sig): remind the user which sigs are
+       local.
+
+       * g10.c (main): Add "exec-path" variable to override PATH for
+       execing programs.
+
+       * export.c (do_export_stream): properly check return code from
+       classify_user_id to catch unclassifiable keys.
+
+2002-03-03  David Shaw  <dshaw@jabberwocky.com>
+
+       * parse-packet.c (parse_signature): variable type tweak for RISC
+       OS (from Stefan)
+
+2002-02-28  David Shaw  <dshaw@jabberwocky.com>
+
+       * getkey.c (check_revocation_keys): New function to check a
+       revocation against a list of potential revocation keys.  Note the
+       loop-breaking code here.  This is to prevent blowing up if A is
+       B's revocation key, while B is also A's.  Note also that this is
+       written so that a revoked revoker can still issue revocations:
+       i.e. If A revokes B, but A is revoked, B is still revoked.  I'm
+       not completely convinced this is the proper behavior, but it
+       matches how PGP does it.  It does at least have the advantage of
+       much simpler code - my first version of this had lots of loop
+       maintaining code so you could chain revokers many levels deep and
+       if D was revoked, C was not, which meant that B was, and so on.
+       It was sort of scary, actually.
+
+       * getkey.c (merge_selfsigs_main): Add any revocation keys onto the
+       pk.  This is particularly interesting since we normally only get
+       data from the most recent 1F signature, but you need multiple 1F
+       sigs to properly handle revocation keys (PGP does it this way, and
+       a revocation key could be marked "sensitive" and hence in a
+       different signature).  Also, if a pk has a revocation key set,
+       check for revocation sigs that were not made by us - if made by a
+       valid revocation key, mark the pk revoked.
+
+       * packet.h, getkey.c (cache_public_key): do not cache key if
+       "dont_cache" is set.  This allows the revocation key code to look
+       up a key and return information that may be inaccurate to prevent
+       loops without caching the fake data.
+
+       * packet.h, sig-check.c (do_signature_check): Record if a
+       signature was made by a revoked pk.
+
+       * packet.h, parse-packet.c (parse_one_sig_subpkt,
+       can_handle_critical, parse_signature): Get revocation key
+       information out of direct sigs.
+       
+       * keylist.c (list_keyblock_print): don't assume that the presence
+       of a 0x20 signature means the key is revoked.  With revocation
+       keys, this may not be true if the revocation key is not around to
+       verify it or if verification failed.  Also, 0x1F should get listed
+       as "sig", and not "unexpected signature class".
+
+       * keyedit.c (show_key_with_all_names): Add a flag for printing
+       revoker information and change all callers.
+
+       * import.c (merge_blocks): merge in any new direct key (0x1F)
+       sigs.
+
+       * import.c (import_revoke_cert): don't keep processing after a
+       revocation is rejected.
+       
+       * import.c (delete_inv_parts): Allow importing a revocation
+       signature even if it was not issued by the key.  This allows a
+       revocation key to issue it.  Of course, the sig still needs to be
+       checked before we trust it.
+
+       * free-packet.c (copy_public_key): Include a new copy of the
+       revocation keys when duping a pk.
+
+       * free-packet.c (free_seckey_enc, release_public_key_parts): Free
+       any revocation keys that are attached to a sig or pk.
+
+       * export.c (do_export_stream): Do not export signatures with
+       "sensitive" revocation keys in them.
+
+2002-02-27  David Shaw  <dshaw@jabberwocky.com>
+
+       * export.c (do_export_stream): Do not include v3 keys in a
+       --export-secret-subkeys export.
+
+       * getkey.c (merge_selfsigs_main): If a key isn't valid (say,
+       because of no self-signature), allow --always-trust to force it
+       valid so it can be trusted.
+
+2002-02-25  David Shaw  <dshaw@jabberwocky.com>
+
+       * hkp.c (hkp_ask_import), hkp.h, keyserver.c (all): treat key
+       lists internally as fingerprints when possible.  All this is via
+       KEYDB_SEARCH_DESC - no point in reinventing the wheel. This allows
+       the helper program to search the keyserver by fingerprint if
+       desired (and the keyserver supports it).  Note that automatic
+       fingerprint promotion during refresh only applies to v4 keys as a
+       v4 fingerprint can be easily changed into a long or short key id,
+       and a v3 cannot.
+
+       * pubkey-enc.c, getkey.c, misc.c, main.h: Take two copies of
+       hextobyte() from pubkey-enc.c and getkey.c and make them into one
+       copy in misc.c.
+
+2002-02-22  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyserver.c (keyserver_search_prompt): Detect a "no keys found"
+       case even if the helper program does not explicitly say how many
+       keys were found.
+
+       * hkp.c (parse_hkp_index): Bug fix - don't report non-revoked keys
+       as revoked in HKP key searches.
+
+2002-02-19  Werner Koch  <wk@gnupg.org>
+
+       * parse-packet.c (parse_trust): Made parsing more robust.
+
+2002-02-19  David Shaw  <dshaw@jabberwocky.com>
+
+       * hkp.c (parse_hkp_index): Catch corruption in HKP index lines
+       (can be caused by broken or malicious keyservers).
+
+       * keyserver.c (keyserver_work): Add KEYSERVER_NOT_SUPPORTED for
+       unsupported actions (say, a keyserver that has no way to search,
+       or a readonly keyserver that has no way to add).  Also add a
+       USE_EXTERNAL_HKP define to disable the internal HKP keyserver
+       code.
+
+2002-02-14  Werner Koch  <wk@gnupg.org>
+
+       * g10.c: New option --no-use-agent. 
+
+       * pkclist.c (check_signatures_trust): Always print the warning for
+       unknown and undefined trust.  Removed the did_add cruft.  Reported
+       by Janusz A. Urbanowicz.
+
+2002-02-11  David Shaw  <dshaw@jabberwocky.com>
+
+       * hkp.c (parse_hkp_index): Bug fix - properly handle user IDs with
+       colons (":") in them while HKP searching.
+
+2002-02-09  David Shaw  <dshaw@jabberwocky.com>
+
+       * misc.c (pct_expando): More comments.
+
+       * keydb.h, sign.c (mk_notation_and_policy): Clarify what is a sig
+       and what is a cert.  A sig has sigclass 0x00, 0x01, 0x02, or 0x40,
+       and everything else is a cert.
+
+       * g10.c (main), keyedit.c (keyedit_menu): Add a "nrlsign" for
+       nonrevocable and local key signatures.
+
+       * g10.c (main): Add a --no-force-mdc to undo --force-mdc.
+
+       * options.h, g10.c (main), cipher.c (write_header): Add a knob to
+       --disable-mdc/--no-disable-mdc.  Off by default, of course, but is
+       used in --pgp2 and --pgp6 modes.
+       
+       * pkclist.c (build_pk_list): Allow specifying multiple users in
+       the "Enter the user ID" loop.  Enter a blank line to stop.  Show
+       each key+id as it is added.
+
+       * keylist.c (show_policy_url), mainproc.c (print_notation_data):
+       It is not illegal (though possibly silly) to have multiple policy
+       URLs in a given signature, so print all that are present.
+       
+       * hkp.c (hkp_search): More efficient implementation of URL-ifying
+       code.
+
+2002-02-04  David Shaw  <dshaw@jabberwocky.com>
+
+       * main.h, misc.c (pct_expando): New function to generalize
+       %-expando processing in any arbitrary string.
+
+       * photoid.c (show_photo): Call the new pct_expando function rather
+       than expand strings internally.
+       
+       * sign.c (mk_notation_and_policy): Show policy URLs and notations
+       when making a signature if show-policy/show-notation is on.
+       %-expand policy URLs during generation.  This lets the user have
+       policy URLs of the form "http://notary.jabberwocky.com/keysign/%K"
+       which will generate a per-signature policy URL.
+
+       * main.h, keylist.c (show_policy_url, show_notation): Add amount
+       to indent so the same function can be used in key listings as well
+       as during sig generation.  Change all callers.
+
+2002-02-04  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyserver.c, options.h (parse_keyserver_options, keyidlist):
+       Workaround for the pksd and OKS keyserver bug that calculates v4
+       RSA keyids as if they were v3.  The workaround/hack is to fetch
+       both the v4 (e.g. 99242560) and v3 (e.g. 68FDDBC7) keyids.  This
+       only happens for key refresh while using the HKP scheme and the
+       refresh-add-fake-v3-keyids keyserver option must be set.  This
+       should stay off by default.
+
+2002-02-03  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyserver.c (keyserver_spawn): Bug fix - do not append keys to
+       each other when --sending more than one.
+
+2002-02-02  David Shaw  <dshaw@jabberwocky.com>
+
+       * options.h, g10.c (main), keyedit.c (sign_uids), sign.c
+       (mk_notation_and_policy): Split "--set-policy-url" into
+       "--cert-policy-url" and "--sig-policy-url" so the user can set
+       different policies for key and data signing.  For backwards
+       compatibility, "--set-policy-url" sets both, as before.
+
+2002-01-30  Werner Koch  <wk@gnupg.org>
+
+       * g10.c (main): --gen-random --armor does now output a base64
+       encoded string.
+
+2002-01-28  David Shaw  <dshaw@jabberwocky.com>
+
+       * g10.c (main), options.h, pkclist.c (algo_available): --pgp6
+       flag.  This is not nearly as involved as --pgp2.  In short, it
+       turns off force_mdc, turns on no_comment, escape_from, and
+       force_v3_sigs, and sets compression to 1.  It also restricts the
+       user to IDEA (if present), 3DES, CAST5, MD5, SHA1, and RIPEMD160.
+       See the comments above algo_available() for lots of discussion on
+       why you would want to do this.
+
+2002-01-27  David Shaw  <dshaw@jabberwocky.com>
+
+       * keygen.c (keygen_set_std_prefs): Comment
+
+       * keyedit.c (sign_uids): Bug fix - when signing with multiple
+       secret keys at the same time, make sure each key gets the sigclass
+       prompt.
+
+       * exec.c (exec_finish): Close the iobuf and FILE before trying to
+       waitpid, so the remote process will get a SIGPIPE and exit.  This
+       is only a factor when using a pipe to communicate.
+
+       * exec.c (exec_write): Disable cache-on-close of the fd iobuf (is
+       this right?  Why is a fd iobuf cached at all?)
+
+2002-01-26  Werner Koch  <wk@gnupg.org>
+
+       * g10.c, options.h: New option --gpg-agent-info
+       * passphrase.c (agent_open): Let it override the environment info.
+       * seckey-cert.c (check_secret_key): Always try 3 times when the
+       agent is enabled.
+       * options.skel: Describe --use-agent.
+
+2002-01-24  David Shaw  <dshaw@jabberwocky.com>
+
+       * pubkey-enc.c (is_algo_in_prefs, get_it): Only check preferences
+       against keys with v4 self sigs - there is really little point in
+       warning for every single non-IDEA message encrypted to an old key.
+
+       * pkclist.c (select_algo_from_prefs): Only put in the fake IDEA
+       preference if --pgp2 is on.
+
+       * mainproc.c (check_sig_and_print): Print "Expired" for expired
+       but good signatures (this still prints "BAD" for expired but bad
+       signatures).
+
+2002-01-23  David Shaw  <dshaw@jabberwocky.com>
+
+       * keygen.c (ask_keysize): Cosmetic: don't present a RSA signing
+       key as a "keypair" which can be 768 bits long (as RSA minimum is
+       1024).
+
+       * pubkey-enc.c (is_algo_in_prefs): Allow IDEA as a fake preference
+       for v3 keys with v3 selfsigs.
+
+2002-01-22  David Shaw  <dshaw@jabberwocky.com>
+
+       * packet.h, getkey.c (merge_selfsigs_main), pkclist.c
+       (select_algo_from_prefs): Implement the fake IDEA preference as
+       per RFC2440:12.1.  This doesn't mean that IDEA will be used (the
+       plugin may not be present), but it does mean that a v3 key with a
+       v3 selfsig has an implicit IDEA preference instead of 3DES.  v3
+       keys with v4 selfsigs use preferences as normal.
+
+       * encode.c (encode_crypt): if select_algo_from_prefs fails, this
+       means that we could not find a cipher that both keys like.  Since
+       all v4 keys have an implicit 3DES preference, this means there is
+       a v3 key with a v3 selfsig in the list.  Use 3DES in this case as
+       it is the safest option (we know the v4 key can handle it, and
+       we'll just hope the v3 key is being used in an implementation that
+       can handle it).  If --pgp2 is on, warn the user what we're doing
+       since it'll probably break PGP2 compatibility.
+
+       * g10.c (main): Do not force using IDEA for encrypted files in
+       --pgp2 mode - let the fake IDEA preference choose this for us for
+       better compatibility when encrypting to multiple keys, only some
+       of which are v3.
+
+       * keygen.c (keygen_set_std_prefs): Put 3DES on the end of the
+       default cipher pref list (RFC2440: "...it is good form to place it
+       there explicitly.").  If the user has the IDEA plugin installed,
+       put a preference for IDEA *after* 3DES to effectively disable its
+       use for everything except encrypting along with v3 keys.
+
+       * encode.c, g10.c, sign.c: Change the PGP2 warning line from
+       "... will not be usable ..." to "... may not be usable ..." as the
+       user could be using one of the enhanced PGP2 variations.
+
+       * helptext.c: Revise the sign_uid.class help text as suggested by
+       Stefan.
+       
+2002-01-20  Werner Koch  <wk@gnupg.org>
+
+       * passphrase.c (passphrase_to_dek): Add tryagain_text arg to be
+       used with the agent.  Changed all callers.
+       (agent_get_passphrase): Likewise and send it to the agent
+       * seckey-cert.c (do_check): New arg tryagain_text.
+       (check_secret_key): Pass the string to do_check.
+       * keygen.c (ask_passphrase): Set the error text is required.
+       * keyedit.c (change_passphrase): Ditto.
+
+       * passphrase.c (agent_open): Disable opt.use_agent in case of a
+       problem with the agent. 
+       (agent_get_passphrase): Ditto.
+       (passphrase_clear_cache): Ditto.
+
+2002-01-19  Werner Koch  <wk@gnupg.org>
+
+       * passphrase.c (agent_open): Add support for the new Assuan based
+       gpg-agent.  New arg to return the used protocol version.
+       (agent_get_passphrase): Implemented new protocol here.
+       (passphrase_clear_cache): Ditto.
+       (readline): New.
+       
+2002-01-15  Timo Schulz  <ts@winpt.org>
+
+       * encode.c (encode_crypt_files): Fail if --output is used.
+       
+       * g10.c: New command --decrypt-files.
+
+       * decrypt.c (decrypt_messages): New.
+       
+2002-01-09  David Shaw  <dshaw@jabberwocky.com>
+
+       * g10.c, misc.c, gpgv.c: move idea_cipher_warn to misc.c so gpgv.c
+       doesn't need a stub for it any longer.
+
+       * g10.c (get_temp_dir), main.h: no longer used (it's in exec.c now)
+
+       * g10.c (main), delkey.c (delete_keys), main.h : Allow
+       --delete-key (now --delete-keys, though --delete-key still works,
+       of course) to delete multiple keys in one go.  This applies to
+       --delete-secret-key(s) and --delete-secret-and-public-key(s) as
+       well.
+
+2002-01-09  Timo Schulz  <ts@winpt.org>
+
+       * encode.c (encode_crypt_files): Now it behaves like verify_files.
+       
+       * g10.c (main): We don't need to check argc for encode_crypt_files
+       any longer.
+
+2002-01-09  Timo Schulz  <ts@winpt.org>
+
+       * exec.c: Include windows.h for dosish systems.
+
+2002-01-08  Timo Schulz  <ts@winpt.org>
+
+       * g10.c (main): New description for --encrypt-files.
+
+2002-01-08  Werner Koch  <wk@gnupg.org>
+
+       * g10.c (main): Must register the secring for encryption because
+       it is needed to figure out the default recipient.  Reported by
+       Roger Sondermann.
+
+2002-01-05  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyedit.c (menu_adduid): Require --expert before adding a photo
+       ID to a v3 key, and before adding a second photo ID to any key.
+
+       * keyedit.c (keyedit_menu): Don't allow adding photo IDs in
+       rfc1991 or pgp2 mode.
+
+       * getkey.c (merge_selfsigs_subkey): Permit v3 subkeys.  Believe it
+       or not, this is allowed by rfc 2440, and both PGP 6 and PGP 7 work
+       fine with them.
+
+       * g10.c, options.h, keyedit.c, sign.c: Move the "ask for
+       expiration" switch off of --expert, which was getting quite
+       overloaded, and onto ask-sig-expire and ask-cert-expire.  Both
+       default to off.
+
+       * g10.c (main): Change the default compression algo to 1, to be
+       more OpenPGP compliant (PGP also uses this, so it'll help with
+       interoperability problems as well).
+
+       * encode.c (encode_crypt): Handle compression algo 2, since the
+       default is now 1.
+
+       * build-packet.c (build_attribute_subpkt): Fix off-by-one error.
+
+2002-01-05  Werner Koch  <wk@gnupg.org>
+
+       * g10.c (main): Do not register the secret keyrings for certain
+       commands.
+
+       * keydb.c (keydb_add_resource): Use access to test for keyring
+       existence.  This avoids cached opened files which are bad under
+       RISC OS.
+
+2002-01-04  David Shaw  <dshaw@jabberwocky.com>
+
+       * sign.c (sign_file, sign_symencrypt_file): always use one-pass
+       packets unless rfc1991 is enabled.  This allows a signature made
+       with a v3 key to work in PGP 6 and 7.  Signatures made with v4
+       keys are unchanged.
+
+       * g10.c (main): Disallow non-detached signatures in PGP2 mode.
+       Move the "you must use files and not pipes" PGP2 warning up so all
+       the PGP2 stuff is together.
+
+       * encode.c (encode_simple): Use the actual filesize instead of
+       partial length packets in the internal literal packet from a
+       symmetric message.  This breaks PGP5(?), but fixes PGP2, 6, and 7.
+       It's a decent tradeoff.  Note there was only an issue with
+       old-style RFC1991 symmetric messages.  2440-style messages in 6
+       and 7 work with or without partial length packets.
+
+2002-01-03  David Shaw  <dshaw@jabberwocky.com>
+
+       * g10.c (main): Removed --no-default-check-level option, as it is
+       not consistent with other "default" options.  Plus, it is the same
+       as saying --default-check-level 0.
+
+       * exec.c (exec_read): Disallow caching tempfile from child
+       process, as this keeps the file handle open and can cause unlink
+       problems on some platforms.
+
+       * keyserver.c (keyserver_search_prompt): Minor tweak - don't
+       bother to transform keyids into textual form if they're just going
+       to be transformed back to numbers.
+
+2002-01-03  Timo Schulz <ts@winpt.org>
+
+       * g10.c: New command --encrypt-files.
+    
+       * verify.c (print_file_status): Removed the static because
+       encode_crypt_files also uses this function.
+
+       * main.h (print_files_status): New.
+       (encode_crypt_files): New.
+
+       * encode.c (encode_crypt_files): New.
+
+2002-01-02  Stefan Bellon  <sbellon@sbellon.de>
+
+       * keyserver.c: Moved util.h include down in order to avoid
+       redefinition problems on RISC OS.
+
+       * keyring.c (keyring_lock): Only lock keyrings that are writable.
+
+       * keyring.c (keyring_update_keyblock): Close unused iobuf.
+
+       * hkp.c (parse_hkp_index, hkp_search) [__riscos__]: Changed
+       unsigned char* to char* because of compiler issues.
+
+       * exec.c (exec_finish) [__riscos__]: Invalidate close cache so
+       that file can be unlinked.
+
+2001-12-28  David Shaw  <dshaw@jabberwocky.com>
+
+       * g10.c (main): Use a different strlist to check extensions since
+       they need to be handled seperately now.
+
+       * misc.c,main.h (check_permissions): Properly handle permission
+       and ownership checks on files in the lib directory
+       (e.g. /usr/local/lib/gnupg), which are owned by root and are
+       world-readable, and change all callers to specify extension or
+       per-user file.
+
+       * photoid.c (show_photo), keyserver.c (keyserver_spawn): Bug fix -
+       don't call exec_finish if exec_write fails.
+
+       * keyserver.c (keyserver_spawn): Look for OPTIONS from the
+       keyserver helper - specifically, a "OUTOFBAND" option for the
+       email keyserver.
+
+       * mainproc.c (list_node), keylist.c (list_keyblock_colon),
+       import.c (delete_inv_parts), export.c (do_export_stream): Use
+       signature flags for exportability check rather than re-parsing the
+       subpacket.
+
+       * keyid.c, keydb.h (get_lsign_letter): No longer needed.
+
+2001-12-27  David Shaw  <dshaw@jabberwocky.com>
+
+       * exec.c (exec_finish): Show errors when temp files cannot be
+       deleted for whatever reason.
+
+       * exec.c (exec_read): Don't rely on WEXITSTATUS being present.
+
+       * exec.c (make_tempdir): Add temp file creator for win32.  Don't
+       create an incoming temp file if the exec is write-only.
+
+       * keyserver.c (keyserver_spawn): Clean up error handling, for when
+       the spawn fails.
+
+       * photoid.c (show_photo): Clean up error handling.
+
+       * misc.c (check_permissions): Neaten.
+
+2001-12-25  David Shaw  <dshaw@jabberwocky.com>
+
+       * mkdtemp.c (mkdtemp): Add copyleft info and tweak the 'X' counter
+       to be a bit simpler.
+
+       * keyserver.c, photoid.c: Remove unused headers left over from
+       when the exec functions lived there.
+
+2001-12-23  Timo Schulz <ts@winpt.org>
+
+       * misc.c (check_permissions): Do not use it for W32 systems.
+
+       * tdbio.c (migrate_from_v2): Define ftruncate as chsize() for W32.
+
+       * mkdtemp.c: W32 support.
+
+       * photoid.c: Ditto.
+
+       * exec.c: Ditto.
+
+2001-12-22  David Shaw  <dshaw@jabberwocky.com>
+
+       * exec.c (make_tempdir): avoid compiler warning with const
+
+       * mkdtemp.c (mkdtemp): catch the empty ("") string case in case
+       someone repurposes mkdtemp at some point.
+
+       * photoid.c (generate_photo_id, show_photo): some type changes
+       from Stefan Bellon.
+
+       * exec.c (make_tempdir): handle Win32 systems, suggested by Timo
+       Schulz.
+
+2001-12-22  Werner Koch  <wk@gnupg.org>
+
+       * encode.c (encode_simple, encode_crypt): i18n 2 strings.
+
+2001-12-22  Timo Schulz <ts@winpt.org>
+       
+       * encode.c (encode_simple, encode_crypt): Use is_file_compressed
+       to avoid to compress compressed files.
+
+2001-12-22  Werner Koch  <wk@gnupg.org>
+
+       * keyserver.c (keyserver_spawn): Removed some variables
+       declaration due to shadowing warnings.
+
+       * build-packet.c (build_attribute_subpkt): s/index/idx/ to avoid
+       compiler warnig due to index(3).
+
+       * getkey.c (get_ctx_handle): Use KEYDB_HANDLE as return value.
+       * keylist.c (list_one): Made resname const.
+
+       * keyedit.c (keyedit_menu): Allow "addphoto" only when --openpgp is
+       not used.
+
+       * options.skel: Changed one example photo viewer to qiv.
+
+2001-12-21  David Shaw  <dshaw@jabberwocky.com>
+
+       * Makefile.am: add exec.c, exec.h, photoid.c, and photoid.h
+
+       * build-packet.c (build_attribute_subpkt): new function to build
+       the raw attribute subpacket.  Note that attribute subpackets have
+       the same format as signature subpackets.
+
+       * exec.c: new file with generic exec-a-program functionality.
+       Used by both photo IDs and keyserver helpers.  This is pretty much
+       the same code that used to be keyserver specific, with some
+       changes to be usable generically.
+
+       * free-packet.c (free_attributes (new)): function to free an
+       attribute packet.
+       
+       * gpgv.c: added stub show_photo
+       
+       * keyedit.c (keyedit_menu, menu_adduid, menu_showphoto): can add a
+       photo (calls generate_photo_id), or display a photo (calls
+       show_photo) from the --edit menu.  New commands are "addphoto",
+       and "delphoto" (same as "deluid").
+
+       * keylist.c (list_keyblock_print): show photos during key list if
+       --show-photos enabled.
+       
+       * keyserver.c (keyserver_spawn): use the generic exec_xxx
+       functions to call keyserver helper.
+
+       * g10.c, options.h: three new options - --{no-}show-photos, and
+       --photo-viewer to give the command line to display a picture.
+
+       * options.skel: instructions for the photo viewer
+       
+       * parse-packet.c (parse_user_id, setup_user_id (new)): common code
+       for both user IDs and attribute IDs moved to setup_user_id.
+
+       * parse-packet.c (make_attribute_uidname (new)): constructs a fake
+       "name" for attribute packets (e.g. "[image of size ...]")
+
+       * parse-packet.c (parse_attribute (replaces parse_photo_id),
+       parse_attribute_subpkts): Builds an array of individual
+       attributes.  Currently only handles attribute image / type jpeg
+       subpackets.
+
+       * sign.c (hash_uid): Fix bug in signing attribute (formerly
+       photo_id) packets.
+
+       * packet.h, and callers: globally change "photo_id" to "attribute"
+       and add structures for attributes.  The packet format is generic
+       attributes, even though the only attribute type thus far defined
+       is jpeg.
+
+2001-12-21  David Shaw  <dshaw@jabberwocky.com>
+
+       * parse-packet.c (can_handle_critical): Can handle critical
+       revocation subpackets now.
+
+       * trustdb.c (mark_usable_uid_certs): Disregard revocations for
+       nonrevocable sigs.  Note that this allows a newer revocable
+       signature to override an older nonrevocable signature.
+
+       * sign.c (make_keysig_packet): add a duration field and change all
+       callers.  This makes make_keysig_packet closer to
+       write_signature_packets and removes some duplicated expiration
+       code.
+
+       * keyedit.c (keyedit_menu, menu_revsig, sign_uids,
+       sign_mk_attrib): Add nrsign command, don't allow revoking a
+       nonrevocable signature,
+
+       * g10.c (main): Add --nrsign option to nonrevocably sign a key
+       from the command line.
+
+       * build-packet.c (build_sig_subpkt_from_sig): Comment to explain
+       the use of CRITICAL.
+
+2001-12-21  Werner Koch  <wk@gnupg.org>
+
+       * g10.c. options.h : New option --show-keyring
+       * getkey.c (get_ctx_handle): New.
+       * keylist.c (list_one): Implement option here.  By David Champion. 
+
+2001-12-20  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyserver.c (keyserver_spawn): Use mkdtemp() to make temp
+       directory.
+
+       * mkdtemp.c: replacement function for those platforms that don't
+       have mkdtemp (make a temp directory securely).
+
+2001-12-19  David Shaw  <dshaw@jabberwocky.com>
+
+       * misc.c (check_permissions): New function to stat() and ensure
+       the permissions of GNUPGHOME and the files have safe permissions.
+
+       * keydb.c (keydb_add_resource): Check keyring permissions.
+
+       * tdbio.c (tdbio_set_dbname): Check permissions of trustdb.gpg
+
+       * keyserver.c (keyserver_spawn): Disable keyserver schemes that
+       involve running external programs if the options file has unsafe
+       permissions or ownership.
+
+       * g10.c, options.h: New option --no-permission-warning to disable
+       the permission warning message(s).  This also permits use of the
+       keyserver if it had been disabled (see above).  Also check the
+       permissions/ownership of random_seed.
+       
+       * keyserver.c (keyserver_spawn): The new glibc prints a warning
+       when using mktemp() (the code was already secure, but the warning
+       was bound to cause confusion).  Use a different implementation
+       based on get_random_bits() instead.  Also try a few times to get
+       the temp dir before giving up.
+
+2001-12-19  Werner Koch  <wk@gnupg.org>
+
+       * g10.c, passphrase.c [CYGWIN32]: Allow this as an alias for MINGW32.
+
+2001-12-18  David Shaw  <dshaw@jabberwocky.com>
+
+       * g10.c (idea_cipher_warn): Add a flag to show the warning always
+       or once per session and change all callers (show always except for
+       the secret key protection and unknown cipher from an encrypted
+       message errors).  Also make the strings translatable.
+
+       * pubkey-enc.c (get_it): Add the IDEA cipher warning if the user
+       tries to decrypt an IDEA encrypted message without the IDEA
+       plugin.
+
+       * keyserver.c (parse_keyserver_uri): More strict checking of the
+       keyserver URI.  Specifically, fail if the ":port" section is
+       anything except a number between 1 and 65535.
+
+2001-12-17  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyserver.c (print_keyinfo): No need to check for
+       control/illegal characters, as utf8_to_native does this for us.
+
+       * mainproc.c (proc_encrypted): Use generic IDEA warning.
+
+       * gpgv.c: add stub for idea_cipher_warn
+
+       * g10.c, hkp.c, keyserver.c: Fix capitalization and plural issues.
+
+       * encode.c (encode_crypt), sign.c (sign_file, clearsign_file):
+       disable pgp2 mode after the message is no longer pgp2 compatible.
+
+       * g10.c (main): Tweak the PGP2.x IDEA warning to use the generic
+       warning, and not merely fail if the IDEA plugin isn't there.
+
+       * g10.c (main, idea_cipher_warn), keygen.c (set_one_pref),
+       seckey-cert.c (do_check): Add a generic IDEA warning for when the
+       IDEA plugin is not present.  This pops up when the user uses
+       "--cipher-algo idea", when setpref is used to set a "S1"
+       preference, and when a secret key protected with IDEA is used.
+
+2001-12-15  Werner Koch  <wk@gnupg.org>
+
+       * keyserver.c (keyserver_spawn): Assert that we have dropped privs.
+
+2001-12-13  Werner Koch  <wk@gnupg.org>
+
+       * pubkey-enc.c (get_session_key): Check that the public key
+       algorithm is indeed usable for en/decryption.  This avoid a
+       strange error message from pubkey_decrypt if for some reasons a
+       bad algorithm indentifier is passed.
+
+2001-12-12  David Shaw  <dshaw@jabberwocky.com>
+
+       * Fixed some types for portability.  Noted by Stefan Bellon.
+
+2001-12-11  Werner Koch  <wk@gnupg.org>
+
+       * hkp.c (hkp_export): Do not print possible control characters
+       from a keyserver response.
+       (parse_hkp_index): Made uid an unsigned char* because it is passed to
+       isspace().
+       (hkp_search): Ditto for the char* vars.
+
+       * g10.c (main): Print the IDEA warning also for -c and -se.
+       
+       * g10.c (get_temp_dir): Assert that we have dropped privs
+
+       * encode.c (encode_crypt): Include the first key into the --pgp2
+       check.
+
+2001-12-07  David Shaw  <dshaw@jabberwocky.com>
+
+       * g10.c, options.h: New option --pgp2.  This is identical to
+       "--rfc1991 --cipher-algo idea --compress-algo 1 --digest-algo md5
+       --force_v3_sigs" with the addition of an warning to advise the
+       user not to use a pipe (which would break pgp2 compatibility).
+
+       * encode.c (encode_crypt): warn if the user tries to encrypt to
+       any key that is not RSA and <= 2048 bits when the --pgp2 option is
+       used.
+
+       * sign.c (sign_file, clearsign_file): When using --pgp2, make a v3
+       sig, and warn if the signature is made with a non-v3 key.
+
+2001-12-05  David Shaw  <dshaw@jabberwocky.com>
+
+       * sign.c (sign_file, clearsign_file, sign_symencrypt_file): Prompt
+       for sig expiration if --expert is set and --force-v3-sigs is not
+       set (v3 sigs cannot expire).
+
+       * mainproc.c (check_sig_and_print): After checking a sig, print
+       expiration status.  This causes a error return if the sig is
+       expired.
+
+       * build-packet.c (build_sig_subpkt_from_sig): Include a critical
+       sig expiration subpacket if the sig is to expire.
+
+       * keyedit.c (sign_uids): Do not sign an expired key unless
+       --expert is set, in which case prompt.  Also, offer to expire a
+       signature when the key the user is signing expires.
+
+       * keygen.c (ask_expire_interval): Add a value to determine whether
+       to prompt for a key or sig expiration and change all callers.
+
+       * keyid.c: New functions: expirestr_from_sig and
+       colon_expirestr_from_sig.
+
+       * keylist.c (list_keyblock_colon): Show sig expiration date in the
+       --with-colons listing.
+
+       * sign.c (make_keysig_packet, write_signature_packets): Pass in an
+       optional timestamp for the signature packet, and change all
+       callers.
+
+       * keyedit.c (sign_mk_attrib): Include a critical expiration
+       subpacket in the signature if an expiration date is given.
+
+2001-12-04  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyedit.c (sign_uids): If the user tries to sign a
+       locally-signed key, allow the cert to be promoted to a full
+       exportable signature.  This essentially deletes the old
+       non-exportable sig, and replaces it with a new exportable one.
+
+2001-12-04  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyedit.c (keyedit_menu): Do not allow signing a revoked key
+       unless --expert is set, and ask even then.
+
+       * keyedit.c (sign_uids): Do not allow signing a revoked UID unless
+       --expert is set, and ask even then.
+
+       * g10.c, options.h : New option --expert
+
+2001-11-16  David Shaw  <dshaw@jabberwocky.com>
+
+       * Allow the user to select no compression via "--compress-algo 0"
+       on the command line.
+
+       * keyedit.c (show_prefs): Show compression preferences in the
+       long-form "showpref" style.
+
+       * keygen.c (set_one_pref): Permit setting a no-compression ("Z0")
+       preference.
+
+       * getkey.c (fixup_uidnode): Fix compression preference corruption
+       bug.
+
+2001-12-02  David Shaw  <dshaw@jabberwocky.com>
+
+       * g10.c: Add advisory --for-your-eyes-only option as per section
+       5.9 of 2440.
+
+2001-12-05  David Shaw  <dshaw@jabberwocky.com>
+
+       * Force a V4 sig if the user has a notation or policy URL set.
+
+2001-12-04  David Shaw  <dshaw@jabberwocky.com>
+
+       * g10.c: Add options --keyserver-options, --temp-directory, and
+       auto-key-retrieve (the opposite of no-auto-key-retrieve).
+
+       * hkp.c (hkp_search): New function to handle searching a HKP
+       keyserver for a key
+
+       * hkp.c (hkp_ask_import, hkp_export): Pretty large changes to make
+       them communicate via the generic functions in keyserver.c
+
+       * keyserver.c: new file with generic keyserver routines for
+       getting keys from a keyserver, sending keys to a keyserver, and
+       searching for keys on a keyserver.  Calls the internal HKP stuff
+       in hkp.c for HKP keyserver functions.  Other calls are handled by
+       an external program which is spawned and written to and read from
+       via pipes.  Platforms that don't have pipes use temp files.
+
+2001-11-20  David Shaw  <dshaw@jabberwocky.com>
+
+       * options.h, g10.c: New options show-notation, no-show-notation,
+       default-check-level, no-default-check-level, show-policy-url,
+       no-show-policy-url.
+
+       * packet.h, sign.c (make_keysig_packet), parse-packet.c
+       (parse_signature), free-packet.c (free_seckey_enc): Fill in
+       structures for notation, policy, sig class, exportability, etc.
+
+       * keyedit.c, keylist.c (print_and_check_one_sig,
+       list_keyblock_print): Show flags in signature display for cert
+       details (class, local, notation, policy, revocable).  If selected,
+       show the notation and policy url.
+
+       * keyedit.c (sign_uids): Prompt for and use different key sig
+       classes.
+
+       * helptext.c (helptexts): Add help text to explain different
+       key signature classes
+
+2001-11-26  David Shaw  <dshaw@jabberwocky.com>
+
+       * trustdb.c (mark_usable_uid_certs): Fix segfault from bad
+       initialization and fix reversed key signature expiration check.
+
+2001-11-09  Werner Koch  <wk@gnupg.org>
+
+       * export.c (do_export_stream): Put all given names into a search
+       description and change the loop so that all matching names are
+       returned.
+
+2001-11-08  Werner Koch  <wk@gnupg.org>
+
+       * pubkey-enc.c (get_it): To reduce the number of questions on the
+       MLs print the the name of cipher algorithm 1 with the error message.
+
+       * mainproc.c: Changed the way old rfc1991 encryption cipher is
+       selected. Based on a patch by W Lewis.
+
+       * pkclist.c (do_edit_ownertrust): Allow to skip over keys, the non
+       working "show info" is now assigned to "i" 
+       * trustdb.c (ask_ownertrust, validate_keys): Implement a real quit
+       here.  Both are by David Shaw.
+       
+       * trustdb.c (validate_keys): Make sure next_exipire is initialized.
+
+       * sign.c (make_keysig_packet): Use SHA-1 with v4 RSA keys.
+
+       * g10.c, options.h : New option --[no-]froce-v4-certs.
+       * sign.c (make_keysig_packet): Create v4 sigs on v4 keys even with
+       a v3 key.  Use that new option.  By David Shaw
+
+       * revoke.c (ask_revocation_reason): Allow to select "no reason".
+       By David Shaw.
+
+       * keyid.c (fingerprint_from_sk): Calculation of an v3 fpr was
+       plain wrong - nearly the same code in fingerprint_from_pk is correct.
+
+       * build-packet.c (do_secret_key): Added a few comments to the code.
+
+2001-11-07  Werner Koch  <wk@gnupg.org>
+
+       * g10.c (main): Print a warning when -r is used w/o encryption.
+       Suggested by Pascal Scheffers.
+
+2001-10-23  Werner Koch  <wk@gnupg.org>
+
+       * keyedit.c (keyedit_menu): Changed helptext for showpref
+       command.  Suggested by Reinhard Wobst.
+
+       * keyring.c (keyring_search): When marking the offtbl ready, take
+       into account that we may have more than one keyring.
+
+2001-10-22  Werner Koch  <wk@gnupg.org>
+
+       * Makefile.am: Do not use OMIT_DEPENDENCIES
+
+       * build-packet.c (build_sig_subpkt): Default is now to put all
+       types of subpackets into the hashed area and only list those which
+       should go into the unhashed area.
+
+2001-10-18  Werner Koch  <wk@gnupg.org>
+
+       * keydb.c (keydb_add_resource): Rearranged the way we keep track
+       of the resource. There will now be an entry for each keyring here
+       and not in keyring.c itself.  Store a token to allow creation of a
+       keyring handle.  Changed all functions to utilize this new design.
+       (keydb_locate_writable): Make a real implementation.
+       * keyring.c (next_kr): Removed and changed all callers to set the
+       resource directly from the one given with the handle.
+       (keyring_is_writable): New. 
+       (keyring_rebuild_cache): Add an arg to pass the token from keydb.
+
+2001-10-17  Werner Koch  <wk@gnupg.org>
+
+       * keyring.c (keyring_search): Enabled word search mode but print a
+       warning that it is buggy.
+       
+2001-10-11  Werner Koch  <wk@gnupg.org>
+
+       * hkp.c (hkp_ask_import): No more need to set the port number for
+       the x-hkp scheme. 
+       (hkp_export): Ditto.
+
+2001-10-06  Stefan Bellon  <sbellon@sbellon.de>
+
+       * passphrase.c [__riscos__]: Disabled agent specific stuff.
+       * g10.c: New option --no-force-v3-sigs.
+
+2001-10-04  Werner Koch  <wk@gnupg.org>
+
+       * export.c (do_export_stream): Do not push the compress filter
+       here because the context would run out of scope due to the
+       iobuf_close done by the caller.
+       (do_export): Do it here instead. 
+
+2001-09-28  Werner Koch  <wk@gnupg.org>
+
+       * keyedit.c (sign_uids): Always use the primary key to sign keys.
+       * getkey.c (finish_lookup): Hack to return only the primary key if
+       a certification key has been requested.
+
+       * trustdb.c (cmp_kid_for_make_key_array): Renamed to
+       (validate_one_keyblock): this and changed arg for direct calling.
+       (make_key_array): Renamed to
+       (validate_one_keyblock): this and changed args for direct calling.
+       (mark_usable_uid_certs, validate_one_keyblock)
+       (validate_key_list): Add next_expire arg to keep track of
+       expiration times.  
+       (validate_keys): Ditto for UTKs and write the stamp.
+
+       * tdbio.c (migrate_from_v2): Check return code of tbdio_sync.
+
+       * tdbdump.c (import_ownertrust): Do a tdbio_sync().
+
+       * keyring.c: Made the offtbl an global object.
+
+2001-09-27  Werner Koch  <wk@gnupg.org>
+
+       * pkclist.c (do_edit_ownertrust): Allow settin of ultimate trust.
+
+       * trustdb.c (mark_keyblock_seen): New.
+       (make_key_array): Use it to mark the subkeys too.
+       (validate_keys): Store validity for ultimatly trusted keys.
+
+2001-09-26  Werner Koch  <wk@gnupg.org>
+
+       * pkclist.c (check_signatures_trust, do_we_trust): Removed the
+       invocation of add_ownertrust. Minor changes to the wording.
+       (add_ownertrust, add_ownertrust_cb): Removed.
+
+       * trustdb.c (get_validity): Allow to lookup the validity using a
+       subkey.
+
+       * trustdb.c (new_key_hash_table): Increased the table size to 1024
+       and changed the masks accordingly.
+       (validate): Changed stats printing.
+       (mark_usable_uid_certs): New.
+       (cmp_kid_for_make_key_array): Does now check the signatures and
+       figures out a usable one.
+
+2001-09-25  Werner Koch  <wk@gnupg.org>
+
+       * keyring.c (new_offset_item,release_offset_items)
+       (new_offset_hash_table, lookup_offset_hash_table)
+       (update_offset_hash_table, update_offset_hash_table_from_kb): New.
+       (keyring_search): Use a offset table to optimize search for
+       unknown keys.
+       (keyring_update_keyblock, keyring_insert_keyblock): Insert new
+       offsets.
+       * getkey.c (MAX_UNK_CACHE_ENTRIES): Removed the unknown keys
+       caching code.
+
+       * g10.c, options.h, import.c: Removed the entire
+       allow-secret-key-import stuff because the validity is now
+       controlled by other means.
+
+       * g10.c: New command --rebuild-keydb-caches.
+       * keydb.c (keydb_rebuild_caches): New.
+       * keyring.c (do_copy): Moved some code to
+       (create_tmp_file, rename_tmp_file, write_keyblock): new functions.
+       (keyring_rebuild_cache): New.
+
+       * packet.h (PKT_ring_trust): Add sigcache field.
+       * parse-packet.c (parse_trust): Parse sigcache.
+       * keyring.c (do_copy): Always insert a sigcache packet.
+       (keyring_get_keyblock): Copy the sigcache packet to the signature.
+       * sig-check.c (cache_sig_result): Renamed from
+       cache_selfsig_result. Changed implementation to use the flag bits
+       and changed all callers.
+       (mdc_kludge_check): Removed this unused code.
+       (do_check): Do not set the sig flags here.
+
+       * import.c (read_block): Make sure that ring_trust packets are
+       never imported.
+       * export.c (do_export_stream): and never export them.
+
+       * trustdb.c (make_key_array): Skip revoked and expired keys.
+
+2001-09-24  Werner Koch  <wk@gnupg.org>
+
+       * g10.c, options.h: New option --no-auto-check-trustdb.
+
+       * keygen.c (do_generate_keypair): Set newly created keys to
+       ultimately trusted.
+
+       * tdbio.h, tdbio.c: Removed all support for records DIR, KEY, UID,
+       PREF, SIG, SDIR and CACH. Changed migration function to work
+       direct on the file.
+       (tdbio_read_nextcheck): New.
+       (tdbio_write_nextcheck): New. 
+
+2001-09-21  Werner Koch  <wk@gnupg.org>
+
+       Revamped the entire key validation system.
+       * trustdb.c: Complete rewrite. No more validation on demand,
+       removed some functions, adjusted to all callers to use the new 
+       and much simpler interface. Does not use the LID anymore.
+       * tdbio.c, tdbio.h: Add new record types trust and valid. Wrote a
+       migration function to convert to the new trustdb layout.
+       * getkey.c (classify_user_id2): Do not allow the use of the "#"
+       prefix. 
+       * keydb.h: Removed the TDBIDX mode add a skipfnc to the
+       descriptor.
+       * keyring.c (keyring_search): Implemented skipfnc.
+
+       * passphrase.c (agent_open): Add missing bracket.  Include windows.h.
+
+2001-09-19  Werner Koch  <wk@gnupg.org>
+
+       * keylist.c (print_fingerprint): Renamed from fingerprint, made
+       global available. Added new arg to control the print style.
+       * mainproc.c (print_fingerprint): Removed. 
+       * pkclist.c (print_fpr, fpr_info): Removed and changed callers to
+       use print_fingerprint.
+       * keyedit.c (show_fingerprint): Ditto.
+
+       * passphrase.c (writen, readn)
+       (agent_open, agent_close)
+       (agent_get_passphrase)
+       (passphrase_clear_cache): Support for W32.  Contributed by Timo.
+
+       * import.c (import_one): Release keydb handles at 2 more places.
+
+       * keyring.c (keyring_release): Close the iobuf.
+       (keyring_get_keyblock): Init ret_kb to NULL and store error contidion.
+
+       * import.c (import_new_stats_handle): New. 
+       (import_release_stats_handle): New.
+       (import_print_stats): Renamed from static fnc print_stats.
+       (import_keys, import_keys_stream): Add an optional status handle
+       arg and changed all callers.
+       * hkp.c (hkp_ask_import): Add an stats_handle arg and changed all
+       callers.
+
+       * mainproc.c (print_pkenc_list): Use print_utf8_string2().
+
+2001-09-18  Werner Koch  <wk@gnupg.org>
+
+       * g10.c: New command --refresh-keys.
+       * hkp.c (hkp_refresh_keys): New. Contributed by Timo Schulz.
+
+       * parse-packet.c (parse): Stop on impossible packet lengths.
+
+2001-09-17  Werner Koch  <wk@gnupg.org>
+
+       * mainproc.c (print_notation_data): Wrap notation data status lines
+       after 50 chars.
+       
+       * mainproc.c (proc_pubkey_enc): Make option try-all-secrets work.
+       By disastry@saiknes.lv.
+
+2001-09-14  Werner Koch  <wk@gnupg.org>
+
+       * parse-packet.c (dump_sig_subpkt): List key server preferences
+       and show the revocable flag correctly. Contributed by David Shaw.
+
+2001-09-09  Werner Koch  <wk@gnupg.org>
+
+       * keyedit.c (keyedit_menu): No need to define another p.
+
+       * keylist.c (print_capabilities): s/used/use/ so that it
+       does not shadow a global.
+       * sign.c (sign_file): Renamed arg encrypt to encryptflag
+       * keygen.c: Replaced all "usage" by "use".
+       * misc.c (openpgp_pk_algo_usage): Ditto.
+
+       * pubkey-enc.c (get_it): Renamed arg k to enc so that the later
+       defined k does not shadow it.
+
+       * parse-packet.c (parse_gpg_control): No need to define another i.
+
+       * getkey.c (get_pubkey_byfprint): Must use the enum values and not
+       the fprint_len.
+       * keyring.c (keyring_search): Removed a non-sense break.  Both
+       bugs pointed out by Stefan.
+
+2001-09-07  Werner Koch  <wk@gnupg.org>
+
+       * status.c, status.h: Added NO_RECP and ALREADY_SIGNED.
+       * pkclist.c (build_pk_list): Issue NO_RECP.
+       * keyedit.c (sign_uids): Added experimental ALREADY_SIGNED
+
+       * hkp.c (hkp_import): Use log_error. Bug reported by Neal H
+       Walfield. 
+
+       * getkey.c (classify_user_id2): Change args to take the desc union
+       direct.  It was a stupid idea to pass the individual fields of an
+       union to this function. Changed all callers.
+       (classify_user_id): Ditto and allow to pass NULL as the description.
+
+2001-09-06  Werner Koch  <wk@gnupg.org>
+
+       * getkey.c (fixup_uidnode): Features flag is now a bit vector.
+       * keygen.c (add_feature_mdc): Ditto.
+
+       Revamped the entire key I/O code to be prepared for other ways of
+       key storages and to get rid of the existing shit.  GDBM support has
+       gone.
+       * keydb.c: New
+       * keyring.c, keyring.h: New.
+       * ringedit.c: Removed.  Moved some stuff to keyring.c
+       * getkey.c: Changed everything related to the key retrieving
+       functions which are now using the keydb_ functions.  
+       (prepare_search, word_match_chars, word_match)
+       (prepare_word_match, compare_name): Moved to keyring.c
+       (get_pubkey_byname): Removed ctx arg and add ret_kdbhd
+       arg.  Changed all callers.
+       (key_byname): Use get_pubkey_end to release the context and take
+       new ret_kbdhd arg.  Changed all callers.
+       (classify_user_id2): Fill the 16 byte fingerprint up with 4 null
+       bytes not with zero bytes of value 4, tsss.
+       * import.c (import_one): Updated to use the new keydb interface.
+       (import_secret_one): Ditto.
+       (import_revoke_cert): Ditto.
+       * delkey.c (do_delete_key): Ditto. 
+       * keyedit.c (keyedit_menu): Ditto.
+       (get_keyblock_byname): Removed.
+       * revoke.c (gen_revoke): Ditto. 
+       * export.c (do_export_stream): Ditto.
+       * trustdb.c (update_trustdb): Ditto.
+       * g10.c, gpgv.c (main): Renamed add_keyblock_resource to
+       keydb_add_resource. 
+       * Makefile.am:  Added and removed files.
 
-       * Makefile.am: Do not install any program
+       * keydb.h: Moved KBNODE typedef and MAX_FINGERPRINT_LEN to
+       * global.h: this new header.
+       
+2001-09-03  Werner Koch  <wk@gnupg.org>
 
-2000-10-12  Werner Koch  <wk@gnupg.org>
+       * passphrase.c (agent_get_passphrase): Changed nread to size_t.
+       (passphrase_clear_cache): Ditto.
 
-       * keygen.c (keygen_add_std_prefs): Add Rijndael to the prefs.
+       * keyid.c (mk_datestr): Avoid trigraphs.
+       (fingerprint_from_pk): Cache the keyid in the pk.
+
+       * options.h: Add opt.with_fingerprint so that we know whether the
+       corresponding options was used.
+       * g10.c (main): Set it here.
+       * pkclist.c (check_signatures_trust): Always print fingerprint
+       when this option is used.  Mixed a minor memory leak.
 
-2000-10-11  Werner Koch  <wk@gnupg.org>
+       * status.c, status.h: New status INV_RECP.
+       * pkclist.c (build_pk_list): Issue this status.
 
-       * packet.h: Add features sig subpacket definition.
-       * parse-packet.c (dump_sig_subpkt,parse_one_sig_subpkt,
-       can_handle_critical): Implemented it here.
-       * build-packet.c (build_sig_subpkt): and here.
-       * keygen.c (keygen_add_std_prefs): Generate a features packet.
+2001-08-31  Werner Koch  <wk@gnupg.org>
+
+       * parse-packet.c (parse_key,parse_pubkeyenc)
+       (parse_signature): Return error on reading bad MPIs.
+       
+       * mainproc.c (check_sig_and_print): Always print the user ID even
+       if it is not bound by a signature.  Use the primary UID in the
+       status messages and encode them in UTF-8
+       * status.c (write_status_text_and_buffer): New.
+
+2001-08-30  Werner Koch  <wk@gnupg.org>
+
+       * packet.h (sigsubpkttype_t): Add SIGSUBPKT_FEATURES.
+       (PKT_public_key, PKT_user_id): Add a flag for it.
+       * parse-packet.c, build-packet.c: Add support for them.
+       * getkey.c (fixup_uidnode, merge_selfsigs): Set the MDC flags.
+       * keygen.c (add_feature_mdc): New.
+       (keygen_upd_std_prefs): Always set the MDC feature.
+       * keyedit.c (show_prefs): List the MDC flag
+       * pkclist.c (select_mdc_from_pklist): New.
+       * encode.c (encode_crypt, encrypt_filter): Test whether MDC
+       should be used.
+       * cipher.c (write_header): Set MDC use depending on the above test.
+       Print more status info.
+
+       * delkey.c (do_delete_key): Kludge to delete a secret key with no
+       public key available.
+
+       * ringedit.c (find_secret_keyblock_direct): New.
+       * getkey.c (seckey_available): Simplified.
+
+       * ringedit.c (cmp_seckey): Now compares the secret key against the
+       public key while ignoring all secret parts.
+       (keyring_search): Use a public key packet as arg.  Allow to search
+       for subnkeys
+       (search): Likewise. Changed all callers.
+       (find_secret_keyblock_bypk): New.
+       (find_secret_keyblock_byname): First locate the pubkey and then
+       find the correponding secret key.
+       * parse-packet.c (parse): Renamed pkttype arg to onlykeypkts and
+       changed code accordingly.  Changed all callers.
+       (search_packet): Removed pkttype arg.
+       * keyedit.c (keyedit_menu): First locate the public key and then
+       try to locate a secret key.
+
+       * ringedit.c (locate_keyblock_by_fpr): Removed.
+       (locate_keyblock_by_keyid): Removed.
+       (find_keyblock_bysk): Removed.
+
+       * sig-check.c (check_key_signature2): Print the keyid along with
+       the wrong sig class errors.
+
+2001-08-24  Werner Koch  <wk@gnupg.org>
+
+       * sign.c (sign_file): Stripped the disabled comment packet code.
+       (sign_file, sign_symencrypt_file): Moved common code to ..
+       (write_onepass_sig_packets): .. this new function.
+       (sign_file, clearsign_file, sign_symencrypt_file): Moved common
+       code to 
+       (write_signature_packets): this new function.
+       (write_signature_packets, make_keysig_packet)
+       (update_keysig_packet): Moved common code to 
+       (hash_uid, hash_sigclass_to_magic): these new functions
+       (sign_file, sign_symencrypt_file): Moved common code to 
+       (write_plaintext_packet):  this new function.
+
+2001-08-21  Stefan Bellon  <sbellon@sbellon.de>
+
+       * trustdb.c (query_trust_info): Changed trustlevel to signed int.
+       * g10.c [__riscos__]: Fixed handling of --use-agent --lock-multiple.
+
+2001-08-20  Werner Koch  <wk@gnupg.org>
+
+       * encr-data.c (decrypt_data): Keep track on whether we already
+       printed information about the used algorithm.
+       * mainproc.c (proc_encrypted): Removed the non-working IDEA hack
+       and print a message about the assumed algorithm.
+       * passphrase.c (passphrase_to_dek): Use the same algorithm as above.
+       (proc_symkey_enc): Print the algorithm, so that the user knows it
+       before entering the passphrase.
+       (proc_pubkey_enc, proc_pubkey_enc): Zero the DEK out.
+       * encode.c (encode_crypt, encrypt_filter): Ditto.
+
+       * g10.c: Allow for --sign --symmetric.
+       * sign.c (sign_and_symencrypt): New.
+
+       Applied patches from Stefan Bellon <sbellon@sbellon.de> to support
+       RISC OS.  Nearly all of these patches are identified by the
+       __riscos__ macro.
+       * compress.c: Added a couple of casts.
+       * g10.c [__riscos__]: Some patches and new options foo-file similar
+       to all foo-fd options.
+       * gpgv.c, openfile.c, ringedit.c, tdbio.c: Minor fixes.  Mainly
+       replaced hardcoded path separators with EXTSEP_S like macros.  
+       * passprase.c [__riscos__]: Disabled agent stuff
+       * trustdb.c (check_trust): Changed r_trustlevel to signed int to
+       avoid mismatch problems in pkclist.c
+       * pkclist.c (add_ownertrust): Ditto.
+       * plaintext.c (handle_plaintext) [__riscos__]: Print a note when
+       file can't be created.
+       * options.h [__riscos__]: Use an extern unless included from the
+       main module.
+       * signal.c (got_fatal_signal) [__riscos__]: Close all files.
        
-2000-10-09  Werner Koch  <wk@gnupg.org>
+2001-08-14  Werner Koch  <wk@gnupg.org>
+
+       * keygen.c (ask_algo): New arg r_usage.  Allow for RSA keys.
+       (gen_rsa): Enabled the code.
+       (do_create): Enabled RSA branch.
+       (parse_parameter_usage): New.
+       (proc_parameter_file): Handle usage parameter.
+       (read_parameter_file): Ditto.
+       (generate_keypair): Ditto.
+       (generate_subkeypair): Ditto.
+       (do_generate_keypair): Ditto.
+       (do_add_key_flags): New.
+       (keygen_add_std_prefs): Use the new function.
+       (keygen_add_key_flags_and_expire): New.
+       (write_selfsig, write_keybinding): Handle new usage arg.
+       * build-packet.c (build_sig_subpkt): Make sure that key flags go
+       into the hashed area.
+       
+       * keygen.c (write_uid): Initialize the reference cunter.
+
+       * keyedit.c (keyedit_menu): No more need to update the trustdb for
+       preferences.  Added calls to merge keblock.
+
+       * kbnode.c (dump_kbnode): Print some more flags.
+
+2001-08-10  Werner Koch  <wk@gnupg.org>
+
+        Revamped the preference handling.
+
+       * packet.h (prefitem_t, preftype_t): New.
+       (PKT_public_key): Added a uid field.
+       (PKT_user_id): Added field to store preferences and a reference
+       counter.
+       * parse-packet.c (parse_user_id,parse_photo_id): Initialize them
+       * free-packet.c (free_user_id): Free them.
+       (copy_user_id): Removed.
+       (scopy_user_id): New. 
+       (cmp_user_ids): Optimized for identical pointers.
+       (release_public_key_parts): Release the uid.
+       (copy_public_key_with_new_namehash): Removed.
+       (copy_prefs): New.
+       * keyedit.c (menu_adduid): Use the new shallow copy user id.
+       (show_prefs): Adjusted implementation.
+       (keyedit_menu): No more need to update the trustdb after changing
+       preferences.
+       * getkey.c (fixup_uidnode): Store preferences.
+       (find_by_name): Return a user id packet and remove namehash stuff.
+       (lookup): Removed the unused namehash stuff.
+       (finish_lookup): Added foundu arg.
+       (pk_from_block): Removed the namehash arg and changed all callers.
+       (merge_selfsigs): Copy prefs to all keys.
+       * trustdb.c (get_pref_data): Removed.
+       (is_algo_in_prefs): Removed.
+       (make_pref_record): Deleted and removed all class.
+       * pkclist.c (select_algo_from_prefs): Adjusted for the new
+       preference implementation.
+       * pubkey-enc.c (is_algo_in_prefs): New.
+       (get_it): Use that new function. 
+
+2001-08-09  Werner Koch  <wk@gnupg.org>
+
+       * build-packet.c (build_sig_subpkt): Fixed calculation of
+       newarea->size.
+
+       * g10.c (main): New option "--preference-list"
+       * keyedit.c (keyedit_menu): New commands "setpref" and "updpref".
+       (menu_set_preferences): New.
+       * keygen.c (keygen_set_std_prefs): New.
+       (set_one_pref): New.
+       (check_zip_algo): New.
+       (keygen_get_std_prefs): New.
+       (keygen_upd_std_prefs): New
+       (keygen_add_std_prefs): Move the pref setting code into the above fnc.
+       * build-packet.c (build_sig_subpkt): Updated the list of allowed
+       to update subpackets.
+
+2001-08-08  Werner Koch  <wk@gnupg.org>
+
+       * packet.h (subpktarea_t): New.
+       (PKT_signature): Use that type for hashed_data and unhashed_data and
+       removed the _data prefix from those fields.  Changed all users.
+       * parse-packet.c (parse_signature): Changed allocation for that.
+       (parse_sig_subpkt): Changed declaration
+       (enum_sig_subpkt): Ditto and changed implementation accordingly.
+       * free-packet.c (cp_subpktarea): Renamed from cp_data_block and
+       adjusted implementation. Changed caller.
+       * sig-check.c (mdc_kludge_check): Adjusted the hashing.
+       (do_check): Ditto.
+       * sign.c (sign_file, clearsign_file, make_keysig_packet,
+       update_keysig_packet): Ditto.
+       * build-packet.c (build_sig_subpkt): Partial rewrite.
+       (find_subpkt): Adjusted and made static.
+       (delete_sig_subpkt): Adjusted.
+       (do_signature): Ditto.
+
+       * keygen.c (ask_keysize): Do not print the notes about suggested
+       key sizes if just a DSA key is generated.
+
+       * trustdb.c (add_ultimate_key): s/log_error/log_info/ for
+       duplicated inserted trusted keys.
+
+2001-08-07  Werner Koch  <wk@gnupg.org>
+
+       * sign.c (sleep): Redefine for W32.
+
+       * g10.c, options.h: Set new flag opt.no_homedir_creation when
+       --no-options is given.
+       * openfile.c (try_make_homedir): Don't create the homedir in that case.
+
+2001-08-03  Werner Koch  <wk@gnupg.org>
+
+       * armor.c (armor_filter): Removed the default comment string
+       because it could get us in trouble due to translations using non
+       ascii characters.
+
+2001-08-01  Werner Koch  <wk@gnupg.org>
+
+       * keylist.c (list_keyblock_print): Do not list revoked UIDs unless
+       in verbose mode and we do no signature listing.
+
+       * getkey.c (finish_lookup): Skip subkeys which are not yet valid.
+       * g10.c, options.h: New option --ignore-valid-from.
+
+       * sign.c (make_keysig_packet): Added new sigversion argument to
+       allow the caller to force generation of required signature
+       version. Changed all callers. Suggested by Thomas Roessler.
+
+       * keyedit.c (sign_uids): Force v4 signature generation for local
+       sigs.  Removed the check for local signature and pre-v4 keys.
+
+2001-07-27  Werner Koch  <wk@gnupg.org>
+
+       * keyedit.c (sign_uids): Check that we are not trying to to a
+       lsign with a pre-v4 key.  Bug noticed by Thomas Roessler.
+
+2001-07-26  Werner Koch  <wk@gnupg.org>
+
+       * parse-packet.c (parse_photo_id): Reset all variables.
+       * getkey.c (merge_selfsigs_main): Removed checks on PHOTO_ID
+       because this is handled identically to a user ID.
+
+2001-07-06  Werner Koch  <wk@gnupg.org>
+
+       * cipher.c (write_header): Don't use MDC with --rfc1991.  Suggested
+       by disastry@saiknes.lv.
+
+2001-07-05  Werner Koch  <wk@gnupg.org>
+
+       * g10.c, options.h: New option --preserve-permissions.
+       * ringedit.c (add_keyblock_resource): Use it here
+       (keyring_copy): and here.
+
+       * trustdb.c (verify_own_keys): Be more silent on --quiet.
+       Suggested by Thomas Roessler.
+       * sig-check.c (check_key_signature2): Ditto.
+       * mainproc.c (proc_encrypted, proc_tree): Ditto
+       * getkey.c (lookup): Ditto.
+
+2001-07-04  Werner Koch  <wk@gnupg.org>
+
+       * ringedit.c (add_keyblock_resource): Restore filename in case of error.
+
+2001-06-25  Werner Koch  <wk@gnupg.org>
 
-       * keygen.c (do_generate_keypair): Removed the keyblock locking.
+       * kbnode.c (dump_kbnode): Print the signature timestamp.
 
-       * ringedit.c (enum_keyblocks): Replaced by ...
-       (enum_keyblocks_begin): New.
-       (enum_keyblocks_next): New.
-       (enum_keyblocks_end): New. And changed all callers.
+       * keyedit.c (keyedit_menu): New menu point "primary".
+       (change_primary_uid_cb): New.
+       (menu_set_primary_uid): New.
+       * sign.c (update_keysig_packet): New.
+       * build-packet.c (build_sig_subpkt): Put the primary UID flag into
+       the hashed area. Allow update of some more packets.
+
+2001-06-15  Werner Koch  <wk@gnupg.org>
+
+       * getkey.c (merge_selfsigs): Exit gracefully when a secret key is
+       encountered.  May happen if a secret key is in public keyring.
+       Reported by Francesco Potorti.
        
-       * import.c (import_one): Removed keyblock locking becuase this is
-       now done inside of insert_keyblock().  Removed get_keyblock_handle
-       because insert_keyblock() now decides what is the default keyring.
-       (import_secret_one): Ditto.
-       (import_revoke_cert): Ditto.
-       (import_one): Ditto.
-
-Fri Oct  6 14:29:16 CEST 2000  Werner Koch  <wk@openit.de>
-
-        Started to rework the whole getkey/ringedit stuff to make
-        it simpler, correcter and faster. 
-
-        * parse-packet.c (parse_packet): Add a 3rd arg to return the filepos.
-        Changed all callers.
-        * getkey.c (classify_user_id): Add new mode 21.
-        (find_by_fpr): Find using this new mode.
-        (get_seckey_byname): New arg to return the context. Changed all
-        callers.
-        * keyid.c (unified_fingerprint_from_pk): New.
-        (unified_fingerprint_from_sk): New.
-        * ringedit.c (find_keyblock_bypk): Changed to use the unified 
-        fingerprint for lookup.  I can't see a reason why we did compare
-        the entire public key.
-        (find_keyblock_bysk): Ditto.
-        (search,cmp_pubkey,cmp_seckey): Removed.
-        (keyring_search, do_kbxf_search): Removed.
-        (locate_keyblock_by_fpr,locate_keyblock_by_keyid): Removed.
-        (find_keyblock_byname): Removed use o search function.
-        (find_secret_keyblock_byname): Ditto.
-        (merge_public_with_secret): Fixed removing subkeys.
-        (premerge_public_with_secret): New.
-
-        * ringedit.c: Removed all GDBM support
-
-        * ringedit.c (read_keyblock): Removed.
-        * ringedit.c (find_keyblock_byname,find_secret_keyblock_byname,
-        find_keyblock_bypk,find_keyblock_bysk): Moved from here to ....
-        * getkey.c: ... here. Changed first arg to return a keyblock and
-        changed all callers to merge the old read_keyblock() with these
-        functions.       
-
-Wed Oct  4 13:16:18 CEST 2000  Werner Koch  <wk@openit.de>
-
-        * getkey.c (merge_selfsigs_main): Fixed for v3 keys.
-
-        * sign.c (hash_for): New arg to take packet version in account. Changed
-        all callers.
-        (write_one_sig): New. Moved the shared code from sign_file and
-        clearsign_file to here.
-        * skclist.c (build_sk_list): Fixed usage check.
-        * pkclist.c (build_pk_list): Ditto.
-
-        * encode.c (encode_crypt): Removed duplicated stuff by using
-        encrypt_filter as sign.c already did.  Removed already disabled
-        comment-packet code.
-
-Mon Sep 18 16:35:45 CEST 2000  Werner Koch  <wk@openit.de>
-
-        * parse-packet.c (dump_sig_subpkt): Dump key flags.
-        (parse_one_sig_subpkt,can_handle_critical): Add KeyFlags support.
-        * build-packet.c (build_sig_subpkt): Ditto.
+2001-06-12  Werner Koch  <wk@gnupg.org>
 
-        * g10.c: New option --allow-freeform-uid. By Jeroen C. van Gelderen.
-        * keygen.c (ask_user_id): Implemented here.
+       * getkey.c (compare_name): Use ascii_memistr(), ascii_memcasecmp()
+       * keyedit.c (keyedit_menu): Use ascii_strcasecmp().
+       * armor.c (radix64_read): Use ascii_toupper().  
+       * ringedit.c (do_bm_search): Ditto.
+       * keygen.c (read_parameter_file): Ditto.
+       * openfile.c (CMP_FILENAME): Ditto.
+       * g10.c (i18n_init): We can now use just LC_ALL.
 
-        * parse-packet.c (dump_sig_subpkt): Print info about the ARR.
+2001-05-29  Werner Koch  <wk@gnupg.org>
 
-        * openfile.c (overwrite_filep): Always return okay if the file is
-        called /dev/null. 
-        (make_outfile_name): Add ".sign" to the list of know extensions.
-        (open_sigfile): Ditto.
+       * keygen.c (generate_subkeypair): Print a warning if a subkey is
+       created on a v3 key. Suggested by Brian M. Carlson.
 
-        * getkey.c: Large parts rewritten to have a better sub key selection
-        and handle some meta information from signatures more correctly.
-        (get_primary_seckey): Removed.
-        * seckey_cert.c (do_check): Set main keyid from the data in the sk.
-        * free-packet.c (copy_public_parts_to_secret_key): New.
-        * sig-check.c (check_key_signature2): Enabled shortcut for already
-        checked signatures.
-        * keydb.h: New macros IS_xxx_SIG, IS_xxx_REV.
-        * misc.c (openpgp_pk_algo_usage): New.
-        * packet.h: New field req_uage and do not use pubkey_usage anymore
-        to request a specific usage.  Changed at all places.
-        * keyid.c (keyid_from_sk): Cache the keyid in the sk
+2001-05-27  Werner Koch  <wk@gnupg.org>
 
-        * passphrase.c (hash_passphrase): Removed funny assert.  Reported by
-        David Mathog.
+       * keyid.c (get_lsign_letter): New.
+       * keylist.c (list_keyblock_colon): Use it here.
+       * mainproc.c (list_node): and here.
 
-        * keyedit.c (keyedit_menu): Allow "debug" on secret keys.
+       * getkey.c, packet.h, free-packet.c: Removed that useless key
+       created field; I dunno why I introducded this at all - the
+       creation time is always bound to the key packet and subject to
+       fingerprint calculation etc.
 
-        * keygen.c (keygen_add_std_prefs): Changed order of preferences to
-        twofish, cast5, blowfish.
+       * getkey.c (fixup_uidnode): Add keycreated arg and use this
+       instead of the signature timestamp to calculate the
+       help_key_expire.  Bug reported by David R. Bergstein.
+       (merge_selfsigs_main): Correct key expiration time calculation.
+       (merge_selfsigs_subkey): Ditto.
 
-        * gpg.c: The --trusted-key option is back.
-        * trustdb.c (verify_own_key): Handle this option.
-        (add_ultimate_key): Moved stuff from verify_own_key to this new func.
-        (register_trusted_key): New.
+2001-05-25  Werner Koch  <wk@gnupg.org>
 
-        * openfile.c (try_make_homedir): Changes for non-Posix systems.
-        * gpg.c (main): Take the default homedir from macro.
+       * revoke.c (gen_revoke): Add a cast to a tty_printf arg.
+       * delkey.c (do_delete_key): Ditto.
+       * keyedit.c (print_and_check_one_sig): Ditto.
+       (ask_revoke_sig): Ditto.
+       (menu_revsig): Ditto.
+       (check_all_keysigs): Removed unused arg.
 
-        * encode.c (encode_simple, encode_crypt): Fix for large files.
-        * sign.c (sign_file): Ditto.
+2001-05-23  Werner Koch  <wk@gnupg.org>
 
-        * gpg.c (main): Don't set --quite along with --no-tty.  By Frank Tobin.
+       * g10.c (opts): Typo fix by Robert C. Ames.
 
-        * misc.c (disable_core_dump): Don't display a warning here but a return
-        a status value and ...
-        * gpg.c (main): ...print warning here. Suggested by Sam Roberts.
+2001-05-06  Werner Koch  <wk@gnupg.org>
 
-        * misc.c (print_pubkey_algo_note): Do not print the RSA notice.
-        * sig-check.c (do_signature_check): Do not emit the RSA status message.
-        * pubkey-enc.c (get_session_key): Ditto.
+       * revoke.c: Small typo fix
 
-        * ringedit.c (cmp_seckey): Fix for v4 RSA keys.
-        * seckey-cert.c (do_check): Workaround for PGP 7 bug.
+2001-05-04  Werner Koch  <wk@gnupg.org>
 
-        * pkclist.c (algo_available): Removed hack to disable Twofish.
+       * passphrase.c (passphrase_clear_cache): Shortcut if agent usage
+       is not enabled.
 
-        * gpg.c (main): Default S2K algorithms are now SHA1 and CAST5 - this
-        should solve a lot of compatibility problems with other OpenPGP
-        apps because those algorithms are SHOULD and not optional.  The old
-        way to force it was by using the --openpgp option whith the drawback 
-        that this would disable a couple of workarounds for PGP.
+2001-05-01  Werner Koch  <wk@gnupg.org>
+
+       * passphrase.c (writen): Replaced ssize_t by int.  Thanks to 
+       to Robert Joop for reporting that SunOS 4.1.4 does not have it.
+
+2001-04-28  Werner Koch  <wk@gnupg.org>
+
+       * getkey.c (merge_public_with_secret): pkttype was not set to subkey.
+
+2001-04-27  Werner Koch  <wk@gnupg.org>
+
+       * skclist.c (build_sk_list): Changed one log_debug to log_info.
+
+2001-04-25  Werner Koch  <wk@gnupg.org>
+
+       * keyedit.c (show_prefs): Add a verbose mode.
+       (show_key_with_all_names): Pass verbose flag for special value of
+       with_pref.
+       (keyedit_menu): New command "showpref"
+       (show_key_with_all_names): Mark revoked uids and the primary key.
+
+2001-04-24  Werner Koch  <wk@gnupg.org>
+
+       * getkey.c (get_primary_uid): Return a different string in case of
+       error and made it translatable.
+
+       * build-packet.c (do_secret_key): Ugly, we wrote a zero
+       instead of the computed ndays.  Thanks to M Taylor for complaining
+       about a secret key import problem.
+
+2001-04-23  Werner Koch  <wk@gnupg.org>
+
+       * hkp.c (hkp_ask_import): Allow to specify a port number for the 
+       keyserver.  Add a kudge to set the no_shutdown flag.
+       (hkp_export): Ditto.
+       * options.skel: Document the changes 
+
+2001-04-20  Werner Koch  <wk@gnupg.org>
+
+       * options.skel: Add some more comments.
+
+2001-04-19  Werner Koch  <wk@gnupg.org>
+
+       * keyid.c (mk_datestr): New.  Handles negative times.  We must do
+       this because Windoze segvs on negative times passed to gmtime().
+       Changed all datestr_from function to use this one.
+
+       * keyid.c, keyid.h (colon_strtime): New. To implement the
+       fixed-list-mode.
+       (colon_datestr_from_pk): New.
+       (colon_datestr_from_sk): New.
+       (colon_datestr_from_sig): New.
+       * keylist.c (list_keyblock_colon): Use these functions here.
+       * mainproc.c (list_node): Ditto.
+
+2001-04-18  Werner Koch  <wk@gnupg.org>
+
+       * openfile.c (open_sigfile): Fixed the handling of ".sign".
+       * mainproc.c (proc_tree): Use iobuf_get_real_fname.
+       Both are by Vincent Broman.
+
+2001-04-14  Werner Koch  <wk@gnupg.org>
+
+       * getkey.c (fixup_uidnode): Removed check for !sig which is
+       pointless here.  Thanks to Jan Niehusmann.
+
+2001-04-10  Werner Koch  <wk@gnupg.org>
+
+       * sig-check.c (check_key_signature2): Use log_info instead of
+       log_error so that messed up keys do not let gpg return an error.
+       Suggested by Christian Kurz.
+
+       * getkey.c (merge_selfsigs_main): Do a fixup_uidnode only if we
+       have both, uid and sig.  Thanks to M Taylor.
+
+2001-04-05  Werner Koch  <wk@gnupg.org>
+
+       * armor.c (unarmor_pump_new,unarmor_pump_release): New.
+       (unarmor_pump): New. 
+       * pipemode.c (pipemode_filter): Use the unarmor_pump to handle
+       armored or non-armored detached signatures.  We can't use the
+       regular armor_filter becuase this does only chack for armored
+       signatures the very first time.  In pipemode we may have a mix of
+       armored and binary detached signatures.
+       * mainproc.c (proc_tree): Do not print the "old style" notice when
+       this is a pipemode processes detached signature.
+       (proc_plaintext): Special handling of pipemode detached sigs.
+
+       * packet.h (CTRLPKT_PLAINTEXT_MARK): New.
+       * parse-packet.c (create_gpg_control): New.
+       * kbnode.c (dump_kbnode): Support it here.
+       * mainproc.c (check_sig_and_print): Fixed the check for bad
+       sequences of multiple signatures.
+       (proc_plaintext): Add the marker packet.
+       (proc_tree): We can now check multiple detached signatures.
+
+2001-04-02  Werner Koch  <wk@gnupg.org>
+
+       The length of encrypted packets for blocksizes != 8 was not
+       correct encoded.  I think this is a minor problem, because we
+       usually use partial length packets.  Kudos to Kahil D. Jallad for
+       pointing this out.
+       * packet.h: Add extralen to PKT_encrypted.
+       * cipher.c (write_header): Set extralen.
+       * build-packet.c (do_encrypted): Use extralen instead of const 10.
+       (do_encrypted_mdc): Ditto.
+       * parse-packet.c (parse_encrypted): Set extralen to 0 because we
+       don't know it here.
+
+2001-03-30  Werner Koch  <wk@gnupg.org>
+
+       * getkey.c (premerge_public_with_secret): Changed wording an add
+       the keyID to the info message.
+
+2001-03-29  Werner Koch  <wk@gnupg.org>
+
+       * getkey.c (premerge_public_with_secret): Use log_info instead of
+       log_error when no secret key was found for a public one.
+       Fix the usage if the secret parts of a key are not available.
+
+       * openfile.c (ask_outfile_name): Trim spaces.
+       (open_outfile): Allow to enter an alternate filename.  Thanks to
+       Stefan Bellon.
+       * plaintext.c (handle_plaintext): Ditto.
+
+2001-03-28  Werner Koch  <wk@gnupg.org>
+
+       * mainproc.c (do_check_sig): Allow direct key and subkey
+       revocation signature.
+       * sig-check.c (check_key_signature2): Check direct key signatures.
+       Print the signature class along with an error.
+
+2001-03-27  Werner Koch  <wk@gnupg.org>
+
+       * packet.h: Add a missing typedef to an enum.  Thanks to Stefan Bellon.
+
+       * g10.c: New option --no-sig-create-check.
+       * sign.c (do_sign): Implement it here.
+       * g10.c: New option --no-sig-cache.
+       * sig-check.c (check_key_signature2): Implement it here.
+       (cache_selfsig_result): and here.
+
+       * keylist.c (list_keyblock): Removed debugging stuff.
+
+       * getkey.c (cache_public_key): Made global.
+       * keygen.c (write_selfsig, write_keybinding): Cache the new key.
+
+       * getkey.c (key_byname): Add new arg secmode and changed all
+       callers to request explicitly the mode.  Deriving this information
+       from the other supplied parameters does not work if neither pk nor
+       sk are supplied.
+
+2001-03-25  Werner Koch  <wk@gnupg.org>
+
+       * packet.h (ctrlpkttype_t): New.
+       * mainproc.c (add_gpg_control,proc_plaintext,proc_tree): Use the
+       new enum values.
+       * pipemode.c (make_control): Ditto.
+       * armor.c (armor_filter): Ditto.
+
+2001-03-24  Werner Koch  <wk@gnupg.org>
+
+       * sign.c (do_sign): Verify the signature right after creation.
+
+2001-03-23  Werner Koch  <wk@gnupg.org>
+
+       * status.c, status.h (STATUS_UNEXPECTED): New.
+       * mainproc.c (do_proc_packets): And emit it here.
+
+2001-03-21  Werner Koch  <wk@gnupg.org>
+
+       * status.c: Add sys/types.h so that it runs on Ultrix.  Reported
+       by Georg Schwarz.x
+
+       * build-packet.c (build_sig_subpkt): Fixed generaton of packet
+       length header in case where 2 bytes headers are needed.  Thanks to
+       Piotr Krukowiecki.
+
+2001-03-19  Werner Koch  <wk@gnupg.org>
+
+       * g10.c (main): the default keyring is no always used unless
+       --no-default-keyring is given.  
+
+       * ringedit.c (add_keyblock_resource): invalidate cache after file
+       creation.
+
+2001-03-15  Werner Koch  <wk@gnupg.org>
+
+       * keygen.c (ask_algo): Changed the warning of the ElGamal S+E Algo.
+
+       * keylist.c (print_capabilities): New.
+       (list_keyblock_colon): and use it here.
+
+2001-03-13  Werner Koch  <wk@gnupg.org>
+
+       * main.c, options.h: New option --fixed_list_mode.
+       * keylist.c (list_keyblock_colon): use it here.
+
+       * getkey.c (merge_keys_and_selfsig): Divert merging of public keys
+       to the function used in key selection..
+       * keylist.c (is_uid_valid): Removed.
+       (list_keyblock): Splitted into ..
+       (list_keyblock_print, list_keyblock_colon): .. these.
+       functions.  Changed them to use the flags set in the key lookup code.
+       (reorder_keyblock): New, so that primary user IDs are listed first.
+
+       * ringedit.c (keyring_copy): flush the new iobuf chaces before
+       rename or remove operations.  This is mainly needed for W32.
 
-        * gpg.c: New option --merge-only.  Suggested by Brendan O'Dea.
-        * import.c (import_one): Implemented it here.
-        (import_secret_one): Ditto.
-        (print_stats): and give some stats.
+       * hkp.c [HAVE_DOSISH_SYSTEM]: Removed the disabled code because we
+       have now W32 socket support in ../util/http.c
 
-        * gpg.c: New option --try-all-secrets on suggestion from
-        Matthias Urlichs.
-        * pubkey-enc.c (get_session_key): Quite easy to implement here.
+       * skclist.c (key_present_in_sk_list): New.
+       (is_duplicated_entry): New.
+       (build_sk_list): Check for duplicates and do that before unlocking.
 
-Mon Aug 21 17:59:17 CEST 2000  Werner Koch  <wk@openit.de>
+2001-03-12  Werner Koch  <wk@gnupg.org>
 
-        * gpg.c: New option --use-agent
+       * armor.c (parse_header_line): Removed double empty line check.
+       (parse_header_line): Replaced trim_trailing_ws with a counting
+       function so that we can adjust for the next read.
+
+       * options.skel: Fixed 3 typos. By Thomas Klausner. Replaced the
+       keyserver example by a better working server. 
+
+       * parse-packet.c (parse_symkeyenc): Return Invalid_Packet on error.
+       (parse_pubkeyenc): Ditto.
+       (parse_onepass_sig): Ditto.
+       (parse_plaintext): Ditto.
+       (parse_encrypted): Ditto.
+       (parse_signature): Return error at other places too.
+       (parse_key): Ditto.
+       * g10.c (main): Set opt.list_packets to another value when invoked
+       with the --list-packets command.
+       * mainproc.c (do_proc_packets): Don's stop processing when running
+       under --list-packets command.
+
+       * signal.c (do_sigaction): Removed.
+       (init_one_signal): New to replace the above.  Needed to support
+       systems without sigactions. Suggested by Dave Dykstra.
+       (got_fatal_signal,init_signals): Use the above here. 
+       (do_block): Use sigset() if sigprocmask() is not available.
+
+       * armor.c (parse_hash_header): Test on TIGER192, which is the
+       correct value as per rfc2440.  By Edwin Woudt.
+
+2001-03-08  Werner Koch  <wk@gnupg.org>
+
+       * misc.c: Include time.h. By James Troup.
+
+       * getkey.c: Re-enabled the unknown user Id and PK caches and
+       increased their sizes.
+
+       * getkey.c (merge_selfsigs_main): Set expire date and continue
+       processing even if we found a revoked key.
+       (merge_selfsigs_subkeys): Ditto.
+       
+       * packet.h: Add an is_revoked flag to the user_id packet.
+       * getkey.c (fixup_uidnode): Set that flag here.
+       (merge_selfsigs_main): Fix so that the latest signature is used to
+       find the self-signature for an UID.
+       * parse-packet.c (parse_user_id): Zero out all fields.
+       * mainproc.c (check_sig_and_print): Print the primary user ID
+       according the the node flag and then all other non-revoked user IDs.
+       (is_uid_revoked): Removed; it is now handled by the key selection code.
+       
+       Changed the year list of all copyright notices.
+       
+2001-03-07  Werner Koch  <wk@gnupg.org>
+
+       * getkey.c (finish_lookup): Print an info message only in verbose mode.
+
+2001-03-05  Werner Koch  <wk@gnupg.org>
+
+       * packet.h: Replaced sigsubpkt_t value 101 by PRIV_VERIFY_CACHE.
+       We have never used the old value, so we can do this without any harm.
+       * parse-packet.c (dump_sig_subpkt): Ditto.
+       (parse_one_sig_subpkt): Parse that new sub packet.
+       * build-packet.c (build_sig_subpkt): Removed the old one from the
+       hashed area.
+       (delete_sig_subpkt): New.
+       (build_sig_subpkt): Allow an update of that new subpkt.
+       * sig-check.c (check_key_signature2): Add verification caching
+       (cache_selfsig_result): New.
+       * export.c (do_export_stream): Delete that sig subpkt before exporting.
+       * import.c (remove_bad_stuff): New.
+       (import): Apply that function to all imported data 
+
+2001-03-03  Werner Koch  <wk@gnupg.org>
+
+       * getkey.c: Introduced a new lookup context flag "exact" and used 
+       it in all place where we once used primary.
+       (classify_user_id2): Replaced the old function and add an extra
+       argument to return whether an exact keyID has been requested.
+       (key_byname): Removed the unused ctx.primary flag
+       (get_seckey_byname2): Ditto.
+       (finish_lookup): Changed debugging output.
+
+2001-03-02  Werner Koch  <wk@gnupg.org>
+
+       * keylist.c (list_one): Remove the merge key calls. 
+
+2001-03-01  Werner Koch  <wk@gnupg.org>
+
+       * getkey.c (finish_lookup): Don't use it if we no specific usage
+       has been requested.
+       (merge_selfsigs_main): fix UID only if we have an signature.
+       (lookup): Return UNU_PUBKEY etc. instead of NO_PUBKEY if we found
+       a key but the requested usage does not allow this key.
+       * import.c (import_one): Take UNU_PUBKEY into account.
+       * mainproc.c (list_node): Ditto.
+       * keylist.c (list_keyblock): Ditto.
+       * keyedit.c (print_and_check_one_sig): Ditto. 
+
+2001-02-09  Werner Koch  <wk@gnupg.org>
+
+       * delkey.c (delete_key): Removed that silly assert which rendered
+       the whole new stuff meaningless.
+
+2001-02-08  Werner Koch  <wk@gnupg.org>
+
+       * getkey.c (key_byname): It can happen that we have both, sk and pk
+       NULL, fix for that.
+
+       * parse-packet.c (parse_one_sig_subpkt): Add support for
+       primary_uid and key_flags.
+       (can_handle_critical): Ditto
+
+       * parse-packet.c (parse_encrypted): Fixed listing of pktlen for
+       MDC packets.
+
+       * getkey.c: Backported the version of this file from gpg 1.1. this
+       involved some changes in other files too.
+       * parse-packet.c (parse_key): Clear req_usage.
+       * skclist.c (build_sk_list): Use req_usage to pass the usage
+       information to the lookup function.
+       * pkclist.c (build_pk_list): Ditto.
+       * free-packet.c (copy_public_parts_to_secret_key): New.
+       * keydb.h: Add IS_* macros to check the sig_class.
+       * misc.c (openpgp_cipher_test_algo): New.
+       (openpgp_pk_test_algo): New.
+       (openpgp_pk_algo_usage): New.
+       (openpgp_md_test_algo): New.
+       * packet.h: Add a few fields to PKT_{public,secret}_key and
+       PKT_user_id.
+       * seckey-cert.c (do_check): Use the new main_keyid field.
+
+2001-02-04  Werner Koch  <wk@gnupg.org>
+
+       * encr-data.c (decrypt_data): Catch error when we had problems to
+       parse the encrypted packet. By Timo.
+
+2001-01-29  Werner Koch  <wk@gnupg.org>
+
+       * g10.c (main): --batch does now set nogreeting.
+
+       * delkey.c (do_delete_key): Fixed delete-both functionality.
+
+2001-01-22  Werner Koch  <wk@gnupg.org>
+
+       * g10.c: New command --delete-secret-and-public-key.
+       * delkey.c (delete_key): Add new arg allow_both.
+       (do_delete_key): Move most stuff from above to this new function.
+
+2001-01-12  Werner Koch  <wk@gnupg.org>
+
+       * passphrase.c (passphrase_to_dek): Use MD5 when IDEA is installed
+       and we have no S2K.
+       * mainproc.c (proc_encrypted): Likewise
+
+2001-01-11  Werner Koch  <wk@gnupg.org>
+
+       * sig-check.c (do_check): Print the signature key expire message
+       only in verbose mode and added the keyID.
+
+2001-01-09  Werner Koch  <wk@gnupg.org>
+
+       * status.c, status.h: New status USERID_HINT. 
+       (write_status_text): Replace LF and CR int text by C-escape sequence.
+
+       * passphrase.c (passphrase_to_dek): Fixed the NEED_PASSPHRASE
+       output.  It does now always print 2 keyIDs.  Emit the new
+       USERID_HINT.
+
+2001-01-08  Werner Koch  <wk@gnupg.org>
+
+       * g10.c, options.h: New option --no-expensive-trust-checks.
+       * keylist.c (list_keyblock): Act on this option.
+
+2001-01-04  Werner Koch  <wk@gnupg.org>
+
+       * g10.c (main): Set homedir only in the pre-parsing phase and
+       replace backslashes in the W32 version.
+
+2001-01-03  Werner Koch  <wk@gnupg.org>
+
+       * status.c, status.h : New status KEY_CREATED
+       * keygen.c (do_generate_keypair,generate_subkeypair): Emit it.
+
+2000-12-28  Werner Koch  <wk@gnupg.org>
+
+       * signal.c (got_fatal_signal): Remove lockfiles here because the
+       atexit stuff does not work due to the use of raise. Suggested by
+       Peter Fales.
+       * gpgv.c (remove_lockfiles): New stub.
+       
+2000-12-19  Werner Koch  <wk@gnupg.org>
+
+       * status.c, status.h (cpr_get_no_help): New.
+       * keyedit.c (keyedit_menu): Use it here because we have our own
+       help list here.
+
+2000-12-18  Werner Koch  <wk@gnupg.org>
+
+       * mainproc.c (print_failed_pkenc): Don't print the sometimes
+       confusing message about unavailabe secret key.  Renamed ...
+       (print_pkenc_list): ... to this and introduced failed arg.
+       (proc_encrypted): Print the failed encryption keys and then
+       the one to be used.
+       (proc_pubkey_enc): Store also the key we are going to use.
+
+       * mainproc.c (check_sig_and_print): Don't list revoked user IDs.
+       (is_uid_revoked): New.
+
+2000-12-08  Werner Koch  <wk@gnupg.org>
+
+       * pipemode.c: Made the command work.  Currently only for
+       non-armored detached signatures.
+       * mainproc.c (release_list): Reset the new pipemode vars.
+       (add_gpg_control): Handle the control packets for pipemode
+       * status.c, status.h: New stati {BEGIN,END}_STREAM.
+
+2000-12-07  Werner Koch  <wk@gnupg.org>
+
+       * g10.c: New option --allow-secret-key-import.
+       * import.c (import_keys,import_keys_stream): Honor this option.
+       (import): New arg allow_secret and pass that arg down to ...
+       (import_secret_one): to this and print a warning if secret key
+       importing is not allowed.
+
+2000-12-05  Werner Koch  <wk@gnupg.org>
+
+       * cipher.c (cipher_filter): Moved the end_encryption status ...
+       * encode.c (encode_simple,encode_crypt): to here
+       * sign.c (sign_file): and here.
+
+       * status.c (mywrite): Removed.
+       (get_status_string): Removed the LFs from the strings.
+       (set_status_fd,is_status_enabed,write_status_text,
+       write_status_buffer): Replaced all mywrite by stdio calls and use
+       fdopen to create a strem.  This is needed to make things smoother
+       in the W32 version.
+
+2000-12-04  Werner Koch  <wk@gnupg.org>
+
+       * import.c (merge_blocks): Increment n_sigs for revocations.
+
+2000-11-30  Werner Koch  <wk@gnupg.org>
+
+       * g10.c (main): Use iobuf_translate_file_handle for all options
+       with filehandles as arguments.  This is function does some magic
+       for the W32 API.
+
+       * verify.c (verify_signatures): Add a comment rant about the
+       detached signature problem.
+       * mainproc.c (proc_tree): Issue an error if a detached signature
+       is assumed but a standard one was found.
+       * plaintext.c (hash_datafiles): Don't fall back to read signature
+       from stdin.
+       * openfile.c (open_sigfile): Print verbose message only if the
+       file could be accessed.
+
+2000-11-24  Werner Koch  <wk@gnupg.org>
+
+       * passphrase.c [HAVE_DOSISH_SYSTEM]: Disabled all the agent stuff.
+
+2000-11-16  Werner Koch  <wk@gnupg.org>
+
+        * g10.c: New option --use-agent
         * passphrase.c (agent_open,agent_close): New.
         (agent_get_passphrase,agent_clear_passphrase): New.
+       (passphrase_clear_cache): New.
         (passphrase_to_dek): Use the agent here.
-        * seckey-cert.c (do_check): Clear wrong cached passphrases.
+       * seckey-cert.c (do_check): Clear cached passphrases.
 
-Fri Aug 18 14:27:14 CEST 2000  Werner Koch  <wk@openit.de>
+2000-11-15  Werner Koch  <wk@gnupg.org>
 
-  * status.c (do_get_from_fd): Ooops, we used fd instead of opt.command_fd.
-  Thanks to Michael Tokarev.
+       * status.c (write_status_text): Moved the big switch to ...
+       (get_status_string): ... new function.
+       (write_status_buffer): New.
 
-Mon Jul 31 10:04:47 CEST 2000  Werner Koch  <wk@openit.de>
+       * status.c (mywrite): New and replaced all write() by this.
 
-  * encode.c, sign.c, keygen.c, pubkey-enc.c: Replaced all
-  gcry_sexp_{car,cdr}_{data,mpi} by the new gcry_sexp_nth_{data,mpi} functions.
+       * status.c, status.h: Add 3 status lcodes for notaions and policy.
+       * mainproc.c (print_notation_data): Do status output of notations.
+       
+2000-11-13  Werner Koch  <wk@gnupg.org>
 
-  * keygen.c (gen_dsa,gen_elg): Changed the way the factors are stored.
-  (factors_from_sexp): Removed.
-  * comment.c (make_mpi_comment_node): Removed.
-  (make_comment_node_from_buffer): New.
+       * sign.c (clearsign_file): Use LF macro to print linefeed.
+       
+2000-11-11  Paul Eggert  <eggert@twinsun.com>
 
-Fri Jul 28 18:19:11 CEST 2000  Werner Koch  <wk@openit.de>
+       Clean up the places in the code that incorrectly use "long" or
+        "unsigned long" for file offsets.  The correct type to use is
+        "off_t".  The difference is important on large-file hosts,
+        where "off_t" is longer than "long".
 
-  * sig-check.c (pk_verify): Fixed the S-Exp withe the pkey.
+        * keydb.h (struct keyblock_pos_struct.offset):
+        Use off_t, not ulong, for file offsets.
+        * packet.h (dbg_search_packet, dbg_copy_some_packets,
+        search_packet, copy_some_packets): Likewise.
+        * parse-packet.c (parse, dbg_search_packet, search_packet,
+        dbg_copy_some_packets, copy_some_packets): Likewise.
+        * ringedit.c (keyring_search): Likewise.
 
-  * gpg.c (main): Use setmode(O_BINARY) for MSDOS while generating random bytes
-  (print_mds): Likewise for stdin.
-  * plaintext.c (handle_plaintext): Likewise for stdout.
+        * parse-packet.c (parse): Do not use %lu to report file
+        offsets in error diagnostics; it's not portable.
+        * ringedit.c (keyring_search): Likewise.
 
-Tue Jul 25 17:44:15 CEST 2000  Werner Koch  <wk@openit.de>
+2000-11-09  Werner Koch  <wk@gnupg.org>
 
-  * keyedit.c (menu_expire): expire date for primary key can be set again.
+       * g10.c (main): New option --enable-special-filenames.
 
-  * keylist.c (is_uid_valid): New.
-  (list_keyblock): Print validity information for all user IDs.  Note, this
-  has to be done at other places too; for now we have only minimal support.
+2000-11-07  Werner Koch  <wk@gnupg.org>
+       * g10.c (main): New command --pipemode.
+       * pipemode.c: New.
+
+2000-10-23  Werner Koch  <wk@gnupg.org>
+
+       * armor.c (armor_filter): Changed output of hdrlines, so that a CR
+       is emitted for DOS systems.
+
+       * keygen.c (read_parameter_file): Add a cast for isspace().
+
+       * status.c (myread): Use SIGINT instead of SIGHUP for DOS. 
+
+2000-10-19  Werner Koch  <wk@gnupg.org>
 
-  * sign.c (pk_sign): Changed to use the new S-Exp interface.
-  * encode.c (pk_encrypt): Ditto.
-  * sig-check.c (pk_verify): Ditto.
-  * seckey-cert.c (pk_check_secret_key): Ditto.
-  * pubkey-enc.c (pk_decrypt): Ditto.
-  * misc.c (pubkey_nbits): Ditto.
-  * keygen.c (key_from_sexp,factors_from_sexp,gen_elg,gen_dsa): Ditto.
+       * g10.c: New option --ignore-crc-error
+       * armor.c (invalid_crc): New.
+       (radix64_read): Act on new option.
 
-Fri Jul 14 19:38:23 CEST 2000  Werner Koch  <wk@>
+       * openfile.c (try_make_homedir): Klaus Singvogel fixed a stupid
+       error introduced on Sep 6th. 
 
-  Replaced everything with the code from the STABLE-BRANCH-1-0 and
-  started to backport the changes from the 1.1 development branch
-  which are dated according to the ChangeLog of the 1.1 from
-  Sat Sep 18 12:16:08 CEST 1999  to  Thu May 25 18:39:11 CEST 2000.
-  Here are those changes, some of them are duplicates because they
-  have been done on both branch simultaneously.
+2000-10-18  Werner Koch  <wk@gnupg.org>
 
-  * gpg.c (print_mds): Add arg keys as a kludge to print hmacs
-  (main): New option --print-hmac.
+       * misc.c (print_cipher_algo_note): Don't print the note for AES.
+       Changed wording.
 
-  * trustdb.c (verify_own_keys): Do not print warning about unprotected
-  key when in quiet mode.
+2000-10-16  Werner Koch  <wk@gnupg.org>
 
-  * build-paket.c (do_user_id): Save offset where name has been stored.
+       * mainproc.c (do_proc_packets): Hack to fix the problem that
+       signatures are not detected when there is a MDC packet but no
+       compression packet.
+       
+       * g10.c (print_hashline): New.
+       (print_mds): Use above func with --with-colons.
+
+       * mainproc.c (check_sig_and_print): Detect multiple signatures
+       and don't verify them.
+
+2000-10-14  Werner Koch  <wk@gnupg.org>
+
+       * mainproc.c (add_onepass_sig): There is an easier solution to the
+       error fixed yesterday; just check that we only have onepass
+       packets.  However, the other solution provides an cleaner
+       interface and opens the path to get access to other information
+       from the armore headers.
+       (release_list): Reset some more variables.
 
-  * ringedit.c : Add new access method KBXF
+2000-10-13  Werner Koch  <wk@gnupg.org>
 
-  * kbxfile.c: New.
+       * mainproc.c (add_gpg_control): New.
+       (do_proc_packets): use it.
+       (proc_plaintext): Changed logic to detect clearsigns.
+       (proc_tree): Check the cleartext sig with some new code.
 
-  * kbx.h: New.
-  * kbxblob.c: Started to work on the keybox stuff.
+       * packet.h: New packet PKT_GPG_CONTROL.
+       * parse-packet.c (parse_gpg_control): New.
+       * misc.c (get_session_marker): New.
+       * armor.c (armor_filter): Replaced the faked 1-pass packet by the
+       new control packet.
 
-  * keygen.c (gen_dsa): Modified to work with gcry_pk_genkey.
+       * keyedit.c (keyedit_menu): Allow batchmode with a command_fd. 
+       * status.c (my_read): New.
+       (do_get_from_fd): use it.
+
+2000-10-12  Werner Koch  <wk@gnupg.org>
+
+       * keygen.c (keygen_add_std_prefs): Add Rijndael to the prefs.
 
-  * Removed dummy-cipher.h from all files.
+2000-10-07  Werner Koch  <wk@gnupg.org>
 
-  * keygen.c (gen_elg): Modified to work with gcry_pk_genkey.
-  (key_from_sexp): New.
-  (factors_from_sexp): New.
+       * gpgv.c: Add more stubs for ununsed code to make the binary smaller.
 
-  * g10.c : Renamed to ...
-  * gpg.c : ... this
-  * Makefile.am: And fixed it here.
+Wed Oct  4 15:50:18 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * Changed all "g10_"/"GPG_" prefixes to "gpg_"/"GPG_".
+        * sign.c (hash_for): New arg to take packet version in account, changed
+        call callers.
 
-  * misc.c (mpi_read_opaque): Fixed double counting.
+        * gpgv.c: New.
+        * Makefile.am: Rearranged source files so that gpgv can be build with
+        at least files as possible.
 
-  * seckey-cert.c (do_check): Removed buffer and the unmotivated free
-  on it.
+Mon Sep 18 12:13:52 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * pubkey-enc.c (pk_decrypt): New wrapper for the gcry_ function.
-  * seckey-cert.c (pk_check_secret_key): Likewise.
-  * encode.c (pk_encrypt): Likewise.
+        * hkp.c (not_implemented): Print a notice for W32
 
-  * parse-packet.c (parse_key): Fixed case of unencrypted secret keys.
+Fri Sep 15 18:40:36 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * misc.c (mpi_print): Use gcry_mpi_aprint.
-  (pubkey_nbits): Kludge to use the gcry_pk_ API.
+        * keygen.c (keygen_add_std_prefs): Changed order of preferences to
+        twofish, cast5, blowfish.
 
-  * seskey.c (encode_session_key): Replaced mpi_set_buffer by *_scan.
-  (do_encode_md): Ditto.
-  (encode_md_value): Ditto.
-  * seckey-cert.c (protect_secret_key): Ditto.
-  * comment.c (make_mpi_comment_node): Replaced mpi_get_buffer by _print.
-  * pubkey-enc.c (get_it): Ditto.
-  * sig-check.c (do_signature_check): Ditto.
+        * pkclist.c (algo_available): Removed hack to disable Twofish.
 
-  * keyid.c (do_fingerprint_md): Replaced mpi_get_buffer by gcry_mpi_print.
-  (v3_keyid): New.
-  (keyid_from_sk): And use it here.
-  (keyid_from_pk): Ditto.
-  (fingerprint_from_sk): Ditto.
-  (fingerprint_from_pk): Ditto.
+Thu Sep 14 17:45:11 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * misc.c (mpi_print): New.
+        * parse-packet.c (dump_sig_subpkt): Dump key flags. Print special
+        warning in case of faked ARRs.
 
-  * misc.c (checksum_mpi): Now uses gcry_mpi_print to get the data.
+        * getkey.c (finsih_lookup): Hack so that for v4 RSA keys the subkey
+        is used for encryption.
 
-  * seckey-cert.c (do_check): Replaced mpi_read_from_buffer.
+Thu Sep 14 14:20:38 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * armor.c (armor_filter): Made the "Comment:" header translatable.
+        * g10.c (main): Default S2K algorithms are now SHA1 and CAST5 - this
+        should solve a lot of compatibility problems with other OpenPGP
+        apps because those algorithms are SHOULD and not optional.  The old
+        way to force it was by using the --openpgp option whith the drawback 
+        that this would disable a couple of workarounds for PGP.
 
-  * seckey-cert.c: Removed obsolete mpi_*_protect_flag.
-  * parse-packet.c: Ditto.
+        * g10.c (main): Don't set --quite along with --no-tty.  By Frank Tobin.
 
-  * misc.c (mpi_read): Removed the secure argumet becuase it is
-  never used.  Changed all Callers.
-  (mpi_read_opaque): New.
-  (mpi_write_opaque): New.
-  * parse-packet.c (parse_key): Use the opaque method also for
-  v3 keys.
-  * build-packet.c (do_secret_key): Likewise.
+        * misc.c (disable_core_dump): Don't display a warning here but a return
+        a status value and ...
+        * g10.c (main): ...print warnining here. Suggested by Sam Roberts.
 
-  * g10.c (main): Check libgcrypt version.
+Wed Sep 13 18:12:34 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * packet.h: replaced inclusion of mpi.h by a plain typeedef of the
-  gcry_mpi structure and removed all inclusions of "mpi.h" in all
-  sources.
+        * keyedit.c (keyedit_menu): Allow to use "debug" on the secret key.
 
-  * g10.c: Add --delete-secret-key to the help page.
+        * ringedit.c (cmp_seckey): Fix for v4 RSA keys.
+        * seckey-cert.c (do_check): Workaround for PGP 7 bug.
 
-  * g10.c (main): Changed the default homedir to "~/.gnupg-test" so
-  that we don't mess up with the stable version.
+Wed Sep  6 17:55:47 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * misc.c (mpi_write): New.
-  (mpi_write): New.
+        * misc.c (print_pubkey_algo_note): Do not print the RSA notice.
+        * sig-check.c (do_signature_check): Do not emit the RSA status message.
+        * pubkey-enc.c (get_session_key): Ditto.
 
-  * misc.c (checksum_u16_nobug): Removed.
-  (checksum_mpi_counted_nbits): Renamed to ...
-  (checksum_mpi): ... this to superseed the old one. Changed all
-  callers. This is because we do not emulate the old gpg bug anymore.
-  * g10.c (oEmuChecksumBug): Removed.
+        * encode.c (encode_simple, encode_crypt): Fix for large files.
+        * sign.c (sign_file): Ditto.
 
-  * g10.c (register_extension): New...
-  (main): Use it here instead of register_cipher_extesnion.
-  (strusage): s/strusage/my_strusage/ . Made static.
-  (main): Use set_strusage().
+Wed Sep  6 14:59:09 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * tdbdump.c (HEXTOBIN): Changed the name of the argument, so that
-  traditional cpp don't mess up the macros. Suggested by Jos Backus.
+        * passphrase.c (hash_passphrase): Removed funny assert.  Reported by
+        David Mathog.
 
-  * armor.c (parse_header_line): Stop parsing on a only WS line too.
-  Suggested by Aric Cyr.
+        * openfile.c (try_make_homedir): Changes for non-Posix systems.
+        * g10.c (main): Take the default homedir from macro.
 
-  * misc.c (pull_in_libs): Removed.
+        * g10.c: The --trusted-key option is back.
+        * trustdb.c (verify_own_key): Handle this option.
+        (add_ultimate_key): Moved stuff from verify_own_key to this new func.
+        (register_trusted_key): New.
 
-  * mainproc.c (list_node): Print the PK algo in the --with-colon mode.
-  * keylist.c (list_keyblock): Ditto.
+Fri Aug 25 16:05:38 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * misc.c (pull_in_libs): Removed pull in of g10c.
+        * parse-packet.c (dump_sig_subpkt): Print info about the ARR.
 
-  * misc.c (map_gcry_rc): Removed here and chnaged all users.
+        * openfile.c (overwrite_filep): Always return okay if the file is
+        called /dev/null. 
+        (make_outfile_name): Add ".sign" to the list of know extensions.
+        (open_sigfile): Ditto.
 
-  * getkey.c: Replaced check_pubkey_algo by openpgp_pk_test_algo.
-  * import.c (delete_inv_parts): Ditto.
-  * pkclist.c: Ditto.
-  * skclist.c: Ditto.
-  * pubkey-enc.c: Ditto.
+Wed Aug 23 19:52:51 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * g10.c (main): Replaced the function to diable PK algos.
+        * g10.c: New option --allow-freeform-uid. By Jeroen C. van Gelderen.
+        * keygen.c (ask_user_id): Implemented here.
 
-  * g10.c (main): Replaced get_random_bits by gcry_random_bytes.
-  * seskey.c (encode_session_key): Likewise.
-  (make_session_key): Renamed randomize_buffer to gcry_randomize
-  and use the GCRY_xxx_RANDOM constants.
-  * cipher.c (write_header): Ditto.
-  * passphrase.c (hash_passphrase): Ditto.
-  * seckey-cert.c (protect_secret_key): Ditto.
+Fri Aug  4 14:23:05 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * getkey.c (find_by_name): Replaced rmd160_hash_buffer
-  by gcry_md_hash_buffer.
-  * keyedit.c (show_prefs): Ditto.
-  * keylist.c (list_keyblock): Ditto.
-  * trustdb.c (print_uid_from_keyblock): Ditto.
-  (make_uid_records): Ditto.
+  * status.c (do_get_from_fd): Ooops, we used fd instead of opt.command_fd.
+  Thanks to Michael Tokarev.
 
-  * skclist.c (build_sk_list): Removed the test on faked RNGs.
-  (is_insecure): Removed.
-  * g10.c (--quick-random): Removed this option.
+Tue Aug  1 20:06:23 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * Replaced all PUBKEY_ALGO_xxx by GCRY_PK_xxxx.
+  * g10.c: New opttion --try-all-secrets on suggestion from Matthias Urlichs.
+  * pubkey-enc.c (get_session_key): Quite easy to implement here.
 
-  * misc.c (pubkey_algo_npkey): New as a wrapper around the gcry fucntion.
-  (pubkey_algo_nskey): Ditto.
-  (pubkey_algo_nsig): Ditto.
-  (pubkey_algo_nenc): Ditto.
+Thu Jul 27 17:33:04 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * Makefile.am (basicdefs.h): Added.
-  (install-data-local): Removed the handling for historic gpgm.
+  * g10.c: New option --merge-only.  Suggested by Brendan O'Dea.
+  * import.c (import_one): Implemented it here
+  (import_secret_one): Ditto.
+  (print_stats): and give some stats.
 
-  * misc.c (openpgp_cipher_test_algo): New.
-  (openpgp_pk_test_algo): New.
-  (openpgp_md_test_algo): New.
+Thu Jul 27 12:01:00 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * g10.c (build_list): Changed to use the new functions from libgcrypt.
+  * g10.c: New options --show-session-key and --override-session-key
+  * pubkey-enc.c (hextobyte): New.
+  (get_override_session_key): New.
+  * mainproc.c (proc_pubkey_enc): Add session-key stuff.
+  * status.h, status.c (STATUS_SESSION_KEY): New.
 
-  * ringedit.c (enum_keyblocks): Set .rt to 0 on open.
+Thu Jul 27 10:02:38 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * encode.c (encode_simple): Use new CTB when we don't have the
-  length of the file.  This is somewhat strange as the comment above
-  indicates that this part is actually fixed for PGP 5 - maybe I simply
-  lost the source line, tsss.
+  * g10.c (main): Use setmode(O_BINARY) for MSDOS while generating random bytes
+  (print_mds): Likewise for stdin.
+  * plaintext.c (handle_plaintext): Likewise for stdout.
 
-  * sign.c (clearsign_file): Avoid duplicated Entries in the "Hash:"
-  line.  Those headers are now only _not_ printed when there are
-  only old-style keys _and_ all hashs are MD5.
+Mon Jul 24 10:30:17 CEST 2000  Werner Koch  <wk@openit.de>
 
-  (clearsign_file): Use gcry_md_test_algo() and gcry_md_algo_name().
+  * keyedit.c (menu_expire): expire date for primary key can be set again.
 
-  * openfile.c (make_outfile_name): Use case-insenstive compare for
-  DOS systems. Add ".pgp" to the list of know extensions.
-  (open_outfile): For DOS systems try to replace the suffix instead of
-  appending it.
+Wed Jul 19 11:26:43 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * encr-data.c (decrypt_data): Reset error on a weak key.
+  * keylist.c (is_uid_valid): New.
+  (list_keyblock): Print validity information for all user IDs.  Note, this
+  has to be done at other places too; for now we have only minimal support.
 
-  * cipher.c: Replaced the cipher and digest functions by the gcry_ ones.
-  * seckey-cert.c: Ditto.
-  * seskey.c: Ditto.
-  * g10.c (print_mds): Replaced digst functions with the new gcry_ ones.
-  * keyid.c: Ditto.
-  * mainproc.c: Ditto.
-  * passphrase.c: Ditto.
-  * sig-check.c: Ditto.
-  * sign.c: Ditto.
+Wed Jul 12 13:32:06 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * pkclist.c (do_edit_ownertrust): Made the answer string const.
+  * helptext.c, pkclist.c: s/superseeded/superseded/
 
-  * basicdefs.h: New.  Move some defs and decl to this header.
+Mon Jul 10 16:08:57 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * openfile.c (open_outfile): Fixed the 8dot3 handling.
+  * parse-packet.c (enum_sig_subpkt): Fixed testing on crtitical bit in case
+  of a NULL buffer.  Reported by Peter Marschall.
 
-  * passphrase.c (passphrase_to_dek): Print uid using utf8 func.
-  * delkey.c (delete_key): Ditto.
-  * pkclist.c (show_paths,do_edit_ownertrust,do_we_trust): Ditto
-  (do_we_trust_pre): Ditto.
-  * trustdb.c (print_user_id,check_uidsigs): Ditto.
-  * revoke.c (gen_revoke,ask_revoke_sig): Ditto.
+Wed Jul  5 13:28:45 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * filter.h: Changed cipher handle types to the the GCRY_xxx ones.
-  replaces include cipher by system header include gcrypt.h.
-  * cipher.c: replaced the cipher functions by the gcry_ ones.
-  Ditto for the md functions.
+  * keyedit.c, keyid.c: Add some _()
 
-  * misc.c (map_gcry_rc): New.
+  * argparse.c:  Changed the flag to suppress --version handling to also
+  suppress --help.
 
-Wed Jun 28 11:54:44 CEST 2000  Werner Koch  <wk@>
+Wed Jun 28 11:54:44 CEST 2000  Werner Koch  <wk@openit.de>
 
   * armor.c (armor_filter): Set sigclass to 0 in case of non-dash-escaped
   clearsig.  This makes this mode work again.
@@ -461,7 +3478,7 @@ Fri Jun  9 10:09:52 CEST 2000  Werner Koch  <wk@openit.de>
 
 Wed Jun  7 19:19:09 CEST 2000  Werner Koch  <wk@openit.de>
 
-  * sig-check.c (do_check): Use EMULATE_MDENCODE also on v4 paclets.
+  * sig-check.c (do_check): Use EMULATE_MDENCODE also on v4 packets.
 
 Wed Jun  7 17:25:38 CEST 2000  Werner Koch  <wk@openit.de>
 
@@ -3280,3 +6297,13 @@ Thu Feb 12 22:24:42 1998  Werner Koch  (wk@frodo)
 
        * pubkey-enc.c (get_session_key): rewritten
 
+
+ Copyright 1998,1999,2000,2001,2002 Free Software Foundation, Inc.
+
+ This file is free software; as a special exception the author gives
+ unlimited permission to copy and/or distribute it, with or without
+ modifications, as long as this notice is preserved.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
index 3e72451..f59cd8b 100644 (file)
+# Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
 ## Process this file with automake to produce Makefile.in
 
-INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl
-EXTRA_DIST = OPTIONS  pubring.asc  options.skel
-OMIT_DEPENDENCIES = zlib.h zconf.h
-LDFLAGS = @LDFLAGS@ $(LIBGCRYPT_LIBS)
-# we need to add libutil.la a second time because we have to resolve
-# gpg_log_ in some libjnlib modules. - very ugly - should be removed soon.
-needed_libs = ../util/libutil.a \
-             ../jnlib/libjnlib.a ../util/libutil.a
+INCLUDES = -I.. -I$(top_srcdir)/include -I$(top_srcdir)/intl
+EXTRA_DIST = options.skel
+# it seems that we can't use this with automake 1.5
+#OMIT_DEPENDENCIES = zlib.h zconf.h
+LDFLAGS = @LDFLAGS@ @DYNLINK_LDFLAGS@
+needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a
 
 #noinst_PROGRAMS = gpgd
-#bin_PROGRAMS = gpg kbxutil
-noinst_PROGRAMS = gpg kbxutil
+bin_PROGRAMS = gpg gpgv
 
 common_source =  \
+             global.h          \
              build-packet.c    \
              compress.c        \
-             basicdefs.h       \
              filter.h          \
              free-packet.c     \
              getkey.c          \
-             keydb.h           \
-             delkey.c          \
-             pkclist.c         \
-             skclist.c         \
-             ringedit.c        \
+             keydb.c keydb.h    \
+             keyring.c keyring.h \
+             seskey.c          \
              kbnode.c          \
-             kbx.h             \
-             kbxblob.c         \
-             kbxio.c           \
-             kbxfile.c         \
              main.h            \
              mainproc.c        \
              armor.c           \
              mdfilter.c        \
              textfilter.c      \
-             cipher.c          \
              misc.c            \
              options.h         \
              openfile.c        \
              keyid.c           \
-             trustdb.c         \
-             trustdb.h         \
-             tdbdump.c         \
-             tdbio.c           \
-             tdbio.h           \
-             hkp.h             \
-             hkp.c             \
              packet.h          \
              parse-packet.c    \
-             passphrase.c      \
-             pubkey-enc.c      \
-             seckey-cert.c     \
-             seskey.c          \
-             import.c          \
-             export.c          \
              comment.c         \
              status.c          \
              status.h          \
-             sign.c            \
              plaintext.c       \
-             encr-data.c       \
-             encode.c          \
-             revoke.c          \
-             keylist.c         \
              sig-check.c       \
-             signal.c          \
-             helptext.c
+             keylist.c         \
+             signal.c
 
-gpg_SOURCES  = gpg.c           \
+gpg_SOURCES  = g10.c           \
              $(common_source)  \
+             pkclist.c         \
+             skclist.c         \
+             pubkey-enc.c      \
+             passphrase.c      \
+             seckey-cert.c     \
+             encr-data.c       \
+             cipher.c          \
+             encode.c          \
+             sign.c            \
              verify.c          \
+             revoke.c          \
              decrypt.c         \
              keyedit.c         \
              dearmor.c         \
-             keygen.c
+             import.c          \
+             export.c          \
+             hkp.h             \
+             hkp.c             \
+             trustdb.c         \
+             trustdb.h         \
+             tdbdump.c         \
+             tdbio.c           \
+             tdbio.h           \
+             delkey.c          \
+             keygen.c          \
+             pipemode.c        \
+             helptext.c        \
+             keyserver.c       \
+             keyserver-internal.h \
+             photoid.c photoid.h \
+             exec.c exec.h
+
+
+
+gpgv_SOURCES = gpgv.c           \
+             $(common_source)  \
+             verify.c          
+
 
-# fixme: remove unused sources from kbxutil
-kbxutil_SOURCES = kbxutil.c   \
-             $(common_source)
 
 
 #gpgd_SOURCES = gpgd.c \
@@ -88,15 +108,18 @@ kbxutil_SOURCES = kbxutil.c   \
 #             ks-db.h \
 #             $(common_source)
 
-
-LDADD =  $(needed_libs)  @ZLIBS@ @INTLLIBS@
-
+LDADD =  $(needed_libs) @ZLIBS@ @INTLLIBS@
+# gpg gets LIBOBJS to add in mkdtemp if the platform doesn't have it
+gpg_LDADD = @LIBOBJS@ $(LDADD) @NETLIBS@
 
 $(PROGRAMS): $(needed_libs)
 
-
 install-data-local:
        $(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
        $(INSTALL_DATA) $(srcdir)/options.skel \
                                $(DESTDIR)$(pkgdatadir)/options.skel
-
+       @set -e;\
+        if test -f $(DESTDIR)$(bindir)/gpgm ; then \
+          echo "removing obsolete gpgm binary" ;   \
+          rm $(DESTDIR)$(bindir)/gpgm ;            \
+        fi
index 819c951..9c7858f 100644 (file)
@@ -1,5 +1,5 @@
 /* armor.c - Armor flter
- *     Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -28,7 +28,7 @@
 
 #include "errors.h"
 #include "iobuf.h"
-#include <gcrypt.h>
+#include "memory.h"
 #include "util.h"
 #include "filter.h"
 #include "packet.h"
@@ -151,8 +151,9 @@ initialize(void)
 }
 
 /****************
- * Check whether this is an armored file or not
- * See also parse-packet.c for details on this code
+ * Check whether this is an armored file or not See also
+ * parse-packet.c for details on this code For unknown historic
+ * reasons we use a string here but only the first byte will be used.
  * Returns: True if it seems to be armored
  */
 static int
@@ -195,6 +196,7 @@ use_armor_filter( IOBUF a )
     byte buf[1];
     int n;
 
+    /* fixme: there might be a problem with iobuf_peek */
     n = iobuf_peek(a, buf, 1 );
     if( n == -1 )
        return 0; /* EOF, doesn't matter whether armored or not */
@@ -210,7 +212,7 @@ static void
 invalid_armor(void)
 {
     write_status(STATUS_BADARMOR);
-    gpg_exit(1); /* stop here */
+    g10_exit(1); /* stop here */
 }
 
 
@@ -245,7 +247,9 @@ parse_hash_header( const char *line )
            found |= 2;
        else if( !strncmp( s, "MD5", s2-s ) )
            found |= 4;
-       else if( !strncmp( s, "TIGER", s2-s ) )
+       else if( !strncmp( s, "TIGER192", s2-s ) )
+           found |= 8;
+       else if( !strncmp( s, "TIGER", s2-s ) ) /* used by old versions */
            found |= 8;
        else
            return 0;
@@ -283,6 +287,14 @@ is_armor_header( byte *line, unsigned len )
        return -1;
     save_p = p;
     p += 5;
+
+    /* Some mail programs on Windows seem to add spaces to the end of
+       the line.  This becomes strict if --openpgp is set. */
+
+    if(!opt.rfc2440)
+      while(*p==' ')
+       p++;
+
     if( *p == '\r' )
        p++;
     if( *p == '\n' )
@@ -312,19 +324,19 @@ is_armor_header( byte *line, unsigned len )
  *      >0: Good header line
  */
 static int
-parse_header_line( armor_filter_context_t *afx, byte *line, unsigned len )
+parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len )
 {
     byte *p;
     int hashes=0;
+    unsigned int len2;
 
-    /* fixme: why this double check?  I think the original code w/o the
-     * second check for an empty line was done from an early draft of
-     * of OpenPGP - or simply very stupid code */
-    if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
-       return 0; /* empty line */
-    len = trim_trailing_ws( line, len );
-    if( !len )
-       return 0; /* WS only same as empty line */
+    len2 = check_trailing_ws( line, len );
+    if( !len2 ) {
+        afx->buffer_pos = len2;  /* (it is not the fine way to do it here) */
+       return 0; /* WS only: same as empty line */
+    }
+    len = len2;
+    line[len2] = 0;
 
     p = strchr( line, ':');
     if( !p || !p[1] ) {
@@ -399,7 +411,7 @@ check_input( armor_filter_context_t *afx, IOBUF a )
            if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
                if( afx->in_cleartext ) {
                    log_error(_("nested clear text signatures\n"));
-                   rc = GPGERR_INVALID_ARMOR;
+                   rc = G10ERR_INVALID_ARMOR;
                }
                afx->in_cleartext = 1;
            }
@@ -429,7 +441,7 @@ check_input( armor_filter_context_t *afx, IOBUF a )
        i = parse_header_line( afx, line, len );
        if( i <= 0 ) {
            if( i )
-               rc = GPGERR_INVALID_ARMOR;
+               rc = G10ERR_INVALID_ARMOR;
            break;
        }
     }
@@ -502,7 +514,7 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
            /* the buffer is always allocated with enough space to append
             * the removed [CR], LF and a Nul
             * The reason for this complicated procedure is to keep at least
-            * the original tupe of lineending - handling of the removed
+            * the original type of lineending - handling of the removed
             * trailing spaces seems to be impossible in our method
             * of faking a packet; either we have to use a temporary file
             * or calculate the hash here in this module and somehow find
@@ -590,6 +602,15 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
 }
 
 
+static int
+invalid_crc(void)
+{
+    if ( opt.ignore_crc_error )
+        return 0;
+    log_inc_errorcount();
+    return G10ERR_INVALID_ARMOR;
+}
+
 
 static int
 radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
@@ -636,9 +657,9 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
                if( isxdigit(cc1) && isxdigit(cc2)
                                  && strchr( "=\n\r\t ", cc3 )) {
                    /* well it seems to be the case - adjust */
-                   c = isdigit(cc1)? (cc1 - '0'): (toupper(cc1)-'A'+10);
+                   c = isdigit(cc1)? (cc1 - '0'): (ascii_toupper(cc1)-'A'+10);
                    c <<= 4;
-                   c |= isdigit(cc2)? (cc2 - '0'): (toupper(cc2)-'A'+10);
+                   c |= isdigit(cc2)? (cc2 - '0'): (ascii_toupper(cc2)-'A'+10);
                    afx->buffer_pos += 2;
                    afx->qp_detected = 1;
                    goto again;
@@ -728,20 +749,23 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
                    break; /* eof */
            } while( ++idx < 4 );
            if( c == -1 ) {
-               log_error(_("premature eof (in CRC)\n"));
-               rc = GPGERR_INVALID_ARMOR;
-           }
+               log_info(_("premature eof (in CRC)\n"));
+               rc = invalid_crc();
+                           }
            else if( idx != 4 ) {
-               log_error(_("malformed CRC\n"));
-               rc = GPGERR_INVALID_ARMOR;
+               log_info(_("malformed CRC\n"));
+               rc = invalid_crc();
            }
            else if( mycrc != afx->crc ) {
-               log_error(_("CRC error; %06lx - %06lx\n"),
+                log_info (_("CRC error; %06lx - %06lx\n"),
                                    (ulong)afx->crc, (ulong)mycrc);
-               rc = GPGERR_INVALID_ARMOR;
+                rc = invalid_crc();
            }
            else {
                rc = 0;
+                /* FIXME: Here we should emit another control packet,
+                 * so that we know in mainproc that we are processing
+                 * a clearsign message */
              #if 0
                for(rc=0;!rc;) {
                    rc = 0 /*check_trailer( &fhdr, c )*/;
@@ -754,11 +778,11 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
                    rc = 0;
                else if( rc == 2 ) {
                    log_error(_("premature eof (in Trailer)\n"));
-                   rc = GPGERR_INVALID_ARMOR;
+                   rc = G10ERR_INVALID_ARMOR;
                }
                else {
                    log_error(_("error in trailer line\n"));
-                   rc = GPGERR_INVALID_ARMOR;
+                   rc = G10ERR_INVALID_ARMOR;
                }
              #endif
            }
@@ -815,7 +839,9 @@ armor_filter( void *opaque, int control,
        *ret_len = n;
     }
     else if( control == IOBUFCTRL_UNDERFLOW ) {
-       if( size < 15+(4*15) )  /* need space for up to 4 onepass_sigs */
+        /* We need some space for the faked packet.  The minmum required
+         * size is ~18 + length of the session marker */
+       if( size < 50 ) 
            BUG(); /* supplied buffer too short */
 
        if( afx->faked )
@@ -831,7 +857,14 @@ armor_filter( void *opaque, int control,
                    rc = -1;
            }
            else if( afx->faked ) {
-               unsigned hashes = afx->hashes;
+               unsigned int hashes = afx->hashes;
+                const byte *sesmark;
+                size_t sesmarklen;
+                
+                sesmark = get_session_marker( &sesmarklen );
+                if ( sesmarklen > 20 )
+                    BUG();
+
                /* the buffer is at least 15+n*15 bytes long, so it
                 * is easy to construct the packets */
 
@@ -842,36 +875,21 @@ armor_filter( void *opaque, int control,
                        afx->pgp2mode = 1;
                }
                n=0;
-               do {
-                   /* first some onepass signature packets */
-                   buf[n++] = 0x90; /* old format, type 4, 1 length byte */
-                   buf[n++] = 13;   /* length */
-                   buf[n++] = 3;    /* version */
-                   buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
-                   if( hashes & 1 ) {
-                       hashes &= ~1;
-                       buf[n++] = GCRY_MD_RMD160;
-                   }
-                   else if( hashes & 2 ) {
-                       hashes &= ~2;
-                       buf[n++] = GCRY_MD_SHA1;
-                   }
-                   else if( hashes & 4 ) {
-                       hashes &= ~4;
-                       buf[n++] = GCRY_MD_MD5;
-                   }
-                   else if( hashes & 8 ) {
-                       hashes &= ~8;
-                       buf[n++] = GCRY_MD_TIGER;
-                   }
-                   else
-                       buf[n++] = 0;    /* (don't know) */
-
-                   buf[n++] = 0;    /* public key algo (don't know) */
-                   memset(buf+n, 0, 8); /* don't know the keyid */
-                   n += 8;
-                   buf[n++] = !hashes;   /* last one */
-               } while( hashes );
+                /* first a gpg control packet */
+                buf[n++] = 0xff; /* new format, type 63, 1 length byte */
+                n++;   /* see below */
+                memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
+                buf[n++] = CTRLPKT_CLEARSIGN_START; 
+                buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
+                if( hashes & 1 ) 
+                    buf[n++] = DIGEST_ALGO_RMD160;
+                if( hashes & 2 ) 
+                    buf[n++] = DIGEST_ALGO_SHA1;
+                if( hashes & 4 ) 
+                    buf[n++] = DIGEST_ALGO_MD5;
+                if( hashes & 8 ) 
+                    buf[n++] = DIGEST_ALGO_TIGER;
+                buf[1] = n - 2;
 
                /* followed by a plaintext packet */
                buf[n++] = 0xaf; /* old packet format, type 11, var length */
@@ -908,9 +926,8 @@ armor_filter( void *opaque, int control,
                                              PRINTABLE_OS_NAME ")" LF );
 
            /* write the comment string or a default one */
-           s = opt.comment_string ? opt.comment_string
-                                  : _("For info see http://www.gnupg.org");
-           if( *s ) {
+           s = opt.comment_string;
+           if( s && *s ) {
                iobuf_writestr(a, "Comment: " );
                for( ; *s; s++ ) {
                    if( *s == '\n' )
@@ -925,8 +942,15 @@ armor_filter( void *opaque, int control,
                iobuf_writestr(a, LF );
            }
 
-           if( afx->hdrlines )
-               iobuf_writestr(a, afx->hdrlines);
+           if ( afx->hdrlines ) {
+                for ( s = afx->hdrlines; *s; s++ ) {
+                  #ifdef HAVE_DOSISH_SYSTEM
+                    if ( *s == '\n' )
+                        iobuf_put( a, '\r');
+                  #endif
+                    iobuf_put(a, *s );
+                }
+            }
            iobuf_writestr(a, LF );
            afx->status++;
            afx->idx = 0;
@@ -1041,7 +1065,7 @@ armor_filter( void *opaque, int control,
        if( afx->qp_detected )
            log_error(_("quoted printable character in armor - "
                        "probably a buggy MTA has been used\n") );
-       gcry_free( afx->buffer );
+       m_free( afx->buffer );
        afx->buffer = NULL;
     }
     else if( control == IOBUFCTRL_DESC )
@@ -1058,7 +1082,7 @@ make_radix64_string( const byte *data, size_t len )
 {
     char *buffer, *p;
 
-    buffer = p = gcry_xmalloc( (len+2)/3*4 + 1 );
+    buffer = p = m_alloc( (len+2)/3*4 + 1 );
     for( ; len >= 3 ; len -= 3, data += 3 ) {
        *p++ = bintoasc[(data[0] >> 2) & 077];
        *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
@@ -1078,3 +1102,221 @@ make_radix64_string( const byte *data, size_t len )
     return buffer;
 }
 
+
+/***********************************************
+ *  For the pipemode command we can't use the armor filter for various
+ *  reasons, so we use this new unarmor_pump stuff to remove the armor 
+ */
+
+enum unarmor_state_e {
+    STA_init = 0,
+    STA_bypass,
+    STA_wait_newline,
+    STA_wait_dash,
+    STA_first_dash, 
+    STA_compare_header,
+    STA_found_header_wait_newline,
+    STA_skip_header_lines,
+    STA_skip_header_lines_non_ws,
+    STA_read_data,
+    STA_wait_crc,
+    STA_read_crc,
+    STA_ready
+};
+
+struct unarmor_pump_s {
+    enum unarmor_state_e state;
+    byte val;
+    int checkcrc;
+    int pos;   /* counts from 0..3 */
+    u32 crc;
+    u32 mycrc; /* the one store in the data */
+};
+
+
+
+UnarmorPump
+unarmor_pump_new (void)
+{
+    UnarmorPump x;
+
+    if( !is_initialized )
+        initialize();
+    x = m_alloc_clear (sizeof *x);
+    return x;
+}
+
+void
+unarmor_pump_release (UnarmorPump x)
+{
+    m_free (x);
+}
+
+/* 
+ * Get the next character from the ascii armor taken from the IOBUF
+ * created earlier by unarmor_pump_new().
+ * Return:  c = Character
+ *        256 = ignore this value
+ *         -1 = End of current armor 
+ *         -2 = Premature EOF (not used)
+ *         -3 = Invalid armor
+ */
+int
+unarmor_pump (UnarmorPump x, int c)
+{
+    int rval = 256; /* default is to ignore the return value */
+
+    switch (x->state) {
+      case STA_init:
+        { 
+            byte tmp[1];
+            tmp[0] = c; 
+            if ( is_armored (tmp) )
+                x->state = c == '-'? STA_first_dash : STA_wait_newline;
+            else {
+                x->state = STA_bypass;
+                return c;
+            }
+        }
+        break;
+      case STA_bypass:
+        return c; /* return here to avoid crc calculation */
+      case STA_wait_newline:
+        if (c == '\n')
+            x->state = STA_wait_dash;
+        break;
+      case STA_wait_dash:
+        x->state = c == '-'? STA_first_dash : STA_wait_newline;
+        break;
+      case STA_first_dash: /* just need for initalization */
+        x->pos = 0;
+        x->state = STA_compare_header;
+      case STA_compare_header:
+        if ( "-----BEGIN PGP SIGNATURE-----"[++x->pos] == c ) {
+            if ( x->pos == 28 ) 
+                x->state = STA_found_header_wait_newline;
+        }
+        else 
+            x->state = c == '\n'? STA_wait_dash : STA_wait_newline;
+        break;
+      case STA_found_header_wait_newline:
+        /* to make CR,LF issues easier we simply allow for white space
+           behind the 5 dashes */
+        if ( c == '\n' )
+            x->state = STA_skip_header_lines;
+        else if ( c != '\r' && c != ' ' && c != '\t' )
+            x->state = STA_wait_dash; /* garbage after the header line */
+        break;
+      case STA_skip_header_lines:
+        /* i.e. wait for one empty line */
+        if ( c == '\n' ) {
+            x->state = STA_read_data;
+            x->crc = CRCINIT;
+            x->val = 0;
+            x->pos = 0;
+        }
+        else if ( c != '\r' && c != ' ' && c != '\t' )
+            x->state = STA_skip_header_lines_non_ws;
+        break;
+      case STA_skip_header_lines_non_ws:
+        /* like above but we already encountered non white space */
+        if ( c == '\n' )
+            x->state = STA_skip_header_lines;
+        break;
+      case STA_read_data:
+        /* fixme: we don't check for the trailing dash lines but rely
+         * on the armor stop characters */
+        if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
+            break; /* skip all kind of white space */
+
+        if( c == '=' ) { /* pad character: stop */
+            if( x->pos == 1 ) /* in this case val has some value */
+                rval = x->val;
+            x->state = STA_wait_crc;
+            break;
+        }
+
+        {
+            int c2;
+            if( (c = asctobin[(c2=c)]) == 255 ) {
+                log_error(_("invalid radix64 character %02x skipped\n"), c2);
+                break;
+            }
+        }
+        
+        switch(x->pos) {
+          case 0:
+            x->val = c << 2;
+            break;
+          case 1:
+            x->val |= (c>>4)&3;
+            rval = x->val;
+            x->val = (c<<4)&0xf0;
+            break;
+          case 2:
+            x->val |= (c>>2)&15;
+            rval = x->val;
+            x->val = (c<<6)&0xc0;
+            break;
+          case 3:
+            x->val |= c&0x3f;
+            rval = x->val;
+            break;
+        }
+        x->pos = (x->pos+1) % 4;
+        break;
+      case STA_wait_crc:
+        if( c == '\n' || c == ' ' || c == '\r' || c == '\t' || c == '=' )
+            break; /* skip ws and pad characters */
+        /* assume that we are at the next line */
+        x->state = STA_read_crc;
+        x->pos = 0;
+        x->mycrc = 0;
+      case STA_read_crc:
+        if( (c = asctobin[c]) == 255 ) {
+            rval = -1; /* ready */
+            if( x->crc != x->mycrc ) {
+                log_info (_("CRC error; %06lx - %06lx\n"),
+                          (ulong)x->crc, (ulong)x->mycrc);
+                if ( invalid_crc() )
+                    rval = -3;
+            }
+            x->state = STA_ready; /* not sure whether this is correct */
+            break;
+        }
+        
+        switch(x->pos) {
+          case 0:
+            x->val = c << 2;
+            break;
+          case 1:
+            x->val |= (c>>4)&3;
+            x->mycrc |= x->val << 16;
+            x->val = (c<<4)&0xf0;
+            break;
+          case 2:
+            x->val |= (c>>2)&15;
+            x->mycrc |= x->val << 8;
+            x->val = (c<<6)&0xc0;
+            break;
+          case 3:
+            x->val |= c&0x3f;
+            x->mycrc |= x->val;
+            break;
+        }
+        x->pos = (x->pos+1) % 4;
+        break;
+      case STA_ready:
+        rval = -1;
+        break;
+    }
+
+    if ( !(rval & ~255) ) { /* compute the CRC */
+        x->crc = (x->crc << 8) ^ crc_table[((x->crc >> 16)&0xff) ^ rval];
+        x->crc &= 0x00ffffff;
+    }
+
+    return rval;
+}
+
+
index 9338187..e24ac3b 100644 (file)
@@ -1,5 +1,5 @@
 /* build-packet.c - assemble packets and write them
- *     Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
 #include <string.h>
 #include <assert.h>
 
-#include <gcrypt.h>
 #include "packet.h"
 #include "errors.h"
 #include "iobuf.h"
+#include "mpi.h"
 #include "util.h"
+#include "cipher.h"
+#include "memory.h"
 #include "options.h"
-#include "main.h"
 
 
 static int do_comment( IOBUF out, int ctb, PKT_comment *rem );
@@ -80,8 +81,8 @@ build_packet( IOBUF out, PACKET *pkt )
       case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break;
       case PKT_COMPRESSED:new_ctb = pkt->pkt.compressed->new_ctb; break;
       case PKT_USER_ID:
-           if( pkt->pkt.user_id->photo )
-               pkttype = PKT_PHOTO_ID;
+           if( pkt->pkt.user_id->attrib_data )
+               pkttype = PKT_ATTRIBUTE;
            break;
       default: break;
     }
@@ -91,7 +92,7 @@ build_packet( IOBUF out, PACKET *pkt )
     else
        ctb = 0x80 | ((pkttype & 15)<<2);
     switch( pkttype ) {
-      case PKT_PHOTO_ID:
+      case PKT_ATTRIBUTE:
       case PKT_USER_ID:
        rc = do_user_id( out, ctb, pkt->pkt.user_id );
        break;
@@ -134,7 +135,7 @@ build_packet( IOBUF out, PACKET *pkt )
        rc = do_onepass_sig( out, ctb, pkt->pkt.onepass_sig );
        break;
       case PKT_RING_TRUST:
-       break; /* ignore it */
+       break; /* ignore it (keyring.c does write it directly)*/
       default:
        log_bug("invalid packet type in build_packet()\n");
        break;
@@ -158,7 +159,7 @@ calc_packet_length( PACKET *pkt )
        n = calc_plaintext( pkt->pkt.plaintext );
        new_ctb = pkt->pkt.plaintext->new_ctb;
        break;
-      case PKT_PHOTO_ID:
+      case PKT_ATTRIBUTE:
       case PKT_USER_ID:
       case PKT_COMMENT:
       case PKT_PUBLIC_KEY:
@@ -195,10 +196,10 @@ write_fake_data( IOBUF out, MPI a )
 static int
 do_comment( IOBUF out, int ctb, PKT_comment *rem )
 {
-    if( !opt.no_comment ) {
+    if( opt.sk_comments ) {
        write_header(out, ctb, rem->len);
        if( iobuf_write( out, rem->data, rem->len ) )
-           return GPGERR_WRITE_FILE;
+           return G10ERR_WRITE_FILE;
     }
     return 0;
 }
@@ -206,19 +207,15 @@ do_comment( IOBUF out, int ctb, PKT_comment *rem )
 static int
 do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
 {
-    if( uid->photo ) {
-       write_header(out, ctb, uid->photolen);
-       uid->stored_at = iobuf_get_temp_length ( out ); /* what a hack ... */
-                 /* ... and it does only work when used with a temp iobuf */
-       if( iobuf_write( out, uid->photo, uid->photolen ) )
-           return GPGERR_WRITE_FILE;
+    if( uid->attrib_data ) {
+       write_header(out, ctb, uid->attrib_len);
+       if( iobuf_write( out, uid->attrib_data, uid->attrib_len ) )
+           return G10ERR_WRITE_FILE;
     }
     else {
        write_header(out, ctb, uid->len);
-       uid->stored_at = iobuf_get_temp_length ( out ); /* what a hack ... */
-                 /* ... and it does only work when used with a temp iobuf */
        if( iobuf_write( out, uid->name, uid->len ) )
-           return GPGERR_WRITE_FILE;
+           return G10ERR_WRITE_FILE;
     }
     return 0;
 }
@@ -252,7 +249,7 @@ do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
 
     write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes, 1 );
     if( iobuf_write_temp( out, a ) )
-       rc = GPGERR_WRITE_FILE;
+       rc = G10ERR_WRITE_FILE;
 
     iobuf_close(a);
     return rc;
@@ -263,7 +260,7 @@ do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
  * Make a hash value from the public key certificate
  */
 void
-hash_public_key( GCRY_MD_HD md, PKT_public_key *pk )
+hash_public_key( MD_HANDLE md, PKT_public_key *pk )
 {
     PACKET pkt;
     int rc = 0;
@@ -283,7 +280,7 @@ hash_public_key( GCRY_MD_HD md, PKT_public_key *pk )
     pkt.pkttype = PKT_PUBLIC_KEY;
     pkt.pkt.public_key = pk;
     if( (rc = build_packet( a, &pkt )) )
-       log_fatal("build public_key for hashing failed: %s\n", gpg_errstr(rc));
+       log_fatal("build public_key for hashing failed: %s\n", g10_errstr(rc));
 
     if( !(pk->version == 3 && pk->pubkey_algo == 16) ) {
        /* skip the constructed header but don't do this for our very old
@@ -314,10 +311,10 @@ hash_public_key( GCRY_MD_HD md, PKT_public_key *pk )
            }
        }
        /* hash a header */
-       gcry_md_putc( md, 0x99 );
+       md_putc( md, 0x99 );
        pktlen &= 0xffff; /* can't handle longer packets */
-       gcry_md_putc( md, pktlen >> 8 );
-       gcry_md_putc( md, pktlen & 0xff );
+       md_putc( md, pktlen >> 8 );
+       md_putc( md, pktlen & 0xff );
     }
     /* hash the packet body */
     while( (c=iobuf_get(a)) != -1 ) {
@@ -328,7 +325,7 @@ hash_public_key( GCRY_MD_HD md, PKT_public_key *pk )
            i=0;
        }
       #endif
-       gcry_md_putc( md, c );
+       md_putc( md, c );
     }
   #if 0
     putc('\n', fp);
@@ -343,43 +340,64 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
 {
     int rc = 0;
     int i, nskey, npkey;
-    IOBUF a = iobuf_temp();
+    IOBUF a = iobuf_temp(); /* build in a self-enlarging buffer */
 
+    /* Write the version number - if none is specified, use 3 */
     if( !sk->version )
        iobuf_put( a, 3 );
     else
        iobuf_put( a, sk->version );
     write_32(a, sk->timestamp );
+
+    /* v3  needs the expiration time */
     if( sk->version < 4 ) {
        u16 ndays;
        if( sk->expiredate )
            ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L);
        else
            ndays = 0;
-       write_16(a, );
+       write_16(a, ndays);
     }
+
     iobuf_put(a, sk->pubkey_algo );
+
+    /* get number of secret and public parameters.  They are held in
+       one array first the public ones, then the secret ones */
     nskey = pubkey_get_nskey( sk->pubkey_algo );
     npkey = pubkey_get_npkey( sk->pubkey_algo );
+
+    /* If we don't have any public parameters - which is the case if
+       we don't know the algorithm used - the parameters are stored as
+       one blob in a faked (opaque) MPI */
     if( !npkey ) {
        write_fake_data( a, sk->skey[0] );
        goto leave;
     }
     assert( npkey < nskey );
 
+    /* Writing the public parameters is easy */
     for(i=0; i < npkey; i++ )
        mpi_write(a, sk->skey[i] );
+
+    /* build the header for protected (encrypted) secret parameters */
     if( sk->is_protected ) {
        if( is_RSA(sk->pubkey_algo) && sk->version < 4
                                    && !sk->protect.s2k.mode ) {
+            /* the simple rfc1991 (v3) way */
            iobuf_put(a, sk->protect.algo );
            iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
        }
        else {
-           iobuf_put(a, 0xff );
+          /* OpenPGP protection according to rfc2440 */
+           iobuf_put(a, sk->protect.sha1chk? 0xfe : 0xff );
            iobuf_put(a, sk->protect.algo );
            if( sk->protect.s2k.mode >= 1000 ) {
-               iobuf_put(a, 101 );
+                /* These modes are not possible in OpenPGP, we use them
+                   to implement our extesnsions, 101 can ve views as a
+                   private/experimental extension (this is not
+                   specified in rfc2440 but the same scheme is used
+                   for all other algorithm identifiers) */
+               iobuf_put(a, 101 ); 
                iobuf_put(a, sk->protect.s2k.hash_algo );
                iobuf_write(a, "GNU", 3 );
                iobuf_put(a, sk->protect.s2k.mode - 1000 );
@@ -392,34 +410,41 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
                || sk->protect.s2k.mode == 3 )
                iobuf_write(a, sk->protect.s2k.salt, 8 );
            if( sk->protect.s2k.mode == 3 )
-               iobuf_put(a, sk->protect.s2k.count );
+               iobuf_put(a, sk->protect.s2k.count ); 
+
+            /* For out special mode 1001 we do not need an IV */
            if( sk->protect.s2k.mode != 1001 )
                iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
        }
     }
     else
        iobuf_put(a, 0 );
+
     if( sk->protect.s2k.mode == 1001 )
-       ;
+        ; /* GnuPG extension - don't write a secret key at all */ 
     else if( sk->is_protected && sk->version >= 4 ) {
+        /* The secret key is protected - write it out as it is */
        byte *p;
-       size_t n;
-       assert( gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
-       p = gcry_mpi_get_opaque( sk->skey[i], &n );
-       iobuf_write(a, p, (n+7)/8 );
+       assert( mpi_is_opaque( sk->skey[npkey] ) );
+       p = mpi_get_opaque( sk->skey[npkey], &i );
+       iobuf_write(a, p, i );
     }
     else {
+        /* v3 way - same code for protected and non- protected key */
        for(   ; i < nskey; i++ )
            mpi_write(a, sk->skey[i] );
        write_16(a, sk->csum );
     }
 
   leave:
+    /* Build the header of the packet - which we must do after writing all
+       the other stuff, so that we know the length of the packet */
     write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes, 1 );
+    /* And finally write it out the real stream */
     if( iobuf_write_temp( out, a ) )
-       rc = GPGERR_WRITE_FILE;
+       rc = G10ERR_WRITE_FILE;
 
-    iobuf_close(a);
+    iobuf_close(a); /* close the remporary buffer */
     return rc;
 }
 
@@ -448,7 +473,7 @@ do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc )
 
     write_header(out, ctb, iobuf_get_temp_length(a) );
     if( iobuf_write_temp( out, a ) )
-       rc = GPGERR_WRITE_FILE;
+       rc = G10ERR_WRITE_FILE;
 
     iobuf_close(a);
     return rc;
@@ -482,7 +507,7 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
 
     write_header(out, ctb, iobuf_get_temp_length(a) );
     if( iobuf_write_temp( out, a ) )
-       rc = GPGERR_WRITE_FILE;
+       rc = G10ERR_WRITE_FILE;
 
     iobuf_close(a);
     return rc;
@@ -511,12 +536,12 @@ do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt )
     for(i=0; i < pt->namelen; i++ )
        iobuf_put(out, pt->name[i] );
     if( write_32(out, pt->timestamp ) )
-       rc = GPGERR_WRITE_FILE;
+       rc = G10ERR_WRITE_FILE;
 
     n = 0;
     while( (nbytes=iobuf_read(pt->buf, buf, 1000)) != -1 ) {
        if( iobuf_write(out, buf, nbytes) == -1 ) {
-           rc = GPGERR_WRITE_FILE;
+           rc = G10ERR_WRITE_FILE;
            break;
        }
        n += nbytes;
@@ -539,7 +564,7 @@ do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed )
     int rc = 0;
     u32 n;
 
-    n = ed->len ? (ed->len + 10) : 0;
+    n = ed->len ? (ed->len + ed->extralen) : 0;
     write_header(out, ctb, n );
 
     /* This is all. The caller has to write the real data */
@@ -555,7 +580,7 @@ do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed )
 
     assert( ed->mdc_method );
 
-    n = ed->len ? (ed->len + 10) : 0;
+    n = ed->len ? (ed->len + ed->extralen) : 0;
     write_header(out, ctb, n );
     iobuf_put(out, 1 );  /* version */
 
@@ -572,7 +597,7 @@ do_mdc( IOBUF out, PKT_mdc *mdc )
     iobuf_put( out, 0xd3 ); /* packet ID and 1 byte length */
     iobuf_put( out, 0x14 ); /* length = 20 */
     if( iobuf_write( out, mdc->hash, sizeof(mdc->hash) ) )
-       return GPGERR_WRITE_FILE;
+       return G10ERR_WRITE_FILE;
     return 0;
 }
 
@@ -591,36 +616,36 @@ do_compressed( IOBUF out, int ctb, PKT_compressed *cd )
 }
 
 
-
 /****************
- * Find a subpacket of type REQTYPE in BUFFER and a return a pointer
- * to the first byte of that subpacket data.
- * And return the length of the packet in RET_N and the number of
- * header bytes in RET_HLEN (length header and type byte).
+ * Delete all subpackets of type REQTYPE and return a bool whether a packet
+ * was deleted.
  */
-byte *
-find_subpkt( byte *buffer, sigsubpkttype_t reqtype,
-            size_t *ret_hlen, size_t *ret_n )
+int
+delete_sig_subpkt (subpktarea_t *area, sigsubpkttype_t reqtype )
 {
     int buflen;
     sigsubpkttype_t type;
-    byte *bufstart;
+    byte *buffer, *bufstart;
     size_t n;
+    size_t unused = 0;
+    int okay = 0;
 
-    if( !buffer )
-       return NULL;
-    buflen = (*buffer << 8) | buffer[1];
-    buffer += 2;
+    if( !area )
+       return 0;
+    buflen = area->len;
+    buffer = area->data;
     for(;;) {
-       if( !buflen )
-           return NULL; /* end of packets; not found */
+       if( !buflen ) {
+            okay = 1;
+            break;
+        }
        bufstart = buffer;
        n = *buffer++; buflen--;
        if( n == 255 ) {
            if( buflen < 4 )
                break;
            n = (buffer[0] << 24) | (buffer[1] << 16)
-                                 | (buffer[2] << 8) | buffer[3];
+                | (buffer[2] << 8) | buffer[3];
            buffer += 4;
            buflen -= 4;
        }
@@ -633,137 +658,175 @@ find_subpkt( byte *buffer, sigsubpkttype_t reqtype,
        }
        if( buflen < n )
            break;
+        
        type = *buffer & 0x7f;
        if( type == reqtype ) {
            buffer++;
+            buflen--;
            n--;
            if( n > buflen )
                break;
-           if( ret_hlen )
-               *ret_hlen = buffer - bufstart;
-           if( ret_n )
-               *ret_n = n;
-           return buffer;
+            buffer += n; /* point to next subpkt */
+            buflen -= n;
+            memmove (bufstart, buffer, buflen); /* shift */
+            unused +=  buffer - bufstart;
+            buffer = bufstart;
        }
-       buffer += n; buflen -=n;
+        else {
+            buffer += n; buflen -=n;
+        }
     }
 
-    log_error("find_subpkt: buffer shorter than subpacket\n");
-    return NULL;
+    if (!okay)
+        log_error ("delete_subpkt: buffer shorter than subpacket\n");
+    assert (unused <= area->len);
+    area->len -= unused;
+    return !!unused;
 }
 
 
 /****************
- * Create or update a signature subpacket for SIG of TYPE.
- * This functions knows where to put the data (hashed or unhashed).
- * The function may move data from the unhased part to the hashed one.
- * Note: All pointers into sig->[un]hashed are not valid after a call
- * to this function.  The data to but into the subpaket should be
- * in buffer with a length of buflen.
+ * Create or update a signature subpacket for SIG of TYPE.  This
+ * functions knows where to put the data (hashed or unhashed).  The
+ * function may move data from the unhashed part to the hashed one.
+ * Note: All pointers into sig->[un]hashed (e.g. returned by
+ * parse_sig_subpkt) are not valid after a call to this function.  The
+ * data to put into the subpaket should be in a buffer with a length
+ * of buflen. 
  */
 void
-build_sig_subpktPKT_signature *sig, sigsubpkttype_t type,
+build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type,
                  const byte *buffer, size_t buflen )
 {
-    byte *data;
-    size_t hlen, dlen, nlen;
-    int found=0;
-    int critical, hashed, realloced;
-    size_t n, n0;
+    byte *p;
+    int critical, hashed;
+    subpktarea_t *oldarea, *newarea;
+    size_t nlen, n, n0;
 
     critical = (type & SIGSUBPKT_FLAG_CRITICAL);
     type &= ~SIGSUBPKT_FLAG_CRITICAL;
 
-    if( type == SIGSUBPKT_NOTATION )
-       ; /* we allow multiple packets */
-    else if( (data = find_subpkt( sig->hashed_data, type, &hlen, &dlen )) )
-       found = 1;
-    else if( (data = find_subpkt( sig->unhashed_data, type, &hlen, &dlen )))
-       found = 2;
+    /* Sanity check buffer sizes */
+    if(parse_one_sig_subpkt(buffer,buflen,type)<0)
+      BUG();
+
+    switch(type)
+      {
+      case SIGSUBPKT_NOTATION:
+      case SIGSUBPKT_POLICY:
+      case SIGSUBPKT_REV_KEY:
+       /* we do allow multiple subpackets */
+       break;
+
+      default:
+       /* we don't allow multiple subpackets */
+       delete_sig_subpkt(sig->hashed,type);
+       delete_sig_subpkt(sig->unhashed,type);
+       break;
+      }
+
+    /* Any special magic that needs to be done for this type so the
+       packet doesn't need to be reparsed? */
+    switch(type)
+      {
+      case SIGSUBPKT_NOTATION:
+       sig->flags.notation=1;
+       break;
+
+      case SIGSUBPKT_POLICY:
+       sig->flags.policy_url=1;
+       break;
+
+      case SIGSUBPKT_EXPORTABLE:
+       if(buffer[0])
+         sig->flags.exportable=1;
+       else
+         sig->flags.exportable=0;
+       break;
+
+      case SIGSUBPKT_REVOCABLE:
+       if(buffer[0])
+         sig->flags.revocable=1;
+       else
+         sig->flags.revocable=0;
+       break;
+
+      default:
+       break;
+      }
 
-    if( found )
-       log_bug("build_sig_packet: update nyi\n");
     if( (buflen+1) >= 8384 )
-       nlen = 5;
+       nlen = 5; /* write 5 byte length header */
     else if( (buflen+1) >= 192 )
-       nlen = 2;
+       nlen = 2; /* write 2 byte length header */
     else
-       nlen = 1;
+       nlen = 1; /* just a 1 byte length header */
 
     switch( type ) {
-      case SIGSUBPKT_SIG_CREATED:
-      case SIGSUBPKT_PRIV_ADD_SIG:
-      case SIGSUBPKT_PREF_SYM:
-      case SIGSUBPKT_PREF_HASH:
-      case SIGSUBPKT_PREF_COMPR:
-      case SIGSUBPKT_KS_FLAGS:
-      case SIGSUBPKT_KEY_EXPIRE:
-      case SIGSUBPKT_NOTATION:
-      case SIGSUBPKT_POLICY:
-      case SIGSUBPKT_REVOC_REASON:
-      case SIGSUBPKT_KEY_FLAGS:
-      case SIGSUBPKT_FEATURES:
-              hashed = 1; break;
-      default: hashed = 0; break;
-    }
-
-    if( hashed ) {
-       n0 = sig->hashed_data ? ((*sig->hashed_data << 8)
-                                   | sig->hashed_data[1]) : 0;
-       n = n0 + nlen + 1 + buflen; /* length, type, buffer */
-       realloced = !!sig->hashed_data;
-       data = sig->hashed_data ? gcry_xrealloc( sig->hashed_data, n+2 )
-                               : gcry_xmalloc( n+2 );
-    }
-    else {
-       n0 = sig->unhashed_data ? ((*sig->unhashed_data << 8)
-                                     | sig->unhashed_data[1]) : 0;
-       n = n0 + nlen + 1 + buflen; /* length, type, buffer */
-       realloced = !!sig->unhashed_data;
-       data = sig->unhashed_data ? gcry_xrealloc( sig->unhashed_data, n+2 )
-                                 : gcry_xmalloc( n+2 );
+      case SIGSUBPKT_ISSUER:
+      case SIGSUBPKT_PRIV_VERIFY_CACHE: /*(obsolete)*/
+        hashed = 0;
+        break;
+      default: 
+        hashed = 1;
+        break;
     }
 
     if( critical )
        type |= SIGSUBPKT_FLAG_CRITICAL;
 
-    data[0] = (n >> 8) & 0xff;
-    data[1] = n & 0xff;
-    if( nlen == 5 ) {
-       data[n0+2] = 255;
-       data[n0+3] = (buflen+1) >> 24;
-       data[n0+4] = (buflen+1) >> 16;
-       data[n0+5] = (buflen+1) >>  8;
-       data[n0+6] = (buflen+1);
-       data[n0+7] = type;
-       memcpy(data+n0+8, buffer, buflen );
+    oldarea = hashed? sig->hashed : sig->unhashed;
+
+    /* Calculate new size of the area and allocate */
+    n0 = oldarea? oldarea->len : 0;
+    n = n0 + nlen + 1 + buflen; /* length, type, buffer */
+    if (oldarea && n <= oldarea->size) { /* fits into the unused space */
+        newarea = oldarea;
+        /*log_debug ("updating area for type %d\n", type );*/
     }
-    else if( nlen == 2 ) {
-       data[n0+2] = (buflen+1-192) / 256 + 192;
-       data[n0+3] = (buflen+1-192) & 256;
-       data[n0+4] = type;
-       memcpy(data+n0+5, buffer, buflen );
+    else if (oldarea) {
+        newarea = m_realloc (oldarea, sizeof (*newarea) + n - 1);
+        newarea->size = n;
+        /*log_debug ("reallocating area for type %d\n", type );*/
     }
     else {
-       data[n0+2] = buflen+1;
-       data[n0+3] = type;
-       memcpy(data+n0+4, buffer, buflen );
+        newarea = m_alloc (sizeof (*newarea) + n - 1);
+        newarea->size = n;
+        /*log_debug ("allocating area for type %d\n", type );*/
     }
-
-    if( hashed ) {
-       if( !realloced )
-           gcry_free(sig->hashed_data);
-       sig->hashed_data = data;
+    newarea->len = n;
+
+    p = newarea->data + n0;
+    if (nlen == 5) {
+       *p++ = 255;
+       *p++ = (buflen+1) >> 24;
+       *p++ = (buflen+1) >> 16;
+       *p++ = (buflen+1) >>  8;
+       *p++ = (buflen+1);
+       *p++ = type;
+       memcpy (p, buffer, buflen);
+    }
+    else if (nlen == 2) {
+       *p++ = (buflen+1-192) / 256 + 192;
+       *p++ = (buflen+1-192) % 256;
+       *p++ = type;
+       memcpy (p, buffer, buflen);
     }
     else {
-       if( !realloced )
-           gcry_free(sig->unhashed_data);
-       sig->unhashed_data = data;
+       *p++ = buflen+1;
+       *p++ = type;
+       memcpy (p, buffer, buflen);
     }
+
+    if (hashed) 
+       sig->hashed = newarea;
+    else
+       sig->unhashed = newarea;
 }
 
 /****************
  * Put all the required stuff from SIG into subpackets of sig.
+ * Hmmm, should we delete those subpackets which are in a wrong area?
  */
 void
 build_sig_subpkt_from_sig( PKT_signature *sig )
@@ -789,8 +852,70 @@ build_sig_subpkt_from_sig( PKT_signature *sig )
     buf[2] = (u >>  8) & 0xff;
     buf[3] = u & 0xff;
     build_sig_subpkt( sig, SIGSUBPKT_SIG_CREATED, buf, 4 );
+
+    if(sig->expiredate)
+      {
+       u = sig->expiredate-sig->timestamp;
+       buf[0] = (u >> 24) & 0xff;
+       buf[1] = (u >> 16) & 0xff;
+       buf[2] = (u >>  8) & 0xff;
+       buf[3] = u & 0xff;
+
+       /* Mark this CRITICAL, so if any implementation doesn't
+           understand sigs that can expire, it'll just disregard this
+           sig altogether. */
+
+       build_sig_subpkt( sig, SIGSUBPKT_SIG_EXPIRE | SIGSUBPKT_FLAG_CRITICAL,
+                         buf, 4 );
+      }
 }
 
+void
+build_attribute_subpkt(PKT_user_id *uid,byte type,
+                      const void *buf,int buflen,
+                      const void *header,int headerlen)
+{
+  byte *attrib;
+  int idx;
+
+  if(1+headerlen+buflen>8383)
+    idx=5;
+  else if(1+headerlen+buflen>191)
+    idx=2;
+  else
+    idx=1;
+
+  /* realloc uid->attrib_data to the right size */
+
+  uid->attrib_data=m_realloc(uid->attrib_data,
+                            uid->attrib_len+idx+1+headerlen+buflen);
+
+  attrib=&uid->attrib_data[uid->attrib_len];
+
+  if(idx==5)
+    {
+      attrib[0]=255;
+      attrib[1]=(1+headerlen+buflen) >> 24;
+      attrib[2]=(1+headerlen+buflen) >> 16;
+      attrib[3]=(1+headerlen+buflen) >> 8;
+      attrib[4]=1+headerlen+buflen;
+    }
+  else if(idx==2)
+    {
+      attrib[0]=(1+headerlen+buflen-192) / 256 + 192;
+      attrib[1]=(1+headerlen+buflen-192) % 256;
+    }
+  else
+    attrib[0]=1+headerlen+buflen; /* Good luck finding a JPEG this small! */
+
+  attrib[idx++]=type;
+
+  /* Tack on our data at the end */
+
+  memcpy(&attrib[idx],header,headerlen);
+  memcpy(&attrib[idx+headerlen],buf,buflen);
+  uid->attrib_len+=idx+headerlen+buflen;
+}
 
 static int
 do_signature( IOBUF out, int ctb, PKT_signature *sig )
@@ -818,16 +943,14 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
        /* timestamp and keyid must have been packed into the
         * subpackets prior to the call of this function, because
         * these subpackets are hashed */
-       nn = sig->hashed_data?((sig->hashed_data[0]<<8)
-                               |sig->hashed_data[1])   :0;
+       nn = sig->hashed? sig->hashed->len : 0;
        write_16(a, nn);
        if( nn )
-           iobuf_write( a, sig->hashed_data+2, nn );
-       nn = sig->unhashed_data?((sig->unhashed_data[0]<<8)
-                                 |sig->unhashed_data[1])   :0;
+           iobuf_write( a, sig->hashed->data, nn );
+       nn = sig->unhashed? sig->unhashed->len : 0;
        write_16(a, nn);
        if( nn )
-           iobuf_write( a, sig->unhashed_data+2, nn );
+           iobuf_write( a, sig->unhashed->data, nn );
     }
     iobuf_put(a, sig->digest_start[0] );
     iobuf_put(a, sig->digest_start[1] );
@@ -842,7 +965,7 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
     else
        write_header(out, ctb, iobuf_get_temp_length(a) );
     if( iobuf_write_temp( out, a ) )
-       rc = GPGERR_WRITE_FILE;
+       rc = G10ERR_WRITE_FILE;
 
     iobuf_close(a);
     return rc;
@@ -865,7 +988,7 @@ do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops )
 
     write_header(out, ctb, iobuf_get_temp_length(a) );
     if( iobuf_write_temp( out, a ) )
-       rc = GPGERR_WRITE_FILE;
+       rc = G10ERR_WRITE_FILE;
 
     iobuf_close(a);
     return rc;
index cad6ff6..2af8750 100644 (file)
@@ -1,5 +1,5 @@
 /* cipher.c - En-/De-ciphering filter
- *     Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -25,9 +25,9 @@
 #include <errno.h>
 #include <assert.h>
 
-#include <gcrypt.h>
 #include "errors.h"
 #include "iobuf.h"
+#include "memory.h"
 #include "util.h"
 #include "filter.h"
 #include "packet.h"
@@ -45,69 +45,69 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
     PACKET pkt;
     PKT_encrypted ed;
     byte temp[18];
-    unsigned int blocksize;
-    unsigned int nprefix;
-    int rc;
-    int use_mdc = opt.force_mdc;
+    unsigned blocksize;
+    unsigned nprefix;
+    int use_mdc;
 
-    blocksize = gcry_cipher_get_algo_blklen( cfx->dek->algo );
+    blocksize = cipher_get_blocksize( cfx->dek->algo );
     if( blocksize < 8 || blocksize > 16 )
        log_fatal("unsupported blocksize %u\n", blocksize );
+
+    use_mdc = cfx->dek->use_mdc;
+
     if( blocksize != 8 )
-       use_mdc = 1;  /* enable it for all modern ciphers */
-    if( opt.rfc2440 )
+       use_mdc = 1;  /* Hack: enable it for all modern ciphers */
+    /* Note: We should remove this hack as soon as a reasonable number of keys
+       are carrying the MDC flag.  But always keep the hack for conventional
+       encryption */
+
+    if (opt.force_mdc)
+        use_mdc = 1;
+        
+    if( opt.rfc2440 || opt.rfc1991 || opt.disable_mdc )
        use_mdc = 0;  /* override - rfc2440 does not know about MDC */
 
     memset( &ed, 0, sizeof ed );
     ed.len = cfx->datalen;
+    ed.extralen = blocksize+2;
     ed.new_ctb = !ed.len && !opt.rfc1991;
     if( use_mdc ) {
-       ed.mdc_method = GCRY_MD_SHA1;
-       cfx->mdc_hash = gcry_md_open( GCRY_MD_SHA1, 0 );
-       if( !cfx->mdc_hash )
-           BUG();
+       ed.mdc_method = DIGEST_ALGO_SHA1;
+       cfx->mdc_hash = md_open( DIGEST_ALGO_SHA1, 0 );
        if ( DBG_HASHING )
-           gcry_md_start_debug( cfx->mdc_hash, "creatmdc" );
+           md_start_debug( cfx->mdc_hash, "creatmdc" );
+    }
+
+    {
+        char buf[20];
+        
+        sprintf (buf, "%d %d", ed.mdc_method, cfx->dek->algo);
+        write_status_text (STATUS_BEGIN_ENCRYPTION, buf);
     }
+
     init_packet( &pkt );
     pkt.pkttype = use_mdc? PKT_ENCRYPTED_MDC : PKT_ENCRYPTED;
     pkt.pkt.encrypted = &ed;
     if( build_packet( a, &pkt ))
        log_bug("build_packet(ENCR_DATA) failed\n");
     nprefix = blocksize;
-    gcry_randomize( temp, nprefix, GCRY_STRONG_RANDOM );
+    randomize_buffer( temp, nprefix, 1 );
     temp[nprefix] = temp[nprefix-2];
     temp[nprefix+1] = temp[nprefix-1];
     print_cipher_algo_note( cfx->dek->algo );
-    if( !(cfx->cipher_hd = gcry_cipher_open( cfx->dek->algo,
-                                      GCRY_CIPHER_MODE_CFB,
-                                      GCRY_CIPHER_SECURE
-                                      | ((use_mdc || cfx->dek->algo >= 100) ?
-                                            0 : GCRY_CIPHER_ENABLE_SYNC)))
-                                    ) {
-       /* we should never get an error here cause we already checked, that
-        * the algorithm is available. */
-       BUG();
-    }
-
-
+    cfx->cipher_hd = cipher_open( cfx->dek->algo,
+                                 use_mdc? CIPHER_MODE_CFB
+                                        : CIPHER_MODE_AUTO_CFB, 1 );
 /*   log_hexdump( "thekey", cfx->dek->key, cfx->dek->keylen );*/
-    rc = gcry_cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen );
-    if( !rc )
-       rc = gcry_cipher_setiv( cfx->cipher_hd, NULL, 0 );
-    if( rc )
-       log_fatal("set key or IV failed: %s\n", gcry_strerror(rc) );
+    cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen );
+    cipher_setiv( cfx->cipher_hd, NULL, 0 );
 /*  log_hexdump( "prefix", temp, nprefix+2 ); */
-    if( cfx->mdc_hash )
-       gcry_md_write( cfx->mdc_hash, temp, nprefix+2 );
-    rc = gcry_cipher_encrypt( cfx->cipher_hd, temp, nprefix+2, NULL, 0 );
-    if( !rc )
-       rc = gcry_cipher_sync( cfx->cipher_hd );
-    if( rc )
-       log_fatal("encrypt failed: %s\n", gcry_strerror(rc) );
+    if( cfx->mdc_hash ) /* hash the "IV" */
+       md_write( cfx->mdc_hash, temp, nprefix+2 );
+    cipher_encrypt( cfx->cipher_hd, temp, temp, nprefix+2);
+    cipher_sync( cfx->cipher_hd );
     iobuf_write(a, temp, nprefix+2);
     cfx->header=1;
-
 }
 
 
@@ -129,46 +129,39 @@ cipher_filter( void *opaque, int control,
     else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
        assert(a);
        if( !cfx->header ) {
-           write_status( STATUS_BEGIN_ENCRYPTION );
            write_header( cfx, a );
        }
        if( cfx->mdc_hash )
-           gcry_md_write( cfx->mdc_hash, buf, size );
-       rc = gcry_cipher_encrypt( cfx->cipher_hd, buf, size, NULL, 0);
-       if( rc )
-           log_fatal("encrypt failed: %s\n", gcry_strerror(rc) );
+           md_write( cfx->mdc_hash, buf, size );
+       cipher_encrypt( cfx->cipher_hd, buf, buf, size);
        if( iobuf_write( a, buf, size ) )
-           rc = GPGERR_WRITE_FILE;
+           rc = G10ERR_WRITE_FILE;
     }
     else if( control == IOBUFCTRL_FREE ) {
        if( cfx->mdc_hash ) {
            byte *hash;
-           int hashlen = gcry_md_get_algo_dlen( gcry_md_get_algo( cfx->mdc_hash ) );
+           int hashlen = md_digest_length( md_get_algo( cfx->mdc_hash ) );
            byte temp[22];
 
            assert( hashlen == 20 );
            /* we must hash the prefix of the MDC packet here */
            temp[0] = 0xd3;
            temp[1] = 0x14;
-           gcry_md_putc( cfx->mdc_hash, temp[0] );
-           gcry_md_putc( cfx->mdc_hash, temp[1] );
+           md_putc( cfx->mdc_hash, temp[0] );
+           md_putc( cfx->mdc_hash, temp[1] );
 
-           hash = gcry_md_read( cfx->mdc_hash, 0 );
+           md_final( cfx->mdc_hash );
+           hash = md_read( cfx->mdc_hash, 0 );
            memcpy(temp+2, hash, 20);
-           rc = gcry_cipher_encrypt( cfx->cipher_hd, temp, 22, NULL, 0 );
-           if( rc )
-               log_fatal("encrypt failed: %s\n", gcry_strerror(rc) );
-           gcry_md_close( cfx->mdc_hash ); cfx->mdc_hash = NULL;
+           cipher_encrypt( cfx->cipher_hd, temp, temp, 22 );
+           md_close( cfx->mdc_hash ); cfx->mdc_hash = NULL;
            if( iobuf_write( a, temp, 22 ) )
                log_error("writing MDC packet failed\n" );
        }
-       gcry_cipher_close(cfx->cipher_hd);
-       write_status( STATUS_END_ENCRYPTION );
+       cipher_close(cfx->cipher_hd);
     }
     else if( control == IOBUFCTRL_DESC ) {
        *(char**)buf = "cipher_filter";
     }
     return rc;
 }
-
-
index b1732a2..6d27e48 100644 (file)
@@ -1,5 +1,5 @@
 /* comment.c - write comment stuff
- *     Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+ *     Copyright (C) 1998 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -29,7 +29,7 @@
 #include "packet.h"
 #include "errors.h"
 #include "iobuf.h"
-#include <gcrypt.h>
+#include "memory.h"
 #include "util.h"
 #include "main.h"
 #include "keydb.h"
@@ -45,41 +45,59 @@ write_comment( IOBUF out, const char *s )
 
     pkt.pkttype = PKT_COMMENT;
     if( *s != '#' ) {
-       pkt.pkt.comment = gcry_xmalloc( sizeof *pkt.pkt.comment + n );
+       pkt.pkt.comment = m_alloc( sizeof *pkt.pkt.comment + n );
        pkt.pkt.comment->len = n+1;
        *pkt.pkt.comment->data = '#';
        strcpy(pkt.pkt.comment->data+1, s);
     }
     else {
-       pkt.pkt.comment = gcry_xmalloc( sizeof *pkt.pkt.comment + n - 1 );
+       pkt.pkt.comment = m_alloc( sizeof *pkt.pkt.comment + n - 1 );
        pkt.pkt.comment->len = n;
        strcpy(pkt.pkt.comment->data, s);
     }
     if( (rc = build_packet( out, &pkt )) )
-       log_error("build_packet(comment) failed: %s\n", gpg_errstr(rc) );
+       log_error("build_packet(comment) failed: %s\n", g10_errstr(rc) );
     free_packet( &pkt );
     return rc;
 }
 
 
 KBNODE
-make_comment_node_from_buffer( const char *s, size_t n )
+make_comment_node( const char *s )
 {
     PACKET *pkt;
+    size_t n = strlen(s);
 
-    pkt = gcry_xcalloc( 1, sizeof *pkt );
+    pkt = m_alloc_clear( sizeof *pkt );
     pkt->pkttype = PKT_COMMENT;
-    pkt->pkt.comment = gcry_xmalloc( sizeof *pkt->pkt.comment + n - 1 );
+    pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n - 1 );
     pkt->pkt.comment->len = n;
     strcpy(pkt->pkt.comment->data, s);
     return new_kbnode( pkt );
 }
 
+
 KBNODE
-make_comment_node( const char *s )
+make_mpi_comment_node( const char *s, MPI a )
 {
-    return make_comment_node_from_buffer ( s, strlen (s) );
-}
+    PACKET *pkt;
+    byte *buf, *p, *pp;
+    unsigned n1, nb1;
+    size_t n = strlen(s);
 
+    nb1 = mpi_get_nbits( a );
+    p = buf = mpi_get_buffer( a, &n1, NULL );
+    pkt = m_alloc_clear( sizeof *pkt );
+    pkt->pkttype = PKT_COMMENT;
+    pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n + 2 + n1 );
+    pkt->pkt.comment->len = n+1+2+n1;
+    pp = pkt->pkt.comment->data;
+    memcpy(pp, s, n+1);
+    pp[n+1] = nb1 >> 8;
+    pp[n+2] = nb1 ;
+    memcpy(pp+n+3, p, n1 );
+    m_free(buf);
+    return new_kbnode( pkt );
+}
 
 
index 2666e90..6d85e01 100644 (file)
@@ -1,5 +1,5 @@
 /* compress.c - compress filter
- *     Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
 #include <errno.h>
 #include <zlib.h>
 
-#include <gcrypt.h>
 #include "util.h"
+#include "memory.h"
 #include "packet.h"
 #include "filter.h"
+#include "main.h"
 #include "options.h"
 
 
@@ -63,7 +64,7 @@ init_compress( compress_filter_context_t *zfx, z_stream *zs )
     }
 
     zfx->outbufsize = 8192;
-    zfx->outbuf = gcry_xmalloc( zfx->outbufsize );
+    zfx->outbuf = m_alloc( zfx->outbufsize );
 }
 
 static int
@@ -73,7 +74,11 @@ do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a )
     unsigned n;
 
     do {
+#ifndef __riscos__
        zs->next_out = zfx->outbuf;
+#else /* __riscos__ */
+       zs->next_out = (Bytef *) zfx->outbuf;
+#endif /* __riscos__ */
        zs->avail_out = zfx->outbufsize;
        if( DBG_FILTER )
            log_debug("enter deflate: avail_in=%u, avail_out=%u, flush=%d\n",
@@ -96,7 +101,7 @@ do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a )
 
        if( iobuf_write( a, zfx->outbuf, n ) ) {
            log_debug("deflate: iobuf_write failed\n");
-           return GPGERR_WRITE_FILE;
+           return G10ERR_WRITE_FILE;
        }
     } while( zs->avail_in || (flush == Z_FINISH && zrc != Z_STREAM_END) );
     return 0;
@@ -121,7 +126,7 @@ init_uncompress( compress_filter_context_t *zfx, z_stream *zs )
     }
 
     zfx->inbufsize = 2048;
-    zfx->inbuf = gcry_xmalloc( zfx->inbufsize );
+    zfx->inbuf = m_alloc( zfx->inbufsize );
     zs->avail_in = 0;
 }
 
@@ -143,7 +148,11 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs,
        if( zs->avail_in < zfx->inbufsize && refill ) {
            n = zs->avail_in;
            if( !n )
+#ifndef __riscos__
                zs->next_in = zfx->inbuf;
+#else /* __riscos__ */
+               zs->next_in = (Bytef *) zfx->inbuf;
+#endif /* __riscos__ */
            count = zfx->inbufsize - n;
            nread = iobuf_read( a, zfx->inbuf + n, count );
            if( nread == -1 ) nread = 0;
@@ -196,12 +205,16 @@ compress_filter( void *opaque, int control,
 
     if( control == IOBUFCTRL_UNDERFLOW ) {
        if( !zfx->status ) {
-           zs = zfx->opaque = gcry_xcalloc( 1, sizeof *zs );
+           zs = zfx->opaque = m_alloc_clear( sizeof *zs );
            init_uncompress( zfx, zs );
            zfx->status = 1;
        }
 
+#ifndef __riscos__
        zs->next_out = buf;
+#else /* __riscos__ */
+       zs->next_out = (Bytef *) buf;
+#endif /* __riscos__ */
        zs->avail_out = size;
        zfx->outbufsize = size; /* needed only for calculation */
        rc = do_uncompress( zfx, zs, a, ret_len );
@@ -212,7 +225,9 @@ compress_filter( void *opaque, int control,
            PKT_compressed cd;
 
            if( !zfx->algo )
-               zfx->algo = opt.def_compress_algo;
+               zfx->algo = DEFAULT_COMPRESS_ALGO;
+           if( zfx->algo != 1 && zfx->algo != 2 )
+             BUG();
            memset( &cd, 0, sizeof cd );
            cd.len = 0;
            cd.algorithm = zfx->algo;
@@ -221,37 +236,54 @@ compress_filter( void *opaque, int control,
            pkt.pkt.compressed = &cd;
            if( build_packet( a, &pkt ))
                log_bug("build_packet(PKT_COMPRESSED) failed\n");
-           zs = zfx->opaque = gcry_xcalloc( 1, sizeof *zs );
+           zs = zfx->opaque = m_alloc_clear( sizeof *zs );
            init_compress( zfx, zs );
            zfx->status = 2;
        }
 
+#ifndef __riscos__
        zs->next_in = buf;
+#else /* __riscos__ */
+       zs->next_in = (Bytef *) buf;
+#endif /* __riscos__ */
        zs->avail_in = size;
        rc = do_compress( zfx, zs, Z_NO_FLUSH, a );
     }
     else if( control == IOBUFCTRL_FREE ) {
        if( zfx->status == 1 ) {
            inflateEnd(zs);
-           gcry_free(zs);
+           m_free(zs);
            zfx->opaque = NULL;
-           gcry_free(zfx->outbuf); zfx->outbuf = NULL;
+           m_free(zfx->outbuf); zfx->outbuf = NULL;
        }
        else if( zfx->status == 2 ) {
+#ifndef __riscos__
            zs->next_in = buf;
+#else /* __riscos__ */
+           zs->next_in = (Bytef *) buf;
+#endif /* __riscos__ */
            zs->avail_in = 0;
            do_compress( zfx, zs, Z_FINISH, a );
            deflateEnd(zs);
-           gcry_free(zs);
+           m_free(zs);
            zfx->opaque = NULL;
-           gcry_free(zfx->outbuf); zfx->outbuf = NULL;
+           m_free(zfx->outbuf); zfx->outbuf = NULL;
        }
+        if (zfx->release)
+          zfx->release (zfx);
     }
     else if( control == IOBUFCTRL_DESC )
        *(char**)buf = "compress_filter";
     return rc;
 }
 
+
+static void
+release_context (compress_filter_context_t *ctx)
+{
+  m_free (ctx);
+}
+
 /****************
  * Handle a compressed packet
  */
@@ -259,26 +291,19 @@ int
 handle_compressed( void *procctx, PKT_compressed *cd,
                   int (*callback)(IOBUF, void *), void *passthru )
 {
-    compress_filter_context_t cfx;
+    compress_filter_context_t *cfx;
     int rc;
 
-    memset( &cfx, 0, sizeof cfx );
     if( cd->algorithm < 1 || cd->algorithm > 2 )
-       return GPGERR_COMPR_ALGO;
-    cfx.algo = cd->algorithm;
-
-    iobuf_push_filter( cd->buf, compress_filter, &cfx );
+       return G10ERR_COMPR_ALGO;
+    cfx = m_alloc_clear (sizeof *cfx);
+    cfx->algo = cd->algorithm;
+    cfx->release = release_context;
+    iobuf_push_filter( cd->buf, compress_filter, cfx );
     if( callback )
        rc = callback(cd->buf, passthru );
     else
        rc = proc_packets(procctx, cd->buf);
-  #if 0
-    iobuf_pop_filter( cd->buf, compress_filter, &cfx );
-    if( cd->len )
-       iobuf_set_limit( cd->buf, 0 ); /* disable the readlimit */
-    else
-       iobuf_clear_eof( cd->buf );
-  #endif
     cd->buf = NULL;
     return rc;
 }
index 937961e..4ec8fa0 100644 (file)
@@ -1,5 +1,5 @@
 /* dearmor.c - Armor utility
- *     Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -25,9 +25,9 @@
 #include <errno.h>
 #include <assert.h>
 
-#include <gcrypt.h>
 #include "errors.h"
 #include "iobuf.h"
+#include "memory.h"
 #include "util.h"
 #include "filter.h"
 #include "packet.h"
@@ -52,7 +52,7 @@ dearmor_file( const char *fname )
     if( !(inp = iobuf_open(fname)) ) {
        log_error("can't open %s: %s\n", fname? fname: "[stdin]",
                                        strerror(errno) );
-       rc = GPGERR_OPEN_FILE;
+       rc = G10ERR_OPEN_FILE;
        goto leave;
     }
 
@@ -94,7 +94,7 @@ enarmor_file( const char *fname )
     if( !(inp = iobuf_open(fname)) ) {
        log_error("can't open %s: %s\n", fname? fname: "[stdin]",
                                        strerror(errno) );
-       rc = GPGERR_OPEN_FILE;
+       rc = G10ERR_OPEN_FILE;
        goto leave;
     }
 
index 9812756..297ee34 100644 (file)
@@ -1,5 +1,5 @@
 /* decrypt.c - verify signed data
- *     Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
 #include <errno.h>
 #include <assert.h>
 
-#include <gcrypt.h>
 #include "options.h"
 #include "packet.h"
 #include "errors.h"
 #include "iobuf.h"
 #include "keydb.h"
+#include "memory.h"
 #include "util.h"
 #include "main.h"
+#include "status.h"
 #include "i18n.h"
 
 
@@ -57,7 +58,7 @@ decrypt_message( const char *filename )
     fp = iobuf_open(filename);
     if( !fp ) {
        log_error(_("can't open `%s'\n"), print_fname_stdin(filename));
-       return GPGERR_OPEN_FILE;
+       return G10ERR_OPEN_FILE;
     }
 
     if( !opt.no_armor ) {
@@ -78,5 +79,60 @@ decrypt_message( const char *filename )
     return rc;
 }
 
+void
+decrypt_messages(int nfiles, char **files)
+{
+  IOBUF fp;
+  armor_filter_context_t afx;  
+  char *p, *output = NULL;
+  int rc = 0;
+  
+  if (opt.outfile)
+    {
+      log_error(_("--output doesn't work for this command\n"));
+      return;
+        
+    }
+
+  while (nfiles--)
+    {
+      print_file_status(STATUS_FILE_START, *files, 3);      
+      output = make_outfile_name(*files);
+      if (!output)
+        continue;
+      fp = iobuf_open(*files);
+      if (!fp)
+        {
+          log_error(_("can't open `%s'\n"), print_fname_stdin(*files));
+          continue;
+        }
+      if (!opt.no_armor)
+        {
+          if (use_armor_filter(fp))
+            {
+              memset(&afx, 0, sizeof afx);
+              iobuf_push_filter(fp, armor_filter, &afx);
+            }
+        }
+      rc = proc_packets(NULL, fp);
+      iobuf_close(fp);
+      if (rc)
+        log_error("%s: decryption failed: %s\n", print_fname_stdin(*files),
+                  g10_errstr(rc));
+      p = get_last_passphrase();
+      set_next_passphrase(p);
+      m_free (p);
+      files++;
+      m_free(output);
+      write_status( STATUS_FILE_DONE );
+    }
+  set_next_passphrase(NULL);  
+}
+
+
+
+
+
+
 
 
index f4bfd01..f9d8821 100644 (file)
@@ -1,5 +1,5 @@
 /* delkey.c - delete keys
- *     Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -31,7 +31,7 @@
 #include "errors.h"
 #include "iobuf.h"
 #include "keydb.h"
-#include <gcrypt.h>
+#include "memory.h"
 #include "util.h"
 #include "main.h"
 #include "trustdb.h"
 
 /****************
  * Delete a public or secret key from a keyring.
+ * r_sec_avail will be set if a secret key is available and the public
+ * key can't be deleted for that reason.
  */
-int
-delete_key( const char *username, int secret )
+static int
+do_delete_key( const char *username, int secret, int *r_sec_avail )
 {
     int rc = 0;
     KBNODE keyblock = NULL;
     KBNODE node;
-    KBPOS kbpos;
+    KEYDB_HANDLE hd = keydb_new (secret);
     PKT_public_key *pk = NULL;
     PKT_secret_key *sk = NULL;
     u32 keyid[2];
     int okay=0;
     int yes;
+    KEYDB_SEARCH_DESC desc;
+
+    *r_sec_avail = 0;
 
     /* search the userid */
-    rc = secret? find_secret_keyblock_byname( &keyblock, username )
-              : find_keyblock_byname( &keyblock, username );
-    if( rc ) {
-       log_error(_("%s: user not found: %s\n"), username, gpg_errstr(rc) );
+    classify_user_id (username, &desc);
+    rc = desc.mode? keydb_search (hd, &desc, 1):G10ERR_INV_USER_ID;
+    if (rc) {
+       log_error (_("key `%s' not found: %s\n"), username, g10_errstr (rc));
        write_status_text( STATUS_DELETE_PROBLEM, "1" );
        goto leave;
     }
 
+    /* read the keyblock */
+    rc = keydb_get_keyblock (hd, &keyblock );
+    if (rc) {
+       log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
+       goto leave;
+    }
+
     /* get the keyid from the keyblock */
     node = find_kbnode( keyblock, secret? PKT_SECRET_KEY:PKT_PUBLIC_KEY );
     if( !node ) {
        log_error("Oops; key not found anymore!\n");
-       rc = GPGERR_GENERAL;
+       rc = G10ERR_GENERAL;
        goto leave;
     }
 
@@ -83,15 +95,12 @@ delete_key( const char *username, int secret )
        keyid_from_pk( pk, keyid );
        rc = seckey_available( keyid );
        if( !rc ) {
-           log_error(_(
-           "there is a secret key for this public key!\n"));
-           log_info(_(
-           "use option \"--delete-secret-key\" to delete it first.\n"));
-           write_status_text( STATUS_DELETE_PROBLEM, "2" );
-           rc = -1;
+            *r_sec_avail = 1;
+            rc = -1;
+            goto leave;
        }
-       else if( rc != GPGERR_NO_SECKEY ) {
-           log_error("%s: get secret key: %s\n", username, gpg_errstr(rc) );
+       else if( rc != G10ERR_NO_SECKEY ) {
+           log_error("%s: get secret key: %s\n", username, g10_errstr(rc) );
        }
        else
            rc = 0;
@@ -113,15 +122,15 @@ delete_key( const char *username, int secret )
            tty_printf("sec  %4u%c/%08lX %s   ",
                      nbits_from_sk( sk ),
                      pubkey_letter( sk->pubkey_algo ),
-                     keyid[1], datestr_from_sk(sk) );
+                     (ulong)keyid[1], datestr_from_sk(sk) );
        else
            tty_printf("pub  %4u%c/%08lX %s   ",
                      nbits_from_pk( pk ),
                      pubkey_letter( pk->pubkey_algo ),
-                     keyid[1], datestr_from_pk(pk) );
+                     (ulong)keyid[1], datestr_from_pk(pk) );
        p = get_user_id( keyid, &n );
        tty_print_utf8_string( p, n );
-       gcry_free(p);
+       m_free(p);
        tty_printf("\n\n");
 
        yes = cpr_get_answer_is_yes( secret? "delete_key.secret.okay"
@@ -142,16 +151,59 @@ delete_key( const char *username, int secret )
 
 
     if( okay ) {
-      #warning MUST FIX THIS!!!
-       rc = delete_keyblock( &kbpos );
-       if( rc ) {
-           log_error("delete_keyblock failed: %s\n", gpg_errstr(rc) );
+       rc = keydb_delete_keyblock (hd);
+       if (rc) {
+           log_error (_("deleting keyblock failed: %s\n"), g10_errstr(rc) );
            goto leave;
        }
+
+       /* Note that the ownertrust being cleared will trigger a
+           revalidation_mark().  This makes sense - only deleting keys
+           that have ownertrust set should trigger this. */
+
+        if (!secret && pk && clear_ownertrust (pk)) {
+          if (opt.verbose)
+            log_info (_("ownertrust information cleared\n"));
+        }
     }
 
   leave:
-    release_kbnode( keyblock );
+    keydb_release (hd);
+    release_kbnode (keyblock);
     return rc;
 }
 
+/****************
+ * Delete a public or secret key from a keyring.
+ */
+int
+delete_keys( STRLIST names, int secret, int allow_both )
+{
+    int rc, avail;
+
+    for(;names;names=names->next) {
+       rc = do_delete_key (names->d, secret, &avail );
+       if ( rc && avail ) { 
+        if ( allow_both ) {
+          rc = do_delete_key (names->d, 1, &avail );
+          if ( !rc )
+            rc = do_delete_key (names->d, 0, &avail );
+        }
+        else {
+          log_error(_(
+             "there is a secret key for public key \"%s\"!\n"),names->d);
+          log_info(_(
+             "use option \"--delete-secret-keys\" to delete it first.\n"));
+          write_status_text( STATUS_DELETE_PROBLEM, "2" );
+          return rc;
+        }
+       }
+
+       if(rc) {
+        log_error("%s: delete key failed: %s\n", names->d, g10_errstr(rc) );
+        return rc;
+       }
+    }
+
+    return 0;
+}
index f033c76..80a9039 100644 (file)
@@ -1,5 +1,5 @@
 /* encode.c - encode data
- *     Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
 #include "errors.h"
 #include "iobuf.h"
 #include "keydb.h"
-#include <gcrypt.h>
+#include "memory.h"
 #include "util.h"
 #include "main.h"
 #include "filter.h"
 #include "trustdb.h"
 #include "i18n.h"
+#include "status.h"
 
-
-static int encode_simple( const char *filename, int mode );
+static int encode_simple( const char *filename, int mode, int compat );
 static int write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out );
 
 
-/****************
- * Emulate our old PK interface here - sometime in the future we might
- * change the internal design to directly fit to libgcrypt.
- */
-static int
-pk_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
-{
-    GCRY_SEXP s_ciph, s_data, s_pkey;
-    int rc;
-
-    /* make a sexp from pkey */
-    if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
-       rc = gcry_sexp_build ( &s_pkey, NULL,
-                             "(public-key(elg(p%m)(g%m)(y%m)))",
-                                 pkey[0], pkey[1], pkey[2] );
-    }
-    else
-       return GPGERR_PUBKEY_ALGO;
-
-    if ( rc )
-       BUG ();
-
-    /* put the data into a simple list */
-    if ( gcry_sexp_build( &s_data, NULL, "%m", data ) )
-       BUG ();
-
-    /* pass it to libgcrypt */
-    rc = gcry_pk_encrypt( &s_ciph, s_data, s_pkey );
-    gcry_sexp_release( s_data );
-    gcry_sexp_release( s_pkey );
-
-    if( rc )
-       ;
-    else { /* add better error handling or make gnupg use S-Exp directly */
-       GCRY_SEXP list = gcry_sexp_find_token( s_ciph, "a" , 0 );
-       assert( list );
-       resarr[0] = gcry_sexp_nth_mpi( list, 1, 0 );
-       assert( resarr[0] );
-       gcry_sexp_release ( list );
-
-       list = gcry_sexp_find_token( s_ciph, "b" , 0 );
-       assert( list );
-       resarr[1] = gcry_sexp_nth_mpi( list, 1, 0 );
-       assert( resarr[1] );
-       gcry_sexp_release ( list );
-    }
-
-    gcry_sexp_release( s_ciph );
-    return rc;
-}
-
 
 /****************
  * Encode FILENAME with only the symmetric cipher.  Take input from
@@ -101,7 +50,11 @@ pk_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
 int
 encode_symmetric( const char *filename )
 {
-    return encode_simple( filename, 1 );
+    int compat = 1;
+    
+    if ( opt.expert )
+        compat = 0; /* PGP knows how to handle this mode. */
+    return encode_simple( filename, 1, compat );
 }
 
 /****************
@@ -111,19 +64,49 @@ encode_symmetric( const char *filename )
 int
 encode_store( const char *filename )
 {
-    return encode_simple( filename, 0 );
+    return encode_simple( filename, 0, 1 );
 }
 
-
+static void
+encode_sesskey( DEK *dek, DEK **ret_dek, byte *enckey )
+{
+    CIPHER_HANDLE hd;
+    DEK *c;
+    byte buf[33];
+
+    assert ( dek->keylen < 32 );
+    
+    c = m_alloc_clear( sizeof *c );
+    c->keylen = dek->keylen;
+    c->algo = dek->algo;
+    make_session_key( c );
+    /*log_hexdump( "thekey", c->key, c->keylen );*/
+
+    buf[0] = c->algo;
+    memcpy( buf + 1, c->key, c->keylen );
+    
+    hd = cipher_open( dek->algo, CIPHER_MODE_CFB, 1 );
+    cipher_setkey( hd, dek->key, dek->keylen );
+    cipher_setiv( hd, NULL, 0 );
+    cipher_encrypt( hd, buf, buf, c->keylen + 1 );
+    cipher_close( hd );
+
+    memcpy( enckey, buf, c->keylen + 1 );
+    memset( buf, 0, sizeof buf ); /* burn key */
+    *ret_dek = c;
+}
 
 static int
-encode_simple( const char *filename, int mode )
+encode_simple( const char *filename, int mode, int compat )
 {
     IOBUF inp, out;
     PACKET pkt;
+    DEK *dek = NULL;
     PKT_plaintext *pt = NULL;
     STRING2KEY *s2k = NULL;
+    byte enckey[33];
     int rc = 0;
+    int seskeylen = 0;
     u32 filesize;
     cipher_filter_context_t cfx;
     armor_filter_context_t afx;
@@ -136,40 +119,62 @@ encode_simple( const char *filename, int mode )
     memset( &zfx, 0, sizeof zfx);
     memset( &tfx, 0, sizeof tfx);
     init_packet(&pkt);
+    
+    if (opt.compress == -1 && is_file_compressed(filename, &rc))
+      {
+        if (opt.verbose)
+          log_info(_("`%s' already compressed\n"), filename);
+        do_compress = 0;        
+      }
+    if (rc)
+        return rc;
 
     /* prepare iobufs */
     if( !(inp = iobuf_open(filename)) ) {
        log_error(_("%s: can't open: %s\n"), filename? filename: "[stdin]",
                                        strerror(errno) );
-       return GPGERR_OPEN_FILE;
+       return G10ERR_OPEN_FILE;
     }
 
     if( opt.textmode )
        iobuf_push_filter( inp, text_filter, &tfx );
 
+    /* Due the the fact that we use don't use an IV to encrypt the
+       session key we can't use the new mode with RFC1991 because
+       it has no S2K salt. RFC1991 always uses simple S2K. */
+    if ( opt.rfc1991 && !compat )
+        compat = 1;
+    
     cfx.dek = NULL;
     if( mode ) {
-       s2k = gcry_xcalloc( 1, sizeof *s2k );
+       s2k = m_alloc_clear( sizeof *s2k );
        s2k->mode = opt.rfc1991? 0:opt.s2k_mode;
        s2k->hash_algo = opt.def_digest_algo ? opt.def_digest_algo
                                             : opt.s2k_digest_algo;
        cfx.dek = passphrase_to_dek( NULL, 0,
-                      opt.def_cipher_algo ? opt.def_cipher_algo
-                                          : opt.s2k_cipher_algo , s2k, 2 );
+                  opt.def_cipher_algo ? opt.def_cipher_algo
+                                     : opt.s2k_cipher_algo , s2k, 2, NULL );
        if( !cfx.dek || !cfx.dek->keylen ) {
-           rc = GPGERR_PASSPHRASE;
-           gcry_free(cfx.dek);
-           gcry_free(s2k);
+           rc = G10ERR_PASSPHRASE;
+           m_free(cfx.dek);
+           m_free(s2k);
            iobuf_close(inp);
-           log_error(_("error creating passphrase: %s\n"), gpg_errstr(rc) );
+           log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) );
            return rc;
        }
+        if ( !compat ) {            
+            seskeylen = cipher_get_keylen( opt.def_cipher_algo ?
+                                           opt.def_cipher_algo:
+                                           opt.s2k_cipher_algo ) / 8;
+            encode_sesskey( cfx.dek, &dek, enckey );
+            m_free( cfx.dek ); cfx.dek = dek;
+        }
     }
 
     if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) {
        iobuf_cancel(inp);
-       gcry_free(cfx.dek);
-       gcry_free(s2k);
+       m_free(cfx.dek);
+       m_free(s2k);
        return rc;
     }
 
@@ -184,15 +189,19 @@ encode_simple( const char *filename, int mode )
     }
   #endif
     if( s2k && !opt.rfc1991 ) {
-       PKT_symkey_enc *enc = gcry_xcalloc( 1, sizeof *enc );
+       PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc + seskeylen + 1 );
        enc->version = 4;
        enc->cipher_algo = cfx.dek->algo;
        enc->s2k = *s2k;
+        if ( !compat && seskeylen ) {
+            enc->seskeylen = seskeylen + 1; /* algo id */
+            memcpy( enc->seskey, enckey, seskeylen + 1 );
+        }
        pkt.pkttype = PKT_SYMKEY_ENC;
        pkt.pkt.symkey_enc = enc;
        if( (rc = build_packet( out, &pkt )) )
-           log_error("build symkey packet failed: %s\n", gpg_errstr(rc) );
-       gcry_free(enc);
+           log_error("build symkey packet failed: %s\n", g10_errstr(rc) );
+       m_free(enc);
     }
 
     if (!opt.no_literal) {
@@ -200,30 +209,36 @@ encode_simple( const char *filename, int mode )
        if( filename || opt.set_filename ) {
            char *s = make_basename( opt.set_filename ? opt.set_filename
                                                      : filename );
-           pt = gcry_xmalloc( sizeof *pt + strlen(s) - 1 );
+           pt = m_alloc( sizeof *pt + strlen(s) - 1 );
            pt->namelen = strlen(s);
            memcpy(pt->name, s, pt->namelen );
-           gcry_free(s);
+           m_free(s);
        }
        else { /* no filename */
-           pt = gcry_xmalloc( sizeof *pt - 1 );
+           pt = m_alloc( sizeof *pt - 1 );
            pt->namelen = 0;
        }
     }
 
-    /* pgp5 has problems to decrypt symmetrically encrypted data from
-     * GnuPG if the filelength is in the inner packet. It works
-     * when only partial length headers are use.  Until we have
-     * tracked this problem down. We use this temporary fix
-     * (fixme: remove the && !mode )
-     */
-    if( filename && !opt.textmode && !mode ) {
+    /* Note that PGP 5 has problems decrypting symmetrically encrypted
+       data if the file length is in the inner packet. It works when
+       only partial length headers are use.  In the past, we always
+       used partial body length here, but since PGP 2, PGP 6, and PGP
+       7 need the file length, and nobody should be using PGP 5
+       nowadays anyway, this is now set to the file length.  Note also
+       that this only applies to the RFC-1991 style symmetric
+       messages, and not the RFC-2440 style.  PGP 6 and 7 work with
+       either partial length or fixed length with the new style
+       messages. */
+
+    if( filename && !opt.textmode ) {
        if( !(filesize = iobuf_get_filelength(inp)) )
            log_info(_("%s: WARNING: empty file\n"), filename );
         /* we can't yet encode the length of very large files,
-         * so we switch to partial length encoding in this case */
+         * so we switch to partial lengthn encoding in this case */
         if ( filesize >= IOBUF_FILELENGTH_LIMIT )
             filesize = 0;
+
     }
     else
        filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
@@ -239,7 +254,11 @@ encode_simple( const char *filename, int mode )
        cfx.datalen = filesize && !do_compress ? calc_packet_length( &pkt ) : 0;
     }
     else
-       cfx.datalen = filesize && !do_compress ? filesize : 0;
+      {
+        cfx.datalen = filesize && !do_compress ? filesize : 0;
+        pkt.pkttype = 0;
+        pkt.pkt.generic = NULL;
+      }
 
     /* register the cipher filter */
     if( mode )
@@ -251,7 +270,7 @@ encode_simple( const char *filename, int mode )
     /* do the work */
     if (!opt.no_literal) {
        if( (rc = build_packet( out, &pkt )) )
-           log_error("build_packet failed: %s\n", gpg_errstr(rc) );
+           log_error("build_packet failed: %s\n", g10_errstr(rc) );
     }
     else {
        /* user requested not to create a literal packet,
@@ -260,8 +279,8 @@ encode_simple( const char *filename, int mode )
        int  bytes_copied;
        while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
            if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
-               rc = GPGERR_WRITE_FILE;
-               log_error("copying input to output failed: %s\n", gpg_errstr(rc) );
+               rc = G10ERR_WRITE_FILE;
+               log_error("copying input to output failed: %s\n", g10_errstr(rc) );
                break;
            }
        memset(copy_buffer, 0, 4096); /* burn buffer */
@@ -271,13 +290,16 @@ encode_simple( const char *filename, int mode )
     iobuf_close(inp);
     if (rc)
        iobuf_cancel(out);
-    else
+    else {
        iobuf_close(out); /* fixme: check returncode */
+        if (mode)
+            write_status( STATUS_END_ENCRYPTION );
+    }
     if (pt)
        pt->buf = NULL;
     free_packet(&pkt);
-    gcry_free(cfx.dek);
-    gcry_free(s2k);
+    m_free(cfx.dek);
+    m_free(s2k);
     return rc;
 }
 
@@ -291,123 +313,203 @@ encode_crypt( const char *filename, STRLIST remusr )
     IOBUF inp = NULL, out = NULL;
     PACKET pkt;
     PKT_plaintext *pt = NULL;
-    int rc = 0;
+    int rc = 0, rc2 = 0;
     u32 filesize;
+    cipher_filter_context_t cfx;
     armor_filter_context_t afx;
     compress_filter_context_t zfx;
     text_filter_context_t tfx;
-    encrypt_filter_context_t efx;
-    PK_LIST pk_list;
+    PK_LIST pk_list,work_list;
     int do_compress = opt.compress && !opt.rfc1991;
 
+
+    memset( &cfx, 0, sizeof cfx);
     memset( &afx, 0, sizeof afx);
     memset( &zfx, 0, sizeof zfx);
     memset( &tfx, 0, sizeof tfx);
-    memset( &efx, 0, sizeof efx);
     init_packet(&pkt);
 
-    if( (rc=build_pk_list( remusr, &pk_list, GCRY_PK_USAGE_ENCR)) )
+    if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) )
        return rc;
 
+    if(opt.pgp2) {
+      for(work_list=pk_list; work_list; work_list=work_list->next)
+       if(!(is_RSA(work_list->pk->pubkey_algo) &&
+            nbits_from_pk(work_list->pk)<=2048))
+         {
+           log_info(_("you can only encrypt to RSA keys of 2048 bits or "
+                      "less in --pgp2 mode\n"));
+           log_info(_("this message may not be usable by PGP 2.x\n"));
+           opt.pgp2=0;
+           break;
+         }
+    }
+
+    if (opt.compress == -1 && is_file_compressed(filename, &rc2))
+      {
+        if (opt.verbose)
+          log_info(_("`%s' already compressed\n"), filename);
+        do_compress = 0;        
+      }
+    if (rc2)
+      {
+        rc = rc2;
+        goto leave;
+      }
+    
     /* prepare iobufs */
     if( !(inp = iobuf_open(filename)) ) {
        log_error(_("can't open %s: %s\n"), filename? filename: "[stdin]",
                                        strerror(errno) );
-       rc = GPGERR_OPEN_FILE;
+       rc = G10ERR_OPEN_FILE;
        goto leave;
     }
     else if( opt.verbose )
        log_info(_("reading from `%s'\n"), filename? filename: "[stdin]");
 
-    /* If the user selected textmode, push the text filter onto the input */
     if( opt.textmode )
        iobuf_push_filter( inp, text_filter, &tfx );
 
-    /* Now we can create the outputfile */
     if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) )
        goto leave;
 
-    /* The first thing we have to push on the output stream
-     * is the armor filter */
+
     if( opt.armor )
        iobuf_push_filter( out, armor_filter, &afx );
+  #ifdef ENABLE_COMMENT_PACKETS
+    else {
+       write_comment( out, "#created by GNUPG v" VERSION " ("
+                                           PRINTABLE_OS_NAME ")");
+       if( opt.comment_string )
+           write_comment( out, opt.comment_string );
+    }
+  #endif
+    /* create a session key */
+    cfx.dek = m_alloc_secure_clear (sizeof *cfx.dek);
+    if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
+       cfx.dek->algo = select_algo_from_prefs(pk_list,PREFTYPE_SYM,-1,NULL);
+       /* The only way select_algo_from_prefs can fail here is when
+           mixing v3 and v4 keys, as v4 keys have an implicit
+           preference entry for 3DES, and the pk_list cannot be empty.
+           In this case, use 3DES anyway as it's the safest choice -
+           perhaps the v3 key is being used in an OpenPGP
+           implementation and we know that the implementation behind
+           any v4 key can handle 3DES. */
+       if( cfx.dek->algo == -1 ) {
+           cfx.dek->algo = CIPHER_ALGO_3DES;
+
+           if( opt.pgp2 ) {
+             log_info(_("unable to use the IDEA cipher for all of the keys "
+                        "you are encrypting to.\n"));
+             log_info(_("this message may not be usable by PGP 2.x\n"));
+             opt.pgp2=0;
+           }
+       }
+    }
+    else {
+      if(!opt.expert &&
+        select_algo_from_prefs(pk_list,PREFTYPE_SYM,
+                               opt.def_cipher_algo,NULL)!=opt.def_cipher_algo)
+       log_info(_("forcing symmetric cipher %s (%d) "
+                  "violates recipient preferences\n"),
+                cipher_algo_to_string(opt.def_cipher_algo),
+                opt.def_cipher_algo);
+
+      cfx.dek->algo = opt.def_cipher_algo;
+    }
+    cfx.dek->use_mdc = select_mdc_from_pklist (pk_list);
 
-    /* Prepare the plaintext packet */
-    {
-        if (!opt.no_literal) {
-            if( filename || opt.set_filename ) {
-                char *s = make_basename( opt.set_filename ?
-                                         opt.set_filename : filename );
-                pt = gcry_xmalloc( sizeof *pt + strlen(s) - 1 );
-                pt->namelen = strlen(s);
-                memcpy(pt->name, s, pt->namelen );
-                gcry_free(s);
-            }
-            else { /* no filename */
-                pt = gcry_xmalloc( sizeof *pt - 1 );
-                pt->namelen = 0;
-            }
-        }
-        
-        if( filename && !opt.textmode ) {
-            if( !(filesize = iobuf_get_filelength(inp)) )
-                log_info(_("%s: WARNING: empty file\n"), filename );
-            /* we can't yet encode the length of very large files,
-             * so we switch to partial lengthn encoding in this case */
-            if ( filesize >= IOBUF_FILELENGTH_LIMIT )
-                filesize = 0;
-        }
-        else
-            filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
-        
-        if (!opt.no_literal) {
-            pt->timestamp = make_timestamp();
-            pt->mode = opt.textmode ? 't' : 'b';
-            pt->len = filesize;
-            pt->new_ctb = !pt->len && !opt.rfc1991;
-            pt->buf = inp;
-            pkt.pkttype = PKT_PLAINTEXT;
-            pkt.pkt.plaintext = pt;
-            efx.cfx.datalen = filesize && !do_compress?
-                calc_packet_length( &pkt ) : 0;
-        }
-        else
-            efx.cfx.datalen = filesize && !do_compress ? filesize : 0;
-    }  /* end preparation of plaintext packet */
-        
-    /* push in the actual encryption filter */
-    efx.pk_list = pk_list;
-    iobuf_push_filter( out, encrypt_filter, &efx ); 
-
-    /* register the compress filter (so that it is done before encryption) */
+    make_session_key( cfx.dek );
+    if( DBG_CIPHER )
+       log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );
+
+    rc = write_pubkey_enc_from_list( pk_list, cfx.dek, out );
+    if( rc  )
+       goto leave;
+
+    if (!opt.no_literal) {
+       /* setup the inner packet */
+       if( filename || opt.set_filename ) {
+           char *s = make_basename( opt.set_filename ? opt.set_filename : filename );
+           pt = m_alloc( sizeof *pt + strlen(s) - 1 );
+           pt->namelen = strlen(s);
+           memcpy(pt->name, s, pt->namelen );
+           m_free(s);
+       }
+       else { /* no filename */
+           pt = m_alloc( sizeof *pt - 1 );
+           pt->namelen = 0;
+       }
+    }
+
+    if( filename && !opt.textmode ) {
+       if( !(filesize = iobuf_get_filelength(inp)) )
+           log_info(_("%s: WARNING: empty file\n"), filename );
+        /* we can't yet encode the length of very large files,
+         * so we switch to partial length encoding in this case */
+        if ( filesize >= IOBUF_FILELENGTH_LIMIT )
+            filesize = 0;
+    }
+    else
+       filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
+
+    if (!opt.no_literal) {
+       pt->timestamp = make_timestamp();
+       pt->mode = opt.textmode ? 't' : 'b';
+       pt->len = filesize;
+       pt->new_ctb = !pt->len && !opt.rfc1991;
+       pt->buf = inp;
+       pkt.pkttype = PKT_PLAINTEXT;
+       pkt.pkt.plaintext = pt;
+       cfx.datalen = filesize && !do_compress? calc_packet_length( &pkt ) : 0;
+    }
+    else
+       cfx.datalen = filesize && !do_compress ? filesize : 0;
+
+    /* register the cipher filter */
+    iobuf_push_filter( out, cipher_filter, &cfx );
+
+    /* register the compress filter */
     if( do_compress ) {
-       int compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_COMPR );
-       if( !compr_algo )
-           ; /* don't use compression */
-       else {
-           if( compr_algo == 1 )
-               zfx.algo = 1; /* default is 2 */
+       int compr_algo = opt.def_compress_algo;
+
+       if(compr_algo==-1)
+         {
+           if((compr_algo=
+               select_algo_from_prefs(pk_list,PREFTYPE_ZIP,-1,NULL))==-1)
+             compr_algo=DEFAULT_COMPRESS_ALGO;
+         }
+       else if(!opt.expert &&
+               select_algo_from_prefs(pk_list,PREFTYPE_ZIP,
+                                      compr_algo,NULL)!=compr_algo)
+         log_info(_("forcing compression algorithm %s (%d) "
+                    "violates recipient preferences\n"),
+                  compress_algo_to_string(compr_algo),compr_algo);
+
+       /* algo 0 means no compression */
+       if( compr_algo )
+         {
+           zfx.algo = compr_algo;
            iobuf_push_filter( out, compress_filter, &zfx );
-       }
+         }
     }
 
     /* do the work */
     if (!opt.no_literal) {
        if( (rc = build_packet( out, &pkt )) )
-           log_error("build_packet failed: %s\n", gpg_errstr(rc) );
+           log_error("build_packet failed: %s\n", g10_errstr(rc) );
     }
     else {
-       /* user requested not to create a literal packet,
-         * so we copy the plain data */
+       /* user requested not to create a literal packet, so we copy the plain data */
        byte copy_buffer[4096];
        int  bytes_copied;
        while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
            if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
-               rc = GPGERR_WRITE_FILE;
-               log_error("copying input to output failed: %s\n", gpg_errstr(rc) );
+               rc = G10ERR_WRITE_FILE;
+               log_error("copying input to output failed: %s\n", g10_errstr(rc) );
                break;
            }
-       memset(copy_buffer, 0, DIM(copy_buffer)); /* burn buffer */
+       memset(copy_buffer, 0, 4096); /* burn buffer */
     }
 
     /* finish the stuff */
@@ -415,13 +517,14 @@ encode_crypt( const char *filename, STRLIST remusr )
     iobuf_close(inp);
     if( rc )
        iobuf_cancel(out);
-    else
+    else {
        iobuf_close(out); /* fixme: check returncode */
+        write_status( STATUS_END_ENCRYPTION );
+    }
     if( pt )
        pt->buf = NULL;
     free_packet(&pkt);
-    gcry_free(efx.cfx.dek); /* Hmmm, why does the encrypt filter does not 
-                             * take care about this? */
+    m_free(cfx.dek);
     release_pk_list( pk_list );
     return rc;
 }
@@ -430,7 +533,7 @@ encode_crypt( const char *filename, STRLIST remusr )
 
 
 /****************
- * Filter to handle the entire public key encryption.
+ * Filter to do a complete public key encryption.
  */
 int
 encrypt_filter( void *opaque, int control,
@@ -445,16 +548,32 @@ encrypt_filter( void *opaque, int control,
     }
     else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
        if( !efx->header_okay ) {
-           efx->cfx.dek = gcry_xmalloc_secure( sizeof *efx->cfx.dek );
+           efx->cfx.dek = m_alloc_secure_clear( sizeof *efx->cfx.dek );
 
            if( !opt.def_cipher_algo  ) { /* try to get it from the prefs */
                efx->cfx.dek->algo =
-                         select_algo_from_prefs( efx->pk_list, PREFTYPE_SYM );
-               if( efx->cfx.dek->algo == -1 )
+                 select_algo_from_prefs(efx->pk_list,PREFTYPE_SYM,-1,NULL);
+               if( efx->cfx.dek->algo == -1 ) {
+                    /* because 3DES is implicitly in the prefs, this can only
+                     * happen if we do not have any public keys in the list */
                    efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO;
+                }
+           }
+           else {
+             if(!opt.expert &&
+                select_algo_from_prefs(efx->pk_list,PREFTYPE_SYM,
+                                       opt.def_cipher_algo,
+                                       NULL)!=opt.def_cipher_algo)
+               log_info(_("forcing symmetric cipher %s (%d) "
+                          "violates recipient preferences\n"),
+                        cipher_algo_to_string(opt.def_cipher_algo),
+                        opt.def_cipher_algo);
+
+             efx->cfx.dek->algo = opt.def_cipher_algo;
            }
-           else
-               efx->cfx.dek->algo = opt.def_cipher_algo;
+
+            efx->cfx.dek->use_mdc = select_mdc_from_pklist (efx->pk_list);
+
            make_session_key( efx->cfx.dek );
            if( DBG_CIPHER )
                log_hexdump("DEK is: ",
@@ -497,7 +616,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
        pk = pk_list->pk;
 
        print_pubkey_algo_note( pk->pubkey_algo );
-       enc = gcry_xcalloc( 1, sizeof *enc );
+       enc = m_alloc_clear( sizeof *enc );
        enc->pubkey_algo = pk->pubkey_algo;
        keyid_from_pk( pk, enc->keyid );
        enc->throw_keyid = opt.throw_keyid;
@@ -517,17 +636,17 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
         */
        frame = encode_session_key( dek, pubkey_nbits( pk->pubkey_algo,
                                                          pk->pkey ) );
-       rc = pk_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey );
-       mpi_release( frame );
+       rc = pubkey_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey );
+       mpi_free( frame );
        if( rc )
-           log_error("pubkey_encrypt failed: %s\n", gpg_errstr(rc) );
+           log_error("pubkey_encrypt failed: %s\n", g10_errstr(rc) );
        else {
            if( opt.verbose ) {
                char *ustr = get_user_id_string_native( enc->keyid );
                log_info(_("%s/%s encrypted for: %s\n"),
-                   gcry_pk_algo_name(enc->pubkey_algo),
-                   gcry_cipher_algo_name(dek->algo), ustr );
-               gcry_free(ustr);
+                   pubkey_algo_to_string(enc->pubkey_algo),
+                   cipher_algo_to_string(dek->algo), ustr );
+               m_free(ustr);
            }
            /* and write it */
            init_packet(&pkt);
@@ -535,7 +654,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
            pkt.pkt.pubkey_enc = enc;
            rc = build_packet( out, &pkt );
            if( rc )
-              log_error("build_packet(pubkey_enc) failed: %s\n", gpg_errstr(rc));
+              log_error("build_packet(pubkey_enc) failed: %s\n", g10_errstr(rc));
        }
        free_pubkey_enc(enc);
        if( rc )
@@ -544,3 +663,47 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
     return 0;
 }
 
+void
+encode_crypt_files(int nfiles, char **files, STRLIST remusr)
+{
+  int rc = 0;
+
+  if (opt.outfile)
+    {
+      log_error(_("--output doesn't work for this command\n"));
+      return;        
+    }
+    
+  if (!nfiles)
+    {
+      char line[2048];
+      unsigned int lno = 0;
+      while ( fgets(line, DIM(line), stdin) )
+        {
+          lno++;
+          if (!*line || line[strlen(line)-1] != '\n')
+            {
+              log_error("input line %u too long or missing LF\n", lno);
+              return;
+            }
+          line[strlen(line)-1] = '\0';
+          print_file_status(STATUS_FILE_START, line, 2);
+          if ( (rc = encode_crypt(line, remusr)) )
+            log_error("%s: encryption failed: %s\n",
+                      print_fname_stdin(line), g10_errstr(rc) );
+          write_status( STATUS_FILE_DONE );
+        }
+    }
+  else
+    {
+      while (nfiles--)
+        {
+          print_file_status(STATUS_FILE_START, *files, 2);
+          if ( (rc = encode_crypt(*files, remusr)) )
+            log_error("%s: encryption failed: %s\n",
+                      print_fname_stdin(*files), g10_errstr(rc) );
+          write_status( STATUS_FILE_DONE );
+          files++;
+        }
+    }
+}
index 17d43e9..c8a8c85 100644 (file)
@@ -1,5 +1,5 @@
 /* encr-data.c -  process an encrypted data packet
- *     Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
-
-#include <gcrypt.h>
 #include "util.h"
+#include "memory.h"
 #include "packet.h"
+#include "mpi.h"
+#include "cipher.h"
 #include "options.h"
 #include "i18n.h"
 
@@ -37,8 +38,8 @@ static int decode_filter( void *opaque, int control, IOBUF a,
                                        byte *buf, size_t *ret_len);
 
 typedef struct {
-    GCRY_CIPHER_HD cipher_hd;
-    GCRY_MD_HD mdc_hash;
+    CIPHER_HANDLE cipher_hd;
+    MD_HANDLE mdc_hash;
     char defer[20];
     int  defer_filled;
     int  eof_seen;
@@ -55,20 +56,21 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
     byte *p;
     int rc=0, c, i;
     byte temp[32];
-    unsigned int blocksize;
-    unsigned int nprefix;
+    unsigned blocksize;
+    unsigned nprefix;
 
     memset( &dfx, 0, sizeof dfx );
-    if( gcry_cipher_test_algo( dek->algo ) ) {
-       if( opt.verbose )
+    if( opt.verbose && !dek->algo_info_printed ) {
+       const char *s = cipher_algo_to_string( dek->algo );
+       if( s )
+           log_info(_("%s encrypted data\n"), s );
+       else
            log_info(_("encrypted with unknown algorithm %d\n"), dek->algo );
-       rc = GPGERR_CIPHER_ALGO;
-       goto leave;
+        dek->algo_info_printed = 1;
     }
-    if( opt.verbose )
-       log_info(_("%s encrypted data\n"), gcry_cipher_algo_name( dek->algo ) );
-
-    blocksize = gcry_cipher_get_algo_blklen( dek->algo );
+    if( (rc=check_cipher_algo(dek->algo)) )
+       goto leave;
+    blocksize = cipher_get_blocksize(dek->algo);
     if( !blocksize || blocksize > 16 )
        log_fatal("unsupported blocksize %u\n", blocksize );
     nprefix = blocksize;
@@ -76,36 +78,28 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
        BUG();
 
     if( ed->mdc_method ) {
-       dfx.mdc_hash = gcry_md_open( ed->mdc_method, 0 );
+       dfx.mdc_hash = md_open( ed->mdc_method, 0 );
        if ( DBG_HASHING )
-           gcry_md_start_debug(dfx.mdc_hash, "checkmdc");
+           md_start_debug(dfx.mdc_hash, "checkmdc");
     }
-    if( !(dfx.cipher_hd = gcry_cipher_open( dek->algo,
-                                     GCRY_CIPHER_MODE_CFB,
-                                     GCRY_CIPHER_SECURE
-                                     | ((ed->mdc_method || dek->algo >= 100)?
-                                          0 : GCRY_CIPHER_ENABLE_SYNC) ))
-                                   ) {
-       /* we should never get an error here cause we already checked, that
-        * the algorithm is available. What about a flag to let the function
-        * die in this case? */
-       BUG();
-    }
-
-
+    dfx.cipher_hd = cipher_open( dek->algo,
+                                ed->mdc_method? CIPHER_MODE_CFB
+                                              : CIPHER_MODE_AUTO_CFB, 1 );
 /* log_hexdump( "thekey", dek->key, dek->keylen );*/
-    rc = gcry_cipher_setkey( dfx.cipher_hd, dek->key, dek->keylen );
-    if( rc == GCRYERR_WEAK_KEY ) {
+    rc = cipher_setkey( dfx.cipher_hd, dek->key, dek->keylen );
+    if( rc == G10ERR_WEAK_KEY )
        log_info(_("WARNING: message was encrypted with "
                    "a weak key in the symmetric cipher.\n"));
-       rc = 0;
-    }
     else if( rc ) {
-       log_error("key setup failed: %s\n", gcry_strerror(rc) );
+       log_error("key setup failed: %s\n", g10_errstr(rc) );
        goto leave;
     }
+    if (!ed->buf) {
+        log_error(_("problem handling encrypted packet\n"));
+        goto leave;
+    }
 
-    gcry_cipher_setiv( dfx.cipher_hd, NULL, 0 );
+    cipher_setiv( dfx.cipher_hd, NULL, 0 );
 
     if( ed->len ) {
        for(i=0; i < (nprefix+2) && ed->len; i++, ed->len-- ) {
@@ -122,17 +116,17 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
            else
                temp[i] = c;
     }
-    gcry_cipher_decrypt( dfx.cipher_hd, temp, nprefix+2, NULL, 0 );
-    gcry_cipher_sync( dfx.cipher_hd );
+    cipher_decrypt( dfx.cipher_hd, temp, temp, nprefix+2);
+    cipher_sync( dfx.cipher_hd );
     p = temp;
 /* log_hexdump( "prefix", temp, nprefix+2 ); */
     if( p[nprefix-2] != p[nprefix] || p[nprefix-1] != p[nprefix+1] ) {
-       rc = GPGERR_BAD_KEY;
+       rc = G10ERR_BAD_KEY;
        goto leave;
     }
 
     if( dfx.mdc_hash )
-       gcry_md_write( dfx.mdc_hash, temp, nprefix+2 );
+       md_write( dfx.mdc_hash, temp, nprefix+2 );
 
     if( ed->mdc_method )
        iobuf_push_filter( ed->buf, mdc_decode_filter, &dfx );
@@ -142,21 +136,23 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
     proc_packets( procctx, ed->buf );
     ed->buf = NULL;
     if( ed->mdc_method && dfx.eof_seen == 2 )
-       rc = GPGERR_INVALID_PACKET;
+       rc = G10ERR_INVALID_PACKET;
     else if( ed->mdc_method ) { /* check the mdc */
-       int datalen = gcry_md_get_algo_dlen( ed->mdc_method );
+       int datalen = md_digest_length( ed->mdc_method );
 
-       gcry_cipher_decrypt( dfx.cipher_hd, dfx.defer, 20, NULL, 0);
+       cipher_decrypt( dfx.cipher_hd, dfx.defer, dfx.defer, 20);
+       md_final( dfx.mdc_hash );
        if( datalen != 20
-           || memcmp(gcry_md_read( dfx.mdc_hash, 0 ), dfx.defer, datalen) )
-           rc = GPGERR_BAD_SIGN;
+           || memcmp(md_read( dfx.mdc_hash, 0 ), dfx.defer, datalen) )
+           rc = G10ERR_BAD_SIGN;
        /*log_hexdump("MDC calculated:", md_read( dfx.mdc_hash, 0), datalen);*/
        /*log_hexdump("MDC message   :", dfx.defer, 20);*/
     }
+    
 
   leave:
-    gcry_cipher_close(dfx.cipher_hd);
-    gcry_md_close( dfx.mdc_hash );
+    cipher_close(dfx.cipher_hd);
+    md_close( dfx.mdc_hash );
     return rc;
 }
 
@@ -222,8 +218,8 @@ mdc_decode_filter( void *opaque, int control, IOBUF a,
        }
 
        if( n ) {
-           gcry_cipher_decrypt( dfx->cipher_hd, buf, n, NULL, 0);
-           gcry_md_write( dfx->mdc_hash, buf, n );
+           cipher_decrypt( dfx->cipher_hd, buf, buf, n);
+           md_write( dfx->mdc_hash, buf, n );
        }
        else {
            assert( dfx->eof_seen );
@@ -249,7 +245,7 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
        n = iobuf_read( a, buf, size );
        if( n == -1 ) n = 0;
        if( n )
-           gcry_cipher_decrypt( fc->cipher_hd, buf, n, NULL, 0 );
+           cipher_decrypt( fc->cipher_hd, buf, buf, n);
        else
            rc = -1; /* eof */
        *ret_len = n;
diff --git a/g10/exec.c b/g10/exec.c
new file mode 100644 (file)
index 0000000..229c968
--- /dev/null
@@ -0,0 +1,579 @@
+/* exec.c - generic call-a-program code
+ * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#ifndef EXEC_TEMPFILE_ONLY
+#include <sys/wait.h>
+#endif
+#ifdef HAVE_DOSISH_SYSTEM
+#include <windows.h>
+#endif
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include "options.h"
+#include "memory.h"
+#include "i18n.h"
+#include "iobuf.h"
+#include "util.h"
+#include "exec.h"
+
+#ifdef NO_EXEC
+int exec_write(struct exec_info **info,const char *program,
+              const char *args_in,const char *name,int writeonly,int binary)
+{
+  log_error(_("no remote program execution supported\n"));
+  return G10ERR_GENERAL;
+}
+
+int exec_read(struct exec_info *info) { return G10ERR_GENERAL; }
+int exec_finish(struct exec_info *info) { return G10ERR_GENERAL; }
+
+#else /* ! NO_EXEC */
+
+#ifndef HAVE_MKDTEMP
+char *mkdtemp(char *template);
+#endif
+
+#if defined (__MINGW32__) || defined (__CYGWIN32__)
+/* This is a nicer system() for windows that waits for programs to
+   return before returning control to the caller.  I hate helpful
+   computers. */
+static int win_system(const char *command)
+{
+  PROCESS_INFORMATION pi;
+  STARTUPINFO si;
+  char *string;
+
+  /* We must use a copy of the command as CreateProcess modifies this
+     argument. */
+  string=m_strdup(command);
+
+  memset(&pi,0,sizeof(pi));
+  memset(&si,0,sizeof(si));
+  si.cb=sizeof(si);
+
+  if(!CreateProcess(NULL,string,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
+    return -1;
+
+  /* Wait for the child to exit */
+  WaitForSingleObject(pi.hProcess,INFINITE);
+
+  CloseHandle(pi.hProcess);
+  CloseHandle(pi.hThread);
+  m_free(string);
+
+  return 0;
+}
+#endif
+
+/* Makes a temp directory and filenames */
+static int make_tempdir(struct exec_info *info)
+{
+  char *tmp=opt.temp_dir,*namein=info->name,*nameout;
+
+  if(!namein)
+    namein=info->binary?"tempin" EXTSEP_S "bin":"tempin" EXTSEP_S "txt";
+
+  nameout=info->binary?"tempout" EXTSEP_S "bin":"tempout" EXTSEP_S "txt";
+
+  /* Make up the temp dir and files in case we need them */
+
+  if(tmp==NULL)
+    {
+#if defined (__MINGW32__) || defined (__CYGWIN32__)
+      tmp=m_alloc(256);
+      if(GetTempPath(256,tmp)==0)
+       strcpy(tmp,"c:\\windows\\temp");
+      else
+       {
+         int len=strlen(tmp);
+
+         /* GetTempPath may return with \ on the end */
+         while(len>0 && tmp[len-1]=='\\')
+           {
+             tmp[len-1]='\0';
+             len--;
+           }
+       }
+#else /* More unixish systems */
+      tmp=getenv("TMPDIR");
+      if(tmp==NULL)
+       {
+         tmp=getenv("TMP");
+         if(tmp==NULL)
+           {
+#ifdef __riscos__
+             tmp="<Wimp$ScrapDir>.GnuPG";
+             mkdir(tmp,0700); /* Error checks occur later on */
+#else
+             tmp="/tmp";
+#endif
+           }
+       }
+#endif
+    }
+
+  info->tempdir=m_alloc(strlen(tmp)+strlen(DIRSEP_S)+10+1);
+
+  sprintf(info->tempdir,"%s" DIRSEP_S "gpg-XXXXXX",tmp);
+
+#if defined (__MINGW32__) || defined (__CYGWIN32__)
+  m_free(tmp);
+#endif
+
+  if(mkdtemp(info->tempdir)==NULL)
+    log_error(_("%s: can't create directory: %s\n"),
+             info->tempdir,strerror(errno));
+  else
+    {
+      info->madedir=1;
+
+      info->tempfile_in=m_alloc(strlen(info->tempdir)+
+                               strlen(DIRSEP_S)+strlen(namein)+1);
+      sprintf(info->tempfile_in,"%s" DIRSEP_S "%s",info->tempdir,namein);
+
+      if(!info->writeonly)
+       {
+         info->tempfile_out=m_alloc(strlen(info->tempdir)+
+                                    strlen(DIRSEP_S)+strlen(nameout)+1);
+         sprintf(info->tempfile_out,"%s" DIRSEP_S "%s",info->tempdir,nameout);
+       }
+    }
+
+  return info->madedir?0:G10ERR_GENERAL;
+}
+
+/* Expands %i and %o in the args to the full temp files within the
+   temp directory. */
+static int expand_args(struct exec_info *info,const char *args_in)
+{
+  const char *ch=args_in;
+  int size,len;
+
+  info->use_temp_files=0;
+  info->keep_temp_files=0;
+
+  if(DBG_EXTPROG)
+    log_debug("expanding string \"%s\"\n",args_in);
+
+  size=100;
+  info->command=m_alloc(size);
+  len=0;
+  info->command[0]='\0';
+
+  while(*ch!='\0')
+    {
+      if(*ch=='%')
+       {
+         char *append=NULL;
+
+         ch++;
+
+         switch(*ch)
+           {
+           case 'O':
+             info->keep_temp_files=1;
+             /* fall through */
+
+           case 'o': /* out */
+             if(!info->madedir)
+               {
+                 if(make_tempdir(info))
+                   goto fail;
+               }
+             append=info->tempfile_out;
+             info->use_temp_files=1;
+             break;
+
+           case 'I':
+             info->keep_temp_files=1;
+             /* fall through */
+
+           case 'i': /* in */
+             if(!info->madedir)
+               {
+                 if(make_tempdir(info))
+                   goto fail;
+               }
+             append=info->tempfile_in;
+             info->use_temp_files=1;
+             break;
+
+           case '%':
+             append="%";
+             break;
+           }
+
+         if(append)
+           {
+             while(strlen(append)+len>size-1)
+               {
+                 size+=100;
+                 info->command=m_realloc(info->command,size);
+               }
+
+             strcat(info->command,append);
+             len+=strlen(append);
+           }
+       }
+      else
+       {
+         if(len==size-1) /* leave room for the \0 */
+           {
+             size+=100;
+             info->command=m_realloc(info->command,size);
+           }
+
+         info->command[len++]=*ch;
+         info->command[len]='\0';
+       }
+
+      ch++;
+    }
+
+  if(DBG_EXTPROG)
+    log_debug("args expanded to \"%s\", use %d, keep %d\n",
+             info->command,info->use_temp_files,info->keep_temp_files);
+
+  return 0;
+
+ fail:
+
+  m_free(info->command);
+  info->command=NULL;
+
+  return G10ERR_GENERAL;
+}
+
+/* Either handles the tempfile creation, or the fork/exec.  If it
+   returns ok, then info->tochild is a FILE * that can be written to.
+   The rules are: if there are no args, then it's a fork/exec/pipe.
+   If there are args, but no tempfiles, then it's a fork/exec/pipe via
+   shell -c.  If there are tempfiles, then it's a system. */
+
+int exec_write(struct exec_info **info,const char *program,
+              const char *args_in,const char *name,int writeonly,int binary)
+{
+  int ret=G10ERR_GENERAL;
+
+  if(opt.exec_disable && !opt.no_perm_warn)
+    {
+      log_info(_("external program calls are disabled due to unsafe "
+                "options file permissions\n"));
+
+      return ret;
+    }
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
+  /* There should be no way to get to this spot while still carrying
+     setuid privs.  Just in case, bomb out if we are. */
+  if(getuid()!=geteuid())
+    BUG();
+#endif
+
+  if(program==NULL && args_in==NULL)
+    BUG();
+
+  *info=m_alloc_clear(sizeof(struct exec_info));
+
+  if(name)
+    (*info)->name=m_strdup(name);
+  (*info)->binary=binary;
+  (*info)->writeonly=writeonly;
+
+  /* Expand the args, if any */
+  if(args_in && expand_args(*info,args_in))
+    goto fail;
+
+#ifdef EXEC_TEMPFILE_ONLY
+  if(!(*info)->use_temp_files)
+    {
+      log_error(_("this platform requires temp files when calling external "
+                 "programs\n"));
+      goto fail;
+    }
+
+#else /* !EXEC_TEMPFILE_ONLY */
+
+  /* If there are no args, or there are args, but no temp files, we
+     can use fork/exec/pipe */
+  if(args_in==NULL || (*info)->use_temp_files==0)
+    {
+      int to[2],from[2];
+
+      if(pipe(to)==-1)
+       goto fail;
+
+      if(pipe(from)==-1)
+       {
+         close(to[0]);
+         close(to[1]);
+         goto fail;
+       }
+
+      if(((*info)->child=fork())==-1)
+       {
+         close(to[0]);
+         close(to[1]);
+         close(from[0]);
+         close(from[1]);
+         goto fail;
+       }
+
+      if((*info)->child==0)
+       {
+         char *shell=getenv("SHELL");
+
+         if(shell==NULL)
+           shell="/bin/sh";
+
+         /* I'm the child */
+
+         /* If the program isn't going to respond back, they get to
+             keep their stdout/stderr */
+         if(!(*info)->writeonly)
+           {
+             /* implied close of STDERR */
+             if(dup2(STDOUT_FILENO,STDERR_FILENO)==-1)
+               _exit(1);
+
+             /* implied close of STDOUT */
+             close(from[0]);
+             if(dup2(from[1],STDOUT_FILENO)==-1)
+               _exit(1);
+           }
+
+         /* implied close of STDIN */
+         close(to[1]);
+         if(dup2(to[0],STDIN_FILENO)==-1)
+           _exit(1);
+
+         if(args_in==NULL)
+           {
+             if(DBG_EXTPROG)
+               log_debug("execlp: %s\n",program);
+
+             execlp(program,program,NULL);
+           }
+         else
+           {
+             if(DBG_EXTPROG)
+               log_debug("execlp: %s -c %s\n",shell,(*info)->command);
+
+             execlp(shell,shell,"-c",(*info)->command,NULL);
+           }
+
+         /* If we get this far the exec failed.  Clean up and return. */
+
+         log_error(_("unable to execute %s \"%s\": %s\n"),
+                   args_in==NULL?"program":"shell",
+                   args_in==NULL?program:shell,
+                   strerror(errno));
+
+         /* This mimics the POSIX sh behavior - 127 means "not found"
+             from the shell. */
+         if(errno==ENOENT)
+           _exit(127);
+
+         _exit(1);
+       }
+
+      /* I'm the parent */
+
+      close(to[0]);
+
+      (*info)->tochild=fdopen(to[1],binary?"wb":"w");
+      if((*info)->tochild==NULL)
+       {
+         close(to[1]);
+         ret=G10ERR_WRITE_FILE;
+         goto fail;
+       }
+
+      close(from[1]);
+
+      (*info)->fromchild=iobuf_fdopen(from[0],"r");
+      if((*info)->fromchild==NULL)
+       {
+         close(from[0]);
+         ret=G10ERR_READ_FILE;
+         goto fail;
+       }
+
+      /* fd iobufs are cached?! */
+      iobuf_ioctl((*info)->fromchild,3,1,NULL);
+
+      return 0;
+    }
+#endif /* !EXEC_TEMPFILE_ONLY */
+
+  if(DBG_EXTPROG)
+    log_debug("using temp file \"%s\"\n",(*info)->tempfile_in);
+
+  /* It's not fork/exec/pipe, so create a temp file */
+  (*info)->tochild=fopen((*info)->tempfile_in,binary?"wb":"w");
+  if((*info)->tochild==NULL)
+    {
+      log_error(_("%s: can't create: %s\n"),
+               (*info)->tempfile_in,strerror(errno));
+      ret=G10ERR_WRITE_FILE;
+      goto fail;
+    }
+
+  ret=0;
+
+ fail:
+  return ret;
+}
+
+int exec_read(struct exec_info *info)
+{
+  int ret=G10ERR_GENERAL;
+
+  fclose(info->tochild);
+  info->tochild=NULL;
+
+  if(info->use_temp_files)
+    {
+      if(DBG_EXTPROG)
+       log_debug("system() command is %s\n",info->command);
+
+#if defined (__MINGW32__) || defined (__CYGWIN32__)
+      info->progreturn=win_system(info->command);
+#else
+      info->progreturn=system(info->command);
+#endif
+
+      if(info->progreturn==-1)
+       {
+         log_error(_("system error while calling external program: %s\n"),
+                   strerror(errno));
+         info->progreturn=127;
+         goto fail;
+       }
+
+#if defined(WIFEXITED) && defined(WEXITSTATUS)
+      if(WIFEXITED(info->progreturn))
+       info->progreturn=WEXITSTATUS(info->progreturn);
+      else
+       {
+         log_error(_("unnatural exit of external program\n"));
+         info->progreturn=127;
+         goto fail;
+       }
+#else
+      /* If we don't have the macros, do the best we can. */
+      info->progreturn = (info->progreturn & 0xff00) >> 8;
+#endif
+
+      /* 127 is the magic value returned from system() to indicate
+         that the shell could not be executed, or from /bin/sh to
+         indicate that the program could not be executed. */
+
+      if(info->progreturn==127)
+       {
+         log_error(_("unable to execute external program\n"));
+         goto fail;
+       }
+
+      if(!info->writeonly)
+       {
+         info->fromchild=iobuf_open(info->tempfile_out);
+         if(info->fromchild==NULL)
+           {
+             log_error(_("unable to read external program response: %s\n"),
+                       strerror(errno));
+             ret=G10ERR_READ_FILE;
+             goto fail;
+           }
+
+         /* Do not cache this iobuf on close */
+         iobuf_ioctl(info->fromchild,3,1,NULL);
+       }
+    }
+
+  ret=0;
+
+ fail:
+  return ret;
+}
+
+int exec_finish(struct exec_info *info)
+{
+  int ret=info->progreturn;
+
+  if(info->fromchild)
+    iobuf_close(info->fromchild);
+
+  if(info->tochild)
+    fclose(info->tochild);
+
+#ifndef EXEC_TEMPFILE_ONLY
+  if(info->child>0)
+    {
+      if(waitpid(info->child,&info->progreturn,0)!=0 &&
+        WIFEXITED(info->progreturn))
+       ret=WEXITSTATUS(info->progreturn);
+      else
+       {
+         log_error(_("unnatural exit of external program\n"));
+         ret=127;
+       }
+    }
+#endif
+
+  if(info->madedir && !info->keep_temp_files)
+    {
+      if(info->tempfile_in)
+       {
+         if(unlink(info->tempfile_in)==-1)
+           log_info(_("Warning: unable to remove tempfile (%s) \"%s\": %s\n"),
+                    "in",info->tempfile_in,strerror(errno));
+       }
+  
+      if(info->tempfile_out)
+       {
+         if(unlink(info->tempfile_out)==-1)
+           log_info(_("Warning: unable to remove tempfile (%s) \"%s\": %s\n"),
+                    "out",info->tempfile_out,strerror(errno));
+       }
+
+      if(rmdir(info->tempdir)==-1)
+       log_info(_("Warning: unable to remove temp directory \"%s\": %s\n"),
+                info->tempdir,strerror(errno));
+    }
+
+  m_free(info->command);
+  m_free(info->name);
+  m_free(info->tempdir);
+  m_free(info->tempfile_in);
+  m_free(info->tempfile_out);
+  m_free(info);
+
+  return ret;
+}
+#endif /* ! NO_EXEC */
diff --git a/g10/exec.h b/g10/exec.h
new file mode 100644 (file)
index 0000000..2e0be46
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _EXEC_H_
+#define _EXEC_H_
+
+#include <unistd.h>
+#include <stdio.h>
+#include "iobuf.h"
+
+struct exec_info
+{
+  int progreturn,binary,writeonly,madedir,use_temp_files,keep_temp_files;
+  pid_t child;
+  FILE *tochild;
+  IOBUF fromchild;
+  char *command,*name,*tempdir,*tempfile_in,*tempfile_out;
+};
+
+int exec_write(struct exec_info **info,const char *program,
+              const char *args_in,const char *name,int writeonly,int binary);
+int exec_read(struct exec_info *info);
+int exec_finish(struct exec_info *info);
+
+#endif /* !_EXEC_H_ */
index 9a9cd98..47d06e6 100644 (file)
@@ -1,5 +1,5 @@
 /* export.c
- *     Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
 #include <errno.h>
 #include <assert.h>
 
-#include <gcrypt.h>
 #include "options.h"
 #include "packet.h"
 #include "errors.h"
 #include "keydb.h"
+#include "memory.h"
 #include "util.h"
 #include "main.h"
 #include "i18n.h"
@@ -83,8 +83,10 @@ do_export( STRLIST users, int secret, int onlyrfc )
     IOBUF out = NULL;
     int any, rc;
     armor_filter_context_t afx;
+    compress_filter_context_t zfx;
 
     memset( &afx, 0, sizeof afx);
+    memset( &zfx, 0, sizeof zfx);
 
     rc = open_outfile( NULL, 0, &out );
     if( rc )
@@ -94,6 +96,8 @@ do_export( STRLIST users, int secret, int onlyrfc )
        afx.what = secret?5:1;
        iobuf_push_filter( out, armor_filter, &afx );
     }
+    if( opt.compress_keys && opt.compress )
+       iobuf_push_filter( out, compress_filter, &zfx );
     rc = do_export_stream( out, users, secret, onlyrfc, &any );
 
     if( rc || !any )
@@ -108,54 +112,58 @@ static int
 do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
 {
     int rc = 0;
-    compress_filter_context_t zfx;
     PACKET pkt;
     KBNODE keyblock = NULL;
     KBNODE kbctx, node;
-    KBPOS kbpos;
+    int ndesc;
+    KEYDB_SEARCH_DESC *desc = NULL;
+    KEYDB_HANDLE kdbhd;
     STRLIST sl;
-    int all = !users;
 
     *any = 0;
-    memset( &zfx, 0, sizeof zfx);
     init_packet( &pkt );
+    kdbhd = keydb_new (secret);
 
-    if( opt.compress_keys && opt.compress )
-       iobuf_push_filter( out, compress_filter, &zfx );
+    if (!users) {
+        ndesc = 1;
+        desc = m_alloc_clear ( ndesc * sizeof *desc);
+        desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
+    }
+    else {
+        for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++) 
+            ;
+        desc = m_alloc ( ndesc * sizeof *desc);
+        
+        for (ndesc=0, sl=users; sl; sl = sl->next) {
+           if (classify_user_id (sl->d, desc+ndesc))
+                ndesc++;
+            else
+                log_error (_("key `%s' not found: %s\n"),
+                           sl->d, g10_errstr (G10ERR_INV_USER_ID));
+        }
 
-    if( all ) {
-       rc = enum_keyblocks_begin( &kbpos, secret );
-       if( rc ) {
-           if( rc != -1 )
-               log_error("enum_keyblocks_begin failed: %s\n", gpg_errstr(rc));
-           goto leave;
-       }
-       all = 2;
+        /* it would be nice to see which of the given users did
+           actually match one in the keyring.  To implement this we
+           need to have a found flag for each entry in desc and to set
+           this we must check all those entries after a match to mark
+           all matched one - currently we stop at the first match.  To
+           do this we need an extra flag to enable this feature so */
     }
 
-    /* use the correct sequence. strlist_last,prev do work correctly with
-     * NULL pointers :-) */
-    for( sl=strlist_last(users); sl || all ; sl=strlist_prev( users, sl )) {
-       if( all ) { /* get the next user */
-           rc = enum_keyblocks_next( kbpos, 1, &keyblock );
-           if( rc == -1 )  /* EOF */
-               break;
-           if( rc ) {
-               log_error("enum_keyblocks_next failed: %s\n", gpg_errstr(rc));
-               break;
-           }
-       }
-       else {
-           /* search the userid */
-           rc = secret? find_secret_keyblock_byname( &keyblock, sl->d )
-                      : find_keyblock_byname( &keyblock, sl->d );
-           if( rc ) {
-               log_error(_("%s: user not found: %s\n"), sl->d, gpg_errstr(rc));
-               rc = 0;
-               continue;
-           }
-       }
 
+    while (!(rc = keydb_search (kdbhd, desc, ndesc))) {
+        int sha1_warned=0;
+       u32 sk_keyid[2];
+
+       if (!users) 
+            desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
+
+        /* read the keyblock */
+        rc = keydb_get_keyblock (kdbhd, &keyblock );
+       if( rc ) {
+            log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
+           goto leave;
+       }
 
        /* do not export keys which are incompatible with rfc2440 */
        if( onlyrfc && (node = find_kbnode( keyblock, PKT_PUBLIC_KEY )) ) {
@@ -167,15 +175,29 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
            }
        }
 
-       /* we can't apply GNU mode 1001 on an unprotected key */
-       if( secret == 2
-           && (node = find_kbnode( keyblock, PKT_SECRET_KEY ))
-           && !node->pkt->pkt.secret_key->is_protected )
-       {
-           log_info(_("key %08lX: not protected - skipped\n"),
-                 (ulong)keyid_from_sk( node->pkt->pkt.secret_key, NULL) );
-           continue;
-       }
+       node=find_kbnode( keyblock, PKT_SECRET_KEY );
+       if(node)
+         {
+           PKT_secret_key *sk=node->pkt->pkt.secret_key;
+
+           keyid_from_sk(sk,sk_keyid);
+
+           /* we can't apply GNU mode 1001 on an unprotected key */
+           if( secret == 2 && !sk->is_protected )
+             {
+               log_info(_("key %08lX: not protected - skipped\n"),
+                        (ulong)sk_keyid[1]);
+               continue;
+             }
+
+           /* no v3 keys with GNU mode 1001 */
+           if( secret == 2 && sk->version == 3 )
+             {
+               log_info(_("key %08lX: PGP 2.x style key - skipped\n"),
+                        (ulong)sk_keyid[1]);
+   &nbs