summaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2000-07-14 19:34:53 +0200
committerWerner Koch <wk@gnupg.org>2000-07-14 19:34:53 +0200
commit92cd25550836198cf1e3a6aac239eef98364359d (patch)
tree4fad355126fae79c93535e0e7c6afd91e384552a /g10
parentSee ChangeLog: Thu May 25 18:39:11 CEST 2000 Werner Koch (diff)
downloadgnupg2-92cd25550836198cf1e3a6aac239eef98364359d.tar.xz
gnupg2-92cd25550836198cf1e3a6aac239eef98364359d.zip
See ChangeLog: Fri Jul 14 19:38:23 CEST 2000 Werner Koch
Diffstat (limited to 'g10')
-rw-r--r--g10/ChangeLog810
-rw-r--r--g10/Makefile.am5
-rw-r--r--g10/armor.c63
-rw-r--r--g10/build-packet.c88
-rw-r--r--g10/cipher.c49
-rw-r--r--g10/comment.c2
-rw-r--r--g10/compress.c4
-rw-r--r--g10/dearmor.c4
-rw-r--r--g10/decrypt.c4
-rw-r--r--g10/delkey.c7
-rw-r--r--g10/encode.c9
-rw-r--r--g10/encr-data.c49
-rw-r--r--g10/export.c35
-rw-r--r--g10/filter.h12
-rw-r--r--g10/free-packet.c6
-rw-r--r--g10/getkey.c120
-rw-r--r--g10/gpg.c279
-rw-r--r--g10/gpgd.c7
-rw-r--r--g10/helptext.c25
-rw-r--r--g10/hkp.c38
-rw-r--r--g10/hkp.h2
-rw-r--r--g10/import.c104
-rw-r--r--g10/kbnode.c7
-rw-r--r--g10/kbxblob.c10
-rw-r--r--g10/kbxfile.c2
-rw-r--r--g10/keydb.h5
-rw-r--r--g10/keyedit.c182
-rw-r--r--g10/keygen.c954
-rw-r--r--g10/keyid.c10
-rw-r--r--g10/keylist.c95
-rw-r--r--g10/ks-proto.h2
-rw-r--r--g10/main.h24
-rw-r--r--g10/mainproc.c161
-rw-r--r--g10/mdfilter.c4
-rw-r--r--g10/misc.c9
-rw-r--r--g10/openfile.c37
-rw-r--r--g10/options.h20
-rw-r--r--g10/packet.h21
-rw-r--r--g10/parse-packet.c136
-rw-r--r--g10/passphrase.c9
-rw-r--r--g10/pkclist.c154
-rw-r--r--g10/plaintext.c16
-rw-r--r--g10/pubkey-enc.c37
-rw-r--r--g10/revoke.c344
-rw-r--r--g10/ringedit.c65
-rw-r--r--g10/seckey-cert.c35
-rw-r--r--g10/seskey.c20
-rw-r--r--g10/sig-check.c193
-rw-r--r--g10/sign.c52
-rw-r--r--g10/signal.c17
-rw-r--r--g10/skclist.c4
-rw-r--r--g10/status.c155
-rw-r--r--g10/status.h17
-rw-r--r--g10/tdbdump.c3
-rw-r--r--g10/tdbio.c22
-rw-r--r--g10/tdbio.h5
-rw-r--r--g10/textfilter.c38
-rw-r--r--g10/trustdb.c294
-rw-r--r--g10/trustdb.h3
-rw-r--r--g10/verify.c91
60 files changed, 3703 insertions, 1272 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 64056be69..6d3aa7cc4 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,231 +1,710 @@
-Thu May 25 18:39:11 CEST 2000 Werner Koch <wk@openit.de>
+Fri Jul 14 19:38:23 CEST 2000 Werner Koch <wk@>
- * kbxio.c: New.
+ 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.
- * kbxfile.c (print_kbxfile): Add a loop
- (do_print_kbxfile): Fixed passing to kbx_dump_blob.
+ * gpg.c (print_mds): Add arg keys as a kludge to print hmacs
+ (main): New option --print-hmac.
-Fri Mar 24 11:25:45 CET 2000 Werner Koch <wk@openit.de>
+ * trustdb.c (verify_own_keys): Do not print warning about unprotected
+ key when in quiet mode.
- * gpg.c (print_mds): Add arg keys as a kludge to print hmacs
- (main): New option --print-hmac.
+ * build-paket.c (do_user_id): Save offset where name has been stored.
+
+ * ringedit.c : Add new access method KBXF
+
+ * kbxfile.c: New.
+
+ * kbx.h: New.
+ * kbxblob.c: Started to work on the keybox stuff.
+
+ * keygen.c (gen_dsa): Modified to work with gcry_pk_genkey.
+
+ * Removed dummy-cipher.h from all files.
+
+ * keygen.c (gen_elg): Modified to work with gcry_pk_genkey.
+ (key_from_sexp): New.
+ (factors_from_sexp): New.
+
+ * g10.c : Renamed to ...
+ * gpg.c : ... this
+ * Makefile.am: And fixed it here.
+
+ * Changed all "g10_"/"GPG_" prefixes to "gpg_"/"GPG_".
+
+ * misc.c (mpi_read_opaque): Fixed double counting.
+
+ * seckey-cert.c (do_check): Removed buffer and the unmotivated free
+ on it.
+
+ * pubkey-enc.c (pk_decrypt): New wrapper for the gcry_ function.
+ * seckey-cert.c (pk_check_secret_key): Likewise.
+ * encode.c (pk_encrypt): Likewise.
+
+ * parse-packet.c (parse_key): Fixed case of unencrypted secret keys.
+
+ * misc.c (mpi_print): Use gcry_mpi_aprint.
+ (pubkey_nbits): Kludge to use the gcry_pk_ API.
+
+ * 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.
+
+ * 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.
+
+ * misc.c (mpi_print): New.
+
+ * misc.c (checksum_mpi): Now uses gcry_mpi_print to get the data.
+
+ * seckey-cert.c (do_check): Replaced mpi_read_from_buffer.
+
+ * armor.c (armor_filter): Made the "Comment:" header translatable.
+
+ * seckey-cert.c: Removed obsolete mpi_*_protect_flag.
+ * parse-packet.c: Ditto.
+
+ * 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.
+
+ * g10.c (main): Check libgcrypt version.
+
+ * 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.
+
+ * g10.c: Add --delete-secret-key to the help page.
+
+ * g10.c (main): Changed the default homedir to "~/.gnupg-test" so
+ that we don't mess up with the stable version.
+
+ * misc.c (mpi_write): New.
+ (mpi_write): New.
+
+ * 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.
+
+ * 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().
+
+ * tdbdump.c (HEXTOBIN): Changed the name of the argument, so that
+ traditional cpp don't mess up the macros. Suggested by Jos Backus.
+
+ * armor.c (parse_header_line): Stop parsing on a only WS line too.
+ Suggested by Aric Cyr.
+
+ * misc.c (pull_in_libs): Removed.
+
+ * mainproc.c (list_node): Print the PK algo in the --with-colon mode.
+ * keylist.c (list_keyblock): Ditto.
+
+ * misc.c (pull_in_libs): Removed pull in of g10c.
+
+ * misc.c (map_gcry_rc): Removed here and chnaged all users.
+
+ * 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.
+
+ * g10.c (main): Replaced the function to diable PK algos.
+
+ * 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.
+
+ * 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.
+
+ * skclist.c (build_sk_list): Removed the test on faked RNGs.
+ (is_insecure): Removed.
+ * g10.c (--quick-random): Removed this option.
+
+ * Replaced all PUBKEY_ALGO_xxx by GCRY_PK_xxxx.
+
+ * 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.
+
+ * Makefile.am (basicdefs.h): Added.
+ (install-data-local): Removed the handling for historic gpgm.
+
+ * misc.c (openpgp_cipher_test_algo): New.
+ (openpgp_pk_test_algo): New.
+ (openpgp_md_test_algo): New.
+
+ * g10.c (build_list): Changed to use the new functions from libgcrypt.
+
+ * ringedit.c (enum_keyblocks): Set .rt to 0 on open.
+
+ * 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.
+
+ * 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.
+
+ (clearsign_file): Use gcry_md_test_algo() and gcry_md_algo_name().
+
+ * 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.
+
+ * encr-data.c (decrypt_data): Reset error on a weak key.
+
+ * 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.
+
+ * pkclist.c (do_edit_ownertrust): Made the answer string const.
+
+ * basicdefs.h: New. Move some defs and decl to this header.
+
+ * openfile.c (open_outfile): Fixed the 8dot3 handling.
+
+ * 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.
+
+ * 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.
+
+ * misc.c (map_gcry_rc): New.
+
+Wed Jun 28 11:54:44 CEST 2000 Werner Koch <wk@>
+
+ * armor.c (armor_filter): Set sigclass to 0 in case of non-dash-escaped
+ clearsig. This makes this mode work again.
+
+ * mainproc.c (proc_tree): Fixed handling of one-pass-sig packets in textmode.
+ Disabled the ugly workaround for PGP 5 - let's see whether thi breaks less
+ cases. Found by Ted Cabeen.
+
+ * options.h (DBG_HASHING): New. All commented md_start_debug are now
+ controlled by this debug option.
+
+ * sign.c (print_status_sig_created): New and called from 2 places.
+
+ * keygen.c (gen_rsa): New, but commented.
+ (ask_algo): Commented support for RSA.
+
+ * seckey-cert.c (protect_secret_key): Started to fix the code for v4 RSA
+ keys - it is not solved yet. However, we have time until, Sep 20th ;)
+
+Wed Jun 14 12:27:09 CEST 2000 Werner Koch <wk@openit.de>
+
+ * status.c (init_shm_coprocessing): Changed the sequence of the get,attach
+ to cope with the changes in newer Linux kernels. This bug has been found
+ by <dmitri@advantrix.com> who also proposed this solution. Hopefully
+ this does not break gpg on to many systems.
+
+ * cipher.c (write_header): Protect the IV with the MDC too.
+ * encr-data.c (decrypt_data): Likewise.
+
+Fri Jun 9 10:09:52 CEST 2000 Werner Koch <wk@openit.de>
+
+ * g10.c: New options --no-auto-key-retrieve
+ * options.h (auto_key_retrieve): New.
+ * mainproc.c (check_sig_and_print): Implemented that.
+
+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.
+
+Wed Jun 7 17:25:38 CEST 2000 Werner Koch <wk@openit.de>
+
+ * cipher.c (write_header): Use plain CFB mode for MDC encrypted packets.
+ * encr-data.c (decrypt_data): Ditto.
+
+Mon Jun 5 23:41:54 CEST 2000 Werner Koch <wk@openit.de>
+
+ * seskey.c (do_encode_md, encode_md_value): Add new arg v3compathack to work
+ around a bug in old versions.
+ * sig-check.c (do_check): use the aboved workaround when enabled.
+ * g10.c: New option --emulate-md-decode-bug
+
+Mon Jun 5 12:37:43 CEST 2000 Werner Koch <wk@openit.de>
+
+ * build-packet.c (do_mdc): New.
+ (do_encrypted_mdc): Changed for the new proposal.
+ * parse-packet.c (parse_mdc): New.
+ (parse_encrypted): Fixed for the new proposal.
+ * packet.h (PKT_MDC): New.
+ * cipher.c (cipher_filter): Build the MDC packet here.
+ * g10.c (main): Enable --force-mdc.
+ * encr-data.c (mdc_decode_filter): Fixed for new MDC method
+
+ * options.h(rfc2440): New.
+ * g10.c (main): Changed the selected values for --openpgp to not include
+ optional algorithms.
+
+Thu May 18 11:38:54 CEST 2000 Werner Koch <wk@openit.de>
+
+ * keyedit.c (keyedit_menu): Add a keyword arg to the prompt.
+
+ * status.c, status.h: Added 3 new status tokens.
+ * status.c (do_get_from_fd): New.
+ (cpr_enabled,cpr_get,cpr_get_hidden,cpr_kill_prompt,
+ cpr_get_answer_is_yes,cpr_get_answer_yes_no_quit): Modified to work
+ with the new function.
+ * g10.c: Add new option --command-fd.
+
+ * status.c (progress_cb): New.
+ (set_status_fd): Register progress functions
+
+Fri May 12 14:01:20 CEST 2000 Werner Koch <wk@openit.de>
+
+ * delkey.c (delete_key): Add 2 new status messages
+ * status.c, status.h (STATUS_DELETE_PROBLEM): New.
+
+ Fixed years of copyright in all source files.
+
+Mon May 1 17:08:14 CEST 2000 Werner Koch <wk@openit.de>
+
+ * trustdb.c (propagate_validity): Fixed the bug that only one uid
+ gets fully trusted even when all are signed by an ultimate key.
+
+Mon May 1 15:38:04 CEST 2000 Werner Koch <wk@openit.de>
+
+ * getkey.c (key_byname): Always returned a defined context. Fixed
+ a segv for invalid user id specifications. Reported by Walter Koch.
+
+ * getkey.c (get_user_id): I18ned "no user id" string. By Walter.
+
+ * pkclist.c (do_show_revocation_reason): Typo fixes.
+ * helptext.c: Ditto.
+
+ * armor.c (armor_filter): Fixed some CRLF issues. By Mike McEwan.
+
+Fri Apr 14 19:37:08 CEST 2000 Werner Koch <wk@openit.de>
+
+ * pkclist.c (do_show_revocation_reason): New.
+ (show_revocation_reason): New and called at various places.
+
+ * g10.c (main): Fixed small typo.
+
+ * pkclist.c (do_we_trust): Act on always_trust but not for revoked
+ keys. Suggested by Chip Salzenberg.
+
+ * g10.c: New option --lock-never.
+
+ * ringedit.c (get_writable_keyblock_file): New.
+ * keygen.c (do_generate_keypair): Use this instead of the hardwired one.
+
+ * keygen.c (ask_user_id): Check that the email address is in the
+ correct field. Suggested by Christian Kurz.
+
+Mon Apr 10 13:34:19 CEST 2000 Werner Koch <wk@openit.de>
+
+ * keyedit.c (show_key_with_all_names): s/sbb/ssb/
+
+Tue Mar 28 14:26:58 CEST 2000 Werner Koch <wk@openit.de>
* trustdb.c (verify_own_keys): Do not print warning about unprotected
key when in quiet mode.
-Mon Mar 13 19:22:46 CET 2000 Werner Koch <wk@openit.de>
+Wed Mar 22 13:50:24 CET 2000 Werner Koch <wk@openit.de>
- * build-paket.c (do_user_id): Save offset where name has been stored.
+ * mainproc.c (print_userid): Do UTF8 conversion before printing.
+ * import.c (import_one): Ditto.
+ (import_secret_one): Ditto.
+ (delete_inv_parts): Ditto.
- * ringedit.c : Add new access method KBXF
+Thu Mar 16 16:20:23 CET 2000 Werner Koch <wk@openit.de>
- * kbxfile.c: New.
+ * keylist.c (print_key_data): Handle a NULL pk gracefully.
-Mon Feb 21 22:43:01 CET 2000 Werner Koch <wk@>
+ * getkey.c (merge_one_pk_and_selfsig): Fixed silly code for
+ getting the primary keys keyID but kept using the one from the
+ subkey.
+ * pubkey-enc.c (get_it): Print a note for expired subkeys.
- * kbx.h: New.
- * kbxblob.c: Started to work on the keybox stuff.
+ * getkey.c (has_expired): New.
+ (subkeys_expiretime): New.
+ (finish_lookup): Check for expired subkeys needed for encryption.
+ (merge_keys_and_selfsig): Fixed expiration date merging for subkeys.
-Mon Jan 31 16:37:34 CET 2000 Werner Koch <wk@gnupg.de>
+ * keylist.c (list_keyblock): Print expiration time for "sub".
+ (list_one): Add missing merging for public keys.
+ * mainproc.c (list_node): Ditto.
- * keygen.c (gen_dsa): Modified to work with gcry_pk_genkey.
+2000-03-14 13:49:38 Werner Koch (wk@habibti.openit.de)
- * Removed dummy-cipher.h from all files.
+ * keygen.c (keyedit_menu): Do not allow to use certain commands
+ while the secret key is selected.
-Thu Jan 27 18:00:44 CET 2000 Werner Koch <wk@gnupg.de>
+2000-03-09 12:53:09 Werner Koch (wk@habibti.openit.de)
- * keygen.c (gen_elg): Modified to work with gcry_pk_genkey.
- (key_from_sexp): New.
- (factors_from_sexp): New.
+ * keygen.c (ask_expire_interval): Movede parsig to ...
+ (parse_expire_string): ... this new function. And some new control
+ commands.
+ (proc_parameter_file): Add expire date parsing.
+ (do_generate_keypair): Allow the use of specified output files.
- * g10.c : Renamed to ...
- * gpg.c : ... this
- * Makefile.am: And fixed it here.
+2000-03-08 10:38:38 Werner Koch (wk@habibti.openit.de)
- * Changed all "g10_"/"GPG_" prefixes to "gpg_"/"GPG_".
+ * keygen.c (ask_algo): Removed is_v4 return value and the commented
+ code to create Elg keys in a v3 packet. Removed the rounding
+ of key sizes here.
+ (do_create): Likewise removed arg v4_packet.
+ (gen_elg): Likewise removed arg version. Now rounding keysizes here.
+ (gen_dsa): Rounding keysize now here.
+ (release_parameter_list): New
+ (get_parameter*): New.
+ (proc_parameter_file): New.
+ (read_parameter_file): New.
+ (generate_keypair): Splitted. Now uses read_parameter_file when in
+ batch mode. Additional argument to specify a parameter file.
+ (do_generate_keypair): Main bulk of above fucntion and uses the
+ parameter list.
+ (do_create): Don't print long notice in batch mode.
+ * g10.c (main): Allow batched key generation.
-Mon Jan 24 22:24:38 CET 2000 Werner Koch <wk@gnupg.de>
+Thu Mar 2 15:37:46 CET 2000 Werner Koch <wk@gnupg.de>
- * misc.c (mpi_read_opaque): Fixed double counting.
+ * pubkey-enc.c (get_it): Print a note about unknown cipher algos.
- * seckey-cert.c (do_check): Removed buffer and the unmotivated free
- on it.
+ * g10.c (opts): Add a note to the help listing about the man page
+ and removed some options from the help listing.
- * pubkey-enc.c (pk_decrypt): New wrapper for the gcry_ function.
- * seckey-cert.c (pk_check_secret_key): Likewise.
- * encode.c (pk_encrypt): Likewise.
+ * keyedit.c (print_and_check_one_sig): Use a new function to truncate
+ the output of the user ID. Suggested by Jan-Benedict Glaw.
- * parse-packet.c (parse_key): Fixed case of unencrypted secret keys.
+Wed Feb 23 10:07:57 CET 2000 Werner Koch <wk@gnupg.de>
-Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de>
+ * helptext.c: typo fix.
- * misc.c (mpi_print): Use gcry_mpi_aprint.
- (pubkey_nbits): Kludge to use the gcry_pk_ API.
+Thu Feb 17 13:39:32 CET 2000 Werner Koch <wk@gnupg.de>
- * 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.
+ * revoke.c: Removed a bunch of commented code.
-Fri Dec 31 12:48:31 CET 1999 Werner Koch <wk@gnupg.de>
+ * packet.h (SIGSUBPKT_REVOC_REASON): New.
+ * build-packet.c (build_sig_subpkt): Support new sub packet.
+ * parse-packet.c (parse_one_sig_subpkt): Ditto.
+ (dump_sig_subpkt): Ditto.
+ * revoke.c (ask_revocation_reason): New.
+ (release_revocation_reason_info): New.
+ (revocation_reason_build_cb): New.
+ (gen_revoke): Ask for reason.
+ * main.h (struct revocation_reason_info): Add declaration.
+ * keyedit.c (menu_revsig): Add support for revocation reason.
+ (menu_revkey): Ditto.
+ (sign_uid_mk_attrib): Renamed to ...
+ (sign_mk_attrib): ... this, made static and add support for reasons.
- * 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.
+Tue Feb 15 08:48:13 CET 2000 Werner Koch <wk@gnupg.de>
+
+ * build-packet.c (build_packet): Fixed fixing of old comment packets.
+
+ * import.c (import_keys): Fixed importing from stdin when called with
+ nnames set to zero as it normally happens.
+
+Mon Feb 14 14:30:20 CET 2000 Werner Koch <wk@gnupg.de>
+
+ * sig-check.c (check_key_signature2): Add new arg r_expired.
+ (do_signature_check): New arg to pass it down to ...
+ (do_check): New arg r-expire which is set when the signature
+ has expired.
+ * trustdb.c (check_sig_record): Set SIGF_EXPIRED flag and set
+ the expiretime to zero so that thi signature will not be checked
+ anymore.
+
+Fri Feb 11 17:44:40 CET 2000 Werner Koch <wk@gnupg.de>
- * misc.c (mpi_print): New.
+ * g10.c (g10_exit): Update the random seed_file.
+ (main): Set the random seed file. New option --no-random-seed-file.
- * misc.c (checksum_mpi): Now uses gcry_mpi_print to get the data.
+Thu Feb 10 17:39:44 CET 2000 Werner Koch <wk@gnupg.de>
- * seckey-cert.c (do_check): Replaced mpi_read_from_buffer.
+ * keyedit.c (menu_expire): Fixed segv due to unitialized sub_pk.
+ By Rémi.
+
+Thu Feb 10 11:39:41 CET 2000 Werner Koch <wk@gnupg.de>
+
+ * keylist.c (list_keyblock): Don't print warnings in the middle of
+ regulat output lines. By Rémi.
+
+ * sig-check.c: Include options.h
+
+Wed Feb 9 15:33:44 CET 2000 Werner Koch <wk@gnupg.de>
+
+ * gpg.c: New option --ignore-time-conflict
+ * sig-check.c (do_check): Implemented this option.
+ * trustdb.c (check_trust): Ditto.
+ * sign.c (do_sign): Ditto.
+ * keygen.c (generate_subkeypair): Ditto.
+
+ * encode.c (encode_simple): use iobuf_cancel after open failure.
+ Reported by Huy Le.
+
+Fri Jan 14 18:32:01 CET 2000 Werner Koch <wk@gnupg.de>
+
+ * packet.h (STRING2KEY): Changed mode from byte to int.
+ * parse-packet.c (parse_key): Add the special GNU protection stuff
+ * build-packet.c (so_secret_key): Ditto.
+ * seckey-cert.c (do_check): Ditto.
+ * keyedit.c (change_passphrase): Ditto.
+ * export.c (export_secsubkeys): New.
+ (do_export_stream): Hack to export the primary key using mode 1001.
+ * g10.c: New command --export-secret-subkeys
+
+Thu Jan 13 19:31:58 CET 2000 Werner Koch <wk@gnupg.de>
+
+ * armor.c (is_armored): Check for 1-pass-sig packets. Reported by
+ David Hallinan <hallinan@rtd.com>.
+ (armor_filter): Replaced one LF by the LF macro. Reported by
+ Wolfgang Redtenbacher.
+
+Wed Jan 5 11:51:17 CET 2000 Werner Koch <wk@gnupg.de>
+
+ * g10.c (main): Reset new global flag opt.pgp2_workarounds
+ when --openpgp is used.
+ * mainproc.c (proc_plaintext): Do the PGP2,5 workarounds only
+ when the global flag is set.
+ (proc_tree): Ditto.
+ * textfilter.c (copy_clearsig_text): Ditto.
+ * armor.c (armor_filter): Ditto.
+
+ * g10.c: New option --list-only
+ * mainproc.c (proc_tree): Don't do it if opt.list_only is active.
+ (proc_pubkey_enc): Implement option.
+
+ * status.h, status.c ({BEGIN,END}_{EN,DE}CRYPTION): New.
+ * cipher.c (cipher_filter): New status outputs.
+ * mainproc.c (proc_encrypted): New status outputs.
+
+Fri Dec 31 14:08:15 CET 1999 Werner Koch <wk@gnupg.de>
* armor.c (armor_filter): Made the "Comment:" header translatable.
-Wed Dec 8 21:58:32 CET 1999 Werner Koch <wk@gnupg.de>
+ * hkp.c (hkp_import): Make sure that the program does not return
+ success when there is a connection problem. Reported by Phillip Jones.
+
+Sun Dec 19 15:22:26 CET 1999 Werner Koch <wk@gnupg.de>
+
+ * armor.c (LF): Use this new macro at all places where a line LF
+ is needed. This way DOSish textfiles should be created when the
+ input data is also in dos mode.
+ * sign.c (LF): Ditto.
+ * textfilter.c (LF): Ditto.
+ (copy_clearsig_text): Disabled the forcing of CR,LF sequences
+ for DOS systems.
+
+ * plaintext.c (handle_plaintext): Fixes for line endings on DOS.
+ and react on a LF in cleartext.
+ * armor.c (fake_packet): Restore the original line ending after
+ removing trailing spaces.
+
+ * signal.c (got_fatal_signal): DOS fix.
- * seckey-cert.c: Removed obsolete mpi_*_protect_flag.
- * parse-packet.c: Ditto.
+Thu Dec 16 10:07:58 CET 1999 Werner Koch <wk@gnupg.de>
- * 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.
+ * mainproc.c (print_failed_pkenc): Fix for unknown algorithm.
+ Found by fygrave@epr0.org.
- * g10.c (main): Check libgcrypt version.
+Thu Dec 9 10:31:05 CET 1999 Werner Koch <wk@gnupg.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.
+ * hkp.c: i18n the strings.
+
+Sat Dec 4 15:32:20 CET 1999 Werner Koch <wk@gnupg.de>
+
+ * trustdb.c (verify_key): Shortcut for ultimately trusted keys.
+
+Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de>
+
+ * pkclist.c (build_pk_list): Validate the trust using the namehash
+ if this one has been set by the key lookup.
* g10.c: Add --delete-secret-key to the help page.
- * g10.c (main): Changed the default homedir to "~/.gnupg-test" so
- that we don't mess up with the stable version.
+ * openfile.c (copy_options_file): Made static.
+ (try_make_homedir): New.
+ * ringedit.c (add_keyblock_resource): Use the try_make_hoemdir logic.
+ * tdbio.c (tdbio_set_dbname): Likewise.
- * misc.c (mpi_write): New.
- (mpi_write): New.
+ * keygen.c (generate_user_id): Use m_alloc_clear() here. We should
+ better use an allocation function specific to the user_id packet.
- * 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.
+ * keygen.c (keygen_add_std_prefs): Changed symmetric preferences
+ to include Blowfish again. This is due to it's better speed compared
+ to CAST5.
-Fri Nov 19 17:15:20 CET 1999 Werner Koch <wk@gnupg.de>
+ * g10.c (strusage): Print the home directory.
- * 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().
+ * armor.c (armor_filter): Take action on the cancel control msg.
+ * filter.h (armor_filter_context_t): Add cancel flag.
- * tdbdump.c (HEXTOBIN): Changed the name of the argument, so that
- traditional cpp don't mess up the macros. Suggested by Jos Backus.
+Mon Nov 29 21:52:11 CET 1999 Werner Koch <wk@gnupg.de>
- * armor.c (parse_header_line): Stop parsing on a only WS line too.
- Suggested by Aric Cyr.
+ * g10.c: New option --fast-list-mode ..
+ * keylist.c (list_keyblock): .. and implemented.
+ * mainproc.c (list_node): Ditto.
-Mon Nov 15 21:36:02 CET 1999 Werner Koch <wk@gnupg.de>
+ * import.c (mark_non_selfsigned_uids_valid): Fixed the case that there
+ is a uid without any packet following.
- * misc.c (pull_in_libs): Removed.
+Mon Nov 22 11:14:53 CET 1999 Werner Koch <wk@gnupg.de>
+
+ * mainproc.c (proc_plaintext): Never enable the hash processing
+ when skip_verify is active.
+
+ * armor.c (parse_header_line): Stop parsing on a WS line too.
+ Suggested by Aric Cyr.
-Sat Nov 13 17:44:23 CET 1999 Werner Koch <wk@gnupg.de>
+ * tdbdump.c (HEXTOBIN): Changed the name of the argument, so that
+ traditional cpp don't mess up the macros. Suggested by Jos Backus.
* mainproc.c (list_node): Print the PK algo in the --with-colon mode.
* keylist.c (list_keyblock): Ditto.
- * misc.c (pull_in_libs): Removed pull in of g10c.
+ * signal.c (got_fatal_signal): Found the reason why exit(8) did not
+ work - it is better to set the disposition back to default before
+ raising the signal. Print the notice on stderr always.
- * misc.c (map_gcry_rc): Removed here and chnaged all users.
+Fri Nov 12 20:33:19 CET 1999 Werner Koch <wk@gnupg.de>
- * 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.
+ * g10.c (make_username): Swapped the logic.
+ * keylist.c (public_key_list): Now takes a STRLIST as arg and moved
+ the creation ot this list to the caller, so that he can copy with
+ UTF-conversion of user IDs. Changed all callers.
+ (secret_key_list): Likewise.
- * g10.c (main): Replaced the function to diable PK algos.
+ * getkey.c (get_user_id_string_native): New and ...
+ * encode.c (write_pubkey_enc_from_list): ... use it 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.
+ * pubring.asc: Updated.
- * getkey.c (find_by_name): Replaced rmd160_hash_buffer
- by gcry_md_hash_buffer.
+ * packet.h (PKT_PHOTO_ID): New.
+ * parse-packet.c (parse_photo_id): New.
+ * build-packet.c (do_user_id: Handle photo IDs.
+ (build_packet): Change CTB for photo IDs
+ * free-packet.c (free_user_id): Release memory used for photo IDs
+ * sig-check.c (hash_uid_node): Handle photo IDs too.
+ * trustdb.c (print_uid_from_keyblock): Hash photo ID.
+ (make_uid_records): Ditto.
+ * getkey.c (find_by_name): Ditto.
* keyedit.c (show_prefs): Ditto.
* keylist.c (list_keyblock): Ditto.
- * trustdb.c (print_uid_from_keyblock): Ditto.
- (make_uid_records): Ditto.
- * skclist.c (build_sk_list): Removed the test on faked RNGs.
- (is_insecure): Removed.
- * g10.c (--quick-random): Removed this option.
+Thu Oct 28 16:08:20 CEST 1999 Werner Koch <wk@gnupg.de>
+
+ * keygen.c (ask_expire_interval): Print a warning for systems
+ with a signed 32 time_t if the exiration time is beyoind 2038.
+
+Fri Oct 8 20:40:50 CEST 1999 Werner Koch <wk@gnupg.de>
- * Replaced all PUBKEY_ALGO_xxx by GCRY_PK_xxxx.
+ * ringedit.c (enum_keyblocks): The last fix way really stupid;
+ reverted and set rt to Unknown.
- * 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.
+Fri Oct 8 20:32:01 CEST 1999 Werner Koch <wk@gnupg.de>
-Tue Oct 26 20:03:44 CEST 1999 Werner Koch <wk@gnupg.de>
+ * ringedit.c (enum_keyblocks): Zero the entire kbpos out on open.
- * Makefile.am (basicdefs.h): Added.
- (install-data-local): Removed the handling for historic gpgm.
+ * g10.c (oEntropyDLL): Removed option.
+ (main): Made the warning on development versions more verbose.
-Tue Oct 26 14:10:21 CEST 1999 Werner Koch <wk@gnupg.de>
+ * g10.c (oHonorHttpProxy): New option.
+ * hkp.c (hkp_ask_import,hkp_export): Implement this option.
+ * options.skel: Enable this option for new installations
- * misc.c (openpgp_cipher_test_algo): New.
- (openpgp_pk_test_algo): New.
- (openpgp_md_test_algo): New.
+Mon Oct 4 21:23:04 CEST 1999 Werner Koch <wk@gnupg.de>
- * g10.c (build_list): Changed to use the new functions from libgcrypt.
+ * import.c (import_keys): Changed calling interface, adjusted caller.
+ (import): Moved printing of stats out ...
+ (print_stats): New. ... to here.
+ (import_keys_stream): Call stats print here.
+ (import_keys): Print stats as totals for all files.
- * ringedit.c (enum_keyblocks): Set .rt to 0 on open.
+ * tdbio.h (DIRF_NEWKEYS): New
+ * tdbio.c (tdbio_dump_record): Print the new flag.
+ * trustdb.c (check_trust_record): New arg sigs_only. Adapted all
+ callers.
+ (do_update_trust_record): Removed recheck arg and add a new sigs_only
+ do we can later improve on the performance. Changed all callers too.
+ (check_trustdb): Evalutate the new flag and add a status output.
+ Do a check when the dir record has not been checked.
+ (build_cert_tree): Evaluate the new flag.
+ (check_trust): Ditto. Do a trust_record check, when the dir record
+ is not marked as checked.
+ (mark_fresh_keys): New.
+ (clear_lid_table): New.
+ (sync_trustdb): New.
+ * import.c (import_keys): Call sync_trustdb() after processing.
+ (import_keys_stream): Ditto.
+ * tdbdump.c (import_ownertrust): Ditto.
+
+ * import.c (import_revoke_cert): Notify the trust DB.
+ (do_update_trust_record): Use |= to set the REVOKED bit and not &=;
+ shame on me for this bad copy+paste introduced bug.
+ (do_we_trust): Add trustmask to allow revoked key override to work.
+ Chnaged are to allow return of a mofified trustlevel. Adapted the
+ one caller.
+
+ * g10.c: New options --emulate-3des-s2k-bug
+ * passphrase.c (hash_passphrase): Implemented above.
+
+ * mainproc.c (proc_tree): Check for standalone signatures.
+ (do_check_sig): Print a notice for a standalone revocation
+ (check_sig_and_print): Do not print an error for unchecked standalone
+ revocations.
+
+Tue Sep 28 20:54:37 CEST 1999 Werner Koch <wk@gnupg.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.
- * 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.
-
- (clearsign_file): Use gcry_md_test_algo() and gcry_md_algo_name().
+ * armor.c (armor_filter): Set a flag if no OpenPGP data has been found.
+ * verify.c (verify_signatures): Add an error helptext.
- * 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.
-
- * encr-data.c (decrypt_data): Reset error on a weak key.
-
- * 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.
-
- * pkclist.c (do_edit_ownertrust): Made the answer string const.
-
- * basicdefs.h: New. Move some defs and decl to this header.
+Thu Sep 23 19:24:30 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* openfile.c (open_outfile): Fixed the 8dot3 handling.
@@ -236,17 +715,33 @@ Tue Oct 26 14:10:21 CEST 1999 Werner Koch <wk@gnupg.de>
* trustdb.c (print_user_id,check_uidsigs): Ditto.
* revoke.c (gen_revoke,ask_revoke_sig): Ditto.
-Sat Sep 18 12:16:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
+Thu Sep 23 09:52:58 CEST 1999 Werner Koch <wk@isil.d.shuttle.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.
+ * verify.c (print_file_status): New.
+ (verify_one_file): Moved status print to th new fnc. Add error status.
+ * status.c, status.h (STATUS_FILE_ERROR): New
- * misc.c (map_gcry_rc): New.
+Wed Sep 22 10:14:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
-Fri Sep 17 12:56:42 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
+ * 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 suffiy instead of
+ appending it.
+
+ * status.c, status.h: Add STATUS_FILE_{START,DONE}.
+ * verify.c (verify_one_file): Emit these new stati.
+ * 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 Sep 20 12:24:41 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
+
+
+ * verify.c (verify_files, ferify_one_file): New.
+ * g10.c: New command --verify-files
+
+Fri Sep 17 12:56:42 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* g10.c: Add UK spelling as alias for armor options ;-)
@@ -256,16 +751,13 @@ Fri Sep 17 12:56:42 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
Wed Sep 15 16:22:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
-
* g10.c: New option --entropy-dll-name
Mon Sep 13 10:51:29 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
-
* signal.c (got_fatal_signal): Print message using write(2) and
only for development versions.
-
Mon Sep 6 19:59:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* tdbio.c (tdbio_set_dbname): Use mkdir macro
diff --git a/g10/Makefile.am b/g10/Makefile.am
index 55d0ed222..6b95ac3a5 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -6,10 +6,11 @@ OMIT_DEPENDENCIES = zlib.h zconf.h
LDFLAGS = -static @LDFLAGS@ @DYNLINK_LDFLAGS@
# 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.la ../gcrypt/libgcrypt.la ../jnlib/libjnlib.la ../util/libutil.la
+needed_libs = ../util/libutil.la ../gcrypt/libgcrypt.la \
+ ../jnlib/libjnlib.la ../util/libutil.la
#noinst_PROGRAMS = gpgd
-bin_PROGRAMS = gpg kbxutil
+bin_PROGRAMS = gpg kbxutil
common_source = \
build-packet.c \
diff --git a/g10/armor.c b/g10/armor.c
index 0661d76ef..819c951dc 100644
--- a/g10/armor.c
+++ b/g10/armor.c
@@ -1,5 +1,5 @@
/* armor.c - Armor flter
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -37,6 +37,11 @@
#include "status.h"
#include "i18n.h"
+#ifdef HAVE_DOSISH_SYSTEM
+ #define LF "\r\n"
+#else
+ #define LF "\n"
+#endif
#define MAX_LINELEN 20000
@@ -162,6 +167,7 @@ is_armored( const byte *buf )
switch( pkttype ) {
case PKT_MARKER:
case PKT_SYMKEY_ENC:
+ case PKT_ONEPASS_SIG:
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
case PKT_PUBKEY_ENC:
@@ -485,13 +491,26 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
if( !maxlen )
afx->truncated++;
if( !afx->not_dash_escaped ) {
+ int crlf;
+ p = afx->buffer;
+ n = afx->buffer_len;
+ crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n';
+
/* PGP2 does not treat a tab as white space character */
- afx->buffer_len =
- trim_trailing_chars( afx->buffer, afx->buffer_len,
+ afx->buffer_len = trim_trailing_chars( p, n,
afx->pgp2mode ? " \r\n" : " \t\r\n");
/* the buffer is always allocated with enough space to append
- * a CR, LF, Nul */
- afx->buffer[afx->buffer_len++] = '\r';
+ * 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
+ * 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
+ * a way to send the hash down the processing line (well, a special
+ * faked packet could do the job).
+ */
+ if( crlf )
+ afx->buffer[afx->buffer_len++] = '\r';
afx->buffer[afx->buffer_len++] = '\n';
afx->buffer[afx->buffer_len] = 0;
}
@@ -819,7 +838,8 @@ armor_filter( void *opaque, int control,
hashes &= 1|2|4|8;
if( !hashes ) {
hashes |= 4; /* default to MD 5 */
- afx->pgp2mode = 1;
+ if( opt.pgp2_workarounds )
+ afx->pgp2mode = 1;
}
n=0;
do {
@@ -827,7 +847,7 @@ armor_filter( void *opaque, int control,
buf[n++] = 0x90; /* old format, type 4, 1 length byte */
buf[n++] = 13; /* length */
buf[n++] = 3; /* version */
- buf[n++] = 0x01; /* sigclass 0x01 (canonical text mode)*/
+ buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
if( hashes & 1 ) {
hashes &= ~1;
buf[n++] = GCRY_MD_RMD160;
@@ -874,7 +894,7 @@ armor_filter( void *opaque, int control,
#endif
*ret_len = n;
}
- else if( control == IOBUFCTRL_FLUSH ) {
+ else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) {
if( !afx->status ) { /* write the header line */
const char *s;
@@ -882,10 +902,10 @@ armor_filter( void *opaque, int control,
log_bug("afx->what=%d", afx->what);
iobuf_writestr(a, "-----");
iobuf_writestr(a, head_strings[afx->what] );
- iobuf_writestr(a, "-----\n");
+ iobuf_writestr(a, "-----" LF );
if( !opt.no_version )
iobuf_writestr(a, "Version: GnuPG v" VERSION " ("
- PRINTABLE_OS_NAME ")\n");
+ PRINTABLE_OS_NAME ")" LF );
/* write the comment string or a default one */
s = opt.comment_string ? opt.comment_string
@@ -902,16 +922,17 @@ armor_filter( void *opaque, int control,
else
iobuf_put(a, *s );
}
- iobuf_put(a, '\n' );
+ iobuf_writestr(a, LF );
}
if( afx->hdrlines )
iobuf_writestr(a, afx->hdrlines);
- iobuf_put(a, '\n');
+ iobuf_writestr(a, LF );
afx->status++;
afx->idx = 0;
afx->idx2 = 0;
afx->crc = CRCINIT;
+
}
crc = afx->crc;
idx = afx->idx;
@@ -936,7 +957,7 @@ armor_filter( void *opaque, int control,
c = bintoasc[radbuf[2]&077];
iobuf_put(a, c);
if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
- iobuf_put(a, '\n');
+ iobuf_writestr(a, LF );
idx2=0;
}
}
@@ -951,8 +972,13 @@ armor_filter( void *opaque, int control,
if( !is_initialized )
initialize();
}
+ else if( control == IOBUFCTRL_CANCEL ) {
+ afx->cancel = 1;
+ }
else if( control == IOBUFCTRL_FREE ) {
- if( afx->status ) { /* pad, write cecksum, and bottom line */
+ if( afx->cancel )
+ ;
+ else if( afx->status ) { /* pad, write cecksum, and bottom line */
crc = afx->crc;
idx = afx->idx;
idx2 = afx->idx2;
@@ -975,13 +1001,13 @@ armor_filter( void *opaque, int control,
iobuf_put(a, '=');
}
if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
- iobuf_put(a, '\n');
+ iobuf_writestr(a, LF );
idx2=0;
}
}
/* may need a linefeed */
if( idx2 )
- iobuf_put(a, '\n');
+ iobuf_writestr(a, LF );
/* write the CRC */
iobuf_put(a, '=');
radbuf[0] = crc >>16;
@@ -995,16 +1021,17 @@ armor_filter( void *opaque, int control,
iobuf_put(a, c);
c = bintoasc[radbuf[2]&077];
iobuf_put(a, c);
- iobuf_put(a, '\n');
+ iobuf_writestr(a, LF );
/* and the the trailer */
if( afx->what >= DIM(tail_strings) )
log_bug("afx->what=%d", afx->what);
iobuf_writestr(a, "-----");
iobuf_writestr(a, tail_strings[afx->what] );
- iobuf_writestr(a, "-----\n");
+ iobuf_writestr(a, "-----" LF );
}
else if( !afx->any_data && !afx->inp_bypass ) {
log_error(_("no valid OpenPGP data found.\n"));
+ afx->no_openpgp_data = 1;
write_status_text( STATUS_NODATA, "1" );
}
if( afx->truncated )
diff --git a/g10/build-packet.c b/g10/build-packet.c
index 84912ac05..878158917 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -1,5 +1,5 @@
/* build-packet.c - assemble packets and write them
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -24,11 +24,11 @@
#include <string.h>
#include <assert.h>
+#include <gcrypt.h>
#include "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "util.h"
-#include <gcrypt.h>
#include "options.h"
#include "main.h"
@@ -43,6 +43,7 @@ static u32 calc_plaintext( PKT_plaintext *pt );
static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt );
static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed );
static int do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed );
+static int do_mdc( IOBUF out, PKT_mdc *mdc );
static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd );
static int do_signature( IOBUF out, int ctb, PKT_signature *sig );
static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops );
@@ -66,25 +67,31 @@ int
build_packet( IOBUF out, PACKET *pkt )
{
int new_ctb=0, rc=0, ctb;
+ int pkttype;
if( DBG_PACKET )
log_debug("build_packet() type=%d\n", pkt->pkttype );
assert( pkt->pkt.generic );
- switch( pkt->pkttype ) {
- case PKT_OLD_COMMENT: pkt->pkttype = PKT_COMMENT; break;
+ switch( (pkttype = pkt->pkttype) ) {
+ case PKT_OLD_COMMENT: pkttype = pkt->pkttype = PKT_COMMENT; break;
case PKT_PLAINTEXT: new_ctb = pkt->pkt.plaintext->new_ctb; break;
case PKT_ENCRYPTED:
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;
+ break;
default: break;
}
- if( new_ctb || pkt->pkttype > 15 ) /* new format */
- ctb = 0xc0 | (pkt->pkttype & 0x3f);
+ if( new_ctb || pkttype > 15 ) /* new format */
+ ctb = 0xc0 | (pkttype & 0x3f);
else
- ctb = 0x80 | ((pkt->pkttype & 15)<<2);
- switch( pkt->pkttype ) {
+ ctb = 0x80 | ((pkttype & 15)<<2);
+ switch( pkttype ) {
+ case PKT_PHOTO_ID:
case PKT_USER_ID:
rc = do_user_id( out, ctb, pkt->pkt.user_id );
break;
@@ -114,6 +121,9 @@ build_packet( IOBUF out, PACKET *pkt )
case PKT_ENCRYPTED_MDC:
rc = do_encrypted_mdc( out, ctb, pkt->pkt.encrypted );
break;
+ case PKT_MDC:
+ rc = do_mdc( out, pkt->pkt.mdc );
+ break;
case PKT_COMPRESSED:
rc = do_compressed( out, ctb, pkt->pkt.compressed );
break;
@@ -148,6 +158,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_USER_ID:
case PKT_COMMENT:
case PKT_PUBLIC_KEY:
@@ -172,11 +183,11 @@ static void
write_fake_data( IOBUF out, MPI a )
{
if( a ) {
- size_t i;
+ int i;
void *p;
- p = gcry_mpi_get_opaque( a, &i );
- iobuf_write( out, p, (i+7)/8 );
+ p = mpi_get_opaque( a, &i );
+ iobuf_write( out, p, i );
}
}
@@ -195,11 +206,20 @@ do_comment( IOBUF out, int ctb, PKT_comment *rem )
static int
do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
{
- 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;
+ 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;
+ }
+ 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 0;
}
@@ -358,19 +378,30 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
else {
iobuf_put(a, 0xff );
iobuf_put(a, sk->protect.algo );
- iobuf_put(a, sk->protect.s2k.mode );
- iobuf_put(a, sk->protect.s2k.hash_algo );
+ if( sk->protect.s2k.mode >= 1000 ) {
+ 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 );
+ }
+ else {
+ iobuf_put(a, sk->protect.s2k.mode );
+ iobuf_put(a, sk->protect.s2k.hash_algo );
+ }
if( sk->protect.s2k.mode == 1
|| 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_write(a, sk->protect.iv, sk->protect.ivlen );
+ if( sk->protect.s2k.mode != 1001 )
+ iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
}
}
else
iobuf_put(a, 0 );
- if( sk->is_protected && sk->version >= 4 ) {
+ if( sk->protect.s2k.mode == 1001 )
+ ;
+ else if( sk->is_protected && sk->version >= 4 ) {
byte *p;
size_t n;
assert( gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
@@ -379,7 +410,7 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
}
else {
for( ; i < nskey; i++ )
- mpi_write_opaque(a, sk->skey[i] );
+ mpi_write(a, sk->skey[i] );
write_16(a, sk->csum );
}
@@ -527,13 +558,24 @@ do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed )
n = ed->len ? (ed->len + 10) : 0;
write_header(out, ctb, n );
iobuf_put(out, 1 ); /* version */
- iobuf_put(out, ed->mdc_method );
/* This is all. The caller has to write the real data */
return rc;
}
+
+static int
+do_mdc( IOBUF out, PKT_mdc *mdc )
+{
+ /* This packet requires a fixed header encoding */
+ 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 0;
+}
+
static int
do_compressed( IOBUF out, int ctb, PKT_compressed *cd )
{
@@ -623,7 +665,6 @@ void
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;
@@ -659,6 +700,7 @@ build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
case SIGSUBPKT_KEY_EXPIRE:
case SIGSUBPKT_NOTATION:
case SIGSUBPKT_POLICY:
+ case SIGSUBPKT_REVOC_REASON:
hashed = 1; break;
default: hashed = 0; break;
}
diff --git a/g10/cipher.c b/g10/cipher.c
index 8fc0d3815..cad6ff664 100644
--- a/g10/cipher.c
+++ b/g10/cipher.c
@@ -1,5 +1,5 @@
/* cipher.c - En-/De-ciphering filter
- * Copyright (C) 1998,1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -33,6 +33,7 @@
#include "packet.h"
#include "options.h"
#include "main.h"
+#include "status.h"
#define MIN_PARTIAL_SIZE 512
@@ -44,10 +45,18 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
PACKET pkt;
PKT_encrypted ed;
byte temp[18];
- int blocksize;
- unsigned nprefix;
- int use_mdc = opt.force_mdc;
+ unsigned int blocksize;
+ unsigned int nprefix;
int rc;
+ int use_mdc = opt.force_mdc;
+
+ blocksize = gcry_cipher_get_algo_blklen( cfx->dek->algo );
+ if( blocksize < 8 || blocksize > 16 )
+ log_fatal("unsupported blocksize %u\n", blocksize );
+ if( blocksize != 8 )
+ use_mdc = 1; /* enable it for all modern ciphers */
+ if( opt.rfc2440 )
+ use_mdc = 0; /* override - rfc2440 does not know about MDC */
memset( &ed, 0, sizeof ed );
ed.len = cfx->datalen;
@@ -55,18 +64,16 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
if( use_mdc ) {
ed.mdc_method = GCRY_MD_SHA1;
cfx->mdc_hash = gcry_md_open( GCRY_MD_SHA1, 0 );
- /*should we check the function works, or is it better to provide
- a flag which makes the function die itself ?? FIXME */
- /*md_start_debug( cfx->mdc_hash, "mdccreat" );*/
+ if( !cfx->mdc_hash )
+ BUG();
+ if ( DBG_HASHING )
+ gcry_md_start_debug( cfx->mdc_hash, "creatmdc" );
}
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");
- blocksize = gcry_cipher_get_algo_blklen( cfx->dek->algo );
- if( blocksize < 8 || blocksize > 16 )
- log_fatal("unsupported blocksize %d\n", blocksize );
nprefix = blocksize;
gcry_randomize( temp, nprefix, GCRY_STRONG_RANDOM );
temp[nprefix] = temp[nprefix-2];
@@ -75,7 +82,7 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
if( !(cfx->cipher_hd = gcry_cipher_open( cfx->dek->algo,
GCRY_CIPHER_MODE_CFB,
GCRY_CIPHER_SECURE
- | (cfx->dek->algo >= 100 ?
+ | ((use_mdc || cfx->dek->algo >= 100) ?
0 : GCRY_CIPHER_ENABLE_SYNC)))
) {
/* we should never get an error here cause we already checked, that
@@ -83,6 +90,7 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
BUG();
}
+
/* log_hexdump( "thekey", cfx->dek->key, cfx->dek->keylen );*/
rc = gcry_cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen );
if( !rc )
@@ -99,6 +107,7 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
log_fatal("encrypt failed: %s\n", gcry_strerror(rc) );
iobuf_write(a, temp, nprefix+2);
cfx->header=1;
+
}
@@ -120,6 +129,7 @@ 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 )
@@ -134,15 +144,26 @@ cipher_filter( void *opaque, int control,
if( cfx->mdc_hash ) {
byte *hash;
int hashlen = gcry_md_get_algo_dlen( gcry_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] );
+
hash = gcry_md_read( cfx->mdc_hash, 0 );
- rc = gcry_cipher_encrypt( cfx->cipher_hd, hash, hashlen, NULL, 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) );
- if( iobuf_write( a, hash, hashlen ) )
- rc = GPGERR_WRITE_FILE;
gcry_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 );
}
else if( control == IOBUFCTRL_DESC ) {
*(char**)buf = "cipher_filter";
diff --git a/g10/comment.c b/g10/comment.c
index fe80a1cf8..f0d884979 100644
--- a/g10/comment.c
+++ b/g10/comment.c
@@ -1,5 +1,5 @@
/* comment.c - write comment stuff
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
diff --git a/g10/compress.c b/g10/compress.c
index 48335ba89..2666e9051 100644
--- a/g10/compress.c
+++ b/g10/compress.c
@@ -1,5 +1,5 @@
/* compress.c - compress filter
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -27,8 +27,8 @@
#include <errno.h>
#include <zlib.h>
-#include "util.h"
#include <gcrypt.h>
+#include "util.h"
#include "packet.h"
#include "filter.h"
#include "options.h"
diff --git a/g10/dearmor.c b/g10/dearmor.c
index 1c0a15bc6..937961e7f 100644
--- a/g10/dearmor.c
+++ b/g10/dearmor.c
@@ -1,5 +1,5 @@
/* dearmor.c - Armor utility
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 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 <gcrypt.h>
#include "util.h"
#include "filter.h"
#include "packet.h"
diff --git a/g10/decrypt.c b/g10/decrypt.c
index e9f1d2b93..981275602 100644
--- a/g10/decrypt.c
+++ b/g10/decrypt.c
@@ -1,5 +1,5 @@
/* decrypt.c - verify signed data
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -25,12 +25,12 @@
#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 <gcrypt.h>
#include "util.h"
#include "main.h"
#include "i18n.h"
diff --git a/g10/delkey.c b/g10/delkey.c
index c452567a8..0c64d41a3 100644
--- a/g10/delkey.c
+++ b/g10/delkey.c
@@ -1,5 +1,5 @@
/* delkey.c - delete keys
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -62,6 +62,7 @@ delete_key( const char *username, int secret )
: find_keyblock_byname( &kbpos, username );
if( rc ) {
log_error(_("%s: user not found\n"), username );
+ write_status_text( STATUS_DELETE_PROBLEM, "1" );
goto leave;
}
@@ -93,10 +94,12 @@ delete_key( const char *username, int secret )
"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;
}
- else if( rc != GPGERR_NO_SECKEY )
+ else if( rc != GPGERR_NO_SECKEY ) {
log_error("%s: get secret key: %s\n", username, gpg_errstr(rc) );
+ }
else
rc = 0;
}
diff --git a/g10/encode.c b/g10/encode.c
index ed4b1df0f..6195b533c 100644
--- a/g10/encode.c
+++ b/g10/encode.c
@@ -1,5 +1,5 @@
/* encode.c - encode data
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -41,6 +41,7 @@
static int encode_simple( const char *filename, int mode );
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.
@@ -162,7 +163,7 @@ encode_simple( const char *filename, int mode )
}
if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) {
- iobuf_close(inp);
+ iobuf_cancel(inp);
gcry_free(cfx.dek);
gcry_free(s2k);
return rc;
@@ -510,7 +511,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
* number of bits we have to use. We then encode the session
* key in some way and we get it back in the big intger value
* FRAME. Then we use FRAME, the public key PK->PKEY and the
- * algorithm number PK->PUBKEY_ALGO and pass it to pk_encrypt
+ * algorithm number PK->PUBKEY_ALGO and pass it to pubkey_encrypt
* which returns the encrypted value in the array ENC->DATA.
* This array has a size which depends on the used algorithm
* (e.g. 2 for ElGamal). We don't need frame anymore because we
@@ -525,7 +526,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
log_error("pubkey_encrypt failed: %s\n", gpg_errstr(rc) );
else {
if( opt.verbose ) {
- char *ustr = get_user_id_string( enc->keyid );
+ 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 );
diff --git a/g10/encr-data.c b/g10/encr-data.c
index 7c90829e2..17d43e9d6 100644
--- a/g10/encr-data.c
+++ b/g10/encr-data.c
@@ -1,5 +1,5 @@
/* encr-data.c - process an encrypted data packet
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+
#include <gcrypt.h>
#include "util.h"
#include "packet.h"
@@ -30,9 +31,9 @@
#include "i18n.h"
-static int decode_filter( void *opaque, int control, IOBUF a,
- byte *buf, size_t *ret_len);
static int mdc_decode_filter( void *opaque, int control, IOBUF a,
+ byte *buf, size_t *ret_len);
+static int decode_filter( void *opaque, int control, IOBUF a,
byte *buf, size_t *ret_len);
typedef struct {
@@ -54,8 +55,8 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
byte *p;
int rc=0, c, i;
byte temp[32];
- int blocksize;
- unsigned nprefix;
+ unsigned int blocksize;
+ unsigned int nprefix;
memset( &dfx, 0, sizeof dfx );
if( gcry_cipher_test_algo( dek->algo ) ) {
@@ -68,7 +69,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
log_info(_("%s encrypted data\n"), gcry_cipher_algo_name( dek->algo ) );
blocksize = gcry_cipher_get_algo_blklen( dek->algo );
- if( blocksize < 1 || blocksize > 16 )
+ if( !blocksize || blocksize > 16 )
log_fatal("unsupported blocksize %u\n", blocksize );
nprefix = blocksize;
if( ed->len && ed->len < (nprefix+2) )
@@ -76,13 +77,13 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
if( ed->mdc_method ) {
dfx.mdc_hash = gcry_md_open( ed->mdc_method, 0 );
- if( !dfx.mdc_hash )
- BUG();
+ if ( DBG_HASHING )
+ gcry_md_start_debug(dfx.mdc_hash, "checkmdc");
}
if( !(dfx.cipher_hd = gcry_cipher_open( dek->algo,
GCRY_CIPHER_MODE_CFB,
GCRY_CIPHER_SECURE
- | (dek->algo >= 100 ?
+ | ((ed->mdc_method || dek->algo >= 100)?
0 : GCRY_CIPHER_ENABLE_SYNC) ))
) {
/* we should never get an error here cause we already checked, that
@@ -122,8 +123,6 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
temp[i] = c;
}
gcry_cipher_decrypt( dfx.cipher_hd, temp, nprefix+2, NULL, 0 );
- if( dfx.mdc_hash )
- gcry_md_write( dfx.mdc_hash, temp, nprefix+2 );
gcry_cipher_sync( dfx.cipher_hd );
p = temp;
/* log_hexdump( "prefix", temp, nprefix+2 ); */
@@ -131,22 +130,30 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
rc = GPGERR_BAD_KEY;
goto leave;
}
+
+ if( dfx.mdc_hash )
+ gcry_md_write( dfx.mdc_hash, temp, nprefix+2 );
+
if( ed->mdc_method )
iobuf_push_filter( ed->buf, mdc_decode_filter, &dfx );
else
iobuf_push_filter( ed->buf, decode_filter, &dfx );
- proc_packets( procctx, ed->buf);
+
+ proc_packets( procctx, ed->buf );
ed->buf = NULL;
if( ed->mdc_method && dfx.eof_seen == 2 )
rc = GPGERR_INVALID_PACKET;
else if( ed->mdc_method ) { /* check the mdc */
int datalen = gcry_md_get_algo_dlen( ed->mdc_method );
+
+ gcry_cipher_decrypt( dfx.cipher_hd, dfx.defer, 20, NULL, 0);
if( datalen != 20
|| memcmp(gcry_md_read( dfx.mdc_hash, 0 ), dfx.defer, datalen) )
rc = GPGERR_BAD_SIGN;
- log_hexdump("MDC calculated:", gcry_md_read( dfx.mdc_hash, 0), datalen);
- log_hexdump("MDC message :", dfx.defer, 20);
+ /*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 );
@@ -154,6 +161,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
}
+
/* I think we should merge this with cipher_filter */
static int
mdc_decode_filter( void *opaque, int control, IOBUF a,
@@ -180,11 +188,14 @@ mdc_decode_filter( void *opaque, int control, IOBUF a,
}
if( n == 40 ) {
/* we have enough stuff - flush the deferred stuff */
- /* (we have asserted that the buffer is large enough */
- if( !dfx->defer_filled ) /* the first time */
+ /* (we have asserted that the buffer is large enough) */
+ if( !dfx->defer_filled ) { /* the first time */
memcpy(buf, buf+20, 20 );
- else
+ n = 20;
+ }
+ else {
memcpy(buf, dfx->defer, 20 );
+ }
/* now fill up */
for(; n < size; n++ ) {
if( (c = iobuf_get(a)) == -1 )
@@ -198,7 +209,7 @@ mdc_decode_filter( void *opaque, int control, IOBUF a,
dfx->defer_filled = 1;
}
else if( !dfx->defer_filled ) { /* eof seen buf empty defer */
- /* this is very bad because there is an incomplete hash */
+ /* this is bad because there is an incomplete hash */
n -= 20;
memcpy(buf, buf+20, n );
dfx->eof_seen = 2; /* eof with incomplete hash */
@@ -238,7 +249,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);
+ gcry_cipher_decrypt( fc->cipher_hd, buf, n, NULL, 0 );
else
rc = -1; /* eof */
*ret_len = n;
diff --git a/g10/export.c b/g10/export.c
index df81babf4..2de9f91bf 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -1,5 +1,5 @@
/* export.c
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -25,11 +25,11 @@
#include <errno.h>
#include <assert.h>
+#include <gcrypt.h>
#include "options.h"
#include "packet.h"
#include "errors.h"
#include "keydb.h"
-#include <gcrypt.h>
#include "util.h"
#include "main.h"
#include "i18n.h"
@@ -71,6 +71,12 @@ export_seckeys( STRLIST users )
return do_export( users, 1, 0 );
}
+int
+export_secsubkeys( STRLIST users )
+{
+ return do_export( users, 2, 0 );
+}
+
static int
do_export( STRLIST users, int secret, int onlyrfc )
{
@@ -168,6 +174,16 @@ 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;
+ }
+
/* and write it */
for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) {
/* don't export any comment packets but those in the
@@ -183,7 +199,20 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
continue; /* not exportable */
}
- if( (rc = build_packet( out, node->pkt )) ) {
+ if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY ) {
+ /* we don't want to export the secret parts of the
+ * primary key, this is done by using GNU protection mode 1001
+ */
+ int save_mode = node->pkt->pkt.secret_key->protect.s2k.mode;
+ node->pkt->pkt.secret_key->protect.s2k.mode = 1001;
+ rc = build_packet( out, node->pkt );
+ node->pkt->pkt.secret_key->protect.s2k.mode = save_mode;
+ }
+ else {
+ rc = build_packet( out, node->pkt );
+ }
+
+ if( rc ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, gpg_errstr(rc) );
rc = GPGERR_WRITE_FILE;
diff --git a/g10/filter.h b/g10/filter.h
index 389026d2c..a29d2aa29 100644
--- a/g10/filter.h
+++ b/g10/filter.h
@@ -1,5 +1,5 @@
/* filter.h
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -26,7 +26,6 @@
#include "iobuf.h"
-
typedef struct {
GCRY_MD_HD md; /* catch all */
GCRY_MD_HD md2; /* if we want to calculate an alternate hash */
@@ -39,6 +38,9 @@ typedef struct {
int only_keyblocks; /* skip all headers but ".... key block" */
const char *hdrlines; /* write these headerlines */
+ /* these fileds must be initialized to zero */
+ int no_openpgp_data; /* output flag: "No valid OpenPGP data found" */
+
/* the following fields must be initialized to zero */
int inp_checked; /* set if the input has been checked */
int inp_bypass; /* set if the input is not armored */
@@ -60,6 +62,7 @@ typedef struct {
u32 crc;
int status; /* an internal state flag */
+ int cancel;
int any_data; /* any valid armored data seen */
int pending_lf; /* used together with faked */
} armor_filter_context_t;
@@ -83,6 +86,8 @@ typedef struct {
GCRY_CIPHER_HD cipher_hd;
int header;
GCRY_MD_HD mdc_hash;
+ byte enchash[20];
+ int create_mdc; /* flag will be set by the cipher filter */
} cipher_filter_context_t;
@@ -93,7 +98,6 @@ typedef struct {
} encrypt_filter_context_t;
-
typedef struct {
byte *buffer; /* malloced buffer */
unsigned buffer_size; /* and size of this buffer */
@@ -108,8 +112,6 @@ typedef struct {
} text_filter_context_t;
-/* encrypt_filter_context_t defined in main.h */
-
/*-- mdfilter.c --*/
int md_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len);
void free_md_filter_context( md_filter_context_t *mfx );
diff --git a/g10/free-packet.c b/g10/free-packet.c
index 173f8d812..1d9aacff6 100644
--- a/g10/free-packet.c
+++ b/g10/free-packet.c
@@ -1,5 +1,5 @@
/* free-packet.c - cleanup stuff for packets
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -24,10 +24,10 @@
#include <string.h>
#include <assert.h>
+#include <gcrypt.h>
#include "packet.h"
#include "iobuf.h"
#include "util.h"
-#include <gcrypt.h>
#include "options.h"
#include "main.h"
@@ -219,6 +219,8 @@ free_comment( PKT_comment *rem )
void
free_user_id( PKT_user_id *uid )
{
+ if( uid->photo )
+ gcry_free( uid->photo );
gcry_free(uid);
}
diff --git a/g10/getkey.c b/g10/getkey.c
index d0b9cc1dd..e9b4a231a 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -1,5 +1,5 @@
/* getkey.c - Get a key from the database
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -24,9 +24,10 @@
#include <string.h>
#include <assert.h>
#include <ctype.h>
-#include <gcrypt.h>
+
#include "util.h"
#include "packet.h"
+#include <gcrypt.h>
#include "iobuf.h"
#include "keydb.h"
#include "options.h"
@@ -45,7 +46,11 @@
* that they are all valid.
* Note: We must use numerical values here in case that this program
* will be converted to those little blue HAL9000s with their strange
- * EBCDIC character set (user ids are UTF-8). */
+ * EBCDIC character set (user ids are UTF-8).
+ * wk 2000-04-13: Hmmm, does this really make sense, given the fact that
+ * we can run gpg now on a S/390 running GNU/Linux, where the code
+ * translation is done by the device drivers?
+ */
static const byte word_match_chars[256] = {
/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -154,6 +159,7 @@ static int uid_cache_entries; /* number of entries in uid cache */
static char* prepare_word_match( const byte *name );
static int lookup_pk( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_kb );
static int lookup_sk( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_kb );
+static u32 subkeys_expiretime( KBNODE node, u32 *mainkid );
#if 0
@@ -696,6 +702,8 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
STRLIST r;
GETKEY_CTX ctx;
+ if( retctx ) /* reset the returned context in case of error */
+ *retctx = NULL;
assert( !pk ^ !sk );
/* build the search context */
@@ -941,7 +949,7 @@ get_seckey_bynames( GETKEY_CTX *retctx, PKT_secret_key *sk,
if( !sk ) {
/* Performance Hint: key_byname should not need a sk here */
- sk = gcry_xcalloc_secure( 1, sizeof *sk );
+ sk = gcry_xcalloc_secure( 1, sizeof *sk );
rc = key_byname( retctx, names, NULL, sk, ret_keyblock );
free_secret_key( sk );
}
@@ -959,7 +967,7 @@ get_seckey_next( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock )
if( !sk ) {
/* Performance Hint: lookup_read should not need a pk in this case */
- sk = gcry_xcalloc_secure( 1, sizeof *sk );
+ sk = gcry_xcalloc_secure( 1, sizeof *sk );
rc = lookup_sk( ctx, sk, ret_keyblock );
free_secret_key( sk );
}
@@ -1150,7 +1158,7 @@ merge_one_pk_and_selfsig( KBNODE keyblock, KBNODE knode,
k = find_kbnode( keyblock, PKT_PUBLIC_KEY );
if( !k )
BUG(); /* keyblock without primary key!!! */
- keyid_from_pk( knode->pkt->pkt.public_key, kid );
+ keyid_from_pk( k->pkt->pkt.public_key, kid );
}
else
keyid_from_pk( pk, kid );
@@ -1208,6 +1216,10 @@ merge_keys_and_selfsig( KBNODE keyblock )
pk = NULL; /* not needed for old keys */
else if( k->pkt->pkttype == PKT_PUBLIC_KEY )
keyid_from_pk( pk, kid );
+ else if( !pk->expiredate ) { /* and subkey */
+ /* insert the expiration date here */
+ pk->expiredate = subkeys_expiretime( k, kid );
+ }
sigdate = 0;
}
else if( k->pkt->pkttype == PKT_SECRET_KEY
@@ -1222,8 +1234,11 @@ merge_keys_and_selfsig( KBNODE keyblock )
else if( (pk || sk ) && k->pkt->pkttype == PKT_SIGNATURE
&& (sig=k->pkt->pkt.signature)->sig_class >= 0x10
&& sig->sig_class <= 0x30 && sig->version > 3
+ && !(sig->sig_class == 0x18 || sig->sig_class == 0x28)
&& sig->keyid[0] == kid[0] && sig->keyid[1] == kid[1] ) {
/* okay this is a self-signature which can be used.
+ * This is not used for subkey binding signature, becuase this
+ * is done above.
* FIXME: We should only use this if the signature is valid
* but this is time consuming - we must provide another
* way to handle this
@@ -1279,9 +1294,16 @@ find_by_name( KBNODE keyblock, PKT_public_key *pk, const char *name,
u32 aki[2];
keyid_from_pk( kk->pkt->pkt.public_key, aki );
cache_user_id( k->pkt->pkt.user_id, aki );
- gcry_md_hash_buffer( GCRY_MD_RMD160, namehash,
- k->pkt->pkt.user_id->name,
- k->pkt->pkt.user_id->len );
+ if( k->pkt->pkt.user_id->photo ) {
+ gcry_md_hash_buffer( GCRY_MD_RMD160, namehash,
+ k->pkt->pkt.user_id->photo,
+ k->pkt->pkt.user_id->photolen );
+ }
+ else {
+ gcry_md_hash_buffer( GCRY_MD_RMD160, namehash,
+ k->pkt->pkt.user_id->name,
+ k->pkt->pkt.user_id->len );
+ }
*use_namehash = 1;
return kk;
}
@@ -1516,6 +1538,56 @@ find_by_fpr_sk( KBNODE keyblock, PKT_secret_key *sk,
}
+/****************
+ * Return the expiretime of a subkey.
+ */
+static u32
+subkeys_expiretime( KBNODE node, u32 *mainkid )
+{
+ KBNODE k;
+ PKT_signature *sig;
+ u32 expires = 0, sigdate = 0;
+
+ assert( node->pkt->pkttype == PKT_PUBLIC_SUBKEY );
+ for(k=node->next; k; k = k->next ) {
+ if( k->pkt->pkttype == PKT_SIGNATURE
+ && (sig=k->pkt->pkt.signature)->sig_class == 0x18
+ && sig->keyid[0] == mainkid[0]
+ && sig->keyid[1] == mainkid[1]
+ && sig->version > 3
+ && sig->timestamp > sigdate ) {
+ /* okay this is a key-binding which can be used.
+ * We use the latest self-signature.
+ * FIXME: We should only use this if the binding signature is valid
+ * but this is time consuming - we must provide another
+ * way to handle this
+ */
+ const byte *p;
+ u32 ed;
+
+ p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL );
+ ed = p? node->pkt->pkt.public_key->timestamp + buffer_to_u32(p):0;
+ sigdate = sig->timestamp;
+ expires = ed;
+ }
+ else if( k->pkt->pkttype == PKT_PUBLIC_SUBKEY )
+ break; /* stop at the next subkey */
+ }
+
+ return expires;
+}
+
+
+/****************
+ * Check whether the subkey has expired. Node must point to the subkey
+ */
+static int
+has_expired( KBNODE node, u32 *mainkid, u32 cur_time )
+{
+ u32 expires = subkeys_expiretime( node, mainkid );
+ return expires && expires <= cur_time;
+}
+
static void
finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash,
int use_namehash, int primary )
@@ -1534,6 +1606,10 @@ finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash,
pk->pubkey_usage ) == GPGERR_WR_PUBKEY_ALGO ) {
/* if the usage is not correct, try to use a subkey */
KBNODE save_k = k;
+ u32 mainkid[2];
+ u32 cur_time = make_timestamp();
+
+ keyid_from_pk( keyblock->pkt->pkt.public_key, mainkid );
k = NULL;
/* kludge for pgp 5: which doesn't accept type 20:
@@ -1545,7 +1621,8 @@ finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash,
== GCRY_PK_ELG_E
&& !openpgp_pk_test_algo(
k->pkt->pkt.public_key->pubkey_algo,
- pk->pubkey_usage ) )
+ pk->pubkey_usage )
+ && !has_expired(k, mainkid, cur_time) )
break;
}
}
@@ -1555,7 +1632,10 @@ finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash,
if( k->pkt->pkttype == PKT_PUBLIC_SUBKEY
&& !openpgp_pk_test_algo(
k->pkt->pkt.public_key->pubkey_algo,
- pk->pubkey_usage ) )
+ pk->pubkey_usage )
+ && ( pk->pubkey_usage != GCRY_PK_USAGE_ENCR
+ || !has_expired( k, mainkid, cur_time ) )
+ )
break;
}
}
@@ -1887,6 +1967,18 @@ get_user_id_string( u32 *keyid )
return p;
}
+
+char*
+get_user_id_string_native( u32 *keyid )
+{
+ char *p = get_user_id_string( keyid );
+ char *p2 = utf8_to_native( p, strlen(p) );
+
+ gcry_free(p);
+ return p2;
+}
+
+
char*
get_long_user_id_string( u32 *keyid )
{
@@ -1914,6 +2006,7 @@ get_user_id( u32 *keyid, size_t *rn )
user_id_db_t r;
char *p;
int pass=0;
+
/* try it two times; second pass reads from key resources */
do {
for(r=user_id_db; r; r = r->next )
@@ -1924,9 +2017,8 @@ get_user_id( u32 *keyid, size_t *rn )
return p;
}
} while( ++pass < 2 && !get_pubkey( NULL, keyid ) );
- p = gcry_xmalloc( 19 );
- memcpy(p, "[User id not found]", 19 );
- *rn = 19;
+ p = gcry_xstrdup( _("[User id not found]") );
+ *rn = strlen(p);
return p;
}
diff --git a/g10/gpg.c b/g10/gpg.c
index 2b66509f4..fb1be046f 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -26,8 +26,8 @@
#include <ctype.h>
#include <unistd.h>
-#include <gcrypt.h>
+#include <gcrypt.h>
#include "packet.h"
#include "iobuf.h"
#include "util.h"
@@ -77,6 +77,7 @@ enum cmd_and_opt_values { aNull = 0,
aImport,
aFastImport,
aVerify,
+ aVerifyFiles,
aListKeys,
aListSigs,
aListSecretKeys,
@@ -85,12 +86,13 @@ enum cmd_and_opt_values { aNull = 0,
aExport,
aExportAll,
aExportSecret,
+ aExportSecretSub,
aCheckKeys,
aGenRevoke,
aPrimegen,
aPrintMD,
- aPrintHMAC,
aPrintMDs,
+ aPrintHMAC,
aCheckTrustDB,
aUpdateTrustDB,
aFixTrustDB,
@@ -130,6 +132,7 @@ enum cmd_and_opt_values { aNull = 0,
oDigestAlgo,
oCompressAlgo,
oPasswdFD,
+ oCommandFD,
oNoVerbose,
oTrustDBName,
oNoSecmemWarn,
@@ -146,7 +149,6 @@ enum cmd_and_opt_values { aNull = 0,
oCompressKeys,
oCompressSigs,
oAlwaysTrust,
- oEmuChecksumBug,
oRunAsShmCP,
oSetFilename,
oSetPolicyURL,
@@ -164,6 +166,7 @@ enum cmd_and_opt_values { aNull = 0,
oEscapeFrom,
oLockOnce,
oLockMultiple,
+ oLockNever,
oKeyServer,
oEncryptTo,
oNoEncryptTo,
@@ -175,7 +178,14 @@ enum cmd_and_opt_values { aNull = 0,
oAllowNonSelfsignedUID,
oNoLiteral,
oSetFilesize,
- oEntropyDLLName,
+ oHonorHttpProxy,
+ oFastListMode,
+ oListOnly,
+ oIgnoreTimeConflict,
+ oNoRandomSeedFile,
+ oNoAutoKeyRetrieve,
+ oEmu3DESS2KBug, /* will be removed in 1.1 */
+ oEmuMDEncodeBug,
aTest };
@@ -191,6 +201,7 @@ static ARGPARSE_OPTS opts[] = {
{ aStore, "store", 256, N_("store only")},
{ aDecrypt, "decrypt", 256, N_("decrypt data (default)")},
{ aVerify, "verify" , 256, N_("verify a signature")},
+ { aVerifyFiles, "verify-files" , 256, "@" },
{ aListKeys, "list-keys", 256, N_("list keys")},
{ aListKeys, "list-public-keys", 256, "@" },
{ aListSigs, "list-sigs", 256, N_("list keys and signatures")},
@@ -210,6 +221,7 @@ static ARGPARSE_OPTS opts[] = {
{ aRecvKeys, "recv-keys" , 256, N_("import keys from a key server") },
{ aExportAll, "export-all" , 256, "@" },
{ aExportSecret, "export-secret-keys" , 256, "@" },
+ { aExportSecretSub, "export-secret-subkeys" , 256, "@" },
{ aImport, "import", 256 , N_("import/merge keys")},
{ aFastImport, "fast-import", 256 , "@"},
{ aListPackets, "list-packets",256,N_("list only the sequence of packets")},
@@ -266,12 +278,12 @@ static ARGPARSE_OPTS opts[] = {
{ oCharset, "charset" , 2, N_("|NAME|set terminal charset to NAME") },
{ oOptions, "options" , 2, N_("read options from file")},
- { oDebug, "debug" ,4|16, N_("set debugging flags")},
- { oDebugAll, "debug-all" ,0, N_("enable full debugging")},
+ { oDebug, "debug" ,4|16, "@"},
+ { oDebugAll, "debug-all" ,0, "@"},
{ oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") },
- { oNoComment, "no-comment", 0, N_("do not write comment packets")},
- { oCompletesNeeded, "completes-needed", 1, N_("(default is 1)")},
- { oMarginalsNeeded, "marginals-needed", 1, N_("(default is 3)")},
+ { oNoComment, "no-comment", 0, "@"},
+ { oCompletesNeeded, "completes-needed", 1, "@"},
+ { oMarginalsNeeded, "marginals-needed", 1, "@"},
{ oMaxCertDepth, "max-cert-depth", 1, "@" },
{ oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")},
{ oRFC1991, "rfc1991", 0, N_("emulate the mode described in RFC1991")},
@@ -287,7 +299,11 @@ static ARGPARSE_OPTS opts[] = {
{ oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")},
{ oNotation, "notation-data", 2, N_("|NAME=VALUE|use this notation data")},
- { 302, NULL, 0, N_("@\nExamples:\n\n"
+ { 302, NULL, 0, N_(
+ "@\n(See the man page for a complete listing of all commands and options)\n"
+ )},
+
+ { 303, NULL, 0, N_("@\nExamples:\n\n"
" -se -r Bob [file] sign and encrypt for user Bob\n"
" --clearsign [file] make a clear text signature\n"
" --detach-sign [file] make a detached signature\n"
@@ -301,6 +317,7 @@ static ARGPARSE_OPTS opts[] = {
{ aListTrustPath, "list-trust-path",0, "@"},
{ oKOption, NULL, 0, "@"},
{ oPasswdFD, "passphrase-fd",1, "@" },
+ { oCommandFD, "command-fd",1, "@" },
{ oNoVerbose, "no-verbose", 0, "@"},
{ oTrustDBName, "trustdb-name", 2, "@" },
{ oNoSecmemWarn, "no-secmem-warning", 0, "@" }, /* used only by regression tests */
@@ -331,6 +348,7 @@ static ARGPARSE_OPTS opts[] = {
{ oEscapeFrom, "escape-from-lines", 0, "@" },
{ oLockOnce, "lock-once", 0, "@" },
{ oLockMultiple, "lock-multiple", 0, "@" },
+ { oLockNever, "lock-never", 0, "@" },
{ oLoggerFD, "logger-fd",1, "@" },
{ oUseEmbeddedFilename, "use-embedded-filename", 0, "@" },
{ oUtf8Strings, "utf8-strings", 0, "@" },
@@ -341,7 +359,14 @@ static ARGPARSE_OPTS opts[] = {
{ oAllowNonSelfsignedUID, "allow-non-selfsigned-uid", 0, "@" },
{ oNoLiteral, "no-literal", 0, "@" },
{ oSetFilesize, "set-filesize", 20, "@" },
- { oEntropyDLLName, "entropy-dll-name", 2, "@" },
+ { oHonorHttpProxy,"honor-http-proxy", 0, "@" },
+ { oFastListMode,"fast-list-mode", 0, "@" },
+ { oListOnly, "list-only", 0, "@"},
+ { oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" },
+ { oNoRandomSeedFile, "no-random-seed-file", 0, "@" },
+ { oNoAutoKeyRetrieve, "no-auto-key-retrieve", 0, "@" },
+ { oEmu3DESS2KBug, "emulate-3des-s2k-bug", 0, "@"},
+ { oEmuMDEncodeBug, "emulate-md-encode-bug", 0, "@"},
{0} };
@@ -351,8 +376,8 @@ int gpg_errors_seen = 0;
static int utf8_strings = 0;
static int maybe_setuid = 1;
-static char *build_list( const char *text, const char * (*mapf)(int),
- int (*chkf)(int) );
+static char *build_list( const char *text,
+ const char *(*mapf)(int), int (*chkf)(int) );
static void set_cmd( enum cmd_and_opt_values *ret_cmd,
enum cmd_and_opt_values new_cmd );
static void print_hex( byte *p, size_t n );
@@ -360,13 +385,13 @@ static void print_mds( const char *fname, int algo, const char *key );
static void add_notation_data( const char *string );
static int check_policy_url( const char *s );
+
static int
our_pk_test_algo( int algo )
{
return openpgp_pk_test_algo( algo, 0 );
}
-
static const char *
my_strusage( int level )
{
@@ -390,26 +415,29 @@ my_strusage( int level )
"default operation depends on the input data\n");
break;
- case 31: p = _("\nSupported algorithms:\n"); break;
- case 32:
+ case 31: p = "\nHome: "; break;
+ case 32: p = opt.homedir; break;
+ case 33: p = _("\nSupported algorithms:\n"); break;
+ case 34:
if( !ciphers )
ciphers = build_list("Cipher: ", gcry_cipher_algo_name,
openpgp_cipher_test_algo );
p = ciphers;
break;
- case 33:
+ case 35:
if( !pubkeys )
pubkeys = build_list("Pubkey: ", gcry_pk_algo_name,
our_pk_test_algo );
p = pubkeys;
break;
- case 34:
+ case 36:
if( !digests )
digests = build_list("Hash: ", gcry_md_algo_name,
openpgp_md_test_algo );
p = digests;
break;
+
default: p = NULL;
}
return p;
@@ -465,27 +493,6 @@ i18n_init(void)
#endif
}
-static void
-wrong_args( const char *text)
-{
- fputs(_("usage: gpg [options] "),stderr);
- fputs(text,stderr);
- putc('\n',stderr);
- gpg_exit(2);
-}
-
-
-static char *
-make_username( const char *string )
-{
- char *p;
- if( utf8_strings )
- p = native_to_utf8( string );
- else
- p = gcry_xstrdup(string);
- return p;
-}
-
static void
register_extension( const char *mainpgm, const char *fname )
@@ -510,15 +517,37 @@ register_extension( const char *mainpgm, const char *fname )
static void
+wrong_args( const char *text)
+{
+ fputs(_("usage: gpg [options] "),stderr);
+ fputs(text,stderr);
+ putc('\n',stderr);
+ gpg_exit(2);
+}
+
+
+static char *
+make_username( const char *string )
+{
+ char *p;
+ if( utf8_strings )
+ p = gcry_xstrdup(string);
+ else
+ p = native_to_utf8( string );
+ return p;
+}
+
+
+static void
set_debug(void)
{
- #if 0
- #warning memory debuggig not enabled
+ #if 0
+ #warning memory debugging not enabled
if( opt.debug & DBG_MEMORY_VALUE )
memory_debug_mode = 1;
if( opt.debug & DBG_MEMSTAT_VALUE )
memory_stat_debug_mode = 1;
- #endif
+ #endif
if( opt.debug & DBG_MPI_VALUE )
gcry_control( GCRYCTL_SET_DEBUG_FLAGS, 2 );
@@ -579,6 +608,7 @@ main( int argc, char **argv )
int default_keyring = 1;
int greeting = 0;
int nogreeting = 0;
+ int use_random_seed = 1;
enum cmd_and_opt_values cmd = 0;
const char *trustdb_name = NULL;
char *def_cipher_string = NULL;
@@ -611,6 +641,7 @@ main( int argc, char **argv )
init_signals();
create_dotlock(NULL); /* register locking cleanup */
i18n_init();
+ opt.command_fd = -1; /* no command fd */
opt.compress = -1; /* defaults to standard compress level */
/* note: if you change these lines, look at oOpenPGP */
opt.def_cipher_algo = 0;
@@ -622,7 +653,13 @@ main( int argc, char **argv )
opt.completes_needed = 1;
opt.marginals_needed = 3;
opt.max_cert_depth = 5;
+ opt.pgp2_workarounds = 1;
+ opt.auto_key_retrieve = 1;
+ #ifdef __MINGW32__
+ opt.homedir = read_w32_registry_string( NULL, "Software\\GNU\\GnuPG", "HomeDir" );
+ #else
opt.homedir = getenv("GNUPGHOME");
+ #endif
if( !opt.homedir || !*opt.homedir ) {
#ifdef HAVE_DRIVE_LETTERS
opt.homedir = "c:/gnupg-test";
@@ -679,7 +716,6 @@ main( int argc, char **argv )
if( default_config )
configname = make_filename(opt.homedir, "options", NULL );
-
argc = orig_argc;
argv = orig_argv;
pargs.argc = &argc;
@@ -721,13 +757,16 @@ main( int argc, char **argv )
case aListKeys: set_cmd( &cmd, aListKeys); break;
case aListSigs: set_cmd( &cmd, aListSigs); break;
case aExportSecret: set_cmd( &cmd, aExportSecret); break;
+ case aExportSecretSub: set_cmd( &cmd, aExportSecretSub); break;
case aDeleteSecretKey: set_cmd( &cmd, aDeleteSecretKey);
greeting=1; break;
case aDeleteKey: set_cmd( &cmd, aDeleteKey); greeting=1; break;
case aDetachedSign: detached_sig = 1; set_cmd( &cmd, aSign ); break;
case aSym: set_cmd( &cmd, aSym); break;
+
case aDecrypt: set_cmd( &cmd, aDecrypt); break;
+
case aEncr: set_cmd( &cmd, aEncr); break;
case aSign: set_cmd( &cmd, aSign ); break;
case aKeygen: set_cmd( &cmd, aKeygen); greeting=1; break;
@@ -738,11 +777,12 @@ main( int argc, char **argv )
case aClearsign: set_cmd( &cmd, aClearsign); break;
case aGenRevoke: set_cmd( &cmd, aGenRevoke); break;
case aVerify: set_cmd( &cmd, aVerify); break;
+ case aVerifyFiles: set_cmd( &cmd, aVerifyFiles); break;
case aPrimegen: set_cmd( &cmd, aPrimegen); break;
case aGenRandom: set_cmd( &cmd, aGenRandom); break;
case aPrintMD: set_cmd( &cmd, aPrintMD); break;
- case aPrintHMAC: set_cmd( &cmd, aPrintHMAC); break;
case aPrintMDs: set_cmd( &cmd, aPrintMDs); break;
+ case aPrintHMAC: set_cmd( &cmd, aPrintHMAC); break;
case aListTrustDB: set_cmd( &cmd, aListTrustDB); break;
case aCheckTrustDB: set_cmd( &cmd, aCheckTrustDB); break;
case aUpdateTrustDB: set_cmd( &cmd, aUpdateTrustDB); break;
@@ -828,11 +868,14 @@ main( int argc, char **argv )
break;
case oRFC1991:
opt.rfc1991 = 1;
+ opt.rfc2440 = 0;
opt.no_comment = 1;
opt.escape_from = 1;
break;
case oOpenPGP:
opt.rfc1991 = 0;
+ opt.rfc2440 = 1;
+ opt.pgp2_workarounds = 0;
opt.escape_from = 0;
opt.force_v3_sigs = 0;
opt.compress_keys = 0; /* not mandated but we do it */
@@ -840,11 +883,13 @@ main( int argc, char **argv )
opt.not_dash_escaped = 0;
opt.def_cipher_algo = 0;
opt.def_digest_algo = 0;
- opt.def_compress_algo = 2;
+ opt.def_compress_algo = 1;
opt.s2k_mode = 3; /* iterated+salted */
- opt.s2k_digest_algo = GCRY_MD_RMD160;
- opt.s2k_cipher_algo = GCRY_CIPHER_BLOWFISH;
+ opt.s2k_digest_algo = GCRY_MD_SHA1;
+ opt.s2k_cipher_algo = GCRY_CIPHER_CAST5;
break;
+ case oEmu3DESS2KBug: opt.emulate_bugs |= EMUBUG_3DESS2K; break;
+ case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break;
case oCompressSigs: opt.compress_sigs = 1; break;
case oRunAsShmCP:
#ifndef USE_SHM_COPROCESSING
@@ -880,6 +925,7 @@ main( int argc, char **argv )
break;
case oCompress: opt.compress = pargs.r.ret_int; break;
case oPasswdFD: pwfd = pargs.r.ret_int; break;
+ case oCommandFD: opt.command_fd = pargs.r.ret_int; break;
case oCipherAlgo: def_cipher_string = gcry_xstrdup(pargs.r.ret_str); break;
case oDigestAlgo: def_digest_string = gcry_xstrdup(pargs.r.ret_str); break;
case oNoSecmemWarn: gcry_control( GCRYCTL_DISABLE_SECMEM_WARN ); break;
@@ -891,6 +937,10 @@ main( int argc, char **argv )
case oNotDashEscaped: opt.not_dash_escaped = 1; break;
case oEscapeFrom: opt.escape_from = 1; break;
case oLockOnce: opt.lock_once = 1; break;
+ #if 0
+ #warning no disable_dotlock() yet
+ case oLockNever: disable_dotlock(); break;
+ #endif
case oLockMultiple: opt.lock_once = 0; break;
case oKeyServer: opt.keyserver_name = pargs.r.ret_str; break;
case oNotation: add_notation_data( pargs.r.ret_str ); break;
@@ -908,22 +958,15 @@ main( int argc, char **argv )
&algo, sizeof algo );
}
break;
- case oAllowNonSelfsignedUID:
- opt.allow_non_selfsigned_uid = 1;
- break;
- case oNoLiteral:
- opt.no_literal = 1;
- break;
- case oSetFilesize:
- opt.set_filesize = pargs.r.ret_ulong;
- break;
-
- case oEntropyDLLName:
- #ifdef USE_STATIC_RNDW32
- log_info("set dllname to `%s'\n", pargs.r.ret_str );
- rndw32_set_dll_name( pargs.r.ret_str );
- #endif
- break;
+ case oAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid = 1; break;
+ case oNoLiteral: opt.no_literal = 1; break;
+ case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break;
+ case oHonorHttpProxy: opt.honor_http_proxy = 1; break;
+ case oFastListMode: opt.fast_list_mode = 1; break;
+ case oListOnly: opt.list_only=1; break;
+ case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
+ case oNoRandomSeedFile: use_random_seed = 0; break;
+ case oNoAutoKeyRetrieve: opt.auto_key_retrieve = 0; break;
default : pargs.err = configfp? 1:2; break;
}
@@ -946,14 +989,12 @@ main( int argc, char **argv )
fprintf(stderr, "%s\n", strusage(15) );
}
#ifdef IS_DEVELOPMENT_VERSION
- if( !opt.batch )
- log_info("NOTE: this is a development version!\n");
- #endif
- if( opt.force_mdc ) {
- log_info("--force-mdc ignored because"
- " the OpenPGP WG has not yet aggreed on MDCs\n");
- opt.force_mdc = 0;
+ if( !opt.batch ) {
+ log_info("NOTE: THIS IS A DEVELOPMENT VERSION!\n");
+ log_info("It is only intended for test purposes and should NOT be\n");
+ log_info("used in a production environment or with production keys!\n");
}
+ #endif
if (opt.no_literal) {
log_info(_("NOTE: %s is not for normal use!\n"), "--no-literal");
if (opt.textmode)
@@ -975,7 +1016,7 @@ main( int argc, char **argv )
* gpg_opt_homedir = opt.homedir; */
/* must do this after dropping setuid, because string_to...
- * may try to load a module */
+ * may try to load an module */
if( def_cipher_string ) {
opt.def_cipher_algo = gcry_cipher_map_name(def_cipher_string);
gcry_free(def_cipher_string); def_cipher_string = NULL;
@@ -1025,8 +1066,19 @@ main( int argc, char **argv )
if( log_get_errorcount(0) )
gpg_exit(2);
- if( !cmd && opt.fingerprint && !with_fpr )
+ /* set the random seed file */
+ if( use_random_seed ) {
+ char *p = make_filename(opt.homedir, "random_seed", NULL );
+ #if 0
+ #warning set_random_seed_file missing
+ set_random_seed_file(p);
+ #endif
+ gcry_free(p);
+ }
+
+ if( !cmd && opt.fingerprint && !with_fpr ) {
set_cmd( &cmd, aListKeys);
+ }
if( cmd == aKMode || cmd == aKModeC ) { /* kludge to be compatible to pgp */
if( cmd == aKModeC ) {
@@ -1077,8 +1129,8 @@ main( int argc, char **argv )
switch( cmd ) {
case aPrimegen:
case aPrintMD:
- case aPrintHMAC:
case aPrintMDs:
+ case aPrintHMAC:
case aGenRandom:
case aDeArmor:
case aEnArmor:
@@ -1167,6 +1219,11 @@ main( int argc, char **argv )
log_error("verify signatures failed: %s\n", gpg_errstr(rc) );
break;
+ case aVerifyFiles:
+ if( (rc = verify_files( argc, argv ) ))
+ log_error("verify files failed: %s\n", gpg_errstr(rc) );
+ break;
+
case aDecrypt:
if( argc > 1 )
wrong_args(_("--decrypt [filename]"));
@@ -1225,16 +1282,28 @@ main( int argc, char **argv )
case aListSigs:
opt.list_sigs = 1;
case aListKeys:
- /* fixme: we chnaged this in 1.0 */
- public_key_list( argc, argv );
+ sl = NULL;
+ for( ; argc; argc--, argv++ )
+ add_to_strlist2( &sl, *argv, utf8_strings );
+ public_key_list( sl );
+ free_strlist(sl);
break;
case aListSecretKeys:
- secret_key_list( argc, argv );
+ sl = NULL;
+ for( ; argc; argc--, argv++ )
+ add_to_strlist2( &sl, *argv, utf8_strings );
+ secret_key_list( sl );
+ free_strlist(sl);
break;
case aKMode: /* list keyring -- NOTE: This will be removed soon */
- if( argc < 2 ) /* -kv [userid] */
- public_key_list( (argc && **argv)? 1:0, argv );
+ if( argc < 2 ) { /* -kv [userid] */
+ sl = NULL;
+ if (argc && **argv)
+ add_to_strlist2( &sl, *argv, utf8_strings );
+ public_key_list( sl );
+ free_strlist(sl);
+ }
else if( argc == 2 ) { /* -kv userid keyring */
if( access( argv[1], R_OK ) ) {
log_error(_("can't open %s: %s\n"),
@@ -1244,32 +1313,33 @@ main( int argc, char **argv )
/* add keyring (default keyrings are not registered in this
* special case */
add_keyblock_resource( argv[1], 0, 0 );
- public_key_list( **argv?1:0, argv );
+ sl = NULL;
+ if (**argv)
+ add_to_strlist2( &sl, *argv, utf8_strings );
+ public_key_list( sl );
+ free_strlist(sl);
}
}
else
wrong_args(_("-k[v][v][v][c] [user-id] [keyring]") );
break;
- case aKeygen: /* generate a key (interactive) */
- if( argc )
- wrong_args("--gen-key");
- generate_keypair();
+ case aKeygen: /* generate a key */
+ if( opt.batch ) {
+ if( argc > 1 )
+ wrong_args("--gen-key [parameterfile]");
+ generate_keypair( argc? *argv : NULL );
+ }
+ else {
+ if( argc )
+ wrong_args("--gen-key");
+ generate_keypair(NULL);
+ }
break;
case aFastImport:
case aImport:
- if( !argc ) {
- rc = import_keys( NULL, (cmd == aFastImport) );
- if( rc )
- log_error("import failed: %s\n", gpg_errstr(rc) );
- }
- for( ; argc; argc--, argv++ ) {
- rc = import_keys( *argv, (cmd == aFastImport) );
- if( rc )
- log_error("import from `%s' failed: %s\n",
- *argv, gpg_errstr(rc) );
- }
+ import_keys( argc? argv:NULL, argc, (cmd == aFastImport) );
break;
case aExport:
@@ -1296,6 +1366,14 @@ main( int argc, char **argv )
free_strlist(sl);
break;
+ case aExportSecretSub:
+ sl = NULL;
+ for( ; argc; argc--, argv++ )
+ add_to_strlist2( &sl, *argv, utf8_strings );
+ export_secsubkeys( sl );
+ free_strlist(sl);
+ break;
+
case aGenRevoke:
if( argc != 1 )
wrong_args("--gen-revoke user-id");
@@ -1342,7 +1420,7 @@ main( int argc, char **argv )
mpi_print( stdout, factors[0], 1 ); /* print q */
}
else if( mode == 4 && argc == 3 ) {
- MPI g = mpi_new(8);
+ MPI g = mpi_alloc(1);
mpi_print( stdout, generate_elg_prime(
0, atoi(argv[1]),
atoi(argv[2]), g, NULL ), 1);
@@ -1424,6 +1502,7 @@ main( int argc, char **argv )
}
break;
+
case aPrintMDs: /* old option */
if( !argc )
print_mds(NULL,0,NULL);
@@ -1461,11 +1540,9 @@ main( int argc, char **argv )
break;
case aFixTrustDB:
- log_error("this command is not yet implemented.\"\n");
+ log_error("this command is not yet implemented.\n");
log_error("A workaround is to use \"--export-ownertrust\", remove\n");
log_error("the trustdb file and do an \"--import-ownertrust\".\n" );
- #warning removed the next line
- export_as_kbxfile();
break;
case aListTrustPath:
@@ -1533,6 +1610,10 @@ main( int argc, char **argv )
void
gpg_exit( int rc )
{
+ #if 0
+ #warning no update_random_seed_file
+ update_random_seed_file();
+ #endif
if( opt.debug & DBG_MEMSTAT_VALUE ) {
gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
@@ -1629,7 +1710,7 @@ print_mds( const char *fname, int algo, const char *key )
if( algo ) {
if( fname )
fputs( pname, stdout );
- print_hex( gcry_md_read(md, algo), gcry_md_get_algo_dlen(algo) );
+ print_hex(gcry_md_read(md, algo), gcry_md_get_algo_dlen(algo) );
}
else {
printf( "%s MD5 = ", fname?pname:"" );
diff --git a/g10/gpgd.c b/g10/gpgd.c
index 99c91f6fc..8ca37d34a 100644
--- a/g10/gpgd.c
+++ b/g10/gpgd.c
@@ -1,4 +1,4 @@
-/* gpg.c - The GnuPG daemon (keyserver)
+/* ggpd.c - The GnuPG daemon (keyserver)
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
@@ -38,6 +38,7 @@
#include <sys/stat.h>
#include "util.h"
+#include "cipher.h"
#include "options.h"
#include "main.h"
@@ -84,7 +85,7 @@ strusage( int level )
case 33:
if( !pubkeys )
pubkeys = build_list("Supported pubkeys: ", pubkey_algo_to_string,
- openpgp_pk_test_algo );
+ check_pubkey_algo );
p = pubkeys;
break;
case 34:
@@ -137,7 +138,7 @@ set_debug(void)
if( opt.debug & DBG_MPI_VALUE )
mpi_debug_mode = 1;
if( opt.debug & DBG_CIPHER_VALUE )
- gpgc_debug_mode = 1;
+ g10c_debug_mode = 1;
if( opt.debug & DBG_IOBUF_VALUE )
iobuf_debug_mode = 1;
}
diff --git a/g10/helptext.c b/g10/helptext.c
index e42902512..4a7a14fde 100644
--- a/g10/helptext.c
+++ b/g10/helptext.c
@@ -1,5 +1,5 @@
/* helptext.c - English help texts
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -224,6 +224,29 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = {
"file (which is shown in brackets) will be used."
)},
+/* revoke.c (ask_revocation_reason) */
+{ "ask_revocation_reason.code", N_(
+ "You should specify a reason for the certification. Depending on the\n"
+ "context you have the ability to choose from this list:\n"
+ " \"Key has been compromised\"\n"
+ " Use this if you have a reason to believe that unauthorized persons\n"
+ " got access to your secret key.\n"
+ " \"Key is superseeded\"\n"
+ " Use this if you have replaced this key with a newer one.\n"
+ " \"Key is no longer used\"\n"
+ " Use this if you have retired this key.\n"
+ " \"User ID is no longer valid\"\n"
+ " Use this to state that the user ID should not longer be used;\n"
+ " this is normally used to mark an email address invalid.\n"
+)},
+
+/* revoke.c (ask_revocation_reason) */
+{ "ask_revocation_reason.text", N_(
+ "If you like, you can enter a text describing why you issue this\n"
+ "revocation certificate. Please keep this text concise.\n"
+ "An empty line ends the text.\n"
+)},
+
/* end of list */
{ NULL, NULL } };
diff --git a/g10/hkp.c b/g10/hkp.c
index b60b3cc6f..2f6031361 100644
--- a/g10/hkp.c
+++ b/g10/hkp.c
@@ -30,7 +30,6 @@
#include "util.h"
#include "ttyio.h"
#include "i18n.h"
-#include <gcrypt.h>
#include "options.h"
#include "filter.h"
#include "http.h"
@@ -56,19 +55,24 @@ hkp_ask_import( u32 *keyid )
struct http_context hd;
char *request;
int rc;
+ unsigned int hflags = opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY : 0;
if( !opt.keyserver_name )
return -1;
- log_info("requesting key %08lX from %s ...\n", (ulong)keyid[1],
+ log_info(_("requesting key %08lX from %s ...\n"), (ulong)keyid[1],
opt.keyserver_name );
request = gcry_xmalloc( strlen( opt.keyserver_name ) + 100 );
/* hkp does not accept the long keyid - we should really write a
- * nicer one */
+ * nicer one :-)
+ * FIXME: request binary mode - need to pass no_armor mode
+ * down to the import function. Marc told that there is such a
+ * binary mode ... how?
+ */
sprintf( request, "x-hkp://%s:11371/pks/lookup?op=get&search=0x%08lX",
opt.keyserver_name, (ulong)keyid[1] );
- rc = http_open_document( &hd, request, 0 );
+ rc = http_open_document( &hd, request, hflags );
if( rc ) {
- log_info("can't get key from keyserver: %s\n",
+ log_info(_("can't get key from keyserver: %s\n"),
rc == GPGERR_NETWORK? strerror(errno)
: gpg_errstr(rc) );
}
@@ -91,7 +95,7 @@ hkp_import( STRLIST users )
return -1;
#else
if( !opt.keyserver_name ) {
- log_error("no keyserver known (use option --keyserver)\n");
+ log_error(_("no keyserver known (use option --keyserver)\n"));
return -1;
}
@@ -99,10 +103,15 @@ hkp_import( STRLIST users )
u32 kid[2];
int type = classify_user_id( users->d, kid, NULL, NULL, NULL );
if( type != 10 && type != 11 ) {
- log_info("%s: not a valid key ID\n", users->d );
+ log_info(_("%s: not a valid key ID\n"), users->d );
continue;
}
- hkp_ask_import( kid );
+ /* because the function may use log_info in some situations, the
+ * errorcounter ist not increaed and the program will return
+ * with success - which is not good when this function is used.
+ */
+ if( hkp_ask_import( kid ) )
+ log_inc_errorcount();
}
return 0;
#endif
@@ -121,9 +130,10 @@ hkp_export( STRLIST users )
struct http_context hd;
char *request;
unsigned int status;
+ unsigned int hflags = opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY : 0;
if( !opt.keyserver_name ) {
- log_error("no keyserver known (use option --keyserver)\n");
+ log_error(_("no keyserver known (use option --keyserver)\n"));
return -1;
}
@@ -143,9 +153,9 @@ hkp_export( STRLIST users )
request = gcry_xmalloc( strlen( opt.keyserver_name ) + 100 );
sprintf( request, "x-hkp://%s:11371/pks/add", opt.keyserver_name );
- rc = http_open( &hd, HTTP_REQ_POST, request , 0 );
+ rc = http_open( &hd, HTTP_REQ_POST, request , hflags );
if( rc ) {
- log_error("can't connect to `%s': %s\n",
+ log_error(_("can't connect to `%s': %s\n"),
opt.keyserver_name,
rc == GPGERR_NETWORK? strerror(errno)
: gpg_errstr(rc) );
@@ -169,7 +179,7 @@ hkp_export( STRLIST users )
rc = http_wait_response( &hd, &status );
if( rc ) {
- log_error("error sending to `%s': %s\n",
+ log_error(_("error sending to `%s': %s\n"),
opt.keyserver_name, gpg_errstr(rc) );
}
else {
@@ -181,10 +191,10 @@ hkp_export( STRLIST users )
}
#endif
if( (status/100) == 2 )
- log_info("success sending to `%s' (status=%u)\n",
+ log_info(_("success sending to `%s' (status=%u)\n"),
opt.keyserver_name, status );
else
- log_error("failed sending to `%s': status=%u\n",
+ log_error(_("failed sending to `%s': status=%u\n"),
opt.keyserver_name, status );
}
http_close( &hd );
diff --git a/g10/hkp.h b/g10/hkp.h
index a7b78da96..64f049739 100644
--- a/g10/hkp.h
+++ b/g10/hkp.h
@@ -1,5 +1,5 @@
/* hkp.h - Horrowitz Keyserver Protocol
- * Copyright (C) 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
diff --git a/g10/import.c b/g10/import.c
index 731351275..578082577 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -1,5 +1,5 @@
/* import.c
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -38,6 +38,7 @@
static struct {
+ ulong count;
ulong no_user_id;
ulong imported;
ulong imported_rsa;
@@ -53,6 +54,7 @@ static struct {
static int import( IOBUF inp, int fast, const char* fname );
+static void print_stats(void);
static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root );
static int import_one( const char *fname, KBNODE keyblock, int fast );
static int import_secret_one( const char *fname, KBNODE keyblock );
@@ -105,30 +107,51 @@ static int merge_keysigs( KBNODE dst, KBNODE src, int *n_sigs,
* Key revocation certificates have special handling.
*
*/
-int
-import_keys( const char *fname, int fast )
+void
+import_keys( char **fnames, int nnames, int fast )
{
- IOBUF inp = NULL;
- int rc;
+ int i;
- inp = iobuf_open(fname);
- if( !fname )
- fname = "[stdin]";
- if( !inp ) {
- log_error(_("can't open `%s': %s\n"), fname, strerror(errno) );
- return GPGERR_OPEN_FILE;
- }
+ /* fixme: don't use static variables */
+ memset( &stats, 0, sizeof( stats ) );
- rc = import( inp, fast, fname );
+ if( !fnames && !nnames )
+ nnames = 1; /* Ohh what a ugly hack to jump into the loop */
- iobuf_close(inp);
- return rc;
+ for(i=0; i < nnames; i++ ) {
+ const char *fname = fnames? fnames[i] : NULL;
+ IOBUF inp = iobuf_open(fname);
+ if( !fname )
+ fname = "[stdin]";
+ if( !inp )
+ log_error(_("can't open `%s': %s\n"), fname, strerror(errno) );
+ else {
+ int rc = import( inp, fast, fname );
+ iobuf_close(inp);
+ if( rc )
+ log_error("import from `%s' failed: %s\n", fname,
+ gpg_errstr(rc) );
+ }
+ if( !fname )
+ break;
+ }
+ print_stats();
+ if( !fast )
+ sync_trustdb();
}
int
import_keys_stream( IOBUF inp, int fast )
{
- return import( inp, fast, "[stream]" );
+ int rc = 0;
+
+ /* fixme: don't use static variables */
+ memset( &stats, 0, sizeof( stats ) );
+ rc = import( inp, fast, "[stream]" );
+ print_stats();
+ if( !fast )
+ sync_trustdb();
+ return rc;
}
static int
@@ -137,10 +160,6 @@ import( IOBUF inp, int fast, const char* fname )
PACKET *pending_pkt = NULL;
KBNODE keyblock;
int rc = 0;
- ulong count=0;
-
- /* fixme: don't use static variables */
- memset( &stats, 0, sizeof( stats ) );
getkey_disable_caches();
@@ -165,16 +184,23 @@ import( IOBUF inp, int fast, const char* fname )
release_kbnode(keyblock);
if( rc )
break;
- if( !(++count % 100) && !opt.quiet )
- log_info(_("%lu keys so far processed\n"), count );
+ if( !(++stats.count % 100) && !opt.quiet )
+ log_info(_("%lu keys so far processed\n"), stats.count );
}
if( rc == -1 )
rc = 0;
else if( rc && rc != GPGERR_INV_KEYRING )
log_error( _("error reading `%s': %s\n"), fname, gpg_errstr(rc));
+ return rc;
+}
+
+
+static void
+print_stats()
+{
if( !opt.quiet ) {
- log_info(_("Total number processed: %lu\n"), count );
+ log_info(_("Total number processed: %lu\n"), stats.count );
if( stats.no_user_id )
log_info(_(" w/o user IDs: %lu\n"), stats.no_user_id );
if( stats.imported || stats.imported_rsa ) {
@@ -202,9 +228,9 @@ import( IOBUF inp, int fast, const char* fname )
}
if( is_status_enabled() ) {
- char buf[12*16];
+ char buf[12*20];
sprintf(buf, "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
- count,
+ stats.count,
stats.no_user_id,
stats.imported,
stats.imported_rsa,
@@ -218,8 +244,6 @@ import( IOBUF inp, int fast, const char* fname )
stats.secret_dups);
write_status_text( STATUS_IMPORT_RES, buf );
}
-
- return rc;
}
@@ -354,8 +378,8 @@ import_one( const char *fname, KBNODE keyblock, int fast )
pubkey_letter( pk->pubkey_algo ),
(ulong)keyid[1], datestr_from_pk(pk) );
if( uidnode )
- print_string( stderr, uidnode->pkt->pkt.user_id->name,
- uidnode->pkt->pkt.user_id->len, 0 );
+ print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name,
+ uidnode->pkt->pkt.user_id->len );
putc('\n', stderr);
}
if( !uidnode ) {
@@ -545,8 +569,8 @@ import_secret_one( const char *fname, KBNODE keyblock )
pubkey_letter( sk->pubkey_algo ),
(ulong)keyid[1], datestr_from_sk(sk) );
if( uidnode )
- print_string( stderr, uidnode->pkt->pkt.user_id->name,
- uidnode->pkt->pkt.user_id->len, 0 );
+ print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name,
+ uidnode->pkt->pkt.user_id->len );
putc('\n', stderr);
}
stats.secret_read++;
@@ -678,6 +702,15 @@ import_revoke_cert( const char *fname, KBNODE node )
log_info( _("key %08lX: revocation certificate imported\n"),
(ulong)keyid[1]);
stats.n_revoc++;
+ if( clear_trust_checked_flag( pk ) ) {
+ /* seems that we have to insert the record first */
+ rc = insert_trust_record( keyblock );
+ if( rc )
+ log_error("key %08lX: trustdb insert failed: %s\n",
+ (ulong)keyid[1], gpg_errstr(rc) );
+ else
+ rc = clear_trust_checked_flag( pk );
+ }
leave:
release_kbnode( keyblock );
@@ -764,7 +797,8 @@ mark_non_selfsigned_uids_valid( KBNODE keyblock, u32 *kid )
KBNODE node;
for(node=keyblock->next; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID && !(node->flag & 1) ) {
- if( node->next && node->next->pkt->pkttype == PKT_SIGNATURE ) {
+ if( (node->next && node->next->pkt->pkttype == PKT_SIGNATURE)
+ || !node->next ) {
node->flag |= 1;
log_info( _("key %08lX: accepted non self-signed user ID '"),
(ulong)kid[1]);
@@ -797,8 +831,8 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
if( opt.verbose ) {
log_info( _("key %08lX: skipped user ID '"),
(ulong)keyid[1]);
- print_string( stderr, node->pkt->pkt.user_id->name,
- node->pkt->pkt.user_id->len, 0 );
+ print_utf8_string( stderr, node->pkt->pkt.user_id->name,
+ node->pkt->pkt.user_id->len );
fputs("'\n", stderr );
}
delete_kbnode( node ); /* the user-id */
@@ -831,7 +865,7 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
}
}
else if( node->pkt->pkttype == PKT_SIGNATURE
- && openpgp_pk_test_algo( node->pkt->pkt.signature->pubkey_algo, 0)
+ && openpgp_pk_test_algo( node->pkt->pkt.signature->pubkey_algo, 0 )
&& node->pkt->pkt.signature->pubkey_algo != GCRY_PK_RSA )
delete_kbnode( node ); /* build_packet() can't handle this */
else if( node->pkt->pkttype == PKT_SIGNATURE
diff --git a/g10/kbnode.c b/g10/kbnode.c
index 79c1386aa..2c1e2ad3c 100644
--- a/g10/kbnode.c
+++ b/g10/kbnode.c
@@ -1,5 +1,5 @@
/* kbnode.c - keyblock node utility functions
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -23,8 +23,9 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
-#include "util.h"
+
#include <gcrypt.h>
+#include "util.h"
#include "packet.h"
#include "keydb.h"
@@ -165,7 +166,7 @@ find_prev_kbnode( KBNODE root, KBNODE node, int pkttype )
KBNODE n1;
for(n1=NULL ; root && root != node; root = root->next )
- if( !pkttype || root->pkt->pkttype == pkttype )
+ if( !pkttype || root->pkt->pkttype == pkttype )
n1 = root;
return n1;
}
diff --git a/g10/kbxblob.c b/g10/kbxblob.c
index c298d587f..01d0dfe10 100644
--- a/g10/kbxblob.c
+++ b/g10/kbxblob.c
@@ -511,7 +511,7 @@ kbx_create_blob ( KBXBLOB *r_blob, KBNODE keyblock )
KBXBLOB blob;
*r_blob = NULL;
- blob = gcry_calloc (1, sizeof *blob );
+ blob = gcry_xcalloc (1, sizeof *blob );
if( !blob )
return GCRYERR_NO_MEM;
@@ -529,9 +529,9 @@ kbx_create_blob ( KBXBLOB *r_blob, KBNODE keyblock )
default: break;
}
}
- blob->keys = gcry_calloc ( blob->nkeys, sizeof ( *blob->keys ) );
- blob->uids = gcry_calloc ( blob->nuids, sizeof ( *blob->uids ) );
- blob->sigs = gcry_calloc ( blob->nsigs, sizeof ( *blob->sigs ) );
+ blob->keys = gcry_xcalloc ( blob->nkeys, sizeof ( *blob->keys ) );
+ blob->uids = gcry_xcalloc ( blob->nuids, sizeof ( *blob->uids ) );
+ blob->sigs = gcry_xcalloc ( blob->nsigs, sizeof ( *blob->sigs ) );
if ( !blob->keys || !blob->uids || !blob->sigs ) {
rc = GCRYERR_NO_MEM;
goto leave;
@@ -581,7 +581,7 @@ kbx_new_blob ( KBXBLOB *r_blob, char *image, size_t imagelen )
KBXBLOB blob;
*r_blob = NULL;
- blob = gcry_calloc (1, sizeof *blob );
+ blob = gcry_xcalloc (1, sizeof *blob );
if( !blob )
return GCRYERR_NO_MEM;
blob->blob = image;
diff --git a/g10/kbxfile.c b/g10/kbxfile.c
index 7bf615098..457fb1716 100644
--- a/g10/kbxfile.c
+++ b/g10/kbxfile.c
@@ -321,7 +321,7 @@ print_kbxfile( const char *filename )
fp = fopen ( filename, "rb" );
if( !fp ) {
log_error(_("can't open `%s': %s\n"), filename, strerror(errno) );
- return 1;
+ return;
}
while ( !do_print_kbxfile( filename, fp ) )
diff --git a/g10/keydb.h b/g10/keydb.h
index 05aac77d3..e0af39aa0 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -1,5 +1,5 @@
/* keydb.h - Key database
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -25,6 +25,7 @@
#include <gdbm.h>
#endif
+#include "types.h"
#include "basicdefs.h"
#include "packet.h"
@@ -156,6 +157,7 @@ void get_seckey_end( GETKEY_CTX ctx );
int enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys );
void merge_keys_and_selfsig( KBNODE keyblock );
char*get_user_id_string( u32 *keyid );
+char*get_user_id_string_native( u32 *keyid );
char*get_long_user_id_string( u32 *keyid );
char*get_user_id( u32 *keyid, size_t *rn );
@@ -197,6 +199,7 @@ const char *enum_keyblock_resources( int *sequence, int secret );
int add_keyblock_resource( const char *resname, int force, int secret );
const char *keyblock_resource_name( KBPOS *kbpos );
int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos );
+char *get_writable_keyblock_file( int secret );
int locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr,
int fprlen, int secret );
int locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid,
diff --git a/g10/keyedit.c b/g10/keyedit.c
index fdb8bf6ad..a64c7e86f 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -1,5 +1,5 @@
/* keyedit.c - keyedit stuff
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -74,8 +74,9 @@ static int enable_disable_key( KBNODE keyblock, int disable );
#define NODFLG_SELSIG (1<<10) /* indicate a selected signature */
-struct sign_uid_attrib {
+struct sign_attrib {
int non_exportable;
+ struct revocation_reason_info *reason;
};
@@ -157,7 +158,7 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node,
else {
size_t n;
char *p = get_user_id( sig->keyid, &n );
- tty_print_utf8_string( p, n > 40? 40 : n );
+ tty_print_utf8_string2( p, n, 40 );
gcry_free(p);
}
tty_printf("\n");
@@ -239,16 +240,18 @@ check_all_keysigs( KBNODE keyblock, int only_selected )
-int
-sign_uid_mk_attrib( PKT_signature *sig, void *opaque )
+static int
+sign_mk_attrib( PKT_signature *sig, void *opaque )
{
- struct sign_uid_attrib *attrib = opaque;
+ struct sign_attrib *attrib = opaque;
byte buf[8];
if( attrib->non_exportable ) {
buf[0] = 0; /* not exportable */
build_sig_subpkt( sig, SIGSUBPKT_EXPORTABLE, buf, 1 );
}
+ if( attrib->reason )
+ revocation_reason_build_cb( sig, attrib->reason );
return 0;
}
@@ -353,7 +356,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, int local )
&& (node->flag & NODFLG_MARK_A) ) {
PACKET *pkt;
PKT_signature *sig;
- struct sign_uid_attrib attrib;
+ struct sign_attrib attrib;
assert( primary_pk );
memset( &attrib, 0, sizeof attrib );
@@ -364,7 +367,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, int local )
NULL,
sk,
0x10, 0,
- sign_uid_mk_attrib,
+ sign_mk_attrib,
&attrib );
if( rc ) {
log_error(_("signing failed: %s\n"), gpg_errstr(rc));
@@ -407,6 +410,7 @@ change_passphrase( KBNODE keyblock )
KBNODE node;
PKT_secret_key *sk;
char *passphrase = NULL;
+ int no_primary_secrets = 0;
node = find_kbnode( keyblock, PKT_SECRET_KEY );
if( !node ) {
@@ -423,10 +427,16 @@ change_passphrase( KBNODE keyblock )
tty_printf(_("This key is not protected.\n"));
break;
default:
- tty_printf(_("Key is protected.\n"));
- rc = check_secret_key( sk, 0 );
- if( !rc )
- passphrase = get_last_passphrase();
+ if( sk->protect.s2k.mode == 1001 ) {
+ tty_printf(_("Secret parts of primary key are not available.\n"));
+ no_primary_secrets = 1;
+ }
+ else {
+ tty_printf(_("Key is protected.\n"));
+ rc = check_secret_key( sk, 0 );
+ if( !rc )
+ passphrase = get_last_passphrase();
+ }
break;
}
@@ -436,6 +446,8 @@ change_passphrase( KBNODE keyblock )
PKT_secret_key *subsk = node->pkt->pkt.secret_key;
set_next_passphrase( passphrase );
rc = check_secret_key( subsk, 0 );
+ if( !rc && !passphrase )
+ passphrase = get_last_passphrase();
}
}
@@ -465,9 +477,12 @@ change_passphrase( KBNODE keyblock )
break;
}
else { /* okay */
- sk->protect.algo = dek->algo;
- sk->protect.s2k = *s2k;
- rc = protect_secret_key( sk, dek );
+ rc = 0;
+ if( !no_primary_secrets ) {
+ sk->protect.algo = dek->algo;
+ sk->protect.s2k = *s2k;
+ rc = protect_secret_key( sk, dek );
+ }
for(node=keyblock; !rc && node; node = node->next ) {
if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
PKT_secret_key *subsk = node->pkt->pkt.secret_key;
@@ -558,41 +573,42 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
static struct { const char *name;
enum cmdids id;
int need_sk;
+ int not_with_sk;
int signmode;
const char *desc;
} cmds[] = {
- { N_("quit") , cmdQUIT , 0,1, N_("quit this menu") },
- { N_("q") , cmdQUIT , 0,1, NULL },
- { N_("save") , cmdSAVE , 0,1, N_("save and quit") },
- { N_("help") , cmdHELP , 0,1, N_("show this help") },
- { "?" , cmdHELP , 0,1, NULL },
- { N_("fpr") , cmdFPR , 0,1, N_("show fingerprint") },
- { N_("list") , cmdLIST , 0,1, N_("list key and user IDs") },
- { N_("l") , cmdLIST , 0,1, NULL },
- { N_("uid") , cmdSELUID , 0,1, N_("select user ID N") },
- { N_("key") , cmdSELKEY , 0,0, N_("select secondary key N") },
- { N_("check") , cmdCHECK , 0,1, N_("list signatures") },
- { N_("c") , cmdCHECK , 0,1, NULL },
- { N_("sign") , cmdSIGN , 0,1, N_("sign the key") },
- { N_("s") , cmdSIGN , 0,1, NULL },
- { N_("lsign") , cmdLSIGN , 0,1, N_("sign the key locally") },
- { N_("debug") , cmdDEBUG , 0,0, NULL },
- { N_("adduid") , cmdADDUID , 1,0, N_("add a user ID") },
- { N_("deluid") , cmdDELUID , 0,0, N_("delete user ID") },
- { N_("addkey") , cmdADDKEY , 1,0, N_("add a secondary key") },
- { N_("delkey") , cmdDELKEY , 0,0, N_("delete a secondary key") },
- { N_("delsig") , cmdDELSIG , 0,0, N_("delete signatures") },
- { N_("expire") , cmdEXPIRE , 1,0, N_("change the expire date") },
- { N_("toggle") , cmdTOGGLE , 1,0, N_("toggle between secret "
- "and public key listing") },
- { N_("t" ) , cmdTOGGLE , 1,0, NULL },
- { N_("pref") , cmdPREF , 0,0, N_("list preferences") },
- { N_("passwd") , cmdPASSWD , 1,0, N_("change the passphrase") },
- { N_("trust") , cmdTRUST , 0,0, N_("change the ownertrust") },
- { N_("revsig") , cmdREVSIG , 0,0, N_("revoke signatures") },
- { N_("revkey") , cmdREVKEY , 1,0, N_("revoke a secondary key") },
- { N_("disable") , cmdDISABLEKEY, 0,0, N_("disable a key") },
- { N_("enable") , cmdENABLEKEY , 0,0, N_("enable a key") },
+ { N_("quit") , cmdQUIT , 0,0,1, N_("quit this menu") },
+ { N_("q") , cmdQUIT , 0,0,1, NULL },
+ { N_("save") , cmdSAVE , 0,0,1, N_("save and quit") },
+ { N_("help") , cmdHELP , 0,0,1, N_("show this help") },
+ { "?" , cmdHELP , 0,0,1, NULL },
+ { N_("fpr") , cmdFPR , 0,0,1, N_("show fingerprint") },
+ { N_("list") , cmdLIST , 0,0,1, N_("list key and user IDs") },
+ { N_("l") , cmdLIST , 0,0,1, NULL },
+ { N_("uid") , cmdSELUID , 0,0,1, N_("select user ID N") },
+ { N_("key") , cmdSELKEY , 0,0,0, N_("select secondary key N") },
+ { N_("check") , cmdCHECK , 0,0,1, N_("list signatures") },
+ { N_("c") , cmdCHECK , 0,0,1, NULL },
+ { N_("sign") , cmdSIGN , 0,1,1, N_("sign the key") },
+ { N_("s") , cmdSIGN , 0,1,1, NULL },
+ { N_("lsign") , cmdLSIGN , 0,1,1, N_("sign the key locally") },
+ { N_("debug") , cmdDEBUG , 0,1,0, NULL },
+ { N_("adduid") , cmdADDUID , 1,1,0, N_("add a user ID") },
+ { N_("deluid") , cmdDELUID , 0,1,0, N_("delete user ID") },
+ { N_("addkey") , cmdADDKEY , 1,1,0, N_("add a secondary key") },
+ { N_("delkey") , cmdDELKEY , 0,1,0, N_("delete a secondary key") },
+ { N_("delsig") , cmdDELSIG , 0,1,0, N_("delete signatures") },
+ { N_("expire") , cmdEXPIRE , 1,1,0, N_("change the expire date") },
+ { N_("toggle") , cmdTOGGLE , 1,0,0, N_("toggle between secret "
+ "and public key listing") },
+ { N_("t" ) , cmdTOGGLE , 1,0,0, NULL },
+ { N_("pref") , cmdPREF , 0,1,0, N_("list preferences") },
+ { N_("passwd") , cmdPASSWD , 1,1,0, N_("change the passphrase") },
+ { N_("trust") , cmdTRUST , 0,1,0, N_("change the ownertrust") },
+ { N_("revsig") , cmdREVSIG , 0,1,0, N_("revoke signatures") },
+ { N_("revkey") , cmdREVKEY , 1,1,0, N_("revoke a secondary key") },
+ { N_("disable") , cmdDISABLEKEY, 0,1,0, N_("disable a key") },
+ { N_("enable") , cmdENABLEKEY , 0,1,0, N_("enable a key") },
{ NULL, cmdNONE } };
enum cmdids cmd = 0;
@@ -678,7 +694,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
have_commands = 0;
}
if( !have_commands ) {
- answer = cpr_get("", _("Command> "));
+ answer = cpr_get("keyedit.prompt", _("Command> "));
cpr_kill_prompt();
}
trim_spaces(answer);
@@ -711,6 +727,10 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
tty_printf(_("Need the secret key to do this.\n"));
cmd = cmdNOP;
}
+ else if( cmds[i].not_with_sk && sec_keyblock && toggle ) {
+ tty_printf(_("Please use the command \"toggle\" first.\n"));
+ cmd = cmdNOP;
+ }
else
cmd = cmds[i].id;
}
@@ -763,6 +783,11 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
if( !sign_uids( keyblock, locusr, &modified, cmd == cmdLSIGN )
&& sign_mode )
goto do_cmd_save;
+ /* Actually we should do a update_trust_record() here so that
+ * the trust gets displayed correctly. however this is not possible
+ * because we would have to save the keyblock first - something
+ * we don't want to do without an explicit save command.
+ */
break;
case cmdDEBUG:
@@ -1005,7 +1030,13 @@ show_prefs( KBNODE keyblock, PKT_user_id *uid )
return;
}
- gcry_md_hash_buffer( GCRY_MD_RMD160, namehash, uid->name, uid->len );
+ if( uid->photo ) {
+ gcry_md_hash_buffer( GCRY_MD_RMD160, namehash, uid->photo,
+ uid->photolen );
+ }
+ else {
+ gcry_md_hash_buffer( GCRY_MD_RMD160, namehash, uid->name, uid->len );
+ }
p = get_pref_data( pk->local_id, namehash, &n );
if( !p )
@@ -1049,7 +1080,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
otrust = get_ownertrust_info( pk->local_id );
}
- tty_printf("%s%c %4u%c/%08lX created: %s expires: %s",
+ tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"),
node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
(node->flag & NODFLG_SELKEY)? '*':' ',
nbits_from_pk( pk ),
@@ -1058,7 +1089,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
datestr_from_pk(pk),
expirestr_from_pk(pk) );
if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
- tty_printf(" trust: %c/%c", otrust, trust );
+ tty_printf(_(" trust: %c/%c"), otrust, trust );
if( node->pkt->pkttype == PKT_PUBLIC_KEY
&& (get_ownertrust( pk->local_id )&TRUST_FLAG_DISABLED)) {
tty_printf("\n*** ");
@@ -1075,14 +1106,15 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
else if( node->pkt->pkttype == PKT_SECRET_KEY
|| (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
PKT_secret_key *sk = node->pkt->pkt.secret_key;
- tty_printf("%s%c %4u%c/%08lX created: %s expires: %s\n",
- node->pkt->pkttype == PKT_SECRET_KEY? "sec":"sbb",
+ tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"),
+ node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
(node->flag & NODFLG_SELKEY)? '*':' ',
nbits_from_sk( sk ),
pubkey_letter( sk->pubkey_algo ),
(ulong)keyid_from_sk(sk,NULL),
datestr_from_sk(sk),
expirestr_from_sk(sk) );
+ tty_printf("\n");
}
else if( with_subkeys && node->pkt->pkttype == PKT_SIGNATURE
&& node->pkt->pkt.signature->sig_class == 0x28 ) {
@@ -1090,12 +1122,12 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
rc = check_key_signature( keyblock, node, NULL );
if( !rc )
- tty_printf( "rev! subkey has been revoked: %s\n",
+ tty_printf( _("rev! subkey has been revoked: %s\n"),
datestr_from_sig( sig ) );
else if( rc == GPGERR_BAD_SIGN )
- tty_printf( "rev- faked revocation found\n" );
+ tty_printf( _("rev- faked revocation found\n") );
else if( rc )
- tty_printf( "rev? problem checking revocation: %s\n",
+ tty_printf( _("rev? problem checking revocation: %s\n"),
gpg_errstr(rc) );
}
}
@@ -1156,7 +1188,7 @@ show_fingerprint( PKT_public_key *pk )
fingerprint_from_pk( pk, array, &n );
p = array;
- tty_printf(" Fingerprint:");
+ tty_printf(_(" Fingerprint:"));
if( n == 20 ) {
for(i=0; i < n ; i++, i++, p += 2 ) {
if( i == 10 )
@@ -1471,7 +1503,8 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
}
else if( node->pkt->pkttype == PKT_USER_ID )
uid = node->pkt->pkt.user_id;
- else if( main_pk && node->pkt->pkttype == PKT_SIGNATURE ) {
+ else if( main_pk && node->pkt->pkttype == PKT_SIGNATURE
+ && sub_pk != NULL ) {
PKT_signature *sig = node->pkt->pkt.signature;
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
&& ( (mainkey && uid && (sig->sig_class&~3) == 0x10)
@@ -1535,6 +1568,7 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
gcry_free( sn->pkt );
sn->pkt = newpkt;
}
+ sub_pk = NULL;
}
}
}
@@ -1735,6 +1769,7 @@ menu_revsig( KBNODE keyblock )
int changed = 0;
int upd_trust = 0;
int rc, any;
+ struct revocation_reason_info *reason = NULL;
/* FIXME: detect duplicates here */
tty_printf(_("You have signed these user IDs:\n"));
@@ -1797,6 +1832,10 @@ menu_revsig( KBNODE keyblock )
_("Really create the revocation certificates? (y/N)")) )
return 0; /* forget it */
+ reason = ask_revocation_reason( 0, 1, 0 );
+ if( !reason ) { /* user decided to cancel */
+ return 0;
+ }
/* now we can sign the user ids */
reloop: /* (must use this, because we are modifing the list) */
@@ -1804,7 +1843,7 @@ menu_revsig( KBNODE keyblock )
for( node=keyblock; node; node = node->next ) {
KBNODE unode;
PACKET *pkt;
- struct sign_uid_attrib attrib;
+ struct sign_attrib attrib;
PKT_secret_key *sk;
if( !(node->flag & NODFLG_MARK_A)
@@ -1814,8 +1853,10 @@ menu_revsig( KBNODE keyblock )
assert( unode ); /* we already checked this */
memset( &attrib, 0, sizeof attrib );
+ attrib.reason = reason;
+
node->flag &= ~NODFLG_MARK_A;
- sk = gcry_xcalloc_secure( 1, sizeof *sk );
+ sk = gcry_xcalloc_secure( 1, sizeof *sk );
if( get_seckey( sk, node->pkt->pkt.signature->keyid ) ) {
log_info(_("no secret key\n"));
continue;
@@ -1825,11 +1866,12 @@ menu_revsig( KBNODE keyblock )
NULL,
sk,
0x30, 0,
- sign_uid_mk_attrib,
+ sign_mk_attrib,
&attrib );
free_secret_key(sk);
if( rc ) {
log_error(_("signing failed: %s\n"), gpg_errstr(rc));
+ release_revocation_reason_info( reason );
return changed;
}
changed = 1; /* we changed the keyblock */
@@ -1844,7 +1886,7 @@ menu_revsig( KBNODE keyblock )
if( upd_trust )
clear_trust_checked_flag( primary_pk );
-
+ release_revocation_reason_info( reason );
return changed;
}
@@ -1861,6 +1903,13 @@ menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
int changed = 0;
int upd_trust = 0;
int rc;
+ struct revocation_reason_info *reason = NULL;
+
+ reason = ask_revocation_reason( 1, 0, 0 );
+ if( !reason ) { /* user decided to cancel */
+ return 0;
+ }
+
reloop: /* (better this way because we are modifing the keyring) */
mainpk = pub_keyblock->pkt->pkt.public_key;
@@ -1871,14 +1920,20 @@ menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
PKT_signature *sig;
PKT_secret_key *sk;
PKT_public_key *subpk = node->pkt->pkt.public_key;
+ struct sign_attrib attrib;
+
+ memset( &attrib, 0, sizeof attrib );
+ attrib.reason = reason;
node->flag &= ~NODFLG_SELKEY;
sk = copy_secret_key( NULL, sec_keyblock->pkt->pkt.secret_key );
rc = make_keysig_packet( &sig, mainpk, NULL, subpk, sk, 0x28, 0,
- NULL, NULL );
+ sign_mk_attrib,
+ &attrib );
free_secret_key(sk);
if( rc ) {
log_error(_("signing failed: %s\n"), gpg_errstr(rc));
+ release_revocation_reason_info( reason );
return changed;
}
changed = 1; /* we changed the keyblock */
@@ -1897,6 +1952,7 @@ menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
if( upd_trust )
clear_trust_checked_flag( mainpk );
+ release_revocation_reason_info( reason );
return changed;
}
diff --git a/g10/keygen.c b/g10/keygen.c
index af288b3aa..b6c6cc7e3 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -1,5 +1,5 @@
/* keygen.c - generate a key pair
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -35,6 +35,58 @@
#include "status.h"
#include "i18n.h"
+enum para_name {
+ pKEYTYPE,
+ pKEYLENGTH,
+ pSUBKEYTYPE,
+ pSUBKEYLENGTH,
+ pNAMEREAL,
+ pNAMEEMAIL,
+ pNAMECOMMENT,
+ pUSERID,
+ pEXPIREDATE,
+ pKEYEXPIRE, /* in n seconds */
+ pSUBKEYEXPIRE, /* in n seconds */
+ pPASSPHRASE,
+ pPASSPHRASE_DEK,
+ pPASSPHRASE_S2K
+};
+
+struct para_data_s {
+ struct para_data_s *next;
+ int lnr;
+ enum para_name key;
+ union {
+ DEK *dek;
+ STRING2KEY *s2k;
+ u32 expire;
+ char value[1];
+ } u;
+};
+
+struct output_control_s {
+ int lnr;
+ int dryrun;
+ int use_files;
+ struct {
+ char *fname;
+ char *newfname;
+ IOBUF stream;
+ armor_filter_context_t afx;
+ } pub;
+ struct {
+ char *fname;
+ char *newfname;
+ IOBUF stream;
+ armor_filter_context_t afx;
+ } sec;
+};
+
+
+static void do_generate_keypair( struct para_data_s *para,
+ struct output_control_s *outctrl );
+static int write_keyblock( IOBUF out, KBNODE node );
+
static void
write_uid( KBNODE root, const char *s )
@@ -43,7 +95,7 @@ write_uid( KBNODE root, const char *s )
size_t n = strlen(s);
pkt->pkttype = PKT_USER_ID;
- pkt->pkt.user_id = gcry_xmalloc( sizeof *pkt->pkt.user_id + n - 1 );
+ pkt->pkt.user_id = gcry_xcalloc( 1, sizeof *pkt->pkt.user_id + n - 1 );
pkt->pkt.user_id->len = n;
strcpy(pkt->pkt.user_id->name, s);
add_kbnode( root, new_kbnode( pkt ) );
@@ -84,8 +136,9 @@ keygen_add_std_prefs( PKT_signature *sig, void *opaque )
keygen_add_key_expire( sig, opaque );
buf[0] = GCRY_CIPHER_TWOFISH;
- buf[1] = GCRY_CIPHER_CAST5;
- build_sig_subpkt( sig, SIGSUBPKT_PREF_SYM, buf, 2 );
+ buf[1] = GCRY_CIPHER_BLOWFISH;
+ buf[2] = GCRY_CIPHER_CAST5;
+ build_sig_subpkt( sig, SIGSUBPKT_PREF_SYM, buf, 3 );
buf[0] = GCRY_MD_RMD160;
buf[1] = GCRY_MD_SHA1;
@@ -189,6 +242,7 @@ write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_key *sk )
}
+
static int
key_from_sexp( GCRY_MPI *array,
GCRY_SEXP sexp, const char *topname, const char *elems )
@@ -252,7 +306,7 @@ factors_from_sexp( MPI **retarray, GCRY_SEXP sexp )
for( n=0; (l2 = gcry_sexp_enum( list, &ctx, 0 )); n++ )
;
- array = gcry_calloc( n, sizeof *array );
+ array = gcry_xcalloc( n, sizeof *array );
if( !array )
return GCRYERR_NO_MEM;
@@ -275,10 +329,10 @@ factors_from_sexp( MPI **retarray, GCRY_SEXP sexp )
}
+
static int
gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
- STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval,
- int version )
+ STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval )
{
int rc;
int i;
@@ -289,6 +343,18 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
char buf[100];
GCRY_SEXP s_parms, s_key;
+ assert( is_ELGAMAL(algo) );
+
+ if( nbits < 512 ) {
+ nbits = 1024;
+ log_info(_("keysize invalid; using %u bits\n"), nbits );
+ }
+
+ if( (nbits % 32) ) {
+ nbits = ((nbits + 31) / 32) * 32;
+ log_info(_("keysize rounded up to %u bits\n"), nbits );
+ }
+
sprintf(buf, "%u", nbits );
s_parms = SEXP_CONS( SEXP_NEW( "genkey", 0 ),
SEXP_CONS( SEXP_NEW(algo == GCRY_PK_ELG_E ? "openpgp-elg" :
@@ -303,10 +369,11 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
return rc;
}
+
sk = gcry_xcalloc( 1, sizeof *sk );
pk = gcry_xcalloc( 1, sizeof *pk );
sk->timestamp = pk->timestamp = make_timestamp();
- sk->version = pk->version = version;
+ sk->version = pk->version = 4;
if( expireval ) {
sk->expiredate = pk->expiredate = sk->timestamp + expireval;
}
@@ -361,7 +428,6 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
for(i=0; factors[i]; i++ ) {
add_kbnode( sec_root,
make_mpi_comment_node("#:ELG_factor:", factors[i] ));
- gcry_mpi_release(factors[i]);
}
return 0;
@@ -372,7 +438,7 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
* Generate a DSA key
*/
static int
-gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
+gen_dsa(unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval )
{
int rc;
@@ -384,8 +450,15 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
char buf[100];
GCRY_SEXP s_parms, s_key;
- if( nbits > 1024 )
+ if( nbits > 1024 || nbits < 512 ) {
nbits = 1024;
+ log_info(_("keysize invalid; using %u bits\n"), nbits );
+ }
+
+ if( (nbits % 64) ) {
+ nbits = ((nbits + 63) / 64) * 64;
+ log_info(_("keysize rounded up to %u bits\n"), nbits );
+ }
sprintf(buf, "%u", nbits );
s_parms = SEXP_CONS( SEXP_NEW( "genkey", 0 ),
@@ -400,6 +473,7 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
return rc;
}
+
sk = gcry_xcalloc( 1, sizeof *sk );
pk = gcry_xcalloc( 1, sizeof *pk );
sk->timestamp = pk->timestamp = make_timestamp();
@@ -464,10 +538,91 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
make_mpi_comment_node("#:DSA_factor:", factors[i] ));
/* fixme: Merge this with the elg-generate function and release
- * some more stuff */
+ * some more stuff (memory-leak) */
return 0;
}
+#if 0
+static int
+gen_rsa(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
+ STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval )
+{
+ int rc;
+ PACKET *pkt;
+ PKT_secret_key *sk;
+ PKT_public_key *pk;
+ MPI skey[4];
+ MPI *factors;
+
+ assert( is_RSA(algo) );
+
+ if( nbits < 1024 ) {
+ nbits = 1024;
+ log_info(_("keysize invalid; using %u bits\n"), nbits );
+ }
+
+ if( (nbits % 32) ) {
+ nbits = ((nbits + 31) / 32) * 32;
+ log_info(_("keysize rounded up to %u bits\n"), nbits );
+ }
+
+ rc = pubkey_generate( algo, nbits, skey, &factors );
+ if( rc ) {
+ log_error("pubkey_generate failed: %s\n", gpg_errstr(rc) );
+ return rc;
+ }
+
+ sk = gcry_xcalloc( 1, sizeof *sk );
+ pk = gcry_xcalloc( 1, sizeof *pk );
+ sk->timestamp = pk->timestamp = make_timestamp();
+ sk->version = pk->version = 4;
+ if( expireval ) {
+ sk->expiredate = pk->expiredate = sk->timestamp + expireval;
+ }
+ sk->pubkey_algo = pk->pubkey_algo = algo;
+ pk->pkey[0] = mpi_copy( skey[0] );
+ pk->pkey[1] = mpi_copy( skey[1] );
+ sk->skey[0] = skey[0];
+ sk->skey[1] = skey[1];
+ sk->skey[2] = skey[2];
+ sk->skey[3] = skey[3];
+ sk->skey[4] = skey[4];
+ sk->skey[5] = skey[5];
+ sk->is_protected = 0;
+ sk->protect.algo = 0;
+
+ sk->csum = checksum_mpi_counted_nbits( sk->skey[2] );
+ sk->csum += checksum_mpi_counted_nbits( sk->skey[3] );
+ sk->csum += checksum_mpi_counted_nbits( sk->skey[4] );
+ sk->csum += checksum_mpi_counted_nbits( sk->skey[5] );
+ if( ret_sk ) /* not a subkey: return an unprotected version of the sk */
+ *ret_sk = copy_secret_key( NULL, sk );
+
+ if( dek ) {
+ sk->protect.algo = dek->algo;
+ sk->protect.s2k = *s2k;
+ rc = protect_secret_key( sk, dek );
+ if( rc ) {
+ log_error("protect_secret_key failed: %s\n", gpg_errstr(rc) );
+ free_public_key(pk);
+ free_secret_key(sk);
+ return rc;
+ }
+ }
+
+ pkt = gcry_xcalloc( 1,sizeof *pkt);
+ pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY;
+ pkt->pkt.public_key = pk;
+ add_kbnode(pub_root, new_kbnode( pkt ));
+
+ pkt = gcry_xcalloc( 1,sizeof *pkt);
+ pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY;
+ pkt->pkt.secret_key = sk;
+ add_kbnode(sec_root, new_kbnode( pkt ));
+
+ return 0;
+}
+#endif
/****************
@@ -502,7 +657,7 @@ check_valid_days( const char *s )
* Returns: 0 to create both a DSA and a ElGamal key.
*/
static int
-ask_algo( int *ret_v4, int addmode )
+ask_algo( int addmode )
{
char *answer;
int algo;
@@ -515,10 +670,9 @@ ask_algo( int *ret_v4, int addmode )
tty_printf( _(" (%d) ElGamal (encrypt only)\n"), 3 );
tty_printf( _(" (%d) ElGamal (sign and encrypt)\n"), 4 );
#if 0
- tty_printf( _(" (%d) ElGamal in a v3 packet\n"), 5 );
+ tty_printf( _(" (%d) RSA (sign and encrypt)\n"), 5 );
#endif
- *ret_v4 = 1;
for(;;) {
answer = cpr_get("keygen.algo",_("Your selection? "));
cpr_kill_prompt();
@@ -528,6 +682,15 @@ ask_algo( int *ret_v4, int addmode )
algo = 0; /* create both keys */
break;
}
+ #if 0
+ else if( algo == 5 ) {
+ if( cpr_get_answer_is_yes("keygen.algo.rsa_se",_(
+ "Do you really want to create a sign and encrypt key? "))) {
+ algo = GCRY_PK_RSA;
+ break;
+ }
+ }
+ #endif
else if( algo == 4 ) {
if( cpr_get_answer_is_yes("keygen.algo.elg_se",_(
"Do you really want to create a sign and encrypt key? "))) {
@@ -543,13 +706,6 @@ ask_algo( int *ret_v4, int addmode )
algo = GCRY_PK_DSA;
break;
}
- #if 0
- else if( algo == 5 ) {
- algo = GCRY_PK_ELG_E;
- *ret_v4 = 0;
- break;
- }
- #endif
else
tty_printf(_("Invalid selection.\n"));
}
@@ -578,6 +734,9 @@ ask_keysize( int algo )
tty_printf(_("DSA only allows keysizes from 512 to 1024\n"));
else if( nbits < 768 )
tty_printf(_("keysize too small; 768 is smallest value allowed.\n"));
+ else if( algo == GCRY_PK_RSA && nbits < 1024 )
+ tty_printf(_("keysize too small;"
+ " 1024 is smallest value allowed for RSA.\n"));
else if( nbits > 4096 ) {
/* It is ridiculous and an annoyance to use larger key sizes!
* GnuPG can handle much larger sizes; but it takes an eternity
@@ -602,7 +761,7 @@ ask_keysize( int algo )
break;
}
}
- else if( nbits > 1536 && !cpr_enabled() ) {
+ else if( nbits > 1536 && !cpr_enabled() && algo != GCRY_PK_RSA ) {
if( cpr_get_answer_is_yes("keygen.size.large.okay",_(
"Do you really need such a large keysize? ")) )
break;
@@ -623,6 +782,41 @@ ask_keysize( int algo )
}
+/****************
+ * Parse an expire string and return it's value in days.
+ * Returns -1 on error.
+ */
+static int
+parse_expire_string( const char *string )
+{
+ int mult;
+ u32 abs_date=0;
+ u32 curtime = make_timestamp();
+ int valid_days;
+
+ if( !*string )
+ valid_days = 0;
+ else if( (abs_date = scan_isodatestr(string)) && abs_date > curtime ) {
+ /* This calculation is not perfectly okay because we
+ * are later going to simply multiply by 86400 and don't
+ * correct for leapseconds. A solution would be to change
+ * the whole implemenation to work with dates and not intervals
+ * which are required for v3 keys.
+ */
+ valid_days = abs_date/86400-curtime/86400+1;
+ }
+ else if( (mult=check_valid_days(string)) ) {
+ valid_days = atoi(string) * mult;
+ if( valid_days < 0 || valid_days > 39447 )
+ valid_days = 0;
+ }
+ else {
+ valid_days = -1;
+ }
+ return valid_days;
+}
+
+
static u32
ask_expire_interval(void)
{
@@ -642,32 +836,14 @@ ask_expire_interval(void)
answer = NULL;
for(;;) {
- int mult;
- u32 abs_date=0;
- u32 curtime=0;;
+ u32 curtime=make_timestamp();
gcry_free(answer);
answer = cpr_get("keygen.valid",_("Key is valid for? (0) "));
cpr_kill_prompt();
trim_spaces(answer);
- curtime = make_timestamp();
- if( !*answer )
- valid_days = 0;
- else if( (abs_date = scan_isodatestr(answer)) && abs_date > curtime ) {
- /* This calculation is not perfectly okay because we
- * are later going to simply multiply by 86400 and don't
- * correct for leapseconds. A solution would be to change
- * the whole implemenation to work with dates and not intervals
- * which are required for v3 keys.
- */
- valid_days = abs_date/86400-curtime/86400+1;
- }
- else if( (mult=check_valid_days(answer)) ) {
- valid_days = atoi(answer) * mult;
- if( valid_days < 0 || valid_days > 32767 )
- valid_days = 0;
- }
- else {
+ valid_days = parse_expire_string( answer );
+ if( valid_days < 0 ) {
tty_printf(_("invalid value\n"));
continue;
}
@@ -680,7 +856,10 @@ ask_expire_interval(void)
interval = valid_days * 86400L;
/* print the date when the key expires */
tty_printf(_("Key expires at %s\n"),
- asctimestamp(curtime + interval ) );
+ asctimestamp((ulong)(curtime + interval) ) );
+ if( (time_t)((ulong)(curtime+interval)) < 0 )
+ tty_printf(_("Your system can't display dates beyond 2038.\n"
+ "However, it will be correctly handled up to 2106.\n"));
}
if( cpr_enabled() || cpr_get_answer_is_yes("keygen.valid.okay",
@@ -734,6 +913,7 @@ ask_user_id( int mode )
uid = aname = acomment = amail = NULL;
for(;;) {
char *p;
+ int fail=0;
if( !aname ) {
for(;;) {
@@ -785,6 +965,7 @@ ask_user_id( int mode )
}
}
+
gcry_free(uid);
uid = p = gcry_xmalloc(strlen(aname)+strlen(amail)+strlen(acomment)+12+10);
p = stpcpy(p, aname );
@@ -812,8 +993,14 @@ ask_user_id( int mode )
tty_printf(_("You selected this USER-ID:\n \"%s\"\n\n"), uid);
/* fixme: add a warning if this user-id already exists */
+ if( !*amail && (strchr( aname, '@' ) || strchr( acomment, '@'))) {
+ fail = 1;
+ tty_printf(_("Please don't put the email address "
+ "into the real name or the comment\n") );
+ }
+
for(;;) {
- const char *ansstr = _("NnCcEeOoQq");
+ char *ansstr = _("NnCcEeOoQq");
if( strlen(ansstr) != 10 )
BUG();
@@ -822,8 +1009,9 @@ ask_user_id( int mode )
answer[1] = 0;
}
else {
- answer = cpr_get("keygen.userid.cmd",_(
- "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "));
+ answer = cpr_get("keygen.userid.cmd", fail?
+ _("Change (N)ame, (C)omment, (E)mail or (Q)uit? ") :
+ _("Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "));
cpr_kill_prompt();
}
if( strlen(answer) > 1 )
@@ -841,10 +1029,15 @@ ask_user_id( int mode )
break;
}
else if( *answer == ansstr[6] || *answer == ansstr[7] ) {
- gcry_free(aname); aname = NULL;
- gcry_free(acomment); acomment = NULL;
- gcry_free(amail); amail = NULL;
- break;
+ if( fail ) {
+ tty_printf(_("Please correct the error first\n"));
+ }
+ else {
+ gcry_free(aname); aname = NULL;
+ gcry_free(acomment); acomment = NULL;
+ gcry_free(amail); amail = NULL;
+ break;
+ }
}
else if( *answer == ansstr[8] || *answer == ansstr[9] ) {
gcry_free(aname); aname = NULL;
@@ -904,22 +1097,25 @@ ask_passphrase( STRING2KEY **ret_s2k )
static int
do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root,
- DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, u32 expiredate,
- int v4_packet )
+ DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, u32 expiredate )
{
int rc=0;
- tty_printf(_(
+ if( !opt.batch )
+ tty_printf(_(
"We need to generate a lot of random bytes. It is a good idea to perform\n"
"some other action (type on the keyboard, move the mouse, utilize the\n"
"disks) during the prime generation; this gives the random number\n"
"generator a better chance to gain enough entropy.\n") );
if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E )
- rc = gen_elg(algo, nbits, pub_root, sec_root, dek, s2k,
- sk, expiredate, v4_packet? 4:3 );
+ rc = gen_elg(algo, nbits, pub_root, sec_root, dek, s2k, sk, expiredate);
else if( algo == GCRY_PK_DSA )
rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk, expiredate);
+ #if 0
+ else if( algo == GCRY_PK_RSA )
+ rc = gen_rsa(algo, nbits, pub_root, sec_root, dek, s2k, sk, expiredate);
+ #endif
else
BUG();
@@ -951,61 +1147,553 @@ generate_user_id()
if( !p )
return NULL;
n = strlen(p);
- uid = gcry_xmalloc( sizeof *uid + n - 1 );
+ uid = gcry_xcalloc( 1, sizeof *uid + n - 1 );
uid->len = n;
strcpy(uid->name, p);
return uid;
}
+static void
+release_parameter_list( struct para_data_s *r )
+{
+ struct para_data_s *r2;
+
+ for( ; r ; r = r2 ) {
+ r2 = r->next;
+ if( r->key == pPASSPHRASE_DEK )
+ gcry_free( r->u.dek );
+ else if( r->key == pPASSPHRASE_S2K )
+ gcry_free( r->u.s2k );
+
+ gcry_free(r);
+ }
+}
+
+static struct para_data_s *
+get_parameter( struct para_data_s *para, enum para_name key )
+{
+ struct para_data_s *r;
+
+ for( r = para; r && r->key != key; r = r->next )
+ ;
+ return r;
+}
+
+static const char *
+get_parameter_value( struct para_data_s *para, enum para_name key )
+{
+ struct para_data_s *r = get_parameter( para, key );
+ return (r && *r->u.value)? r->u.value : NULL;
+}
+
+static int
+get_parameter_algo( struct para_data_s *para, enum para_name key )
+{
+ struct para_data_s *r = get_parameter( para, key );
+ if( !r )
+ return -1;
+ if( isdigit( *r->u.value ) )
+ return atoi( r->u.value );
+ return gcry_pk_map_name( r->u.value );
+}
+
+
+static u32
+get_parameter_u32( struct para_data_s *para, enum para_name key )
+{
+ struct para_data_s *r = get_parameter( para, key );
+
+ if( !r )
+ return 0;
+ if( r->key == pKEYEXPIRE || r->key == pSUBKEYEXPIRE )
+ return r->u.expire;
+
+ return (unsigned int)strtoul( r->u.value, NULL, 10 );
+}
+
+static unsigned int
+get_parameter_uint( struct para_data_s *para, enum para_name key )
+{
+ return get_parameter_u32( para, key );
+}
+
+static DEK *
+get_parameter_dek( struct para_data_s *para, enum para_name key )
+{
+ struct para_data_s *r = get_parameter( para, key );
+ return r? r->u.dek : NULL;
+}
+
+static STRING2KEY *
+get_parameter_s2k( struct para_data_s *para, enum para_name key )
+{
+ struct para_data_s *r = get_parameter( para, key );
+ return r? r->u.s2k : NULL;
+}
+
+
+static int
+proc_parameter_file( struct para_data_s *para, const char *fname,
+ struct output_control_s *outctrl )
+{
+ struct para_data_s *r;
+ const char *s1, *s2, *s3;
+ size_t n;
+ char *p;
+ int i;
+
+ /* check that we have all required parameters */
+ assert( get_parameter( para, pKEYTYPE ) );
+ i = get_parameter_algo( para, pKEYTYPE );
+ if( i < 1 || openpgp_pk_test_algo( i, GCRY_PK_USAGE_SIGN ) ) {
+ r = get_parameter( para, pKEYTYPE );
+ log_error("%s:%d: invalid algorithm\n", fname, r->lnr );
+ return -1;
+ }
+
+ i = get_parameter_algo( para, pSUBKEYTYPE );
+ if( i > 1 && openpgp_pk_test_algo( i, 0 ) ) {
+ r = get_parameter( para, pSUBKEYTYPE );
+ log_error("%s:%d: invalid algorithm\n", fname, r->lnr );
+ return -1;
+ }
+
+ if( !get_parameter_value( para, pUSERID ) ) {
+ /* create the formatted user ID */
+ s1 = get_parameter_value( para, pNAMEREAL );
+ s2 = get_parameter_value( para, pNAMECOMMENT );
+ s3 = get_parameter_value( para, pNAMEEMAIL );
+ if( s1 || s2 || s3 ) {
+ n = (s1?strlen(s1):0) + (s2?strlen(s2):0) + (s3?strlen(s3):0);
+ r = gcry_xcalloc( 1, sizeof *r + n + 20 );
+ r->key = pUSERID;
+ p = r->u.value;
+ if( s1 )
+ p = stpcpy(p, s1 );
+ if( s2 )
+ p = stpcpy(stpcpy(stpcpy(p," ("), s2 ),")");
+ if( s3 )
+ p = stpcpy(stpcpy(stpcpy(p," <"), s3 ),">");
+ r->next = para;
+ para = r;
+ }
+ }
+
+ /* make DEK and S2K from the Passphrase */
+ r = get_parameter( para, pPASSPHRASE );
+ if( r && *r->u.value ) {
+ /* we have a plain text passphrase - create a DEK from it.
+ * It is a little bit ridiculous to keep it ih secure memory
+ * but becuase we do this alwasy, why not here */
+ STRING2KEY *s2k;
+ DEK *dek;
+
+ s2k = gcry_xmalloc_secure( sizeof *s2k );
+ s2k->mode = opt.s2k_mode;
+ s2k->hash_algo = opt.s2k_digest_algo;
+ set_next_passphrase( r->u.value );
+ dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2 );
+ set_next_passphrase( NULL );
+ assert( dek );
+ memset( r->u.value, 0, strlen(r->u.value) );
+
+ r = gcry_xcalloc( 1, sizeof *r );
+ r->key = pPASSPHRASE_S2K;
+ r->u.s2k = s2k;
+ r->next = para;
+ para = r;
+ r = gcry_xcalloc( 1, sizeof *r );
+ r->key = pPASSPHRASE_DEK;
+ r->u.dek = dek;
+ r->next = para;
+ para = r;
+ }
+
+ /* make KEYEXPIRE from Expire-Date */
+ r = get_parameter( para, pEXPIREDATE );
+ if( r && *r->u.value ) {
+ i = parse_expire_string( r->u.value );
+ if( i < 0 ) {
+ log_error("%s:%d: invalid expire date\n", fname, r->lnr );
+ return -1;
+ }
+ r->u.expire = i * 86400L;
+ r->key = pKEYEXPIRE; /* change hat entry */
+ /* also set it for the subkey */
+ r = gcry_xcalloc( 1, sizeof *r + 20 );
+ r->key = pSUBKEYEXPIRE;
+ r->u.expire = i * 86400L;
+ r->next = para;
+ para = r;
+ }
+
+ if( !!outctrl->pub.newfname ^ !!outctrl->sec.newfname ) {
+ log_error("%s:%d: only one ring name is set\n", fname, outctrl->lnr );
+ return -1;
+ }
+
+ do_generate_keypair( para, outctrl );
+ return 0;
+}
+
+
+/****************
+ * Kludge to allow non interactive key generation controlled
+ * by a parameter file (which currently is only stdin)
+ * Note, that string parameters are expected to be in UTF-8
+ */
+static void
+read_parameter_file( const char *fname )
+{
+ static struct { const char *name;
+ enum para_name key;
+ } keywords[] = {
+ { "Key-Type", pKEYTYPE},
+ { "Key-Length", pKEYLENGTH },
+ { "Subkey-Type", pSUBKEYTYPE },
+ { "Subkey-Length", pSUBKEYLENGTH },
+ { "Name-Real", pNAMEREAL },
+ { "Name-Email", pNAMEEMAIL },
+ { "Name-Comment", pNAMECOMMENT },
+ { "Expire-Date", pEXPIREDATE },
+ { "Passphrase", pPASSPHRASE },
+ { NULL, 0 }
+ };
+ FILE *fp;
+ char line[1024], *p;
+ int lnr;
+ const char *err = NULL;
+ struct para_data_s *para, *r;
+ int i;
+ struct output_control_s outctrl;
+
+ memset( &outctrl, 0, sizeof( outctrl ) );
+
+ if( !fname || !*fname || !strcmp(fname,"-") ) {
+ fp = stdin;
+ fname = "-";
+ }
+ else {
+ fp = fopen( fname, "r" );
+ if( !fp ) {
+ log_error(_("can't open `%s': %s\n"), fname, strerror(errno) );
+ return;
+ }
+ }
+
+ lnr = 0;
+ err = NULL;
+ para = NULL;
+ while( fgets( line, DIM(line)-1, fp ) ) {
+ char *keyword, *value;
+
+ lnr++;
+ if( *line && line[strlen(line)-1] != '\n' ) {
+ err = "line too long";
+ break;
+ }
+ for( p = line; isspace(*p); p++ )
+ ;
+ if( !*p || *p == '#' )
+ continue;
+ keyword = p;
+ if( *keyword == '%' ) {
+ for( ; !isspace(*p); p++ )
+ ;
+ if( *p )
+ *p++ = 0;
+ for( ; isspace(*p); p++ )
+ ;
+ value = p;
+ trim_trailing_ws( value, strlen(value) );
+ if( !stricmp( keyword, "%echo" ) )
+ log_info("%s\n", value );
+ else if( !stricmp( keyword, "%dry-run" ) )
+ outctrl.dryrun = 1;
+ else if( !stricmp( keyword, "%commit" ) ) {
+ outctrl.lnr = lnr;
+ proc_parameter_file( para, fname, &outctrl );
+ release_parameter_list( para );
+ para = NULL;
+ }
+ else if( !stricmp( keyword, "%pubring" ) ) {
+ if( outctrl.pub.fname && !strcmp( outctrl.pub.fname, value ) )
+ ; /* still the same file - ignore it */
+ else {
+ gcry_free( outctrl.pub.newfname );
+ outctrl.pub.newfname = gcry_xstrdup( value );
+ outctrl.use_files = 1;
+ }
+ }
+ else if( !stricmp( keyword, "%secring" ) ) {
+ if( outctrl.sec.fname && !strcmp( outctrl.sec.fname, value ) )
+ ; /* still the same file - ignore it */
+ else {
+ gcry_free( outctrl.sec.newfname );
+ outctrl.sec.newfname = gcry_xstrdup( value );
+ outctrl.use_files = 1;
+ }
+ }
+ else
+ log_info("skipping control `%s' (%s)\n", keyword, value );
+
+
+ continue;
+ }
+
+
+ if( !(p = strchr( p, ':' )) || p == keyword ) {
+ err = "missing colon";
+ break;
+ }
+ if( *p )
+ *p++ = 0;
+ for( ; isspace(*p); p++ )
+ ;
+ if( !*p ) {
+ err = "missing argument";
+ break;
+ }
+ value = p;
+ trim_trailing_ws( value, strlen(value) );
+
+ for(i=0; keywords[i].name; i++ ) {
+ if( !stricmp( keywords[i].name, keyword ) )
+ break;
+ }
+ if( !keywords[i].name ) {
+ err = "unknown keyword";
+ break;
+ }
+ if( keywords[i].key != pKEYTYPE && !para ) {
+ err = "parameter block does not start with \"Key-Type\"";
+ break;
+ }
+
+ if( keywords[i].key == pKEYTYPE && para ) {
+ outctrl.lnr = lnr;
+ proc_parameter_file( para, fname, &outctrl );
+ release_parameter_list( para );
+ para = NULL;
+ }
+ else {
+ for( r = para; r; r = r->next ) {
+ if( r->key == keywords[i].key )
+ break;
+ }
+ if( r ) {
+ err = "duplicate keyword";
+ break;
+ }
+ }
+ r = gcry_xcalloc( 1, sizeof *r + strlen( value ) );
+ r->lnr = lnr;
+ r->key = keywords[i].key;
+ strcpy( r->u.value, value );
+ r->next = para;
+ para = r;
+ }
+ if( err )
+ log_error("%s:%d: %s\n", fname, lnr, err );
+ else if( ferror(fp) ) {
+ log_error("%s:%d: read error: %s\n", fname, lnr, strerror(errno) );
+ }
+ else if( para ) {
+ outctrl.lnr = lnr;
+ proc_parameter_file( para, fname, &outctrl );
+ }
+
+ if( outctrl.use_files ) { /* close open streams */
+ iobuf_close( outctrl.pub.stream );
+ iobuf_close( outctrl.sec.stream );
+ gcry_free( outctrl.pub.fname );
+ gcry_free( outctrl.pub.newfname );
+ gcry_free( outctrl.sec.fname );
+ gcry_free( outctrl.sec.newfname );
+ }
+
+ release_parameter_list( para );
+ if( strcmp( fname, "-" ) )
+ fclose(fp);
+}
+
+
/****************
* Generate a keypair
+ * (fname is only used in batch mode)
*/
void
-generate_keypair()
+generate_keypair( const char *fname )
{
- unsigned nbits;
- char *pub_fname = NULL;
- char *sec_fname = NULL;
+ unsigned int nbits;
char *uid = NULL;
- KBNODE pub_root = NULL;
- KBNODE sec_root = NULL;
- PKT_secret_key *sk = NULL;
DEK *dek;
STRING2KEY *s2k;
- int rc;
int algo;
- u32 expire;
- int v4;
int both = 0;
+ u32 expire;
+ struct para_data_s *para = NULL;
+ struct para_data_s *r;
+ struct output_control_s outctrl;
+
+ memset( &outctrl, 0, sizeof( outctrl ) );
- if( opt.batch || opt.answer_yes || opt.answer_no ) {
- log_error(_("Key generation can only be used in interactive mode\n"));
+ if( opt.batch ) {
+ read_parameter_file( fname );
return;
}
- algo = ask_algo( &v4, 0 );
- if( !algo ) {
- algo = GCRY_PK_ELG_E;
+ algo = ask_algo( 0 );
+ if( !algo ) { /* default: DSA with ElG subkey of the specified size */
both = 1;
+ r = gcry_xcalloc( 1, sizeof *r + 20 );
+ r->key = pKEYTYPE;
+ sprintf( r->u.value, "%d", GCRY_PK_DSA );
+ r->next = para;
+ para = r;
tty_printf(_("DSA keypair will have 1024 bits.\n"));
+ r = gcry_xcalloc( 1, sizeof *r + 20 );
+ r->key = pKEYLENGTH;
+ strcpy( r->u.value, "1024" );
+ r->next = para;
+ para = r;
+
+ algo = GCRY_PK_ELG_E;
+ r = gcry_xcalloc( 1, sizeof *r + 20 );
+ r->key = pSUBKEYTYPE;
+ sprintf( r->u.value, "%d", algo );
+ r->next = para;
+ para = r;
+ }
+ else {
+ r = gcry_xcalloc( 1, sizeof *r + 20 );
+ r->key = pKEYTYPE;
+ sprintf( r->u.value, "%d", algo );
+ r->next = para;
+ para = r;
}
+
nbits = ask_keysize( algo );
+ r = gcry_xcalloc( 1, sizeof *r + 20 );
+ r->key = both? pSUBKEYLENGTH : pKEYLENGTH;
+ sprintf( r->u.value, "%u", nbits);
+ r->next = para;
+ para = r;
+
expire = ask_expire_interval();
+ r = gcry_xcalloc( 1, sizeof *r + 20 );
+ r->key = pKEYEXPIRE;
+ r->u.expire = expire;
+ r->next = para;
+ para = r;
+ r = gcry_xcalloc( 1, sizeof *r + 20 );
+ r->key = pSUBKEYEXPIRE;
+ r->u.expire = expire;
+ r->next = para;
+ para = r;
+
uid = ask_user_id(0);
if( !uid ) {
log_error(_("Key generation canceled.\n"));
+ release_parameter_list( para );
return;
}
+ r = gcry_xcalloc( 1, sizeof *r + strlen(uid) );
+ r->key = pUSERID;
+ strcpy( r->u.value, uid );
+ r->next = para;
+ para = r;
+
dek = ask_passphrase( &s2k );
+ if( dek ) {
+ r = gcry_xcalloc( 1, sizeof *r );
+ r->key = pPASSPHRASE_DEK;
+ r->u.dek = dek;
+ r->next = para;
+ para = r;
+ r = gcry_xcalloc( 1, sizeof *r );
+ r->key = pPASSPHRASE_S2K;
+ r->u.s2k = s2k;
+ r->next = para;
+ para = r;
+ }
+
+ proc_parameter_file( para, "[internal]", &outctrl );
+ release_parameter_list( para );
+}
- /* now check whether we are allowed to write to the keyrings */
- pub_fname = make_filename(opt.homedir, "pubring.gpg", NULL );
- sec_fname = make_filename(opt.homedir, "secring.gpg", NULL );
+static void
+do_generate_keypair( struct para_data_s *para,
+ struct output_control_s *outctrl )
+{
+ char *pub_fname = NULL;
+ char *sec_fname = NULL;
+ KBNODE pub_root = NULL;
+ KBNODE sec_root = NULL;
+ PKT_secret_key *sk = NULL;
+ const char *s;
+ int rc;
+
+ if( outctrl->dryrun ) {
+ log_info("dry-run mode - key generation skipped\n");
+ return;
+ }
+
+
+ if( outctrl->use_files ) {
+ if( outctrl->pub.newfname ) {
+ iobuf_close(outctrl->pub.stream);
+ outctrl->pub.stream = NULL;
+ gcry_free( outctrl->pub.fname );
+ outctrl->pub.fname = outctrl->pub.newfname;
+ outctrl->pub.newfname = NULL;
+
+ outctrl->pub.stream = iobuf_create( outctrl->pub.fname );
+ if( !outctrl->pub.stream ) {
+ log_error("can't create `%s': %s\n", outctrl->pub.newfname,
+ strerror(errno) );
+ return;
+ }
+ if( opt.armor ) {
+ outctrl->pub.afx.what = 1;
+ iobuf_push_filter( outctrl->pub.stream, armor_filter,
+ &outctrl->pub.afx );
+ }
+ }
+ if( outctrl->sec.newfname ) {
+ iobuf_close(outctrl->sec.stream);
+ outctrl->sec.stream = NULL;
+ gcry_free( outctrl->sec.fname );
+ outctrl->sec.fname = outctrl->sec.newfname;
+ outctrl->sec.newfname = NULL;
+
+ outctrl->sec.stream = iobuf_create( outctrl->sec.fname );
+ if( !outctrl->sec.stream ) {
+ log_error("can't create `%s': %s\n", outctrl->sec.newfname,
+ strerror(errno) );
+ return;
+ }
+ if( opt.armor ) {
+ outctrl->sec.afx.what = 5;
+ iobuf_push_filter( outctrl->sec.stream, armor_filter,
+ &outctrl->sec.afx );
+ }
+ }
+ pub_fname = outctrl->pub.fname; /* only for info output */
+ sec_fname = outctrl->sec.fname; /* only for info output */
+ assert( outctrl->pub.stream );
+ assert( outctrl->sec.stream );
+ }
+ else {
+ pub_fname = get_writable_keyblock_file( 0 );
+ sec_fname = get_writable_keyblock_file( 1 );
+ }
+
if( opt.verbose ) {
- tty_printf(_("writing public certificate to `%s'\n"), pub_fname );
- tty_printf(_("writing secret certificate to `%s'\n"), sec_fname );
+ log_info(_("writing public key to `%s'\n"), pub_fname );
+ log_info(_("writing secret key to `%s'\n"), sec_fname );
}
/* we create the packets as a tree of kbnodes. Because the structure
@@ -1016,24 +1704,31 @@ generate_keypair()
pub_root = make_comment_node("#"); delete_kbnode(pub_root);
sec_root = make_comment_node("#"); delete_kbnode(sec_root);
- if( both )
- rc = do_create( GCRY_PK_DSA, 1024, pub_root, sec_root,
- dek, s2k, &sk, expire, 1);
- else
- rc = do_create( algo, nbits, pub_root, sec_root,
- dek, s2k, &sk, expire, v4);
- if( !rc )
- write_uid(pub_root, uid );
- if( !rc )
- write_uid(sec_root, uid );
- if( !rc )
- rc = write_selfsig(pub_root, pub_root, sk);
- if( !rc )
- rc = write_selfsig(sec_root, pub_root, sk);
+ rc = do_create( get_parameter_algo( para, pKEYTYPE ),
+ get_parameter_uint( para, pKEYLENGTH ),
+ pub_root, sec_root,
+ get_parameter_dek( para, pPASSPHRASE_DEK ),
+ get_parameter_s2k( para, pPASSPHRASE_S2K ),
+ &sk,
+ get_parameter_u32( para, pKEYEXPIRE ) );
+ if( !rc && (s=get_parameter_value(para, pUSERID)) ) {
+ write_uid(pub_root, s );
+ if( !rc )
+ write_uid(sec_root, s );
+ if( !rc )
+ rc = write_selfsig(pub_root, pub_root, sk);
+ if( !rc )
+ rc = write_selfsig(sec_root, pub_root, sk);
+ }
- if( both ) {
- rc = do_create( algo, nbits, pub_root, sec_root,
- dek, s2k, NULL, expire, 1 );
+ if( get_parameter( para, pSUBKEYTYPE ) ) {
+ rc = do_create( get_parameter_algo( para, pSUBKEYTYPE ),
+ get_parameter_uint( para, pSUBKEYLENGTH ),
+ pub_root, sec_root,
+ get_parameter_dek( para, pPASSPHRASE_DEK ),
+ get_parameter_s2k( para, pPASSPHRASE_S2K ),
+ NULL,
+ get_parameter_u32( para, pSUBKEYEXPIRE ) );
if( !rc )
rc = write_keybinding(pub_root, pub_root, sk);
if( !rc )
@@ -1041,7 +1736,18 @@ generate_keypair()
}
- if( !rc ) {
+ if( !rc && outctrl->use_files ) { /* direct write to specified files */
+ rc = write_keyblock( outctrl->pub.stream, pub_root );
+ if( rc )
+ log_error("can't write public key: %s\n", gpg_errstr(rc) );
+ if( !rc ) {
+ rc = write_keyblock( outctrl->sec.stream, sec_root );
+ if( rc )
+ log_error("can't write secret key: %s\n", gpg_errstr(rc) );
+ }
+
+ }
+ else if( !rc ) { /* write to the standard keyrings */
KBPOS pub_kbpos;
KBPOS sec_kbpos;
int rc1 = -1;
@@ -1082,12 +1788,17 @@ generate_keypair()
else if( (rc=insert_keyblock( &sec_kbpos, sec_root )) )
log_error("can't write secret key: %s\n", gpg_errstr(rc) );
else {
- tty_printf(_("public and secret key created and signed.\n") );
- if( algo == GCRY_PK_DSA )
+ if( !opt.batch )
+ tty_printf(_("public and secret key created and signed.\n") );
+ if( !opt.batch
+ && get_parameter_algo( para, pKEYTYPE ) == GCRY_PK_DSA
+ && !get_parameter( para, pSUBKEYTYPE ) )
+ {
tty_printf(_("Note that this key cannot be used for "
"encryption. You may want to use\n"
"the command \"--edit-key\" to generate a "
"secondary key for this purpose.\n") );
+ }
}
if( !rc1 )
@@ -1096,18 +1807,20 @@ generate_keypair()
unlock_keyblock( &sec_kbpos );
}
-
- if( rc )
- tty_printf(_("Key generation failed: %s\n"), gpg_errstr(rc) );
+ if( rc ) {
+ if( opt.batch )
+ log_error("key generation failed: %s\n", gpg_errstr(rc) );
+ else
+ tty_printf(_("Key generation failed: %s\n"), gpg_errstr(rc) );
+ }
release_kbnode( pub_root );
release_kbnode( sec_root );
if( sk ) /* the unprotected secret key */
free_secret_key(sk);
- gcry_free(uid);
- gcry_free(dek);
- gcry_free(s2k);
- gcry_free(pub_fname);
- gcry_free(sec_fname);
+ if( !outctrl->use_files ) {
+ gcry_free(pub_fname);
+ gcry_free(sec_fname);
+ }
}
@@ -1121,7 +1834,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
int okay=0, rc=0;
KBNODE node;
PKT_secret_key *sk = NULL; /* this is the primary sk */
- int v4, algo;
+ int algo;
u32 expire;
unsigned nbits;
char *passphrase = NULL;
@@ -1146,8 +1859,10 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
"in future (time warp or clock problem)\n")
: _("key has been created %lu seconds "
"in future (time warp or clock problem)\n"), d );
- rc = GPGERR_TIME_CONFLICT;
- goto leave;
+ if( !opt.ignore_time_conflict ) {
+ rc = GPGERR_TIME_CONFLICT;
+ goto leave;
+ }
}
@@ -1170,7 +1885,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
goto leave;
- algo = ask_algo( &v4, 1 );
+ algo = ask_algo( 1 );
assert(algo);
nbits = ask_keysize( algo );
expire = ask_expire_interval();
@@ -1187,7 +1902,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
}
rc = do_create( algo, nbits, pub_keyblock, sec_keyblock,
- dek, s2k, NULL, expire, v4 );
+ dek, s2k, NULL, expire );
if( !rc )
rc = write_keybinding(pub_keyblock, pub_keyblock, sk);
if( !rc )
@@ -1207,3 +1922,20 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
return okay;
}
+/****************
+ * Write a keyblock to an output stream
+ */
+static int
+write_keyblock( IOBUF out, KBNODE node )
+{
+ for( ; node ; node = node->next ) {
+ int rc = build_packet( out, node->pkt );
+ if( rc ) {
+ log_error("build_packet(%d) failed: %s\n",
+ node->pkt->pkttype, gpg_errstr(rc) );
+ return GPGERR_WRITE_FILE;
+ }
+ }
+ return 0;
+}
+
diff --git a/g10/keyid.c b/g10/keyid.c
index ddaf0d5d3..14406b60b 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -1,5 +1,5 @@
/* keyid.c - jeyid and fingerprint handling
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -25,12 +25,14 @@
#include <errno.h>
#include <time.h>
#include <assert.h>
+
#include <gcrypt.h>
#include "util.h"
#include "main.h"
#include "packet.h"
#include "options.h"
#include "keydb.h"
+#include "i18n.h"
int
@@ -52,7 +54,7 @@ static GCRY_MD_HD
do_fingerprint_md( PKT_public_key *pk )
{
GCRY_MD_HD md;
- unsigned n;
+ unsigned int n;
unsigned int nn[GNUPG_MAX_NPKEY];
byte *pp[GNUPG_MAX_NPKEY];
int i;
@@ -339,7 +341,7 @@ expirestr_from_pk( PKT_public_key *pk )
time_t atime;
if( !pk->expiredate )
- return "never ";
+ return _("never ");
atime = pk->expiredate;
tp = gmtime( &atime );
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
@@ -354,7 +356,7 @@ expirestr_from_sk( PKT_secret_key *sk )
time_t atime;
if( !sk->expiredate )
- return "never ";
+ return _("never ");
atime = sk->expiredate;
tp = gmtime( &atime );
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
diff --git a/g10/keylist.c b/g10/keylist.c
index 0cefa2d56..751a61c9b 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -1,5 +1,5 @@
/* keylist.c
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -43,34 +43,24 @@ static void fingerprint( PKT_public_key *pk, PKT_secret_key *sk );
/****************
* List the keys
- * If NNAMES is 0; all available keys are listed
+ * If list is NULL, all available keys are listed
*/
void
-public_key_list( int nnames, char **names )
+public_key_list( STRLIST list )
{
- if( !nnames )
+ if( !list )
list_all(0);
- else { /* List by user id */
- STRLIST list = NULL;
- for( ; nnames ; nnames--, names++ )
- add_to_strlist( &list, *names );
+ else
list_one( list, 0 );
- free_strlist( list );
- }
}
void
-secret_key_list( int nnames, char **names )
+secret_key_list( STRLIST list )
{
- if( !nnames )
+ if( !list )
list_all(1);
- else { /* List by user id */
- STRLIST list = NULL;
- for( ; nnames ; nnames--, names++ )
- add_to_strlist( &list, *names );
+ else /* List by user id */
list_one( list, 1 );
- free_strlist( list );
- }
}
@@ -145,6 +135,7 @@ list_one( STRLIST names, int secret )
return;
}
do {
+ merge_keys_and_selfsig( keyblock );
list_keyblock( keyblock, 0 );
release_kbnode( keyblock );
} while( !get_pubkey_next( ctx, NULL, &keyblock ) );
@@ -155,7 +146,7 @@ list_one( STRLIST names, int secret )
static void
print_key_data( PKT_public_key *pk, u32 *keyid )
{
- int n = pubkey_get_npkey( pk->pubkey_algo );
+ int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
int i;
for(i=0; i < n; i++ ) {
@@ -211,21 +202,26 @@ list_keyblock( KBNODE keyblock, int secret )
sk = NULL;
keyid_from_pk( pk, keyid );
if( opt.with_colons ) {
- trustletter = query_trust_info( pk, NULL );
- if( trustletter == 'u' )
- ulti_hack = 1;
- printf("pub:%c:%u:%d:%08lX%08lX:%s:%s:",
- trustletter,
+ if ( opt.fast_list_mode ) {
+ fputs( "pub::", stdout );
+ trustletter = 0;
+ }
+ else {
+ trustletter = query_trust_info( pk, NULL );
+ if( trustletter == 'u' )
+ ulti_hack = 1;
+ printf("pub:%c:", trustletter );
+ }
+ printf("%u:%d:%08lX%08lX:%s:%s:",
nbits_from_pk( pk ),
pk->pubkey_algo,
(ulong)keyid[0],(ulong)keyid[1],
datestr_from_pk( pk ),
- pk->expiredate? strtimestamp(pk->expiredate):""
- );
+ pk->expiredate? strtimestamp(pk->expiredate):"" );
if( pk->local_id )
printf("%lu", pk->local_id );
putchar(':');
- if( pk->local_id )
+ if( pk->local_id && !opt.fast_list_mode )
putchar( get_ownertrust_info( pk->local_id ) );
putchar(':');
}
@@ -237,15 +233,22 @@ list_keyblock( KBNODE keyblock, int secret )
}
for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
- if( node->pkt->pkttype == PKT_USER_ID ) {
+ if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) {
if( any ) {
- if( opt.with_colons ) {
+ if ( opt.with_colons ) {
byte namehash[20];
if( pk && !ulti_hack ) {
- gcry_md_hash_buffer( GCRY_MD_RMD160, namehash,
- node->pkt->pkt.user_id->name,
- node->pkt->pkt.user_id->len );
+ if( node->pkt->pkt.user_id->photo ) {
+ gcry_md_hash_buffer( GCRY_MD_RMD160, namehash,
+ node->pkt->pkt.user_id->name,
+ node->pkt->pkt.user_id->len );
+ }
+ else {
+ gcry_md_hash_buffer( GCRY_MD_RMD160, namehash,
+ node->pkt->pkt.user_id->name,
+ node->pkt->pkt.user_id->len );
+ }
trustletter = query_trust_info( pk, namehash );
}
else
@@ -288,8 +291,13 @@ list_keyblock( KBNODE keyblock, int secret )
keyid_from_pk( pk2, keyid2 );
if( opt.with_colons ) {
- printf("sub:%c:%u:%d:%08lX%08lX:%s:%s:",
- trustletter,
+ if ( opt.fast_list_mode ) {
+ fputs( "sub::", stdout );
+ }
+ else {
+ printf("sub:%c:", trustletter );
+ }
+ printf("%u:%d:%08lX%08lX:%s:%s:",
nbits_from_pk( pk2 ),
pk2->pubkey_algo,
(ulong)keyid2[0],(ulong)keyid2[1],
@@ -303,11 +311,16 @@ list_keyblock( KBNODE keyblock, int secret )
putchar(':');
putchar('\n');
}
- else
- printf("sub %4u%c/%08lX %s\n", nbits_from_pk( pk2 ),
+ else {
+ printf("sub %4u%c/%08lX %s", nbits_from_pk( pk2 ),
pubkey_letter( pk2->pubkey_algo ),
(ulong)keyid2[1],
datestr_from_pk( pk2 ) );
+ if( pk2->expiredate ) {
+ printf(_(" [expires: %s]"), expirestr_from_pk( pk2 ) );
+ }
+ putchar('\n');
+ }
if( opt.fingerprint > 1 )
fingerprint( pk2, NULL );
if( opt.with_key_data )
@@ -346,6 +359,7 @@ list_keyblock( KBNODE keyblock, int secret )
else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;
int sigrc;
+ char *sigstr;
if( !any ) { /* no user id, (maybe a revocation follows)*/
if( sig->sig_class == 0x20 )
@@ -363,11 +377,11 @@ list_keyblock( KBNODE keyblock, int secret )
if( sig->sig_class == 0x20 || sig->sig_class == 0x28
|| sig->sig_class == 0x30 )
- fputs("rev", stdout);
+ sigstr = "rev";
else if( (sig->sig_class&~3) == 0x10 )
- fputs("sig", stdout);
+ sigstr = "sig";
else if( sig->sig_class == 0x18 )
- fputs("sig", stdout);
+ sigstr = "sig";
else {
if( opt.with_colons )
printf("sig::::::::::%02x:\n",sig->sig_class );
@@ -390,6 +404,7 @@ list_keyblock( KBNODE keyblock, int secret )
rc = 0;
sigrc = ' ';
}
+ fputs( sigstr, stdout );
if( opt.with_colons ) {
putchar(':');
if( sigrc != ' ' )
@@ -405,7 +420,7 @@ list_keyblock( KBNODE keyblock, int secret )
printf("[%s] ", gpg_errstr(rc) );
else if( sigrc == '?' )
;
- else {
+ else if ( !opt.fast_list_mode ) {
size_t n;
char *p = get_user_id( sig->keyid, &n );
if( opt.with_colons )
diff --git a/g10/ks-proto.h b/g10/ks-proto.h
index 2a3b2ddb1..6e8bbad0b 100644
--- a/g10/ks-proto.h
+++ b/g10/ks-proto.h
@@ -1,5 +1,5 @@
/* ks-proto.h
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
diff --git a/g10/main.h b/g10/main.h
index 621fc57de..711f5b8d2 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -1,5 +1,5 @@
/* main.h
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -73,7 +73,6 @@ int pubkey_get_nsig( int algo );
int pubkey_get_nenc( int algo );
unsigned int pubkey_nbits( int algo, MPI *pkey );
-
/*-- helptext.c --*/
void display_online_help( const char *keyword );
@@ -94,7 +93,7 @@ int clearsign_file( const char *fname, STRLIST locusr, const char *outfile );
/*-- sig-check.c --*/
int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig );
int check_key_signature2( KBNODE root, KBNODE node,
- int *is_selfsig, u32 *r_expire );
+ int *is_selfsig, u32 *r_expiredate, int *r_expired );
/*-- delkey.c --*/
int delete_key( const char *username, int secure );
@@ -105,7 +104,7 @@ void keyedit_menu( const char *username, STRLIST locusr, STRLIST cmds,
/*-- keygen.c --*/
u32 ask_expiredate(void);
-void generate_keypair(void);
+void generate_keypair( const char *fname );
int keygen_add_key_expire( PKT_signature *sig, void *opaque );
int keygen_add_std_prefs( PKT_signature *sig, void *opaque );
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
@@ -116,20 +115,20 @@ char *make_outfile_name( const char *iname );
char *ask_outfile_name( const char *name, size_t namelen );
int open_outfile( const char *iname, int mode, IOBUF *a );
IOBUF open_sigfile( const char *iname );
-void copy_options_file( const char *destdir );
+void try_make_homedir( const char *fname );
/*-- seskey.c --*/
void make_session_key( DEK *dek );
MPI encode_session_key( DEK *dek, unsigned nbits );
MPI encode_md_value( int pubkey_algo, GCRY_MD_HD md,
- int hash_algo, unsigned nbits );
+ int hash_algo, unsigned nbits, int v3compathack );
/*-- comment.c --*/
KBNODE make_comment_node( const char *s );
KBNODE make_mpi_comment_node( const char *s, MPI a );
/*-- import.c --*/
-int import_keys( const char *filename, int fast );
+void import_keys( char **fnames, int nnames, int fast );
int import_keys_stream( IOBUF inp, int fast );
int collapse_uids( KBNODE *keyblock );
@@ -137,20 +136,27 @@ int collapse_uids( KBNODE *keyblock );
int export_pubkeys( STRLIST users, int onlyrfc );
int export_pubkeys_stream( IOBUF out, STRLIST users, int onlyrfc );
int export_seckeys( STRLIST users );
+int export_secsubkeys( STRLIST users );
/* dearmor.c --*/
int dearmor_file( const char *fname );
int enarmor_file( const char *fname );
/*-- revoke.c --*/
+struct revocation_reason_info;
int gen_revoke( const char *uname );
+int revocation_reason_build_cb( PKT_signature *sig, void *opaque );
+struct revocation_reason_info *
+ ask_revocation_reason( int key_rev, int cert_rev, int hint );
+void release_revocation_reason_info( struct revocation_reason_info *reason );
/*-- keylist.c --*/
-void public_key_list( int nnames, char **names );
-void secret_key_list( int nnames, char **names );
+void public_key_list( STRLIST list );
+void secret_key_list( STRLIST list );
/*-- verify.c --*/
int verify_signatures( int nfiles, char **files );
+int verify_files( int nfiles, char **files );
/*-- decrypt.c --*/
int decrypt_message( const char *filename );
diff --git a/g10/mainproc.c b/g10/mainproc.c
index f2637340c..09c35db21 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -1,5 +1,5 @@
/* mainproc.c - handle packets
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -160,11 +160,11 @@ add_signature( CTX c, PACKET *pkt )
if( pkt->pkttype == PKT_SIGNATURE && !c->list ) {
/* This is the first signature for the following datafile.
- * gpg does not write such packets; instead it always uses
+ * GPG does not write such packets; instead it always uses
* onepass-sig packets. The drawback of PGP's method
* of prepending the signature to the data is
* that it is not possible to make a signature from data read
- * from stdin. (gpg is able to read PGP stuff anyway.) */
+ * from stdin. (GPG is able to read PGP stuff anyway.) */
node = new_kbnode( pkt );
c->list = node;
return 1;
@@ -224,10 +224,14 @@ proc_pubkey_enc( CTX c, PACKET *pkt )
|| is_RSA(enc->pubkey_algo) ) {
if ( !c->dek && ((!enc->keyid[0] && !enc->keyid[1])
|| !seckey_available( enc->keyid )) ) {
- c->dek = gcry_xmalloc_secure( sizeof *c->dek );
- if( (result = get_session_key( enc, c->dek )) ) {
- /* error: delete the DEK */
- gcry_free(c->dek); c->dek = NULL;
+ if( opt.list_only )
+ result = -1;
+ else {
+ c->dek = gcry_xmalloc_secure( sizeof *c->dek );
+ if( (result = get_session_key( enc, c->dek )) ) {
+ /* error: delete the DEK */
+ gcry_free(c->dek); c->dek = NULL;
+ }
}
}
else
@@ -267,6 +271,8 @@ print_failed_pkenc( struct kidlist_item *list )
PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
const char *algstr = gcry_pk_algo_name( list->pubkey_algo );
+ if( !algstr )
+ algstr = "[?]";
pk->pubkey_algo = list->pubkey_algo;
if( !get_pubkey( pk, list->kid ) ) {
size_t n;
@@ -309,10 +315,14 @@ proc_encrypted( CTX c, PACKET *pkt )
print_failed_pkenc( c->failed_pkenc );
+ write_status( STATUS_BEGIN_DECRYPTION );
+
/*log_debug("dat: %sencrypted data\n", c->dek?"":"conventional ");*/
- if( !c->dek && !c->last_was_session_key ) {
+ if( opt.list_only )
+ result = -1;
+ else if( !c->dek && !c->last_was_session_key ) {
/* assume this is old conventional encrypted data
- * Actually we should use IDEA and MD5 in this case, but becuase
+ * Actually we should use IDEA and MD5 in this case, but because
* IDEA is patented we can't do so */
c->dek = passphrase_to_dek( NULL, 0,
opt.def_cipher_algo ? opt.def_cipher_algo
@@ -322,6 +332,7 @@ proc_encrypted( CTX c, PACKET *pkt )
result = GPGERR_NO_SECKEY;
if( !result )
result = decrypt_data( c, pkt->pkt.encrypted, c->dek );
+
gcry_free(c->dek); c->dek = NULL;
if( result == -1 )
;
@@ -339,11 +350,12 @@ proc_encrypted( CTX c, PACKET *pkt )
else {
write_status( STATUS_DECRYPTION_FAILED );
log_error(_("decryption failed: %s\n"), gpg_errstr(result));
- /* Hmmm: does this work when we have encrypted using a multiple
+ /* Hmmm: does this work when we have encrypted using multiple
* ways to specify the session key (symmmetric and PK)*/
}
free_packet(pkt);
c->last_was_session_key = 0;
+ write_status( STATUS_END_DECRYPTION );
}
@@ -360,7 +372,8 @@ proc_plaintext( CTX c, PACKET *pkt )
else if( opt.verbose )
log_info(_("original file name='%.*s'\n"), pt->namelen, pt->name);
free_md_filter_context( &c->mfx );
- if( !(c->mfx.md = gcry_md_open( 0, 0)) )
+ c->mfx.md = gcry_md_open( 0, 0);
+ if( !c->mfx.md )
BUG();
/* fixme: we may need to push the textfilter if we have sigclass 1
* and no armoring - Not yet tested
@@ -372,8 +385,7 @@ proc_plaintext( CTX c, PACKET *pkt )
for(n=c->list; n; n = n->next ) {
if( n->pkt->pkttype == PKT_ONEPASS_SIG ) {
if( n->pkt->pkt.onepass_sig->digest_algo ) {
- gcry_md_enable( c->mfx.md,
- n->pkt->pkt.onepass_sig->digest_algo );
+ gcry_md_enable( c->mfx.md, n->pkt->pkt.onepass_sig->digest_algo );
if( !any && n->pkt->pkt.onepass_sig->digest_algo
== GCRY_MD_MD5 )
only_md5 = 1;
@@ -398,24 +410,28 @@ proc_plaintext( CTX c, PACKET *pkt )
clearsig = 1;
}
}
- if( !any ) { /* no onepass sig packet: enable all standard algos */
+
+ if( !any && !opt.skip_verify ) {
+ /* no onepass sig packet: enable all standard algos */
gcry_md_enable( c->mfx.md, GCRY_MD_RMD160 );
gcry_md_enable( c->mfx.md, GCRY_MD_SHA1 );
gcry_md_enable( c->mfx.md, GCRY_MD_MD5 );
}
- if( only_md5 ) {
+ if( opt.pgp2_workarounds && only_md5 && !opt.skip_verify ) {
/* This is a kludge to work around a bug in pgp2. It does only
* catch those mails which are armored. To catch the non-armored
* pgp mails we could see whether there is the signature packet
* in front of the plaintext. If someone needs this, send me a patch.
*/
- if( !(c->mfx.md2 = gcry_md_open( GCRY_MD_MD5, 0)) )
+ c->mfx.md2 = gcry_md_open( GCRY_MD_MD5, 0);
+ if( !c->mfx.md2 )
BUG();
}
- #if 0
- #warning md_start_debug is enabled
- md_start_debug( c->mfx.md, "verify" );
- #endif
+ if ( DBG_HASHING ) {
+ gcry_md_start_debug( c->mfx.md, "verify" );
+ if ( c->mfx.md2 )
+ gcry_md_start_debug( c->mfx.md2, "verify2" );
+ }
rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig );
if( rc == GPGERR_CREATE_FILE && !c->sigs_only) {
/* can't write output but we hash it anyway to
@@ -494,12 +510,17 @@ do_check_sig( CTX c, KBNODE node, int *is_selfsig )
* in canonical mode ??? (calculating both modes???) */
if( c->mfx.md ) {
md = gcry_md_copy( c->mfx.md );
- if( c->mfx.md2 )
+ if( !md )
+ BUG();
+ if( c->mfx.md2 ) {
md2 = gcry_md_copy( c->mfx.md2 );
+ if( !md2 )
+ BUG();
+ }
}
else { /* detached signature */
- log_debug("Do we really need this here?");
- md = gcry_md_open( 0, 0 ); /* signature_check() will enable the md*/
+ log_debug("Do we really need this here?");
+ md = gcry_md_open( 0, 0 ); /* signature_check() will enable the md*/
md2 = gcry_md_open( 0, 0 );
if( !md || !md2 )
BUG();
@@ -513,6 +534,11 @@ do_check_sig( CTX c, KBNODE node, int *is_selfsig )
|| c->list->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
return check_key_signature( c->list, node, is_selfsig );
}
+ else if( sig->sig_class == 0x20 ) {
+ log_info(_("standalone revocation - "
+ "use \"gpg --import\" to apply\n"));
+ return GPGERR_NOT_PROCESSED;
+ }
else {
log_error("invalid root packet for sigclass %02x\n",
sig->sig_class);
@@ -540,8 +566,12 @@ print_userid( PACKET *pkt )
printf("ERROR: unexpected packet type %d", pkt->pkttype );
return;
}
- print_string( stdout, pkt->pkt.user_id->name, pkt->pkt.user_id->len,
- opt.with_colons );
+ if( opt.with_colons )
+ print_string( stdout, pkt->pkt.user_id->name,
+ pkt->pkt.user_id->len, ':');
+ else
+ print_utf8_string( stdout, pkt->pkt.user_id->name,
+ pkt->pkt.user_id->len );
}
@@ -644,11 +674,13 @@ list_node( CTX c, KBNODE node )
keyid_from_pk( pk, keyid );
if( mainkey ) {
c->local_id = pk->local_id;
- c->trustletter = query_trust_info( pk, NULL );
+ c->trustletter = opt.fast_list_mode?
+ 0 : query_trust_info( pk, NULL );
}
- printf("%s:%c:%u:%d:%08lX%08lX:%s:%s:",
- mainkey? "pub":"sub",
- c->trustletter,
+ printf("%s:", mainkey? "pub":"sub" );
+ if( c->trustletter )
+ putchar( c->trustletter );
+ printf(":%u:%d:%08lX%08lX:%s:%s:",
nbits_from_pk( pk ),
pk->pubkey_algo,
(ulong)keyid[0],(ulong)keyid[1],
@@ -657,7 +689,7 @@ list_node( CTX c, KBNODE node )
if( c->local_id )
printf("%lu", c->local_id );
putchar(':');
- if( c->local_id )
+ if( c->local_id && !opt.fast_list_mode )
putchar( get_ownertrust_info( c->local_id ) );
putchar(':');
if( node->next && node->next->pkt->pkttype == PKT_RING_TRUST) {
@@ -675,6 +707,7 @@ list_node( CTX c, KBNODE node )
pubkey_letter( pk->pubkey_algo ),
(ulong)keyid_from_pk( pk, NULL ),
datestr_from_pk( pk ) );
+
if( mainkey ) {
/* and now list all userids with their signatures */
for( node = node->next; node; node = node->next ) {
@@ -717,6 +750,10 @@ list_node( CTX c, KBNODE node )
}
}
}
+ else if( pk->expiredate ) { /* of subkey */
+ printf(_(" [expires: %s]"), expirestr_from_pk( pk ) );
+ }
+
if( !any )
putchar('\n');
if( !mainkey && opt.fingerprint > 1 )
@@ -847,7 +884,7 @@ list_node( CTX c, KBNODE node )
if( opt.with_colons )
putchar(':');
}
- else {
+ else if( !opt.fast_list_mode ) {
p = get_user_id( sig->keyid, &n );
print_string( stdout, p, n, opt.with_colons );
gcry_free(p);
@@ -861,6 +898,7 @@ list_node( CTX c, KBNODE node )
}
+
int
proc_packets( void *anchor, IOBUF a )
{
@@ -873,6 +911,8 @@ proc_packets( void *anchor, IOBUF a )
return rc;
}
+
+
int
proc_signature_packets( void *anchor, IOBUF a,
STRLIST signedfiles, const char *sigfilename )
@@ -1027,7 +1067,7 @@ static int
check_sig_and_print( CTX c, KBNODE node )
{
PKT_signature *sig = node->pkt->pkt.signature;
- const char *tstr;
+ const char *astr, *tstr;
int rc;
if( opt.skip_verify ) {
@@ -1036,12 +1076,12 @@ check_sig_and_print( CTX c, KBNODE node )
}
tstr = asctimestamp(sig->timestamp);
+ astr = gcry_pk_algo_name( sig->pubkey_algo );
log_info(_("Signature made %.*s using %s key ID %08lX\n"),
- (int)strlen(tstr), tstr, gcry_pk_algo_name( sig->pubkey_algo ),
- (ulong)sig->keyid[1] );
+ (int)strlen(tstr), tstr, astr? astr: "?", (ulong)sig->keyid[1] );
rc = do_check_sig(c, node, NULL );
- if( rc == GPGERR_NO_PUBKEY && opt.keyserver_name ) {
+ if( rc == GPGERR_NO_PUBKEY && opt.keyserver_name && opt.auto_key_retrieve) {
if( !hkp_ask_import( sig->keyid ) )
rc = do_check_sig(c, node, NULL );
}
@@ -1121,7 +1161,8 @@ check_sig_and_print( CTX c, KBNODE node )
buf[16] = 0;
write_status_text( STATUS_NO_PUBKEY, buf );
}
- log_error(_("Can't check signature: %s\n"), gpg_errstr(rc) );
+ if( rc != GPGERR_NOT_PROCESSED )
+ log_error(_("Can't check signature: %s\n"), gpg_errstr(rc) );
}
return rc;
}
@@ -1136,7 +1177,7 @@ proc_tree( CTX c, KBNODE node )
KBNODE n1;
int rc;
- if( opt.list_packets )
+ if( opt.list_packets || opt.list_only )
return;
c->local_id = 0;
@@ -1155,7 +1196,7 @@ proc_tree( CTX c, KBNODE node )
if( !c->have_data ) {
free_md_filter_context( &c->mfx );
/* prepare to create all requested message digests */
- if( !(c->mfx.md = gcry_md_open(0, 0)) )
+ if ( !(c->mfx.md = gcry_md_open(0, 0)) )
BUG();
/* fixme: why looking for the signature packet and not 1passpacket*/
@@ -1163,13 +1204,16 @@ proc_tree( CTX c, KBNODE node )
gcry_md_enable( c->mfx.md, n1->pkt->pkt.signature->digest_algo);
}
/* ask for file and hash it */
- if( c->sigs_only )
+ if( c->sigs_only ) {
rc = hash_datafiles( c->mfx.md, NULL,
c->signed_data, c->sigfilename,
n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 );
- else
+ }
+ else {
rc = ask_for_detached_datafile( c->mfx.md, c->mfx.md2,
- iobuf_get_fname(c->iobuf), 0 );
+ iobuf_get_fname(c->iobuf),
+ n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 );
+ }
if( rc ) {
log_error("can't hash datafile: %s\n", gpg_errstr(rc));
return;
@@ -1182,15 +1226,22 @@ proc_tree( CTX c, KBNODE node )
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;
- if( !c->have_data ) {
+ if( sig->sig_class != 0x00 && sig->sig_class != 0x01 )
+ log_info(_("standalone signature of class 0x%02x\n"),
+ sig->sig_class);
+ else if( !c->have_data ) {
/* detached signature */
free_md_filter_context( &c->mfx );
- if( !(c->mfx.md = gcry_md_open(sig->digest_algo, 0)) )
+ c->mfx.md = gcry_md_open(sig->digest_algo, 0);
+ if ( !c->mfx.md )
BUG();
- if( sig->digest_algo == GCRY_MD_MD5
- && is_RSA( sig->pubkey_algo ) ) {
+ if( !opt.pgp2_workarounds )
+ ;
+ else if( sig->digest_algo == GCRY_MD_MD5
+ && is_RSA( sig->pubkey_algo ) ) {
/* enable a workaround for a pgp2 bug */
- if( !(c->mfx.md2 = gcry_md_open( GCRY_MD_MD5, 0 )) )
+ c->mfx.md2 = gcry_md_open( GCRY_MD_MD5, 0 );
+ if ( !c->mfx.md2 )
BUG();
}
else if( sig->digest_algo == GCRY_MD_SHA1
@@ -1198,9 +1249,11 @@ proc_tree( CTX c, KBNODE node )
&& sig->sig_class == 0x01 ) {
/* enable the workaround also for pgp5 when the detached
* signature has been created in textmode */
- if( !(c->mfx.md2 = gcry_md_open( sig->digest_algo, 0 )) )
+ c->mfx.md2 = gcry_md_open( sig->digest_algo, 0 );
+ if ( !c->mfx.md2 )
BUG();
}
+ #if 0 /* workaround disabled */
/* Here we have another hack to work around a pgp 2 bug
* It works by not using the textmode for detached signatures;
* this will let the first signature check (on md) fail
@@ -1208,14 +1261,18 @@ proc_tree( CTX c, KBNODE node )
* then produce the "correct" hash. This is very, very ugly
* hack but it may help in some cases (and break others)
*/
- if( c->sigs_only )
+ /* c->mfx.md2? 0 :(sig->sig_class == 0x01) */
+ #endif
+ if( c->sigs_only ) {
rc = hash_datafiles( c->mfx.md, c->mfx.md2,
c->signed_data, c->sigfilename,
- c->mfx.md2? 0 :(sig->sig_class == 0x01) );
- else
+ (sig->sig_class == 0x01) );
+ }
+ else {
rc = ask_for_detached_datafile( c->mfx.md, c->mfx.md2,
- iobuf_get_fname(c->iobuf),
- c->mfx.md2? 0 :(sig->sig_class == 0x01) );
+ iobuf_get_fname(c->iobuf),
+ (sig->sig_class == 0x01) );
+ }
if( rc ) {
log_error("can't hash datafile: %s\n", gpg_errstr(rc));
return;
diff --git a/g10/mdfilter.c b/g10/mdfilter.c
index abb55d8c1..c41ad857e 100644
--- a/g10/mdfilter.c
+++ b/g10/mdfilter.c
@@ -1,5 +1,5 @@
/* mdfilter.c - filter data and calculate a message digest
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 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 <gcrypt.h>
#include "util.h"
#include "filter.h"
diff --git a/g10/misc.c b/g10/misc.c
index d3c01f4ef..e7bd8fac6 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -1,5 +1,5 @@
/* misc.c - miscellaneous functions
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -23,7 +23,6 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-#include <assert.h>
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
#include <asm/sysinfo.h>
#include <asm/unistd.h>
@@ -32,6 +31,8 @@
#include <sys/time.h>
#include <sys/resource.h>
#endif
+#include <assert.h>
+
#include <gcrypt.h>
#include "util.h"
#include "main.h"
@@ -41,7 +42,6 @@
#define MAX_EXTERN_MPI_BITS 16384
-
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
#warning using trap_unaligned
static int
@@ -246,6 +246,7 @@ mpi_print( FILE *fp, MPI a, int mode )
}
+
u16
checksum_u16( unsigned n )
{
@@ -289,7 +290,6 @@ checksum_mpi( MPI a )
}
-
u32
buffer_to_u32( const byte *buffer )
{
@@ -359,6 +359,7 @@ print_digest_algo_note( int algo )
}
+
/****************
* Wrapper around the libgcrypt function with addional checks on
* openPGP contrainst for the algo ID.
diff --git a/g10/openfile.c b/g10/openfile.c
index 0b768fe5e..47dca0e76 100644
--- a/g10/openfile.c
+++ b/g10/openfile.c
@@ -1,5 +1,5 @@
/* openfile.c
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -24,6 +24,9 @@
#include <string.h>
#include <assert.h>
#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <unistd.h>
#include "util.h"
#include <gcrypt.h>
@@ -39,13 +42,16 @@
#define SKELEXT ".skel"
#endif
-
#ifdef HAVE_DRIVE_LETTERS
#define CMP_FILENAME(a,b) stricmp( (a), (b) )
#else
#define CMP_FILENAME(a,b) strcmp( (a), (b) )
#endif
+#ifdef MKDIR_TAKES_ONE_ARG
+# undef mkdir
+# define mkdir(a,b) mkdir(a)
+#endif
/* FIXME: Implement opt.interactive. */
@@ -78,7 +84,6 @@ overwrite_filep( const char *fname )
}
-
/****************
* Strip know extensions from iname and return a newly allocated
* filename. Return NULL if we can't do that.
@@ -176,7 +181,7 @@ open_outfile( const char *iname, int mode, IOBUF *a )
name = opt.outfile;
else {
#ifdef USE_ONLY_8DOT3
- /* It is quite common for DOS system to have only one dot in a
+ /* It is quite common DOS system to have only one dot in a
* a filename So if we have something like this, we simple
* replace the suffix execpt in cases where the suffix is
* larger than 3 characters and not the same as.
@@ -195,7 +200,7 @@ open_outfile( const char *iname, int mode, IOBUF *a )
strcpy(dot, newsfx );
}
else if( dot && !dot[1] ) /* don't duplicate a dot */
- strcat( dot, newsfx+1 );
+ strcpy( dot, newsfx+1 );
else
strcat( buf, newsfx );
#else
@@ -253,7 +258,7 @@ open_sigfile( const char *iname )
/****************
* Copy the option file skeleton to the given directory.
*/
-void
+static void
copy_options_file( const char *destdir )
{
const char *datadir = GNUPG_DATADIR;
@@ -296,3 +301,23 @@ copy_options_file( const char *destdir )
gcry_free(fname);
}
+
+void
+try_make_homedir( const char *fname )
+{
+ if( opt.dry_run )
+ return;
+ if( strlen(fname) >= 7
+ && !strcmp(fname+strlen(fname)-7, "/.gnupg" ) ) {
+ if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
+ log_fatal( _("%s: can't create directory: %s\n"),
+ fname, strerror(errno) );
+ else if( !opt.quiet )
+ log_info( _("%s: directory created\n"), fname );
+ copy_options_file( fname );
+ log_info(_("you have to start GnuPG again, "
+ "so it can read the new options file\n") );
+ gpg_exit(1);
+ }
+}
+
diff --git a/g10/options.h b/g10/options.h
index cbe6c24e0..79b6bcd55 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -1,5 +1,5 @@
/* options.h
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -28,11 +28,12 @@
struct {
int verbose;
int quiet;
- unsigned debug;
+ unsigned int debug;
int armor;
int compress;
char *outfile;
int dry_run;
+ int list_only;
int textmode;
int batch; /* run in batch mode */
int answer_yes; /* answer yes on most questions */
@@ -63,7 +64,9 @@ struct {
int compress_sigs;
int always_trust;
int rfc1991;
- unsigned emulate_bugs; /* bug emulation flags EMUBUG_xxxx */
+ int rfc2440;
+ int pgp2_workarounds;
+ unsigned int emulate_bugs; /* bug emulation flags EMUBUG_xxxx */
int shm_coprocess;
const char *set_filename;
const char *comment_string;
@@ -83,9 +86,17 @@ struct {
int allow_non_selfsigned_uid;
int no_literal;
ulong set_filesize;
+ int honor_http_proxy;
+ int fast_list_mode;
+ int ignore_time_conflict;
+ int command_fd;
+ int auto_key_retrieve;
} opt;
+#define EMUBUG_3DESS2K 2
+#define EMUBUG_MDENCODE 4
+
#define DBG_PACKET_VALUE 1 /* debug packet reading/writing */
#define DBG_MPI_VALUE 2 /* debug mpi details */
#define DBG_CIPHER_VALUE 4 /* debug cipher handling */
@@ -96,6 +107,7 @@ struct {
#define DBG_CACHE_VALUE 64 /* debug the cacheing */
#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
#define DBG_TRUST_VALUE 256 /* debug the trustdb */
+#define DBG_HASHING_VALUE 512 /* debug hashing operations */
#define DBG_PACKET (opt.debug & DBG_PACKET_VALUE)
@@ -104,6 +116,6 @@ struct {
#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
#define DBG_TRUST (opt.debug & DBG_TRUST_VALUE)
#define DBG_CIPHER (opt.debug & DBG_CIPHER_VALUE)
-
+#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
#endif /*GPG_OPTIONS_H*/
diff --git a/g10/packet.h b/g10/packet.h
index 02f701799..f6da15e17 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -1,5 +1,5 @@
/* packet.h - packet read/write stuff
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -54,14 +54,16 @@ typedef enum {
PKT_USER_ID =13, /* user id packet */
PKT_PUBLIC_SUBKEY =14, /* public subkey (OpenPGP) */
PKT_OLD_COMMENT =16, /* comment packet from an OpenPGP draft */
+ PKT_PHOTO_ID =17, /* PGP's photo ID */
+ PKT_ENCRYPTED_MDC =18, /* integrity protected encrypted data */
+ PKT_MDC =19, /* manipulaion detection code packet */
PKT_COMMENT =61, /* new comment packet (private) */
- PKT_ENCRYPTED_MDC =62, /* test: encrypted data with MDC */
} pkttype_t;
typedef struct packet_struct PACKET;
typedef struct {
- byte mode;
+ int mode;
byte hash_algo;
byte salt[8];
u32 count;
@@ -105,7 +107,7 @@ typedef struct {
byte version;
byte sig_class; /* sig classification, append for MD calculation*/
byte pubkey_algo; /* algorithm used for public key scheme */
- /* (PUBKEY_ALGO_xxx) */
+ /* (GCRY_PK_xxx) */
byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */
byte *hashed_data; /* all subpackets with hashed data (v4 only) */
byte *unhashed_data; /* ditto for unhashed data */
@@ -165,6 +167,8 @@ typedef struct {
ulong stored_at; /* the stream offset where it was stored
* by build-packet */
int len; /* length of the name */
+ char *photo; /* if this is not NULL, the packet is a photo ID */
+ int photolen; /* and the length of the photo */
char name[1];
} PKT_user_id;
@@ -178,11 +182,15 @@ typedef struct {
typedef struct {
u32 len; /* length of encrypted data */
byte new_ctb; /* uses a new CTB */
- byte mdc_method; /* test: > 0: this is is an encrypted_mdc packet */
+ byte mdc_method; /* > 0: integrity protected encrypted data packet */
IOBUF buf; /* IOBUF reference */
} PKT_encrypted;
typedef struct {
+ byte hash[20];
+} PKT_mdc;
+
+typedef struct {
unsigned int trustval;
} PKT_ring_trust;
@@ -212,6 +220,7 @@ struct packet_struct {
PKT_user_id *user_id; /* PKT_USER_ID */
PKT_compressed *compressed; /* PKT_COMPRESSED */
PKT_encrypted *encrypted; /* PKT_ENCRYPTED[_MDC] */
+ PKT_mdc *mdc; /* PKT_MDC */
PKT_ring_trust *ring_trust; /* PKT_RING_TRUST */
PKT_plaintext *plaintext; /* PKT_PLAINTEXT */
} pkt;
@@ -246,6 +255,7 @@ typedef enum {
SIGSUBPKT_POLICY =26, /* policy URL */
SIGSUBPKT_KEY_FLAGS =27, /* key flags */
SIGSUBPKT_SIGNERS_UID =28, /* signer's user id */
+ SIGSUBPKT_REVOC_REASON =29, /* reason for revocation */
SIGSUBPKT_PRIV_ADD_SIG =101,/* signatur is also valid for this uid */
SIGSUBPKT_FLAG_CRITICAL=128
@@ -339,7 +349,6 @@ int handle_compressed( void *ctx, PKT_compressed *cd,
/*-- encr-data.c --*/
int decrypt_data( void *ctx, PKT_encrypted *ed, DEK *dek );
-int encrypt_data( PKT_encrypted *ed, DEK *dek );
/*-- plaintext.c --*/
int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 886ba4a25..867f93d1d 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -1,5 +1,5 @@
/* parse-packet.c - read packets
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -24,10 +24,10 @@
#include <string.h>
#include <assert.h>
+#include <gcrypt.h>
#include "packet.h"
#include "iobuf.h"
#include "util.h"
-#include <gcrypt.h>
#include "filter.h"
#include "options.h"
#include "main.h"
@@ -59,6 +59,8 @@ static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
byte *hdr, int hdrlen, PACKET *packet );
static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
+static int parse_photo_id( IOBUF inp, int pkttype, unsigned long pktlen,
+ PACKET *packet );
static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen,
@@ -69,6 +71,8 @@ static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet, int new_ctb );
static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet, int new_ctb);
+static int parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen,
+ PACKET *packet, int new_ctb);
static unsigned short
read_16(IOBUF inp)
@@ -415,6 +419,10 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
case PKT_USER_ID:
rc = parse_user_id(inp, pkttype, pktlen, pkt );
break;
+ case PKT_PHOTO_ID:
+ pkt->pkttype = pkttype = PKT_USER_ID; /* must fix it */
+ rc = parse_photo_id(inp, pkttype, pktlen, pkt);
+ break;
case PKT_OLD_COMMENT:
case PKT_COMMENT:
rc = parse_comment(inp, pkttype, pktlen, pkt);
@@ -433,6 +441,9 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
case PKT_ENCRYPTED_MDC:
rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb );
break;
+ case PKT_MDC:
+ rc = parse_mdc(inp, pkttype, pktlen, pkt, new_ctb );
+ break;
default:
skip_packet(inp, pkttype, pktlen);
break;
@@ -803,6 +814,13 @@ dump_sig_subpkt( int hashed, int type, int critical,
case SIGSUBPKT_SIGNERS_UID:
p = "signer's user ID";
break;
+ case SIGSUBPKT_REVOC_REASON:
+ if( length ) {
+ printf("revocation reason 0x%02x (", *buffer );
+ print_string( stdout, buffer+1, length-1, ')' );
+ p = ")";
+ }
+ break;
case SIGSUBPKT_PRIV_ADD_SIG:
p = "signs additional user ID";
break;
@@ -840,6 +858,10 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
if( n < 8 ) /* minimum length needed */
break;
return 0;
+ case SIGSUBPKT_REVOC_REASON:
+ if( !n )
+ break;
+ return 0;
case SIGSUBPKT_PREF_SYM:
case SIGSUBPKT_PREF_HASH:
case SIGSUBPKT_PREF_COMPR:
@@ -877,7 +899,7 @@ can_handle_critical( const byte *buffer, size_t n, int type )
case SIGSUBPKT_PREF_COMPR:
return 1;
- case SIGSUBPKT_POLICY: /* Is enough to show the policy? */
+ case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */
default:
return 0;
}
@@ -896,8 +918,12 @@ enum_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype,
int seq = 0;
int reqseq = start? *start: 0;
- if( !buffer || reqseq == -1 )
- return NULL;
+ if( !buffer || reqseq == -1 ) {
+ /* return some value different from NULL to indicate that
+ * there is no crtitical bit we do not understand. The caller
+ * will never use the value. Yes I know, it is an ugly hack */
+ return reqtype == SIGSUBPKT_TEST_CRITICAL? (const byte*)&buffer : NULL;
+ }
buflen = (*buffer << 8) | buffer[1];
buffer += 2;
while( buflen ) {
@@ -1131,8 +1157,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
unknown_pubkey_warning( sig->pubkey_algo );
/* we store the plain material in data[0], so that we are able
* to write it back with build_packet() */
- sig->data[0] = gcry_mpi_set_opaque(NULL,
- read_rest(inp, pktlen), pktlen*8 );
+ sig->data[0] = mpi_set_opaque(NULL, read_rest(inp, pktlen), pktlen );
pktlen = 0;
}
else {
@@ -1317,6 +1342,24 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
sk->protect.algo = iobuf_get_noeof(inp); pktlen--;
sk->protect.s2k.mode = iobuf_get_noeof(inp); pktlen--;
sk->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
+ /* check for the special GNU extension */
+ if( is_v4 && sk->protect.s2k.mode == 101 ) {
+ for(i=0; i < 4 && pktlen; i++, pktlen-- )
+ temp[i] = iobuf_get_noeof(inp);
+ if( i < 4 || memcmp( temp, "GNU", 3 ) ) {
+ if( list_mode )
+ printf( "\tunknown S2K %d\n",
+ sk->protect.s2k.mode );
+ rc = GPGERR_INVALID_PACKET;
+ goto leave;
+ }
+ /* here we know that it is a gnu extension
+ * What follows is the GNU protection mode:
+ * All values have special meanings
+ * and they are mapped in the mode with a base of 1000.
+ */
+ sk->protect.s2k.mode = 1000 + temp[3];
+ }
switch( sk->protect.s2k.mode ) {
case 1:
case 3:
@@ -1332,10 +1375,13 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
break;
case 3: if( list_mode ) printf( "\titer+salt S2K" );
break;
+ case 1001: if( list_mode ) printf( "\tgnu-dummy S2K" );
+ break;
default:
if( list_mode )
- printf( "\tunknown S2K %d\n",
- sk->protect.s2k.mode );
+ printf( "\tunknown %sS2K %d\n",
+ sk->protect.s2k.mode < 1000? "":"GNU ",
+ sk->protect.s2k.mode );
rc = GPGERR_INVALID_PACKET;
goto leave;
}
@@ -1388,6 +1434,9 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
default:
sk->protect.ivlen = 8;
}
+ if( sk->protect.s2k.mode == 1001 )
+ sk->protect.ivlen = 0;
+
if( pktlen < sk->protect.ivlen ) {
rc = GPGERR_INVALID_PACKET;
goto leave;
@@ -1408,10 +1457,15 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
* If the user is so careless, not to protect his secret key,
* we can assume, that he operates an open system :=(.
* So we put the key into secure memory when we unprotect it. */
- if( is_v4 && sk->is_protected ) {
+ if( sk->protect.s2k.mode == 1001 ) {
+ /* better set some dummy stuff here */
+ sk->skey[npkey] = mpi_set_opaque(NULL, gcry_xstrdup("dummydata"), 10);
+ pktlen = 0;
+ }
+ else if( is_v4 && sk->is_protected ) {
/* ugly; the length is encrypted too, so we read all
* stuff up to the end of the packet into the first
- * skey element (which is the one indexed by npkey) */
+ * skey element */
sk->skey[npkey] = gcry_mpi_set_opaque(NULL,
read_rest(inp, pktlen), pktlen*8 );
pktlen = 0;
@@ -1475,6 +1529,8 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
packet->pkt.user_id = gcry_xmalloc(sizeof *packet->pkt.user_id + pktlen);
packet->pkt.user_id->len = pktlen;
+ packet->pkt.user_id->photo = NULL;
+ packet->pkt.user_id->photolen = 0;
p = packet->pkt.user_id->name;
for( ; pktlen; pktlen--, p++ )
*p = iobuf_get_noeof(inp);
@@ -1496,6 +1552,31 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
}
+/****************
+ * PGP generates a packet of type 17. We assume this is a photo ID and
+ * simply store it here as a comment packet.
+ */
+static int
+parse_photo_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
+{
+ byte *p;
+
+ packet->pkt.user_id = gcry_xmalloc(sizeof *packet->pkt.user_id + 30);
+ sprintf( packet->pkt.user_id->name, "[image of size %lu]", pktlen );
+ packet->pkt.user_id->len = strlen(packet->pkt.user_id->name);
+
+ packet->pkt.user_id->photo = gcry_xmalloc(sizeof *packet->pkt.user_id + pktlen);
+ packet->pkt.user_id->photolen = pktlen;
+ p = packet->pkt.user_id->photo;
+ for( ; pktlen; pktlen--, p++ )
+ *p = iobuf_get_noeof(inp);
+
+ if( list_mode ) {
+ printf(":photo_id packet: %s\n", packet->pkt.user_id->name );
+ }
+ return 0;
+}
+
static int
parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
@@ -1624,9 +1705,8 @@ parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
ed->new_ctb = new_ctb;
ed->mdc_method = 0;
if( pkttype == PKT_ENCRYPTED_MDC ) {
- /* test: this is the new encrypted_mdc packet */
/* fixme: add some pktlen sanity checks */
- int version, method;
+ int version;
version = iobuf_get_noeof(inp); pktlen--;
if( version != 1 ) {
@@ -1634,12 +1714,7 @@ parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
version);
goto leave;
}
- method = iobuf_get_noeof(inp); pktlen--;
- if( method != GCRY_MD_SHA1 ) {
- log_error("encrypted_mdc does not use SHA1 method\n" );
- goto leave;
- }
- ed->mdc_method = method;
+ ed->mdc_method = GCRY_MD_SHA1;
}
if( pktlen && pktlen < 10 ) { /* actually this is blocksize+2 */
log_error("packet(%d) too short\n", pkttype);
@@ -1662,3 +1737,26 @@ parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
return 0;
}
+
+static int
+parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen,
+ PACKET *pkt, int new_ctb )
+{
+ PKT_mdc *mdc;
+ byte *p;
+
+ mdc = pkt->pkt.mdc= gcry_xmalloc(sizeof *pkt->pkt.mdc );
+ if( list_mode )
+ printf(":mdc packet: length=%lu\n", pktlen);
+ if( !new_ctb || pktlen != 20 ) {
+ log_error("mdc_packet with invalid encoding\n");
+ goto leave;
+ }
+ p = mdc->hash;
+ for( ; pktlen; pktlen--, p++ )
+ *p = iobuf_get_noeof(inp);
+
+ leave:
+ return 0;
+}
+
diff --git a/g10/passphrase.c b/g10/passphrase.c
index 53b2a82a3..24addd072 100644
--- a/g10/passphrase.c
+++ b/g10/passphrase.c
@@ -1,5 +1,5 @@
/* passphrase.c - Get a passphrase
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -24,8 +24,9 @@
#include <string.h>
#include <unistd.h>
#include <assert.h>
-#include "util.h"
+
#include <gcrypt.h>
+#include "util.h"
#include "options.h"
#include "ttyio.h"
#include "keydb.h"
@@ -163,9 +164,9 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
tty_printf("\"\n");
if( !get_pubkey( pk, keyid ) ) {
+ const char *s = gcry_pk_algo_name( pk->pubkey_algo );
tty_printf( _("%u-bit %s key, ID %08lX, created %s"),
- nbits_from_pk( pk ),
- gcry_pk_algo_name( pk->pubkey_algo ), (ulong)keyid[1],
+ nbits_from_pk( pk ), s?s:"?", (ulong)keyid[1],
strtimestamp(pk->timestamp) );
if( keyid[2] && keyid[3] && keyid[0] != keyid[2]
&& keyid[1] != keyid[3] )
diff --git a/g10/pkclist.c b/g10/pkclist.c
index abd75f9cd..8e61ffdd0 100644
--- a/g10/pkclist.c
+++ b/g10/pkclist.c
@@ -1,5 +1,5 @@
/* pkclist.c
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -24,11 +24,10 @@
#include <string.h>
#include <errno.h>
#include <assert.h>
-#include <gcrypt.h>
+#include <gcrypt.h>
#include "options.h"
#include "packet.h"
-#include "main.h"
#include "errors.h"
#include "keydb.h"
#include "util.h"
@@ -36,6 +35,7 @@
#include "ttyio.h"
#include "status.h"
#include "i18n.h"
+#include "main.h"
#define CONTROL_D ('D' - 'A' + 1)
@@ -97,6 +97,112 @@ fpr_info( PKT_public_key *pk )
}
+/****************
+ * Show the revocation reason as it is stored with the given signature
+ */
+static void
+do_show_revocation_reason( PKT_signature *sig )
+{
+ size_t n, nn;
+ const byte *p, *pp;
+ int seq = 0;
+ const char *text;
+
+ while( (p = enum_sig_subpkt( sig->hashed_data, SIGSUBPKT_REVOC_REASON,
+ &n, &seq )) ) {
+ if( !n )
+ continue; /* invalid - just skip it */
+
+ if( *p == 0 )
+ text = _("No reason specified");
+ else if( *p == 0x01 )
+ text = _("Key is superseeded");
+ else if( *p == 0x02 )
+ text = _("Key has been compromised");
+ else if( *p == 0x03 )
+ text = _("Key is no longer used");
+ else if( *p == 0x20 )
+ text = _("User ID is no longer valid");
+ else
+ text = NULL;
+
+ log_info( _("Reason for revocation: ") );
+ if( text )
+ fputs( text, log_stream() );
+ else
+ fprintf( log_stream(), "code=%02x", *p );
+ putc( '\n', log_stream() );
+ n--; p++;
+ pp = NULL;
+ do {
+ /* We don't want any empty lines, so skip them */
+ while( n && *p == '\n' ) {
+ p++;
+ n--;
+ }
+ if( n ) {
+ pp = memchr( p, '\n', n );
+ nn = pp? pp - p : n;
+ log_info( _("Revocation comment: ") );
+ print_string( log_stream(), p, nn, 0 );
+ putc( '\n', log_stream() );
+ p += nn; n -= nn;
+ }
+ } while( pp );
+ }
+}
+
+
+static void
+show_revocation_reason( PKT_public_key *pk )
+{
+ /* Hmmm, this is not so easy becuase we have to duplicate the code
+ * used in the trustbd to calculate the keyflags. We need to find
+ * a clean way to check revocation certificates on keys and signatures.
+ * And there should be no duplicate code. Because we enter this function
+ * only when the trustdb toldus, taht we have a revoked key, we could
+ * simplylook for a revocation cert and display this one, when there is
+ * only one. Let's try to do this until we have a better solution.
+ */
+ KBNODE node, keyblock = NULL;
+ byte fingerprint[MAX_FINGERPRINT_LEN];
+ size_t fingerlen;
+ int rc;
+
+ /* get the keyblock */
+ fingerprint_from_pk( pk, fingerprint, &fingerlen );
+ rc = get_keyblock_byfprint( &keyblock, fingerprint, fingerlen );
+ if( rc ) { /* that should never happen */
+ log_debug( "failed to get the keyblock\n");
+ return;
+ }
+
+ for( node=keyblock; node; node = node->next ) {
+ if( ( node->pkt->pkttype == PKT_PUBLIC_KEY
+ || node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
+ && !cmp_public_keys( node->pkt->pkt.public_key, pk ) )
+ break;
+ }
+ if( !node ) {
+ log_debug("Oops, PK not in keyblock\n");
+ release_kbnode( keyblock );
+ return;
+ }
+ /* now find the revocation certificate */
+ for( node = node->next; node ; node = node->next ) {
+ if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
+ break;
+ if( node->pkt->pkttype == PKT_SIGNATURE
+ && (node->pkt->pkt.signature->sig_class == 0x20
+ || node->pkt->pkt.signature->sig_class == 0x28 ) ) {
+ /* FIXME: we should check the signature here */
+ do_show_revocation_reason ( node->pkt->pkt.signature );
+ }
+ }
+
+ release_kbnode( keyblock );
+}
+
static void
show_paths( ulong lid, int only_first )
@@ -338,38 +444,53 @@ _("Could not find a valid trust path to the key. Let's see whether we\n"
/****************
* Check whether we can trust this pk which has a trustlevel of TRUSTLEVEL
- * Returns: true if we trust.
+ * Returns: true if we trust. Might change the trustlevel
*/
static int
-do_we_trust( PKT_public_key *pk, int trustlevel )
+do_we_trust( PKT_public_key *pk, int *trustlevel )
{
int rc;
int did_add = 0;
+ int trustmask = 0;
retry:
- if( (trustlevel & TRUST_FLAG_REVOKED) ) {
+ if( (*trustlevel & TRUST_FLAG_REVOKED) ) {
log_info(_("key %08lX: key has been revoked!\n"),
(ulong)keyid_from_pk( pk, NULL) );
+ show_revocation_reason( pk );
if( opt.batch )
return 0;
if( !cpr_get_answer_is_yes("revoked_key.override",
_("Use this key anyway? ")) )
return 0;
+ trustmask |= TRUST_FLAG_REVOKED;
}
- else if( (trustlevel & TRUST_FLAG_SUB_REVOKED) ) {
+ else if( (*trustlevel & TRUST_FLAG_SUB_REVOKED) ) {
log_info(_("key %08lX: subkey has been revoked!\n"),
(ulong)keyid_from_pk( pk, NULL) );
+ show_revocation_reason( pk );
if( opt.batch )
return 0;
if( !cpr_get_answer_is_yes("revoked_key.override",
_("Use this key anyway? ")) )
return 0;
+ trustmask |= TRUST_FLAG_SUB_REVOKED;
+ }
+ *trustlevel &= ~trustmask;
+
+ if( opt.always_trust) {
+ if( opt.verbose )
+ log_info("No trust check due to --always-trust option\n");
+ /* The problem with this, is that EXPIRE can't be checked as
+ * this needs to insert a ne key into the trustdb first and
+ * we don't want that */
+ return 1;
}
- switch( (trustlevel & TRUST_MASK) ) {
+ switch( (*trustlevel & TRUST_MASK) ) {
case TRUST_UNKNOWN: /* No pubkey in trustDB: Insert and check again */
rc = insert_trust_record_by_pk( pk );
if( rc ) {
@@ -377,11 +498,12 @@ do_we_trust( PKT_public_key *pk, int trustlevel )
gpg_errstr(rc) );
return 0; /* no */
}
- rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
+ rc = check_trust( pk, trustlevel, NULL, NULL, NULL );
+ *trustlevel &= ~trustmask;
if( rc )
log_fatal("trust check after insert failed: %s\n",
gpg_errstr(rc) );
- if( trustlevel == TRUST_UNKNOWN || trustlevel == TRUST_EXPIRED ) {
+ if( *trustlevel == TRUST_UNKNOWN || *trustlevel == TRUST_EXPIRED ) {
log_debug("do_we_trust: oops at %d\n", __LINE__ );
return 0;
}
@@ -399,7 +521,8 @@ do_we_trust( PKT_public_key *pk, int trustlevel )
else {
int quit;
- rc = add_ownertrust( pk, &quit, &trustlevel );
+ rc = add_ownertrust( pk, &quit, trustlevel );
+ *trustlevel &= ~trustmask;
if( !rc && !did_add && !quit ) {
did_add = 1;
goto retry;
@@ -445,7 +568,7 @@ do_we_trust_pre( PKT_public_key *pk, int trustlevel )
{
int rc;
- rc = do_we_trust( pk, trustlevel );
+ rc = do_we_trust( pk, &trustlevel );
if( (trustlevel & TRUST_FLAG_REVOKED) && !rc )
return 0;
@@ -528,10 +651,12 @@ check_signatures_trust( PKT_signature *sig )
write_status( STATUS_KEYREVOKED );
log_info(_("WARNING: This key has been revoked by its owner!\n"));
log_info(_(" This could mean that the signature is forgery.\n"));
+ show_revocation_reason( pk );
}
else if( (trustlevel & TRUST_FLAG_SUB_REVOKED) ) {
write_status( STATUS_KEYREVOKED );
log_info(_("WARNING: This subkey has been revoked by its owner!\n"));
+ show_revocation_reason( pk );
}
@@ -770,7 +895,8 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
else {
int trustlevel;
- rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
+ rc = check_trust( pk, &trustlevel, pk->namehash,
+ NULL, NULL );
if( rc ) {
log_error("error checking pk of `%s': %s\n",
answer, gpg_errstr(rc) );
@@ -844,7 +970,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
else if( !(rc=openpgp_pk_test_algo(pk->pubkey_algo, use )) ) {
int trustlevel;
- rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
+ rc = check_trust( pk, &trustlevel, pk->namehash, NULL, NULL );
if( rc ) {
free_public_key( pk ); pk = NULL;
log_error(_("%s: error checking key: %s\n"),
diff --git a/g10/plaintext.c b/g10/plaintext.c
index f0c01ca8e..e3c7a865c 100644
--- a/g10/plaintext.c
+++ b/g10/plaintext.c
@@ -1,5 +1,5 @@
/* plaintext.c - process an plaintext packet
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -107,8 +107,10 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
}
if( mfx->md )
gcry_md_putc(mfx->md, c );
- if( c == '\r' )
- continue; /* fixme: this hack might be too simple */
+ #ifndef HAVE_DOSISH_SYSTEM
+ if( c == '\r' ) /* convert to native line ending */
+ continue; /* fixme: this hack might be too simple */
+ #endif
if( fp ) {
if( putc( c, fp ) == EOF ) {
log_error("Error writing to `%s': %s\n",
@@ -152,8 +154,10 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
while( (c = iobuf_get(pt->buf)) != -1 ) {
if( mfx->md )
gcry_md_putc(mfx->md, c );
+ #ifndef HAVE_DOSISH_SYSTEM
if( convert && c == '\r' )
continue; /* fixme: this hack might be too simple */
+ #endif
if( fp ) {
if( putc( c, fp ) == EOF ) {
log_error("Error writing to `%s': %s\n",
@@ -169,10 +173,10 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
int eof;
for( eof=0; !eof; ) {
/* Why do we check for len < 32768:
- * If we won´ we would practically read 2 EOFS but
+ * If we won't, we would practically read 2 EOFs but
* the first one has already popped the block_filter
* off and therefore we don't catch the boundary.
- * Always assume EOF if iobuf_read returns less bytes
+ * So, always assume EOF if iobuf_read returns less bytes
* then requested */
int len = iobuf_read( pt->buf, buffer, 32768 );
if( len == -1 )
@@ -217,6 +221,8 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
if( !state ) {
if( c == '\r' )
state = 1;
+ else if( c == '\n' )
+ state = 2;
else
gcry_md_putc(mfx->md, c );
}
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index 587847aeb..2019d0301 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -1,5 +1,5 @@
/* pubkey-enc.c - public key encoded packet handling
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -23,14 +23,15 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
-#include "util.h"
+
#include <gcrypt.h>
+#include "util.h"
#include "packet.h"
-#include "main.h"
#include "keydb.h"
#include "trustdb.h"
#include "status.h"
#include "options.h"
+#include "main.h"
#include "i18n.h"
static int get_it( PKT_pubkey_enc *k,
@@ -103,7 +104,6 @@ pk_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
}
-
/****************
* Get the session key from a pubkey enc paket and return
* it in DEK, which should have been allocated in secure memory.
@@ -169,7 +169,7 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
int rc;
MPI plain_dek = NULL;
byte *frame = NULL;
- unsigned n;
+ unsigned int n;
size_t nframe;
u16 csum, csum2;
@@ -199,7 +199,7 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
* DEK is the encryption key (session key) with length k
* CSUM
*/
- if( (opt.debug & DBG_CIPHER_VALUE) )
+ if( DBG_CIPHER )
log_hexdump("DEK frame:", frame, nframe );
n=0;
if( n + 7 > nframe )
@@ -219,10 +219,14 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
dek->keylen = nframe - (n+1) - 2;
dek->algo = frame[n++];
- if( dek->algo == GCRY_CIPHER_IDEA )
+ if( dek->algo == GCRY_CIPHER_IDEA )
write_status(STATUS_RSA_OR_IDEA);
rc = openpgp_cipher_test_algo( dek->algo );
if( rc ) {
+ if( !opt.quiet && rc == GPGERR_CIPHER_ALGO ) {
+ log_info(_("cipher algorithm %d is unknown or disabled\n"),
+ dek->algo);
+ }
dek->algo = 0;
goto leave;
}
@@ -241,9 +245,9 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
rc = GPGERR_WRONG_SECKEY;
goto leave;
}
- if( (opt.debug & DBG_CIPHER_VALUE) )
+ if( DBG_CIPHER )
log_hexdump("DEK is:", dek->key, dek->keylen );
- /* check that the algo is in the preferences */
+ /* check that the algo is in the preferences and whether it has expired */
{
PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
if( (rc = get_pubkey( pk, keyid )) )
@@ -262,10 +266,25 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
"NOTE: cipher algorithm %d not found in preferences\n"),
dek->algo );
}
+
+
+ if( !rc && pk->expiredate && pk->expiredate <= make_timestamp() ) {
+ log_info(_("NOTE: secret key %08lX expired at %s\n"),
+ (ulong)keyid[1], asctimestamp( pk->expiredate) );
+ }
+
+ /* FIXME: check wheter the key has been revoked and display
+ * the revocation reason. Actually the user should know this himself,
+ * but the sender might not know already and therefor the user
+ * should get a notice that an revoked key has been used to decode
+ * the message. The user can than watch out for snakes send by
+ * one of those Eves outside his paradise :-)
+ */
free_public_key( pk );
rc = 0;
}
+
leave:
mpi_release(plain_dek);
gcry_free(frame);
diff --git a/g10/revoke.c b/g10/revoke.c
index b1a50e786..4abd5edd7 100644
--- a/g10/revoke.c
+++ b/g10/revoke.c
@@ -1,5 +1,5 @@
/* revoke.c
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -24,6 +24,7 @@
#include <string.h>
#include <errno.h>
#include <assert.h>
+#include <ctype.h>
#include "options.h"
#include "packet.h"
@@ -37,6 +38,38 @@
#include "i18n.h"
+struct revocation_reason_info {
+ int code;
+ char *desc;
+};
+
+
+int
+revocation_reason_build_cb( PKT_signature *sig, void *opaque )
+{
+ struct revocation_reason_info *reason = opaque;
+ char *ud = NULL;
+ byte *buffer;
+ size_t buflen = 1;
+
+ if( reason->desc ) {
+ ud = native_to_utf8( reason->desc );
+ buflen += strlen(ud);
+ }
+ buffer = gcry_xmalloc( buflen );
+ *buffer = reason->code;
+ if( ud ) {
+ memcpy(buffer+1, ud, strlen(ud) );
+ gcry_free( ud );
+ }
+
+ build_sig_subpkt( sig, SIGSUBPKT_REVOC_REASON, buffer, buflen );
+ gcry_free( buffer );
+ return 0;
+}
+
+
+
/****************
* Generate a revocation certificate for UNAME
*/
@@ -55,6 +88,7 @@ gen_revoke( const char *uname )
KBNODE keyblock = NULL;
KBNODE node;
KBPOS kbpos;
+ struct revocation_reason_info *reason = NULL;
if( opt.batch ) {
log_error(_("sorry, can't do this in batch mode\n"));
@@ -62,19 +96,6 @@ gen_revoke( const char *uname )
}
- /* FIXME: ask for the reason of revocation
- 0x00 - No reason specified (key revocations or cert revocations)
- Does not make sense!
-
- 0x01 - Key is superceded (key revocations)
- 0x02 - Key material has been compromised (key revocations)
- 0x03 - Key is no longer used (key revocations)
- 0x20 - User id information is no longer valid (cert revocations)
-
- Following the revocation code is a string of octets which gives
- information about the reason for revocation in human-readable form
- */
-
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx);
init_packet( &pkt );
@@ -136,6 +157,13 @@ gen_revoke( const char *uname )
goto leave;
}
+ /* get the reason for the revocation */
+ reason = ask_revocation_reason( 1, 0, 1 );
+ if( !reason ) { /* user decided to cancel */
+ rc = 0;
+ goto leave;
+ }
+
switch( is_secret_key_protected( sk ) ) {
case -1:
log_error(_("unknown protection algorithm\n"));
@@ -163,7 +191,9 @@ gen_revoke( const char *uname )
iobuf_push_filter( out, armor_filter, &afx );
/* create it */
- rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0, NULL, NULL);
+ rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
+ revocation_reason_build_cb,
+ reason );
if( rc ) {
log_error(_("make_keysig_packet failed: %s\n"), gpg_errstr(rc));
goto leave;
@@ -198,193 +228,127 @@ gen_revoke( const char *uname )
iobuf_cancel(out);
else
iobuf_close(out);
+ release_revocation_reason_info( reason );
return rc;
}
-#if 0 /* The code is not complete but anyway, now we use */
- /* the edit menu to revoke signature */
-/****************
- * Return true if there is already a revocation signature for KEYID
- * in KEYBLOCK at point node.
- */
-static int
-already_revoked( const KBNODE keyblock, const KBNODE node, u32 *keyid ) ) {
-{
- const KBNODE n = find_prev_kbnode( keyblock, node, PKT_USER_ID );
-
- for( ; n; n = n->next ) {
- PKT_signature *sig;
- if( n->pkt->pkttype == PKT_SIGNATURE
- && (sig = node->pkt->pkt.signature)->sig_class == 0x30
- && sig->keyid[0] == keyid[0]
- && sig->keyid[1] == keyid[1] )
- return 1;
- }
- else if( n->pkt->pkttype == PKT_USER_ID
- break;
- else if( n->pkt->pkttype == PKT_PUBLIC_SUBKEY
- break;
- }
- return 0;
-}
-/****************
- * Ask whether the signature should be revoked. If the user commits this,
- * flag bit 0 is set.
- */
-static void
-ask_revoke_sig( KBNODE keyblock, KBNODE node, PKT_signature *sig ) ) {
-{
- KBNODE unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
- if( !unode ) {
- log_error("Oops: no user ID for signature\n");
- return;
- }
-
- tty_printf(_("user ID: \""));
- tty_print_utf8_string( unode->pkt->pkt.user_id->name,
- unode->pkt->pkt.user_id->len, 0 );
- tty_printf(_("\"\nsigned with your key %08lX at %s\n"),
- sig->keyid[1], datestr_from_sig(sig) );
-
- if( cpr_get_answer_is_yes("ask_revoke_sig.one",
- _("Create a revocation certificate for this signature? (y/N)")) ) {
- node->flag |= 1;
- }
-}
-
-/****************
- * Generate a signature revocation certificate for UNAME
- */
-int
-gen_sig_revoke( const char *uname )
+struct revocation_reason_info *
+ask_revocation_reason( int key_rev, int cert_rev, int hint )
{
- int rc = 0;
- armor_filter_context_t afx;
- compress_filter_context_t zfx;
- PACKET pkt;
- IOBUF out = NULL;
- KBNODE keyblock = NULL;
- KBNODE node;
- KBPOS kbpos;
- int uidchg;
-
- if( opt.batch ) {
- log_error(_("sorry, can't do this in batch mode\n"));
- return GPGERR_GENERAL;
- }
-
-
- memset( &afx, 0, sizeof afx);
- memset( &zfx, 0, sizeof zfx);
- init_packet( &pkt );
-
-
- /* get the keyblock */
- rc = find_keyblock_byname( &kbpos, uname );
- if( rc ) {
- log_error(_("public key for user `%s' not found\n"), uname );
- goto leave;
- }
-
- /* read the keyblock */
- rc = read_keyblock( &kbpos, &keyblock );
- if( rc ) {
- log_error(_("error reading the certificate: %s\n"), gpg_errstr(rc) );
- goto leave;
- }
-
- /* get the keyid from the keyblock */
- node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
- if( !node ) {
- log_error(_("Oops; public key lost!\n"));
- rc = GPGERR_GENERAL;
- goto leave;
- }
-
- if( (rc = open_outfile( NULL, 0, &out )) )
- goto leave;
-
- if( opt.armor ) {
- afx.what = 1;
- iobuf_push_filter( out, armor_filter, &afx );
- }
+ int code;
+ char *description = NULL;
+ struct revocation_reason_info *reason;
+ const char *text_1 = _("Key has been compromised");
+ const char *text_2 = _("Key is superseded");
+ const char *text_3 = _("Key is no longer used");
+ const char *text_4 = _("User ID is non longer valid");
+ const char *code_text = NULL;
+
+ do {
+ gcry_free(description);
+ description = NULL;
+
+ tty_printf(_("Please select the reason for the revocation:\n"));
+ if( key_rev )
+ tty_printf(" 1 = %s\n", text_1 );
+ if( key_rev )
+ tty_printf(" 2 = %s\n", text_2 );
+ if( key_rev )
+ tty_printf(" 3 = %s\n", text_3 );
+ if( cert_rev )
+ tty_printf(" 4 = %s\n", text_4 );
+ tty_printf( " 0 = %s\n", _("Cancel") );
+ if( hint )
+ tty_printf(_("(Probably you want to select %d here)\n"), hint );
+
+ for(code = 0; !code;) {
+ int n;
+ char *answer = cpr_get("ask_revocation_reason.code",
+ _("Your decision? "));
+ trim_spaces( answer );
+ cpr_kill_prompt();
+ if( *answer == 'q' || *answer == 'Q' )
+ n = 0;
+ else if( !isdigit( *answer ) )
+ n = -1;
+ else if( hint && !*answer )
+ n = hint;
+ else
+ n = atoi(answer);
+ gcry_free(answer);
+ if( !n )
+ return NULL; /* cancel */
+ else if( key_rev && n == 1 ) {
+ code = 0x02; /* key has been compromised */
+ code_text = text_1;
+ }
+ else if( key_rev && n == 2 ) {
+ code = 0x01; /* key is superseded */
+ code_text = text_2;
+ }
+ else if( key_rev && n == 3 ) {
+ code = 0x03; /* key is no longer used */
+ code_text = text_3;
+ }
+ else if( cert_rev && n == 4 ) {
+ code = 0x20; /* uid is non longer valid */
+ code_text = text_4;
+ }
+ else
+ tty_printf(_("Invalid selection.\n"));
+ }
- /* Now walk over all signatures which we did with one of
- * our secret keys. Hmmm: Should we check for duplicate signatures */
- clear_kbnode_flags( flags );
- for( node = keyblock; node; node = node->next ) {
- PKT_signature *sig;
- if( node->pkt->pkttype == PKT_SIGNATURE
- && ((sig = node->pkt->pkt.signature)->sig_class&~3) == 0x10
- && seckey_available( sig->keyid )
- && !already_revoked( keyblock, node, sig->keyid ) ) { ) {
- ask_revoke_sig( keyblock, node, sig )
+ tty_printf(_("Enter an optional description; "
+ "end it with an empty line:\n") );
+ for(;;) {
+ char *answer = cpr_get("ask_revocation_reason.text", "> " );
+ trim_trailing_ws( answer, strlen(answer) );
+ cpr_kill_prompt();
+ if( !*answer ) {
+ gcry_free(answer);
+ break;
+ }
+
+ {
+ char *p = make_printable_string( answer, strlen(answer), 0 );
+ gcry_free(answer);
+ answer = p;
+ }
+
+ if( !description )
+ description = gcry_xstrdup(answer);
+ else {
+ char *p = gcry_xmalloc( strlen(description) + strlen(answer) + 2 );
+ strcpy(stpcpy(stpcpy( p, description),"\n"),answer);
+ gcry_free(description);
+ description = p;
+ }
+ gcry_free(answer);
}
- else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
- break;
- }
+ tty_printf(_("Reason for revocation: %s\n"), code_text );
+ if( !description )
+ tty_printf(_("(No description given)\n") );
+ else
+ tty_printf("%s\n", description );
- for( node = keyblock; node; node = node->next ) { {
- if( (node->flag & 1) )
- break;
- }
- if( !node ) {
- log_info(_("nothing to revoke\n"));
- iobuf_cancel(out);
- out = NULL;
- goto leave;
- }
+ } while( !cpr_get_answer_is_yes("ask_revocation_reason.okay",
+ _("Is this okay? ")) );
- init_packet( &pkt );
- pkt.pkttype = PKT_PUBLIC_KEY;
- pkt.pkt.public_key = keyblock->pkt->pkt.public_key;
- rc = build_packet( out, &pkt );
- if( rc ) {
- log_error(_("build_packet failed: %s\n"), gpg_errstr(rc) );
- goto leave;
- }
- uidchg = 1;
- for( node = keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_USER_ID )
- uidchg = 1;
- if( !(node->flag & 1) )
- continue;
-
- if( uidchg ) {
- /* create a user ID packet */
- .......
- uidchg = 0;
- }
+ reason = gcry_xmalloc( sizeof *reason );
+ reason->code = code;
+ reason->desc = description;
+ return reason;
+}
- /* create it */
- rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x30, 0, NULL, NULL);
- if( rc ) {
- log_error(_("make_keysig_packet failed: %s\n"), gpg_errstr(rc));
- goto leave;
- }
- init_packet( &pkt );
- pkt.pkttype = PKT_SIGNATURE;
- pkt.pkt.signature = sig;
-
- rc = build_packet( out, &pkt );
- if( rc ) {
- log_error(_("build_packet failed: %s\n"), gpg_errstr(rc) );
- goto leave;
- }
+void
+release_revocation_reason_info( struct revocation_reason_info *reason )
+{
+ if( reason ) {
+ gcry_free( reason->desc );
+ gcry_free( reason );
}
-
- leave:
- release_kbnode( keyblock );
- if( !out )
- ;
- else if( rc )
- iobuf_cancel(out);
- else
- iobuf_close(out);
- return rc;
}
-#endif /* unused code */
diff --git a/g10/ringedit.c b/g10/ringedit.c
index 2fa79fd74..3a29654d2 100644
--- a/g10/ringedit.c
+++ b/g10/ringedit.c
@@ -1,5 +1,5 @@
/* ringedit.c - Function for key ring editing
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -51,9 +51,10 @@
#ifdef HAVE_LIBGDBM
#include <gdbm.h>
#endif
+
+#include <gcrypt.h>
#include "util.h"
#include "packet.h"
-#include <gcrypt.h>
#include "iobuf.h"
#include "keydb.h"
#include "host2net.h"
@@ -63,10 +64,6 @@
#include "kbx.h"
-#ifdef MKDIR_TAKES_ONE_ARG
-# undef mkdir
-# define mkdir(a,b) mkdir(a)
-#endif
struct resource_table_struct {
@@ -191,7 +188,6 @@ enum_keyblock_resources( int *sequence, int secret )
}
-
/****************
* Register a resource (which currently may only be a keyring file).
* The first keyring which is added by this function is
@@ -312,24 +308,13 @@ add_keyblock_resource( const char *url, int force, int secret )
*last_slash_in_filename = 0;
if( access(filename, F_OK) ) {
- if( strlen(filename) >= 7
- && !strcmp(filename+strlen(filename)-7, "/.gnupg") ) {
- if( mkdir(filename, S_IRUSR|S_IWUSR|S_IXUSR) )
- {
- log_error( _("%s: can't create directory: %s\n"),
- filename, strerror(errno));
- rc = GPGERR_OPEN_FILE;
- goto leave;
- }
- else if( !opt.quiet )
- log_info( _("%s: directory created\n"), filename );
- copy_options_file( filename );
- }
- else
- {
- rc = GPGERR_OPEN_FILE;
- goto leave;
- }
+ /* on the first time we try to create the default homedir and
+ * in this case the process will be terminated, so that on the
+ * next invocation it can read the options file in on startup
+ */
+ try_make_homedir( filename );
+ rc = GPGERR_OPEN_FILE;
+ goto leave;
}
*last_slash_in_filename = '/';
@@ -363,7 +348,6 @@ add_keyblock_resource( const char *url, int force, int secret )
#endif
break;
-
#ifdef HAVE_LIBGDBM
case rt_GDBM:
resource_table[i].dbf = gdbm_open( filename, 0,
@@ -457,6 +441,35 @@ get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos )
}
+/****************
+ * Return the filename of the firstkeyblock resource which is intended
+ * for write access. This will either be the default resource or in
+ * case this is not writable one of the others. If no writable is found,
+ * the default filename in the homedirectory will be returned.
+ * Caller must free, will never return NULL.
+ */
+char *
+get_writable_keyblock_file( int secret )
+{
+ int i = secret? default_secret_resource : default_public_resource;
+
+ if( resource_table[i].used && !resource_table[i].secret == !secret ) {
+ if( !access( resource_table[i].fname, R_OK|W_OK ) ) {
+ return gcry_xstrdup( resource_table[i].fname );
+ }
+ }
+ for(i=0; i < MAX_RESOURCES; i++ ) {
+ if( resource_table[i].used && !resource_table[i].secret == !secret ) {
+ if( !access( resource_table[i].fname, R_OK|W_OK ) ) {
+ return gcry_xstrdup( resource_table[i].fname );
+ }
+ }
+ }
+ /* Assume the home dir is always writable */
+ return make_filename(opt.homedir, secret? "secring.gpg"
+ : "pubring.gpg", NULL );
+}
+
/****************
* Search a keyblock which starts with the given packet and puts all
diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c
index bef75507e..ab09b8f4d 100644
--- a/g10/seckey-cert.c
+++ b/g10/seckey-cert.c
@@ -1,5 +1,5 @@
/* seckey-cert.c - secret key certificate packet handling
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -33,6 +33,7 @@
#include "i18n.h"
#include "status.h"
+
/****************
* Emulate our old PK interface here - sometime in the future we might
* change the internal design to directly fit to libgcrypt.
@@ -82,9 +83,11 @@ pk_check_secret_key( int algo, MPI *skey )
return rc;
}
+
static int
do_check( PKT_secret_key *sk )
{
+ byte *buffer;
u16 csum=0;
int i, res;
unsigned nbytes;
@@ -95,6 +98,10 @@ do_check( PKT_secret_key *sk )
GCRY_CIPHER_HD cipher_hd=NULL;
PKT_secret_key *save_sk;
+ if( sk->protect.s2k.mode == 1001 ) {
+ log_info(_("secret key parts are not available\n"));
+ return GPGERR_GENERAL;
+ }
if( sk->protect.algo == GCRY_CIPHER_NONE )
BUG();
if( openpgp_cipher_test_algo( sk->protect.algo ) ) {
@@ -112,6 +119,7 @@ do_check( PKT_secret_key *sk )
}
dek = passphrase_to_dek( keyid, sk->pubkey_algo, sk->protect.algo,
&sk->protect.s2k, 0 );
+ /* Hmmm: Do we use sync mode here even for Twofish? */
if( !(cipher_hd = gcry_cipher_open( sk->protect.algo,
GCRY_CIPHER_MODE_CFB,
GCRY_CIPHER_SECURE
@@ -198,7 +206,8 @@ do_check( PKT_secret_key *sk )
free_secret_key( save_sk );
return GPGERR_BAD_PASS;
}
- /* the checksum may fail, so we also check the key itself */
+ /* the checksum may be correct in some cases,
+ * so we also check the key itself */
res = pk_check_secret_key( sk->pubkey_algo, sk->skey );
if( res ) {
copy_secret_key( sk, save_sk );
@@ -300,8 +309,6 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
) {
BUG();
}
-
-
rc = gcry_cipher_setkey( cipher_hd, dek->key, dek->keylen );
if( rc == GCRYERR_WEAK_KEY ) {
log_info(_("WARNING: Weak key detected"
@@ -316,18 +323,19 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
if( blocksize != 8 && blocksize != 16 )
log_fatal("unsupported blocksize %d\n", blocksize );
sk->protect.ivlen = blocksize;
+ assert( sk->protect.ivlen <= DIM(sk->protect.iv) );
}
-
- assert( sk->protect.ivlen <= DIM(sk->protect.iv) );
gcry_randomize(sk->protect.iv, sk->protect.ivlen,
- GCRY_STRONG_RANDOM);
+ GCRY_STRONG_RANDOM);
gcry_cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen );
+
#warning FIXME: replace set/get buffer
if( sk->version >= 4 ) {
- #define NMPIS (GNUPG_MAX_NSKEY - GNUPG_MAX_NPKEY)
- byte *bufarr[NMPIS];
- unsigned narr[NMPIS];
- unsigned nbits[NMPIS];
+ /* FIXME: There is a bug in this function for all algorithms
+ * where the secret MPIs are more than 1 */
+ byte *bufarr[GNUPG_MAX_NSKEY];
+ unsigned narr[GNUPG_MAX_NSKEY];
+ unsigned nbits[GNUPG_MAX_NSKEY];
int ndata=0;
byte *p, *data;
@@ -342,13 +350,13 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
nbits[j] = gcry_mpi_get_nbits( sk->skey[i] );
ndata += narr[j] + 2;
}
- for( ; j < NMPIS; j++ )
+ for( ; j < GNUPG_MAX_NSKEY; j++ )
bufarr[j] = NULL;
ndata += 2; /* for checksum */
data = gcry_xmalloc_secure( ndata );
p = data;
- for(j=0; j < NMPIS && bufarr[j]; j++ ) {
+ for(j=0; j < GNUPG_MAX_NSKEY && bufarr[j]; j++ ) {
p[0] = nbits[j] >> 8 ;
p[1] = nbits[j];
p += 2;
@@ -356,7 +364,6 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
p += narr[j];
gcry_free(bufarr[j]);
}
- #undef NMPIS
csum = checksum( data, ndata-2);
sk->csum = csum;
*p++ = csum >> 8;
diff --git a/g10/seskey.c b/g10/seskey.c
index 996118e0f..aa2a1511c 100644
--- a/g10/seskey.c
+++ b/g10/seskey.c
@@ -1,5 +1,5 @@
/* seskey.c - make sesssion keys etc.
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -152,7 +152,7 @@ encode_session_key( DEK *dek, unsigned nbits )
static MPI
do_encode_md( GCRY_MD_HD md, int algo, size_t len, unsigned nbits,
- const byte *asn, size_t asnlen )
+ const byte *asn, size_t asnlen, int v3compathack )
{
int nframe = (nbits+7) / 8;
byte *frame;
@@ -165,7 +165,7 @@ do_encode_md( GCRY_MD_HD md, int algo, size_t len, unsigned nbits,
/* We encode the MD in this way:
*
- * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
+ * 0 1 PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
*
* PAD consists of FF bytes.
*/
@@ -173,7 +173,7 @@ do_encode_md( GCRY_MD_HD md, int algo, size_t len, unsigned nbits,
: gcry_xmalloc( nframe );
n = 0;
frame[n++] = 0;
- frame[n++] = algo;
+ frame[n++] = v3compathack? algo : 1; /* block type */
i = nframe - len - asnlen -3 ;
assert( i > 1 );
memset( frame+n, 0xff, i ); n += i;
@@ -188,8 +188,15 @@ do_encode_md( GCRY_MD_HD md, int algo, size_t len, unsigned nbits,
}
+/****************
+ * Encode a message digest into an MPI.
+ * v3compathack is used to work around a bug in old GnuPG versions
+ * which did put the algo identifier inseatd of the block type 1 into
+ * the encoded value. setting this vare force the old behaviour.
+ */
MPI
-encode_md_value( int pubkey_algo, GCRY_MD_HD md, int hash_algo, unsigned nbits )
+encode_md_value( int pubkey_algo, GCRY_MD_HD md, int hash_algo,
+ unsigned nbits, int v3compathack )
{
int algo = hash_algo? hash_algo : gcry_md_get_algo(md);
MPI frame;
@@ -211,9 +218,10 @@ encode_md_value( int pubkey_algo, GCRY_MD_HD md, int hash_algo, unsigned nbits )
if( gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, asn, &asnlen ) )
BUG();
frame = do_encode_md( md, algo, gcry_md_get_algo_dlen( algo ),
- nbits, asn, asnlen );
+ nbits, asn, asnlen, v3compathack );
gcry_free( asn );
}
return frame;
}
+
diff --git a/g10/sig-check.c b/g10/sig-check.c
index bd68d44d7..f12cfa6d3 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.c
@@ -1,5 +1,5 @@
/* sig-check.c - Check a signature
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -31,6 +31,7 @@
#include "main.h"
#include "status.h"
#include "i18n.h"
+#include "options.h"
struct cmp_help_context_s {
PKT_signature *sig;
@@ -39,9 +40,10 @@ struct cmp_help_context_s {
static int do_signature_check( PKT_signature *sig, GCRY_MD_HD digest,
- u32 *r_expire );
+ u32 *r_expiredate, int *r_expired );
static int do_check( PKT_public_key *pk, PKT_signature *sig,
- GCRY_MD_HD digest );
+ GCRY_MD_HD digest, int *r_expired );
+
/****************
@@ -131,11 +133,13 @@ int
signature_check( PKT_signature *sig, GCRY_MD_HD digest )
{
u32 dummy;
- return do_signature_check( sig, digest, &dummy );
+ int dum2;
+ return do_signature_check( sig, digest, &dummy, &dum2 );
}
static int
-do_signature_check( PKT_signature *sig, GCRY_MD_HD digest, u32 *r_expire )
+do_signature_check( PKT_signature *sig, GCRY_MD_HD digest,
+ u32 *r_expiredate, int *r_expired )
{
PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
int rc=0;
@@ -143,12 +147,12 @@ do_signature_check( PKT_signature *sig, GCRY_MD_HD digest, u32 *r_expire )
if( is_RSA(sig->pubkey_algo) )
write_status(STATUS_RSA_OR_IDEA);
- *r_expire = 0;
+ *r_expiredate = 0;
if( get_pubkey( pk, sig->keyid ) )
rc = GPGERR_NO_PUBKEY;
else {
- *r_expire = pk->expiredate;
- rc = do_check( pk, sig, digest );
+ *r_expiredate = pk->expiredate;
+ rc = do_check( pk, sig, digest, r_expired );
}
free_public_key( pk );
@@ -199,97 +203,6 @@ do_signature_check( PKT_signature *sig, GCRY_MD_HD digest, u32 *r_expire )
}
-#if 0 /* not anymore used */
-/****************
- * Check the MDC which is contained in SIG.
- * The GCRY_MD_HD should be currently open, so that this function
- * is able to append some data, before finalizing the digest.
- */
-int
-mdc_kludge_check( PKT_signature *sig, GCRY_MD_HD digest )
-{
- int rc=0;
-
- if( (rc=check_digest_algo(sig->digest_algo)) )
- return rc;
-
- /* make sure the digest algo is enabled (in case of a detached mdc??) */
- md_enable( digest, sig->digest_algo );
-
- /* complete the digest */
- if( sig->version >= 4 )
- gcry_md_putc( digest, sig->version );
- gcry_md_putc( digest, sig->sig_class );
- if( sig->version < 4 ) {
- u32 a = sig->timestamp;
- gcry_md_putc( digest, (a >> 24) & 0xff );
- gcry_md_putc( digest, (a >> 16) & 0xff );
- gcry_md_putc( digest, (a >> 8) & 0xff );
- gcry_md_putc( digest, a & 0xff );
- }
- else {
- byte buf[6];
- size_t n;
- gcry_md_putc( digest, sig->pubkey_algo );
- gcry_md_putc( digest, sig->digest_algo );
- if( sig->hashed_data ) {
- n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
- gcry_md_write( digest, sig->hashed_data, n+2 );
- n += 6;
- }
- else
- n = 6;
- /* add some magic */
- buf[0] = sig->version;
- buf[1] = 0xff;
- buf[2] = n >> 24;
- buf[3] = n >> 16;
- buf[4] = n >> 8;
- buf[5] = n;
- gcry_md_write( digest, buf, 6 );
- }
- md_final( digest );
-
- rc = GPGERR_BAD_SIGN;
- { const byte *s1 = md_read( digest, sig->digest_algo );
- int s1len = md_digest_length( sig->digest_algo );
-
- log_hexdump( "MDC calculated", s1, s1len );
-
- if( !sig->data[0] )
- log_debug("sig_data[0] is NULL\n");
- else {
- unsigned s2len;
- char *s2;
-
- if( gcry_mpi_print( GCRYMPI_FMT_USG, &s2, &s2len, sig->data[0] ))
- BUG();
-
- log_hexdump( "MDC stored ", s2, s2len );
-
- if( s2len != s1len )
- log_debug("MDC check: len differ: %d/%d\n", s1len, s2len);
- else if( memcmp( s1, s2, s1len ) )
- log_debug("MDC check: hashs differ\n");
- else
- rc = 0;
- gcry_free(s2);
- }
- }
-
- if( !rc && sig->flags.unknown_critical ) {
- log_info(_("assuming bad MDC due to an unknown critical bit\n"));
- rc = GPGERR_BAD_SIGN;
- }
- sig->flags.checked = 1;
- sig->flags.valid = !rc;
-
- /* FIXME: check that we are actually in an encrypted packet */
-
- return rc;
-}
-#endif
-
/****************
* This function gets called by pubkey_verify() if the algorithm needs it.
*/
@@ -366,16 +279,18 @@ cmp_help( void *opaque, MPI result )
static int
-do_check( PKT_public_key *pk, PKT_signature *sig, GCRY_MD_HD digest )
+do_check( PKT_public_key *pk, PKT_signature *sig, GCRY_MD_HD digest,
+ int *r_expired )
{
MPI result = NULL;
int rc=0;
struct cmp_help_context_s ctx;
u32 cur_time;
+ *r_expired = 0;
if( pk->version == 4 && pk->pubkey_algo == GCRY_PK_ELG_E ) {
log_info(_("this is a PGP generated "
- "ElGamal key which is NOT secure for signatures!\n"));
+ "ElGamal key which is NOT secure for signatures!\n"));
return GPGERR_PUBKEY_ALGO;
}
@@ -385,7 +300,8 @@ do_check( PKT_public_key *pk, PKT_signature *sig, GCRY_MD_HD digest )
? _("public key is %lu second newer than the signature\n")
: _("public key is %lu seconds newer than the signature\n"),
d );
- return GPGERR_TIME_CONFLICT; /* pubkey newer than signature */
+ if( !opt.ignore_time_conflict )
+ return GPGERR_TIME_CONFLICT; /* pubkey newer than signature */
}
cur_time = make_timestamp();
@@ -395,13 +311,15 @@ do_check( PKT_public_key *pk, PKT_signature *sig, GCRY_MD_HD digest )
"in future (time warp or clock problem)\n")
: _("key has been created %lu seconds "
"in future (time warp or clock problem)\n"), d );
- return GPGERR_TIME_CONFLICT;
+ if( !opt.ignore_time_conflict )
+ return GPGERR_TIME_CONFLICT;
}
if( pk->expiredate && pk->expiredate < cur_time ) {
log_info(_("NOTE: signature key expired %s\n"),
asctimestamp( pk->expiredate ) );
write_status(STATUS_SIGEXPIRED);
+ *r_expired = 1;
}
@@ -448,13 +366,24 @@ do_check( PKT_public_key *pk, PKT_signature *sig, GCRY_MD_HD digest )
gcry_md_final( digest );
result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo,
- gcry_mpi_get_nbits(pk->pkey[0]));
-
+ gcry_mpi_get_nbits(pk->pkey[0]), 0);
ctx.sig = sig;
ctx.md = digest;
rc = pk_verify( pk->pubkey_algo, result, sig->data, pk->pkey,
cmp_help, &ctx );
mpi_release( result );
+ if( (opt.emulate_bugs & EMUBUG_MDENCODE)
+ && rc == GPGERR_BAD_SIGN && is_ELGAMAL(pk->pubkey_algo) ) {
+ /* In this case we try again because old GnuPG versions didn't encode
+ * the hash right. There is no problem with DSA however */
+ result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo,
+ gcry_mpi_get_nbits(pk->pkey[0]), (sig->version < 5) );
+ ctx.sig = sig;
+ ctx.md = digest;
+ rc = pk_verify( pk->pubkey_algo, result, sig->data, pk->pkey,
+ cmp_help, &ctx );
+ }
+
if( !rc && sig->flags.unknown_critical ) {
log_info(_("assuming bad signature due to an unknown critical bit\n"));
rc = GPGERR_BAD_SIGN;
@@ -472,16 +401,30 @@ hash_uid_node( KBNODE unode, GCRY_MD_HD md, PKT_signature *sig )
PKT_user_id *uid = unode->pkt->pkt.user_id;
assert( unode->pkt->pkttype == PKT_USER_ID );
- if( sig->version >=4 ) {
- byte buf[5];
- buf[0] = 0xb4; /* indicates a userid packet */
- buf[1] = uid->len >> 24; /* always use 4 length bytes */
- buf[2] = uid->len >> 16;
- buf[3] = uid->len >> 8;
- buf[4] = uid->len;
- gcry_md_write( md, buf, 5 );
+ if( uid->photo ) {
+ if( sig->version >=4 ) {
+ byte buf[5];
+ buf[0] = 0xd1; /* packet of type 17 */
+ buf[1] = uid->photolen >> 24; /* always use 4 length bytes */
+ buf[2] = uid->photolen >> 16;
+ buf[3] = uid->photolen >> 8;
+ buf[4] = uid->photolen;
+ gcry_md_write( md, buf, 5 );
+ }
+ gcry_md_write( md, uid->photo, uid->photolen );
+ }
+ else {
+ if( sig->version >=4 ) {
+ byte buf[5];
+ buf[0] = 0xb4; /* indicates a userid packet */
+ buf[1] = uid->len >> 24; /* always use 4 length bytes */
+ buf[2] = uid->len >> 16;
+ buf[3] = uid->len >> 8;
+ buf[4] = uid->len;
+ gcry_md_write( md, buf, 5 );
+ }
+ gcry_md_write( md, uid->name, uid->len );
}
- gcry_md_write( md, uid->name, uid->len );
}
/****************
@@ -493,11 +436,13 @@ int
check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
{
u32 dummy;
- return check_key_signature2(root, node, is_selfsig, &dummy );
+ int dum2;
+ return check_key_signature2(root, node, is_selfsig, &dummy, &dum2 );
}
int
-check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, u32 *r_expire)
+check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
+ u32 *r_expiredate, int *r_expired )
{
GCRY_MD_HD md;
PKT_public_key *pk;
@@ -507,7 +452,8 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, u32 *r_expire)
if( is_selfsig )
*is_selfsig = 0;
- *r_expire = 0;
+ *r_expiredate = 0;
+ *r_expired = 0;
assert( node->pkt->pkttype == PKT_SIGNATURE );
assert( root->pkt->pkttype == PKT_PUBLIC_KEY );
@@ -528,7 +474,7 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, u32 *r_expire)
if( !(md = gcry_md_open( algo, 0 )) )
BUG();
hash_public_key( md, pk );
- rc = do_check( pk, sig, md );
+ rc = do_check( pk, sig, md, r_expired );
gcry_md_close(md);
}
else if( sig->sig_class == 0x28 ) { /* subkey revocation */
@@ -539,7 +485,7 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, u32 *r_expire)
BUG();
hash_public_key( md, pk );
hash_public_key( md, snode->pkt->pkt.public_key );
- rc = do_check( pk, sig, md );
+ rc = do_check( pk, sig, md, r_expired );
gcry_md_close(md);
}
else {
@@ -562,7 +508,7 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, u32 *r_expire)
BUG();
hash_public_key( md, pk );
hash_public_key( md, snode->pkt->pkt.public_key );
- rc = do_check( pk, sig, md );
+ rc = do_check( pk, sig, md, r_expired );
gcry_md_close(md);
}
else {
@@ -584,10 +530,11 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, u32 *r_expire)
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) {
if( is_selfsig )
*is_selfsig = 1;
- rc = do_check( pk, sig, md );
+ rc = do_check( pk, sig, md, r_expired );
+ }
+ else {
+ rc = do_signature_check( sig, md, r_expiredate, r_expired );
}
- else
- rc = do_signature_check( sig, md, r_expire );
gcry_md_close(md);
}
else {
diff --git a/g10/sign.c b/g10/sign.c
index bb2d2290c..9d0c203b8 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -1,5 +1,5 @@
/* sign.c - sign data
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -36,9 +36,16 @@
#include "filter.h"
#include "ttyio.h"
#include "trustdb.h"
+#include "status.h"
#include "i18n.h"
+#ifdef HAVE_DOSISH_SYSTEM
+ #define LF "\r\n"
+#else
+ #define LF "\n"
+#endif
+
/****************
* Emulate our old PK interface here - sometime in the future we might
* change the internal design to directly fit to libgcrypt.
@@ -163,7 +170,8 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
"in future (time warp or clock problem)\n")
: _("key has been created %lu seconds "
"in future (time warp or clock problem)\n"), d );
- return GPGERR_TIME_CONFLICT;
+ if( !opt.ignore_time_conflict )
+ return GPGERR_TIME_CONFLICT;
}
@@ -178,7 +186,7 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
sig->digest_start[0] = dp[0];
sig->digest_start[1] = dp[1];
frame = encode_md_value( sk->pubkey_algo, md,
- digest_algo, gcry_mpi_get_nbits(sk->skey[0]));
+ digest_algo, gcry_mpi_get_nbits(sk->skey[0]), 0 );
rc = pk_sign( sk->pubkey_algo, sig->data, frame, sk->skey );
mpi_release(frame);
if( rc )
@@ -240,6 +248,25 @@ only_old_style( SK_LIST sk_list )
}
+static void
+print_status_sig_created ( PKT_secret_key *sk, PKT_signature *sig, int what )
+{
+ byte array[MAX_FINGERPRINT_LEN], *p;
+ char buf[100+MAX_FINGERPRINT_LEN*2];
+ size_t i, n;
+
+ sprintf(buf, "%c %d %d %02x %lu ",
+ what, sig->pubkey_algo, sig->digest_algo, sig->sig_class,
+ (ulong)sig->timestamp );
+
+ fingerprint_from_sk( sk, array, &n );
+ p = buf + strlen(buf);
+ for(i=0; i < n ; i++ )
+ sprintf(p+2*i, "%02X", array[i] );
+
+ write_status_text( STATUS_SIG_CREATED, buf );
+}
+
/****************
* Sign the files whose names are in FILENAME.
@@ -521,6 +548,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
sig->sig_class = opt.textmode && !outfile? 0x01 : 0x00;
md = gcry_md_copy( mfx.md );
+ if( !md )
+ BUG();
if( sig->version >= 4 ) {
build_sig_subpkt_from_sig( sig );
@@ -573,12 +602,16 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
pkt.pkttype = PKT_SIGNATURE;
pkt.pkt.signature = sig;
rc = build_packet( out, &pkt );
+ if( !rc && is_status_enabled() ) {
+ print_status_sig_created ( sk, sig, detached ? 'D':'S');
+ }
free_packet( &pkt );
if( rc )
log_error("build signature packet failed: %s\n", gpg_errstr(rc) );
}
if( rc )
goto leave;
+
}
@@ -640,7 +673,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
else if( (rc = open_outfile( fname, 1, &out )) )
goto leave;
- iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----\n" );
+ iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----" LF );
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
PKT_secret_key *sk = sk_rover->sk;
@@ -683,13 +716,15 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
}
- if( !(textmd = gcry_md_open(0, 0)) )
+ textmd = gcry_md_open(0, 0);
+ if( !textmd )
BUG();
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
PKT_secret_key *sk = sk_rover->sk;
gcry_md_enable(textmd, hash_for(sk->pubkey_algo));
}
- /*md_start_debug( textmd, "sign" );*/
+ if ( DBG_HASHING )
+ gcry_md_start_debug( textmd, "clearsign" );
copy_clearsig_text( out, inp, textmd,
!opt.not_dash_escaped, opt.escape_from, old_style );
/* fixme: check for read errors */
@@ -717,6 +752,8 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
sig->sig_class = 0x01;
md = gcry_md_copy( textmd );
+ if( !md )
+ BUG();
if( sig->version >= 4 ) {
build_sig_subpkt_from_sig( sig );
gcry_md_putc( md, sig->version );
@@ -768,6 +805,9 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
pkt.pkttype = PKT_SIGNATURE;
pkt.pkt.signature = sig;
rc = build_packet( out, &pkt );
+ if( !rc && is_status_enabled() ) {
+ print_status_sig_created ( sk, sig, 'C');
+ }
free_packet( &pkt );
if( rc )
log_error("build signature packet failed: %s\n", gpg_errstr(rc) );
diff --git a/g10/signal.c b/g10/signal.c
index fcb012e02..f61b0a8f8 100644
--- a/g10/signal.c
+++ b/g10/signal.c
@@ -1,5 +1,5 @@
/* signal.c - signal handling
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -27,9 +27,9 @@
#include <errno.h>
#include <assert.h>
+#include <gcrypt.h>
#include "options.h"
#include "errors.h"
-#include <gcrypt.h>
#include "util.h"
#include "main.h"
#include "ttyio.h"
@@ -59,14 +59,23 @@ got_fatal_signal( int sig )
caught_fatal_sig = 1;
gcry_control( GCRYCTL_TERM_SECMEM );
- #ifdef IS_DEVELOPMENT_VERSION
+ /* better don't transtale these messages */
write(2, "\n", 1 );
s = log_get_name(); if( s ) write(2, s, strlen(s) );
write(2, ": ", 2 );
s = get_signal_name(sig); write(2, s, strlen(s) );
write(2, " caught ... exiting\n", 21 );
+
+ #ifndef HAVE_DOSISH_SYSTEM
+ { /* reset action to default action and raise signal again */
+ struct sigaction nact;
+ nact.sa_handler = SIG_DFL;
+ sigemptyset( &nact.sa_mask );
+ nact.sa_flags = 0;
+ sigaction( sig, &nact, NULL);
+ }
#endif
- exit(8); /* Hmmm, for some reasons rais2e does not work */
+ raise( sig );
}
diff --git a/g10/skclist.c b/g10/skclist.c
index a0d69a49e..8fcb22aba 100644
--- a/g10/skclist.c
+++ b/g10/skclist.c
@@ -1,5 +1,5 @@
/* skclist.c
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -66,7 +66,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock,
}
else if( !(rc=openpgp_pk_test_algo(sk->pubkey_algo, use)) ) {
SK_LIST r;
- if( sk->version == 4 && (use & GCRY_PK_USAGE_SIGN)
+ if( sk->version == 4 && (use & GCRY_PK_USAGE_SIGN )
&& sk->pubkey_algo == GCRY_PK_ELG_E ) {
log_info("this is a PGP generated "
"ElGamal key which is NOT secure for signatures!\n");
diff --git a/g10/status.c b/g10/status.c
index 3eeec4648..c35a8adba 100644
--- a/g10/status.c
+++ b/g10/status.c
@@ -1,5 +1,5 @@
/* status.c
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -38,12 +38,13 @@
#include <sys/mman.h>
#endif
#endif
+
+#include <gcrypt.h>
#include "util.h"
#include "status.h"
#include "ttyio.h"
#include "options.h"
#include "main.h"
-#include <gcrypt.h>
#include "i18n.h"
static int fd = -1;
@@ -54,10 +55,32 @@ static int fd = -1;
static int shm_is_locked;
#endif /*USE_SHM_COPROCESSING*/
+
+static void
+progress_cb ( void *ctx, int c )
+{
+ char buf[50];
+
+ if ( c == '\n' )
+ sprintf ( buf, "%.20s X 100 100", (char*)ctx );
+ else
+ sprintf ( buf, "%.20s %c 0 0", (char*)ctx, c );
+ write_status_text ( STATUS_PROGRESS, buf );
+}
+
+
void
set_status_fd ( int newfd )
{
fd = newfd;
+ if ( fd != -1 ) {
+ #if 0
+ #warning fixme - progress functions
+ register_primegen_progress ( progress_cb, "primegen" );
+ register_pk_dsa_progress ( progress_cb, "pk_dsa" );
+ register_pk_elg_progress ( progress_cb, "pk_elg" );
+ #endif
+ }
}
int
@@ -96,6 +119,10 @@ write_status_text ( int no, const char *text)
case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL\n"; break;
case STATUS_TRUST_FULLY : s = "TRUST_FULLY\n"; break;
case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE\n"; break;
+ case STATUS_GET_BOOL : s = "GET_BOOL\n"; break;
+ case STATUS_GET_LINE : s = "GET_LINE\n"; break;
+ case STATUS_GET_HIDDEN : s = "GET_HIDDEN\n"; break;
+ case STATUS_GOT_IT : s = "GOT_IT\n"; break;
case STATUS_SHM_INFO : s = "SHM_INFO\n"; break;
case STATUS_SHM_GET : s = "SHM_GET\n"; break;
case STATUS_SHM_GET_BOOL : s = "SHM_GET_BOOL\n"; break;
@@ -118,6 +145,16 @@ write_status_text ( int no, const char *text)
case STATUS_ERRMDC : s = "ERRMDC\n"; break;
case STATUS_IMPORTED : s = "IMPORTED\n"; break;
case STATUS_IMPORT_RES : s = "IMPORT_RES\n"; break;
+ case STATUS_FILE_START : s = "FILE_START\n"; break;
+ case STATUS_FILE_DONE : s = "FILE_DONE\n"; break;
+ case STATUS_FILE_ERROR : s = "FILE_ERROR\n"; break;
+ case STATUS_BEGIN_DECRYPTION:s = "BEGIN_DECRYPTION\n"; break;
+ case STATUS_END_DECRYPTION : s = "END_DECRYPTION\n"; break;
+ case STATUS_BEGIN_ENCRYPTION:s = "BEGIN_ENCRYPTION\n"; break;
+ case STATUS_END_ENCRYPTION : s = "END_ENCRYPTION\n"; break;
+ case STATUS_DELETE_PROBLEM : s = "DELETE_PROBLEM\n"; break;
+ case STATUS_PROGRESS : s = "PROGRESS\n"; break;
+ case STATUS_SIG_CREATED : s = "SIG_CREATED\n"; break;
default: s = "?\n"; break;
}
@@ -164,6 +201,10 @@ init_shm_coprocessing ( ulong requested_shm_size, int lock_mem )
if ( shm_id == -1 )
log_fatal("can't get %uk of shared memory: %s\n",
(unsigned)shm_size/1024, strerror(errno));
+
+ #if !defined(IPC_HAVE_SHM_LOCK) \
+ && defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
+ /* part of the old code which uses mlock */
shm_area = shmat( shm_id, 0, 0 );
if ( shm_area == (char*)-1 )
log_fatal("can't attach %uk shared memory: %s\n",
@@ -174,29 +215,17 @@ init_shm_coprocessing ( ulong requested_shm_size, int lock_mem )
#ifdef USE_CAPABILITIES
cap_set_proc( cap_from_text("cap_ipc_lock+ep") );
#endif
- #ifdef IPC_HAVE_SHM_LOCK
- if ( shmctl (shm_id, SHM_LOCK, 0) )
- log_info("locking shared memory %d failed: %s\n",
- shm_id, strerror(errno));
- else
- shm_is_locked = 1;
- #elif defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
/* (need the cast for Solaris with Sun's workshop compilers) */
if ( mlock ( (char*)shm_area, shm_size) )
log_info("locking shared memory %d failed: %s\n",
shm_id, strerror(errno));
else
shm_is_locked = 1;
- #else
- log_info("Locking shared memory %d failed: No way to do it\n", shm_id );
- #endif
#ifdef USE_CAPABILITIES
cap_set_proc( cap_from_text("cap_ipc_lock+p") );
#endif
}
-
-
#ifdef IPC_RMID_DEFERRED_RELEASE
if( shmctl( shm_id, IPC_RMID, 0) )
log_fatal("shmctl IPC_RMDID of %d failed: %s\n",
@@ -213,13 +242,59 @@ init_shm_coprocessing ( ulong requested_shm_size, int lock_mem )
shm_id, strerror(errno));
}
+ #else /* this is the new code which handles the changes in the SHM semantics
+ * introduced with Linux 2.4. The changes is that we now change the
+ * permissions and then attach to the memory.
+ */
+
+ if( lock_mem ) {
+ #ifdef USE_CAPABILITIES
+ cap_set_proc( cap_from_text("cap_ipc_lock+ep") );
+ #endif
+ #ifdef IPC_HAVE_SHM_LOCK
+ if ( shmctl (shm_id, SHM_LOCK, 0) )
+ log_info("locking shared memory %d failed: %s\n",
+ shm_id, strerror(errno));
+ else
+ shm_is_locked = 1;
+ #else
+ log_info("Locking shared memory %d failed: No way to do it\n", shm_id );
+ #endif
+ #ifdef USE_CAPABILITIES
+ cap_set_proc( cap_from_text("cap_ipc_lock+p") );
+ #endif
+ }
+
+ if( shmctl( shm_id, IPC_STAT, &shmds ) )
+ log_fatal("shmctl IPC_STAT of %d failed: %s\n",
+ shm_id, strerror(errno));
+ if( shmds.shm_perm.uid != getuid() ) {
+ shmds.shm_perm.uid = getuid();
+ if( shmctl( shm_id, IPC_SET, &shmds ) )
+ log_fatal("shmctl IPC_SET of %d failed: %s\n",
+ shm_id, strerror(errno));
+ }
+
+ shm_area = shmat( shm_id, 0, 0 );
+ if ( shm_area == (char*)-1 )
+ log_fatal("can't attach %uk shared memory: %s\n",
+ (unsigned)shm_size/1024, strerror(errno));
+ log_debug("mapped %uk shared memory at %p, id=%d\n",
+ (unsigned)shm_size/1024, shm_area, shm_id );
+
+ #ifdef IPC_RMID_DEFERRED_RELEASE
+ if( shmctl( shm_id, IPC_RMID, 0) )
+ log_fatal("shmctl IPC_RMDID of %d failed: %s\n",
+ shm_id, strerror(errno));
+ #endif
+
+ #endif
/* write info; Protocol version, id, size, locked size */
sprintf( buf, "pv=1 pid=%d shmid=%d sz=%u lz=%u", (int)getpid(),
shm_id, (unsigned)shm_size, shm_is_locked? (unsigned)shm_size:0 );
write_status_text( STATUS_SHM_INFO, buf );
}
-
/****************
* Request a string from client
* If bool, returns static string on true (do not free) or NULL for false
@@ -269,10 +344,50 @@ do_shm_get( const char *keyword, int hidden, int bool )
#endif /* USE_SHM_COPROCESSING */
+/****************
+ * Request a string from the client over the command-fd
+ * If bool, returns static string on true (do not free) or NULL for false
+ */
+static char *
+do_get_from_fd( const char *keyword, int hidden, int bool )
+{
+ int i, len;
+ char *string;
+
+ write_status_text( bool? STATUS_GET_BOOL :
+ hidden? STATUS_GET_HIDDEN : STATUS_GET_LINE, keyword );
+
+ for( string = NULL, i = len = 200; ; i++ ) {
+ if( i >= len-1 ) {
+ char *save = string;
+ len += 100;
+ string = hidden? gcry_xmalloc_secure ( len ) : gcry_malloc ( len );
+ if( save )
+ memcpy(string, save, i );
+ else
+ i=0;
+ }
+ /* Hmmm: why not use our read_line function here */
+ if( read( fd, string+i, 1) != 1 || string[i] == '\n' )
+ break;
+ }
+ string[i] = 0;
+
+ write_status( STATUS_GOT_IT );
+
+ if( bool ) /* Fixme: is this correct??? */
+ return string[0] == 'Y' ? "" : NULL;
+
+ return string;
+}
+
+
int
cpr_enabled()
{
+ if( opt.command_fd != -1 )
+ return 1;
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return 1;
@@ -285,6 +400,8 @@ cpr_get( const char *keyword, const char *prompt )
{
char *p;
+ if( opt.command_fd != -1 )
+ return do_get_from_fd ( keyword, 0, 0 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return do_shm_get( keyword, 0, 0 );
@@ -318,6 +435,8 @@ cpr_get_hidden( const char *keyword, const char *prompt )
{
char *p;
+ if( opt.command_fd != -1 )
+ return do_get_from_fd ( keyword, 1, 0 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return do_shm_get( keyword, 1, 0 );
@@ -336,6 +455,8 @@ cpr_get_hidden( const char *keyword, const char *prompt )
void
cpr_kill_prompt(void)
{
+ if( opt.command_fd != -1 )
+ return;
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return;
@@ -350,6 +471,8 @@ cpr_get_answer_is_yes( const char *keyword, const char *prompt )
int yes;
char *p;
+ if( opt.command_fd != -1 )
+ return !!do_get_from_fd ( keyword, 0, 1 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return !!do_shm_get( keyword, 0, 1 );
@@ -376,6 +499,8 @@ cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt )
int yes;
char *p;
+ if( opt.command_fd != -1 )
+ return !!do_get_from_fd ( keyword, 0, 1 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return !!do_shm_get( keyword, 0, 1 );
diff --git a/g10/status.h b/g10/status.h
index 73cc1b1bf..f9cce5b6b 100644
--- a/g10/status.h
+++ b/g10/status.h
@@ -1,5 +1,5 @@
/* status.h
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -65,7 +65,22 @@
#define STATUS_ERRMDC 35
#define STATUS_IMPORTED 36
#define STATUS_IMPORT_RES 37
+#define STATUS_FILE_START 38
+#define STATUS_FILE_DONE 39
+#define STATUS_FILE_ERROR 40
+#define STATUS_BEGIN_DECRYPTION 41
+#define STATUS_END_DECRYPTION 42
+#define STATUS_BEGIN_ENCRYPTION 43
+#define STATUS_END_ENCRYPTION 44
+
+#define STATUS_DELETE_PROBLEM 45
+#define STATUS_GET_BOOL 46
+#define STATUS_GET_LINE 47
+#define STATUS_GET_HIDDEN 48
+#define STATUS_GOT_IT 49
+#define STATUS_PROGRESS 50
+#define STATUS_SIG_CREATED 51
/*-- status.c --*/
void set_status_fd ( int fd );
diff --git a/g10/tdbdump.c b/g10/tdbdump.c
index 9be91241b..6729d4e56 100644
--- a/g10/tdbdump.c
+++ b/g10/tdbdump.c
@@ -1,5 +1,5 @@
/* tdbdump.c
- * Copyright (C) 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -520,5 +520,6 @@ import_ownertrust( const char *fname )
if( !is_stdin )
fclose(fp);
do_sync();
+ sync_trustdb();
}
diff --git a/g10/tdbio.c b/g10/tdbio.c
index 926048fbf..669f66ffc 100644
--- a/g10/tdbio.c
+++ b/g10/tdbio.c
@@ -1,5 +1,5 @@
/* tdbio.c
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -40,11 +40,6 @@
#include "tdbio.h"
-#ifdef MKDIR_TAKES_ONE_ARG
-# undef mkdir
-# define mkdir(a,b) mkdir(a)
-#endif
-
/****************
* Yes, this is a very simple implementation. We should really
* use a page aligned buffer and read complete pages.
@@ -439,17 +434,8 @@ tdbio_set_dbname( const char *new_dbname, int create )
assert(p);
*p = 0;
if( access( fname, F_OK ) ) {
- if( strlen(fname) >= 7
- && !strcmp(fname+strlen(fname)-7, "/.gnupg" ) ) {
- if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
- log_fatal( _("%s: can't create directory: %s\n"),
- fname, strerror(errno) );
- else if( !opt.quiet )
- log_info( _("%s: directory created\n"), fname );
- copy_options_file( fname );
- }
- else
- log_fatal( _("%s: directory does not exist!\n"), fname );
+ try_make_homedir( fname );
+ log_fatal( _("%s: directory does not exist!\n"), fname );
}
*p = '/';
@@ -1130,6 +1116,8 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
fputs(", expired", fp );
if( rec->r.dir.dirflags & DIRF_REVOKED )
fputs(", revoked", fp );
+ if( rec->r.dir.dirflags & DIRF_NEWKEYS )
+ fputs(", newkeys", fp );
}
putc('\n', fp);
break;
diff --git a/g10/tdbio.h b/g10/tdbio.h
index 4eabed91c..a2e5404f6 100644
--- a/g10/tdbio.h
+++ b/g10/tdbio.h
@@ -1,5 +1,5 @@
/* tdbio.h - Trust database I/O functions
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -52,6 +52,7 @@
/* one uid with a selfsignature or an revocation */
#define DIRF_EXPIRED 4 /* the complete key has expired */
#define DIRF_REVOKED 8 /* the complete key has been revoked */
+#define DIRF_NEWKEYS 128 /* new keys are available: we can check the sigs */
#define KEYF_CHECKED 1 /* This key has been checked */
#define KEYF_VALID 2 /* This is a valid (sub)key */
@@ -121,7 +122,7 @@ struct trust_record {
} uid;
struct { /* preference record */
ulong lid; /* point back to the directory record */
- /* or 0 for a glocal pref record */
+ /* or 0 for a global pref record */
ulong next; /* points to next pref record */
byte data[ITEMS_PER_PREF_RECORD];
} pref;
diff --git a/g10/textfilter.c b/g10/textfilter.c
index 06f85dc64..a360ffccb 100644
--- a/g10/textfilter.c
+++ b/g10/textfilter.c
@@ -1,5 +1,5 @@
/* textfilter.c
- * Copyright (C) 1998,1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -31,7 +31,13 @@
#include "util.h"
#include "filter.h"
#include "i18n.h"
+#include "options.h"
+#ifdef HAVE_DOSISH_SYSTEM
+ #define LF "\r\n"
+#else
+ #define LF "\n"
+#endif
#define MAX_LINELEN 19995 /* a little bit smaller than in armor.c */
/* to make sure that a warning is displayed while */
@@ -151,6 +157,9 @@ copy_clearsig_text( IOBUF out, IOBUF inp, GCRY_MD_HD md,
int truncated = 0;
int pending_lf = 0;
+ if( !opt.pgp2_workarounds )
+ pgp2mode = 0;
+
if( !escape_dash )
escape_from = 0;
@@ -183,12 +192,37 @@ copy_clearsig_text( IOBUF out, IOBUF inp, GCRY_MD_HD md,
iobuf_put( out, '-' );
iobuf_put( out, ' ' );
}
+
+ #if 0 /*defined(HAVE_DOSISH_SYSTEM)*/
+ /* We don't use this anymore because my interpretation of rfc2440 7.1
+ * is that there is no conversion needed. If one decides to
+ * clearsign a unix file on a DOS box he will get a mixed line endings.
+ * If at some point it turns out, that a conversion is a nice feature
+ * we can make an option out of it.
+ */
+ /* make sure the lines do end in CR,LF */
+ if( n > 1 && ( (buffer[n-2] == '\r' && buffer[n-1] == '\n' )
+ || (buffer[n-2] == '\n' && buffer[n-1] == '\r'))) {
+ iobuf_write( out, buffer, n-2 );
+ iobuf_put( out, '\r');
+ iobuf_put( out, '\n');
+ }
+ else if( n && buffer[n-1] == '\n' ) {
+ iobuf_write( out, buffer, n-1 );
+ iobuf_put( out, '\r');
+ iobuf_put( out, '\n');
+ }
+ else
+ iobuf_write( out, buffer, n );
+
+ #else
iobuf_write( out, buffer, n );
+ #endif
}
/* at eof */
if( !pending_lf ) { /* make sure that the file ends with a LF */
- iobuf_put( out, '\n');
+ iobuf_writestr( out, LF );
if( !escape_dash )
gcry_md_putc( md, '\n' );
}
diff --git a/g10/trustdb.c b/g10/trustdb.c
index 610b3b355..f75ccc52f 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -1,5 +1,5 @@
/* trustdb.c
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -110,7 +110,6 @@ static int alloced_tns;
static int max_alloced_tns;
-
static LOCAL_ID_TABLE new_lid_table(void);
static int ins_lid_table_item( LOCAL_ID_TABLE tbl, ulong lid, unsigned flag );
static int qry_lid_table_flag( LOCAL_ID_TABLE tbl, ulong lid, unsigned *flag );
@@ -125,13 +124,22 @@ static int do_check( TRUSTREC *drec, unsigned *trustlevel,
unsigned *retflgs);
static int get_dir_record( PKT_public_key *pk, TRUSTREC *rec );
static int do_update_trust_record( KBNODE keyblock, TRUSTREC *drec,
- int recheck, int *modified );
-static int check_trust_record( TRUSTREC *drec );
+ int sigs_only, int *modified );
+static int check_trust_record( TRUSTREC *drec, int sigs_only );
+static void mark_fresh_keys(void);
/* a table used to keep track of ultimately trusted keys
* which are the ones from our secrings and the trusted keys */
static LOCAL_ID_TABLE ultikey_table;
+
+/* a table to keep track of newly importted keys. This one is
+ * create by the insert_trust_record function and from time to time
+ * used to verify key signature which have been done with these new keys */
+static LOCAL_ID_TABLE fresh_imported_keys;
+static int fresh_imported_keys_count;
+#define FRESH_KEY_CHECK_THRESHOLD 200
+
/* list of unused lid items and tables */
static LOCAL_ID_TABLE unused_lid_tables;
static struct local_id_item *unused_lid_items;
@@ -245,6 +253,27 @@ release_lid_table( LOCAL_ID_TABLE tbl )
}
#endif
+
+/****************
+ * Remove all items from a LID table
+ */
+static void
+clear_lid_table( LOCAL_ID_TABLE tbl )
+{
+ struct local_id_item *a, *a2;
+ int i;
+
+ for(i=0; i < 16; i++ ) {
+ for(a=tbl->items[i]; a; a = a2 ) {
+ a2 = a->next;
+ a->next = unused_lid_items;
+ unused_lid_items = a;
+ }
+ tbl->items[i] = NULL;
+ }
+}
+
+
/****************
* Add a new item to the table or return 1 if we already have this item
*/
@@ -454,7 +483,7 @@ verify_own_keys(void)
if( DBG_TRUST )
log_debug("key %08lX: checking secret key\n", (ulong)keyid[1] );
- if( is_secret_key_protected( sk ) < 1 )
+ if( !opt.quiet && is_secret_key_protected( sk ) < 1 )
log_info(_("NOTE: secret key %08lX is NOT protected.\n"),
(ulong)keyid[1] );
@@ -572,6 +601,18 @@ init_trustdb()
+/****************
+ * This function should be called in certain cases to sync the internal state
+ * of the trustdb with the file image. Currently it is needed after
+ * a sequence of insert_trust_record() calls.
+ */
+void
+sync_trustdb()
+{
+ if( fresh_imported_keys && fresh_imported_keys_count )
+ mark_fresh_keys();
+}
+
/***********************************************
@@ -652,7 +693,7 @@ print_path( int pathlen, TN ME .........., FILE *fp, ulong highlight )
p = get_user_id( keyid, &n );
putc(' ', fp);
putc('\"', fp);
- print_utf8_string( fp, p, n > 40? 40:n, 0 );
+ print_utf8_string( fp, p, n > 40? 40:n );
putc('\"', fp);
gcry_free(p);
putc('\n', fp );
@@ -683,8 +724,14 @@ print_uid_from_keyblock( FILE *fp, KBNODE keyblock, ulong urecno )
if( node->pkt->pkttype == PKT_USER_ID ) {
PKT_user_id *uidpkt = node->pkt->pkt.user_id;
- gcry_md_hash_buffer( GCRY_MD_RMD160, uhash,
- uidpkt->name, uidpkt->len );
+ if( uidpkt->photo ) {
+ gcry_md_hash_buffer( GCRY_MD_RMD160, uhash,
+ uidpkt->photo, uidpkt->photolen );
+ }
+ else {
+ gcry_md_hash_buffer( GCRY_MD_RMD160, uhash,
+ uidpkt->name, uidpkt->len );
+ }
if( !memcmp( uhash, urec.r.uid.namehash, 20 ) ) {
print_string( fp, uidpkt->name, uidpkt->len, ':' );
return;
@@ -1001,7 +1048,7 @@ check_uidsigs( KBNODE keyblock, KBNODE keynode, u32 *mainkid, ulong lid,
(ulong)mainkid[1], lid );
assert(keynode->pkt->pkttype == PKT_USER_ID );
uid = keynode->pkt->pkt.user_id;
- print_utf8_string( log_stream(), uid->name, uid->len );
+ print_string( log_stream(), uid->name, uid->len, '\"' );
fputs("\"\n", log_stream());
}
@@ -1083,17 +1130,17 @@ check_uidsigs( KBNODE keyblock, KBNODE keynode, u32 *mainkid, ulong lid,
static unsigned int
check_sig_record( KBNODE keyblock, KBNODE signode,
ulong siglid, int sigidx, u32 *keyid, ulong lid,
- u32 *r_expire )
+ u32 *r_expiretime, int *mod_down, int *mod_up )
{
PKT_signature *sig = signode->pkt->pkt.signature;
unsigned int sigflag = 0;
TRUSTREC tmp;
- int revocation=0, rc;
+ int revocation=0, expired=0, rc;
if( DBG_TRUST )
log_debug("check_sig_record: %08lX.%lu %lu[%d]\n",
(ulong)keyid[1], lid, siglid, sigidx );
- *r_expire = 0;
+ *r_expiretime = 0;
if( (sig->sig_class&~3) == 0x10 ) /* regular certification */
;
else if( sig->sig_class == 0x30 ) /* cert revocation */
@@ -1104,7 +1151,8 @@ check_sig_record( KBNODE keyblock, KBNODE signode,
read_record( siglid, &tmp, 0 );
if( tmp.rectype == RECTYPE_DIR ) {
/* the public key is in the trustdb: check sig */
- rc = check_key_signature2( keyblock, signode, NULL, r_expire );
+ rc = check_key_signature2( keyblock, signode, NULL,
+ r_expiretime, &expired );
if( !rc ) { /* valid signature */
if( opt.verbose )
log_info("sig %08lX.%lu/%lu[%d]/%08lX: %s\n",
@@ -1113,18 +1161,25 @@ check_sig_record( KBNODE keyblock, KBNODE signode,
revocation? _("Valid certificate revocation")
: _("Good certificate") );
sigflag |= SIGF_CHECKED | SIGF_VALID;
+ if( expired ) {
+ sigflag |= SIGF_EXPIRED;
+ /* We have to reset the expiretime, so that this signature
+ * does not get checked over and over due to the reached
+ * expiretime */
+ *r_expiretime = 0;
+ }
if( revocation ) {
sigflag |= SIGF_REVOKED;
- /**mod_down = 1;*/
+ *mod_down = 1;
}
else
- /**mod_up = 1*/;
+ *mod_up = 1;
}
else if( rc == GPGERR_NO_PUBKEY ) {
/* This may happen if the key is still in the trustdb
* but not available in the keystorage */
sigflag |= SIGF_NOPUBKEY;
- /**mod_down = 1;*/
+ *mod_down = 1;
if( revocation )
sigflag |= SIGF_REVOKED;
}
@@ -1138,7 +1193,7 @@ check_sig_record( KBNODE keyblock, KBNODE signode,
sigflag |= SIGF_CHECKED;
if( revocation ) {
sigflag |= SIGF_REVOKED;
- /**mod_down = 1;*/
+ *mod_down = 1;
}
}
}
@@ -1169,14 +1224,15 @@ check_sig_record( KBNODE keyblock, KBNODE signode,
*/
static ulong
make_sig_records( KBNODE keyblock, KBNODE uidnode,
- ulong lid, u32 *mainkid, u32 *min_expire )
+ ulong lid, u32 *mainkid, u32 *min_expire,
+ int *mod_down, int *mod_up )
{
TRUSTREC *srecs, **s_end, *s=NULL, *s2;
KBNODE node;
PKT_signature *sig;
ulong sigrecno, siglid;
int i, sigidx = 0;
- u32 expire;
+ u32 expiretime;
srecs = NULL; s_end = &srecs;
for( node=uidnode->next; node; node = node->next ) {
@@ -1191,6 +1247,12 @@ make_sig_records( KBNODE keyblock, KBNODE uidnode,
siglid = find_or_create_lid( sig );
/* smash dups */
+ /* FIXME: Here we have a problem:
+ * We can't distinguish between a certification and a certification
+ * revocation without looking at class of the signature - we have
+ * to see how we can store the sigclass in the sigrecord..
+ * Argg- I hope I can get rid of this ugly trustdb ASAP.
+ */
for( s2 = s; s2 ; s2 = s2->next ) {
for(i=0; i < sigidx; i++ ) {
if( s2->r.sig.sig[i].lid == siglid )
@@ -1219,7 +1281,8 @@ make_sig_records( KBNODE keyblock, KBNODE uidnode,
s->r.sig.sig[sigidx].lid = siglid;
s->r.sig.sig[sigidx].flag= check_sig_record( keyblock, node,
siglid, sigidx,
- mainkid, lid, &expire );
+ mainkid, lid, &expiretime,
+ mod_down, mod_up );
sigidx++;
if( sigidx == SIGS_PER_RECORD ) {
@@ -1229,8 +1292,8 @@ make_sig_records( KBNODE keyblock, KBNODE uidnode,
sigidx = 0;
}
/* keep track of signers pk expire time */
- if( expire && (!*min_expire || *min_expire > expire ) )
- *min_expire = expire;
+ if( expiretime && (!*min_expire || *min_expire > expiretime ) )
+ *min_expire = expiretime;
}
if( sigidx ) {
s->recnum = tdbio_new_recnum();
@@ -1320,7 +1383,8 @@ make_pref_record( PKT_signature *sig, ulong lid )
static ulong
-make_uid_records( KBNODE keyblock, ulong lid, u32 *keyid, u32 *min_expire )
+make_uid_records( KBNODE keyblock, ulong lid, u32 *keyid, u32 *min_expire,
+ int *mod_down, int *mod_up )
{
TRUSTREC *urecs, **uend, *u, *u2;
KBNODE node;
@@ -1335,7 +1399,14 @@ make_uid_records( KBNODE keyblock, ulong lid, u32 *keyid, u32 *min_expire )
if( node->pkt->pkttype != PKT_USER_ID )
continue;
uid = node->pkt->pkt.user_id;
- gcry_md_hash_buffer( GCRY_MD_RMD160, uidhash, uid->name, uid->len );
+ if( uid->photo ) {
+ gcry_md_hash_buffer( GCRY_MD_RMD160, uidhash,
+ uid->photo, uid->photolen );
+ }
+ else {
+ gcry_md_hash_buffer( GCRY_MD_RMD160, uidhash,
+ uid->name, uid->len );
+ }
/* create the uid record */
u = gcry_xcalloc( 1, sizeof *u );
@@ -1352,9 +1423,21 @@ make_uid_records( KBNODE keyblock, ulong lid, u32 *keyid, u32 *min_expire )
&& (u->r.uid.uidflags & UIDF_VALID) ) {
u->r.uid.prefrec = bestsig? make_pref_record( bestsig, lid ) : 0;
}
+
+ /* the next test is really bad because we should modify
+ * out modification timestamps only if we really have a change.
+ * But because we are deleting the uid records first it is somewhat
+ * difficult to track those changes. fixme */
+ if( !( u->r.uid.uidflags & UIDF_VALID )
+ || ( u->r.uid.uidflags & UIDF_REVOKED ) )
+ *mod_down=1;
+ else
+ *mod_up=1;
+
/* create the list of signatures */
u->r.uid.siglist = make_sig_records( keyblock, node,
- lid, keyid, min_expire );
+ lid, keyid, min_expire,
+ mod_down, mod_up );
}
uidrecno = urecs? urecs->recnum : 0;
@@ -1381,6 +1464,8 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
TRUSTREC drec;
int rc;
+ /* NOTE: We don't need recheck anymore, but this might chnage again in
+ * the future */
if( opt.dry_run )
return 0;
if( modified )
@@ -1391,26 +1476,27 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
if( rc )
return rc;
- rc = do_update_trust_record( keyblock, &drec, recheck, modified );
+ rc = do_update_trust_record( keyblock, &drec, 0, modified );
return rc;
}
/****************
- * Same as update_trust_record, but tghis functions expects the dir record.
- * On exit the dirrecord will reflect any changes made.
+ * Same as update_trust_record, but this functions expects the dir record.
+ * On exit the dir record will reflect any changes made.
+ * With sigs_only set only foreign key signatures are checked.
*/
static int
do_update_trust_record( KBNODE keyblock, TRUSTREC *drec,
- int recheck, int *modified )
+ int sigs_only, int *modified )
{
PKT_public_key *primary_pk;
TRUSTREC krec, urec, prec, helprec;
int i, rc = 0;
u32 keyid[2]; /* keyid of primary key */
-/* int mod_up = 0;
- int mod_down = 0; */
+ int mod_up = 0;
+ int mod_down = 0;
ulong recno, r2;
- u32 expire;
+ u32 expiretime;
primary_pk = find_kbnode( keyblock, PKT_PUBLIC_KEY )->pkt->pkt.public_key;
if( !primary_pk->local_id )
@@ -1425,7 +1511,7 @@ do_update_trust_record( KBNODE keyblock, TRUSTREC *drec,
if( rc )
return rc;
- /* delete the old stuff */
+ /* delete the old stuff FIXME: implementend sigs_only */
for( recno=drec->r.dir.keylist; recno; recno = krec.r.key.next ) {
read_record( recno, &krec, RECTYPE_KEY );
delete_record( recno );
@@ -1448,22 +1534,13 @@ do_update_trust_record( KBNODE keyblock, TRUSTREC *drec,
/* insert new stuff */
drec->r.dir.dirflags &= ~DIRF_REVOKED;
+ drec->r.dir.dirflags &= ~DIRF_NEWKEYS;
drec->r.dir.keylist = make_key_records( keyblock, drec->recnum, keyid, &i );
if( i ) /* primary key has been revoked */
- drec->r.dir.dirflags &= DIRF_REVOKED;
- expire = 0;
+ drec->r.dir.dirflags |= DIRF_REVOKED;
+ expiretime = 0;
drec->r.dir.uidlist = make_uid_records( keyblock, drec->recnum, keyid,
- &expire );
- #if 0
- if( orig_uidflags != urec.r.uid.uidflags ) {
- write_record( &urec );
- if( !( urec.r.uid.uidflags & UIDF_VALID )
- || ( urec.r.uid.uidflags & UIDF_REVOKED ) )
- *mod_down=1;
- else
- *mod_up=1; /*(maybe a new user id)*/
- #endif
-
+ &expiretime, &mod_down, &mod_up );
if( rc )
rc = tdbio_cancel_transaction();
else {
@@ -1471,9 +1548,9 @@ do_update_trust_record( KBNODE keyblock, TRUSTREC *drec,
*modified = 1;
drec->r.dir.dirflags |= DIRF_CHECKED;
drec->r.dir.valcheck = 0;
- drec->r.dir.checkat = expire;
+ drec->r.dir.checkat = expiretime;
write_record( drec );
- /*tdbio_write_modify_stamp( mod_up, mod_down );*/
+ tdbio_write_modify_stamp( mod_up, mod_down );
rc = tdbio_end_transaction();
}
return rc;
@@ -1538,16 +1615,28 @@ insert_trust_record( KBNODE keyblock )
}
}
+
/* mark tdb as modified upwards */
tdbio_write_modify_stamp( 1, 0 );
/* and put all the other stuff into the keydb */
- rc = do_update_trust_record( keyblock, &dirrec, 1, NULL );
+ rc = do_update_trust_record( keyblock, &dirrec, 0, NULL );
do_sync();
+
+ /* keep track of new keys */
+ if( !fresh_imported_keys )
+ fresh_imported_keys = new_lid_table();
+ ins_lid_table_item( fresh_imported_keys, pk->local_id, 0 );
+ if( ++fresh_imported_keys_count > FRESH_KEY_CHECK_THRESHOLD )
+ mark_fresh_keys();
+
return rc;
}
+
+
+
/****************
* Insert a trust record indentified by a PK into the TrustDB
*/
@@ -1585,7 +1674,7 @@ insert_trust_record_by_pk( PKT_public_key *pk )
* Currently we only do an update_trust_record.
*/
static int
-check_trust_record( TRUSTREC *drec )
+check_trust_record( TRUSTREC *drec, int sigs_only )
{
KBNODE keyblock;
int modified, rc;
@@ -1597,7 +1686,7 @@ check_trust_record( TRUSTREC *drec )
return rc;
}
- rc = do_update_trust_record( keyblock, drec, 0, &modified );
+ rc = do_update_trust_record( keyblock, drec, sigs_only, &modified );
release_kbnode( keyblock );
return rc;
@@ -1674,7 +1763,7 @@ update_trustdb()
/****************
- * Do all required check in the trustdb. This function walks over all
+ * Do all required checks in the trustdb. This function walks over all
* records in the trustdb and does scheduled processing.
*/
void
@@ -1682,7 +1771,7 @@ check_trustdb( const char *username )
{
TRUSTREC rec;
ulong recnum;
- ulong count=0, upd_count=0, err_count=0, skip_count=0;
+ ulong count=0, upd_count=0, err_count=0, skip_count=0, sigonly_count=0;
ulong current_time = make_timestamp();
if( username )
@@ -1691,15 +1780,25 @@ check_trustdb( const char *username )
init_trustdb();
for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
+ int sigs_only;
+
if( rec.rectype != RECTYPE_DIR )
continue; /* we only want the dir records */
if( count && !(count % 100) && !opt.quiet )
log_info(_("%lu keys so far processed\n"), count);
count++;
- if( !rec.r.dir.checkat || rec.r.dir.checkat > current_time ) {
- skip_count++;
- continue; /* not scheduled for checking */
+ sigs_only = 0;
+
+ if( !(rec.r.dir.dirflags & DIRF_CHECKED) )
+ ;
+ else if( !rec.r.dir.checkat || rec.r.dir.checkat > current_time ) {
+ if( !(rec.r.dir.dirflags & DIRF_NEWKEYS) ) {
+ skip_count++;
+ continue; /* not scheduled for checking */
+ }
+ sigs_only = 1; /* new public keys - check them */
+ sigonly_count++;
}
if( !rec.r.dir.keylist ) {
@@ -1708,11 +1807,12 @@ check_trustdb( const char *username )
continue;
}
- check_trust_record( &rec );
-
+ check_trust_record( &rec, sigs_only );
}
log_info(_("%lu keys processed\n"), count);
+ if( sigonly_count )
+ log_info(_("\t%lu due to new pubkeys\n"), sigonly_count);
if( skip_count )
log_info(_("\t%lu keys skipped\n"), skip_count);
if( err_count )
@@ -1772,8 +1872,12 @@ build_cert_tree( ulong lid, int depth, int max_depth, TN helproot )
return NULL;
}
- if( dirrec.r.dir.checkat && dirrec.r.dir.checkat <= make_timestamp() )
- check_trust_record( &dirrec );
+ if( dirrec.r.dir.checkat && dirrec.r.dir.checkat <= make_timestamp() ) {
+ check_trust_record( &dirrec, 0 );
+ }
+ else if( (dirrec.r.dir.dirflags & DIRF_NEWKEYS) ) {
+ check_trust_record( &dirrec, 1 );
+ }
keynode->n.k.ownertrust = dirrec.r.dir.ownertrust & TRUST_MASK;
@@ -1924,10 +2028,10 @@ propagate_validity( TN root, TN node, int (*add_fnc)(ulong), unsigned *retflgs )
}
/* loop over all user ids */
- for( ur=node->list; ur && max_validity < TRUST_FULLY; ur = ur->next ) {
+ for( ur=node->list; ur && max_validity <= TRUST_FULLY; ur = ur->next ) {
assert( ur->is_uid );
/* loop over all signators */
- for(kr=ur->list; kr && max_validity < TRUST_FULLY; kr = kr->next ) {
+ for(kr=ur->list; kr && max_validity <= TRUST_FULLY; kr = kr->next ) {
if( propagate_validity( root, kr, add_fnc, retflgs ) )
return -1; /* quit */
if( kr->n.k.validity == TRUST_ULTIMATE ) {
@@ -2001,8 +2105,12 @@ verify_key( int max_depth, TRUSTREC *drec, const char *namehash,
if( !tree )
return TRUST_UNDEFINED;
pv_result = propagate_validity( tree, tree, add_fnc, retflgs );
- if( namehash ) {
+ if( namehash && tree->n.k.validity != TRUST_ULTIMATE ) {
/* find the matching user id.
+ * We don't do this here if the key is ultimately trusted; in
+ * this case there will be no lids for the user IDs and frankly
+ * it does not make sense to compare by the name if we do
+ * have the secret key.
* fixme: the way we handle this is too inefficient */
TN ur;
TRUSTREC rec;
@@ -2075,6 +2183,7 @@ do_check( TRUSTREC *dr, unsigned *validity,
}
else if( !add_fnc
&& tdbio_db_matches_options()
+ /* FIXME, TODO: This comparision is WRONG ! */
&& dr->r.dir.valcheck
> tdbio_read_modify_stamp( (dr->r.dir.validity < TRUST_FULLY) )
&& dr->r.dir.validity )
@@ -2240,10 +2349,16 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel,
log_info(_("key %08lX.%lu: created in future "
"(time warp or clock problem)\n"),
(ulong)keyid[1], pk->local_id );
- return GPGERR_TIME_CONFLICT;
+ if( !opt.ignore_time_conflict )
+ return GPGERR_TIME_CONFLICT;
}
- if( rec.r.dir.checkat && rec.r.dir.checkat <= cur_time )
- check_trust_record( &rec );
+
+ if( !(rec.r.dir.dirflags & DIRF_CHECKED) )
+ check_trust_record( &rec, 0 );
+ else if( rec.r.dir.checkat && rec.r.dir.checkat <= cur_time )
+ check_trust_record( &rec, 0 );
+ else if( (rec.r.dir.dirflags & DIRF_NEWKEYS) )
+ check_trust_record( &rec, 1 );
if( pk->expiredate && pk->expiredate <= cur_time ) {
log_info(_("key %08lX.%lu: expired at %s\n"),
@@ -2299,6 +2414,51 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel,
}
+/****************
+ * scan the whole trustdb and mark all signature records whose keys
+ * are freshly imported.
+ */
+static void
+mark_fresh_keys()
+{
+ TRUSTREC dirrec, rec;
+ ulong recnum, lid;
+ int i;
+
+ memset( &dirrec, 0, sizeof dirrec );
+
+ for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
+ if( rec.rectype != RECTYPE_SIG )
+ continue;
+ /* if we have already have the dir record, we can check it now */
+ if( dirrec.recnum == rec.r.sig.lid
+ && (dirrec.r.dir.dirflags & DIRF_NEWKEYS) )
+ continue; /* flag is already set */
+
+ for(i=0; i < SIGS_PER_RECORD; i++ ) {
+ if( !(lid=rec.r.sig.sig[i].lid) )
+ continue; /* skip deleted sigs */
+ if( !(rec.r.sig.sig[i].flag & SIGF_CHECKED) )
+ continue; /* skip checked signatures */
+ if( qry_lid_table_flag( fresh_imported_keys, lid, NULL ) )
+ continue; /* not in the list of new keys */
+ read_record( rec.r.sig.lid, &dirrec, RECTYPE_DIR );
+ if( !(dirrec.r.dir.dirflags & DIRF_NEWKEYS) ) {
+ dirrec.r.dir.dirflags |= DIRF_NEWKEYS;
+ write_record( &dirrec );
+ }
+ break;
+ }
+ }
+
+ do_sync();
+
+ clear_lid_table( fresh_imported_keys );
+ fresh_imported_keys_count = 0;
+}
+
+
+
int
query_trust_info( PKT_public_key *pk, const byte *namehash )
{
@@ -2532,7 +2692,7 @@ enum_cert_paths_print( void **context, FILE *fp,
/*
* Return an allocated buffer with the preference values for
* the key with LID and the userid which is identified by the
- * HAMEHASH or the firstone if namehash is NULL. ret_n receives
+ * HAMEHASH or the first one if namehash is NULL. ret_n receives
* the length of the allocated buffer. Structure of the buffer is
* a repeated sequences of 2 bytes; where the first byte describes the
* type of the preference and the second one the value. The constants
diff --git a/g10/trustdb.h b/g10/trustdb.h
index 86351c1eb..1279edb0f 100644
--- a/g10/trustdb.h
+++ b/g10/trustdb.h
@@ -1,5 +1,5 @@
/* trustdb.h - Trust database
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -49,6 +49,7 @@ void check_trustdb( const char *username );
void update_trustdb( void );
int setup_trustdb( int level, const char *dbname );
void init_trustdb( void );
+void sync_trustdb( void );
int check_trust( PKT_public_key *pk, unsigned *r_trustlevel,
const byte* nh, int (*add_fnc)(ulong), unsigned *retflgs );
int query_trust_info( PKT_public_key *pk, const byte *nh );
diff --git a/g10/verify.c b/g10/verify.c
index 5fdf99338..f3f9a36eb 100644
--- a/g10/verify.c
+++ b/g10/verify.c
@@ -1,5 +1,5 @@
/* verify.c - verify signed data
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -25,14 +25,15 @@
#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 <gcrypt.h>
#include "util.h"
#include "main.h"
+#include "status.h"
#include "filter.h"
#include "ttyio.h"
#include "i18n.h"
@@ -58,6 +59,7 @@ verify_signatures( int nfiles, char **files )
int i, rc;
STRLIST sl;
+ memset( &afx, 0, sizeof afx);
sigfile = nfiles? *files : NULL;
/* open the signature file */
@@ -67,6 +69,51 @@ verify_signatures( int nfiles, char **files )
return GPGERR_OPEN_FILE;
}
+ if( !opt.no_armor && use_armor_filter( fp ) )
+ iobuf_push_filter( fp, armor_filter, &afx );
+
+ sl = NULL;
+ for(i=1 ; i < nfiles; i++ )
+ add_to_strlist( &sl, files[i] );
+ rc = proc_signature_packets( NULL, fp, sl, sigfile );
+ free_strlist(sl);
+ iobuf_close(fp);
+ if( afx.no_openpgp_data && rc == -1 ) {
+ log_error(_("the signature could not be verified.\n"
+ "Please remember that the signature file (.sig or .asc)\n"
+ "should be the first file given on the command line.\n") );
+ rc = 0;
+ }
+
+ return rc;
+}
+
+
+static void
+print_file_status( int status, const char *name, int what )
+{
+ char *p = gcry_xmalloc(strlen(name)+10);
+ sprintf(p, "%d %s", what, name );
+ write_status_text( status, p );
+ gcry_free(p);
+}
+
+
+static int
+verify_one_file( const char *name )
+{
+ IOBUF fp;
+ armor_filter_context_t afx;
+ int rc;
+
+ print_file_status( STATUS_FILE_START, name, 1 );
+ fp = iobuf_open(name);
+ if( !fp ) {
+ print_file_status( STATUS_FILE_ERROR, name, 1 );
+ log_error(_("can't open `%s'\n"), print_fname_stdin(name));
+ return GPGERR_OPEN_FILE;
+ }
+
if( !opt.no_armor ) {
if( use_armor_filter( fp ) ) {
memset( &afx, 0, sizeof afx);
@@ -74,14 +121,44 @@ verify_signatures( int nfiles, char **files )
}
}
- sl = NULL;
- for(i=1 ; i < nfiles; i++ )
- add_to_strlist( &sl, files[i] );
- rc = proc_signature_packets( NULL, fp, sl, sigfile );
- free_strlist(sl);
+ rc = proc_signature_packets( NULL, fp, NULL, name );
iobuf_close(fp);
+ write_status( STATUS_FILE_DONE );
return rc;
}
+/****************
+ * Verify each file given in the files array or read the names of the
+ * files from stdin.
+ * Note: This function can not handle detached signatures.
+ */
+int
+verify_files( int nfiles, char **files )
+{
+ int i;
+
+ if( !nfiles ) { /* read the filenames from stdin */
+ 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 GPGERR_GENERAL;
+ }
+ /* This code does not work on MSDOS but how cares there are
+ * also no script languages available. We don't strip any
+ * spaces, so that we can process nearly all filenames */
+ line[strlen(line)-1] = 0;
+ verify_one_file( line );
+ }
+
+ }
+ else { /* take filenames from the array */
+ for(i=0; i < nfiles; i++ )
+ verify_one_file( files[i] );
+ }
+ return 0;
+}