aboutsummaryrefslogtreecommitdiffstats
path: root/sm
diff options
context:
space:
mode:
Diffstat (limited to 'sm')
-rw-r--r--sm/ChangeLog1220
-rw-r--r--sm/Makefile.am56
-rw-r--r--sm/base64.c655
-rw-r--r--sm/call-agent.c635
-rw-r--r--sm/call-dirmngr.c785
-rw-r--r--sm/certchain.c976
-rw-r--r--sm/certcheck.c303
-rw-r--r--sm/certdump.c696
-rw-r--r--sm/certlist.c427
-rw-r--r--sm/certreqgen.c739
-rw-r--r--sm/decrypt.c512
-rw-r--r--sm/delete.c172
-rw-r--r--sm/encrypt.c511
-rw-r--r--sm/export.c736
-rw-r--r--sm/fingerprint.c331
-rw-r--r--sm/gpgsm.c1700
-rw-r--r--sm/gpgsm.h311
-rw-r--r--sm/import.c725
-rw-r--r--sm/keydb.c1532
-rw-r--r--sm/keydb.h85
-rw-r--r--sm/keylist.c1252
-rw-r--r--sm/misc.c65
-rw-r--r--sm/server.c1121
-rw-r--r--sm/sign.c666
-rw-r--r--sm/verify.c540
25 files changed, 0 insertions, 16751 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog
deleted file mode 100644
index c1a8f6411..000000000
--- a/sm/ChangeLog
+++ /dev/null
@@ -1,1220 +0,0 @@
-2004-06-06 Werner Koch <[email protected]>
-
- * certreqgen.c (get_parameter_uint, create_request): Create
- an extension for key usage when requested.
-
-2004-05-12 Werner Koch <[email protected]>
-
- * gpgsm.c (main): Install emergency_cleanup also as an atexit
- handler.
-
- * verify.c (gpgsm_verify): Removed the separate error code
- handling for KSBA. We use shared error codes anyway.
-
- * export.c (export_p12): Removed debugging code.
-
- * encrypt.c (gpgsm_encrypt): Put the session key in to secure memory.
-
-2004-05-11 Werner Koch <[email protected]>
-
- * sign.c (gpgsm_sign): Include the error source in the final error
- message.
- * decrypt.c (gpgsm_decrypt): Ditto.
-
- * fingerprint.c (gpgsm_get_key_algo_info): New.
- * sign.c (gpgsm_sign): Don't assume RSA in the status line.
- * keylist.c (list_cert_colon): Really print the algorithm and key
- length.
- (list_cert_raw, list_cert_std): Ditto.
- (list_cert_colon): Reorganized to be able to tell whether a root
- certificate is trusted.
-
- * gpgsm.c: New option --debug-allow-core-dump.
-
- * gpgsm.h (opt): Add member CONFIG_FILENAME.
- * gpgsm.c (main): Use it here instead of the local var.
-
- * server.c (gpgsm_server): Print some additional information with
- the hello in verbose mode.
-
-2004-04-30 Werner Koch <[email protected]>
-
- * import.c (check_and_store): Do not update the stats for hidden
- imports of issuer certs.
- (popen_protect_tool): Request statusmessages from the protect-tool.
- (parse_p12): Detect status messages. Add new arg STATS and update them.
- (print_imported_summary): Include secret key stats.
-
-2004-04-28 Werner Koch <[email protected]>
-
- * gpgsm.c: New command --keydb-clear-some-cert-flags.
- * keydb.c (keydb_clear_some_cert_flags): New.
- (keydb_update_keyblock, keydb_set_flags): Change error code
- CONFLICT to NOT_LOCKED.
-
-2004-04-26 Werner Koch <[email protected]>
-
- * gpgsm.c (main) <gpgconf>: Do not use /dev/null as default config
- filename.
-
- * call-agent.c (gpgsm_agent_pksign, gpgsm_agent_pkdecrypt)
- (gpgsm_agent_genkey, gpgsm_agent_istrusted)
- (gpgsm_agent_marktrusted, gpgsm_agent_havekey)
- (gpgsm_agent_passwd): Add new arg CTRL and changed all callers.
- (start_agent): New arg CTRL. Send progress item when starting a
- new agent.
- * sign.c (gpgsm_get_default_cert, get_default_signer): New arg
- CTRL to be passed down to the agent function.
- * decrypt.c (prepare_decryption): Ditto.
- * certreqgen.c (proc_parameters, read_parameters): Ditto.
- * certcheck.c (gpgsm_create_cms_signature): Ditto.
-
-2004-04-23 Werner Koch <[email protected]>
-
- * keydb.c (keydb_add_resource): Try to compress the file on init.
-
- * keylist.c (oidtranstbl): New. OIDs collected from several sources.
- (print_name_raw, print_names_raw, list_cert_raw): New.
- (gpgsm_list_keys): Check the dump mode and pass it down as
- necessary.
-
-2004-04-22 Werner Koch <[email protected]>
-
- * gpgsm.c (main): New commands --dump-keys, --dump-external-keys,
- --dump-secret-keys.
-
-2004-04-13 Werner Koch <[email protected]>
-
- * misc.c (setup_pinentry_env): New.
- * import.c (popen_protect_tool): Call it.
- * export.c (popen_protect_tool): Call it.
-
-2004-04-08 Werner Koch <[email protected]>
-
- * decrypt.c (gpgsm_decrypt): Return GPG_ERR_NO_DATA if it is not a
- encrypted message.
-
-2004-04-07 Werner Koch <[email protected]>
-
- * gpgsm.c: New option --force-crl-refresh.
- * call-dirmngr.c (gpgsm_dirmngr_isvalid): Pass option to dirmngr.
-
-2004-04-05 Werner Koch <[email protected]>
-
- * server.c (get_status_string): Add STATUS_NEWSIG.
- * verify.c (gpgsm_verify): Print STATUS_NEWSIG for each signature.
-
- * certchain.c (gpgsm_validate_chain) <gpgsm_cert_use_cer_p>: Do
- not just warn if a cert is not suitable; bail out immediately.
-
-2004-04-01 Werner Koch <[email protected]>
-
- * call-dirmngr.c (isvalid_status_cb): New.
- (unhexify_fpr): New. Taken from ../g10/call-agent.c
- (gpgsm_dirmngr_isvalid): Add new arg CTRL, changed caller to pass
- it thru. Detect need to check the respondert cert and do that.
- * certchain.c (gpgsm_validate_chain): Add new arg FLAGS. Changed
- all callers.
-
-2004-03-24 Werner Koch <[email protected]>
-
- * sign.c (gpgsm_sign): Include a short list of capabilities.
-
-2004-03-17 Werner Koch <[email protected]>
-
- * gpgsm.c (main) <gpgconf>: Fixed default value quoting.
-
-2004-03-16 Werner Koch <[email protected]>
-
- * gpgsm.c (main): Implemented --gpgconf-list.
-
-2004-03-15 Werner Koch <[email protected]>
-
- * keylist.c (list_cert_colon): Hack to set the expired flag.
-
-2004-03-09 Werner Koch <[email protected]>
-
- * gpgsm.c (main): Correctly intitialze USE_OCSP flag.
-
- * keydb.c (keydb_delete): s/GPG_ERR_CONFLICT/GPG_ERR_NOT_LOCKED/
-
-2004-03-04 Werner Koch <[email protected]>
-
- * call-dirmngr.c (gpgsm_dirmngr_isvalid): New arg ISSUER_CERT.
-
- * certchain.c (is_cert_still_valid): New. Code moved from ...
- (gpgsm_validate_chain): ... here because we now need to check at
- two places and at a later stage, so that we can pass the issuer
- cert down to the dirmngr.
-
-2004-03-03 Werner Koch <[email protected]>
-
- * call-agent.c (start_agent): Replaced pinentry setup code by a
- call to a new common function.
-
- * certdump.c (gpgsm_format_keydesc): Make sure the string is
- returned as utf-8.
-
- * export.c (gpgsm_export): Make sure that we don't export more
- than one certificate.
-
-2004-03-02 Werner Koch <[email protected]>
-
- * export.c (create_duptable, destroy_duptable)
- (insert_duptable): New.
- (gpgsm_export): Avoid duplicates.
-
-2004-02-26 Werner Koch <[email protected]>
-
- * certchain.c (compare_certs): New.
- (gpgsm_validate_chain): Fixed infinite certificate checks after
- bad signatures.
-
-2004-02-24 Werner Koch <[email protected]>
-
- * keylist.c (list_cert_colon): Print the fingerprint as the
- cert-id for root certificates.
-
-2004-02-21 Werner Koch <[email protected]>
-
- * keylist.c (list_internal_keys): Return error codes.
- (list_external_keys, gpgsm_list_keys): Ditto.
- * server.c (do_listkeys): Ditto.
-
- * gpgsm.c (main): Display a key description for --passwd.
- * call-agent.c (gpgsm_agent_passwd): New arg DESC.
-
-2004-02-20 Werner Koch <[email protected]>
-
- * gpgsm.c (main): New option --debug-ignore-expiration.
- * certchain.c (gpgsm_validate_chain): Use it here.
-
- * certlist.c (cert_usage_p): Apply extKeyUsage.
-
-2004-02-19 Werner Koch <[email protected]>
-
- * export.c (export_p12, popen_protect_tool)
- (gpgsm_p12_export): New.
- * gpgsm.c (main): New command --export-secret-key-p12.
-
-2004-02-18 Werner Koch <[email protected]>
-
- * gpgsm.c (set_debug): Set the new --debug-level flags.
- (main): New option --gpgconf-list.
- (main): Do not setup -u and -r keys when not required.
- (main): Setup the used character set.
-
- * keydb.c (keydb_add_resource): Print a hint to start the
- gpg-agent.
-
-2004-02-17 Werner Koch <[email protected]>
-
- * gpgsm.c: Fixed value parsing for --with-validation.
- * call-agent.c (start_agent): Ignore an empty GPG_AGENT_INFO.
- * call-dirmngr.c (start_dirmngr): Likewise for DIRMNGR_INFO.
-
- * gpgsm.c: New option --with-md5-fingerprint.
- * keylist.c (list_cert_std): Print MD5 fpr.
-
- * gpgsm.c: New options --with-validation.
- * server.c (option_handler): New option "with-validation".
- * keylist.c (list_cert_std, list_internal_keys): New args CTRL and
- WITH_VALIDATION. Changed callers to set it.
- (list_external_cb, list_external_keys): Pass CTRL to the callback.
- (list_cert_colon): Add arg CTRL. Check validation if requested.
- * certchain.c (unknown_criticals, allowed_ca, check_cert_policy)
- (gpgsm_validate_chain): New args LISTMODE and FP.
- (do_list): New helper for info output.
- (find_up): New arg FIND_NEXT.
- (gpgsm_validate_chain): After a bad signature try again with other
- CA certificates.
-
- * import.c (print_imported_status): New arg NEW_CERT. Print
- additional STATUS_IMPORT_OK becuase that is what gpgme expects.
- (check_and_store): Always call above function after import.
- * server.c (get_status_string): Added STATUS_IMPORT_OK.
-
-2004-02-13 Werner Koch <[email protected]>
-
- * certcheck.c (gpgsm_create_cms_signature): Format a description
- for use by the pinentry.
- * decrypt.c (gpgsm_decrypt): Ditto. Free HEXKEYGRIP.
- * certdump.c (format_name_cookie, format_name_writer)
- (gpgsm_format_name): New.
- (gpgsm_format_serial): New.
- (gpgsm_format_keydesc): New.
- * call-agent.c (gpgsm_agent_pksign): New arg DESC.
- (gpgsm_agent_pkdecrypt): Ditto.
-
- * encrypt.c (init_dek): Check for too weak algorithms.
-
- * import.c (parse_p12, popen_protect_tool): New.
-
- * base64.c (gpgsm_create_reader): New arg ALLOW_MULTI_PEM.
- Changed all callers.
- (base64_reader_cb): Handle it here.
- (gpgsm_reader_eof_seen): New.
- (base64_reader_cb): Set a flag for EOF.
- (simple_reader_cb): Ditto.
-
-2004-02-12 Werner Koch <[email protected]>
-
- * gpgsm.h, gpgsm.c: New option --protect-tool-program.
- * gpgsm.c (run_protect_tool): Use it.
-
-2004-02-11 Werner Koch <[email protected]>
-
- * Makefile.am (AM_CPPFLAGS): Pass directory constants via -D; this
- will allow to override directory names at make time.
-
-2004-02-02 Werner Koch <[email protected]>
-
- * import.c (check_and_store): Import certificates even with
- missing issuer's cert. Fixed an "depending on the verbose
- setting" bug.
-
- * certchain.c (gpgsm_validate_chain): Mark revoked certs in the
- keybox.
-
- * keylist.c (list_cert_colon): New arg VALIDITY; use it to print a
- revoked flag.
- (list_internal_keys): Retrieve validity flag.
- (list_external_cb): Pass 0 as validity flag.
- * keydb.c (keydb_get_flags, keydb_set_flags): New.
- (keydb_set_cert_flags): New.
- (lock_all): Return a proper error code.
- (keydb_lock): New.
- (keydb_delete): Don't lock but check that it has been locked.
- (keydb_update_keyblock): Ditto.
- * delete.c (delete_one): Take a lock.
-
-2004-01-30 Werner Koch <[email protected]>
-
- * certchain.c (check_cert_policy): Fixed read error checking.
- (check_cert_policy): With no critical policies issue only a
- warning if the policy file does not exists.
-
- * sign.c (add_certificate_list): Decrement N for the first cert.
-
-2004-01-29 Werner Koch <[email protected]>
-
- * certdump.c (parse_dn_part): Map common OIDs to human readable
- labels. Make sure that a value won't get truncated if it includes
- a Nul.
-
-2004-01-28 Werner Koch <[email protected]>
-
- * certchain.c (gpgsm_validate_chain): Changed the message printed
- for an untrusted root certificate.
-
-2004-01-27 Werner Koch <[email protected]>
-
- * certdump.c (parse_dn_part): Pretty print the nameDistinguisher OID.
- (print_dn_part): Do not delimit multiple RDN by " + ". Handle
- multi-valued RDNs in a special way, i.e. in the order specified by
- the certificate.
- (print_dn_parts): Simplified.
-
-2004-01-16 Werner Koch <[email protected]>
-
- * sign.c (gpgsm_sign): Print an error message on all failures.
- * decrypt.c (gpgsm_decrypt): Ditto.
-
-2003-12-17 Werner Koch <[email protected]>
-
- * server.c (gpgsm_server): Add arg DEFAULT_RECPLIST.
- (cmd_encrypt): Add all enrypt-to marked certs to the list.
- * encrypt.c (gpgsm_encrypt): Check that real recipients are
- available.
- * gpgsm.c (main): Make the --encrypt-to and --no-encrypt-to
- options work. Pass the list of recients to gpgsm_server.
- * gpgsm.h (certlist_s): Add field IS_ENCRYPT_TO.
- (opt): Add NO_ENCRYPT_TO.
- * certlist.c (gpgsm_add_to_certlist): New arg IS_ENCRYPT_TO.
- Changed all callers and ignore duplicate entries.
- (is_cert_in_certlist): New.
- (gpgsm_add_cert_to_certlist): New.
-
- * certdump.c (gpgsm_print_serial): Cleaned up cast use in strtoul.
- (gpgsm_dump_serial): Ditto.
-
- * decrypt.c (gpgsm_decrypt): Replaced ERR by RC.
-
-2003-12-16 Werner Koch <[email protected]>
-
- * gpgsm.c (main): Set the prefixes for assuan logging.
-
- * sign.c (gpgsm_sign): Add validation checks for the default
- certificate.
-
- * gpgsm.c: Add -k as alias for --list-keys and -K for
- --list-secret-keys.
-
-2003-12-15 Werner Koch <[email protected]>
-
- * encrypt.c (init_dek): Use gry_create_nonce for the IV; there is
- not need for real strong random here and it even better protect
- the random bits used for the key.
-
-2003-12-01 Werner Koch <[email protected]>
-
- * gpgsm.c, gpgsm.h: New options --{enable,disable}-ocsp.
- (gpgsm_init_default_ctrl): Set USE_OCSP to the default value.
- * certchain.c (gpgsm_validate_chain): Handle USE_OCSP.
- * call-dirmngr.c (gpgsm_dirmngr_isvalid): Add arg USE_OCSP and
- proceed accordingly.
-
-2003-11-19 Werner Koch <[email protected]>
-
- * verify.c (gpgsm_verify): Use "0" instead of an empty string for
- the VALIDSIG status.
-
-2003-11-18 Werner Koch <[email protected]>
-
- * verify.c (gpgsm_verify): Fixed for changes API of gcry_md_info.
-
- * certchain.c (unknown_criticals): Fixed an error code test.
-
-2003-11-12 Werner Koch <[email protected]>
-
- Adjusted for API changes in Libksba.
-
-2003-10-31 Werner Koch <[email protected]>
-
- * certchain.c (gpgsm_validate_chain): Changed to use ksba_isotime_t.
- * verify.c (strtimestamp_r, gpgsm_verify): Ditto.
- * sign.c (gpgsm_sign): Ditto.
- * keylist.c (print_time, list_cert_std, list_cert_colon): Ditto.
- * certdump.c (gpgsm_print_time, gpgsm_dump_time, gpgsm_dump_cert):
- Ditto.
-
-2003-10-25 Werner Koch <[email protected]>
-
- * certreqgen.c (read_parameters): Fixed faulty of !spacep().
-
-2003-08-20 Marcus Brinkmann <[email protected]>
-
- * encrypt.c (encode_session_key): Allocate enough space. Cast key
- byte to unsigned char to prevent sign extension.
- (encrypt_dek): Check return value before error.
-
-2003-08-14 Timo Schulz <[email protected]>
-
- * encrypt.c (encode_session_key): Use new Libgcrypt interface.
-
-2003-07-31 Werner Koch <[email protected]>
-
- * Makefile.am (gpgsm_LDADD): Added INTLLIBS.
-
-2003-07-29 Werner Koch <[email protected]>
-
- * gpgsm.c (main): Add secmem features and set the random seed file.
- (gpgsm_exit): Update the random seed file and enable debug output.
-
-2003-07-27 Werner Koch <[email protected]>
-
- Adjusted for gcry_mpi_print and gcry_mpi_scan API change.
-
-2003-06-24 Werner Koch <[email protected]>
-
- * server.c (gpgsm_status_with_err_code): New.
- * verify.c (gpgsm_verify): Use it here instead of the old
- tokenizing version.
-
- * verify.c (strtimestamp): Renamed to strtimestamp_r
-
- Adjusted for changes in the libgcrypt API. Some more fixes for the
- libgpg-error stuff.
-
-2003-06-04 Werner Koch <[email protected]>
-
- * call-agent.c (init_membuf,put_membuf,get_membuf): Removed.
- Include new membuf header and changed used type.
-
- Renamed error codes from INVALID to INV and removed _ERROR suffixes.
-
-2003-06-03 Werner Koch <[email protected]>
-
- Changed all error codes in all files to the new libgpg-error scheme.
-
- * gpgsm.h: Include gpg-error.h .
- * Makefile.am: Link with libgpg-error.
-
-2003-04-29 Werner Koch <[email protected]>
-
- * Makefile.am: Use libassuan. Don't override LDFLAGS anymore.
- * server.c (register_commands): Adjust for new Assuan semantics.
-
-2002-12-03 Werner Koch <[email protected]>
-
- * call-agent.c (gpgsm_agent_passwd): New.
- * gpgsm.c (main): New command --passwd and --call-protect-tool
- (run_protect_tool): New.
-
-2002-11-25 Werner Koch <[email protected]>
-
- * verify.c (gpgsm_verify): Handle content-type attribute.
-
-2002-11-13 Werner Koch <[email protected]>
-
- * call-agent.c (start_agent): Try to use $GPG_TTY instead of
- ttyname. Changed ttyname to test stdin becuase it can be assumed
- that output redirection is more common that input redirection.
-
-2002-11-12 Werner Koch <[email protected]>
-
- * gpgsm.c: New command --call-dirmngr.
- * call-dirmngr.c (gpgsm_dirmngr_run_command)
- (run_command_inq_cb,run_command_cb)
- (run_command_status_cb): New.
-
-2002-11-11 Werner Koch <[email protected]>
-
- * certcheck.c (gpgsm_check_cms_signature): Don't double free
- s_sig but free s_pkey at leave.
-
-2002-11-10 Werner Koch <[email protected]>
-
- * gpgsm.c: Removed duplicate --list-secret-key entry.
-
-2002-09-19 Werner Koch <[email protected]>
-
- * certcheck.c (gpgsm_check_cert_sig): Add cert hash debugging.
-
- * certchain.c (find_up): Print info when the cert was not found
- by the autorithyKeyIdentifier.
-
-2002-09-03 Werner Koch <[email protected]>
-
- * gpgsm.c (main): Disable the internal libgcrypt locking.
-
-2002-08-21 Werner Koch <[email protected]>
-
- * import.c (print_imported_summary): Cleaned up. Print new
- not_imported value.
- (check_and_store): Update non_imported counter.
- (print_import_problem): New.
- (check_and_store): Print error status message.
- * server.c (get_status_string): Added STATUS_IMPORT_PROBLEM.
-
-2002-08-20 Werner Koch <[email protected]>
-
- * gpgsm.c (main): Use the log file only in server mode.
-
- * import.c (print_imported_summary): New.
- (check_and_store): Update the counters, take new argument.
- (import_one): Factored out core of gpgsm_import.
- (gpgsm_import): Print counters.
- (gpgsm_import_files): New.
- * gpgsm.c (main): Use the new function for import.
-
-2002-08-19 Werner Koch <[email protected]>
-
- * decrypt.c (gpgsm_decrypt): Return a better error status token.
- * verify.c (gpgsm_verify): Don't error on messages with no signing
- time or no message digest. This is only the case for messages
- without any signed attributes.
-
-2002-08-16 Werner Koch <[email protected]>
-
- * certpath.c: Renamed to ..
- * certchain.c: this. Renamed all all other usages of "path" in the
- context of certificates to "chain".
-
- * call-agent.c (learn_cb): Special treatment when the issuer
- certificate is missing.
-
-2002-08-10 Werner Koch <[email protected]>
-
- * Makefile.am (INCLUDES): Add definition for localedir.
-
- * keylist.c (list_cert_colon): Print the short fingerprint in the
- key ID field.
- * fingerprint.c (gpgsm_get_short_fingerprint): New.
- * verify.c (gpgsm_verify): Print more verbose info for a good
- signature.
-
-2002-08-09 Werner Koch <[email protected]>
-
- * decrypt.c (prepare_decryption): Hack to detected already
- unpkcsedone keys.
-
- * gpgsm.c (emergency_cleanup): New.
- (main): Initialize the signal handler.
-
- * sign.c (gpgsm_sign): Reset the hash context for subsequent
- signers and release it at the end.
-
-2002-08-05 Werner Koch <[email protected]>
-
- * server.c (cmd_signer): New command "SIGNER"
- (register_commands): Register it.
- (cmd_sign): Pass the signer list to gpgsm_sign.
- * certlist.c (gpgsm_add_to_certlist): Add SECRET argument, check
- for secret key if set and changed all callers.
- * sign.c (gpgsm_sign): New argument SIGNERLIST and implemt
- multiple signers.
- * gpgsm.c (main): Support more than one -u.
-
- * server.c (cmd_recipient): Return reason code 1 for No_Public_Key
- which is actually what gets returned from add_to_certlist.
-
-2002-07-26 Werner Koch <[email protected]>
-
- * certcheck.c (gpgsm_check_cert_sig): Implement proper cleanup.
- (gpgsm_check_cms_signature): Ditto.
-
-2002-07-22 Werner Koch <[email protected]>
-
- * keydb.c (keydb_add_resource): Register a lock file.
- (lock_all, unlock_all): Implemented.
-
- * delete.c: New.
- * gpgsm.c: Made --delete-key work.
- * server.c (cmd_delkeys): New.
- (register_commands): New command DELKEYS.
-
- * decrypt.c (gpgsm_decrypt): Print a convenience note when RC2 is
- used and a STATUS_ERROR with the algorithm oid.
-
-2002-07-03 Werner Koch <[email protected]>
-
- * server.c (gpgsm_status2): Insert a blank between all optional
- arguments when using assuan.
- * server.c (cmd_recipient): No more need for extra blank in constants.
- * import.c (print_imported_status): Ditto.
- * gpgsm.c (main): Ditto.
-
-2002-07-02 Werner Koch <[email protected]>
-
- * verify.c (gpgsm_verify): Extend the STATUS_BADSIG line with
- the fingerprint.
-
- * certpath.c (check_cert_policy): Don't use log_error to print a
- warning.
-
- * keydb.c (keydb_store_cert): Add optional ar EXISTED and changed
- all callers.
- * call-agent.c (learn_cb): Print info message only for real imports.
-
- * import.c (gpgsm_import): Moved duplicated code to ...
- (check_and_store): new function. Added magic to import the entire
- chain. Print status only for real imports and moved printing code
- to ..
- (print_imported_status): New.
-
- * call-dirmngr.c (gpgsm_dirmngr_isvalid): print status of dirmngr
- call in very verbose mode.
-
- * gpgsm.c (main): Use the same error codes for STATUS_INV_RECP as
- with the server mode.
-
-2002-06-29 Werner Koch <[email protected]>
-
- * gpgsm.c: New option --auto-issuer-key-retrieve.
- * certpath.c (find_up): Try to retrieve an issuer key from an
- external source and from the ephemeral key DB.
- (find_up_store_certs_cb): New.
-
- * keydb.c (keydb_set_ephemeral): Does now return the old
- state. Call the backend only when required.
-
- * call-dirmngr.c (start_dirmngr): Use GNUPG_DEFAULT_DIRMNGR.
- (lookup_status_cb): Issue status only when CTRL is not NULL.
- (gpgsm_dirmngr_lookup): Document that CTRL is optional.
-
- * call-agent.c (start_agent): Use GNUPG_DEFAULT_AGENT.
-
-2002-06-28 Werner Koch <[email protected]>
-
- * server.c (cmd_recipient): Add more reason codes.
-
-2002-06-27 Werner Koch <[email protected]>
-
- * certpath.c (gpgsm_basic_cert_check): Use
- --debug-no-path-validation to also bypass this basic check.
-
- * gpgsm.c (main): Use GNUPG_DEFAULT_HOMEDIR constant.
-
- * call-agent.c (start_agent): Create and pass the list of FD to
- keep in the child to assuan.
- * call-dirmngr.c (start_dirmngr): Ditto.
-
-2002-06-26 Werner Koch <[email protected]>
-
- * import.c (gpgsm_import): Print an STATUS_IMPORTED.
-
- * gpgsm.c: --debug-no-path-validation does not take an argument.
-
-2002-06-25 Werner Koch <[email protected]>
-
- * certdump.c (print_dn_part): Always print a leading slash,
- removed NEED_DELIM arg and changed caller.
-
- * export.c (gpgsm_export): Print LFs to FP and not stdout.
- (print_short_info): Ditto. Make use of gpgsm_print_name.
-
- * server.c (cmd_export): Use output-fd instead of data lines; this
- was actually the specified way.
-
-2002-06-24 Werner Koch <[email protected]>
-
- * gpgsm.c: Removed duped help entry for --list-keys.
-
- * gpgsm.c, gpgsm.h: New option --debug-no-path-validation.
-
- * certpath.c (gpgsm_validate_path): Use it here instead of the
- debug flag hack.
-
- * certpath.c (check_cert_policy): Return No_Policy_Match if the
- policy file could not be opened.
-
-2002-06-20 Werner Koch <[email protected]>
-
- * certlist.c (gpgsm_add_to_certlist): Fixed locating of a
- certificate with the required key usage.
-
- * gpgsm.c (main): Fixed a segv when using --outfile without an
- argument.
-
- * keylist.c (print_capabilities): Also check for non-repudiation
- and data encipherment.
- * certlist.c (cert_usage_p): Test for signing and encryption was
- swapped. Add a case for certification usage, handle
- non-repudiation and data encipherment.
- (gpgsm_cert_use_cert_p): New.
- (gpgsm_add_to_certlist): Added a CTRL argument and changed all
- callers to pass it.
- * certpath.c (gpgsm_validate_path): Use it here to print a status
- message. Added a CTRL argument and changed all callers to pass it.
- * decrypt.c (gpgsm_decrypt): Print a status message for wrong key
- usage.
- * verify.c (gpgsm_verify): Ditto.
- * keydb.c (classify_user_id): Allow a colon delimited fingerprint.
-
-2002-06-19 Werner Koch <[email protected]>
-
- * call-agent.c (learn_cb): Use log_info instead of log_error on
- successful import.
-
- * keydb.c (keydb_set_ephemeral): New.
- (keydb_store_cert): New are ephemeral, changed all callers.
- * keylist.c (list_external_cb): Store cert as ephemeral.
- * export.c (gpgsm_export): Kludge to export epehmeral certificates.
-
- * gpgsm.c (main): New command --list-external-keys.
-
-2002-06-17 Werner Koch <[email protected]>
-
- * certreqgen.c (read_parameters): Improved error handling.
- (gpgsm_genkey): Print error message.
-
-2002-06-13 Werner Koch <[email protected]>
-
- * gpgsm.c (main): New option --log-file.
-
-2002-06-12 Werner Koch <[email protected]>
-
- * call-dirmngr.c (lookup_status_cb): New.
- (gpgsm_dirmngr_lookup): Use the status CB. Add new arg CTRL and
- changed caller to pass it.
-
- * gpgsm.c (open_fwrite): New.
- (main): Allow --output for --verify.
-
- * sign.c (hash_and_copy_data): New.
- (gpgsm_sign): Implemented normal (non-detached) signatures.
- * gpgsm.c (main): Ditto.
-
- * certpath.c (gpgsm_validate_path): Special error handling for
- no policy match.
-
-2002-06-10 Werner Koch <[email protected]>
-
- * server.c (get_status_string): Add STATUS_ERROR.
-
- * certpath.c (gpgsm_validate_path): Tweaked the error checking to
- return error codes in a more sensitive way.
- * verify.c (gpgsm_verify): Send status TRUST_NEVER also for a bad
- CA certificate and when the certificate has been revoked. Issue
- TRUST_FULLY even when the cert has expired. Append an error token
- to these status lines. Issue the new generic error status when a
- cert was not found and when leaving the function.
-
-2002-06-04 Werner Koch <[email protected]>
-
- * gpgsm.c (main): New command --list-sigs
- * keylist.c (list_cert_std): New. Use it whenever colon mode is
- not used.
- (list_cert_chain): New.
-
-2002-05-31 Werner Koch <[email protected]>
-
- * gpgsm.c (main): Don't print the "go ahead" message for an
- invalid command.
-
-2002-05-23 Werner Koch <[email protected]>
-
- * import.c (gpgsm_import): Add error messages.
-
-2002-05-21 Werner Koch <[email protected]>
-
- * keylist.c (list_internal_keys): Renamed from gpgsm_list_keys.
- (list_external_keys): New.
- (gpgsm_list_keys): Dispatcher for above.
- * call-dirmngr.c (lookup_cb,pattern_from_strlist)
- (gpgsm_dirmngr_lookup): New.
- * server.c (option_handler): Handle new option --list-mode.
- (do_listkeys): Handle options and actually use the mode argument.
- (get_status_string): New code TRUNCATED.
-
- * import.c (gpgsm_import): Try to identify the type of input and
- handle certs-only messages.
-
-2002-05-14 Werner Koch <[email protected]>
-
- * gpgsm.c: New option --faked-system-time
- * sign.c (gpgsm_sign): And use it here.
- * certpath.c (gpgsm_validate_path): Ditto.
-
-2002-05-03 Werner Koch <[email protected]>
-
- * certpath.c (gpgsm_validate_path): Added EXPTIME arg and changed
- all callers.
- * verify.c (gpgsm_verify): Tweaked usage of log_debug and
- log_error. Return EXPSIG status and add expiretime to VALIDSIG.
-
-2002-04-26 Werner Koch <[email protected]>
-
- * gpgsm.h (DBG_AGENT,DBG_AGENT_VALUE): Replaced by DBG_ASSUAN_*.
- Changed all users.
-
- * call-agent.c (start_agent): Be more silent without -v.
- * call-dirmngr.c (start_dirmngr): Ditto.
-
-2002-04-25 Werner Koch <[email protected]>
-
- * call-agent.c (start_agent): Make copies of old locales and check
- for setlocale.
-
-2002-04-25 Marcus Brinkmann <[email protected]>
-
- * call-agent.c (start_agent): Fix error handling logic so the
- locale is always correctly reset.
-
-2002-04-25 Marcus Brinkmann <[email protected]>
-
- * server.c (option_handler): Accept display, ttyname, ttytype,
- lc_ctype and lc_messages options.
- * gpgsm.c (main): Allocate memory for these options.
- * gpgsm.h (struct opt): Make corresponding members non-const.
-
-2002-04-24 Marcus Brinkmann <[email protected]>
-
- * gpgsm.h (struct opt): New members display, ttyname, ttytype,
- lc_ctype, lc_messages.
- * gpgsm.c (enum cmd_and_opt_values): New members oDisplay,
- oTTYname, oTTYtype, oLCctype, oLCmessages.
- (opts): New entries for these options.
- (main): Handle these new options.
- * call-agent.c (start_agent): Set the various display and tty
- parameter after resetting.
-
-2002-04-18 Werner Koch <[email protected]>
-
- * certreqgen.c (gpgsm_genkey): Write status output on success.
-
-2002-04-15 Werner Koch <[email protected]>
-
- * gpgsm.c (main): Check ksba version.
-
- * certpath.c (find_up): New to use the authorithKeyIdentifier.
- Use it in all other functions to locate the signing cert..
-
-2002-04-11 Werner Koch <[email protected]>
-
- * certlist.c (cert_usable_p): New.
- (gpgsm_cert_use_sign_p,gpgsm_cert_use_encrypt_p): New.
- (gpgsm_cert_use_verify_p,gpgsm_cert_use_decrypt_p): New.
- (gpgsm_add_to_certlist): Check the key usage.
- * sign.c (gpgsm_sign): Ditto.
- * verify.c (gpgsm_verify): Print a message wehn an unsuitable
- certificate was used.
- * decrypt.c (gpgsm_decrypt): Ditto
- * keylist.c (print_capabilities): Determine values from the cert.
-
-2002-03-28 Werner Koch <[email protected]>
-
- * keylist.c (list_cert_colon): Fixed listing of crt record; the
- issuer is not at the right place. Print a chainingID.
- * certpath.c (gpgsm_walk_cert_chain): Be a bit more silent on
- common errors.
-
-2002-03-21 Werner Koch <[email protected]>
-
- * export.c: New.
- * gpgsm.c: Add command --export.
- * server.c (cmd_export): New.
-
-2002-03-13 Werner Koch <[email protected]>
-
- * decrypt.c (gpgsm_decrypt): Allow multiple recipients.
-
-2002-03-12 Werner Koch <[email protected]>
-
- * certpath.c (check_cert_policy): Print the policy list.
-
- * verify.c (gpgsm_verify): Detect certs-only message.
-
-2002-03-11 Werner Koch <[email protected]>
-
- * import.c (gpgsm_import): Print a notice about imported certificates
- when in verbose mode.
-
- * gpgsm.c (main): Print INV_RECP status.
- * server.c (cmd_recipient): Ditto.
-
- * server.c (gpgsm_status2): New. Allows for a list of strings.
- (gpgsm_status): Divert to gpgsm_status2.
-
- * encrypt.c (gpgsm_encrypt): Don't use a default key when no
- recipients are given. Print a NO_RECP status.
-
-2002-03-06 Werner Koch <[email protected]>
-
- * server.c (cmd_listkeys, cmd_listsecretkeys): Divert to
- (do_listkeys): new. Add pattern parsing.
-
- * keylist.c (gpgsm_list_keys): Handle selection pattern.
-
- * gpgsm.c: New command --learn-card
- * call-agent.c (learn_cb,gpgsm_agent_learn): New.
-
- * gpgsm.c (main): Print error messages for non-implemented commands.
-
- * base64.c (base64_reader_cb): Use case insensitive compare of the
- Content-Type string to detect plain base-64.
-
-2002-03-05 Werner Koch <[email protected]>
-
- * gpgsm.c, gpgsm.h: Add local_user.
- * sign.c (gpgsm_get_default_cert): New.
- (get_default_signer): Use the new function if local_user is not
- set otherwise used that value.
- * encrypt.c (get_default_recipient): Removed.
- (gpgsm_encrypt): Use gpgsm_get_default_cert.
-
- * verify.c (gpgsm_verify): Better error text for a bad signature
- found by comparing the hashs.
-
-2002-02-27 Werner Koch <[email protected]>
-
- * call-dirmngr.c, call-agent.c: Add 2 more arguments to all uses
- of assuan_transact.
-
-2002-02-25 Werner Koch <[email protected]>
-
- * server.c (option_handler): Allow to use -2 for "send all certs
- except the root cert".
- * sign.c (add_certificate_list): Implement it here.
- * certpath.c (gpgsm_is_root_cert): New.
-
-2002-02-19 Werner Koch <[email protected]>
-
- * certpath.c (check_cert_policy): New.
- (gpgsm_validate_path): And call it from here.
- * gpgsm.c (main): New options --policy-file,
- --disable-policy-checks and --enable-policy-checks.
- * gpgsm.h (opt): Added policy_file, no_policy_checks.
-
-2002-02-18 Werner Koch <[email protected]>
-
- * certpath.c (gpgsm_validate_path): Ask the agent to add the
- certificate into the trusted list.
- * call-agent.c (gpgsm_agent_marktrusted): New.
-
-2002-02-07 Werner Koch <[email protected]>
-
- * certlist.c (gpgsm_add_to_certlist): Check that the specified
- name identifies a certificate unambiguously.
- (gpgsm_find_cert): Ditto.
-
- * server.c (cmd_listkeys): Check that the data stream is available.
- (cmd_listsecretkeys): Ditto.
- (has_option): New.
- (cmd_sign): Fix ambiguousity in option recognition.
-
- * gpgsm.c (main): Enable --logger-fd.
-
- * encrypt.c (gpgsm_encrypt): Increased buffer size for better
- performance.
-
- * call-agent.c (gpgsm_agent_pksign): Check the S-Exp received from
- the agent.
-
- * keylist.c (list_cert_colon): Filter out control characters.
-
-2002-02-06 Werner Koch <[email protected]>
-
- * decrypt.c (gpgsm_decrypt): Bail out after an decryption error.
-
- * server.c (reset_notify): Close input and output FDs.
- (cmd_encrypt,cmd_decrypt,cmd_verify,cmd_sign.cmd_import)
- (cmd_genkey): Close the FDs and release the recipient list even in
- the error case.
-
-2002-02-01 Marcus Brinkmann <[email protected]>
-
- * sign.c (gpgsm_sign): Do not release certificate twice.
-
-2002-01-29 Werner Koch <[email protected]>
-
- * call-agent.c (gpgsm_agent_havekey): New.
- * keylist.c (list_cert_colon): New arg HAVE_SECRET, print "crs"
- when we know that the secret key is available.
- (gpgsm_list_keys): New arg MODE, check whether a secret key is
- available. Changed all callers.
- * gpgsm.c (main): New command --list-secret-keys.
- * server.c (cmd_listsecretkeys): New.
- (cmd_listkeys): Return secret keys with "crs" record.
-
-2002-01-28 Werner Koch <[email protected]>
-
- * certreqgen.c (create_request): Store the email address in the req.
-
-2002-01-25 Werner Koch <[email protected]>
-
- * gpgsm.c (main): Disable core dumps.
-
- * sign.c (add_certificate_list): New.
- (gpgsm_sign): Add the certificates to the CMS object.
- * certpath.c (gpgsm_walk_cert_chain): New.
- * gpgsm.h (server_control_s): Add included_certs.
- * gpgsm.c: Add option --include-certs.
- (gpgsm_init_default_ctrl): New.
- (main): Call it.
- * server.c (gpgsm_server): Ditto.
- (option_handler): Support --include-certs.
-
-2002-01-23 Werner Koch <[email protected]>
-
- * certpath.c (gpgsm_validate_path): Print the DN of a missing issuer.
- * certdump.c (gpgsm_dump_string): New.
- (print_dn): Replaced by above.
-
-2002-01-22 Werner Koch <[email protected]>
-
- * certpath.c (unknown_criticals): New.
- (allowed_ca): New.
- (gpgsm_validate_path): Check validity, CA attribute, path length
- and unknown critical extensions.
-
-2002-01-21 Werner Koch <[email protected]>
-
- * gpgsm.c: Add option --enable-crl-checks.
-
- * call-agent.c (start_agent): Implemented socket based access.
- * call-dirmngr.c (start_dirmngr): Ditto.
-
-2002-01-20 Werner Koch <[email protected]>
-
- * server.c (option_handler): New.
- (gpgsm_server): Register it with assuan.
-
-2002-01-19 Werner Koch <[email protected]>
-
- * server.c (gpgsm_server): Use assuan_deinit_server and setup
- assuan logging if enabled.
- * call-agent.c (inq_ciphertext_cb): Don't show the session key in
- an Assuan log file.
-
- * gpgsm.c (my_strusage): Take bugreport address from configure.ac
-
-2002-01-15 Werner Koch <[email protected]>
-
- * import.c (gpgsm_import): Just do a basic cert check before
- storing it.
- * certpath.c (gpgsm_basic_cert_check): New.
-
- * keydb.c (keydb_store_cert): New.
- * import.c (store_cert): Removed and change all caller to use
- the new function.
- * verify.c (store_cert): Ditto.
-
- * certlist.c (gpgsm_add_to_certlist): Validate the path
-
- * certpath.c (gpgsm_validate_path): Check the trust list.
- * call-agent.c (gpgsm_agent_istrusted): New.
-
-2002-01-14 Werner Koch <[email protected]>
-
- * call-dirmngr.c (inq_certificate): Changed for new interface semantic.
- * certlist.c (gpgsm_find_cert): New.
-
-2002-01-13 Werner Koch <[email protected]>
-
- * fingerprint.c (gpgsm_get_certid): Print the serial and not the
- hash after the dot.
-
-2002-01-11 Werner Koch <[email protected]>
-
- * call-dirmngr.c: New.
- * certpath.c (gpgsm_validate_path): Check the CRL here.
- * fingerprint.c (gpgsm_get_certid): New.
- * gpgsm.c: New options --dirmngr-program and --disable-crl-checks.
-
-2002-01-10 Werner Koch <[email protected]>
-
- * base64.c (gpgsm_create_writer): Allow to set the object name
-
-2002-01-08 Werner Koch <[email protected]>
-
- * keydb.c (spacep): Removed because it is now in util.c
-
- * server.c (cmd_genkey): New.
- * certreqgen.c: New. The parameter handling code has been taken
- from gnupg/g10/keygen.c version 1.0.6.
- * call-agent.c (gpgsm_agent_genkey): New.
-
-2002-01-02 Werner Koch <[email protected]>
-
- * server.c (rc_to_assuan_status): Removed and changed all callers
- to use map_to_assuan_status.
-
-2001-12-20 Werner Koch <[email protected]>
-
- * verify.c (gpgsm_verify): Implemented non-detached signature
- verification. Add OUT_FP arg, initialize a writer and changed all
- callers.
- * server.c (cmd_verify): Pass an out_fp if one has been set.
-
- * base64.c (base64_reader_cb): Try to detect an S/MIME body part.
-
- * certdump.c (print_sexp): Renamed to gpgsm_dump_serial, made
- global.
- (print_time): Renamed to gpgsm_dump_time, made global.
- (gpgsm_dump_serial): Take a real S-Expression as argument and
- print the first item.
- * keylist.c (list_cert_colon): Ditto.
- * keydb.c (keydb_search_issuer_sn): Ditto.
- * decrypt.c (print_integer_sexp): Removed and made callers
- use gpgsm_dump_serial.
- * verify.c (print_time): Removed, made callers use gpgsm_dump_time.
-
-2001-12-19 Marcus Brinkmann <[email protected]>
-
- * call-agent.c (start_agent): Add new argument to assuan_pipe_connect.
-
-2001-12-18 Werner Koch <[email protected]>
-
- * verify.c (print_integer_sexp): Renamed from print_integer and
- print the serial number according to the S-Exp rules.
- * decrypt.c (print_integer_sexp): Ditto.
-
-2001-12-17 Werner Koch <[email protected]>
-
- * keylist.c (list_cert_colon): Changed for new return value of
- get_serial.
- * keydb.c (keydb_search_issuer_sn): Ditto.
- * certcheck.c (gpgsm_check_cert_sig): Likewise for other S-Exp
- returingin functions.
- * fingerprint.c (gpgsm_get_keygrip): Ditto.
- * encrypt.c (encrypt_dek): Ditto
- * certcheck.c (gpgsm_check_cms_signature): Ditto
- * decrypt.c (prepare_decryption): Ditto.
- * call-agent.c (gpgsm_agent_pkdecrypt): Removed arg ciphertextlen,
- use KsbaSexp type and calculate the length.
-
- * certdump.c (print_sexp): Remaned from print_integer, changed caller.
-
- * Makefile.am: Use the LIBGCRYPT and LIBKSBA variables.
-
- * fingerprint.c (gpgsm_get_keygrip): Use the new
- gcry_pk_get_keygrip to calculate the grip - note the algorithm and
- therefore the grip values changed.
-
-2001-12-15 Werner Koch <[email protected]>
-
- * certcheck.c (gpgsm_check_cms_signature): Removed the faked-key
- kludge.
- (gpgsm_create_cms_signature): Removed the commented fake key
- code. This makes the function pretty simple.
-
- * gpgsm.c (main): Renamed the default key database to "keyring.kbx".
-
- * decrypt.c (gpgsm_decrypt): Write STATUS_DECRYPTION_*.
- * sign.c (gpgsm_sign): Write a STATUS_SIG_CREATED.
-
-2001-12-14 Werner Koch <[email protected]>
-
- * keylist.c (list_cert_colon): Kludge to show an email address
- encoded in the subject's DN.
-
- * verify.c (gpgsm_verify): Add hash debug helpers
- * sign.c (gpgsm_sign): Ditto.
-
- * base64.c (base64_reader_cb): Reset the linelen when we need to
- skip the line and adjusted test; I somehow forgot about DeMorgan.
-
- * server.c (cmd_encrypt,cmd_decrypt,cmd_sign,cmd_verify)
- (cmd_import): Close the FDs on success.
- (close_message_fd): New.
- (input_notify): Setting autodetect_encoding to 0 after initializing
- it to 0 is pretty pointless. Easy to fix.
-
- * gpgsm.c (main): New option --debug-wait n, so that it is
- possible to attach gdb when used in server mode.
-
- * sign.c (get_default_signer): Use keydb_classify_name here.
-
-2001-12-14 Marcus Brinkmann <[email protected]>
-
- * call-agent.c (LINELENGTH): Removed.
- (gpgsm_agent_pksign): Use ASSUAN_LINELENGTH, not LINELENGTH.
- (gpgsm_agent_pkdecrypt): Likewise.
-
-2001-12-13 Werner Koch <[email protected]>
-
- * keylist.c (list_cert_colon): Print alternative names of subject
- and a few other values.
-
-2001-12-12 Werner Koch <[email protected]>
-
- * gpgsm.c (main): New options --assume-{armor,base64,binary}.
- * base64.c (base64_reader_cb): Fixed non-autodetection mode.
-
-2001-12-04 Werner Koch <[email protected]>
-
- * call-agent.c (read_from_agent): Check for inquire responses.
- (request_reply): Handle them using a new callback arg, changed all
- callers.
- (gpgsm_agent_pkdecrypt): New.
-
-2001-11-27 Werner Koch <[email protected]>
-
- * base64.c: New. Changed all other functions to use this instead
- of direct creation of ksba_reader/writer.
- * gpgsm.c (main): Set ctrl.auto_encoding unless --no-armor is used.
-
-2001-11-26 Werner Koch <[email protected]>
-
- * gpgsm.c: New option --agent-program
- * call-agent.c (start_agent): Allow to override the default path
- to the agent.
-
- * keydb.c (keydb_add_resource): Create keybox
-
- * keylist.c (gpgsm_list_keys): Fixed non-server keylisting.
-
- * server.c (rc_to_assuan_status): New. Use it for all commands.
-
-
- Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
-
- This file is free software; as a special exception the author gives
- unlimited permission to copy and/or distribute it, with or without
- modifications, as long as this notice is preserved.
-
- This file is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/sm/Makefile.am b/sm/Makefile.am
deleted file mode 100644
index 1ac7cbe84..000000000
--- a/sm/Makefile.am
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
-#
-# This file is part of GnuPG.
-#
-# GnuPG is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# GnuPG is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
-## Process this file with automake to produce Makefile.in
-
-
-bin_PROGRAMS = gpgsm
-
-AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(KSBA_CFLAGS)
-
-AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl
-include $(top_srcdir)/am/cmacros.am
-
-
-gpgsm_SOURCES = \
- gpgsm.c gpgsm.h \
- misc.c \
- keydb.c keydb.h \
- server.c \
- call-agent.c \
- call-dirmngr.c \
- fingerprint.c \
- base64.c \
- certlist.c \
- certdump.c \
- certcheck.c \
- certchain.c \
- keylist.c \
- verify.c \
- sign.c \
- encrypt.c \
- decrypt.c \
- import.c \
- export.c \
- delete.c \
- certreqgen.c
-
-
-gpgsm_LDADD = ../jnlib/libjnlib.a ../kbx/libkeybox.a ../common/libcommon.a \
- $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(KSBA_LIBS) -lgpg-error \
- $(INTLLIBS)
diff --git a/sm/base64.c b/sm/base64.c
deleted file mode 100644
index 4cc6ffa27..000000000
--- a/sm/base64.c
+++ /dev/null
@@ -1,655 +0,0 @@
-/* base64.c
- * Copyright (C) 2001, 2003 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-
-#include <ksba.h>
-
-#include "i18n.h"
-
-#ifdef HAVE_DOSISH_SYSTEM
- #define LF "\r\n"
-#else
- #define LF "\n"
-#endif
-
-/* data used by the reader callbacks */
-struct reader_cb_parm_s {
- FILE *fp;
- unsigned char line[1024];
- int linelen;
- int readpos;
- int have_lf;
- unsigned long line_counter;
-
- int allow_multi_pem; /* Allow processing of multiple PEM objects. */
- int autodetect; /* Try to detect the input encoding. */
- int assume_pem; /* Assume input encoding is PEM. */
- int assume_base64; /* Assume input is base64 encoded. */
-
- int identified;
- int is_pem;
- int is_base64;
- int stop_seen;
- int might_be_smime;
-
- int eof_seen;
-
- struct {
- int idx;
- unsigned char val;
- int stop_seen;
- } base64;
-};
-
-/* data used by the writer callbacks */
-struct writer_cb_parm_s {
- FILE *fp;
- const char *pem_name;
-
- int wrote_begin;
- int did_finish;
-
- struct {
- int idx;
- int quad_count;
- unsigned char radbuf[4];
- } base64;
-
-};
-
-
-/* context for this module's functions */
-struct base64_context_s {
- union {
- struct reader_cb_parm_s rparm;
- struct writer_cb_parm_s wparm;
- } u;
-};
-
-
-/* The base-64 character list */
-static unsigned char bintoasc[64] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789+/";
-/* The reverse base-64 list */
-static unsigned char asctobin[256] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
- 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
- 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
- 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
- 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff
-};
-
-
-static int
-has_only_base64 (const unsigned char *line, int linelen)
-{
- if (linelen < 20)
- return 0;
- for (; linelen; line++, linelen--)
- {
- if (*line == '\n' || (linelen > 1 && *line == '\r' && line[1] == '\n'))
- break;
- if ( !strchr (bintoasc, *line) )
- return 0;
- }
- return 1; /* yes */
-}
-
-static int
-is_empty_line (const unsigned char *line, int linelen)
-{
- if (linelen >= 2 && *line == '\r' && line[1] == '\n')
- return 1;
- if (linelen >= 1 && *line == '\n')
- return 1;
- return 0;
-}
-
-
-static int
-base64_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
-{
- struct reader_cb_parm_s *parm = cb_value;
- size_t n;
- int c, c2;
-
- *nread = 0;
- if (!buffer)
- return -1; /* not supported */
-
- next:
- if (!parm->linelen)
- {
- /* read an entire line or up to the size of the buffer */
- parm->line_counter++;
- parm->have_lf = 0;
- for (n=0; n < DIM(parm->line);)
- {
- c = getc (parm->fp);
- if (c == EOF)
- {
- parm->eof_seen = 1;
- if (ferror (parm->fp))
- return -1;
- break;
- }
- parm->line[n++] = c;
- if (c == '\n')
- {
- parm->have_lf = 1;
- /* Fixme: we need to skip overlong lines while detecting
- the dashed lines */
- break;
- }
- }
- parm->linelen = n;
- if (!n)
- return -1; /* eof */
- parm->readpos = 0;
- }
-
- if (!parm->identified)
- {
- if (!parm->autodetect)
- {
- if (parm->assume_pem)
- {
- /* wait for the header line */
- parm->linelen = parm->readpos = 0;
- if (!parm->have_lf || strncmp (parm->line, "-----BEGIN ", 11)
- || !strncmp (parm->line+11, "PGP ", 4))
- goto next;
- parm->is_pem = 1;
- }
- else if (parm->assume_base64)
- parm->is_base64 = 1;
- }
- else if (parm->line_counter == 1 && !parm->have_lf)
- {
- /* first line too long - assume DER encoding */
- parm->is_pem = 0;
- }
- else if (parm->line_counter == 1 && parm->linelen && *parm->line == 0x30)
- {
- /* the very first byte does pretty much look like a SEQUENCE tag*/
- parm->is_pem = 0;
- }
- else if ( parm->have_lf && !strncmp (parm->line, "-----BEGIN ", 11)
- && strncmp (parm->line+11, "PGP ", 4) )
- {
- /* Fixme: we must only compare if the line really starts at
- the beginning */
- parm->is_pem = 1;
- parm->linelen = parm->readpos = 0;
- }
- else if ( parm->have_lf && parm->line_counter == 1
- && parm->linelen >= 13
- && !ascii_memcasecmp (parm->line, "Content-Type:", 13))
- { /* might be a S/MIME body */
- parm->might_be_smime = 1;
- parm->linelen = parm->readpos = 0;
- goto next;
- }
- else if (parm->might_be_smime == 1
- && is_empty_line (parm->line, parm->linelen))
- {
- parm->might_be_smime = 2;
- parm->linelen = parm->readpos = 0;
- goto next;
- }
- else if (parm->might_be_smime == 2)
- {
- parm->might_be_smime = 0;
- if ( !has_only_base64 (parm->line, parm->linelen))
- {
- parm->linelen = parm->readpos = 0;
- goto next;
- }
- parm->is_pem = 1;
- }
- else
- {
- parm->linelen = parm->readpos = 0;
- goto next;
- }
- parm->identified = 1;
- parm->base64.stop_seen = 0;
- parm->base64.idx = 0;
- }
-
-
- n = 0;
- if (parm->is_pem || parm->is_base64)
- {
- if (parm->is_pem && parm->have_lf
- && !strncmp (parm->line, "-----END ", 9))
- {
- parm->identified = 0;
- parm->linelen = parm->readpos = 0;
-
- /* If the caller want to read multiple PEM objects from one
- file, we have to reset our internal state and return a
- EOF immediately. The caller is the expected to use
- ksba_reader_clear to clear the EOF condition and continue
- to read. If we don't want to do that we just return 0
- bytes which will force the ksba_reader to skip until
- EOF. */
- if (parm->allow_multi_pem)
- {
- parm->identified = 0;
- parm->autodetect = 0;
- parm->assume_pem = 1;
- parm->stop_seen = 0;
- return -1; /* Send EOF now. */
- }
- }
- else if (parm->stop_seen)
- { /* skip the rest of the line */
- parm->linelen = parm->readpos = 0;
- }
- else
- {
- int idx = parm->base64.idx;
- unsigned char val = parm->base64.val;
-
- while (n < count && parm->readpos < parm->linelen )
- {
- c = parm->line[parm->readpos++];
- if (c == '\n' || c == ' ' || c == '\r' || c == '\t')
- continue;
- if (c == '=')
- { /* pad character: stop */
- if (idx == 1)
- buffer[n++] = val;
- parm->stop_seen = 1;
- break;
- }
- if( (c = asctobin[(c2=c)]) == 255 )
- {
- log_error (_("invalid radix64 character %02x skipped\n"),
- c2);
- continue;
- }
- switch (idx)
- {
- case 0:
- val = c << 2;
- break;
- case 1:
- val |= (c>>4)&3;
- buffer[n++] = val;
- val = (c<<4)&0xf0;
- break;
- case 2:
- val |= (c>>2)&15;
- buffer[n++] = val;
- val = (c<<6)&0xc0;
- break;
- case 3:
- val |= c&0x3f;
- buffer[n++] = val;
- break;
- }
- idx = (idx+1) % 4;
- }
- if (parm->readpos == parm->linelen)
- parm->linelen = parm->readpos = 0;
-
- parm->base64.idx = idx;
- parm->base64.val = val;
- }
- }
- else
- { /* DER encoded */
- while (n < count && parm->readpos < parm->linelen)
- buffer[n++] = parm->line[parm->readpos++];
- if (parm->readpos == parm->linelen)
- parm->linelen = parm->readpos = 0;
- }
-
- *nread = n;
- return 0;
-}
-
-
-
-static int
-simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
-{
- struct reader_cb_parm_s *parm = cb_value;
- size_t n;
- int c = 0;
-
- *nread = 0;
- if (!buffer)
- return -1; /* not supported */
-
- for (n=0; n < count; n++)
- {
- c = getc (parm->fp);
- if (c == EOF)
- {
- parm->eof_seen = 1;
- if ( ferror (parm->fp) )
- return -1;
- if (n)
- break; /* return what we have before an EOF */
- return -1;
- }
- *(byte *)buffer++ = c;
- }
-
- *nread = n;
- return 0;
-}
-
-
-
-
-static int
-base64_writer_cb (void *cb_value, const void *buffer, size_t count)
-{
- struct writer_cb_parm_s *parm = cb_value;
- unsigned char radbuf[4];
- int i, c, idx, quad_count;
- const unsigned char *p;
- FILE *fp = parm->fp;
-
- if (!count)
- return 0;
-
- if (!parm->wrote_begin)
- {
- if (parm->pem_name)
- {
- fputs ("-----BEGIN ", fp);
- fputs (parm->pem_name, fp);
- fputs ("-----\n", fp);
- }
- parm->wrote_begin = 1;
- parm->base64.idx = 0;
- parm->base64.quad_count = 0;
- }
-
- idx = parm->base64.idx;
- quad_count = parm->base64.quad_count;
- for (i=0; i < idx; i++)
- radbuf[i] = parm->base64.radbuf[i];
-
- for (p=buffer; count; p++, count--)
- {
- radbuf[idx++] = *p;
- if (idx > 2)
- {
- idx = 0;
- c = bintoasc[(*radbuf >> 2) & 077];
- putc (c, fp);
- c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
- putc (c, fp);
- c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
- putc (c, fp);
- c = bintoasc[radbuf[2]&077];
- putc (c, fp);
- if (++quad_count >= (64/4))
- {
- fputs (LF, fp);
- quad_count = 0;
- }
- }
- }
- for (i=0; i < idx; i++)
- parm->base64.radbuf[i] = radbuf[i];
- parm->base64.idx = idx;
- parm->base64.quad_count = quad_count;
-
- return ferror (fp) ? gpg_error_from_errno (errno) : 0;
-}
-
-static int
-base64_finish_write (struct writer_cb_parm_s *parm)
-{
- unsigned char radbuf[4];
- int i, c, idx, quad_count;
- FILE *fp = parm->fp;
-
- if (!parm->wrote_begin)
- return 0; /* nothing written */
-
- /* flush the base64 encoding */
- idx = parm->base64.idx;
- quad_count = parm->base64.quad_count;
- for (i=0; i < idx; i++)
- radbuf[i] = parm->base64.radbuf[i];
-
- if (idx)
- {
- c = bintoasc[(*radbuf>>2)&077];
- putc (c, fp);
- if (idx == 1)
- {
- c = bintoasc[((*radbuf << 4) & 060) & 077];
- putc (c, fp);
- putc ('=', fp);
- putc ('=', fp);
- }
- else
- {
- c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
- putc (c, fp);
- c = bintoasc[((radbuf[1] << 2) & 074) & 077];
- putc (c, fp);
- putc ('=', fp);
-
- }
- if (++quad_count >= (64/4))
- {
- fputs (LF, fp);
- quad_count = 0;
- }
- }
-
- if (quad_count)
- fputs (LF, fp);
-
- if (parm->pem_name)
- {
- fputs ("-----END ", fp);
- fputs (parm->pem_name, fp);
- fputs ("-----\n", fp);
- }
- return ferror (fp)? gpg_error (gpg_err_code_from_errno (errno)) : 0;
-}
-
-
-
-
-/* Create a reader for the given file descriptor. Depending on the
- control information an input decoding is automagically choosen.
- The function returns a Base64Context object which must be passed to
- the gpgme_destroy_reader function. The created KsbaReader object
- is also returned, but the caller must not call the
- ksba_reader_release function on. If ALLOW_MULTI_PEM is true, the
- reader expects that the caller uses ksba_reader_clear after EOF
- until no more objects were found. */
-int
-gpgsm_create_reader (Base64Context *ctx,
- CTRL ctrl, FILE *fp, int allow_multi_pem,
- ksba_reader_t *r_reader)
-{
- int rc;
- ksba_reader_t r;
-
- *r_reader = NULL;
- *ctx = xtrycalloc (1, sizeof **ctx);
- if (!*ctx)
- return OUT_OF_CORE (errno);
- (*ctx)->u.rparm.allow_multi_pem = allow_multi_pem;
-
- rc = ksba_reader_new (&r);
- if (rc)
- {
- xfree (*ctx); *ctx = NULL;
- return rc;
- }
-
- (*ctx)->u.rparm.fp = fp;
- if (ctrl->is_pem)
- {
- (*ctx)->u.rparm.assume_pem = 1;
- (*ctx)->u.rparm.assume_base64 = 1;
- rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm);
- }
- else if (ctrl->is_base64)
- {
- (*ctx)->u.rparm.assume_base64 = 1;
- rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm);
- }
- else if (ctrl->autodetect_encoding)
- {
- (*ctx)->u.rparm.autodetect = 1;
- rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm);
- }
- else
- rc = ksba_reader_set_cb (r, simple_reader_cb, &(*ctx)->u.rparm);
-
- if (rc)
- {
- ksba_reader_release (r);
- xfree (*ctx); *ctx = NULL;
- return rc;
- }
-
- *r_reader = r;
- return 0;
-}
-
-
-int
-gpgsm_reader_eof_seen (Base64Context ctx)
-{
- return ctx && ctx->u.rparm.eof_seen;
-}
-
-void
-gpgsm_destroy_reader (Base64Context ctx)
-{
- xfree (ctx);
-}
-
-
-
-/* Create a writer for the given stream. Depending on the control
- information an output encoding is automagically choosen. The
- function returns a Base64Context object which must be passed to the
- gpgme_destroy_writer function. The created KsbaWriter object is
- also returned, but the caller must not call the ksba_reader_release
- function on. */
-int
-gpgsm_create_writer (Base64Context *ctx,
- CTRL ctrl, FILE *fp, ksba_writer_t *r_writer)
-{
- int rc;
- ksba_writer_t w;
-
- *r_writer = NULL;
- *ctx = xtrycalloc (1, sizeof **ctx);
- if (!*ctx)
- return OUT_OF_CORE (errno);
-
- rc = ksba_writer_new (&w);
- if (rc)
- {
- xfree (*ctx); *ctx = NULL;
- return rc;
- }
-
- if (ctrl->create_pem || ctrl->create_base64)
- {
- (*ctx)->u.wparm.fp = fp;
- if (ctrl->create_pem)
- (*ctx)->u.wparm.pem_name = ctrl->pem_name? ctrl->pem_name
- : "CMS OBJECT";
- rc = ksba_writer_set_cb (w, base64_writer_cb, &(*ctx)->u.wparm);
- }
- else
- rc = ksba_writer_set_file (w, fp);
-
- if (rc)
- {
- ksba_writer_release (w);
- xfree (*ctx); *ctx = NULL;
- return rc;
- }
-
- *r_writer = w;
- return 0;
-}
-
-
-int
-gpgsm_finish_writer (Base64Context ctx)
-{
- struct writer_cb_parm_s *parm;
-
- if (!ctx)
- return gpg_error (GPG_ERR_INV_VALUE);
- parm = &ctx->u.wparm;
- if (parm->did_finish)
- return 0; /* already done */
- parm->did_finish = 1;
- if (!parm->fp)
- return 0; /* callback was not used */
- return base64_finish_write (parm);
-}
-
-void
-gpgsm_destroy_writer (Base64Context ctx)
-{
- xfree (ctx);
-}
diff --git a/sm/call-agent.c b/sm/call-agent.c
deleted file mode 100644
index 2e8c75496..000000000
--- a/sm/call-agent.c
+++ /dev/null
@@ -1,635 +0,0 @@
-/* call-agent.c - divert operations to the agent
- * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-#ifdef HAVE_LOCALE_H
-#include <locale.h>
-#endif
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <assuan.h>
-#include "i18n.h"
-#include "asshelp.h"
-#include "keydb.h" /* fixme: Move this to import.c */
-#include "../common/membuf.h"
-
-
-static ASSUAN_CONTEXT agent_ctx = NULL;
-static int force_pipe_server = 0;
-
-struct cipher_parm_s {
- ASSUAN_CONTEXT ctx;
- const char *ciphertext;
- size_t ciphertextlen;
-};
-
-struct genkey_parm_s {
- ASSUAN_CONTEXT ctx;
- const char *sexp;
- size_t sexplen;
-};
-
-struct learn_parm_s {
- int error;
- ASSUAN_CONTEXT ctx;
- membuf_t *data;
-};
-
-
-
-/* Try to connect to the agent via socket or fork it off and work by
- pipes. Handle the server's initial greeting */
-static int
-start_agent (ctrl_t ctrl)
-{
- int rc = 0;
- char *infostr, *p;
- assuan_context_t ctx;
-
- if (agent_ctx)
- return 0; /* fixme: We need a context for each thread or serialize
- the access to the agent (which is suitable given that
- the agent is not MT. */
-
- infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO");
- if (!infostr || !*infostr)
- {
- const char *pgmname;
- const char *argv[3];
- int no_close_list[3];
- int i;
-
- if (opt.verbose)
- log_info (_("no running gpg-agent - starting one\n"));
-
- gpgsm_status (ctrl, STATUS_PROGRESS, "starting_agent ? 0 0");
-
- if (fflush (NULL))
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("error flushing pending output: %s\n", strerror (errno));
- return tmperr;
- }
-
- if (!opt.agent_program || !*opt.agent_program)
- opt.agent_program = GNUPG_DEFAULT_AGENT;
- if ( !(pgmname = strrchr (opt.agent_program, '/')))
- pgmname = opt.agent_program;
- else
- pgmname++;
-
- argv[0] = pgmname;
- argv[1] = "--server";
- argv[2] = NULL;
-
- i=0;
- if (log_get_fd () != -1)
- no_close_list[i++] = log_get_fd ();
- no_close_list[i++] = fileno (stderr);
- no_close_list[i] = -1;
-
- /* connect to the agent and perform initial handshaking */
- rc = assuan_pipe_connect (&ctx, opt.agent_program, (char**)argv,
- no_close_list);
- }
- else
- {
- int prot;
- int pid;
-
- infostr = xstrdup (infostr);
- if ( !(p = strchr (infostr, ':')) || p == infostr)
- {
- log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
- xfree (infostr);
- force_pipe_server = 1;
- return start_agent (ctrl);
- }
- *p++ = 0;
- pid = atoi (p);
- while (*p && *p != ':')
- p++;
- prot = *p? atoi (p+1) : 0;
- if (prot != 1)
- {
- log_error (_("gpg-agent protocol version %d is not supported\n"),
- prot);
- xfree (infostr);
- force_pipe_server = 1;
- return start_agent (ctrl);
- }
-
- rc = assuan_socket_connect (&ctx, infostr, pid);
- xfree (infostr);
- if (rc == ASSUAN_Connect_Failed)
- {
- log_error (_("can't connect to the agent - trying fall back\n"));
- force_pipe_server = 1;
- return start_agent (ctrl);
- }
- }
-
- if (rc)
- {
- log_error ("can't connect to the agent: %s\n", assuan_strerror (rc));
- return gpg_error (GPG_ERR_NO_AGENT);
- }
- agent_ctx = ctx;
-
- if (DBG_ASSUAN)
- log_debug ("connection to agent established\n");
-
- rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
-
- return send_pinentry_environment (agent_ctx,
- opt.display, opt.ttyname, opt.ttytype,
- opt.lc_ctype, opt.lc_messages);
-}
-
-
-static AssuanError
-membuf_data_cb (void *opaque, const void *buffer, size_t length)
-{
- membuf_t *data = opaque;
-
- if (buffer)
- put_membuf (data, buffer, length);
- return 0;
-}
-
-
-
-
-/* Call the agent to do a sign operation using the key identified by
- the hex string KEYGRIP. */
-int
-gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
- unsigned char *digest, size_t digestlen, int digestalgo,
- char **r_buf, size_t *r_buflen )
-{
- int rc, i;
- char *p, line[ASSUAN_LINELENGTH];
- membuf_t data;
- size_t len;
-
- *r_buf = NULL;
- rc = start_agent (ctrl);
- if (rc)
- return rc;
-
- if (digestlen*2 + 50 > DIM(line))
- return gpg_error (GPG_ERR_GENERAL);
-
- rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
-
- snprintf (line, DIM(line)-1, "SIGKEY %s", keygrip);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
-
- if (desc)
- {
- snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (agent_ctx, line,
- NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
- }
-
- sprintf (line, "SETHASH %d ", digestalgo);
- p = line + strlen (line);
- for (i=0; i < digestlen ; i++, p += 2 )
- sprintf (p, "%02X", digest[i]);
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
-
- init_membuf (&data, 1024);
- rc = assuan_transact (agent_ctx, "PKSIGN",
- membuf_data_cb, &data, NULL, NULL, NULL, NULL);
- if (rc)
- {
- xfree (get_membuf (&data, &len));
- return map_assuan_err (rc);
- }
- *r_buf = get_membuf (&data, r_buflen);
-
- if (!gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL))
- {
- xfree (*r_buf); *r_buf = NULL;
- return gpg_error (GPG_ERR_INV_VALUE);
- }
-
- return *r_buf? 0 : OUT_OF_CORE (errno);
-}
-
-
-
-
-/* Handle a CIPHERTEXT inquiry. Note, we only send the data,
- assuan_transact talkes care of flushing and writing the end */
-static AssuanError
-inq_ciphertext_cb (void *opaque, const char *keyword)
-{
- struct cipher_parm_s *parm = opaque;
- AssuanError rc;
-
- assuan_begin_confidential (parm->ctx);
- rc = assuan_send_data (parm->ctx, parm->ciphertext, parm->ciphertextlen);
- assuan_end_confidential (parm->ctx);
- return rc;
-}
-
-
-/* Call the agent to do a decrypt operation using the key identified by
- the hex string KEYGRIP. */
-int
-gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
- ksba_const_sexp_t ciphertext,
- char **r_buf, size_t *r_buflen )
-{
- int rc;
- char line[ASSUAN_LINELENGTH];
- membuf_t data;
- struct cipher_parm_s cipher_parm;
- size_t n, len;
- char *buf, *endp;
- size_t ciphertextlen;
-
- if (!keygrip || strlen(keygrip) != 40 || !ciphertext || !r_buf || !r_buflen)
- return gpg_error (GPG_ERR_INV_VALUE);
- *r_buf = NULL;
-
- ciphertextlen = gcry_sexp_canon_len (ciphertext, 0, NULL, NULL);
- if (!ciphertextlen)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- rc = start_agent (ctrl);
- if (rc)
- return rc;
-
- rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
-
- assert ( DIM(line) >= 50 );
- snprintf (line, DIM(line)-1, "SETKEY %s", keygrip);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
-
- if (desc)
- {
- snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (agent_ctx, line,
- NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
- }
-
- init_membuf (&data, 1024);
- cipher_parm.ctx = agent_ctx;
- cipher_parm.ciphertext = ciphertext;
- cipher_parm.ciphertextlen = ciphertextlen;
- rc = assuan_transact (agent_ctx, "PKDECRYPT",
- membuf_data_cb, &data,
- inq_ciphertext_cb, &cipher_parm, NULL, NULL);
- if (rc)
- {
- xfree (get_membuf (&data, &len));
- return map_assuan_err (rc);
- }
-
- put_membuf (&data, "", 1); /* make sure it is 0 terminated */
- buf = get_membuf (&data, &len);
- if (!buf)
- return gpg_error (GPG_ERR_ENOMEM);
- /* FIXME: We would better a return a full S-exp and not just a part */
- assert (len);
- len--; /* remove the terminating 0 */
- n = strtoul (buf, &endp, 10);
- if (!n || *endp != ':')
- return gpg_error (GPG_ERR_INV_SEXP);
- endp++;
- if (endp-buf+n > len)
- return gpg_error (GPG_ERR_INV_SEXP); /* oops len does not
- match internal len*/
- memmove (buf, endp, n);
- *r_buflen = n;
- *r_buf = buf;
- return 0;
-}
-
-
-
-
-
-/* Handle a KEYPARMS inquiry. Note, we only send the data,
- assuan_transact takes care of flushing and writing the end */
-static AssuanError
-inq_genkey_parms (void *opaque, const char *keyword)
-{
- struct genkey_parm_s *parm = opaque;
- AssuanError rc;
-
- rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen);
- return rc;
-}
-
-
-
-/* Call the agent to generate a newkey */
-int
-gpgsm_agent_genkey (ctrl_t ctrl,
- ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
-{
- int rc;
- struct genkey_parm_s gk_parm;
- membuf_t data;
- size_t len;
- char *buf;
-
- *r_pubkey = NULL;
- rc = start_agent (ctrl);
- if (rc)
- return rc;
-
- rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
-
- init_membuf (&data, 1024);
- gk_parm.ctx = agent_ctx;
- gk_parm.sexp = keyparms;
- gk_parm.sexplen = gcry_sexp_canon_len (keyparms, 0, NULL, NULL);
- if (!gk_parm.sexplen)
- return gpg_error (GPG_ERR_INV_VALUE);
- rc = assuan_transact (agent_ctx, "GENKEY",
- membuf_data_cb, &data,
- inq_genkey_parms, &gk_parm, NULL, NULL);
- if (rc)
- {
- xfree (get_membuf (&data, &len));
- return map_assuan_err (rc);
- }
- buf = get_membuf (&data, &len);
- if (!buf)
- return gpg_error (GPG_ERR_ENOMEM);
- if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
- {
- xfree (buf);
- return gpg_error (GPG_ERR_INV_SEXP);
- }
- *r_pubkey = buf;
- return 0;
-}
-
-
-/* Ask the agent whether the certificate is in the list of trusted
- keys */
-int
-gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert)
-{
- int rc;
- char *fpr;
- char line[ASSUAN_LINELENGTH];
-
- rc = start_agent (ctrl);
- if (rc)
- return rc;
-
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- if (!fpr)
- {
- log_error ("error getting the fingerprint\n");
- return gpg_error (GPG_ERR_GENERAL);
- }
-
- snprintf (line, DIM(line)-1, "ISTRUSTED %s", fpr);
- line[DIM(line)-1] = 0;
- xfree (fpr);
-
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- return map_assuan_err (rc);
-}
-
-/* Ask the agent to mark CERT as a trusted Root-CA one */
-int
-gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert)
-{
- int rc;
- char *fpr, *dn;
- char line[ASSUAN_LINELENGTH];
-
- rc = start_agent (ctrl);
- if (rc)
- return rc;
-
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- if (!fpr)
- {
- log_error ("error getting the fingerprint\n");
- return gpg_error (GPG_ERR_GENERAL);
- }
-
- dn = ksba_cert_get_issuer (cert, 0);
- if (!dn)
- {
- xfree (fpr);
- return gpg_error (GPG_ERR_GENERAL);
- }
- snprintf (line, DIM(line)-1, "MARKTRUSTED %s S %s", fpr, dn);
- line[DIM(line)-1] = 0;
- ksba_free (dn);
- xfree (fpr);
-
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- return map_assuan_err (rc);
-}
-
-
-
-/* Ask the agent whether the a corresponding secret key is available
- for the given keygrip */
-int
-gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip)
-{
- int rc;
- char line[ASSUAN_LINELENGTH];
-
- rc = start_agent (ctrl);
- if (rc)
- return rc;
-
- if (!hexkeygrip || strlen (hexkeygrip) != 40)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip);
- line[DIM(line)-1] = 0;
-
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- return map_assuan_err (rc);
-}
-
-
-static AssuanError
-learn_cb (void *opaque, const void *buffer, size_t length)
-{
- struct learn_parm_s *parm = opaque;
- size_t len;
- char *buf;
- ksba_cert_t cert;
- int rc;
-
- if (parm->error)
- return 0;
-
- if (buffer)
- {
- put_membuf (parm->data, buffer, length);
- return 0;
- }
- /* END encountered - process what we have */
- buf = get_membuf (parm->data, &len);
- if (!buf)
- {
- parm->error = gpg_error (GPG_ERR_ENOMEM);
- return 0;
- }
-
-
- /* FIXME: this should go into import.c */
- rc = ksba_cert_new (&cert);
- if (rc)
- {
- parm->error = rc;
- return 0;
- }
- rc = ksba_cert_init_from_mem (cert, buf, len);
- if (rc)
- {
- log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
- ksba_cert_release (cert);
- parm->error = rc;
- return 0;
- }
-
- rc = gpgsm_basic_cert_check (cert);
- if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT)
- { /* For later use we store it in the ephemeral database. */
- log_info ("issuer certificate missing - storing as ephemeral\n");
- keydb_store_cert (cert, 1, NULL);
- }
- else if (rc)
- log_error ("invalid certificate: %s\n", gpg_strerror (rc));
- else
- {
- int existed;
-
- if (!keydb_store_cert (cert, 0, &existed))
- {
- if (opt.verbose > 1 && existed)
- log_info ("certificate already in DB\n");
- else if (opt.verbose && !existed)
- log_info ("certificate imported\n");
- }
- }
-
- ksba_cert_release (cert);
- init_membuf (parm->data, 4096);
- return 0;
-}
-
-/* Call the agent to learn about a smartcard */
-int
-gpgsm_agent_learn (ctrl_t ctrl)
-{
- int rc;
- struct learn_parm_s learn_parm;
- membuf_t data;
- size_t len;
-
- rc = start_agent (ctrl);
- if (rc)
- return rc;
-
- init_membuf (&data, 4096);
- learn_parm.error = 0;
- learn_parm.ctx = agent_ctx;
- learn_parm.data = &data;
- rc = assuan_transact (agent_ctx, "LEARN --send",
- learn_cb, &learn_parm,
- NULL, NULL, NULL, NULL);
- xfree (get_membuf (&data, &len));
- if (rc)
- return map_assuan_err (rc);
- return learn_parm.error;
-}
-
-
-/* Ask the agent to change the passphrase of the key identified by
- HEXKEYGRIP. If DESC is not NULL, display instead of the default
- description message. */
-int
-gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc)
-{
- int rc;
- char line[ASSUAN_LINELENGTH];
-
- rc = start_agent (ctrl);
- if (rc)
- return rc;
-
- if (!hexkeygrip || strlen (hexkeygrip) != 40)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- if (desc)
- {
- snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (agent_ctx, line,
- NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
- }
-
- snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip);
- line[DIM(line)-1] = 0;
-
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- return map_assuan_err (rc);
-}
-
diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c
deleted file mode 100644
index 15160dc41..000000000
--- a/sm/call-dirmngr.c
+++ /dev/null
@@ -1,785 +0,0 @@
-/* call-dirmngr.c - communication with the dromngr
- * Copyright (C) 2002, 2003 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-#include <ctype.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <assuan.h>
-
-#include "i18n.h"
-#include "keydb.h"
-
-
-struct membuf {
- size_t len;
- size_t size;
- char *buf;
- int out_of_core;
-};
-
-
-
-static ASSUAN_CONTEXT dirmngr_ctx = NULL;
-static int force_pipe_server = 0;
-
-struct inq_certificate_parm_s {
- ASSUAN_CONTEXT ctx;
- ksba_cert_t cert;
- ksba_cert_t issuer_cert;
-};
-
-struct isvalid_status_parm_s {
- int seen;
- unsigned char fpr[20];
-};
-
-
-struct lookup_parm_s {
- CTRL ctrl;
- ASSUAN_CONTEXT ctx;
- void (*cb)(void *, ksba_cert_t);
- void *cb_value;
- struct membuf data;
- int error;
-};
-
-struct run_command_parm_s {
- ASSUAN_CONTEXT ctx;
-};
-
-
-/* A simple implementation of a dynamic buffer. Use init_membuf() to
- create a buffer, put_membuf to append bytes and get_membuf to
- release and return the buffer. Allocation errors are detected but
- only returned at the final get_membuf(), this helps not to clutter
- the code with out of core checks. */
-
-static void
-init_membuf (struct membuf *mb, int initiallen)
-{
- mb->len = 0;
- mb->size = initiallen;
- mb->out_of_core = 0;
- mb->buf = xtrymalloc (initiallen);
- if (!mb->buf)
- mb->out_of_core = 1;
-}
-
-static void
-put_membuf (struct membuf *mb, const void *buf, size_t len)
-{
- if (mb->out_of_core)
- return;
-
- if (mb->len + len >= mb->size)
- {
- char *p;
-
- mb->size += len + 1024;
- p = xtryrealloc (mb->buf, mb->size);
- if (!p)
- {
- mb->out_of_core = 1;
- return;
- }
- mb->buf = p;
- }
- memcpy (mb->buf + mb->len, buf, len);
- mb->len += len;
-}
-
-static void *
-get_membuf (struct membuf *mb, size_t *len)
-{
- char *p;
-
- if (mb->out_of_core)
- {
- xfree (mb->buf);
- mb->buf = NULL;
- return NULL;
- }
-
- p = mb->buf;
- *len = mb->len;
- mb->buf = NULL;
- mb->out_of_core = 1; /* don't allow a reuse */
- return p;
-}
-
-
-
-
-
-/* Try to connect to the agent via socket or fork it off and work by
- pipes. Handle the server's initial greeting */
-static int
-start_dirmngr (void)
-{
- int rc;
- char *infostr, *p;
- ASSUAN_CONTEXT ctx;
-
- if (dirmngr_ctx)
- return 0; /* fixme: We need a context for each thread or serialize
- the access to the dirmngr */
- /* Note: if you change this to multiple connections, you also need
- to take care of the implicit option sending caching. */
-
- infostr = force_pipe_server? NULL : getenv ("DIRMNGR_INFO");
- if (!infostr || !*infostr)
- {
- const char *pgmname;
- const char *argv[3];
- int no_close_list[3];
- int i;
-
- if (opt.verbose)
- log_info (_("no running dirmngr - starting one\n"));
-
- if (fflush (NULL))
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("error flushing pending output: %s\n", strerror (errno));
- return tmperr;
- }
-
- if (!opt.dirmngr_program || !*opt.dirmngr_program)
- opt.dirmngr_program = GNUPG_DEFAULT_DIRMNGR;
- if ( !(pgmname = strrchr (opt.dirmngr_program, '/')))
- pgmname = opt.dirmngr_program;
- else
- pgmname++;
-
- argv[0] = pgmname;
- argv[1] = "--server";
- argv[2] = NULL;
-
- i=0;
- if (log_get_fd () != -1)
- no_close_list[i++] = log_get_fd ();
- no_close_list[i++] = fileno (stderr);
- no_close_list[i] = -1;
-
- /* connect to the agent and perform initial handshaking */
- rc = assuan_pipe_connect (&ctx, opt.dirmngr_program, (char**)argv,
- no_close_list);
- }
- else
- {
- int prot;
- int pid;
-
- infostr = xstrdup (infostr);
- if ( !(p = strchr (infostr, ':')) || p == infostr)
- {
- log_error (_("malformed DIRMNGR_INFO environment variable\n"));
- xfree (infostr);
- force_pipe_server = 1;
- return start_dirmngr ();
- }
- *p++ = 0;
- pid = atoi (p);
- while (*p && *p != ':')
- p++;
- prot = *p? atoi (p+1) : 0;
- if (prot != 1)
- {
- log_error (_("dirmngr protocol version %d is not supported\n"),
- prot);
- xfree (infostr);
- force_pipe_server = 1;
- return start_dirmngr ();
- }
-
- rc = assuan_socket_connect (&ctx, infostr, pid);
- xfree (infostr);
- if (rc == ASSUAN_Connect_Failed)
- {
- log_error (_("can't connect to the dirmngr - trying fall back\n"));
- force_pipe_server = 1;
- return start_dirmngr ();
- }
- }
-
- if (rc)
- {
- log_error ("can't connect to the dirmngr: %s\n", assuan_strerror (rc));
- return gpg_error (GPG_ERR_NO_DIRMNGR);
- }
- dirmngr_ctx = ctx;
-
- if (DBG_ASSUAN)
- log_debug ("connection to dirmngr established\n");
- return 0;
-}
-
-
-
-/* Handle a SENDCERT inquiry. */
-static AssuanError
-inq_certificate (void *opaque, const char *line)
-{
- struct inq_certificate_parm_s *parm = opaque;
- AssuanError rc;
- const unsigned char *der;
- size_t derlen;
- int issuer_mode = 0;
-
- if (!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]))
- {
- line += 8;
- }
- else if (!strncmp (line, "SENDISSUERCERT", 14)
- && (line[14] == ' ' || !line[14]))
- {
- line += 14;
- issuer_mode = 1;
- }
- else
- {
- log_error ("unsupported inquiry `%s'\n", line);
- return ASSUAN_Inquire_Unknown;
- }
-
- if (!*line)
- { /* Send the current certificate. */
- der = ksba_cert_get_image (issuer_mode? parm->issuer_cert : parm->cert,
- &derlen);
- if (!der)
- rc = ASSUAN_Inquire_Error;
- else
- rc = assuan_send_data (parm->ctx, der, derlen);
- }
- else if (issuer_mode)
- {
- log_error ("sending specific issuer certificate back "
- "is not yet implemented\n");
- rc = ASSUAN_Inquire_Error;
- }
- else
- { /* Send the given certificate. */
- int err;
- ksba_cert_t cert;
-
-
- err = gpgsm_find_cert (line, &cert);
- if (err)
- {
- log_error ("certificate not found: %s\n", gpg_strerror (err));
- rc = ASSUAN_Inquire_Error;
- }
- else
- {
- der = ksba_cert_get_image (cert, &derlen);
- if (!der)
- rc = ASSUAN_Inquire_Error;
- else
- rc = assuan_send_data (parm->ctx, der, derlen);
- ksba_cert_release (cert);
- }
- }
-
- return rc;
-}
-
-
-/* Take a 20 byte hexencoded string and put it into the the provided
- 20 byte buffer FPR in binary format. */
-static int
-unhexify_fpr (const char *hexstr, unsigned char *fpr)
-{
- const char *s;
- int n;
-
- for (s=hexstr, n=0; hexdigitp (s); s++, n++)
- ;
- if (*s || (n != 40))
- return 0; /* no fingerprint (invalid or wrong length). */
- n /= 2;
- for (s=hexstr, n=0; *s; s += 2, n++)
- fpr[n] = xtoi_2 (s);
- return 1; /* okay */
-}
-
-
-static assuan_error_t
-isvalid_status_cb (void *opaque, const char *line)
-{
- struct isvalid_status_parm_s *parm = opaque;
-
- if (!strncmp (line, "ONLY_VALID_IF_CERT_VALID", 24)
- && (line[24]==' ' || !line[24]))
- {
- parm->seen++;
- if (!line[24] || !unhexify_fpr (line+25, parm->fpr))
- parm->seen++; /* Bumb it to indicate an error. */
- }
- return 0;
-}
-
-
-
-
-/* Call the directory manager to check whether the certificate is valid
- Returns 0 for valid or usually one of the errors:
-
- GPG_ERR_CERTIFICATE_REVOKED
- GPG_ERR_NO_CRL_KNOWN
- GPG_ERR_CRL_TOO_OLD
-
- With USE_OCSP set to true, the dirmngr is asked to do an OCSP
- request first.
- */
-int
-gpgsm_dirmngr_isvalid (ctrl_t ctrl,
- ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp)
-{
- static int did_options;
- int rc;
- char *certid;
- char line[ASSUAN_LINELENGTH];
- struct inq_certificate_parm_s parm;
- struct isvalid_status_parm_s stparm;
-
-
- rc = start_dirmngr ();
- if (rc)
- return rc;
-
- if (use_ocsp)
- {
- certid = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- }
- else
- {
- certid = gpgsm_get_certid (cert);
- if (!certid)
- {
- log_error ("error getting the certificate ID\n");
- return gpg_error (GPG_ERR_GENERAL);
- }
- }
-
- if (opt.verbose > 1)
- {
- char *fpr = gpgsm_get_fingerprint_string (cert, GCRY_MD_SHA1);
- log_info ("asking dirmngr about %s%s\n", fpr,
- use_ocsp? " (using OCSP)":"");
- xfree (fpr);
- }
-
- parm.ctx = dirmngr_ctx;
- parm.cert = cert;
- parm.issuer_cert = issuer_cert;
-
- stparm.seen = 0;
- memset (stparm.fpr, 0, 20);
-
- /* FIXME: If --disable-crl-checks has been set, we should pass an
- option to dirmngr, so that no fallback CRL check is done after an
- ocsp check. */
-
- /* It is sufficient to send the options only once because we have
- one connection per process only. */
- if (!did_options)
- {
- if (opt.force_crl_refresh)
- assuan_transact (dirmngr_ctx, "OPTION force-crl-refresh=1",
- NULL, NULL, NULL, NULL, NULL, NULL);
- did_options = 1;
- }
- snprintf (line, DIM(line)-1, "ISVALID %s", certid);
- line[DIM(line)-1] = 0;
- xfree (certid);
-
- rc = assuan_transact (dirmngr_ctx, line, NULL, NULL,
- inq_certificate, &parm,
- isvalid_status_cb, &stparm);
- if (opt.verbose > 1)
- log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay");
- rc = map_assuan_err (rc);
-
- if (!rc && stparm.seen)
- {
- /* Need to also check the certificate validity. */
- if (stparm.seen != 1)
- {
- log_error ("communication problem with dirmngr detected\n");
- rc = gpg_error (GPG_ERR_INV_CRL);
- }
- else
- {
- KEYDB_HANDLE kh;
- ksba_cert_t rspcert = NULL;
-
- /* Fixme: First try to get the certificate from the
- dirmngr's cache - it should be there. */
- kh = keydb_new (0);
- if (!kh)
- rc = gpg_error (GPG_ERR_ENOMEM);
- if (!rc)
- rc = keydb_search_fpr (kh, stparm.fpr);
- if (!rc)
- rc = keydb_get_cert (kh, &rspcert);
- if (rc)
- {
- log_error ("unable to find the certificate used "
- "by the dirmngr: %s\n", gpg_strerror (rc));
- rc = gpg_error (GPG_ERR_INV_CRL);
- }
- keydb_release (kh);
-
- if (!rc)
- {
- /* fixme: We should refine the check to check for
- certificates allowed for CRL/OCPS. */
- rc = gpgsm_cert_use_verify_p (rspcert);
- if (rc)
- rc = gpg_error (GPG_ERR_INV_CRL);
- else
- {
- /* Note, the flag = 1: This avoids checking this
- certificate over and over again. */
- rc = gpgsm_validate_chain (ctrl, rspcert, NULL, 0, NULL, 1);
- if (rc)
- {
- log_error ("invalid certificate used for CRL/OCSP: %s\n",
- gpg_strerror (rc));
- rc = gpg_error (GPG_ERR_INV_CRL);
- }
- }
- }
- ksba_cert_release (rspcert);
- }
- }
- return rc;
-}
-
-
-
-/* Lookup helpers*/
-static AssuanError
-lookup_cb (void *opaque, const void *buffer, size_t length)
-{
- struct lookup_parm_s *parm = opaque;
- size_t len;
- char *buf;
- ksba_cert_t cert;
- int rc;
-
- if (parm->error)
- return 0;
-
- if (buffer)
- {
- put_membuf (&parm->data, buffer, length);
- return 0;
- }
- /* END encountered - process what we have */
- buf = get_membuf (&parm->data, &len);
- if (!buf)
- {
- parm->error = gpg_error (GPG_ERR_ENOMEM);
- return 0;
- }
-
- rc = ksba_cert_new (&cert);
- if (rc)
- {
- parm->error = rc;
- return 0;
- }
- rc = ksba_cert_init_from_mem (cert, buf, len);
- if (rc)
- {
- log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
- }
- else
- {
- parm->cb (parm->cb_value, cert);
- }
-
- ksba_cert_release (cert);
- init_membuf (&parm->data, 4096);
- return 0;
-}
-
-/* Return a properly escaped pattern from NAMES. The only error
- return is NULL to indicate a malloc failure. */
-static char *
-pattern_from_strlist (STRLIST names)
-{
- STRLIST sl;
- int n;
- const char *s;
- char *pattern, *p;
-
- for (n=0, sl=names; sl; sl = sl->next)
- {
- for (s=sl->d; *s; s++, n++)
- {
- if (*s == '%' || *s == ' ' || *s == '+')
- n += 2;
- }
- n++;
- }
-
- p = pattern = xtrymalloc (n+1);
- if (!pattern)
- return NULL;
-
- for (n=0, sl=names; sl; sl = sl->next)
- {
- for (s=sl->d; *s; s++)
- {
- switch (*s)
- {
- case '%':
- *p++ = '%';
- *p++ = '2';
- *p++ = '5';
- break;
- case ' ':
- *p++ = '%';
- *p++ = '2';
- *p++ = '0';
- break;
- case '+':
- *p++ = '%';
- *p++ = '2';
- *p++ = 'B';
- break;
- default:
- *p++ = *s;
- break;
- }
- }
- *p++ = ' ';
- }
- if (p == pattern)
- *pattern = 0; /* is empty */
- else
- p[-1] = '\0'; /* remove trailing blank */
-
- return pattern;
-}
-
-static AssuanError
-lookup_status_cb (void *opaque, const char *line)
-{
- struct lookup_parm_s *parm = opaque;
-
- if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9]))
- {
- if (parm->ctrl)
- {
- for (line +=9; *line == ' '; line++)
- ;
- gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line);
- }
- }
- return 0;
-}
-
-
-/* Run the Directroy Managers lookup command using the pattern
- compiled from the strings given in NAMES. The caller must provide
- the callback CB which will be passed cert by cert. Note that CTRL
- is optional. */
-int
-gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names,
- void (*cb)(void*, ksba_cert_t), void *cb_value)
-{
- int rc;
- char *pattern;
- char line[ASSUAN_LINELENGTH];
- struct lookup_parm_s parm;
- size_t len;
-
- rc = start_dirmngr ();
- if (rc)
- return rc;
-
- pattern = pattern_from_strlist (names);
- if (!pattern)
- return OUT_OF_CORE (errno);
- snprintf (line, DIM(line)-1, "LOOKUP %s", pattern);
- line[DIM(line)-1] = 0;
- xfree (pattern);
-
- parm.ctrl = ctrl;
- parm.ctx = dirmngr_ctx;
- parm.cb = cb;
- parm.cb_value = cb_value;
- parm.error = 0;
- init_membuf (&parm.data, 4096);
-
- rc = assuan_transact (dirmngr_ctx, line, lookup_cb, &parm,
- NULL, NULL, lookup_status_cb, &parm);
- xfree (get_membuf (&parm.data, &len));
- if (rc)
- return map_assuan_err (rc);
- return parm.error;
-}
-
-
-
-/* Run Command helpers*/
-
-/* Fairly simple callback to write all output of dirmngr to stdout. */
-static AssuanError
-run_command_cb (void *opaque, const void *buffer, size_t length)
-{
- if (buffer)
- {
- if ( fwrite (buffer, length, 1, stdout) != 1 )
- log_error ("error writing to stdout: %s\n", strerror (errno));
- }
- return 0;
-}
-
-/* Handle inquiries from the dirmngr COMMAND. */
-static AssuanError
-run_command_inq_cb (void *opaque, const char *line)
-{
- struct run_command_parm_s *parm = opaque;
- AssuanError rc = 0;
-
- if ( !strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]) )
- { /* send the given certificate */
- int err;
- ksba_cert_t cert;
- const unsigned char *der;
- size_t derlen;
-
- line += 8;
- if (!*line)
- return ASSUAN_Inquire_Error;
-
- err = gpgsm_find_cert (line, &cert);
- if (err)
- {
- log_error ("certificate not found: %s\n", gpg_strerror (err));
- rc = ASSUAN_Inquire_Error;
- }
- else
- {
- der = ksba_cert_get_image (cert, &derlen);
- if (!der)
- rc = ASSUAN_Inquire_Error;
- else
- rc = assuan_send_data (parm->ctx, der, derlen);
- ksba_cert_release (cert);
- }
- }
- else if ( !strncmp (line, "PRINTINFO", 9) && (line[9] == ' ' || !line[9]) )
- { /* Simply show the message given in the argument. */
- line += 9;
- log_info ("dirmngr: %s\n", line);
- }
- else
- {
- log_error ("unsupported inquiry `%s'\n", line);
- rc = ASSUAN_Inquire_Unknown;
- }
-
- return rc;
-}
-
-static AssuanError
-run_command_status_cb (void *opaque, const char *line)
-{
- if (opt.verbose)
- {
- log_info ("dirmngr status: %s\n", line);
- }
- return 0;
-}
-
-
-
-/* Pass COMMAND to dirmngr and print all output generated by Dirmngr
- to stdout. A couple of inquiries are defined (see above). ARGC
- arguments in ARGV are given to the Dirmngr. Spaces, plus and
- percent characters within the argument strings are percent escaped
- so that blanks can act as delimiters. */
-int
-gpgsm_dirmngr_run_command (CTRL ctrl, const char *command,
- int argc, char **argv)
-{
- int rc;
- int i;
- const char *s;
- char *line, *p;
- size_t len;
- struct run_command_parm_s parm;
-
- rc = start_dirmngr ();
- if (rc)
- return rc;
-
- parm.ctx = dirmngr_ctx;
-
- len = strlen (command) + 1;
- for (i=0; i < argc; i++)
- len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */
- line = xtrymalloc (len);
- if (!line)
- return OUT_OF_CORE (errno);
-
- p = stpcpy (line, command);
- for (i=0; i < argc; i++)
- {
- *p++ = ' ';
- for (s=argv[i]; *s; s++)
- {
- if (!isascii (*s))
- *p++ = *s;
- else if (*s == ' ')
- *p++ = '+';
- else if (!isprint (*s) || *s == '+')
- {
- sprintf (p, "%%%02X", *s);
- p += 3;
- }
- else
- *p++ = *s;
- }
- }
- *p = 0;
-
- rc = assuan_transact (dirmngr_ctx, line,
- run_command_cb, NULL,
- run_command_inq_cb, &parm,
- run_command_status_cb, NULL);
- xfree (line);
- log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay");
- return map_assuan_err (rc);
-}
diff --git a/sm/certchain.c b/sm/certchain.c
deleted file mode 100644
index 3009c21aa..000000000
--- a/sm/certchain.c
+++ /dev/null
@@ -1,976 +0,0 @@
-/* certchain.c - certificate chain validation
- * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <stdarg.h>
-#include <assert.h>
-
-#define JNLIB_NEED_LOG_LOGV /* We need log_logv. */
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
-#include "i18n.h"
-
-
-/* If LISTMODE is true, print FORMAT in liting mode to FP. If
- LISTMODE is false, use the string to print an log_info or, if
- IS_ERROR is true, an log_error. */
-static void
-do_list (int is_error, int listmode, FILE *fp, const char *format, ...)
-{
- va_list arg_ptr;
-
- va_start (arg_ptr, format) ;
- if (listmode)
- {
- if (fp)
- {
- fputs (" [", fp);
- vfprintf (fp, format, arg_ptr);
- fputs ("]\n", fp);
- }
- }
- else
- {
- log_logv (is_error? JNLIB_LOG_ERROR: JNLIB_LOG_INFO, format, arg_ptr);
- log_printf ("\n");
- }
- va_end (arg_ptr);
-}
-
-/* Return 0 if A and B are equal. */
-static int
-compare_certs (ksba_cert_t a, ksba_cert_t b)
-{
- const unsigned char *img_a, *img_b;
- size_t len_a, len_b;
-
- img_a = ksba_cert_get_image (a, &len_a);
- if (!img_a)
- return 1;
- img_b = ksba_cert_get_image (b, &len_b);
- if (!img_b)
- return 1;
- return !(len_a == len_b && !memcmp (img_a, img_b, len_a));
-}
-
-
-static int
-unknown_criticals (ksba_cert_t cert, int listmode, FILE *fp)
-{
- static const char *known[] = {
- "2.5.29.15", /* keyUsage */
- "2.5.29.19", /* basic Constraints */
- "2.5.29.32", /* certificatePolicies */
- "2.5.29.37", /* extendedKeyUsage - handled by certlist.c */
- NULL
- };
- int rc = 0, i, idx, crit;
- const char *oid;
- gpg_error_t err;
-
- for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
- &oid, &crit, NULL, NULL));idx++)
- {
- if (!crit)
- continue;
- for (i=0; known[i] && strcmp (known[i],oid); i++)
- ;
- if (!known[i])
- {
- do_list (1, listmode, fp,
- _("critical certificate extension %s is not supported"),
- oid);
- rc = gpg_error (GPG_ERR_UNSUPPORTED_CERT);
- }
- }
- if (err && gpg_err_code (err) != GPG_ERR_EOF)
- rc = err;
-
- return rc;
-}
-
-static int
-allowed_ca (ksba_cert_t cert, int *chainlen, int listmode, FILE *fp)
-{
- gpg_error_t err;
- int flag;
-
- err = ksba_cert_is_ca (cert, &flag, chainlen);
- if (err)
- return err;
- if (!flag)
- {
- do_list (1, listmode, fp,_("issuer certificate is not marked as a CA"));
- return gpg_error (GPG_ERR_BAD_CA_CERT);
- }
- return 0;
-}
-
-
-static int
-check_cert_policy (ksba_cert_t cert, int listmode, FILE *fplist)
-{
- gpg_error_t err;
- char *policies;
- FILE *fp;
- int any_critical;
-
- err = ksba_cert_get_cert_policies (cert, &policies);
- if (gpg_err_code (err) == GPG_ERR_NO_DATA)
- return 0; /* no policy given */
- if (err)
- return err;
-
- /* STRING is a line delimited list of certifiate policies as stored
- in the certificate. The line itself is colon delimited where the
- first field is the OID of the policy and the second field either
- N or C for normal or critical extension */
-
- if (opt.verbose > 1 && !listmode)
- log_info ("certificate's policy list: %s\n", policies);
-
- /* The check is very minimal but won't give false positives */
- any_critical = !!strstr (policies, ":C");
-
- if (!opt.policy_file)
- {
- xfree (policies);
- if (any_critical)
- {
- do_list (1, listmode, fplist,
- _("critical marked policy without configured policies"));
- return gpg_error (GPG_ERR_NO_POLICY_MATCH);
- }
- return 0;
- }
-
- fp = fopen (opt.policy_file, "r");
- if (!fp)
- {
- log_error ("failed to open `%s': %s\n",
- opt.policy_file, strerror (errno));
- xfree (policies);
- /* With no critical policies this is only a warning */
- if (!any_critical)
- {
- do_list (0, listmode, fplist,
- _("note: non-critical certificate policy not allowed"));
- return 0;
- }
- do_list (1, listmode, fplist,
- _("certificate policy not allowed"));
- return gpg_error (GPG_ERR_NO_POLICY_MATCH);
- }
-
- for (;;)
- {
- int c;
- char *p, line[256];
- char *haystack, *allowed;
-
- /* read line */
- do
- {
- if (!fgets (line, DIM(line)-1, fp) )
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
-
- xfree (policies);
- if (feof (fp))
- {
- fclose (fp);
- /* With no critical policies this is only a warning */
- if (!any_critical)
- {
- do_list (0, listmode, fplist,
- _("note: non-critical certificate policy not allowed"));
- return 0;
- }
- do_list (1, listmode, fplist,
- _("certificate policy not allowed"));
- return gpg_error (GPG_ERR_NO_POLICY_MATCH);
- }
- fclose (fp);
- return tmperr;
- }
-
- if (!*line || line[strlen(line)-1] != '\n')
- {
- /* eat until end of line */
- while ( (c=getc (fp)) != EOF && c != '\n')
- ;
- fclose (fp);
- xfree (policies);
- return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
- : GPG_ERR_INCOMPLETE_LINE);
- }
-
- /* Allow for empty lines and spaces */
- for (p=line; spacep (p); p++)
- ;
- }
- while (!*p || *p == '\n' || *p == '#');
-
- /* parse line */
- for (allowed=line; spacep (allowed); allowed++)
- ;
- p = strpbrk (allowed, " :\n");
- if (!*p || p == allowed)
- {
- fclose (fp);
- xfree (policies);
- return gpg_error (GPG_ERR_CONFIGURATION);
- }
- *p = 0; /* strip the rest of the line */
- /* See whether we find ALLOWED (which is an OID) in POLICIES */
- for (haystack=policies; (p=strstr (haystack, allowed)); haystack = p+1)
- {
- if ( !(p == policies || p[-1] == '\n') )
- continue; /* Does not match the begin of a line. */
- if (p[strlen (allowed)] != ':')
- continue; /* The length does not match. */
- /* Yep - it does match so return okay. */
- fclose (fp);
- xfree (policies);
- return 0;
- }
- }
-}
-
-
-static void
-find_up_store_certs_cb (void *cb_value, ksba_cert_t cert)
-{
- if (keydb_store_cert (cert, 1, NULL))
- log_error ("error storing issuer certificate as ephemeral\n");
- ++*(int*)cb_value;
-}
-
-
-static int
-find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next)
-{
- ksba_name_t authid;
- ksba_sexp_t authidno;
- int rc = -1;
-
- if (!ksba_cert_get_auth_key_id (cert, NULL, &authid, &authidno))
- {
- const char *s = ksba_name_enum (authid, 0);
- if (s && *authidno)
- {
- rc = keydb_search_issuer_sn (kh, s, authidno);
- if (rc)
- keydb_search_reset (kh);
-
- /* In case of an error try the ephemeral DB. We can't do
- that in find-netx mode because we can't keep the search
- state then. */
- if (rc == -1 && !find_next)
- {
- int old = keydb_set_ephemeral (kh, 1);
- if (!old)
- {
- rc = keydb_search_issuer_sn (kh, s, authidno);
- if (rc)
- keydb_search_reset (kh);
- }
- keydb_set_ephemeral (kh, old);
- }
- }
- /* Print a note so that the user does not feel too helpless when
- an issuer certificate was found and gpgsm prints BAD
- signature because it is not the correct one. */
- if (rc == -1)
- {
- log_info ("issuer certificate (#");
- gpgsm_dump_serial (authidno);
- log_printf ("/");
- gpgsm_dump_string (s);
- log_printf (") not found\n");
- }
- else if (rc)
- log_error ("failed to find authorityKeyIdentifier: rc=%d\n", rc);
- ksba_name_release (authid);
- xfree (authidno);
- /* Fixme: don't know how to do dirmngr lookup with serial+issuer. */
- }
-
- if (rc) /* not found via authorithyKeyIdentifier, try regular issuer name */
- rc = keydb_search_subject (kh, issuer);
- if (rc == -1 && !find_next)
- {
- /* Not found, lets see whether we have one in the ephemeral key DB. */
- int old = keydb_set_ephemeral (kh, 1);
- if (!old)
- {
- keydb_search_reset (kh);
- rc = keydb_search_subject (kh, issuer);
- }
- keydb_set_ephemeral (kh, old);
- }
-
- if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next)
- {
- STRLIST names = NULL;
- int count = 0;
- char *pattern;
- const char *s;
-
- if (opt.verbose)
- log_info (_("looking up issuer at external location\n"));
- /* dirmngr is confused about unknown attributes so as a quick
- and ugly hack we locate the CN and use this and the
- following. Fixme: we should have far better parsing in the
- dirmngr. */
- s = strstr (issuer, "CN=");
- if (!s || s == issuer || s[-1] != ',')
- s = issuer;
-
- pattern = xtrymalloc (strlen (s)+2);
- if (!pattern)
- return OUT_OF_CORE (errno);
- strcpy (stpcpy (pattern, "/"), s);
- add_to_strlist (&names, pattern);
- xfree (pattern);
- rc = gpgsm_dirmngr_lookup (NULL, names, find_up_store_certs_cb, &count);
- free_strlist (names);
- if (opt.verbose)
- log_info (_("number of issuers matching: %d\n"), count);
- if (rc)
- {
- log_error ("external key lookup failed: %s\n", gpg_strerror (rc));
- rc = -1;
- }
- else if (!count)
- rc = -1;
- else
- {
- int old;
- /* The issuers are currently stored in the ephemeral key
- DB, so we temporary switch to ephemeral mode. */
- old = keydb_set_ephemeral (kh, 1);
- keydb_search_reset (kh);
- rc = keydb_search_subject (kh, issuer);
- keydb_set_ephemeral (kh, old);
- }
- }
- return rc;
-}
-
-
-/* Return the next certificate up in the chain starting at START.
- Returns -1 when there are no more certificates. */
-int
-gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next)
-{
- int rc = 0;
- char *issuer = NULL;
- char *subject = NULL;
- KEYDB_HANDLE kh = keydb_new (0);
-
- *r_next = NULL;
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- issuer = ksba_cert_get_issuer (start, 0);
- subject = ksba_cert_get_subject (start, 0);
- if (!issuer)
- {
- log_error ("no issuer found in certificate\n");
- rc = gpg_error (GPG_ERR_BAD_CERT);
- goto leave;
- }
- if (!subject)
- {
- log_error ("no subject found in certificate\n");
- rc = gpg_error (GPG_ERR_BAD_CERT);
- goto leave;
- }
-
- if (!strcmp (issuer, subject))
- {
- rc = -1; /* we are at the root */
- goto leave;
- }
-
- rc = find_up (kh, start, issuer, 0);
- if (rc)
- {
- /* it is quite common not to have a certificate, so better don't
- print an error here */
- if (rc != -1 && opt.verbose > 1)
- log_error ("failed to find issuer's certificate: rc=%d\n", rc);
- rc = gpg_error (GPG_ERR_MISSING_CERT);
- goto leave;
- }
-
- rc = keydb_get_cert (kh, r_next);
- if (rc)
- {
- log_error ("failed to get cert: rc=%d\n", rc);
- rc = gpg_error (GPG_ERR_GENERAL);
- }
-
- leave:
- xfree (issuer);
- xfree (subject);
- keydb_release (kh);
- return rc;
-}
-
-
-/* Check whether the CERT is a root certificate. Returns True if this
- is the case. */
-int
-gpgsm_is_root_cert (ksba_cert_t cert)
-{
- char *issuer;
- char *subject;
- int yes;
-
- issuer = ksba_cert_get_issuer (cert, 0);
- subject = ksba_cert_get_subject (cert, 0);
- yes = (issuer && subject && !strcmp (issuer, subject));
- xfree (issuer);
- xfree (subject);
- return yes;
-}
-
-
-/* This is a helper for gpgsm_validate_chain. */
-static gpg_error_t
-is_cert_still_valid (ctrl_t ctrl, int lm, FILE *fp,
- ksba_cert_t subject_cert, ksba_cert_t issuer_cert,
- int *any_revoked, int *any_no_crl, int *any_crl_too_old)
-{
- if (!opt.no_crl_check || ctrl->use_ocsp)
- {
- gpg_error_t err;
-
- err = gpgsm_dirmngr_isvalid (ctrl,
- subject_cert, issuer_cert, ctrl->use_ocsp);
- if (err)
- {
- /* Fixme: We should change the wording because we may
- have used OCSP. */
- switch (gpg_err_code (err))
- {
- case GPG_ERR_CERT_REVOKED:
- do_list (1, lm, fp, _("certificate has been revoked"));
- *any_revoked = 1;
- /* Store that in the keybox so that key listings are
- able to return the revoked flag. We don't care
- about error, though. */
- keydb_set_cert_flags (subject_cert, KEYBOX_FLAG_VALIDITY, 0,
- VALIDITY_REVOKED);
- break;
- case GPG_ERR_NO_CRL_KNOWN:
- do_list (1, lm, fp, _("no CRL found for certificate"));
- *any_no_crl = 1;
- break;
- case GPG_ERR_CRL_TOO_OLD:
- do_list (1, lm, fp, _("the available CRL is too old"));
- if (!lm)
- log_info (_("please make sure that the "
- "\"dirmngr\" is properly installed\n"));
- *any_crl_too_old = 1;
- break;
- default:
- do_list (1, lm, fp, _("checking the CRL failed: %s"),
- gpg_strerror (err));
- return err;
- }
- }
- }
- return 0;
-}
-
-
-
-/* Validate a chain and optionally return the nearest expiration time
- in R_EXPTIME. With LISTMODE set to 1 a special listmode is
- activated where only information about the certificate is printed
- to FP and no output is send to the usual log stream.
-
- Defined flag bits: 0 - do not do any dirmngr isvalid checks.
-*/
-int
-gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
- int listmode, FILE *fp, unsigned int flags)
-{
- int rc = 0, depth = 0, maxdepth;
- char *issuer = NULL;
- char *subject = NULL;
- KEYDB_HANDLE kh = keydb_new (0);
- ksba_cert_t subject_cert = NULL, issuer_cert = NULL;
- ksba_isotime_t current_time;
- ksba_isotime_t exptime;
- int any_expired = 0;
- int any_revoked = 0;
- int any_no_crl = 0;
- int any_crl_too_old = 0;
- int any_no_policy_match = 0;
- int lm = listmode;
-
- gnupg_get_isotime (current_time);
- if (r_exptime)
- *r_exptime = 0;
- *exptime = 0;
-
- if (opt.no_chain_validation && !listmode)
- {
- log_info ("WARNING: bypassing certificate chain validation\n");
- return 0;
- }
-
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- if (DBG_X509 && !listmode)
- gpgsm_dump_cert ("subject", cert);
-
- subject_cert = cert;
- maxdepth = 50;
-
- for (;;)
- {
- xfree (issuer);
- xfree (subject);
- issuer = ksba_cert_get_issuer (subject_cert, 0);
- subject = ksba_cert_get_subject (subject_cert, 0);
-
- if (!issuer)
- {
- do_list (1, lm, fp, _("no issuer found in certificate"));
- rc = gpg_error (GPG_ERR_BAD_CERT);
- goto leave;
- }
-
- {
- ksba_isotime_t not_before, not_after;
-
- rc = ksba_cert_get_validity (subject_cert, 0, not_before);
- if (!rc)
- rc = ksba_cert_get_validity (subject_cert, 1, not_after);
- if (rc)
- {
- do_list (1, lm, fp, _("certificate with invalid validity: %s"),
- gpg_strerror (rc));
- rc = gpg_error (GPG_ERR_BAD_CERT);
- goto leave;
- }
-
- if (*not_after)
- {
- if (!*exptime)
- gnupg_copy_time (exptime, not_after);
- else if (strcmp (not_after, exptime) < 0 )
- gnupg_copy_time (exptime, not_after);
- }
-
- if (*not_before && strcmp (current_time, not_before) < 0 )
- {
- do_list (1, lm, fp, _("certificate not yet valid"));
- if (!lm)
- {
- log_info ("(valid from ");
- gpgsm_dump_time (not_before);
- log_printf (")\n");
- }
- rc = gpg_error (GPG_ERR_CERT_TOO_YOUNG);
- goto leave;
- }
- if (*not_after && strcmp (current_time, not_after) > 0 )
- {
- do_list (opt.ignore_expiration?0:1, lm, fp,
- _("certificate has expired"));
- if (!lm)
- {
- log_info ("(expired at ");
- gpgsm_dump_time (not_after);
- log_printf (")\n");
- }
- if (opt.ignore_expiration)
- log_info ("WARNING: ignoring expiration\n");
- else
- any_expired = 1;
- }
- }
-
- rc = unknown_criticals (subject_cert, listmode, fp);
- if (rc)
- goto leave;
-
- if (!opt.no_policy_check)
- {
- rc = check_cert_policy (subject_cert, listmode, fp);
- if (gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH)
- {
- any_no_policy_match = 1;
- rc = 1;
- }
- else if (rc)
- goto leave;
- }
-
-
- /* Is this a self-signed certificate? */
- if (subject && !strcmp (issuer, subject))
- { /* Yes. */
- if (gpgsm_check_cert_sig (subject_cert, subject_cert) )
- {
- do_list (1, lm, fp,
- _("selfsigned certificate has a BAD signature"));
- rc = gpg_error (depth? GPG_ERR_BAD_CERT_CHAIN
- : GPG_ERR_BAD_CERT);
- goto leave;
- }
- rc = allowed_ca (subject_cert, NULL, listmode, fp);
- if (rc)
- goto leave;
-
- rc = gpgsm_agent_istrusted (ctrl, subject_cert);
- if (!rc)
- ;
- else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
- {
- do_list (0, lm, fp, _("root certificate is not marked trusted"));
- if (!lm)
- {
- int rc2;
- char *fpr = gpgsm_get_fingerprint_string (subject_cert,
- GCRY_MD_SHA1);
- log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
- xfree (fpr);
- rc2 = gpgsm_agent_marktrusted (ctrl, subject_cert);
- if (!rc2)
- {
- log_info (_("root certificate has now"
- " been marked as trusted\n"));
- rc = 0;
- }
- else
- {
- gpgsm_dump_cert ("issuer", subject_cert);
- log_info ("after checking the fingerprint, you may want "
- "to add it manually to the list of trusted "
- "certificates.\n");
- }
- }
- }
- else
- {
- log_error (_("checking the trust list failed: %s\n"),
- gpg_strerror (rc));
- }
-
- /* Check for revocations etc. */
- if ((flags & 1))
- rc = 0;
- else
- rc = is_cert_still_valid (ctrl, lm, fp,
- subject_cert, subject_cert,
- &any_revoked, &any_no_crl,
- &any_crl_too_old);
- if (rc)
- goto leave;
-
- break; /* Okay: a self-signed certicate is an end-point. */
- }
-
- depth++;
- if (depth > maxdepth)
- {
- do_list (1, lm, fp, _("certificate chain too long\n"));
- rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
- goto leave;
- }
-
- /* find the next cert up the tree */
- keydb_search_reset (kh);
- rc = find_up (kh, subject_cert, issuer, 0);
- if (rc)
- {
- if (rc == -1)
- {
- do_list (0, lm, fp, _("issuer certificate not found"));
- if (!lm)
- {
- log_info ("issuer certificate: #/");
- gpgsm_dump_string (issuer);
- log_printf ("\n");
- }
- }
- else
- log_error ("failed to find issuer's certificate: rc=%d\n", rc);
- rc = gpg_error (GPG_ERR_MISSING_CERT);
- goto leave;
- }
-
- ksba_cert_release (issuer_cert); issuer_cert = NULL;
- rc = keydb_get_cert (kh, &issuer_cert);
- if (rc)
- {
- log_error ("failed to get cert: rc=%d\n", rc);
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- try_another_cert:
- if (DBG_X509)
- {
- log_debug ("got issuer's certificate:\n");
- gpgsm_dump_cert ("issuer", issuer_cert);
- }
-
- rc = gpgsm_check_cert_sig (issuer_cert, subject_cert);
- if (rc)
- {
- do_list (0, lm, fp, _("certificate has a BAD signature"));
- if (gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE)
- {
- /* We now try to find other issuer certificates which
- might have been used. This is rquired because some
- CAs are reusing the issuer and subject DN for new
- root certificates. */
- rc = find_up (kh, subject_cert, issuer, 1);
- if (!rc)
- {
- ksba_cert_t tmp_cert;
-
- rc = keydb_get_cert (kh, &tmp_cert);
- if (rc || !compare_certs (issuer_cert, tmp_cert))
- {
- /* The find next did not work or returned an
- identical certificate. We better stop here
- to avoid infinite checks. */
- rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
- ksba_cert_release (tmp_cert);
- }
- else
- {
- do_list (0, lm, fp, _("found another possible matching "
- "CA certificate - trying again"));
- ksba_cert_release (issuer_cert);
- issuer_cert = tmp_cert;
- goto try_another_cert;
- }
- }
- }
-
- /* We give a more descriptive error code than the one
- returned from the signature checking. */
- rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
- goto leave;
- }
-
- {
- int chainlen;
- rc = allowed_ca (issuer_cert, &chainlen, listmode, fp);
- if (rc)
- goto leave;
- if (chainlen >= 0 && (depth - 1) > chainlen)
- {
- do_list (1, lm, fp,
- _("certificate chain longer than allowed by CA (%d)"),
- chainlen);
- rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
- goto leave;
- }
- }
-
- if (!listmode)
- {
- rc = gpgsm_cert_use_cert_p (issuer_cert);
- if (rc)
- {
- char numbuf[50];
- sprintf (numbuf, "%d", rc);
- gpgsm_status2 (ctrl, STATUS_ERROR, "certcert.issuer.keyusage",
- numbuf, NULL);
- goto leave;
- }
- }
-
- /* Check for revocations etc. */
- if ((flags & 1))
- rc = 0;
- else
- rc = is_cert_still_valid (ctrl, lm, fp,
- subject_cert, issuer_cert,
- &any_revoked, &any_no_crl, &any_crl_too_old);
- if (rc)
- goto leave;
-
-
- if (opt.verbose && !listmode)
- log_info ("certificate is good\n");
-
- keydb_search_reset (kh);
- subject_cert = issuer_cert;
- issuer_cert = NULL;
- }
-
- if (!listmode)
- {
- if (opt.no_policy_check)
- log_info ("policies not checked due to %s option\n",
- "--disable-policy-checks");
- if (opt.no_crl_check && !ctrl->use_ocsp)
- log_info ("CRLs not checked due to %s option\n",
- "--disable-crl-checks");
- }
-
- if (!rc)
- { /* If we encountered an error somewhere during the checks, set
- the error code to the most critical one */
- if (any_revoked)
- rc = gpg_error (GPG_ERR_CERT_REVOKED);
- else if (any_no_crl)
- rc = gpg_error (GPG_ERR_NO_CRL_KNOWN);
- else if (any_crl_too_old)
- rc = gpg_error (GPG_ERR_CRL_TOO_OLD);
- else if (any_no_policy_match)
- rc = gpg_error (GPG_ERR_NO_POLICY_MATCH);
- else if (any_expired)
- rc = gpg_error (GPG_ERR_CERT_EXPIRED);
- }
-
- leave:
- if (r_exptime)
- gnupg_copy_time (r_exptime, exptime);
- xfree (issuer);
- keydb_release (kh);
- ksba_cert_release (issuer_cert);
- if (subject_cert != cert)
- ksba_cert_release (subject_cert);
- return rc;
-}
-
-
-/* Check that the given certificate is valid but DO NOT check any
- constraints. We assume that the issuers certificate is already in
- the DB and that this one is valid; which it should be because it
- has been checked using this function. */
-int
-gpgsm_basic_cert_check (ksba_cert_t cert)
-{
- int rc = 0;
- char *issuer = NULL;
- char *subject = NULL;
- KEYDB_HANDLE kh = keydb_new (0);
- ksba_cert_t issuer_cert = NULL;
-
- if (opt.no_chain_validation)
- {
- log_info ("WARNING: bypassing basic certificate checks\n");
- return 0;
- }
-
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- issuer = ksba_cert_get_issuer (cert, 0);
- subject = ksba_cert_get_subject (cert, 0);
- if (!issuer)
- {
- log_error ("no issuer found in certificate\n");
- rc = gpg_error (GPG_ERR_BAD_CERT);
- goto leave;
- }
-
- if (subject && !strcmp (issuer, subject))
- {
- if (gpgsm_check_cert_sig (cert, cert) )
- {
- log_error ("selfsigned certificate has a BAD signature\n");
- rc = gpg_error (GPG_ERR_BAD_CERT);
- goto leave;
- }
- }
- else
- {
- /* find the next cert up the tree */
- keydb_search_reset (kh);
- rc = find_up (kh, cert, issuer, 0);
- if (rc)
- {
- if (rc == -1)
- {
- log_info ("issuer certificate (#/");
- gpgsm_dump_string (issuer);
- log_printf (") not found\n");
- }
- else
- log_error ("failed to find issuer's certificate: rc=%d\n", rc);
- rc = gpg_error (GPG_ERR_MISSING_CERT);
- goto leave;
- }
-
- ksba_cert_release (issuer_cert); issuer_cert = NULL;
- rc = keydb_get_cert (kh, &issuer_cert);
- if (rc)
- {
- log_error ("failed to get cert: rc=%d\n", rc);
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- if (gpgsm_check_cert_sig (issuer_cert, cert) )
- {
- log_error ("certificate has a BAD signature\n");
- rc = gpg_error (GPG_ERR_BAD_CERT);
- goto leave;
- }
- if (opt.verbose)
- log_info ("certificate is good\n");
- }
-
- leave:
- xfree (issuer);
- keydb_release (kh);
- ksba_cert_release (issuer_cert);
- return rc;
-}
-
diff --git a/sm/certcheck.c b/sm/certcheck.c
deleted file mode 100644
index b5ed9914a..000000000
--- a/sm/certcheck.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/* certcheck.c - check one certificate
- * Copyright (C) 2001, 2003 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-
-static int
-do_encode_md (gcry_md_hd_t md, int algo, unsigned int nbits,
- gcry_mpi_t *r_val)
-{
- int nframe = (nbits+7) / 8;
- byte *frame;
- int i, n;
- byte asn[100];
- size_t asnlen;
- size_t len;
-
- asnlen = DIM(asn);
- if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
- {
- log_error ("no object identifier for algo %d\n", algo);
- return gpg_error (GPG_ERR_INTERNAL);
- }
-
- len = gcry_md_get_algo_dlen (algo);
-
- if ( len + asnlen + 4 > nframe )
- {
- log_error ("can't encode a %d bit MD into a %d bits frame\n",
- (int)(len*8), (int)nbits);
- return gpg_error (GPG_ERR_INTERNAL);
- }
-
- /* We encode the MD in this way:
- *
- * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
- *
- * PAD consists of FF bytes.
- */
- frame = xtrymalloc (nframe);
- if (!frame)
- return OUT_OF_CORE (errno);
- n = 0;
- frame[n++] = 0;
- frame[n++] = 1; /* block type */
- i = nframe - len - asnlen -3 ;
- assert ( i > 1 );
- memset ( frame+n, 0xff, i ); n += i;
- frame[n++] = 0;
- memcpy ( frame+n, asn, asnlen ); n += asnlen;
- memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len;
- assert ( n == nframe );
- if (DBG_X509)
- {
- int j;
- log_debug ("encoded hash:");
- for (j=0; j < nframe; j++)
- log_printf (" %02X", frame[j]);
- log_printf ("\n");
- }
-
- gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, n, &nframe);
- xfree (frame);
- return 0;
-}
-
-
-/*
- Check the signature on CERT using the ISSUER-CERT. This function
- does only test the cryptographic signature and nothing else. It is
- assumed that the ISSUER_CERT is valid. */
-int
-gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
-{
- const char *algoid;
- gcry_md_hd_t md;
- int rc, algo;
- gcry_mpi_t frame;
- ksba_sexp_t p;
- size_t n;
- gcry_sexp_t s_sig, s_hash, s_pkey;
-
- algo = gcry_md_map_name ( (algoid=ksba_cert_get_digest_algo (cert)));
- if (!algo)
- {
- log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?");
- return gpg_error (GPG_ERR_GENERAL);
- }
- rc = gcry_md_open (&md, algo, 0);
- if (rc)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (rc));
- return rc;
- }
- if (DBG_HASHING)
- gcry_md_start_debug (md, "hash.cert");
-
- rc = ksba_cert_hash (cert, 1, HASH_FNC, md);
- if (rc)
- {
- log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (rc));
- gcry_md_close (md);
- return rc;
- }
- gcry_md_final (md);
-
- p = ksba_cert_get_sig_val (cert);
- n = gcry_sexp_canon_len (p, 0, NULL, NULL);
- if (!n)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- gcry_md_close (md);
- ksba_free (p);
- return gpg_error (GPG_ERR_BUG);
- }
- if (DBG_X509)
- {
- int j;
- log_debug ("signature value:");
- for (j=0; j < n; j++)
- log_printf (" %02X", p[j]);
- log_printf ("\n");
- }
-
- rc = gcry_sexp_sscan ( &s_sig, NULL, p, n);
- ksba_free (p);
- if (rc)
- {
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- gcry_md_close (md);
- return rc;
- }
-
- p = ksba_cert_get_public_key (issuer_cert);
- n = gcry_sexp_canon_len (p, 0, NULL, NULL);
- if (!n)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- gcry_md_close (md);
- ksba_free (p);
- gcry_sexp_release (s_sig);
- return gpg_error (GPG_ERR_BUG);
- }
- rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
- ksba_free (p);
- if (rc)
- {
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- gcry_md_close (md);
- gcry_sexp_release (s_sig);
- return rc;
- }
-
- rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame);
- if (rc)
- {
- gcry_md_close (md);
- gcry_sexp_release (s_sig);
- gcry_sexp_release (s_pkey);
- return rc;
- }
-
- /* put hash into the S-Exp s_hash */
- if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
- BUG ();
- gcry_mpi_release (frame);
-
-
- rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
- if (DBG_CRYPTO)
- log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
- gcry_md_close (md);
- gcry_sexp_release (s_sig);
- gcry_sexp_release (s_hash);
- gcry_sexp_release (s_pkey);
- return rc;
-}
-
-
-
-int
-gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
- gcry_md_hd_t md, int algo)
-{
- int rc;
- ksba_sexp_t p;
- gcry_mpi_t frame;
- gcry_sexp_t s_sig, s_hash, s_pkey;
- size_t n;
-
- n = gcry_sexp_canon_len (sigval, 0, NULL, NULL);
- if (!n)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- return gpg_error (GPG_ERR_BUG);
- }
- rc = gcry_sexp_sscan (&s_sig, NULL, sigval, n);
- if (rc)
- {
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- return rc;
- }
-
- p = ksba_cert_get_public_key (cert);
- n = gcry_sexp_canon_len (p, 0, NULL, NULL);
- if (!n)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- ksba_free (p);
- gcry_sexp_release (s_sig);
- return gpg_error (GPG_ERR_BUG);
- }
- if (DBG_X509)
- log_printhex ("public key: ", p, n);
-
- rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
- ksba_free (p);
- if (rc)
- {
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- gcry_sexp_release (s_sig);
- return rc;
- }
-
-
- rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame);
- if (rc)
- {
- gcry_sexp_release (s_sig);
- gcry_sexp_release (s_pkey);
- return rc;
- }
- /* put hash into the S-Exp s_hash */
- if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
- BUG ();
- gcry_mpi_release (frame);
-
- rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
- if (DBG_CRYPTO)
- log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
- gcry_sexp_release (s_sig);
- gcry_sexp_release (s_hash);
- gcry_sexp_release (s_pkey);
- return rc;
-}
-
-
-
-int
-gpgsm_create_cms_signature (ctrl_t ctrl, ksba_cert_t cert,
- gcry_md_hd_t md, int mdalgo, char **r_sigval)
-{
- int rc;
- char *grip, *desc;
- size_t siglen;
-
- grip = gpgsm_get_keygrip_hexstring (cert);
- if (!grip)
- return gpg_error (GPG_ERR_BAD_CERT);
-
- desc = gpgsm_format_keydesc (cert);
-
- rc = gpgsm_agent_pksign (ctrl, grip, desc, gcry_md_read(md, mdalgo),
- gcry_md_get_algo_dlen (mdalgo), mdalgo,
- r_sigval, &siglen);
- xfree (desc);
- xfree (grip);
- return rc;
-}
-
-
-
diff --git a/sm/certdump.c b/sm/certdump.c
deleted file mode 100644
index 21581dca3..000000000
--- a/sm/certdump.c
+++ /dev/null
@@ -1,696 +0,0 @@
-/* certdump.c - Dump a certificate for debugging
- * Copyright (C) 2001, 2004 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-#ifdef HAVE_LOCALE_H
-#include <locale.h>
-#endif
-#ifdef HAVE_LANGINFO_CODESET
-#include <langinfo.h>
-#endif
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-struct dn_array_s {
- char *key;
- char *value;
- int multivalued;
- int done;
-};
-
-
-/* print the first element of an S-Expression */
-void
-gpgsm_print_serial (FILE *fp, ksba_const_sexp_t p)
-{
- unsigned long n;
- char *endp;
-
- if (!p)
- fputs (_("none"), fp);
- else if (*p != '(')
- fputs ("[Internal error - not an S-expression]", fp);
- else
- {
- p++;
- n = strtoul (p, &endp, 10);
- p = endp;
- if (*p!=':')
- fputs ("[Internal Error - invalid S-expression]", fp);
- else
- {
- for (p++; n; n--, p++)
- fprintf (fp, "%02X", *p);
- }
- }
-}
-
-
-void
-gpgsm_dump_serial (ksba_const_sexp_t p)
-{
- unsigned long n;
- char *endp;
-
- if (!p)
- log_printf ("none");
- else if (*p != '(')
- log_printf ("ERROR - not an S-expression");
- else
- {
- p++;
- n = strtoul (p, &endp, 10);
- p = endp;
- if (*p!=':')
- log_printf ("ERROR - invalid S-expression");
- else
- {
- for (p++; n; n--, p++)
- log_printf ("%02X", *p);
- }
- }
-}
-
-
-char *
-gpgsm_format_serial (ksba_const_sexp_t p)
-{
- unsigned long n;
- char *endp;
- char *buffer;
- int i;
-
- if (!p)
- return NULL;
-
- if (*p != '(')
- BUG (); /* Not a valid S-expression. */
-
- p++;
- n = strtoul (p, &endp, 10);
- p = endp;
- if (*p!=':')
- BUG (); /* Not a valid S-expression. */
- p++;
-
- buffer = xtrymalloc (n*2+1);
- if (buffer)
- {
- for (i=0; n; n--, p++, i+=2)
- sprintf (buffer+i, "%02X", *(unsigned char *)p);
- buffer[i] = 0;
- }
- return buffer;
-}
-
-
-
-
-void
-gpgsm_print_time (FILE *fp, ksba_isotime_t t)
-{
- if (!t || !*t)
- fputs (_("none"), fp);
- else
- fprintf (fp, "%.4s-%.2s-%.2s %.2s:%.2s:%s", t, t+4, t+6, t+9, t+11, t+13);
-}
-
-void
-gpgsm_dump_time (ksba_isotime_t t)
-{
- if (!t || !*t)
- log_printf (_("[none]"));
- else
- log_printf ("%.4s-%.2s-%.2s %.2s:%.2s:%s",
- t, t+4, t+6, t+9, t+11, t+13);
-}
-
-
-
-
-void
-gpgsm_dump_string (const char *string)
-{
-
- if (!string)
- log_printf ("[error]");
- else
- {
- const unsigned char *s;
-
- for (s=string; *s; s++)
- {
- if (*s < ' ' || (*s >= 0x7f && *s <= 0xa0))
- break;
- }
- if (!*s && *string != '[')
- log_printf ("%s", string);
- else
- {
- log_printf ( "[ ");
- log_printhex (NULL, string, strlen (string));
- log_printf ( " ]");
- }
- }
-}
-
-
-/* This simple dump function is mainly used for debugging purposes. */
-void
-gpgsm_dump_cert (const char *text, ksba_cert_t cert)
-{
- ksba_sexp_t sexp;
- unsigned char *p;
- char *dn;
- ksba_isotime_t t;
-
- log_debug ("BEGIN Certificate `%s':\n", text? text:"");
- if (cert)
- {
- sexp = ksba_cert_get_serial (cert);
- log_debug (" serial: ");
- gpgsm_dump_serial (sexp);
- ksba_free (sexp);
- log_printf ("\n");
-
- ksba_cert_get_validity (cert, 0, t);
- log_debug (" notBefore: ");
- gpgsm_dump_time (t);
- log_printf ("\n");
- ksba_cert_get_validity (cert, 1, t);
- log_debug (" notAfter: ");
- gpgsm_dump_time (t);
- log_printf ("\n");
-
- dn = ksba_cert_get_issuer (cert, 0);
- log_debug (" issuer: ");
- gpgsm_dump_string (dn);
- ksba_free (dn);
- log_printf ("\n");
-
- dn = ksba_cert_get_subject (cert, 0);
- log_debug (" subject: ");
- gpgsm_dump_string (dn);
- ksba_free (dn);
- log_printf ("\n");
-
- log_debug (" hash algo: %s\n", ksba_cert_get_digest_algo (cert));
-
- p = gpgsm_get_fingerprint_string (cert, 0);
- log_debug (" SHA1 Fingerprint: %s\n", p);
- xfree (p);
- }
- log_debug ("END Certificate\n");
-}
-
-
-
-/* helper for the rfc2253 string parser */
-static const unsigned char *
-parse_dn_part (struct dn_array_s *array, const unsigned char *string)
-{
- static struct {
- const char *label;
- const char *oid;
- } label_map[] = {
- /* Warning: When adding new labels, make sure that the buffer
- below we be allocated large enough. */
- {"EMail", "1.2.840.113549.1.9.1" },
- {"T", "2.5.4.12" },
- {"GN", "2.5.4.42" },
- {"SN", "2.5.4.4" },
- {"NameDistinguisher", "0.2.262.1.10.7.20"},
- {"ADDR", "2.5.4.16" },
- {"BC", "2.5.4.15" },
- {"D", "2.5.4.13" },
- {"PostalCode", "2.5.4.17" },
- {"Pseudo", "2.5.4.65" },
- {"SerialNumber", "2.5.4.5" },
- {NULL, NULL}
- };
- const unsigned char *s, *s1;
- size_t n;
- unsigned char *p;
- int i;
-
- /* Parse attributeType */
- for (s = string+1; *s && *s != '='; s++)
- ;
- if (!*s)
- return NULL; /* error */
- n = s - string;
- if (!n)
- return NULL; /* empty key */
-
- /* We need to allocate a few bytes more due to the possible mapping
- from the shorter OID to the longer label. */
- array->key = p = xtrymalloc (n+10);
- if (!array->key)
- return NULL;
- memcpy (p, string, n);
- p[n] = 0;
- trim_trailing_spaces (p);
-
- if (digitp (p))
- {
- for (i=0; label_map[i].label; i++ )
- if ( !strcmp (p, label_map[i].oid) )
- {
- strcpy (p, label_map[i].label);
- break;
- }
- }
- string = s + 1;
-
- if (*string == '#')
- { /* hexstring */
- string++;
- for (s=string; hexdigitp (s); s++)
- s++;
- n = s - string;
- if (!n || (n & 1))
- return NULL; /* Empty or odd number of digits. */
- n /= 2;
- array->value = p = xtrymalloc (n+1);
- if (!p)
- return NULL;
- for (s1=string; n; s1 += 2, n--, p++)
- {
- *p = xtoi_2 (s1);
- if (!*p)
- *p = 0x01; /* Better print a wrong value than truncating
- the string. */
- }
- *p = 0;
- }
- else
- { /* regular v3 quoted string */
- for (n=0, s=string; *s; s++)
- {
- if (*s == '\\')
- { /* pair */
- s++;
- if (*s == ',' || *s == '=' || *s == '+'
- || *s == '<' || *s == '>' || *s == '#' || *s == ';'
- || *s == '\\' || *s == '\"' || *s == ' ')
- n++;
- else if (hexdigitp (s) && hexdigitp (s+1))
- {
- s++;
- n++;
- }
- else
- return NULL; /* invalid escape sequence */
- }
- else if (*s == '\"')
- return NULL; /* invalid encoding */
- else if (*s == ',' || *s == '=' || *s == '+'
- || *s == '<' || *s == '>' || *s == '#' || *s == ';' )
- break;
- else
- n++;
- }
-
- array->value = p = xtrymalloc (n+1);
- if (!p)
- return NULL;
- for (s=string; n; s++, n--)
- {
- if (*s == '\\')
- {
- s++;
- if (hexdigitp (s))
- {
- *p++ = xtoi_2 (s);
- s++;
- }
- else
- *p++ = *s;
- }
- else
- *p++ = *s;
- }
- *p = 0;
- }
- return s;
-}
-
-
-/* Parse a DN and return an array-ized one. This is not a validating
- parser and it does not support any old-stylish syntax; KSBA is
- expected to return only rfc2253 compatible strings. */
-static struct dn_array_s *
-parse_dn (const unsigned char *string)
-{
- struct dn_array_s *array;
- size_t arrayidx, arraysize;
- int i;
-
- arraysize = 7; /* C,ST,L,O,OU,CN,email */
- arrayidx = 0;
- array = xtrymalloc ((arraysize+1) * sizeof *array);
- if (!array)
- return NULL;
- while (*string)
- {
- while (*string == ' ')
- string++;
- if (!*string)
- break; /* ready */
- if (arrayidx >= arraysize)
- {
- struct dn_array_s *a2;
-
- arraysize += 5;
- a2 = xtryrealloc (array, (arraysize+1) * sizeof *array);
- if (!a2)
- goto failure;
- array = a2;
- }
- array[arrayidx].key = NULL;
- array[arrayidx].value = NULL;
- string = parse_dn_part (array+arrayidx, string);
- if (!string)
- goto failure;
- while (*string == ' ')
- string++;
- array[arrayidx].multivalued = (*string == '+');
- array[arrayidx].done = 0;
- arrayidx++;
- if (*string && *string != ',' && *string != ';' && *string != '+')
- goto failure; /* invalid delimiter */
- if (*string)
- string++;
- }
- array[arrayidx].key = NULL;
- array[arrayidx].value = NULL;
- return array;
-
- failure:
- for (i=0; i < arrayidx; i++)
- {
- xfree (array[i].key);
- xfree (array[i].value);
- }
- xfree (array);
- return NULL;
-}
-
-
-static void
-print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key)
-{
- struct dn_array_s *first_dn = dn;
-
- for (; dn->key; dn++)
- {
- if (!dn->done && !strcmp (dn->key, key))
- {
- /* Forward to the last multi-valued RDN, so that we can
- print them all in reverse in the correct order. Note
- that this overrides the the standard sequence but that
- seems to a reasonable thing to do with multi-valued
- RDNs. */
- while (dn->multivalued && dn[1].key)
- dn++;
- next:
- if (!dn->done && dn->value && *dn->value)
- {
- fprintf (fp, "/%s=", dn->key);
- print_sanitized_utf8_string (fp, dn->value, '/');
- }
- dn->done = 1;
- if (dn > first_dn && dn[-1].multivalued)
- {
- dn--;
- goto next;
- }
- }
- }
-}
-
-/* Print all parts of a DN in a "standard" sequence. We first print
- all the known parts, followed by the uncommon ones */
-static void
-print_dn_parts (FILE *fp, struct dn_array_s *dn)
-{
- const char *stdpart[] = {
- "CN", "OU", "O", "STREET", "L", "ST", "C", "EMail", NULL
- };
- int i;
-
- for (i=0; stdpart[i]; i++)
- print_dn_part (fp, dn, stdpart[i]);
-
- /* Now print the rest without any specific ordering */
- for (; dn->key; dn++)
- print_dn_part (fp, dn, dn->key);
-}
-
-
-
-void
-gpgsm_print_name (FILE *fp, const char *name)
-{
- const unsigned char *s;
- int i;
-
- s = name;
- if (!s)
- {
- fputs (_("[Error - No name]"), fp);
- }
- else if (*s == '<')
- {
- const unsigned char *s2 = strchr (s+1, '>');
- if (s2)
- print_sanitized_utf8_buffer (fp, s + 1, s2 - s - 1, 0);
- }
- else if (*s == '(')
- fputs (_("[Error - unknown encoding]"), fp);
- else if (!((*s >= '0' && *s < '9')
- || (*s >= 'A' && *s <= 'Z')
- || (*s >= 'a' && *s <= 'z')))
- fputs (_("[Error - invalid encoding]"), fp);
- else
- {
- struct dn_array_s *dn = parse_dn (s);
- if (!dn)
- fputs (_("[Error - invalid DN]"), fp);
- else
- {
- print_dn_parts (fp, dn);
- for (i=0; dn[i].key; i++)
- {
- xfree (dn[i].key);
- xfree (dn[i].value);
- }
- xfree (dn);
- }
- }
-}
-
-
-
-/* A cookie structure used for the memory stream. */
-struct format_name_cookie
-{
- char *buffer; /* Malloced buffer with the data to deliver. */
- size_t size; /* Allocated size of this buffer. */
- size_t len; /* strlen (buffer). */
- int error; /* system error code if any. */
-};
-
-/* The writer function for the memory stream. */
-static int
-format_name_writer (void *cookie, const char *buffer, size_t size)
-{
- struct format_name_cookie *c = cookie;
- char *p;
-
- if (c->buffer)
- p = xtryrealloc (c->buffer, c->size + size + 1);
- else
- p = xtrymalloc (size + 1);
- if (!p)
- {
- c->error = errno;
- xfree (c->buffer);
- errno = c->error;
- return -1;
- }
- c->buffer = p;
- memcpy (p + c->len, buffer, size);
- c->len += size;
- p[c->len] = 0; /* Terminate string. */
-
- return size;
-}
-
-/* Format NAME which is expected to be in rfc2253 format into a better
- human readable format. Caller must free the returned string. NULL
- is returned in case of an error. */
-char *
-gpgsm_format_name (const char *name)
-{
-#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
- FILE *fp;
- struct format_name_cookie cookie;
-
- memset (&cookie, 0, sizeof cookie);
-
-#ifdef HAVE_FOPENCOOKIE
- {
- cookie_io_functions_t io = { NULL };
- io.write = format_name_writer;
-
- fp = fopencookie (&cookie, "w", io);
- }
-#else /*!HAVE_FOPENCOOKIE*/
- {
- fp = funopen (&cookie, NULL, format_name_writer, NULL, NULL);
- }
-#endif /*!HAVE_FOPENCOOKIE*/
- if (!fp)
- {
- int save_errno = errno;
- log_error ("error creating memory stream: %s\n", strerror (errno));
- errno = save_errno;
- return NULL;
- }
- gpgsm_print_name (fp, name);
- fclose (fp);
- if (cookie.error || !cookie.buffer)
- {
- xfree (cookie.buffer);
- errno = cookie.error;
- return NULL;
- }
- return cookie.buffer;
-#else /* No fun - use the name verbatim. */
- return xtrystrdup (name);
-#endif /* No fun. */
-}
-
-
-/* Create a key description for the CERT, this may be passed to the
- pinentry. The caller must free the returned string. NULL may be
- returned on error. */
-char *
-gpgsm_format_keydesc (ksba_cert_t cert)
-{
- int rc;
- char *name, *subject, *buffer, *p;
- const char *s;
- ksba_isotime_t t;
- char created[20];
- char *sn;
- ksba_sexp_t sexp;
- char *orig_codeset = NULL;
-
- name = ksba_cert_get_subject (cert, 0);
- subject = name? gpgsm_format_name (name) : NULL;
- ksba_free (name); name = NULL;
-
- sexp = ksba_cert_get_serial (cert);
- sn = sexp? gpgsm_format_serial (sexp) : NULL;
- ksba_free (sexp);
-
- ksba_cert_get_validity (cert, 0, t);
- if (t && *t)
- sprintf (created, "%.4s-%.2s-%.2s", t, t+4, t+6);
- else
- *created = 0;
-
-
-#ifdef ENABLE_NLS
- /* The Assuan agent protol requires us to transmit utf-8 strings */
- orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL);
-#ifdef HAVE_LANGINFO_CODESET
- if (!orig_codeset)
- orig_codeset = nl_langinfo (CODESET);
-#endif
- if (orig_codeset)
- { /* We only switch when we are able to restore the codeset later. */
- orig_codeset = xstrdup (orig_codeset);
- if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8"))
- orig_codeset = NULL;
- }
-#endif
-
-
- rc = asprintf (&name,
- _("Please enter the passphrase to unlock the"
- " secret key for:\n"
- "\"%s\"\n"
- "S/N %s, ID %08lX, created %s" ),
- subject? subject:"?",
- sn? sn: "?",
- gpgsm_get_short_fingerprint (cert),
- created);
-
-#ifdef ENABLE_NLS
- if (orig_codeset)
- bind_textdomain_codeset (PACKAGE_GT, orig_codeset);
-#endif
- xfree (orig_codeset);
-
- if (rc < 0)
- {
- int save_errno = errno;
- xfree (subject);
- xfree (sn);
- errno = save_errno;
- return NULL;
- }
-
- xfree (subject);
- xfree (sn);
-
- buffer = p = xtrymalloc (strlen (name) * 3 + 1);
- for (s=name; *s; s++)
- {
- if (*s < ' ' || *s == '+')
- {
- sprintf (p, "%%%02X", *(unsigned char *)s);
- p += 3;
- }
- else if (*s == ' ')
- *p++ = '+';
- else
- *p++ = *s;
- }
- *p = 0;
- free (name);
-
- return buffer;
-}
diff --git a/sm/certlist.c b/sm/certlist.c
deleted file mode 100644
index 96acf90f7..000000000
--- a/sm/certlist.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/* certlist.c - build list of certificates
- * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-
-static const char oid_kp_serverAuth[] = "1.3.6.1.5.5.7.3.1";
-static const char oid_kp_clientAuth[] = "1.3.6.1.5.5.7.3.2";
-static const char oid_kp_codeSigning[] = "1.3.6.1.5.5.7.3.3";
-static const char oid_kp_emailProtection[]= "1.3.6.1.5.5.7.3.4";
-static const char oid_kp_timeStamping[] = "1.3.6.1.5.5.7.3.8";
-static const char oid_kp_ocspSigning[] = "1.3.6.1.5.6.7.3.9";
-
-/* Return 0 if the cert is usable for encryption. A MODE of 0 checks
- for signing a MODE of 1 checks for encryption, a MODE of 2 checks
- for verification and a MODE of 3 for decryption (just for
- debugging) */
-static int
-cert_usage_p (ksba_cert_t cert, int mode)
-{
- gpg_error_t err;
- unsigned int use;
- char *extkeyusages;
-
- err = ksba_cert_get_ext_key_usages (cert, &extkeyusages);
- if (gpg_err_code (err) == GPG_ERR_NO_DATA)
- err = 0; /* no policy given */
- if (!err)
- {
- unsigned int extusemask = ~0; /* Allow all. */
-
- if (extkeyusages)
- {
- char *p, *pend;
- int any_critical = 0;
-
- extusemask = 0;
-
- p = extkeyusages;
- while (p && (pend=strchr (p, ':')))
- {
- *pend++ = 0;
- /* Only care about critical flagged usages. */
- if ( *pend == 'C' )
- {
- any_critical = 1;
- if ( !strcmp (p, oid_kp_serverAuth))
- extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE
- | KSBA_KEYUSAGE_KEY_ENCIPHERMENT
- | KSBA_KEYUSAGE_KEY_AGREEMENT);
- else if ( !strcmp (p, oid_kp_clientAuth))
- extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE
- | KSBA_KEYUSAGE_KEY_AGREEMENT);
- else if ( !strcmp (p, oid_kp_codeSigning))
- extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE);
- else if ( !strcmp (p, oid_kp_emailProtection))
- extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE
- | KSBA_KEYUSAGE_NON_REPUDIATION
- | KSBA_KEYUSAGE_KEY_ENCIPHERMENT
- | KSBA_KEYUSAGE_KEY_AGREEMENT);
- else if ( !strcmp (p, oid_kp_timeStamping))
- extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE
- | KSBA_KEYUSAGE_NON_REPUDIATION);
- }
-
- if ((p = strchr (pend, '\n')))
- p++;
- }
- xfree (extkeyusages);
- extkeyusages = NULL;
-
- if (!any_critical)
- extusemask = ~0; /* Reset to the don't care mask. */
- }
-
-
- err = ksba_cert_get_key_usage (cert, &use);
- if (gpg_err_code (err) == GPG_ERR_NO_DATA)
- {
- err = 0;
- if (opt.verbose && mode < 2)
- log_info (_("no key usage specified - assuming all usages\n"));
- use = ~0;
- }
-
- /* Apply extKeyUsage. */
- use &= extusemask;
-
- }
- if (err)
- {
- log_error (_("error getting key usage information: %s\n"),
- gpg_strerror (err));
- xfree (extkeyusages);
- return err;
- }
-
- if (mode == 4)
- {
- if ((use & (KSBA_KEYUSAGE_KEY_CERT_SIGN)))
- return 0;
- log_info (_("certificate should have not "
- "been used for certification\n"));
- return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
- }
-
- if ((use & ((mode&1)?
- (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT):
- (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
- )
- return 0;
-
- log_info (mode==3? _("certificate should have not been used for encryption\n"):
- mode==2? _("certificate should have not been used for signing\n"):
- mode==1? _("certificate is not usable for encryption\n"):
- _("certificate is not usable for signing\n"));
- return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
-}
-
-
-/* Return 0 if the cert is usable for signing */
-int
-gpgsm_cert_use_sign_p (ksba_cert_t cert)
-{
- return cert_usage_p (cert, 0);
-}
-
-
-/* Return 0 if the cert is usable for encryption */
-int
-gpgsm_cert_use_encrypt_p (ksba_cert_t cert)
-{
- return cert_usage_p (cert, 1);
-}
-
-int
-gpgsm_cert_use_verify_p (ksba_cert_t cert)
-{
- return cert_usage_p (cert, 2);
-}
-
-int
-gpgsm_cert_use_decrypt_p (ksba_cert_t cert)
-{
- return cert_usage_p (cert, 3);
-}
-
-int
-gpgsm_cert_use_cert_p (ksba_cert_t cert)
-{
- return cert_usage_p (cert, 4);
-}
-
-
-static int
-same_subject_issuer (const char *subject, const char *issuer, ksba_cert_t cert)
-{
- char *subject2 = ksba_cert_get_subject (cert, 0);
- char *issuer2 = ksba_cert_get_subject (cert, 0);
- int tmp;
-
- tmp = (subject && subject2
- && !strcmp (subject, subject2)
- && issuer && issuer2
- && !strcmp (issuer, issuer2));
- xfree (subject2);
- xfree (issuer2);
- return tmp;
-}
-
-/* Return true if CERT is already contained in CERTLIST. */
-static int
-is_cert_in_certlist (ksba_cert_t cert, certlist_t certlist)
-{
- const unsigned char *img_a, *img_b;
- size_t len_a, len_b;
-
- img_a = ksba_cert_get_image (cert, &len_a);
- if (img_a)
- {
- for ( ; certlist; certlist = certlist->next)
- {
- img_b = ksba_cert_get_image (certlist->cert, &len_b);
- if (img_b && len_a == len_b && !memcmp (img_a, img_b, len_a))
- return 1; /* Already contained. */
- }
- }
- return 0;
-}
-
-
-/* Add CERT to the list of certificates at CERTADDR but avoid
- duplicates. */
-int
-gpgsm_add_cert_to_certlist (ctrl_t ctrl, ksba_cert_t cert,
- certlist_t *listaddr, int is_encrypt_to)
-{
- if (!is_cert_in_certlist (cert, *listaddr))
- {
- certlist_t cl = xtrycalloc (1, sizeof *cl);
- if (!cl)
- return OUT_OF_CORE (errno);
- cl->cert = cert;
- ksba_cert_ref (cert);
- cl->next = *listaddr;
- cl->is_encrypt_to = is_encrypt_to;
- *listaddr = cl;
- }
- return 0;
-}
-
-/* Add a certificate to a list of certificate and make sure that it is
- a valid certificate. With SECRET set to true a secret key must be
- available for the certificate. IS_ENCRYPT_TO sets the corresponding
- flag in the new create LISTADDR item. */
-int
-gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret,
- CERTLIST *listaddr, int is_encrypt_to)
-{
- int rc;
- KEYDB_SEARCH_DESC desc;
- KEYDB_HANDLE kh = NULL;
- ksba_cert_t cert = NULL;
-
- rc = keydb_classify_name (name, &desc);
- if (!rc)
- {
- kh = keydb_new (0);
- if (!kh)
- rc = gpg_error (GPG_ERR_ENOMEM);
- else
- {
- int wrong_usage = 0;
- char *subject = NULL;
- char *issuer = NULL;
-
- get_next:
- rc = keydb_search (kh, &desc, 1);
- if (!rc)
- rc = keydb_get_cert (kh, &cert);
- if (!rc)
- {
- rc = secret? gpgsm_cert_use_sign_p (cert)
- : gpgsm_cert_use_encrypt_p (cert);
- if (gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE)
- {
- /* There might be another certificate with the
- correct usage, so we try again */
- if (!wrong_usage)
- { /* save the first match */
- wrong_usage = rc;
- subject = ksba_cert_get_subject (cert, 0);
- issuer = ksba_cert_get_subject (cert, 0);
- ksba_cert_release (cert);
- cert = NULL;
- goto get_next;
- }
- else if (same_subject_issuer (subject, issuer, cert))
- {
- wrong_usage = rc;
- ksba_cert_release (cert);
- cert = NULL;
- goto get_next;
- }
- else
- wrong_usage = rc;
-
- }
- }
- /* We want the error code from the first match in this case. */
- if (rc && wrong_usage)
- rc = wrong_usage;
-
- if (!rc)
- {
- next_ambigious:
- rc = keydb_search (kh, &desc, 1);
- if (rc == -1)
- rc = 0;
- else if (!rc)
- {
- ksba_cert_t cert2 = NULL;
-
- /* We have to ignore ambigious names as long as
- there only fault is a bad key usage */
- if (!keydb_get_cert (kh, &cert2))
- {
- int tmp = (same_subject_issuer (subject, issuer, cert2)
- && ((gpg_err_code (
- secret? gpgsm_cert_use_sign_p (cert2)
- : gpgsm_cert_use_encrypt_p (cert2)
- )
- ) == GPG_ERR_WRONG_KEY_USAGE));
- ksba_cert_release (cert2);
- if (tmp)
- goto next_ambigious;
- }
- rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
- }
- }
- xfree (subject);
- xfree (issuer);
-
- if (!rc && !is_cert_in_certlist (cert, *listaddr))
- {
- if (!rc && secret)
- {
- char *p;
-
- rc = gpg_error (GPG_ERR_NO_SECKEY);
- p = gpgsm_get_keygrip_hexstring (cert);
- if (p)
- {
- if (!gpgsm_agent_havekey (ctrl, p))
- rc = 0;
- xfree (p);
- }
- }
- if (!rc)
- rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0);
- if (!rc)
- {
- CERTLIST cl = xtrycalloc (1, sizeof *cl);
- if (!cl)
- rc = OUT_OF_CORE (errno);
- else
- {
- cl->cert = cert; cert = NULL;
- cl->next = *listaddr;
- cl->is_encrypt_to = is_encrypt_to;
- *listaddr = cl;
- }
- }
- }
- }
- }
-
- keydb_release (kh);
- ksba_cert_release (cert);
- return rc == -1? gpg_error (GPG_ERR_NO_PUBKEY): rc;
-}
-
-void
-gpgsm_release_certlist (CERTLIST list)
-{
- while (list)
- {
- CERTLIST cl = list->next;
- ksba_cert_release (list->cert);
- xfree (list);
- list = cl;
- }
-}
-
-
-/* Like gpgsm_add_to_certlist, but look only for one certificate. No
- chain validation is done */
-int
-gpgsm_find_cert (const char *name, ksba_cert_t *r_cert)
-{
- int rc;
- KEYDB_SEARCH_DESC desc;
- KEYDB_HANDLE kh = NULL;
-
- *r_cert = NULL;
- rc = keydb_classify_name (name, &desc);
- if (!rc)
- {
- kh = keydb_new (0);
- if (!kh)
- rc = gpg_error (GPG_ERR_ENOMEM);
- else
- {
- rc = keydb_search (kh, &desc, 1);
- if (!rc)
- rc = keydb_get_cert (kh, r_cert);
- if (!rc)
- {
- rc = keydb_search (kh, &desc, 1);
- if (rc == -1)
- rc = 0;
- else
- {
- if (!rc)
- rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
- ksba_cert_release (*r_cert);
- *r_cert = NULL;
- }
- }
- }
- }
-
- keydb_release (kh);
- return rc == -1? gpg_error (GPG_ERR_NO_PUBKEY): rc;
-}
-
diff --git a/sm/certreqgen.c b/sm/certreqgen.c
deleted file mode 100644
index 969ed14b0..000000000
--- a/sm/certreqgen.c
+++ /dev/null
@@ -1,739 +0,0 @@
-/* certreqgen.c - Generate a key and a certification request
- * Copyright (C) 2002, 2003 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-/*
-The format of the native parameter file is follows:
- o Text only, line length is limited to about 1000 chars.
- o You must use UTF-8 encoding to specify non-ascii characters.
- o Empty lines are ignored.
- o Leading and trailing spaces are ignored.
- o A hash sign as the first non white space character is a comment line.
- o Control statements are indicated by a leading percent sign, the
- arguments are separated by white space from the keyword.
- o Parameters are specified by a keyword, followed by a colon. Arguments
- are separated by white space.
- o The first parameter must be "Key-Type", control statements
- may be placed anywhere.
- o Key generation takes place when either the end of the parameter file
- is reached, the next "Key-Type" parameter is encountered or at the
- controlstatement "%commit"
- o Control statements:
- %echo <text>
- Print <text>.
- %dry-run
- Suppress actual key generation (useful for syntax checking).
- %commit
- Perform the key generation. Note that an implicit commit is done
- at the next "Key-Type" parameter.
- %certfile <filename>
- Do not write the certificate to the keyDB but to <filename>.
- This must be given before the first
- commit to take place, duplicate specification of the same filename
- is ignored, the last filename before a commit is used.
- The filename is used until a new filename is used (at commit points)
- and all keys are written to that file. If a new filename is given,
- this file is created (and overwrites an existing one).
- Both control statements must be given.
- o The order of the parameters does not matter except for "Key-Type"
- which must be the first parameter. The parameters are only for the
- generated keyblock and parameters from previous key generations are not
- used. Some syntactically checks may be performed.
- The currently defined parameters are:
- Key-Type: <algo>
- Starts a new parameter block by giving the type of the
- primary key. The algorithm must be capable of signing.
- This is a required parameter. For now the only supported
- algorithm is "rsa".
- Key-Length: <length-in-bits>
- Length of the key in bits. Default is 1024.
- Key-Usage: <usage-list>
- Space or comma delimited list of key usage, allowed values are
- "encrypt" and "sign". This is used to generate the KeyUsage extension.
- Please make sure that the algorithm is capable of this usage. Default
- is to allow encrypt and sign.
- Name-DN: subject name
- This is the DN name of the subject in rfc2253 format.
- Name-Email: <string>
- The ist the email address
-
-Here is an example:
-$ cat >foo <<EOF
-%echo Generating a standard key
-Key-Type: RSA
-Key-Length: 1024
-Name-DN: CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=Düsseldorf,C=DE
-Name-Email: [email protected]
-# Do a commit here, so that we can later print "done" :-)
-%commit
-%echo done
-EOF
-*/
-
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-
-enum para_name {
- pKEYTYPE,
- pKEYLENGTH,
- pKEYUSAGE,
- pNAMEDN,
- pNAMEEMAIL
-};
-
-struct para_data_s {
- struct para_data_s *next;
- int lnr;
- enum para_name key;
- union {
- unsigned int usage;
- char value[1];
- } u;
-};
-
-struct reqgen_ctrl_s {
- int lnr;
- int dryrun;
- ksba_writer_t writer;
-};
-
-
-static const char oidstr_keyUsage[] = "2.5.29.15";
-
-
-static int proc_parameters (ctrl_t ctrl,
- struct para_data_s *para,
- struct reqgen_ctrl_s *outctrl);
-static int create_request (ctrl_t ctrl,
- struct para_data_s *para,
- ksba_const_sexp_t public,
- struct reqgen_ctrl_s *outctrl);
-
-
-
-static void
-release_parameter_list (struct para_data_s *r)
-{
- struct para_data_s *r2;
-
- for (; r ; r = r2)
- {
- r2 = r->next;
- xfree(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 (digitp (r->u.value))
- return atoi( r->u.value );
- return gcry_pk_map_name (r->u.value);
-}
-
-/* Parse the usage parameter. Returns 0 on success. Note that we
- only care about sign and encrypt and don't (yet) allow all the
- other X.509 usage to be specified; instead we will use a fixed
- mapping to the X.509 usage flags. */
-static int
-parse_parameter_usage (struct para_data_s *para, enum para_name key)
-{
- struct para_data_s *r = get_parameter (para, key);
- char *p, *pn;
- unsigned int use;
-
- if (!r)
- return 0; /* none (this is an optional parameter)*/
-
- use = 0;
- pn = r->u.value;
- while ( (p = strsep (&pn, " \t,")) )
- {
- if (!*p)
- ;
- else if ( !ascii_strcasecmp (p, "sign") )
- use |= GCRY_PK_USAGE_SIGN;
- else if ( !ascii_strcasecmp (p, "encrypt") )
- use |= GCRY_PK_USAGE_ENCR;
- else
- {
- log_error ("line %d: invalid usage list\n", r->lnr);
- return -1; /* error */
- }
- }
- r->u.usage = use;
- return 0;
-}
-
-
-static unsigned int
-get_parameter_uint (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 == pKEYUSAGE)
- return r->u.usage;
-
- return (unsigned int)strtoul (r->u.value, NULL, 10);
-}
-
-
-
-/* Read the certificate generation parameters from FP and generate
- (all) certificate requests. */
-static int
-read_parameters (ctrl_t ctrl, FILE *fp, ksba_writer_t writer)
-{
- static struct {
- const char *name;
- enum para_name key;
- } keywords[] = {
- { "Key-Type", pKEYTYPE},
- { "Key-Length", pKEYLENGTH },
- { "Key-Usage", pKEYUSAGE },
- { "Name-DN", pNAMEDN },
- { "Name-Email", pNAMEEMAIL },
- { NULL, 0 }
- };
- char line[1024], *p;
- const char *err = NULL;
- struct para_data_s *para, *r;
- int i, rc = 0, any = 0;
- struct reqgen_ctrl_s outctrl;
-
- memset (&outctrl, 0, sizeof (outctrl));
- outctrl.writer = writer;
-
- err = NULL;
- para = NULL;
- while (fgets (line, DIM(line)-1, fp) )
- {
- char *keyword, *value;
-
- outctrl.lnr++;
- if (*line && line[strlen(line)-1] != '\n')
- {
- err = "line too long";
- break;
- }
- for (p=line; spacep (p); p++)
- ;
- if (!*p || *p == '#')
- continue;
-
- keyword = p;
- if (*keyword == '%')
- {
- for (; *p && !spacep (p); p++)
- ;
- if (*p)
- *p++ = 0;
- for (; spacep (p); p++)
- ;
- value = p;
- trim_trailing_spaces (value);
-
- if (!ascii_strcasecmp (keyword, "%echo"))
- log_info ("%s\n", value);
- else if (!ascii_strcasecmp (keyword, "%dry-run"))
- outctrl.dryrun = 1;
- else if (!ascii_strcasecmp( keyword, "%commit"))
- {
- rc = proc_parameters (ctrl, para, &outctrl);
- if (rc)
- goto leave;
- any = 1;
- release_parameter_list (para);
- para = NULL;
- }
- 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 (; spacep (p); p++)
- ;
- if (!*p)
- {
- err = "missing argument";
- break;
- }
- value = p;
- trim_trailing_spaces (value);
-
- for (i=0; (keywords[i].name
- && ascii_strcasecmp (keywords[i].name, keyword)); i++)
- ;
- 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)
- {
- rc = proc_parameters (ctrl, para, &outctrl);
- if (rc)
- goto leave;
- any = 1;
- release_parameter_list (para);
- para = NULL;
- }
- else
- {
- for (r = para; r && r->key != keywords[i].key; r = r->next)
- ;
- if (r)
- {
- err = "duplicate keyword";
- break;
- }
- }
-
- r = xtrycalloc (1, sizeof *r + strlen( value ));
- if (!r)
- {
- err = "out of core";
- break;
- }
- r->lnr = outctrl.lnr;
- r->key = keywords[i].key;
- strcpy (r->u.value, value);
- r->next = para;
- para = r;
- }
-
- if (err)
- {
- log_error ("line %d: %s\n", outctrl.lnr, err);
- rc = gpg_error (GPG_ERR_GENERAL);
- }
- else if (ferror(fp))
- {
- log_error ("line %d: read error: %s\n", outctrl.lnr, strerror(errno) );
- rc = gpg_error (GPG_ERR_GENERAL);
- }
- else if (para)
- {
- rc = proc_parameters (ctrl, para, &outctrl);
- if (rc)
- goto leave;
- any = 1;
- }
-
- if (!rc && !any)
- rc = gpg_error (GPG_ERR_NO_DATA);
-
- leave:
- release_parameter_list (para);
- return rc;
-}
-
-/* check whether there are invalid characters in the email address S */
-static int
-has_invalid_email_chars (const char *s)
-{
- int at_seen=0;
- static char valid_chars[] = "01234567890_-."
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- for (; *s; s++)
- {
- if (*s & 0x80)
- return 1;
- if (*s == '@')
- at_seen++;
- else if (!at_seen && !( !!strchr (valid_chars, *s) || *s == '+'))
- return 1;
- else if (at_seen && !strchr (valid_chars, *s))
- return 1;
- }
- return at_seen != 1;
-}
-
-
-/* Check that all required parameters are given and perform the action */
-static int
-proc_parameters (ctrl_t ctrl,
- struct para_data_s *para, struct reqgen_ctrl_s *outctrl)
-{
- struct para_data_s *r;
- const char *s;
- int i;
- unsigned int nbits;
- char numbuf[20];
- unsigned char keyparms[100];
- int rc;
- ksba_sexp_t public;
-
- /* check that we have all required parameters */
- assert (get_parameter (para, pKEYTYPE));
-
- /* We can only use RSA for now. There is a with pkcs-10 on how to
- use ElGamal because it is expected that a PK algorithm can always
- be used for signing. */
- i = get_parameter_algo (para, pKEYTYPE);
- if (i < 1 || i != GCRY_PK_RSA )
- {
- r = get_parameter (para, pKEYTYPE);
- log_error ("line %d: invalid algorithm\n", r->lnr);
- return gpg_error (GPG_ERR_INV_PARAMETER);
- }
-
- /* check the keylength */
- if (!get_parameter (para, pKEYLENGTH))
- nbits = 1024;
- else
- nbits = get_parameter_uint (para, pKEYLENGTH);
- if (nbits < 512 || nbits > 4096)
- {
- r = get_parameter (para, pKEYTYPE);
- log_error ("line %d: invalid key length %u (valid are 512 to 4096)\n",
- r->lnr, nbits);
- return gpg_error (GPG_ERR_INV_PARAMETER);
- }
-
- /* check the usage */
- if (parse_parameter_usage (para, pKEYUSAGE))
- return gpg_error (GPG_ERR_INV_PARAMETER);
-
- /* check that there is a subject name and that this DN fits our
- requirements */
- if (!(s=get_parameter_value (para, pNAMEDN)))
- {
- r = get_parameter (para, pKEYTYPE);
- log_error ("line %d: no subject name given\n", r->lnr);
- return gpg_error (GPG_ERR_INV_PARAMETER);
- }
- /* fixme check s */
-
- /* check that the optional email address is okay */
- if ((s=get_parameter_value (para, pNAMEEMAIL)))
- {
- if (has_invalid_email_chars (s)
- || *s == '@'
- || s[strlen(s)-1] == '@'
- || s[strlen(s)-1] == '.'
- || strstr(s, ".."))
- {
- r = get_parameter (para, pKEYTYPE);
- log_error ("line %d: not a valid email address\n", r->lnr);
- return gpg_error (GPG_ERR_INV_PARAMETER);
- }
- }
-
- sprintf (numbuf, "%u", nbits);
- snprintf (keyparms, DIM (keyparms)-1,
- "(6:genkey(3:rsa(5:nbits%d:%s)))", strlen (numbuf), numbuf);
- rc = gpgsm_agent_genkey (ctrl, keyparms, &public);
- if (rc)
- {
- r = get_parameter (para, pKEYTYPE);
- log_error ("line %d: key generation failed: %s\n",
- r->lnr, gpg_strerror (rc));
- return rc;
- }
-
- rc = create_request (ctrl, para, public, outctrl);
- xfree (public);
-
- return rc;
-}
-
-
-/* Parameters are checked, the key pair has been created. Now
- generate the request and write it out */
-static int
-create_request (ctrl_t ctrl,
- struct para_data_s *para, ksba_const_sexp_t public,
- struct reqgen_ctrl_s *outctrl)
-{
- ksba_certreq_t cr;
- gpg_error_t err;
- gcry_md_hd_t md;
- ksba_stop_reason_t stopreason;
- int rc = 0;
- const char *s;
- unsigned int use;
-
- err = ksba_certreq_new (&cr);
- if (err)
- return err;
-
- rc = gcry_md_open (&md, GCRY_MD_SHA1, 0);
- if (rc)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- if (DBG_HASHING)
- gcry_md_start_debug (md, "cr.cri");
-
- ksba_certreq_set_hash_function (cr, HASH_FNC, md);
- ksba_certreq_set_writer (cr, outctrl->writer);
-
- err = ksba_certreq_add_subject (cr, get_parameter_value (para, pNAMEDN));
- if (err)
- {
- log_error ("error setting the subject's name: %s\n",
- gpg_strerror (err));
- rc = err;
- goto leave;
- }
-
- s = get_parameter_value (para, pNAMEEMAIL);
- if (s)
- {
- char *buf;
-
- buf = xtrymalloc (strlen (s) + 3);
- if (!buf)
- {
- rc = OUT_OF_CORE (errno);
- goto leave;
- }
- *buf = '<';
- strcpy (buf+1, s);
- strcat (buf+1, ">");
- err = ksba_certreq_add_subject (cr, buf);
- xfree (buf);
- if (err)
- {
- log_error ("error setting the subject's alternate name: %s\n",
- gpg_strerror (err));
- rc = err;
- goto leave;
- }
- }
-
-
- err = ksba_certreq_set_public_key (cr, public);
- if (err)
- {
- log_error ("error setting the public key: %s\n",
- gpg_strerror (err));
- rc = err;
- goto leave;
- }
-
-
- use = get_parameter_uint (para, pKEYUSAGE);
- if (use == GCRY_PK_USAGE_SIGN)
- {
- /* For signing only we encode the bits:
- KSBA_KEYUSAGE_DIGITAL_SIGNATURE
- KSBA_KEYUSAGE_NON_REPUDIATION */
- err = ksba_certreq_add_extension (cr, oidstr_keyUsage, 1,
- "\x03\x02\x06\xC0", 4);
- }
- else if (use == GCRY_PK_USAGE_ENCR)
- {
- /* For encrypt only we encode the bits:
- KSBA_KEYUSAGE_KEY_ENCIPHERMENT
- KSBA_KEYUSAGE_DATA_ENCIPHERMENT */
- err = ksba_certreq_add_extension (cr, oidstr_keyUsage, 1,
- "\x03\x02\x04\x30", 4);
- }
- else
- err = 0; /* Both or none given: don't request one. */
- if (err)
- {
- log_error ("error setting the key usage: %s\n",
- gpg_strerror (err));
- rc = err;
- goto leave;
- }
-
-
- do
- {
- err = ksba_certreq_build (cr, &stopreason);
- if (err)
- {
- log_error ("ksba_certreq_build failed: %s\n", gpg_strerror (err));
- rc = err;
- goto leave;
- }
- if (stopreason == KSBA_SR_NEED_SIG)
- {
- gcry_sexp_t s_pkey;
- size_t n;
- unsigned char grip[20], hexgrip[41];
- char *sigval;
- size_t siglen;
-
- n = gcry_sexp_canon_len (public, 0, NULL, NULL);
- if (!n)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- err = gpg_error (GPG_ERR_BUG);
- goto leave;
- }
- rc = gcry_sexp_sscan (&s_pkey, NULL, public, n);
- if (rc)
- {
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- if ( !gcry_pk_get_keygrip (s_pkey, grip) )
- {
- rc = gpg_error (GPG_ERR_GENERAL);
- log_error ("can't figure out the keygrip\n");
- gcry_sexp_release (s_pkey);
- goto leave;
- }
- gcry_sexp_release (s_pkey);
- for (n=0; n < 20; n++)
- sprintf (hexgrip+n*2, "%02X", grip[n]);
-
- rc = gpgsm_agent_pksign (ctrl, hexgrip, NULL,
- gcry_md_read(md, GCRY_MD_SHA1),
- gcry_md_get_algo_dlen (GCRY_MD_SHA1),
- GCRY_MD_SHA1,
- &sigval, &siglen);
- if (rc)
- {
- log_error ("signing failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- err = ksba_certreq_set_sig_val (cr, sigval);
- xfree (sigval);
- if (err)
- {
- log_error ("failed to store the sig_val: %s\n",
- gpg_strerror (err));
- rc = err;
- goto leave;
- }
- }
- }
- while (stopreason != KSBA_SR_READY);
-
-
- leave:
- gcry_md_close (md);
- ksba_certreq_release (cr);
- return rc;
-}
-
-
-
-/* Create a new key by reading the parameters from in_fd. Multiple
- keys may be created */
-int
-gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp)
-{
- int rc;
- FILE *in_fp;
- Base64Context b64writer = NULL;
- ksba_writer_t writer;
-
- in_fp = fdopen (dup (in_fd), "rb");
- if (!in_fp)
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("fdopen() failed: %s\n", strerror (errno));
- return tmperr;
- }
-
- ctrl->pem_name = "NEW CERTIFICATE REQUEST";
- rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
- if (rc)
- {
- log_error ("can't create writer: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- rc = read_parameters (ctrl, in_fp, writer);
- if (rc)
- {
- log_error ("error creating certificate request: %s\n",
- gpg_strerror (rc));
- goto leave;
- }
-
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- gpgsm_status (ctrl, STATUS_KEY_CREATED, "P");
- log_info ("certificate request created\n");
-
- leave:
- gpgsm_destroy_writer (b64writer);
- fclose (in_fp);
- return rc;
-}
-
diff --git a/sm/decrypt.c b/sm/decrypt.c
deleted file mode 100644
index 8ac2e23fe..000000000
--- a/sm/decrypt.c
+++ /dev/null
@@ -1,512 +0,0 @@
-/* decrypt.c - Decrypt a message
- * Copyright (C) 2001, 2003 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-struct decrypt_filter_parm_s {
- int algo;
- int mode;
- int blklen;
- gcry_cipher_hd_t hd;
- char iv[16];
- size_t ivlen;
- int any_data; /* dod we push anything through the filter at all? */
- unsigned char lastblock[16]; /* to strip the padding we have to
- keep this one */
- char helpblock[16]; /* needed because there is no block buffering in
- libgcrypt (yet) */
- int helpblocklen;
-};
-
-
-
-/* Decrypt the session key and fill in the parm structure. The
- algo and the IV is expected to be already in PARM. */
-static int
-prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
- ksba_const_sexp_t enc_val,
- struct decrypt_filter_parm_s *parm)
-{
- char *seskey = NULL;
- size_t n, seskeylen;
- int rc;
-
- rc = gpgsm_agent_pkdecrypt (ctrl, hexkeygrip, desc, enc_val,
- &seskey, &seskeylen);
- if (rc)
- {
- log_error ("error decrypting session key: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- if (DBG_CRYPTO)
- log_printhex ("pkcs1 encoded session key:", seskey, seskeylen);
-
- n=0;
- if (seskeylen == 24)
- {
- /* Smells like a 3-des key. This might happen because a SC has
- already done the unpacking. */
- }
- else
- {
- if (n + 7 > seskeylen )
- {
- rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
- goto leave;
- }
-
- /* FIXME: Actually the leading zero is required but due to the way
- we encode the output in libgcrypt as an MPI we are not able to
- encode that leading zero. However, when using a Smartcard we are
- doing it the right way and therefore we have to skip the zero. This
- should be fixed in gpg-agent of course. */
- if (!seskey[n])
- n++;
-
- if (seskey[n] != 2 ) /* Wrong block type version. */
- {
- rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
- goto leave;
- }
-
- for (n++; n < seskeylen && seskey[n]; n++) /* Skip the random bytes. */
- ;
- n++; /* and the zero byte */
- if (n >= seskeylen )
- {
- rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
- goto leave;
- }
- }
-
- if (DBG_CRYPTO)
- log_printhex ("session key:", seskey+n, seskeylen-n);
-
- rc = gcry_cipher_open (&parm->hd, parm->algo, parm->mode, 0);
- if (rc)
- {
- log_error ("error creating decryptor: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- rc = gcry_cipher_setkey (parm->hd, seskey+n, seskeylen-n);
- if (gpg_err_code (rc) == GPG_ERR_WEAK_KEY)
- {
- log_info (_("WARNING: message was encrypted with "
- "a weak key in the symmetric cipher.\n"));
- rc = 0;
- }
- if (rc)
- {
- log_error("key setup failed: %s\n", gpg_strerror(rc) );
- goto leave;
- }
-
- gcry_cipher_setiv (parm->hd, parm->iv, parm->ivlen);
-
- leave:
- xfree (seskey);
- return rc;
-}
-
-
-/* This function is called by the KSBA writer just before the actual
- write is done. The function must take INLEN bytes from INBUF,
- decrypt it and store it inoutbuf which has a maximum size of
- maxoutlen. The valid bytes in outbuf should be return in outlen.
- Due to different buffer sizes or different length of input and
- output, it may happen that fewer bytes are process or fewer bytes
- are written. */
-static gpg_error_t
-decrypt_filter (void *arg,
- const void *inbuf, size_t inlen, size_t *inused,
- void *outbuf, size_t maxoutlen, size_t *outlen)
-{
- struct decrypt_filter_parm_s *parm = arg;
- int blklen = parm->blklen;
- size_t orig_inlen = inlen;
-
- /* fixme: Should we issue an error when we have not seen one full block? */
- if (!inlen)
- return gpg_error (GPG_ERR_BUG);
-
- if (maxoutlen < 2*parm->blklen)
- return gpg_error (GPG_ERR_BUG);
- /* make some space becuase we will later need an extra block at the end */
- maxoutlen -= blklen;
-
- if (parm->helpblocklen)
- {
- int i, j;
-
- for (i=parm->helpblocklen,j=0; i < blklen && j < inlen; i++, j++)
- parm->helpblock[i] = ((const char*)inbuf)[j];
- inlen -= j;
- if (blklen > maxoutlen)
- return gpg_error (GPG_ERR_BUG);
- if (i < blklen)
- {
- parm->helpblocklen = i;
- *outlen = 0;
- }
- else
- {
- parm->helpblocklen = 0;
- if (parm->any_data)
- {
- memcpy (outbuf, parm->lastblock, blklen);
- *outlen =blklen;
- }
- else
- *outlen = 0;
- gcry_cipher_decrypt (parm->hd, parm->lastblock, blklen,
- parm->helpblock, blklen);
- parm->any_data = 1;
- }
- *inused = orig_inlen - inlen;
- return 0;
- }
-
-
- if (inlen > maxoutlen)
- inlen = maxoutlen;
- if (inlen % blklen)
- { /* store the remainder away */
- parm->helpblocklen = inlen%blklen;
- inlen = inlen/blklen*blklen;
- memcpy (parm->helpblock, (const char*)inbuf+inlen, parm->helpblocklen);
- }
-
- *inused = inlen + parm->helpblocklen;
- if (inlen)
- {
- assert (inlen >= blklen);
- if (parm->any_data)
- {
- gcry_cipher_decrypt (parm->hd, (char*)outbuf+blklen, inlen,
- inbuf, inlen);
- memcpy (outbuf, parm->lastblock, blklen);
- memcpy (parm->lastblock,(char*)outbuf+inlen, blklen);
- *outlen = inlen;
- }
- else
- {
- gcry_cipher_decrypt (parm->hd, outbuf, inlen, inbuf, inlen);
- memcpy (parm->lastblock, (char*)outbuf+inlen-blklen, blklen);
- *outlen = inlen - blklen;
- parm->any_data = 1;
- }
- }
- else
- *outlen = 0;
- return 0;
-}
-
-
-
-/* Perform a decrypt operation. */
-int
-gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
-{
- int rc;
- Base64Context b64reader = NULL;
- Base64Context b64writer = NULL;
- ksba_reader_t reader;
- ksba_writer_t writer;
- ksba_cms_t cms = NULL;
- ksba_stop_reason_t stopreason;
- KEYDB_HANDLE kh;
- int recp;
- FILE *in_fp = NULL;
- struct decrypt_filter_parm_s dfparm;
-
- memset (&dfparm, 0, sizeof dfparm);
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
-
- in_fp = fdopen ( dup (in_fd), "rb");
- if (!in_fp)
- {
- rc = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("fdopen() failed: %s\n", strerror (errno));
- goto leave;
- }
-
- rc = gpgsm_create_reader (&b64reader, ctrl, in_fp, 0, &reader);
- if (rc)
- {
- log_error ("can't create reader: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
- if (rc)
- {
- log_error ("can't create writer: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- rc = ksba_cms_new (&cms);
- if (rc)
- goto leave;
-
- rc = ksba_cms_set_reader_writer (cms, reader, writer);
- if (rc)
- {
- log_debug ("ksba_cms_set_reader_writer failed: %s\n",
- gpg_strerror (rc));
- goto leave;
- }
-
- /* parser loop */
- do
- {
- rc = ksba_cms_parse (cms, &stopreason);
- if (rc)
- {
- log_debug ("ksba_cms_parse failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- if (stopreason == KSBA_SR_BEGIN_DATA
- || stopreason == KSBA_SR_DETACHED_DATA)
- {
- int algo, mode;
- const char *algoid;
- int any_key = 0;
-
- algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/);
- algo = gcry_cipher_map_name (algoid);
- mode = gcry_cipher_mode_from_oid (algoid);
- if (!algo || !mode)
- {
- rc = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
- log_error ("unsupported algorithm `%s'\n", algoid? algoid:"?");
- if (algoid && !strcmp (algoid, "1.2.840.113549.3.2"))
- log_info (_("(this is the RC2 algorithm)\n"));
- else if (!algoid)
- log_info (_("(this does not seem to be an encrypted"
- " message)\n"));
- {
- char numbuf[50];
- sprintf (numbuf, "%d", rc);
- gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm",
- numbuf, algoid?algoid:"?", NULL);
- }
-
- /* If it seems that this is not an ecrypted message we
- return a more sensible error code. */
- if (!algoid)
- rc = gpg_error (GPG_ERR_NO_DATA);
-
- goto leave;
- }
- dfparm.algo = algo;
- dfparm.mode = mode;
- dfparm.blklen = gcry_cipher_get_algo_blklen (algo);
- if (dfparm.blklen > sizeof (dfparm.helpblock))
- return gpg_error (GPG_ERR_BUG);
-
- rc = ksba_cms_get_content_enc_iv (cms,
- dfparm.iv,
- sizeof (dfparm.iv),
- &dfparm.ivlen);
- if (rc)
- {
- log_error ("error getting IV: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- for (recp=0; !any_key; recp++)
- {
- char *issuer;
- ksba_sexp_t serial;
- ksba_sexp_t enc_val;
- char *hexkeygrip = NULL;
- char *desc = NULL;
-
- rc = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial);
- if (rc == -1 && recp)
- break; /* no more recipients */
- if (rc)
- log_error ("recp %d - error getting info: %s\n",
- recp, gpg_strerror (rc));
- else
- {
- ksba_cert_t cert = NULL;
-
- log_debug ("recp %d - issuer: `%s'\n",
- recp, issuer? issuer:"[NONE]");
- log_debug ("recp %d - serial: ", recp);
- gpgsm_dump_serial (serial);
- log_printf ("\n");
-
- keydb_search_reset (kh);
- rc = keydb_search_issuer_sn (kh, issuer, serial);
- if (rc)
- {
- log_error ("failed to find the certificate: %s\n",
- gpg_strerror(rc));
- goto oops;
- }
-
- rc = keydb_get_cert (kh, &cert);
- if (rc)
- {
- log_error ("failed to get cert: %s\n", gpg_strerror (rc));
- goto oops;
- }
- /* Just in case there is a problem with the own
- certificate we print this message - should never
- happen of course */
- rc = gpgsm_cert_use_decrypt_p (cert);
- if (rc)
- {
- char numbuf[50];
- sprintf (numbuf, "%d", rc);
- gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.keyusage",
- numbuf, NULL);
- rc = 0;
- }
-
- hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
- desc = gpgsm_format_keydesc (cert);
-
- oops:
- xfree (issuer);
- xfree (serial);
- ksba_cert_release (cert);
- }
-
- if (!hexkeygrip)
- ;
- else if (!(enc_val = ksba_cms_get_enc_val (cms, recp)))
- log_error ("recp %d - error getting encrypted session key\n",
- recp);
- else
- {
- rc = prepare_decryption (ctrl,
- hexkeygrip, desc, enc_val, &dfparm);
- xfree (enc_val);
- if (rc)
- {
- log_info ("decrypting session key failed: %s\n",
- gpg_strerror (rc));
- }
- else
- { /* setup the bulk decrypter */
- any_key = 1;
- ksba_writer_set_filter (writer,
- decrypt_filter,
- &dfparm);
- }
- }
- xfree (hexkeygrip);
- xfree (desc);
- }
- if (!any_key)
- {
- rc = gpg_error (GPG_ERR_NO_SECKEY);
- goto leave;
- }
- }
- else if (stopreason == KSBA_SR_END_DATA)
- {
- ksba_writer_set_filter (writer, NULL, NULL);
- if (dfparm.any_data)
- { /* write the last block with padding removed */
- int i, npadding = dfparm.lastblock[dfparm.blklen-1];
- if (!npadding || npadding > dfparm.blklen)
- {
- log_error ("invalid padding with value %d\n", npadding);
- rc = gpg_error (GPG_ERR_INV_DATA);
- goto leave;
- }
- rc = ksba_writer_write (writer,
- dfparm.lastblock,
- dfparm.blklen - npadding);
- if (rc)
- goto leave;
-
- for (i=dfparm.blklen - npadding; i < dfparm.blklen; i++)
- {
- if (dfparm.lastblock[i] != npadding)
- {
- log_error ("inconsistent padding\n");
- rc = gpg_error (GPG_ERR_INV_DATA);
- goto leave;
- }
- }
- }
- }
-
- }
- while (stopreason != KSBA_SR_READY);
-
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- gpgsm_status (ctrl, STATUS_DECRYPTION_OKAY, NULL);
-
-
- leave:
- if (rc)
- {
- gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL);
- log_error ("message decryption failed: %s <%s>\n",
- gpg_strerror (rc), gpg_strsource (rc));
- }
- ksba_cms_release (cms);
- gpgsm_destroy_reader (b64reader);
- gpgsm_destroy_writer (b64writer);
- keydb_release (kh);
- if (in_fp)
- fclose (in_fp);
- if (dfparm.hd)
- gcry_cipher_close (dfparm.hd);
- return rc;
-}
-
-
diff --git a/sm/delete.c b/sm/delete.c
deleted file mode 100644
index 11a0a5476..000000000
--- a/sm/delete.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* delete.c
- * Copyright (C) 2002 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-
-/* Delete a certificate or an secret key from a key database. */
-static int
-delete_one (CTRL ctrl, const char *username)
-{
- int rc = 0;
- KEYDB_SEARCH_DESC desc;
- KEYDB_HANDLE kh = NULL;
- ksba_cert_t cert = NULL;
- int duplicates = 0;
-
- rc = keydb_classify_name (username, &desc);
- if (rc)
- {
- log_error (_("certificate `%s' not found: %s\n"),
- username, gpg_strerror (rc));
- gpgsm_status2 (ctrl, STATUS_DELETE_PROBLEM, "1", NULL);
- goto leave;
- }
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error ("keydb_new failed\n");
- goto leave;
- }
-
-
- rc = keydb_search (kh, &desc, 1);
- if (!rc)
- rc = keydb_get_cert (kh, &cert);
- if (!rc)
- {
- char fpr[20];
-
- gpgsm_get_fingerprint (cert, 0, fpr, NULL);
-
- next_ambigious:
- rc = keydb_search (kh, &desc, 1);
- if (rc == -1)
- rc = 0;
- else if (!rc)
- {
- ksba_cert_t cert2 = NULL;
- char fpr2[20];
-
- /* We ignore all duplicated certificates which might have
- been inserted due to program bugs. */
- if (!keydb_get_cert (kh, &cert2))
- {
- gpgsm_get_fingerprint (cert2, 0, fpr2, NULL);
- ksba_cert_release (cert2);
- if (!memcmp (fpr, fpr2, 20))
- {
- duplicates++;
- goto next_ambigious;
- }
- }
- rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
- }
- }
- if (rc)
- {
- if (rc == -1)
- rc = gpg_error (GPG_ERR_NO_PUBKEY);
- log_error (_("certificate `%s' not found: %s\n"),
- username, gpg_strerror (rc));
- gpgsm_status2 (ctrl, STATUS_DELETE_PROBLEM, "3", NULL);
- goto leave;
- }
-
- /* We need to search again to get back to the right position. */
- rc = keydb_lock (kh);
- if (rc)
- {
- log_error (_("error locking keybox: %s\n"), gpg_strerror (rc));
- goto leave;
- }
-
- do
- {
- keydb_search_reset (kh);
- rc = keydb_search (kh, &desc, 1);
- if (rc)
- {
- log_error ("problem re-searching certificate: %s\n",
- gpg_strerror (rc));
- goto leave;
- }
-
- rc = keydb_delete (kh);
- if (rc)
- goto leave;
- if (opt.verbose)
- {
- if (duplicates)
- log_info (_("duplicated certificate `%s' deleted\n"), username);
- else
- log_info (_("certificate `%s' deleted\n"), username);
- }
- }
- while (duplicates--);
-
- leave:
- keydb_release (kh);
- ksba_cert_release (cert);
- return rc;
-}
-
-
-
-/* Delete the certificates specified by NAMES. */
-int
-gpgsm_delete (CTRL ctrl, STRLIST names)
-{
- int rc;
-
- if (!names)
- {
- log_error ("nothing to delete\n");
- return gpg_error (GPG_ERR_NO_DATA);
- }
-
- for (; names; names=names->next )
- {
- rc = delete_one (ctrl, names->d);
- if (rc)
- {
- log_error (_("deleting certificate \"%s\" failed: %s\n"),
- names->d, gpg_strerror (rc) );
- return rc;
- }
- }
-
- return 0;
-}
diff --git a/sm/encrypt.c b/sm/encrypt.c
deleted file mode 100644
index 50da92c32..000000000
--- a/sm/encrypt.c
+++ /dev/null
@@ -1,511 +0,0 @@
-/* encrypt.c - Encrypt a message
- * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-
-struct dek_s {
- const char *algoid;
- int algo;
- gcry_cipher_hd_t chd;
- char key[32];
- int keylen;
- char iv[32];
- int ivlen;
-};
-typedef struct dek_s *DEK;
-
-struct encrypt_cb_parm_s {
- FILE *fp;
- DEK dek;
- int eof_seen;
- int ready;
- int readerror;
- int bufsize;
- unsigned char *buffer;
- int buflen;
-};
-
-
-
-
-
-/* Initialize the data encryption key (session key). */
-static int
-init_dek (DEK dek)
-{
- int rc=0, mode, i;
-
- dek->algo = gcry_cipher_map_name (dek->algoid);
- mode = gcry_cipher_mode_from_oid (dek->algoid);
- if (!dek->algo || !mode)
- {
- log_error ("unsupported algorithm `%s'\n", dek->algoid);
- return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
- }
-
- /* Extra check for algorithms we considere to be to weak for
- encryption, qlthough we suppor them fro decryption. Note that
- there is another check below discriminating on the key length. */
- switch (dek->algo)
- {
- case GCRY_CIPHER_DES:
- case GCRY_CIPHER_RFC2268_40:
- log_error ("cipher algorithm `%s' not allowed: too weak\n",
- gcry_cipher_algo_name (dek->algo));
- return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
- default:
- break;
- }
-
- dek->keylen = gcry_cipher_get_algo_keylen (dek->algo);
- if (!dek->keylen || dek->keylen > sizeof (dek->key))
- return gpg_error (GPG_ERR_BUG);
-
- dek->ivlen = gcry_cipher_get_algo_blklen (dek->algo);
- if (!dek->ivlen || dek->ivlen > sizeof (dek->iv))
- return gpg_error (GPG_ERR_BUG);
-
- /* Make sure we don't use weak keys. */
- if (dek->keylen < 100/8)
- {
- log_error ("key length of `%s' too small\n", dek->algoid);
- return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
- }
-
- rc = gcry_cipher_open (&dek->chd, dek->algo, mode, GCRY_CIPHER_SECURE);
- if (rc)
- {
- log_error ("failed to create cipher context: %s\n", gpg_strerror (rc));
- return rc;
- }
-
- for (i=0; i < 8; i++)
- {
- gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM );
- rc = gcry_cipher_setkey (dek->chd, dek->key, dek->keylen);
- if (gpg_err_code (rc) != GPG_ERR_WEAK_KEY)
- break;
- log_info(_("weak key created - retrying\n") );
- }
- if (rc)
- {
- log_error ("failed to set the key: %s\n", gpg_strerror (rc));
- gcry_cipher_close (dek->chd);
- dek->chd = NULL;
- return rc;
- }
-
- gcry_create_nonce (dek->iv, dek->ivlen);
- rc = gcry_cipher_setiv (dek->chd, dek->iv, dek->ivlen);
- if (rc)
- {
- log_error ("failed to set the IV: %s\n", gpg_strerror (rc));
- gcry_cipher_close (dek->chd);
- dek->chd = NULL;
- return rc;
- }
-
- return 0;
-}
-
-
-static int
-encode_session_key (DEK dek, gcry_sexp_t * r_data)
-{
- gcry_sexp_t data;
- char * p, tmp[3];
- int i;
- int rc;
-
- p = xmalloc (64 + 2 * dek->keylen);
- strcpy (p, "(data\n (flags pkcs1)\n (value #");
- for (i=0; i < dek->keylen; i++)
- {
- sprintf (tmp, "%02x", (unsigned char) dek->key[i]);
- strcat (p, tmp);
- }
- strcat (p, "#))\n");
- rc = gcry_sexp_sscan (&data, NULL, p, strlen (p));
- xfree (p);
- *r_data = data;
- return rc;
-}
-
-
-/* encrypt the DEK under the key contained in CERT and return it as a
- canonical S-Exp in encval */
-static int
-encrypt_dek (const DEK dek, ksba_cert_t cert, char **encval)
-{
- gcry_sexp_t s_ciph, s_data, s_pkey;
- int rc;
- ksba_sexp_t buf;
- size_t len;
-
- *encval = NULL;
-
- /* get the key from the cert */
- buf = ksba_cert_get_public_key (cert);
- if (!buf)
- {
- log_error ("no public key for recipient\n");
- return gpg_error (GPG_ERR_NO_PUBKEY);
- }
- len = gcry_sexp_canon_len (buf, 0, NULL, NULL);
- if (!len)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- return gpg_error (GPG_ERR_BUG);
- }
- rc = gcry_sexp_sscan (&s_pkey, NULL, buf, len);
- xfree (buf); buf = NULL;
- if (rc)
- {
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- return rc;
- }
-
- /* put the encoded cleartext into a simple list */
- rc = encode_session_key (dek, &s_data);
- if (rc)
- {
- log_error ("encode_session_key failed: %s\n", gpg_strerror (rc));
- return rc;
- }
-
- /* pass it to libgcrypt */
- rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
- gcry_sexp_release (s_data);
- gcry_sexp_release (s_pkey);
-
- /* reformat it */
- len = gcry_sexp_sprint (s_ciph, GCRYSEXP_FMT_CANON, NULL, 0);
- assert (len);
- buf = xtrymalloc (len);
- if (!buf)
- {
- gpg_error_t tmperr = OUT_OF_CORE (errno);
- gcry_sexp_release (s_ciph);
- return tmperr;
- }
- len = gcry_sexp_sprint (s_ciph, GCRYSEXP_FMT_CANON, buf, len);
- assert (len);
-
- *encval = buf;
- return 0;
-}
-
-
-
-/* do the actual encryption */
-static int
-encrypt_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
-{
- struct encrypt_cb_parm_s *parm = cb_value;
- int blklen = parm->dek->ivlen;
- unsigned char *p;
- size_t n;
-
- *nread = 0;
- if (!buffer)
- return -1; /* not supported */
-
- if (parm->ready)
- return -1;
-
- if (count < blklen)
- BUG ();
-
- if (!parm->eof_seen)
- { /* fillup the buffer */
- p = parm->buffer;
- for (n=parm->buflen; n < parm->bufsize; n++)
- {
- int c = getc (parm->fp);
- if (c == EOF)
- {
- if (ferror (parm->fp))
- {
- parm->readerror = errno;
- return -1;
- }
- parm->eof_seen = 1;
- break;
- }
- p[n] = c;
- }
- parm->buflen = n;
- }
-
- n = parm->buflen < count? parm->buflen : count;
- n = n/blklen * blklen;
- if (n)
- { /* encrypt the stuff */
- gcry_cipher_encrypt (parm->dek->chd, buffer, n, parm->buffer, n);
- *nread = n;
- /* Who cares about cycles, take the easy way and shift the buffer */
- parm->buflen -= n;
- memmove (parm->buffer, parm->buffer+n, parm->buflen);
- }
- else if (parm->eof_seen)
- { /* no complete block but eof: add padding */
- /* fixme: we should try to do this also in the above code path */
- int i, npad = blklen - (parm->buflen % blklen);
- p = parm->buffer;
- for (n=parm->buflen, i=0; n < parm->bufsize && i < npad; n++, i++)
- p[n] = npad;
- gcry_cipher_encrypt (parm->dek->chd, buffer, n, parm->buffer, n);
- *nread = n;
- parm->ready = 1;
- }
-
- return 0;
-}
-
-
-
-
-/* Perform an encrypt operation.
-
- Encrypt the data received on DATA-FD and write it to OUT_FP. The
- recipients are take from the certificate given in recplist; if this
- is NULL it will be encrypted for a default recipient */
-int
-gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp)
-{
- int rc = 0;
- Base64Context b64writer = NULL;
- gpg_error_t err;
- ksba_writer_t writer;
- ksba_reader_t reader = NULL;
- ksba_cms_t cms = NULL;
- ksba_stop_reason_t stopreason;
- KEYDB_HANDLE kh = NULL;
- struct encrypt_cb_parm_s encparm;
- DEK dek = NULL;
- int recpno;
- FILE *data_fp = NULL;
- CERTLIST cl;
-
- memset (&encparm, 0, sizeof encparm);
-
- /* Check that the certificate list is not empty and that at least
- one certificate is not flagged as encrypt_to; i.e. is a real
- recipient. */
- for (cl = recplist; cl; cl = cl->next)
- if (!cl->is_encrypt_to)
- break;
- if (!cl)
- {
- log_error(_("no valid recipients given\n"));
- gpgsm_status (ctrl, STATUS_NO_RECP, "0");
- rc = gpg_error (GPG_ERR_NO_PUBKEY);
- goto leave;
- }
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- data_fp = fdopen ( dup (data_fd), "rb");
- if (!data_fp)
- {
- rc = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("fdopen() failed: %s\n", strerror (errno));
- goto leave;
- }
-
- err = ksba_reader_new (&reader);
- if (err)
- rc = err;
- if (!rc)
- rc = ksba_reader_set_cb (reader, encrypt_cb, &encparm);
- if (rc)
- goto leave;
-
- encparm.fp = data_fp;
-
- ctrl->pem_name = "ENCRYPTED MESSAGE";
- rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
- if (rc)
- {
- log_error ("can't create writer: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- err = ksba_cms_new (&cms);
- if (err)
- {
- rc = err;
- goto leave;
- }
-
- err = ksba_cms_set_reader_writer (cms, reader, writer);
- if (err)
- {
- log_debug ("ksba_cms_set_reader_writer failed: %s\n",
- gpg_strerror (err));
- rc = err;
- goto leave;
- }
-
- /* We are going to create enveloped data with uninterpreted data as
- inner content */
- err = ksba_cms_set_content_type (cms, 0, KSBA_CT_ENVELOPED_DATA);
- if (!err)
- err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA);
- if (err)
- {
- log_debug ("ksba_cms_set_content_type failed: %s\n",
- gpg_strerror (err));
- rc = err;
- goto leave;
- }
-
- /* Create a session key */
- dek = xtrycalloc_secure (1, sizeof *dek);
- if (!dek)
- rc = OUT_OF_CORE (errno);
- else
- {
- dek->algoid = opt.def_cipher_algoid;
- rc = init_dek (dek);
- }
- if (rc)
- {
- log_error ("failed to create the session key: %s\n",
- gpg_strerror (rc));
- goto leave;
- }
-
- err = ksba_cms_set_content_enc_algo (cms, dek->algoid, dek->iv, dek->ivlen);
- if (err)
- {
- log_error ("ksba_cms_set_content_enc_algo failed: %s\n",
- gpg_strerror (err));
- rc = err;
- goto leave;
- }
-
- encparm.dek = dek;
- /* Use a ~8k (AES) or ~4k (3DES) buffer */
- encparm.bufsize = 500 * dek->ivlen;
- encparm.buffer = xtrymalloc (encparm.bufsize);
- if (!encparm.buffer)
- {
- rc = OUT_OF_CORE (errno);
- goto leave;
- }
-
- /* Gather certificates of recipients, encrypt the session key for
- each and store them in the CMS object */
- for (recpno = 0, cl = recplist; cl; recpno++, cl = cl->next)
- {
- char *encval;
-
- rc = encrypt_dek (dek, cl->cert, &encval);
- if (rc)
- {
- log_error ("encryption failed for recipient no. %d: %s\n",
- recpno, gpg_strerror (rc));
- goto leave;
- }
-
- err = ksba_cms_add_recipient (cms, cl->cert);
- if (err)
- {
- log_error ("ksba_cms_add_recipient failed: %s\n",
- gpg_strerror (err));
- rc = err;
- xfree (encval);
- goto leave;
- }
-
- err = ksba_cms_set_enc_val (cms, recpno, encval);
- xfree (encval);
- if (err)
- {
- log_error ("ksba_cms_set_enc_val failed: %s\n",
- gpg_strerror (err));
- rc = err;
- goto leave;
- }
- }
-
- /* Main control loop for encryption. */
- recpno = 0;
- do
- {
- err = ksba_cms_build (cms, &stopreason);
- if (err)
- {
- log_debug ("ksba_cms_build failed: %s\n", gpg_strerror (err));
- rc = err;
- goto leave;
- }
- }
- while (stopreason != KSBA_SR_READY);
-
- if (encparm.readerror)
- {
- log_error ("error reading input: %s\n", strerror (encparm.readerror));
- rc = gpg_error (gpg_err_code_from_errno (encparm.readerror));
- goto leave;
- }
-
-
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- log_info ("encrypted data created\n");
-
- leave:
- ksba_cms_release (cms);
- gpgsm_destroy_writer (b64writer);
- ksba_reader_release (reader);
- keydb_release (kh);
- xfree (dek);
- if (data_fp)
- fclose (data_fp);
- xfree (encparm.buffer);
- return rc;
-}
diff --git a/sm/export.c b/sm/export.c
deleted file mode 100644
index 3f7457502..000000000
--- a/sm/export.c
+++ /dev/null
@@ -1,736 +0,0 @@
-/* export.c
- * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-#ifdef _POSIX_OPEN_MAX
-#define MAX_OPEN_FDS _POSIX_OPEN_MAX
-#else
-#define MAX_OPEN_FDS 20
-#endif
-
-
-/* A table to store a fingerprint as used in a duplicates table. We
- don't need to hash here because a fingerprint is alrady a perfect
- hash value. This we use the most significant bits to index the
- table and then use a linked list for the overflow. Possible
- enhancement for very large number of certictates: Add a second
- level table and then resort to a linked list. */
-struct duptable_s
-{
- struct duptable_s *next;
-
- /* Note that we only need to store 19 bytes because the first byte
- is implictly given by the table index (we require at least 8
- bits). */
- unsigned char fpr[19];
-};
-typedef struct duptable_s *duptable_t;
-#define DUPTABLE_BITS 12
-#define DUPTABLE_SIZE (1 << DUPTABLE_BITS)
-
-
-static void print_short_info (ksba_cert_t cert, FILE *fp);
-static gpg_error_t export_p12 (const unsigned char *certimg, size_t certimglen,
- const char *prompt, const char *keygrip,
- FILE **retfp);
-
-
-/* Create a table used to indetify duplicated certificates. */
-static duptable_t *
-create_duptable (void)
-{
- return xtrycalloc (DUPTABLE_SIZE, sizeof (duptable_t));
-}
-
-static void
-destroy_duptable (duptable_t *table)
-{
- int idx;
- duptable_t t, t2;
-
- if (table)
- {
- for (idx=0; idx < DUPTABLE_SIZE; idx++)
- for (t = table[idx]; t; t = t2)
- {
- t2 = t->next;
- xfree (t);
- }
- xfree (table);
- }
-}
-
-/* Insert the 20 byte fingerprint FPR into TABLE. Sets EXITS to true
- if the fingerprint already exists in the table. */
-static gpg_error_t
-insert_duptable (duptable_t *table, unsigned char *fpr, int *exists)
-{
- size_t idx;
- duptable_t t;
-
- *exists = 0;
- idx = fpr[0];
-#if DUPTABLE_BITS > 16 || DUPTABLE_BITS < 8
-#error cannot handle a table larger than 16 bits or smaller than 8 bits
-#elif DUPTABLE_BITS > 8
- idx <<= (DUPTABLE_BITS - 8);
- idx |= (fpr[1] & ~(~0 << 4));
-#endif
-
- for (t = table[idx]; t; t = t->next)
- if (!memcmp (t->fpr, fpr+1, 19))
- break;
- if (t)
- {
- *exists = 1;
- return 0;
- }
- /* Insert that fingerprint. */
- t = xtrymalloc (sizeof *t);
- if (!t)
- return gpg_error_from_errno (errno);
- memcpy (t->fpr, fpr+1, 19);
- t->next = table[idx];
- table[idx] = t;
- return 0;
-}
-
-
-
-
-/* Export all certificates or just those given in NAMES. */
-void
-gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp)
-{
- KEYDB_HANDLE hd = NULL;
- KEYDB_SEARCH_DESC *desc = NULL;
- int ndesc;
- Base64Context b64writer = NULL;
- ksba_writer_t writer;
- STRLIST sl;
- ksba_cert_t cert = NULL;
- int rc=0;
- int count = 0;
- int i;
- duptable_t *dtable;
-
-
- dtable = create_duptable ();
- if (!dtable)
- {
- log_error ("creating duplicates table failed: %s\n", strerror (errno));
- goto leave;
- }
-
- hd = keydb_new (0);
- if (!hd)
- {
- log_error ("keydb_new failed\n");
- goto leave;
- }
-
- if (!names)
- ndesc = 1;
- else
- {
- for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
- ;
- }
-
- desc = xtrycalloc (ndesc, sizeof *desc);
- if (!ndesc)
- {
- log_error ("allocating memory for export failed: %s\n",
- gpg_strerror (OUT_OF_CORE (errno)));
- goto leave;
- }
-
- if (!names)
- desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
- else
- {
- for (ndesc=0, sl=names; sl; sl = sl->next)
- {
- rc = keydb_classify_name (sl->d, desc+ndesc);
- if (rc)
- {
- log_error ("key `%s' not found: %s\n",
- sl->d, gpg_strerror (rc));
- rc = 0;
- }
- else
- ndesc++;
- }
- }
-
- /* If all specifications are done by fingerprint, we switch to
- ephemeral mode so that _all_ currently available and matching
- certificates are exported.
-
- fixme: we should in this case keep a list of certificates to
- avoid accidential export of duplicate certificates. */
- if (names && ndesc)
- {
- for (i=0; (i < ndesc
- && (desc[i].mode == KEYDB_SEARCH_MODE_FPR
- || desc[i].mode == KEYDB_SEARCH_MODE_FPR20
- || desc[i].mode == KEYDB_SEARCH_MODE_FPR16)); i++)
- ;
- if (i == ndesc)
- keydb_set_ephemeral (hd, 1);
- }
-
- while (!(rc = keydb_search (hd, desc, ndesc)))
- {
- unsigned char fpr[20];
- int exists;
-
- if (!names)
- desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
-
- rc = keydb_get_cert (hd, &cert);
- if (rc)
- {
- log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- gpgsm_get_fingerprint (cert, 0, fpr, NULL);
- rc = insert_duptable (dtable, fpr, &exists);
- if (rc)
- {
- log_error ("inserting into duplicates table fauiled: %s\n",
- gpg_strerror (rc));
- goto leave;
- }
-
- if (!exists && count && !ctrl->create_pem)
- {
- log_info ("exporting more than one certificate "
- "is not possible in binary mode\n");
- log_info ("ignoring other certificates\n");
- break;
- }
-
- if (!exists)
- {
- const unsigned char *image;
- size_t imagelen;
-
- image = ksba_cert_get_image (cert, &imagelen);
- if (!image)
- {
- log_error ("ksba_cert_get_image failed\n");
- goto leave;
- }
-
-
- if (ctrl->create_pem)
- {
- if (count)
- putc ('\n', fp);
- print_short_info (cert, fp);
- putc ('\n', fp);
- }
- count++;
-
- if (!b64writer)
- {
- ctrl->pem_name = "CERTIFICATE";
- rc = gpgsm_create_writer (&b64writer, ctrl, fp, &writer);
- if (rc)
- {
- log_error ("can't create writer: %s\n", gpg_strerror (rc));
- goto leave;
- }
- }
-
- rc = ksba_writer_write (writer, image, imagelen);
- if (rc)
- {
- log_error ("write error: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- if (ctrl->create_pem)
- {
- /* We want one certificate per PEM block */
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- gpgsm_destroy_writer (b64writer);
- b64writer = NULL;
- }
- }
-
- ksba_cert_release (cert);
- cert = NULL;
- }
- if (rc && rc != -1)
- log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
- else if (b64writer)
- {
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- }
-
- leave:
- gpgsm_destroy_writer (b64writer);
- ksba_cert_release (cert);
- xfree (desc);
- keydb_release (hd);
- destroy_duptable (dtable);
-}
-
-
-/* Export a certificates and its private key. */
-void
-gpgsm_p12_export (ctrl_t ctrl, const char *name, FILE *fp)
-{
- KEYDB_HANDLE hd;
- KEYDB_SEARCH_DESC *desc = NULL;
- Base64Context b64writer = NULL;
- ksba_writer_t writer;
- ksba_cert_t cert = NULL;
- int rc=0;
- const unsigned char *image;
- size_t imagelen;
- char *keygrip = NULL;
- char *prompt;
- char buffer[1024];
- int nread;
- FILE *datafp = NULL;
-
-
- hd = keydb_new (0);
- if (!hd)
- {
- log_error ("keydb_new failed\n");
- goto leave;
- }
-
- desc = xtrycalloc (1, sizeof *desc);
- if (!desc)
- {
- log_error ("allocating memory for export failed: %s\n",
- gpg_strerror (OUT_OF_CORE (errno)));
- goto leave;
- }
-
- rc = keydb_classify_name (name, desc);
- if (rc)
- {
- log_error ("key `%s' not found: %s\n",
- name, gpg_strerror (rc));
- goto leave;
- }
-
- /* Lookup the certificate an make sure that it is unique. */
- rc = keydb_search (hd, desc, 1);
- if (!rc)
- {
- rc = keydb_get_cert (hd, &cert);
- if (rc)
- {
- log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- rc = keydb_search (hd, desc, 1);
- if (!rc)
- rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
- else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
- rc = 0;
- if (rc)
- {
- log_error ("key `%s' not found: %s\n",
- name, gpg_strerror (rc));
- goto leave;
- }
- }
-
- keygrip = gpgsm_get_keygrip_hexstring (cert);
- if (!keygrip || gpgsm_agent_havekey (ctrl, keygrip))
- {
- /* Note, that the !keygrip case indicates a bad certificate. */
- rc = gpg_error (GPG_ERR_NO_SECKEY);
- log_error ("can't export key `%s': %s\n", name, gpg_strerror (rc));
- goto leave;
- }
-
- image = ksba_cert_get_image (cert, &imagelen);
- if (!image)
- {
- log_error ("ksba_cert_get_image failed\n");
- goto leave;
- }
-
- if (ctrl->create_pem)
- {
- print_short_info (cert, fp);
- putc ('\n', fp);
- }
-
- ctrl->pem_name = "PKCS12";
- rc = gpgsm_create_writer (&b64writer, ctrl, fp, &writer);
- if (rc)
- {
- log_error ("can't create writer: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
-
- prompt = gpgsm_format_keydesc (cert);
- rc = export_p12 (image, imagelen, prompt, keygrip, &datafp);
- xfree (prompt);
- if (rc)
- goto leave;
- rewind (datafp);
- while ( (nread = fread (buffer, 1, sizeof buffer, datafp)) > 0 )
- if ((rc = ksba_writer_write (writer, buffer, nread)))
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- if (ferror (datafp))
- {
- rc = gpg_error_from_errno (rc);
- log_error ("error reading temporary file: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- if (ctrl->create_pem)
- {
- /* We want one certificate per PEM block */
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- gpgsm_destroy_writer (b64writer);
- b64writer = NULL;
- }
-
- ksba_cert_release (cert);
- cert = NULL;
-
- leave:
- if (datafp)
- fclose (datafp);
- gpgsm_destroy_writer (b64writer);
- ksba_cert_release (cert);
- xfree (desc);
- keydb_release (hd);
-}
-
-
-/* Print some info about the certifciate CERT to FP */
-static void
-print_short_info (ksba_cert_t cert, FILE *fp)
-{
- char *p;
- ksba_sexp_t sexp;
- int idx;
-
- for (idx=0; (p = ksba_cert_get_issuer (cert, idx)); idx++)
- {
- fputs (!idx? "Issuer ...: "
- : "\n aka ...: ", fp);
- gpgsm_print_name (fp, p);
- xfree (p);
- }
- putc ('\n', fp);
-
- fputs ("Serial ...: ", fp);
- sexp = ksba_cert_get_serial (cert);
- if (sexp)
- {
- int len;
- const unsigned char *s = sexp;
-
- if (*s == '(')
- {
- s++;
- for (len=0; *s && *s != ':' && digitp (s); s++)
- len = len*10 + atoi_1 (s);
- if (*s == ':')
- for (s++; len; len--, s++)
- fprintf (fp, "%02X", *s);
- }
- xfree (sexp);
- }
- putc ('\n', fp);
-
- for (idx=0; (p = ksba_cert_get_subject (cert, idx)); idx++)
- {
- fputs (!idx? "Subject ..: "
- : "\n aka ..: ", fp);
- gpgsm_print_name (fp, p);
- xfree (p);
- }
- putc ('\n', fp);
-}
-
-
-static gpg_error_t
-popen_protect_tool (const char *pgmname,
- FILE *infile, FILE *outfile, FILE **statusfile,
- const char *prompt, const char *keygrip,
- pid_t *pid)
-{
- gpg_error_t err;
- int fd, fdout, rp[2];
- int n, i;
-
- fflush (infile);
- rewind (infile);
- fd = fileno (infile);
- fdout = fileno (outfile);
- if (fd == -1 || fdout == -1)
- log_fatal ("no file descriptor for temporary file: %s\n",
- strerror (errno));
-
- /* Now start the protect-tool. */
- if (pipe (rp) == -1)
- {
- err = gpg_error_from_errno (errno);
- log_error (_("error creating a pipe: %s\n"), strerror (errno));
- return err;
- }
-
- *pid = fork ();
- if (*pid == -1)
- {
- err = gpg_error_from_errno (errno);
- log_error (_("error forking process: %s\n"), strerror (errno));
- close (rp[0]);
- close (rp[1]);
- return err;
- }
-
- if (!*pid)
- { /* Child. */
- const char *arg0;
-
- arg0 = strrchr (pgmname, '/');
- if (arg0)
- arg0++;
- else
- arg0 = pgmname;
-
- /* Connect the infile to stdin. */
- if (fd != 0 && dup2 (fd, 0) == -1)
- log_fatal ("dup2 stdin failed: %s\n", strerror (errno));
-
- /* Connect the outfile to stdout. */
- if (fdout != 1 && dup2 (fdout, 1) == -1)
- log_fatal ("dup2 stdout failed: %s\n", strerror (errno));
-
- /* Connect stderr to our pipe. */
- if (rp[1] != 2 && dup2 (rp[1], 2) == -1)
- log_fatal ("dup2 stderr failed: %s\n", strerror (errno));
-
- /* Close all other files. */
- n = sysconf (_SC_OPEN_MAX);
- if (n < 0)
- n = MAX_OPEN_FDS;
- for (i=3; i < n; i++)
- close(i);
- errno = 0;
-
- setup_pinentry_env ();
-
- execlp (pgmname, arg0,
- "--homedir", opt.homedir,
- "--p12-export",
- "--prompt", prompt?prompt:"",
- "--",
- keygrip,
- NULL);
- /* No way to print anything, as we have closed all streams. */
- _exit (31);
- }
-
- /* Parent. */
- close (rp[1]);
- *statusfile = fdopen (rp[0], "r");
- if (!*statusfile)
- {
- err = gpg_error_from_errno (errno);
- log_error ("can't fdopen pipe for reading: %s", strerror (errno));
- kill (*pid, SIGTERM);
- return err;
- }
-
- return 0;
-}
-
-
-static gpg_error_t
-export_p12 (const unsigned char *certimg, size_t certimglen,
- const char *prompt, const char *keygrip,
- FILE **retfp)
-{
- const char *pgmname;
- gpg_error_t err = 0, child_err = 0;
- int i, c, cont_line;
- unsigned int pos;
- FILE *infp = NULL, *outfp = NULL, *fp = NULL;
- char buffer[1024];
- pid_t pid = -1;
-
- if (!opt.protect_tool_program || !*opt.protect_tool_program)
- pgmname = GNUPG_DEFAULT_PROTECT_TOOL;
- else
- pgmname = opt.protect_tool_program;
-
- infp = tmpfile ();
- if (!infp)
- {
- err = gpg_error_from_errno (errno);
- log_error (_("error creating temporary file: %s\n"), strerror (errno));
- goto cleanup;
- }
-
- if (fwrite (certimg, certimglen, 1, infp) != 1)
- {
- err = gpg_error_from_errno (errno);
- log_error (_("error writing to temporary file: %s\n"),
- strerror (errno));
- goto cleanup;
- }
-
- outfp = tmpfile ();
- if (!outfp)
- {
- err = gpg_error_from_errno (errno);
- log_error (_("error creating temporary file: %s\n"), strerror (errno));
- goto cleanup;
- }
-
- err = popen_protect_tool (pgmname, infp, outfp, &fp, prompt, keygrip, &pid);
- if (err)
- {
- pid = -1;
- goto cleanup;
- }
- fclose (infp);
- infp = NULL;
-
- /* Read stderr of the protect tool. */
- pos = 0;
- cont_line = 0;
- while ((c=getc (fp)) != EOF)
- {
- /* fixme: We could here grep for status information of the
- protect tool to figure out better error codes for
- CHILD_ERR. */
- buffer[pos++] = c;
- if (pos >= sizeof buffer - 5 || c == '\n')
- {
- buffer[pos - (c == '\n')] = 0;
- if (cont_line)
- log_printf ("%s", buffer);
- else
- log_info ("%s", buffer);
- pos = 0;
- cont_line = (c != '\n');
- }
- }
-
- if (pos)
- {
- buffer[pos] = 0;
- if (cont_line)
- log_printf ("%s\n", buffer);
- else
- log_info ("%s\n", buffer);
- }
- else if (cont_line)
- log_printf ("\n");
-
- /* If we found no error in the output of the child, setup a suitable
- error code, which will later be reset if the exit status of the
- child is 0. */
- if (!child_err)
- child_err = gpg_error (GPG_ERR_DECRYPT_FAILED);
-
- cleanup:
- if (infp)
- fclose (infp);
- if (fp)
- fclose (fp);
- if (pid != -1)
- {
- int status;
-
- while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
- ;
- if (i == -1)
- log_error (_("waiting for protect-tools to terminate failed: %s\n"),
- strerror (errno));
- else if (WIFEXITED (status) && WEXITSTATUS (status) == 31)
- log_error (_("error running `%s': probably not installed\n"), pgmname);
- else if (WIFEXITED (status) && WEXITSTATUS (status))
- log_error (_("error running `%s': exit status %d\n"), pgmname,
- WEXITSTATUS (status));
- else if (!WIFEXITED (status))
- log_error (_("error running `%s': terminated\n"), pgmname);
- else
- child_err = 0;
- }
- if (!err)
- err = child_err;
- if (err)
- {
- if (outfp)
- fclose (outfp);
- }
- else
- *retfp = outfp;
- return err;
-}
-
diff --git a/sm/fingerprint.c b/sm/fingerprint.c
deleted file mode 100644
index 7fe619c18..000000000
--- a/sm/fingerprint.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/* fingerprint.c - Get the fingerprint
- * Copyright (C) 2001 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-/* Return the fingerprint of the certificate (we can't put this into
- libksba because we need libgcrypt support). The caller must
- provide an array of sufficient length or NULL so that the function
- allocates the array. If r_len is not NULL, the length of the
- digest is returned; well, this can also be done by using
- gcry_md_get_algo_dlen(). If algo is 0, a SHA-1 will be used.
-
- If there is a problem , the function does never return NULL but a
- digest of all 0xff.
- */
-char *
-gpgsm_get_fingerprint (ksba_cert_t cert, int algo, char *array, int *r_len)
-{
- gcry_md_hd_t md;
- int rc, len;
-
- if (!algo)
- algo = GCRY_MD_SHA1;
-
- len = gcry_md_get_algo_dlen (algo);
- assert (len);
- if (!array)
- array = xmalloc (len);
-
- if (r_len)
- *r_len = len;
-
- rc = gcry_md_open (&md, algo, 0);
- if (rc)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (rc));
- memset (array, 0xff, len); /* better return an invalid fpr than NULL */
- return array;
- }
-
- rc = ksba_cert_hash (cert, 0, HASH_FNC, md);
- if (rc)
- {
- log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (rc));
- gcry_md_close (md);
- memset (array, 0xff, len); /* better return an invalid fpr than NULL */
- return array;
- }
- gcry_md_final (md);
- memcpy (array, gcry_md_read(md, algo), len );
- return array;
-}
-
-
-/* Return an allocated buffer with the formatted fingerprint */
-char *
-gpgsm_get_fingerprint_string (ksba_cert_t cert, int algo)
-{
- unsigned char digest[MAX_DIGEST_LEN];
- char *buf;
- int len, i;
-
- if (!algo)
- algo = GCRY_MD_SHA1;
-
- len = gcry_md_get_algo_dlen (algo);
- assert (len <= MAX_DIGEST_LEN );
- gpgsm_get_fingerprint (cert, algo, digest, NULL);
- buf = xmalloc (len*3+1);
- *buf = 0;
- for (i=0; i < len; i++ )
- sprintf (buf+strlen(buf), i? ":%02X":"%02X", digest[i]);
- return buf;
-}
-
-/* Return an allocated buffer with the formatted fingerprint as one
- large hexnumber */
-char *
-gpgsm_get_fingerprint_hexstring (ksba_cert_t cert, int algo)
-{
- unsigned char digest[MAX_DIGEST_LEN];
- char *buf;
- int len, i;
-
- if (!algo)
- algo = GCRY_MD_SHA1;
-
- len = gcry_md_get_algo_dlen (algo);
- assert (len <= MAX_DIGEST_LEN );
- gpgsm_get_fingerprint (cert, algo, digest, NULL);
- buf = xmalloc (len*3+1);
- *buf = 0;
- for (i=0; i < len; i++ )
- sprintf (buf+strlen(buf), "%02X", digest[i]);
- return buf;
-}
-
-/* Return a certificate ID. These are the last 4 bytes of the SHA-1
- fingerprint. */
-unsigned long
-gpgsm_get_short_fingerprint (ksba_cert_t cert)
-{
- unsigned char digest[20];
-
- gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL);
- return ((digest[16]<<24)|(digest[17]<<16)|(digest[18]<< 8)|digest[19]);
-}
-
-
-/* Return the so called KEYGRIP which is the SHA-1 hash of the public
- key parameters expressed as an canoncial encoded S-Exp. array must
- be 20 bytes long. returns the array or a newly allocated one if the
- passed one was NULL */
-char *
-gpgsm_get_keygrip (ksba_cert_t cert, char *array)
-{
- gcry_sexp_t s_pkey;
- int rc;
- ksba_sexp_t p;
- size_t n;
-
- p = ksba_cert_get_public_key (cert);
- if (!p)
- return NULL; /* oops */
-
- if (DBG_X509)
- log_debug ("get_keygrip for public key\n");
- n = gcry_sexp_canon_len (p, 0, NULL, NULL);
- if (!n)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- return NULL;
- }
- rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
- xfree (p);
- if (rc)
- {
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- return NULL;
- }
- array = gcry_pk_get_keygrip (s_pkey, array);
- gcry_sexp_release (s_pkey);
- if (!array)
- {
- rc = gpg_error (GPG_ERR_GENERAL);
- log_error ("can't calculate keygrip\n");
- return NULL;
- }
- if (DBG_X509)
- log_printhex ("keygrip=", array, 20);
-
- return array;
-}
-
-/* Return an allocated buffer with the keygrip of CERT in from of an
- hexstring. NULL is returned in case of error */
-char *
-gpgsm_get_keygrip_hexstring (ksba_cert_t cert)
-{
- unsigned char grip[20];
- char *buf, *p;
- int i;
-
- gpgsm_get_keygrip (cert, grip);
- buf = p = xmalloc (20*2+1);
- for (i=0; i < 20; i++, p += 2 )
- sprintf (p, "%02X", grip[i]);
- return buf;
-}
-
-
-/* Return the PK algorithm used by CERT as well as the length in bits
- of the public key at NBITS. */
-int
-gpgsm_get_key_algo_info (ksba_cert_t cert, unsigned int *nbits)
-{
- gcry_sexp_t s_pkey;
- int rc;
- ksba_sexp_t p;
- size_t n;
- gcry_sexp_t l1, l2;
- const char *name;
- char namebuf[128];
-
- if (nbits)
- *nbits = 0;
-
- p = ksba_cert_get_public_key (cert);
- if (!p)
- return 0;
- n = gcry_sexp_canon_len (p, 0, NULL, NULL);
- if (!n)
- {
- xfree (p);
- return 0;
- }
- rc = gcry_sexp_sscan (&s_pkey, NULL, p, n);
- xfree (p);
- if (rc)
- return 0;
-
- if (nbits)
- *nbits = gcry_pk_get_nbits (s_pkey);
-
- /* Breaking the algorithm out of the S-exp is a bit of a challenge ... */
- l1 = gcry_sexp_find_token (s_pkey, "public-key", 0);
- if (!l1)
- {
- gcry_sexp_release (s_pkey);
- return 0;
- }
- l2 = gcry_sexp_cadr (l1);
- gcry_sexp_release (l1);
- l1 = l2;
- name = gcry_sexp_nth_data (l1, 0, &n);
- if (name)
- {
- if (n > sizeof namebuf -1)
- n = sizeof namebuf -1;
- memcpy (namebuf, name, n);
- namebuf[n] = 0;
- }
- else
- *namebuf = 0;
- gcry_sexp_release (l1);
- gcry_sexp_release (s_pkey);
- return gcry_pk_map_name (namebuf);
-}
-
-
-
-
-/* For certain purposes we need a certificate id which has an upper
- limit of the size. We use the hash of the issuer name and the
- serial number for this. In most cases the serial number is not
- that large and the resulting string can be passed on an assuan
- command line. Everything is hexencoded with the serialnumber
- delimited from the hash by a dot.
-
- The caller must free the string.
-*/
-char *
-gpgsm_get_certid (ksba_cert_t cert)
-{
- ksba_sexp_t serial;
- unsigned char *p;
- char *endp;
- unsigned char hash[20];
- unsigned long n;
- char *certid;
- int i;
-
- p = ksba_cert_get_issuer (cert, 0);
- if (!p)
- return NULL; /* Ooops: No issuer */
- gcry_md_hash_buffer (GCRY_MD_SHA1, hash, p, strlen (p));
- xfree (p);
-
- serial = ksba_cert_get_serial (cert);
- if (!serial)
- return NULL; /* oops: no serial number */
- p = serial;
- if (*p != '(')
- {
- log_error ("Ooops: invalid serial number\n");
- xfree (serial);
- return NULL;
- }
- p++;
- n = strtoul (p, &endp, 10);
- p = endp;
- if (*p != ':')
- {
- log_error ("Ooops: invalid serial number (no colon)\n");
- xfree (serial);
- return NULL;
- }
- p++;
-
- certid = xtrymalloc ( 40 + 1 + n*2 + 1);
- if (!certid)
- {
- xfree (serial);
- return NULL; /* out of core */
- }
-
- for (i=0, endp = certid; i < 20; i++, endp += 2 )
- sprintf (endp, "%02X", hash[i]);
- *endp++ = '.';
- for (i=0; i < n; i++, endp += 2)
- sprintf (endp, "%02X", p[i]);
- *endp = 0;
-
- xfree (serial);
- return certid;
-}
-
-
-
-
-
-
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
deleted file mode 100644
index bf053b7a5..000000000
--- a/sm/gpgsm.c
+++ /dev/null
@@ -1,1700 +0,0 @@
-/* gpgsm.c - GnuPG for S/MIME
- * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <assuan.h> /* malloc hooks */
-
-#include "../kbx/keybox.h" /* malloc hooks */
-#include "i18n.h"
-#include "keydb.h"
-#include "sysutils.h"
-
-enum cmd_and_opt_values {
- aNull = 0,
- oArmor = 'a',
- aDetachedSign = 'b',
- aSym = 'c',
- aDecrypt = 'd',
- aEncr = 'e',
- oInteractive = 'i',
- aListKeys = 'k',
- aListSecretKeys = 'K',
- oDryRun = 'n',
- oOutput = 'o',
- oQuiet = 'q',
- oRecipient = 'r',
- aSign = 's',
- oTextmodeShort= 't',
- oUser = 'u',
- oVerbose = 'v',
- oCompress = 'z',
- oNotation = 'N',
- oBatch = 500,
- aClearsign,
- aStore,
- aKeygen,
- aSignEncr,
- aSignKey,
- aLSignKey,
- aListPackets,
- aEditKey,
- aDeleteKey,
- aImport,
- aVerify,
- aVerifyFiles,
- aListExternalKeys,
- aListSigs,
- aSendKeys,
- aRecvKeys,
- aExport,
- aExportSecretKeyP12,
- aCheckKeys, /* nyi */
- aServer,
- aLearnCard,
- aCallDirmngr,
- aCallProtectTool,
- aPasswd,
- aGPGConfList,
- aDumpKeys,
- aDumpSecretKeys,
- aDumpExternalKeys,
- aKeydbClearSomeCertFlags,
-
- oOptions,
- oDebug,
- oDebugLevel,
- oDebugAll,
- oDebugWait,
- oDebugAllowCoreDump,
- oDebugNoChainValidation,
- oDebugIgnoreExpiration,
- oLogFile,
-
- oEnableSpecialFilenames,
-
- oAgentProgram,
- oDisplay,
- oTTYname,
- oTTYtype,
- oLCctype,
- oLCmessages,
-
- oDirmngrProgram,
- oProtectToolProgram,
- oFakedSystemTime,
-
-
- oAssumeArmor,
- oAssumeBase64,
- oAssumeBinary,
-
- oBase64,
- oNoArmor,
-
- oDisableCRLChecks,
- oEnableCRLChecks,
- oForceCRLRefresh,
-
- oDisableOCSP,
- oEnableOCSP,
-
- oIncludeCerts,
- oPolicyFile,
- oDisablePolicyChecks,
- oEnablePolicyChecks,
- oAutoIssuerKeyRetrieve,
-
-
- oTextmode,
- oFingerprint,
- oWithFingerprint,
- oWithMD5Fingerprint,
- oAnswerYes,
- oAnswerNo,
- oKeyring,
- oSecretKeyring,
- oDefaultKey,
- oDefRecipient,
- oDefRecipientSelf,
- oNoDefRecipient,
- oStatusFD,
- oNoComment,
- oNoVersion,
- oEmitVersion,
- oCompletesNeeded,
- oMarginalsNeeded,
- oMaxCertDepth,
- oLoadExtension,
- oRFC1991,
- oOpenPGP,
- oCipherAlgo,
- oDigestAlgo,
- oCompressAlgo,
- oCommandFD,
- oNoVerbose,
- oTrustDBName,
- oNoSecmemWarn,
- oNoDefKeyring,
- oNoGreeting,
- oNoTTY,
- oNoOptions,
- oNoBatch,
- oHomedir,
- oWithColons,
- oWithKeyData,
- oWithValidation,
- oSkipVerify,
- oCompressKeys,
- oCompressSigs,
- oAlwaysTrust,
- oRunAsShmCP,
- oSetFilename,
- oSetPolicyURL,
- oUseEmbeddedFilename,
- oComment,
- oDefaultComment,
- oThrowKeyid,
- oForceV3Sigs,
- oForceMDC,
- oS2KMode,
- oS2KDigest,
- oS2KCipher,
- oCharset,
- oNotDashEscaped,
- oEscapeFrom,
- oLockOnce,
- oLockMultiple,
- oLockNever,
- oKeyServer,
- oEncryptTo,
- oNoEncryptTo,
- oLoggerFD,
- oUtf8Strings,
- oNoUtf8Strings,
- oDisableCipherAlgo,
- oDisablePubkeyAlgo,
- oAllowNonSelfsignedUID,
- oAllowFreeformUID,
- oNoLiteral,
- oSetFilesize,
- oHonorHttpProxy,
- oFastListMode,
- oListOnly,
- oIgnoreTimeConflict,
- oNoRandomSeedFile,
- oNoAutoKeyRetrieve,
- oUseAgent,
- oMergeOnly,
- oTryAllSecrets,
- oTrustedKey,
- oEmuMDEncodeBug,
- aDummy
- };
-
-
-static ARGPARSE_OPTS opts[] = {
-
- { 300, NULL, 0, N_("@Commands:\n ") },
-
- { aSign, "sign", 256, N_("|[FILE]|make a signature")},
- { aClearsign, "clearsign", 256, N_("|[FILE]|make a clear text signature") },
- { aDetachedSign, "detach-sign", 256, N_("make a detached signature")},
- { aEncr, "encrypt", 256, N_("encrypt data")},
- { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")},
- { 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")},
- { aListExternalKeys, "list-external-keys", 256, N_("list external keys")},
- { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
- { aListSigs, "list-sigs", 256, N_("list certificate chain")},
- { aListSigs, "check-sigs",256, "@"},
- { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")},
- { aKeygen, "gen-key", 256, N_("generate a new key pair")},
- { aDeleteKey, "delete-key",256, N_("remove key from the public keyring")},
- { aSendKeys, "send-keys" , 256, N_("export keys to a key server") },
- { aRecvKeys, "recv-keys" , 256, N_("import keys from a key server") },
- { aImport, "import", 256 , N_("import certificates")},
- { aExport, "export", 256 , N_("export certificates")},
- { aLearnCard, "learn-card", 256 ,N_("register a smartcard")},
- { aServer, "server", 256, N_("run in server mode")},
- { aCallDirmngr, "call-dirmngr", 256, N_("pass a command to the dirmngr")},
- { aCallProtectTool, "call-protect-tool", 256,
- N_("invoke gpg-protect-tool")},
- { aPasswd, "passwd", 256, N_("change a passphrase")},
- { aGPGConfList, "gpgconf-list", 256, "@" },
-
- { aDumpKeys, "dump-keys", 256, "@"},
- { aDumpExternalKeys, "dump-external-keys", 256, "@"},
- { aDumpSecretKeys, "dump-secret-keys", 256, "@"},
- { aKeydbClearSomeCertFlags, "keydb-clear-some-cert-flags", 256, "@"},
-
- { 301, NULL, 0, N_("@\nOptions:\n ") },
-
- { oArmor, "armor", 0, N_("create ascii armored output")},
- { oArmor, "armour", 0, "@" },
- { oBase64, "base64", 0, N_("create base-64 encoded output")},
-
- { oAssumeArmor, "assume-armor", 0, N_("assume input is in PEM format")},
- { oAssumeBase64, "assume-base64", 0,
- N_("assume input is in base-64 format")},
- { oAssumeBinary, "assume-binary", 0,
- N_("assume input is in binary format")},
-
- { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")},
-
-
- { oDisableCRLChecks, "disable-crl-checks", 0, N_("never consult a CRL")},
- { oEnableCRLChecks, "enable-crl-checks", 0, "@"},
- { oForceCRLRefresh, "force-crl-refresh", 0, "@"},
-
- { oDisableOCSP, "disable-ocsp", 0, "@" },
- { oEnableOCSP, "enable-ocsp", 0, N_("check validity using OCSP")},
-
- { oIncludeCerts, "include-certs", 1,
- N_("|N|number of certificates to include") },
-
- { oPolicyFile, "policy-file", 2,
- N_("|FILE|take policy information from FILE") },
-
- { oDisablePolicyChecks, "disable-policy-checks", 0,
- N_("do not check certificate policies")},
- { oEnablePolicyChecks, "enable-policy-checks", 0, "@"},
-
- { oAutoIssuerKeyRetrieve, "auto-issuer-key-retrieve", 0,
- N_("fetch missing issuer certificates")},
-
-#if 0
- { oDefRecipient, "default-recipient" ,2,
- N_("|NAME|use NAME as default recipient")},
- { oDefRecipientSelf, "default-recipient-self" ,0,
- N_("use the default key as default recipient")},
- { oNoDefRecipient, "no-default-recipient", 0, "@" },
-#endif
- { oEncryptTo, "encrypt-to", 2, "@" },
- { oNoEncryptTo, "no-encrypt-to", 0, "@" },
-
- { oUser, "local-user",2, N_("use this user-id to sign or decrypt")},
-
-#if 0
- { oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") },
- { oTextmodeShort, NULL, 0, "@"},
- { oTextmode, "textmode", 0, N_("use canonical text mode")},
-#endif
-
- { oOutput, "output", 2, N_("use as output file")},
- { oVerbose, "verbose", 0, N_("verbose") },
- { oQuiet, "quiet", 0, N_("be somewhat more quiet") },
- { oNoTTY, "no-tty", 0, N_("don't use the terminal at all") },
- { oLogFile, "log-file" ,2, N_("use a log file for the server")},
-#if 0
- { oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") },
- { oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") },
-#endif
- { oDryRun, "dry-run", 0, N_("do not make any changes") },
- /*{ oInteractive, "interactive", 0, N_("prompt before overwriting") }, */
- /*{ oUseAgent, "use-agent",0, N_("use the gpg-agent")},*/
- { oBatch, "batch", 0, N_("batch mode: never ask")},
- { oAnswerYes, "yes", 0, N_("assume yes on most questions")},
- { oAnswerNo, "no", 0, N_("assume no on most questions")},
-
- { oKeyring, "keyring" ,2, N_("add this keyring to the list of keyrings")},
- { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")},
- { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")},
- { oKeyServer, "keyserver",2, N_("|HOST|use this keyserver to lookup keys")},
- { oCharset, "charset" , 2, N_("|NAME|set terminal charset to NAME") },
- { oOptions, "options" , 2, N_("read options from file")},
-
- { oDebug, "debug" ,4|16, "@"},
- { oDebugLevel, "debug-level" ,2, "@"},
- { oDebugAll, "debug-all" ,0, "@"},
- { oDebugWait, "debug-wait" ,1, "@"},
- { oDebugAllowCoreDump, "debug-allow-core-dump", 0, "@" },
- { oDebugNoChainValidation, "debug-no-chain-validation", 0, "@"},
- { oDebugIgnoreExpiration, "debug-ignore-expiration", 0, "@"},
- { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") },
- { aDummy, "no-comment", 0, "@"},
- { aDummy, "completes-needed", 1, "@"},
- { aDummy, "marginals-needed", 1, "@"},
- { oMaxCertDepth, "max-cert-depth", 1, "@" },
- { aDummy, "trusted-key", 2, "@"},
- { oLoadExtension, "load-extension" ,2,
- N_("|FILE|load extension module FILE")},
- { aDummy, "rfc1991", 0, "@"},
- { aDummy, "openpgp", 0, "@"},
- { aDummy, "s2k-mode", 1, "@"},
- { aDummy, "s2k-digest-algo",2, "@"},
- { aDummy, "s2k-cipher-algo",2, "@"},
- { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")},
- { oDigestAlgo, "digest-algo", 2 ,
- N_("|NAME|use message digest algorithm NAME")},
-#if 0
- { oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")},
-#endif
- { aDummy, "throw-keyid", 0, "@"},
- { aDummy, "notation-data", 2, "@"},
- { aExportSecretKeyP12, "export-secret-key-p12", 256, "@"},
-
-
- { 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"
- " --list-keys [names] show keys\n"
- " --fingerprint [names] show fingerprints\n" ) },
-
- /* hidden options */
- { oNoVerbose, "no-verbose", 0, "@"},
-
- { oEnableSpecialFilenames, "enable-special-filenames", 0, "@" },
-
-
- { oTrustDBName, "trustdb-name", 2, "@" },
- { oNoSecmemWarn, "no-secmem-warning", 0, "@" },
- { oNoArmor, "no-armor", 0, "@"},
- { oNoArmor, "no-armour", 0, "@"},
- { oNoDefKeyring, "no-default-keyring", 0, "@" },
- { oNoGreeting, "no-greeting", 0, "@" },
- { oNoOptions, "no-options", 0, "@" }, /* shortcut for --options /dev/null */
- { oHomedir, "homedir", 2, "@" }, /* defaults to "~/.gnupg" */
- { oAgentProgram, "agent-program", 2 , "@" },
- { oDisplay, "display", 2, "@" },
- { oTTYname, "ttyname", 2, "@" },
- { oTTYtype, "ttytype", 2, "@" },
- { oLCctype, "lc-ctype", 2, "@" },
- { oLCmessages, "lc-messages", 2, "@" },
- { oDirmngrProgram, "dirmngr-program", 2 , "@" },
- { oProtectToolProgram, "protect-tool-program", 2 , "@" },
- { oFakedSystemTime, "faked-system-time", 4, "@" }, /* (epoch time) */
-
-
- { oNoBatch, "no-batch", 0, "@" },
- { oWithColons, "with-colons", 0, "@"},
- { oWithKeyData,"with-key-data", 0, "@"},
- { oWithValidation, "with-validation", 0, "@"},
- { oWithMD5Fingerprint, "with-md5-fingerprint", 0, "@"},
- { aListKeys, "list-key", 0, "@" }, /* alias */
- { aListSigs, "list-sig", 0, "@" }, /* alias */
- { aListSigs, "check-sig",0, "@" }, /* alias */
- { oSkipVerify, "skip-verify",0, "@" },
- { oCompressKeys, "compress-keys",0, "@"},
- { oCompressSigs, "compress-sigs",0, "@"},
- { oAlwaysTrust, "always-trust", 0, "@"},
- { oNoVersion, "no-version", 0, "@"},
- { oLockOnce, "lock-once", 0, "@" },
- { oLockMultiple, "lock-multiple", 0, "@" },
- { oLockNever, "lock-never", 0, "@" },
- { oLoggerFD, "logger-fd",1, "@" },
- { oWithFingerprint, "with-fingerprint", 0, "@" },
- { oDisableCipherAlgo, "disable-cipher-algo", 2, "@" },
- { oDisablePubkeyAlgo, "disable-pubkey-algo", 2, "@" },
- { oHonorHttpProxy,"honor-http-proxy", 0, "@" },
- { oListOnly, "list-only", 0, "@"},
- { oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" },
- { oNoRandomSeedFile, "no-random-seed-file", 0, "@" },
-{0} };
-
-
-
-int gpgsm_errors_seen = 0;
-
-/* It is possible that we are currentlu running under setuid permissions */
-static int maybe_setuid = 1;
-
-/* Option --enable-special-filenames */
-static int allow_special_filenames;
-
-
-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 emergency_cleanup (void);
-static int check_special_filename (const char *fname);
-static int open_read (const char *filename);
-static FILE *open_fwrite (const char *filename);
-static void run_protect_tool (int argc, char **argv);
-
-
-static int
-our_pk_test_algo (int algo)
-{
- return 1;
-}
-
-static int
-our_cipher_test_algo (int algo)
-{
- return 1;
-}
-
-static int
-our_md_test_algo (int algo)
-{
- return 1;
-}
-
-static const char *
-my_strusage( int level )
-{
- static char *digests, *pubkeys, *ciphers;
- const char *p;
-
- switch (level)
- {
- case 11: p = "gpgsm (GnuPG)";
- break;
- case 13: p = VERSION; break;
- case 17: p = PRINTABLE_OS_NAME; break;
- case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
- break;
- case 1:
- case 40: p = _("Usage: gpgsm [options] [files] (-h for help)");
- break;
- case 41:
- p = _("Syntax: gpgsm [options] [files]\n"
- "sign, check, encrypt or decrypt using the S/MIME protocol\n"
- "default operation depends on the input data\n");
- break;
-
- 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,
- our_cipher_test_algo );
- p = ciphers;
- break;
- case 35:
- if (!pubkeys)
- pubkeys = build_list ("Pubkey: ", gcry_pk_algo_name,
- our_pk_test_algo );
- p = pubkeys;
- break;
- case 36:
- if (!digests)
- digests = build_list("Hash: ", gcry_md_algo_name, our_md_test_algo );
- p = digests;
- break;
-
- default: p = NULL; break;
- }
- return p;
-}
-
-
-static char *
-build_list (const char *text, const char * (*mapf)(int), int (*chkf)(int))
-{
- int i;
- size_t n=strlen(text)+2;
- char *list, *p;
-
- if (maybe_setuid) {
- gcry_control (GCRYCTL_DROP_PRIVS); /* drop setuid */
- }
-
- for (i=1; i < 110; i++ )
- if (!chkf(i))
- n += strlen(mapf(i)) + 2;
- list = xmalloc (21 + n);
- *list = 0;
- for (p=NULL, i=1; i < 110; i++)
- {
- if (!chkf(i))
- {
- if( !p )
- p = stpcpy (list, text );
- else
- p = stpcpy (p, ", ");
- p = stpcpy (p, mapf(i) );
- }
- }
- if (p)
- p = stpcpy(p, "\n" );
- return list;
-}
-
-
-static void
-i18n_init(void)
-{
-#ifdef USE_SIMPLE_GETTEXT
- set_gettext_file (PACKAGE_GT);
-#else
-# ifdef ENABLE_NLS
-# ifdef HAVE_LC_MESSAGES
- setlocale (LC_TIME, "");
- setlocale (LC_MESSAGES, "");
-# else
- setlocale (LC_ALL, "" );
-# endif
- bindtextdomain (PACKAGE_GT, LOCALEDIR);
- textdomain (PACKAGE_GT);
-# endif
-#endif
-}
-
-
-static void
-wrong_args (const char *text)
-{
- fputs (_("usage: gpgsm [options] "), stderr);
- fputs (text, stderr);
- putc ('\n', stderr);
- gpgsm_exit (2);
-}
-
-
-/* Setup the debugging. With a LEVEL of NULL only the active debug
- flags are propagated to the subsystems. With LEVEL set, a specific
- set of debug flags is set; thus overriding all flags already
- set. */
-static void
-set_debug (const char *level)
-{
- if (!level)
- ;
- else if (!strcmp (level, "none"))
- opt.debug = 0;
- else if (!strcmp (level, "basic"))
- opt.debug = DBG_ASSUAN_VALUE;
- else if (!strcmp (level, "advanced"))
- opt.debug = DBG_ASSUAN_VALUE|DBG_X509_VALUE;
- else if (!strcmp (level, "expert"))
- opt.debug = (DBG_ASSUAN_VALUE|DBG_X509_VALUE
- |DBG_CACHE_VALUE|DBG_CRYPTO_VALUE);
- else if (!strcmp (level, "guru"))
- opt.debug = ~0;
- else
- {
- log_error (_("invalid debug-level `%s' given\n"), level);
- gpgsm_exit(2);
- }
-
-
- if (opt.debug && !opt.verbose)
- {
- opt.verbose = 1;
- gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
- }
- if (opt.debug && opt.quiet)
- opt.quiet = 0;
-
- if (opt.debug & DBG_MPI_VALUE)
- gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2);
- if (opt.debug & DBG_CRYPTO_VALUE )
- gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
-}
-
-
-
-static void
-set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd)
-{
- enum cmd_and_opt_values cmd = *ret_cmd;
-
- if (!cmd || cmd == new_cmd)
- cmd = new_cmd;
- else if ( cmd == aSign && new_cmd == aEncr )
- cmd = aSignEncr;
- else if ( cmd == aEncr && new_cmd == aSign )
- cmd = aSignEncr;
- else if ( (cmd == aSign && new_cmd == aClearsign)
- || (cmd == aClearsign && new_cmd == aSign) )
- cmd = aClearsign;
- else
- {
- log_error(_("conflicting commands\n"));
- gpgsm_exit(2);
- }
-
- *ret_cmd = cmd;
-}
-
-
-/* Helper to add recipients to a list. */
-static void
-do_add_recipient (ctrl_t ctrl, const char *name,
- certlist_t *recplist, int is_encrypt_to)
-{
- int rc = gpgsm_add_to_certlist (ctrl, name, 0, recplist, is_encrypt_to);
- if (rc)
- {
- log_error (_("can't encrypt to `%s': %s\n"), name, gpg_strerror (rc));
- gpgsm_status2 (ctrl, STATUS_INV_RECP,
- gpg_err_code (rc) == -1? "1":
- gpg_err_code (rc) == GPG_ERR_NO_PUBKEY? "1":
- gpg_err_code (rc) == GPG_ERR_AMBIGUOUS_NAME? "2":
- gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE? "3":
- gpg_err_code (rc) == GPG_ERR_CERT_REVOKED? "4":
- gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED? "5":
- gpg_err_code (rc) == GPG_ERR_NO_CRL_KNOWN? "6":
- gpg_err_code (rc) == GPG_ERR_CRL_TOO_OLD? "7":
- gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH? "8":
- "0",
- name, NULL);
- }
-}
-
-
-int
-main ( int argc, char **argv)
-{
- ARGPARSE_ARGS pargs;
- int orig_argc;
- char **orig_argv;
- const char *fname;
- /* char *username;*/
- int may_coredump;
- STRLIST sl, remusr= NULL, locusr=NULL;
- STRLIST nrings=NULL;
- int detached_sig = 0;
- FILE *configfp = NULL;
- char *configname = NULL;
- unsigned configlineno;
- int parse_debug = 0;
- int no_more_options = 0;
- int default_config =1;
- int default_keyring = 1;
- char *logfile = NULL;
- int greeting = 0;
- int nogreeting = 0;
- int debug_wait = 0;
- const char *debug_level = NULL;
- int use_random_seed = 1;
- int with_fpr = 0;
- char *def_digest_string = NULL;
- enum cmd_and_opt_values cmd = 0;
- struct server_control_s ctrl;
- CERTLIST recplist = NULL;
- CERTLIST signerlist = NULL;
- int do_not_setup_keys = 0;
-
- /* trap_unaligned ();*/
- set_strusage (my_strusage);
- gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
- /* We don't need any locking in libgcrypt unless we use any kind of
- threading. */
- gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING);
-
- /* Please note that we may running SUID(ROOT), so be very CAREFUL
- when adding any stuff between here and the call to secmem_init()
- somewhere after the option parsing */
- log_set_prefix ("gpgsm", 1);
-
- /* Try to auto set the character set. */
- set_native_charset (NULL);
-
- /* Check that the libraries are suitable. Do it here because the
- option parse may need services of the library */
- if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
- {
- log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
- NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
- }
- if (!ksba_check_version (NEED_KSBA_VERSION) )
- {
- log_fatal( _("libksba is too old (need %s, have %s)\n"),
- NEED_KSBA_VERSION, ksba_check_version (NULL) );
- }
-
- gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
-
- may_coredump = disable_core_dumps ();
-
- gnupg_init_signals (0, emergency_cleanup);
-
- create_dotlock (NULL); /* register locking cleanup */
- i18n_init();
-
- opt.def_cipher_algoid = "1.2.840.113549.3.7"; /*des-EDE3-CBC*/
-#ifdef __MINGW32__
- opt.homedir = read_w32_registry_string ( NULL,
- "Software\\GNU\\GnuPG", "HomeDir" );
-#else
- opt.homedir = getenv ("GNUPGHOME");
-#endif
- if (!opt.homedir || !*opt.homedir )
- opt.homedir = GNUPG_DEFAULT_HOMEDIR;
-
- /* first check whether we have a config file on the commandline */
- orig_argc = argc;
- orig_argv = argv;
- pargs.argc = &argc;
- pargs.argv = &argv;
- pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */
- while (arg_parse( &pargs, opts))
- {
- if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll)
- parse_debug++;
- else if (pargs.r_opt == oOptions)
- { /* yes there is one, so we do not try the default one but
- read the config file when it is encountered at the
- commandline */
- default_config = 0;
- }
- else if (pargs.r_opt == oNoOptions)
- default_config = 0; /* --no-options */
- else if (pargs.r_opt == oHomedir)
- opt.homedir = pargs.r.ret_str;
- else if (pargs.r_opt == aCallProtectTool)
- break; /* This break makes sure that --version and --help are
- passed to the protect-tool. */
- }
-
-
- /* initialize the secure memory. */
- gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
- maybe_setuid = 0;
-
- /*
- Now we are now working under our real uid
- */
-
- ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
-
- assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
- assuan_set_assuan_log_stream (log_get_stream ());
- assuan_set_assuan_log_prefix (log_get_prefix (NULL));
-
- keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
-
- /* Setup a default control structure for command line mode */
- memset (&ctrl, 0, sizeof ctrl);
- gpgsm_init_default_ctrl (&ctrl);
- ctrl.no_server = 1;
- ctrl.status_fd = -1; /* not status output */
- ctrl.autodetect_encoding = 1;
-
- /* set the default option file */
- if (default_config )
- configname = make_filename (opt.homedir, "gpgsm.conf", NULL);
- /* cet the default policy file */
- opt.policy_file = make_filename (opt.homedir, "policies.txt", NULL);
-
- argc = orig_argc;
- argv = orig_argv;
- pargs.argc = &argc;
- pargs.argv = &argv;
- pargs.flags = 1; /* do not remove the args */
-
- next_pass:
- if (configname) {
- configlineno = 0;
- configfp = fopen (configname, "r");
- if (!configfp)
- {
- if (default_config)
- {
- if (parse_debug)
- log_info (_("NOTE: no default option file `%s'\n"), configname);
- }
- else
- {
- log_error (_("option file `%s': %s\n"), configname, strerror(errno));
- gpgsm_exit(2);
- }
- xfree(configname);
- configname = NULL;
- }
- if (parse_debug && configname)
- log_info (_("reading options from `%s'\n"), configname);
- default_config = 0;
- }
-
- while (!no_more_options
- && optfile_parse (configfp, configname, &configlineno, &pargs, opts))
- {
- switch (pargs.r_opt)
- {
- case aGPGConfList:
- set_cmd (&cmd, pargs.r_opt);
- do_not_setup_keys = 1;
- nogreeting = 1;
- break;
-
- case aServer:
- opt.batch = 1;
- set_cmd (&cmd, aServer);
- break;
-
- case aCallDirmngr:
- opt.batch = 1;
- set_cmd (&cmd, aCallDirmngr);
- do_not_setup_keys = 1;
- break;
-
- case aCallProtectTool:
- opt.batch = 1;
- set_cmd (&cmd, aCallProtectTool);
- no_more_options = 1; /* Stop parsing. */
- do_not_setup_keys = 1;
- break;
-
- case aDeleteKey:
- set_cmd (&cmd, aDeleteKey);
- /*greeting=1;*/
- do_not_setup_keys = 1;
- break;
-
- case aDetachedSign:
- detached_sig = 1;
- set_cmd (&cmd, aSign );
- break;
-
- case aKeygen:
- set_cmd (&cmd, aKeygen);
- greeting=1;
- do_not_setup_keys = 1;
- break;
-
- case aCheckKeys:
- case aImport:
- case aSendKeys:
- case aRecvKeys:
- case aExport:
- case aExportSecretKeyP12:
- case aDumpKeys:
- case aDumpExternalKeys:
- case aDumpSecretKeys:
- case aListKeys:
- case aListExternalKeys:
- case aListSecretKeys:
- case aListSigs:
- case aLearnCard:
- case aPasswd:
- case aKeydbClearSomeCertFlags:
- do_not_setup_keys = 1;
- set_cmd (&cmd, pargs.r_opt);
- break;
-
- case aSym:
- case aDecrypt:
- case aEncr:
- case aSign:
- case aClearsign:
- case aVerify:
- set_cmd (&cmd, pargs.r_opt);
- break;
-
- /* output encoding selection */
- case oArmor:
- ctrl.create_pem = 1;
- break;
- case oBase64:
- ctrl.create_pem = 0;
- ctrl.create_base64 = 1;
- break;
- case oNoArmor:
- ctrl.create_pem = 0;
- ctrl.create_base64 = 0;
- break;
-
- /* Input encoding selection */
- case oAssumeArmor:
- ctrl.autodetect_encoding = 0;
- ctrl.is_pem = 1;
- ctrl.is_base64 = 0;
- break;
- case oAssumeBase64:
- ctrl.autodetect_encoding = 0;
- ctrl.is_pem = 0;
- ctrl.is_base64 = 1;
- break;
- case oAssumeBinary:
- ctrl.autodetect_encoding = 0;
- ctrl.is_pem = 0;
- ctrl.is_base64 = 0;
- break;
-
- case oDisableCRLChecks:
- opt.no_crl_check = 1;
- break;
- case oEnableCRLChecks:
- opt.no_crl_check = 0;
- break;
- case oForceCRLRefresh:
- opt.force_crl_refresh = 1;
- break;
-
- case oDisableOCSP:
- ctrl.use_ocsp = opt.enable_ocsp = 0;
- break;
- case oEnableOCSP:
- ctrl.use_ocsp = opt.enable_ocsp = 1;
- break;
-
- case oIncludeCerts: ctrl.include_certs = pargs.r.ret_int; break;
-
- case oPolicyFile:
- xfree (opt.policy_file);
- if (*pargs.r.ret_str)
- opt.policy_file = xstrdup (pargs.r.ret_str);
- else
- opt.policy_file = NULL;
- break;
-
- case oDisablePolicyChecks:
- opt.no_policy_check = 1;
- break;
- case oEnablePolicyChecks:
- opt.no_policy_check = 0;
- break;
-
- case oAutoIssuerKeyRetrieve:
- opt.auto_issuer_key_retrieve = 1;
- break;
-
- case oOutput: opt.outfile = pargs.r.ret_str; break;
-
-
- case oQuiet: opt.quiet = 1; break;
- case oNoTTY: /* fixme:tty_no_terminal(1);*/ break;
- case oDryRun: opt.dry_run = 1; break;
-
- case oVerbose:
- opt.verbose++;
- gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
- break;
- case oNoVerbose:
- opt.verbose = 0;
- gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
- break;
-
- case oLogFile: logfile = pargs.r.ret_str; break;
-
- case oBatch:
- opt.batch = 1;
- greeting = 0;
- break;
- case oNoBatch: opt.batch = 0; break;
-
- case oAnswerYes: opt.answer_yes = 1; break;
- case oAnswerNo: opt.answer_no = 1; break;
-
- case oKeyring: append_to_strlist (&nrings, pargs.r.ret_str); break;
-
- case oDebug: opt.debug |= pargs.r.ret_ulong; break;
- case oDebugAll: opt.debug = ~0; break;
- case oDebugLevel: debug_level = pargs.r.ret_str; break;
- case oDebugWait: debug_wait = pargs.r.ret_int; break;
- case oDebugAllowCoreDump:
- may_coredump = enable_core_dumps ();
- break;
- case oDebugNoChainValidation: opt.no_chain_validation = 1; break;
- case oDebugIgnoreExpiration: opt.ignore_expiration = 1; break;
-
- case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
- case oLoggerFD: log_set_fd (pargs.r.ret_int ); break;
- case oWithMD5Fingerprint:
- opt.with_md5_fingerprint=1; /*fall thru*/
- case oWithFingerprint:
- with_fpr=1; /*fall thru*/
- case oFingerprint:
- opt.fingerprint++;
- break;
-
- case oOptions:
- /* config files may not be nested (silently ignore them) */
- if (!configfp)
- {
- xfree(configname);
- configname = xstrdup (pargs.r.ret_str);
- goto next_pass;
- }
- break;
- case oNoOptions: break; /* no-options */
- case oHomedir: opt.homedir = pargs.r.ret_str; break;
- case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
- case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break;
- case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break;
- case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break;
- case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break;
- case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break;
- case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break;
- case oProtectToolProgram:
- opt.protect_tool_program = pargs.r.ret_str;
- break;
-
- case oFakedSystemTime:
- gnupg_set_time ( (time_t)pargs.r.ret_ulong, 0);
- break;
-
- case oNoDefKeyring: default_keyring = 0; break;
- case oNoGreeting: nogreeting = 1; break;
-
- case oDefaultKey:
- /* fixme:opt.def_secret_key = pargs.r.ret_str;*/
- break;
- case oDefRecipient:
- if (*pargs.r.ret_str)
- opt.def_recipient = xstrdup (pargs.r.ret_str);
- break;
- case oDefRecipientSelf:
- xfree (opt.def_recipient);
- opt.def_recipient = NULL;
- opt.def_recipient_self = 1;
- break;
- case oNoDefRecipient:
- xfree (opt.def_recipient);
- opt.def_recipient = NULL;
- opt.def_recipient_self = 0;
- break;
-
- case oWithKeyData: opt.with_key_data=1; /* fall thru */
- case oWithColons: ctrl.with_colons = 1; break;
- case oWithValidation: ctrl.with_validation=1; break;
-
- case oSkipVerify: opt.skip_verify=1; break;
-
- case oNoEncryptTo: opt.no_encrypt_to = 1; break;
- case oEncryptTo: /* Store the recipient in the second list */
- sl = add_to_strlist (&remusr, pargs.r.ret_str);
- sl->flags = 1;
- break;
-
- case oRecipient: /* store the recipient */
- add_to_strlist ( &remusr, pargs.r.ret_str);
- break;
-
- case oTextmodeShort: /*fixme:opt.textmode = 2;*/ break;
- case oTextmode: /*fixme:opt.textmode=1;*/ break;
-
- case oUser: /* store the local users, the first one is the default */
- if (!opt.local_user)
- opt.local_user = pargs.r.ret_str;
- add_to_strlist (&locusr, pargs.r.ret_str);
- break;
-
- case oNoSecmemWarn:
- gcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
- break;
-
- case oCipherAlgo:
- opt.def_cipher_algoid = pargs.r.ret_str;
- break;
-
- case oDisableCipherAlgo:
- {
- int algo = gcry_cipher_map_name (pargs.r.ret_str);
- gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, &algo, sizeof algo);
- }
- break;
- case oDisablePubkeyAlgo:
- {
- int algo = gcry_pk_map_name (pargs.r.ret_str);
- gcry_pk_ctl (GCRYCTL_DISABLE_ALGO,&algo, sizeof algo );
- }
- break;
-
- case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
- case oNoRandomSeedFile: use_random_seed = 0; break;
-
- case oEnableSpecialFilenames: allow_special_filenames =1; break;
-
-
- case aDummy:
- break;
- default:
- pargs.err = configfp? 1:2;
- break;
- }
- }
-
- if (configfp)
- {
- fclose (configfp);
- configfp = NULL;
- /* Keep a copy of the config filename. */
- opt.config_filename = configname;
- configname = NULL;
- goto next_pass;
- }
- xfree (configname);
- configname = NULL;
-
- if (!opt.config_filename)
- opt.config_filename = make_filename (opt.homedir, "gpgsm.conf", NULL);
-
- if (log_get_errorcount(0))
- gpgsm_exit(2);
-
- if (nogreeting)
- greeting = 0;
-
- if (greeting)
- {
- fprintf(stderr, "%s %s; %s\n",
- strusage(11), strusage(13), strusage(14) );
- fprintf(stderr, "%s\n", strusage(15) );
- }
-# ifdef IS_DEVELOPMENT_VERSION
- 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 (may_coredump && !opt.quiet)
- log_info (_("WARNING: program may create a core file!\n"));
-
- if (logfile && cmd == aServer)
- {
- log_set_file (logfile);
- log_set_prefix (NULL, 1|2|4);
- }
-
- if (gnupg_faked_time_p ())
- {
- gnupg_isotime_t tbuf;
-
- log_info (_("WARNING: running with faked system time: "));
- gnupg_get_isotime (tbuf);
- gpgsm_dump_time (tbuf);
- log_printf ("\n");
- }
-
-/*FIXME if (opt.batch) */
-/* tty_batchmode (1); */
-
- gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
-
- set_debug (debug_level);
-
- /* Although we alwasy use gpgsm_exit, we better install a regualr
- exit handler so that at least the secure memory gets wiped
- out. */
- if (atexit (emergency_cleanup))
- {
- log_error ("atexit failed\n");
- gpgsm_exit (2);
- }
-
- /* Must do this after dropping setuid, because the mapping functions
- may try to load an module and we may have disabled an algorithm. */
- if ( !gcry_cipher_map_name (opt.def_cipher_algoid)
- || !gcry_cipher_mode_from_oid (opt.def_cipher_algoid))
- log_error (_("selected cipher algorithm is invalid\n"));
-
- if (def_digest_string)
- {
- opt.def_digest_algo = gcry_md_map_name (def_digest_string);
- xfree (def_digest_string);
- def_digest_string = NULL;
- if (our_md_test_algo(opt.def_digest_algo) )
- log_error (_("selected digest algorithm is invalid\n"));
- }
-
- if (log_get_errorcount(0))
- gpgsm_exit(2);
-
- /* Set the random seed file. */
- if (use_random_seed) {
- char *p = make_filename (opt.homedir, "random_seed", NULL);
- gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
- xfree(p);
- }
-
-
- if (!cmd && opt.fingerprint && !with_fpr)
- set_cmd (&cmd, aListKeys);
-
- if (!nrings && default_keyring) /* add default keybox */
- keydb_add_resource ("pubring.kbx", 0, 0);
- for (sl = nrings; sl; sl = sl->next)
- keydb_add_resource (sl->d, 0, 0);
- FREE_STRLIST(nrings);
-
- if (!do_not_setup_keys)
- {
- for (sl = locusr; sl ; sl = sl->next)
- {
- int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist, 0);
- if (rc)
- {
- log_error (_("can't sign using `%s': %s\n"),
- sl->d, gpg_strerror (rc));
- gpgsm_status2 (&ctrl, STATUS_INV_RECP,
- gpg_err_code (rc) == -1? "1":
- gpg_err_code (rc) == GPG_ERR_NO_PUBKEY? "1":
- gpg_err_code (rc) == GPG_ERR_AMBIGUOUS_NAME? "2":
- gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE? "3":
- gpg_err_code (rc) == GPG_ERR_CERT_REVOKED? "4":
- gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED? "5":
- gpg_err_code (rc) == GPG_ERR_NO_CRL_KNOWN? "6":
- gpg_err_code (rc) == GPG_ERR_CRL_TOO_OLD? "7":
- gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH? "8":
- gpg_err_code (rc) == GPG_ERR_NO_SECKEY? "9":
- "0",
- sl->d, NULL);
- }
- }
-
- /* Build the recipient list. We first add the regular ones and then
- the encrypt-to ones because the underlying function will silenty
- ignore duplicates and we can't allow to keep a duplicate which is
- flagged as encrypt-to as the actually encrypt function would then
- complain about no (regular) recipients. */
- for (sl = remusr; sl; sl = sl->next)
- if (!(sl->flags & 1))
- do_add_recipient (&ctrl, sl->d, &recplist, 0);
- if (!opt.no_encrypt_to)
- {
- for (sl = remusr; sl; sl = sl->next)
- if ((sl->flags & 1))
- do_add_recipient (&ctrl, sl->d, &recplist, 1);
- }
- }
-
- if (log_get_errorcount(0))
- gpgsm_exit(1); /* must stop for invalid recipients */
-
- fname = argc? *argv : NULL;
-
- switch (cmd)
- {
- case aGPGConfList:
- { /* List options and default values in the GPG Conf format. */
-
- /* The following list is taken from gnupg/tools/gpgconf-comp.c. */
- /* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING
- FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */
-#define GC_OPT_FLAG_NONE 0UL
- /* The RUNTIME flag for an option indicates that the option can be
- changed at runtime. */
-#define GC_OPT_FLAG_RUNTIME (1UL << 3)
- /* The DEFAULT flag for an option indicates that the option has a
- default value. */
-#define GC_OPT_FLAG_DEFAULT (1UL << 4)
- /* The DEF_DESC flag for an option indicates that the option has a
- default, which is described by the value of the default field. */
-#define GC_OPT_FLAG_DEF_DESC (1UL << 5)
- /* The NO_ARG_DESC flag for an option indicates that the argument has
- a default, which is described by the value of the ARGDEF field. */
-#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6)
-
- printf ("gpgconf-gpgsm.conf:%lu:\"%s\n",
- GC_OPT_FLAG_DEFAULT, opt.config_filename);
-
- printf ("verbose:%lu:\n"
- "quiet:%lu:\n"
- "debug-level:%lu:\"none:\n"
- "log-file:%lu:\n",
- GC_OPT_FLAG_NONE,
- GC_OPT_FLAG_NONE,
- GC_OPT_FLAG_DEFAULT,
- GC_OPT_FLAG_NONE );
- printf ("disable-crl-checks:%lu:\n",
- GC_OPT_FLAG_NONE );
- printf ("enable-ocsp:%lu:\n",
- GC_OPT_FLAG_NONE );
- printf ("include-certs:%lu:1:\n",
- GC_OPT_FLAG_DEFAULT );
- printf ("disable-policy-checks:%lu:\n",
- GC_OPT_FLAG_NONE );
- printf ("auto-issuer-key-retrieve:%lu:\n",
- GC_OPT_FLAG_NONE );
-
- }
- break;
-
- case aServer:
- if (debug_wait)
- {
- log_debug ("waiting for debugger - my pid is %u .....\n",
- (unsigned int)getpid());
- sleep (debug_wait);
- log_debug ("... okay\n");
- }
- gpgsm_server (recplist);
- break;
-
- case aCallDirmngr:
- if (!argc)
- wrong_args ("--call-dirmngr <command> {args}");
- else
- if (gpgsm_dirmngr_run_command (&ctrl, *argv, argc-1, argv+1))
- gpgsm_exit (1);
- break;
-
- case aCallProtectTool:
- run_protect_tool (argc, argv);
- break;
-
- case aEncr: /* encrypt the given file */
- if (!argc)
- gpgsm_encrypt (&ctrl, recplist, 0, stdout); /* from stdin */
- else if (argc == 1)
- gpgsm_encrypt (&ctrl, recplist, open_read (*argv), stdout); /* from file */
- else
- wrong_args ("--encrypt [datafile]");
- break;
-
- case aSign: /* sign the given file */
- /* FIXME: We don't handle --output yet. We should also allow
- to concatenate multiple files for signing because that is
- what gpg does.*/
- if (!argc)
- gpgsm_sign (&ctrl, signerlist,
- 0, detached_sig, stdout); /* create from stdin */
- else if (argc == 1)
- gpgsm_sign (&ctrl, signerlist,
- open_read (*argv), detached_sig, stdout); /* from file */
- else
- wrong_args ("--sign [datafile]");
- break;
-
- case aSignEncr: /* sign and encrypt the given file */
- log_error ("this command has not yet been implemented\n");
- break;
-
- case aClearsign: /* make a clearsig */
- log_error ("this command has not yet been implemented\n");
- break;
-
- case aVerify:
- {
- FILE *fp = NULL;
-
- if (argc == 2 && opt.outfile)
- log_info ("option --output ignored for a detached signature\n");
- else if (opt.outfile)
- fp = open_fwrite (opt.outfile);
-
- if (!argc)
- gpgsm_verify (&ctrl, 0, -1, fp); /* normal signature from stdin */
- else if (argc == 1)
- gpgsm_verify (&ctrl, open_read (*argv), -1, fp); /* std signature */
- else if (argc == 2) /* detached signature (sig, detached) */
- gpgsm_verify (&ctrl, open_read (*argv), open_read (argv[1]), NULL);
- else
- wrong_args ("--verify [signature [detached_data]]");
-
- if (fp && fp != stdout)
- fclose (fp);
- }
- break;
-
- case aVerifyFiles:
- log_error (_("this command has not yet been implemented\n"));
- break;
-
- case aDecrypt:
- if (!argc)
- gpgsm_decrypt (&ctrl, 0, stdout); /* from stdin */
- else if (argc == 1)
- gpgsm_decrypt (&ctrl, open_read (*argv), stdout); /* from file */
- else
- wrong_args ("--decrypt [filename]");
- break;
-
- case aDeleteKey:
- for (sl=NULL; argc; argc--, argv++)
- add_to_strlist (&sl, *argv);
- gpgsm_delete (&ctrl, sl);
- free_strlist(sl);
- break;
-
- case aListSigs:
- ctrl.with_chain = 1;
- case aListKeys:
- for (sl=NULL; argc; argc--, argv++)
- add_to_strlist (&sl, *argv);
- gpgsm_list_keys (&ctrl, sl, stdout, (0 | (1<<6)));
- free_strlist(sl);
- break;
-
- case aDumpKeys:
- for (sl=NULL; argc; argc--, argv++)
- add_to_strlist (&sl, *argv);
- gpgsm_list_keys (&ctrl, sl, stdout, (256 | (1<<6)));
- free_strlist(sl);
- break;
-
- case aListExternalKeys:
- for (sl=NULL; argc; argc--, argv++)
- add_to_strlist (&sl, *argv);
- gpgsm_list_keys (&ctrl, sl, stdout,
- (0 | (1<<7)));
- free_strlist(sl);
- break;
-
- case aDumpExternalKeys:
- for (sl=NULL; argc; argc--, argv++)
- add_to_strlist (&sl, *argv);
- gpgsm_list_keys (&ctrl, sl, stdout,
- (256 | (1<<7)));
- free_strlist(sl);
- break;
-
- case aListSecretKeys:
- for (sl=NULL; argc; argc--, argv++)
- add_to_strlist (&sl, *argv);
- gpgsm_list_keys (&ctrl, sl, stdout, (2 | (1<<6)));
- free_strlist(sl);
- break;
-
- case aDumpSecretKeys:
- for (sl=NULL; argc; argc--, argv++)
- add_to_strlist (&sl, *argv);
- gpgsm_list_keys (&ctrl, sl, stdout, (256 | 2 | (1<<6)));
- free_strlist(sl);
- break;
-
- case aKeygen: /* generate a key */
- log_error ("this function is not yet available from the commandline\n");
- break;
-
- case aImport:
- gpgsm_import_files (&ctrl, argc, argv, open_read);
- break;
-
- case aExport:
- for (sl=NULL; argc; argc--, argv++)
- add_to_strlist (&sl, *argv);
- gpgsm_export (&ctrl, sl, stdout);
- free_strlist(sl);
- break;
-
- case aExportSecretKeyP12:
- if (argc == 1)
- gpgsm_p12_export (&ctrl, *argv, stdout);
- else
- wrong_args ("--export-secret-key-p12 KEY-ID");
- break;
-
- case aSendKeys:
- case aRecvKeys:
- log_error ("this command has not yet been implemented\n");
- break;
-
-
- case aLearnCard:
- if (argc)
- wrong_args ("--learn-card");
- else
- {
- int rc = gpgsm_agent_learn (&ctrl);
- if (rc)
- log_error ("error learning card: %s\n", gpg_strerror (rc));
- }
- break;
-
- case aPasswd:
- if (argc != 1)
- wrong_args ("--passwd <key-Id>");
- else
- {
- int rc;
- ksba_cert_t cert = NULL;
- char *grip = NULL;
-
- rc = gpgsm_find_cert (*argv, &cert);
- if (rc)
- ;
- else if (!(grip = gpgsm_get_keygrip_hexstring (cert)))
- rc = gpg_error (GPG_ERR_BUG);
- else
- {
- char *desc = gpgsm_format_keydesc (cert);
- rc = gpgsm_agent_passwd (&ctrl, grip, desc);
- xfree (desc);
- }
- if (rc)
- log_error ("error changing passphrase: %s\n", gpg_strerror (rc));
- xfree (grip);
- ksba_cert_release (cert);
- }
- break;
-
- case aKeydbClearSomeCertFlags:
- for (sl=NULL; argc; argc--, argv++)
- add_to_strlist (&sl, *argv);
- keydb_clear_some_cert_flags (&ctrl, sl);
- free_strlist(sl);
- break;
-
-
- default:
- log_error ("invalid command (there is no implicit command)\n");
- break;
- }
-
- /* cleanup */
- gpgsm_release_certlist (recplist);
- gpgsm_release_certlist (signerlist);
- FREE_STRLIST(remusr);
- FREE_STRLIST(locusr);
- gpgsm_exit(0);
- return 8; /*NEVER REACHED*/
-}
-
-/* Note: This function is used by signal handlers!. */
-static void
-emergency_cleanup (void)
-{
- gcry_control (GCRYCTL_TERM_SECMEM );
-}
-
-
-void
-gpgsm_exit (int rc)
-{
- gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
- if (opt.debug & DBG_MEMSTAT_VALUE)
- {
- gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
- gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
- }
- if (opt.debug)
- gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
- emergency_cleanup ();
- rc = rc? rc : log_get_errorcount(0)? 2 : gpgsm_errors_seen? 1 : 0;
- exit (rc);
-}
-
-
-void
-gpgsm_init_default_ctrl (struct server_control_s *ctrl)
-{
- ctrl->include_certs = 1; /* only include the signer's cert */
- ctrl->use_ocsp = opt.enable_ocsp;
-}
-
-
-
-/* Check whether the filename has the form "-&nnnn", where n is a
- non-zero number. Returns this number or -1 if it is not the case. */
-static int
-check_special_filename (const char *fname)
-{
- if (allow_special_filenames
- && fname && *fname == '-' && fname[1] == '&' ) {
- int i;
-
- fname += 2;
- for (i=0; isdigit (fname[i]); i++ )
- ;
- if ( !fname[i] )
- return atoi (fname);
- }
- return -1;
-}
-
-
-
-/* Open the FILENAME for read and return the filedescriptor. Stop
- with an error message in case of problems. "-" denotes stdin and
- if special filenames are allowed the given fd is opened instead. */
-static int
-open_read (const char *filename)
-{
- int fd;
-
- if (filename[0] == '-' && !filename[1])
- return 0; /* stdin */
- fd = check_special_filename (filename);
- if (fd != -1)
- return fd;
- fd = open (filename, O_RDONLY);
- if (fd == -1)
- {
- log_error (_("can't open `%s': %s\n"), filename, strerror (errno));
- gpgsm_exit (2);
- }
- return fd;
-}
-
-/* Open FILENAME for fwrite and return the stream. Stop with an error
- message in case of problems. "-" denotes stdout and if special
- filenames are allowed the given fd is opened instead. Caller must
- close the returned stream unless it is stdout. */
-static FILE *
-open_fwrite (const char *filename)
-{
- int fd;
- FILE *fp;
-
- if (filename[0] == '-' && !filename[1])
- return stdout;
-
- fd = check_special_filename (filename);
- if (fd != -1)
- {
- fp = fdopen (dup (fd), "wb");
- if (!fp)
- {
- log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
- gpgsm_exit (2);
- }
- return fp;
- }
- fp = fopen (filename, "wb");
- if (!fp)
- {
- log_error (_("can't open `%s': %s\n"), filename, strerror (errno));
- gpgsm_exit (2);
- }
- return fp;
-}
-
-
-static void
-run_protect_tool (int argc, char **argv)
-{
- const char *pgm;
- char **av;
- int i;
-
- if (!opt.protect_tool_program || !*opt.protect_tool_program)
- pgm = GNUPG_DEFAULT_PROTECT_TOOL;
- else
- pgm = opt.protect_tool_program;
-
- av = xcalloc (argc+2, sizeof *av);
- av[0] = strrchr (pgm, '/');
- if (!av[0])
- av[0] = xstrdup (pgm);
- for (i=1; argc; i++, argc--, argv++)
- av[i] = *argv;
- av[i] = NULL;
- execv (pgm, av);
- log_error ("error executing `%s': %s\n", pgm, strerror (errno));
- gpgsm_exit (2);
-}
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
deleted file mode 100644
index 786a97353..000000000
--- a/sm/gpgsm.h
+++ /dev/null
@@ -1,311 +0,0 @@
-/* gpgsm.h - Global definitions for GpgSM
- * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef GPGSM_H
-#define GPGSM_H
-
-#ifdef GPG_ERR_SOURCE_DEFAULT
-#error GPG_ERR_SOURCE_DEFAULT already defined
-#endif
-#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GPGSM
-#include <gpg-error.h>
-
-#include <ksba.h>
-#include "../common/util.h"
-#include "../common/errors.h"
-
-#define OUT_OF_CORE(a) (gpg_error (gpg_err_code_from_errno ((a))))
-
-#define MAX_DIGEST_LEN 24
-
-/* A large struct named "opt" to keep global flags */
-struct {
- unsigned int debug; /* debug flags (DBG_foo_VALUE) */
- int verbose; /* verbosity level */
- int quiet; /* be as quiet as possible */
- int batch; /* run in batch mode, i.e w/o any user interaction */
- int answer_yes; /* assume yes on most questions */
- int answer_no; /* assume no on most questions */
- int dry_run; /* don't change any persistent data */
-
- const char *homedir; /* Configuration directory name */
- const char *config_filename; /* Name of the used config file. */
- const char *agent_program;
- char *display;
- char *ttyname;
- char *ttytype;
- char *lc_ctype;
- char *lc_messages;
-
- const char *dirmngr_program;
- const char *protect_tool_program;
- char *outfile; /* name of output file */
-
- int with_key_data;/* include raw key in the column delimted output */
-
- int fingerprint; /* list fingerprints in all key listings */
-
- int with_md5_fingerprint; /* Also print an MD5 fingerprint for
- standard key listings. */
-
- int armor; /* force base64 armoring (see also ctrl.with_base64) */
- int no_armor; /* don't try to figure out whether data is base64 armored*/
-
- const char *def_cipher_algoid; /* cipher algorithm to use if
- nothing else is specified */
-
- int def_digest_algo; /* Ditto for hash algorithm */
- int def_compress_algo; /* Ditto for compress algorithm */
-
- char *def_recipient; /* userID of the default recipient */
- int def_recipient_self; /* The default recipient is the default key */
-
- int no_encrypt_to; /* Ignore all as encrypt to marked recipients. */
-
- char *local_user; /* NULL or argument to -u */
-
- int always_trust; /* Trust the given keys even if there is no
- valid certification chain */
- int skip_verify; /* do not check signatures on data */
-
- int lock_once; /* Keep lock once they are set */
-
- int ignore_time_conflict; /* Ignore certain time conflicts */
-
- int no_crl_check; /* Don't do a CRL check */
- int force_crl_refresh; /* Force refreshing the CRL. */
- int enable_ocsp; /* Default to use OCSP checks. */
-
- char *policy_file; /* full pathname of policy file */
- int no_policy_check; /* ignore certificate policies */
- int no_chain_validation; /* Bypass all cert chain validity tests */
- int ignore_expiration; /* Ignore the notAfter validity checks. */
-
- int auto_issuer_key_retrieve; /* try to retrieve a missing issuer key. */
-} opt;
-
-
-#define DBG_X509_VALUE 1 /* debug x.509 data reading/writing */
-#define DBG_MPI_VALUE 2 /* debug mpi details */
-#define DBG_CRYPTO_VALUE 4 /* debug low level crypto */
-#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */
-#define DBG_CACHE_VALUE 64 /* debug the caching */
-#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
-#define DBG_HASHING_VALUE 512 /* debug hashing operations */
-#define DBG_ASSUAN_VALUE 1024 /* debug assuan communication */
-
-#define DBG_X509 (opt.debug & DBG_X509_VALUE)
-#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE)
-#define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE)
-#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
-#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
-#define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE)
-
-struct server_local_s;
-
-/* Note that the default values for this are set by
- gpgsm_init_default_ctrl() */
-struct server_control_s {
- int no_server; /* We are not running under server control */
- int status_fd; /* Only for non-server mode */
- struct server_local_s *server_local;
- int with_colons; /* Use column delimited output format */
- int with_chain; /* Include the certifying certs in a listing */
- int with_validation;/* Validate each key while listing. */
-
- int autodetect_encoding; /* Try to detect the input encoding */
- int is_pem; /* Is in PEM format */
- int is_base64; /* is in plain base-64 format */
-
- int create_base64; /* Create base64 encoded output */
- int create_pem; /* create PEM output */
- const char *pem_name; /* PEM name to use */
-
- int include_certs; /* -1 to send all certificates in the chain
- along with a signature or the number of
- certificates up the chain (0 = none, 1 = only
- signer) */
- int use_ocsp; /* Set to true if OCSP should be used. */
-};
-typedef struct server_control_s *CTRL;
-typedef struct server_control_s *ctrl_t;
-
-/* data structure used in base64.c */
-typedef struct base64_context_s *Base64Context;
-
-
-struct certlist_s {
- struct certlist_s *next;
- ksba_cert_t cert;
- int is_encrypt_to; /* True if the certificate has been set through
- the --encrypto-to option. */
-};
-typedef struct certlist_s *CERTLIST;
-typedef struct certlist_s *certlist_t;
-
-/*-- gpgsm.c --*/
-void gpgsm_exit (int rc);
-void gpgsm_init_default_ctrl (struct server_control_s *ctrl);
-
-/*-- server.c --*/
-void gpgsm_server (certlist_t default_recplist);
-void gpgsm_status (ctrl_t ctrl, int no, const char *text);
-void gpgsm_status2 (ctrl_t ctrl, int no, ...);
-void gpgsm_status_with_err_code (ctrl_t ctrl, int no, const char *text,
- gpg_err_code_t ec);
-
-/*-- fingerprint --*/
-char *gpgsm_get_fingerprint (ksba_cert_t cert, int algo,
- char *array, int *r_len);
-char *gpgsm_get_fingerprint_string (ksba_cert_t cert, int algo);
-char *gpgsm_get_fingerprint_hexstring (ksba_cert_t cert, int algo);
-unsigned long gpgsm_get_short_fingerprint (ksba_cert_t cert);
-char *gpgsm_get_keygrip (ksba_cert_t cert, char *array);
-char *gpgsm_get_keygrip_hexstring (ksba_cert_t cert);
-int gpgsm_get_key_algo_info (ksba_cert_t cert, unsigned int *nbits);
-char *gpgsm_get_certid (ksba_cert_t cert);
-
-
-/*-- base64.c --*/
-int gpgsm_create_reader (Base64Context *ctx,
- ctrl_t ctrl, FILE *fp, int allow_multi_pem,
- ksba_reader_t *r_reader);
-int gpgsm_reader_eof_seen (Base64Context ctx);
-void gpgsm_destroy_reader (Base64Context ctx);
-int gpgsm_create_writer (Base64Context *ctx,
- ctrl_t ctrl, FILE *fp, ksba_writer_t *r_writer);
-int gpgsm_finish_writer (Base64Context ctx);
-void gpgsm_destroy_writer (Base64Context ctx);
-
-
-/*-- certdump.c --*/
-void gpgsm_print_serial (FILE *fp, ksba_const_sexp_t p);
-void gpgsm_print_time (FILE *fp, ksba_isotime_t t);
-void gpgsm_print_name (FILE *fp, const char *string);
-
-void gpgsm_dump_cert (const char *text, ksba_cert_t cert);
-void gpgsm_dump_serial (ksba_const_sexp_t p);
-void gpgsm_dump_time (ksba_isotime_t t);
-void gpgsm_dump_string (const char *string);
-
-char *gpgsm_format_serial (ksba_const_sexp_t p);
-char *gpgsm_format_name (const char *name);
-
-char *gpgsm_format_keydesc (ksba_cert_t cert);
-
-
-/*-- certcheck.c --*/
-int gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert);
-int gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
- gcry_md_hd_t md, int hash_algo);
-/* fixme: move create functions to another file */
-int gpgsm_create_cms_signature (ctrl_t ctrl,
- ksba_cert_t cert, gcry_md_hd_t md, int mdalgo,
- char **r_sigval);
-
-
-/*-- certchain.c --*/
-int gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next);
-int gpgsm_is_root_cert (ksba_cert_t cert);
-int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert,
- ksba_isotime_t r_exptime,
- int listmode, FILE *listfp,
- unsigned int flags);
-int gpgsm_basic_cert_check (ksba_cert_t cert);
-
-/*-- certlist.c --*/
-int gpgsm_cert_use_sign_p (ksba_cert_t cert);
-int gpgsm_cert_use_encrypt_p (ksba_cert_t cert);
-int gpgsm_cert_use_verify_p (ksba_cert_t cert);
-int gpgsm_cert_use_decrypt_p (ksba_cert_t cert);
-int gpgsm_cert_use_cert_p (ksba_cert_t cert);
-int gpgsm_add_cert_to_certlist (ctrl_t ctrl, ksba_cert_t cert,
- certlist_t *listaddr, int is_encrypt_to);
-int gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret,
- certlist_t *listaddr, int is_encrypt_to);
-void gpgsm_release_certlist (certlist_t list);
-int gpgsm_find_cert (const char *name, ksba_cert_t *r_cert);
-
-/*-- keylist.c --*/
-gpg_error_t gpgsm_list_keys (ctrl_t ctrl, STRLIST names,
- FILE *fp, unsigned int mode);
-
-/*-- import.c --*/
-int gpgsm_import (ctrl_t ctrl, int in_fd);
-int gpgsm_import_files (ctrl_t ctrl, int nfiles, char **files,
- int (*of)(const char *fname));
-
-/*-- export.c --*/
-void gpgsm_export (ctrl_t ctrl, STRLIST names, FILE *fp);
-void gpgsm_p12_export (ctrl_t ctrl, const char *name, FILE *fp);
-
-/*-- delete.c --*/
-int gpgsm_delete (ctrl_t ctrl, STRLIST names);
-
-/*-- verify.c --*/
-int gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp);
-
-/*-- sign.c --*/
-int gpgsm_get_default_cert (ctrl_t ctrl, ksba_cert_t *r_cert);
-int gpgsm_sign (ctrl_t ctrl, CERTLIST signerlist,
- int data_fd, int detached, FILE *out_fp);
-
-/*-- encrypt.c --*/
-int gpgsm_encrypt (ctrl_t ctrl, CERTLIST recplist, int in_fd, FILE *out_fp);
-
-/*-- decrypt.c --*/
-int gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp);
-
-/*-- certreqgen.c --*/
-int gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp);
-
-/*-- call-agent.c --*/
-int gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
- unsigned char *digest,
- size_t digestlen,
- int digestalgo,
- char **r_buf, size_t *r_buflen);
-int gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
- ksba_const_sexp_t ciphertext,
- char **r_buf, size_t *r_buflen);
-int gpgsm_agent_genkey (ctrl_t ctrl,
- ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey);
-int gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert);
-int gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip);
-int gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert);
-int gpgsm_agent_learn (ctrl_t ctrl);
-int gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc);
-
-/*-- call-dirmngr.c --*/
-int gpgsm_dirmngr_isvalid (ctrl_t ctrl,
- ksba_cert_t cert, ksba_cert_t issuer_cert,
- int use_ocsp);
-int gpgsm_dirmngr_lookup (ctrl_t ctrl, STRLIST names,
- void (*cb)(void*, ksba_cert_t), void *cb_value);
-int gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
- int argc, char **argv);
-
-
-/*-- misc.c --*/
-void setup_pinentry_env (void);
-
-
-
-#endif /*GPGSM_H*/
diff --git a/sm/import.c b/sm/import.c
deleted file mode 100644
index c5581eb64..000000000
--- a/sm/import.c
+++ /dev/null
@@ -1,725 +0,0 @@
-/* import.c - Import certificates
- * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-#ifdef _POSIX_OPEN_MAX
-#define MAX_OPEN_FDS _POSIX_OPEN_MAX
-#else
-#define MAX_OPEN_FDS 20
-#endif
-
-
-struct stats_s {
- unsigned long count;
- unsigned long imported;
- unsigned long unchanged;
- unsigned long not_imported;
- unsigned long secret_read;
- unsigned long secret_imported;
- unsigned long secret_dups;
- };
-
-
-static gpg_error_t parse_p12 (ksba_reader_t reader, FILE **retfp,
- struct stats_s *stats);
-
-
-
-static void
-print_imported_status (CTRL ctrl, ksba_cert_t cert, int new_cert)
-{
- char *fpr;
-
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- if (new_cert)
- gpgsm_status2 (ctrl, STATUS_IMPORTED, fpr, "[X.509]", NULL);
-
- gpgsm_status2 (ctrl, STATUS_IMPORT_OK,
- new_cert? "1":"0", fpr, NULL);
-
- xfree (fpr);
-}
-
-
-/* Print an IMPORT_PROBLEM status. REASON is one of:
- 0 := "No specific reason given".
- 1 := "Invalid Certificate".
- 2 := "Issuer Certificate missing".
- 3 := "Certificate Chain too long".
- 4 := "Error storing certificate".
-*/
-static void
-print_import_problem (CTRL ctrl, ksba_cert_t cert, int reason)
-{
- char *fpr = NULL;
- char buf[25];
- int i;
-
- sprintf (buf, "%d", reason);
- if (cert)
- {
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- /* detetect an error (all high) value */
- for (i=0; fpr[i] == 'F'; i++)
- ;
- if (!fpr[i])
- {
- xfree (fpr);
- fpr = NULL;
- }
- }
- gpgsm_status2 (ctrl, STATUS_IMPORT_PROBLEM, buf, fpr, NULL);
- xfree (fpr);
-}
-
-
-void
-print_imported_summary (CTRL ctrl, struct stats_s *stats)
-{
- char buf[14*25];
-
- if (!opt.quiet)
- {
- log_info (_("total number processed: %lu\n"), stats->count);
- if (stats->imported)
- {
- log_info (_(" imported: %lu"), stats->imported );
- log_printf ("\n");
- }
- if (stats->unchanged)
- log_info (_(" unchanged: %lu\n"), stats->unchanged);
- if (stats->secret_read)
- log_info (_(" secret keys read: %lu\n"), stats->secret_read );
- if (stats->secret_imported)
- log_info (_(" secret keys imported: %lu\n"), stats->secret_imported );
- if (stats->secret_dups)
- log_info (_(" secret keys unchanged: %lu\n"), stats->secret_dups );
- if (stats->not_imported)
- log_info (_(" not imported: %lu\n"), stats->not_imported);
- }
-
- sprintf(buf, "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
- stats->count,
- 0l /*stats->no_user_id*/,
- stats->imported,
- 0l /*stats->imported_rsa*/,
- stats->unchanged,
- 0l /*stats->n_uids*/,
- 0l /*stats->n_subk*/,
- 0l /*stats->n_sigs*/,
- 0l /*stats->n_revoc*/,
- stats->secret_read,
- stats->secret_imported,
- stats->secret_dups,
- 0l /*stats->skipped_new_keys*/,
- stats->not_imported
- );
- gpgsm_status (ctrl, STATUS_IMPORT_RES, buf);
-}
-
-
-
-static void
-check_and_store (CTRL ctrl, struct stats_s *stats, ksba_cert_t cert, int depth)
-{
- int rc;
-
- if (stats)
- stats->count++;
- if ( depth >= 50 )
- {
- log_error (_("certificate chain too long\n"));
- if (stats)
- stats->not_imported++;
- print_import_problem (ctrl, cert, 3);
- return;
- }
-
- /* Some basic checks, but don't care about missing certificates;
- this is so that we are able to import entire certificate chains
- w/o requirening a special order (i.e. root-CA first). This used
- to be different but because gpgsm_verify even imports
- certificates without any checks, it doesn't matter much and the
- code gets much cleaner. A housekeeping function to remove
- certificates w/o an anchor would be nice, though. */
- rc = gpgsm_basic_cert_check (cert);
- if (!rc || gpg_err_code (rc) == GPG_ERR_MISSING_CERT)
- {
- int existed;
-
- if (!keydb_store_cert (cert, 0, &existed))
- {
- ksba_cert_t next = NULL;
-
- if (!existed)
- {
- print_imported_status (ctrl, cert, 1);
- if (stats)
- stats->imported++;
- }
- else
- {
- print_imported_status (ctrl, cert, 0);
- if (stats)
- stats->unchanged++;
- }
-
- if (opt.verbose > 1 && existed)
- {
- if (depth)
- log_info ("issuer certificate already in DB\n");
- else
- log_info ("certificate already in DB\n");
- }
- else if (opt.verbose && !existed)
- {
- if (depth)
- log_info ("issuer certificate imported\n");
- else
- log_info ("certificate imported\n");
- }
-
- /* Now lets walk up the chain and import all certificates up
- the chain. This is required in case we already stored
- parent certificates in the ephemeral keybox. Do not
- update the statistics, though. */
- if (!gpgsm_walk_cert_chain (cert, &next))
- {
- check_and_store (ctrl, NULL, next, depth+1);
- ksba_cert_release (next);
- }
- }
- else
- {
- log_error (_("error storing certificate\n"));
- if (stats)
- stats->not_imported++;
- print_import_problem (ctrl, cert, 4);
- }
- }
- else
- {
- log_error (_("basic certificate checks failed - not imported\n"));
- if (stats)
- stats->not_imported++;
- print_import_problem (ctrl, cert,
- gpg_err_code (rc) == GPG_ERR_MISSING_CERT? 2 :
- gpg_err_code (rc) == GPG_ERR_BAD_CERT? 1 : 0);
- }
-}
-
-
-
-
-static int
-import_one (CTRL ctrl, struct stats_s *stats, int in_fd)
-{
- int rc;
- Base64Context b64reader = NULL;
- ksba_reader_t reader;
- ksba_cert_t cert = NULL;
- ksba_cms_t cms = NULL;
- FILE *fp = NULL;
- ksba_content_type_t ct;
- int any = 0;
-
- fp = fdopen ( dup (in_fd), "rb");
- if (!fp)
- {
- rc = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("fdopen() failed: %s\n", strerror (errno));
- goto leave;
- }
-
- rc = gpgsm_create_reader (&b64reader, ctrl, fp, 1, &reader);
- if (rc)
- {
- log_error ("can't create reader: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
-
- /* We need to loop here to handle multiple PEM objects in one
- file. */
- do
- {
- ksba_cms_release (cms); cms = NULL;
- ksba_cert_release (cert); cert = NULL;
-
- ct = ksba_cms_identify (reader);
- if (ct == KSBA_CT_SIGNED_DATA)
- { /* This is probably a signed-only message - import the certs */
- ksba_stop_reason_t stopreason;
- int i;
-
- rc = ksba_cms_new (&cms);
- if (rc)
- goto leave;
-
- rc = ksba_cms_set_reader_writer (cms, reader, NULL);
- if (rc)
- {
- log_error ("ksba_cms_set_reader_writer failed: %s\n",
- gpg_strerror (rc));
- goto leave;
- }
-
- do
- {
- rc = ksba_cms_parse (cms, &stopreason);
- if (rc)
- {
- log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- if (stopreason == KSBA_SR_BEGIN_DATA)
- log_info ("not a certs-only message\n");
- }
- while (stopreason != KSBA_SR_READY);
-
- for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
- {
- check_and_store (ctrl, stats, cert, 0);
- ksba_cert_release (cert);
- cert = NULL;
- }
- if (!i)
- log_error ("no certificate found\n");
- else
- any = 1;
- }
- else if (ct == KSBA_CT_PKCS12)
- { /* This seems to be a pkcs12 message. We use an external
- tool to parse the message and to store the private keys.
- We need to use a another reader here to parse the
- certificate we included in the p12 file; then we continue
- to look for other pkcs12 files (works only if they are in
- PEM format. */
- FILE *certfp;
- Base64Context b64p12rdr;
- ksba_reader_t p12rdr;
-
- rc = parse_p12 (reader, &certfp, stats);
- if (!rc)
- {
- any = 1;
-
- rewind (certfp);
- rc = gpgsm_create_reader (&b64p12rdr, ctrl, certfp, 1, &p12rdr);
- if (rc)
- {
- log_error ("can't create reader: %s\n", gpg_strerror (rc));
- fclose (certfp);
- goto leave;
- }
-
- do
- {
- ksba_cert_release (cert); cert = NULL;
- rc = ksba_cert_new (&cert);
- if (!rc)
- {
- rc = ksba_cert_read_der (cert, p12rdr);
- if (!rc)
- check_and_store (ctrl, stats, cert, 0);
- }
- ksba_reader_clear (p12rdr, NULL, NULL);
- }
- while (!rc && !gpgsm_reader_eof_seen (b64p12rdr));
-
- if (gpg_err_code (rc) == GPG_ERR_EOF)
- rc = 0;
- gpgsm_destroy_reader (b64p12rdr);
- fclose (certfp);
- if (rc)
- goto leave;
- }
- }
- else if (ct == KSBA_CT_NONE)
- { /* Failed to identify this message - assume a certificate */
-
- rc = ksba_cert_new (&cert);
- if (rc)
- goto leave;
-
- rc = ksba_cert_read_der (cert, reader);
- if (rc)
- goto leave;
-
- check_and_store (ctrl, stats, cert, 0);
- any = 1;
- }
- else
- {
- log_error ("can't extract certificates from input\n");
- rc = gpg_error (GPG_ERR_NO_DATA);
- }
-
- ksba_reader_clear (reader, NULL, NULL);
- }
- while (!gpgsm_reader_eof_seen (b64reader));
-
- leave:
- if (any && gpg_err_code (rc) == GPG_ERR_EOF)
- rc = 0;
- ksba_cms_release (cms);
- ksba_cert_release (cert);
- gpgsm_destroy_reader (b64reader);
- if (fp)
- fclose (fp);
- return rc;
-}
-
-
-int
-gpgsm_import (CTRL ctrl, int in_fd)
-{
- int rc;
- struct stats_s stats;
-
- memset (&stats, 0, sizeof stats);
- rc = import_one (ctrl, &stats, in_fd);
- print_imported_summary (ctrl, &stats);
- /* If we never printed an error message do it now so that a command
- line invocation will return with an error (log_error keeps a
- global errorcount) */
- if (rc && !log_get_errorcount (0))
- log_error (_("error importing certificate: %s\n"), gpg_strerror (rc));
- return rc;
-}
-
-
-int
-gpgsm_import_files (CTRL ctrl, int nfiles, char **files,
- int (*of)(const char *fname))
-{
- int rc = 0;
- struct stats_s stats;
-
- memset (&stats, 0, sizeof stats);
-
- if (!nfiles)
- rc = import_one (ctrl, &stats, 0);
- else
- {
- for (; nfiles && !rc ; nfiles--, files++)
- {
- int fd = of (*files);
- rc = import_one (ctrl, &stats, fd);
- close (fd);
- if (rc == -1)
- rc = 0;
- }
- }
- print_imported_summary (ctrl, &stats);
- /* If we never printed an error message do it now so that a command
- line invocation will return with an error (log_error keeps a
- global errorcount) */
- if (rc && !log_get_errorcount (0))
- log_error (_("error importing certificate: %s\n"), gpg_strerror (rc));
- return rc;
-}
-
-
-/* Fork and exec the protecttool, connect the file descriptor of
- INFILE to stdin, return a new stream in STATUSFILE, write the
- output to OUTFILE and the pid of the process in PID. Returns 0 on
- success or an error code. */
-static gpg_error_t
-popen_protect_tool (const char *pgmname,
- FILE *infile, FILE *outfile, FILE **statusfile, pid_t *pid)
-{
- gpg_error_t err;
- int fd, fdout, rp[2];
- int n, i;
-
- fflush (infile);
- rewind (infile);
- fd = fileno (infile);
- fdout = fileno (outfile);
- if (fd == -1 || fdout == -1)
- log_fatal ("no file descriptor for temporary file: %s\n",
- strerror (errno));
-
- /* Now start the protect-tool. */
- if (pipe (rp) == -1)
- {
- err = gpg_error_from_errno (errno);
- log_error (_("error creating a pipe: %s\n"), strerror (errno));
- return err;
- }
-
- *pid = fork ();
- if (*pid == -1)
- {
- err = gpg_error_from_errno (errno);
- log_error (_("error forking process: %s\n"), strerror (errno));
- close (rp[0]);
- close (rp[1]);
- return err;
- }
-
- if (!*pid)
- { /* Child. */
- const char *arg0;
-
- arg0 = strrchr (pgmname, '/');
- if (arg0)
- arg0++;
- else
- arg0 = pgmname;
-
- /* Connect the infile to stdin. */
- if (fd != 0 && dup2 (fd, 0) == -1)
- log_fatal ("dup2 stdin failed: %s\n", strerror (errno));
-
- /* Connect the outfile to stdout. */
- if (fdout != 1 && dup2 (fdout, 1) == -1)
- log_fatal ("dup2 stdout failed: %s\n", strerror (errno));
-
- /* Connect stderr to our pipe. */
- if (rp[1] != 2 && dup2 (rp[1], 2) == -1)
- log_fatal ("dup2 stderr failed: %s\n", strerror (errno));
-
- /* Close all other files. */
- n = sysconf (_SC_OPEN_MAX);
- if (n < 0)
- n = MAX_OPEN_FDS;
- for (i=3; i < n; i++)
- close(i);
- errno = 0;
-
- setup_pinentry_env ();
-
- execlp (pgmname, arg0,
- "--homedir", opt.homedir,
- "--p12-import",
- "--store",
- "--no-fail-on-exist",
- "--enable-status-msg",
- "--",
- NULL);
- /* No way to print anything, as we have closed all streams. */
- _exit (31);
- }
-
- /* Parent. */
- close (rp[1]);
- *statusfile = fdopen (rp[0], "r");
- if (!*statusfile)
- {
- err = gpg_error_from_errno (errno);
- log_error ("can't fdopen pipe for reading: %s", strerror (errno));
- kill (*pid, SIGTERM);
- return err;
- }
-
- return 0;
-}
-
-
-/* Assume that the reader is at a pkcs#12 message and try to import
- certificates from that stupid format. We will alos store secret
- keys. All of the pkcs#12 parsing and key storing is handled by the
- gpg-protect-tool, we merely have to take care of receiving the
- certificates. On success RETFP returns a temporary file with
- certificates. */
-static gpg_error_t
-parse_p12 (ksba_reader_t reader, FILE **retfp, struct stats_s *stats)
-{
- const char *pgmname;
- gpg_error_t err = 0, child_err = 0;
- int i, c, cont_line;
- unsigned int pos;
- FILE *tmpfp, *certfp = NULL, *fp = NULL;
- char buffer[1024];
- size_t nread;
- pid_t pid = -1;
-
- if (!opt.protect_tool_program || !*opt.protect_tool_program)
- pgmname = GNUPG_DEFAULT_PROTECT_TOOL;
- else
- pgmname = opt.protect_tool_program;
-
- *retfp = NULL;
-
- /* To avoid an extra feeder process or doing selects and because
- gpg-protect-tool will anyway parse the entire pkcs#12 message in
- memory, we simply use tempfiles here and pass them to
- the gpg-protect-tool. */
- tmpfp = tmpfile ();
- if (!tmpfp)
- {
- err = gpg_error_from_errno (errno);
- log_error (_("error creating temporary file: %s\n"), strerror (errno));
- goto cleanup;
- }
- while (!(err = ksba_reader_read (reader, buffer, sizeof buffer, &nread)))
- {
- if (nread && fwrite (buffer, nread, 1, tmpfp) != 1)
- {
- err = gpg_error_from_errno (errno);
- log_error (_("error writing to temporary file: %s\n"),
- strerror (errno));
- goto cleanup;
- }
- }
- if (gpg_err_code (err) == GPG_ERR_EOF)
- err = 0;
- if (err)
- {
- log_error (_("error reading input: %s\n"), gpg_strerror (err));
- goto cleanup;
- }
-
- certfp = tmpfile ();
- if (!certfp)
- {
- err = gpg_error_from_errno (errno);
- log_error (_("error creating temporary file: %s\n"), strerror (errno));
- goto cleanup;
- }
-
- err = popen_protect_tool (pgmname, tmpfp, certfp, &fp, &pid);
- if (err)
- {
- pid = -1;
- goto cleanup;
- }
- fclose (tmpfp);
- tmpfp = NULL;
-
- /* Read stderr of the protect tool. */
- pos = 0;
- cont_line = 0;
- while ((c=getc (fp)) != EOF)
- {
- /* fixme: We could here grep for status information of the
- protect tool to figure out better error codes for
- CHILD_ERR. */
- buffer[pos++] = c;
- if (pos >= sizeof buffer - 5 || c == '\n')
- {
- buffer[pos - (c == '\n')] = 0;
- if (cont_line)
- log_printf ("%s", buffer);
- else
- {
- if (!strncmp (buffer, "gpg-protect-tool: [PROTECT-TOOL:] ",34))
- {
- char *p, *pend;
-
- p = buffer + 34;
- pend = strchr (p, ' ');
- if (pend)
- *pend = 0;
- if ( !strcmp (p, "secretkey-stored"))
- {
- stats->count++;
- stats->secret_read++;
- stats->secret_imported++;
- }
- else if ( !strcmp (p, "secretkey-exists"))
- {
- stats->count++;
- stats->secret_read++;
- stats->secret_dups++;
- }
- else if ( !strcmp (p, "bad-passphrase"))
- ;
- }
- else
- log_info ("%s", buffer);
- }
- pos = 0;
- cont_line = (c != '\n');
- }
- }
-
- if (pos)
- {
- buffer[pos] = 0;
- if (cont_line)
- log_printf ("%s\n", buffer);
- else
- log_info ("%s\n", buffer);
- }
-
- /* If we found no error in the output of the cild, setup a suitable
- error code, which will later be reset if the exit status of the
- child is 0. */
- if (!child_err)
- child_err = gpg_error (GPG_ERR_DECRYPT_FAILED);
-
-
- cleanup:
- if (tmpfp)
- fclose (tmpfp);
- if (fp)
- fclose (fp);
- if (pid != -1)
- {
- int status;
-
- while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
- ;
- if (i == -1)
- log_error (_("waiting for protect-tool to terminate failed: %s\n"),
- strerror (errno));
- else if (WIFEXITED (status) && WEXITSTATUS (status) == 31)
- log_error (_("error running `%s': probably not installed\n"), pgmname);
- else if (WIFEXITED (status) && WEXITSTATUS (status))
- log_error (_("error running `%s': exit status %d\n"), pgmname,
- WEXITSTATUS (status));
- else if (!WIFEXITED (status))
- log_error (_("error running `%s': terminated\n"), pgmname);
- else
- child_err = 0;
- }
- if (!err)
- err = child_err;
- if (err)
- {
- if (certfp)
- fclose (certfp);
- }
- else
- *retfp = certfp;
- return err;
-}
diff --git a/sm/keydb.c b/sm/keydb.c
deleted file mode 100644
index 6c5c77364..000000000
--- a/sm/keydb.c
+++ /dev/null
@@ -1,1532 +0,0 @@
-/* keydb.c - key database dispatcher
- * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "gpgsm.h"
-#include "../kbx/keybox.h"
-#include "keydb.h"
-#include "i18n.h"
-
-#define DIRSEP_C '/'
-
-static int active_handles;
-
-typedef enum {
- KEYDB_RESOURCE_TYPE_NONE = 0,
- KEYDB_RESOURCE_TYPE_KEYBOX
-} KeydbResourceType;
-#define MAX_KEYDB_RESOURCES 20
-
-struct resource_item {
- KeydbResourceType type;
- union {
- KEYBOX_HANDLE kr;
- } u;
- void *token;
- int secret;
- DOTLOCK lockhandle;
-};
-
-static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
-static int used_resources;
-
-struct keydb_handle {
- int locked;
- int found;
- int current;
- int is_ephemeral;
- int used; /* items in active */
- struct resource_item active[MAX_KEYDB_RESOURCES];
-};
-
-
-static int lock_all (KEYDB_HANDLE hd);
-static void unlock_all (KEYDB_HANDLE hd);
-
-
-/*
- * Register a resource (which currently may only be a keybox file).
- * The first keybox which is added by this function is
- * created if it does not exist.
- * Note: this function may be called before secure memory is
- * available.
- */
-int
-keydb_add_resource (const char *url, int force, int secret)
-{
- static int any_secret, any_public;
- const char *resname = url;
- char *filename = NULL;
- int rc = 0;
- FILE *fp;
- KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
- const char *created_fname = NULL;
-
- /* Do we have an URL?
- gnupg-kbx:filename := this is a plain keybox
- filename := See what is is, but create as plain keybox.
- */
- if (strlen (resname) > 10)
- {
- if (!strncmp (resname, "gnupg-kbx:", 10) )
- {
- rt = KEYDB_RESOURCE_TYPE_KEYBOX;
- resname += 10;
- }
-#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
- else if (strchr (resname, ':'))
- {
- log_error ("invalid key resource URL `%s'\n", url );
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-#endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
- }
-
- if (*resname != DIRSEP_C )
- { /* do tilde expansion etc */
- if (strchr(resname, DIRSEP_C) )
- filename = make_filename (resname, NULL);
- else
- filename = make_filename (opt.homedir, resname, NULL);
- }
- else
- filename = xstrdup (resname);
-
- if (!force)
- force = secret? !any_secret : !any_public;
-
- /* see whether we can determine the filetype */
- if (rt == KEYDB_RESOURCE_TYPE_NONE)
- {
- FILE *fp2 = fopen( filename, "rb" );
-
- if (fp2) {
- u32 magic;
-
- /* FIXME: check for the keybox magic */
- if (fread( &magic, 4, 1, fp2) == 1 )
- {
- if (magic == 0x13579ace || magic == 0xce9a5713)
- ; /* GDBM magic - no more support */
- else
- rt = KEYDB_RESOURCE_TYPE_KEYBOX;
- }
- else /* maybe empty: assume ring */
- rt = KEYDB_RESOURCE_TYPE_KEYBOX;
- fclose (fp2);
- }
- else /* no file yet: create ring */
- rt = KEYDB_RESOURCE_TYPE_KEYBOX;
- }
-
- switch (rt)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- log_error ("unknown type of key resource `%s'\n", url );
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
-
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- fp = fopen (filename, "rb");
- if (!fp && !force)
- {
- rc = gpg_error (gpg_err_code_from_errno (errno));
- goto leave;
- }
-
- if (!fp)
- { /* no file */
-#if 0 /* no autocreate of the homedirectory yet */
- {
- char *last_slash_in_filename;
-
- last_slash_in_filename = strrchr (filename, DIRSEP_C);
- *last_slash_in_filename = 0;
- if (access (filename, F_OK))
- { /* 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 can
- read the options file in on startup */
- try_make_homedir (filename);
- rc = gpg_error (GPG_ERR_FILE_OPEN_ERROR);
- *last_slash_in_filename = DIRSEP_C;
- goto leave;
- }
- *last_slash_in_filename = DIRSEP_C;
- }
-#endif
- fp = fopen (filename, "w");
- if (!fp)
- {
- rc = gpg_error (gpg_err_code_from_errno (errno));
- log_error (_("error creating keybox `%s': %s\n"),
- filename, strerror(errno));
- if (errno == ENOENT)
- log_info (_("you may want to start the gpg-agent first\n"));
- goto leave;
- }
-
- if (!opt.quiet)
- log_info (_("keybox `%s' created\n"), filename);
- created_fname = filename;
- }
- fclose (fp);
- fp = NULL;
- /* now register the file */
- {
-
- void *token = keybox_register_file (filename, secret);
- if (!token)
- ; /* already registered - ignore it */
- else if (used_resources >= MAX_KEYDB_RESOURCES)
- rc = gpg_error (GPG_ERR_RESOURCE_LIMIT);
- else
- {
- all_resources[used_resources].type = rt;
- all_resources[used_resources].u.kr = NULL; /* Not used here */
- all_resources[used_resources].token = token;
- all_resources[used_resources].secret = secret;
-
- all_resources[used_resources].lockhandle
- = create_dotlock (filename);
- if (!all_resources[used_resources].lockhandle)
- log_fatal ( _("can't create lock for `%s'\n"), filename);
-
- /* Do a compress run if needed and the file is not locked. */
- if (!make_dotlock (all_resources[used_resources].lockhandle, 0))
- {
- KEYBOX_HANDLE kbxhd = keybox_new (token, secret);
-
- if (kbxhd)
- {
- keybox_compress (kbxhd);
- keybox_release (kbxhd);
- }
- release_dotlock (all_resources[used_resources].lockhandle);
- }
-
- used_resources++;
- }
- }
-
-
- break;
- default:
- log_error ("resource type of `%s' not supported\n", url);
- rc = gpg_error (GPG_ERR_NOT_SUPPORTED);
- goto leave;
- }
-
- /* fixme: check directory permissions and print a warning */
-
- leave:
- if (rc)
- log_error ("keyblock resource `%s': %s\n", filename, gpg_strerror(rc));
- else if (secret)
- any_secret = 1;
- else
- any_public = 1;
- xfree (filename);
- return rc;
-}
-
-
-KEYDB_HANDLE
-keydb_new (int secret)
-{
- KEYDB_HANDLE hd;
- int i, j;
-
- hd = xcalloc (1, sizeof *hd);
- hd->found = -1;
-
- assert (used_resources <= MAX_KEYDB_RESOURCES);
- for (i=j=0; i < used_resources; i++)
- {
- if (!all_resources[i].secret != !secret)
- continue;
- switch (all_resources[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- hd->active[j].type = all_resources[i].type;
- hd->active[j].token = all_resources[i].token;
- hd->active[j].secret = all_resources[i].secret;
- hd->active[j].lockhandle = all_resources[i].lockhandle;
- hd->active[j].u.kr = keybox_new (all_resources[i].token, secret);
- if (!hd->active[j].u.kr)
- {
- xfree (hd);
- return NULL; /* fixme: release all previously allocated handles*/
- }
- j++;
- break;
- }
- }
- hd->used = j;
-
- active_handles++;
- return hd;
-}
-
-void
-keydb_release (KEYDB_HANDLE hd)
-{
- int i;
-
- if (!hd)
- return;
- assert (active_handles > 0);
- active_handles--;
-
- unlock_all (hd);
- for (i=0; i < hd->used; i++)
- {
- switch (hd->active[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- keybox_release (hd->active[i].u.kr);
- break;
- }
- }
-
- xfree (hd);
-}
-
-
-/* Return the name of the current resource. This is function first
- looks for the last found found, then for the current search
- position, and last returns the first available resource. The
- returned string is only valid as long as the handle exists. This
- function does only return NULL if no handle is specified, in all
- other error cases an empty string is returned. */
-const char *
-keydb_get_resource_name (KEYDB_HANDLE hd)
-{
- int idx;
- const char *s = NULL;
-
- if (!hd)
- return NULL;
-
- if ( hd->found >= 0 && hd->found < hd->used)
- idx = hd->found;
- else if ( hd->current >= 0 && hd->current < hd->used)
- idx = hd->current;
- else
- idx = 0;
-
- switch (hd->active[idx].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- s = NULL;
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- s = keybox_get_resource_name (hd->active[idx].u.kr);
- break;
- }
-
- return s? s: "";
-}
-
-/* Switch the handle into ephemeral mode and return the orginal value. */
-int
-keydb_set_ephemeral (KEYDB_HANDLE hd, int yes)
-{
- int i;
-
- if (!hd)
- return 0;
-
- yes = !!yes;
- if (hd->is_ephemeral != yes)
- {
- for (i=0; i < hd->used; i++)
- {
- switch (hd->active[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- keybox_set_ephemeral (hd->active[i].u.kr, yes);
- break;
- }
- }
- }
-
- i = hd->is_ephemeral;
- hd->is_ephemeral = yes;
- return i;
-}
-
-
-/* If the keyring has not yet been locked, lock it now. This
- operation is required before any update opeations; it is optionaly
- for an insert operation. The lock is released with
- keydb_released. */
-gpg_error_t
-keydb_lock (KEYDB_HANDLE hd)
-{
- if (!hd)
- return gpg_error (GPG_ERR_INV_HANDLE);
- if (hd->locked)
- return 0; /* Already locked. */
- return lock_all (hd);
-}
-
-
-
-static int
-lock_all (KEYDB_HANDLE hd)
-{
- int i, rc = 0;
-
- /* Fixme: This locking scheme may lead to deadlock if the resources
- are not added in the same order by all processes. We are
- currently only allowing one resource so it is not a problem. */
- for (i=0; i < hd->used; i++)
- {
- switch (hd->active[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- if (hd->active[i].lockhandle)
- rc = make_dotlock (hd->active[i].lockhandle, -1);
- break;
- }
- if (rc)
- break;
- }
-
- if (rc)
- {
- /* revert the already set locks */
- for (i--; i >= 0; i--)
- {
- switch (hd->active[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- if (hd->active[i].lockhandle)
- release_dotlock (hd->active[i].lockhandle);
- break;
- }
- }
- }
- else
- hd->locked = 1;
-
- /* make_dotlock () does not yet guarantee that errno is set, thus
- we can't rely on the error reason and will simply use
- EACCES. */
- return rc? gpg_error (GPG_ERR_EACCES) : 0;
-}
-
-static void
-unlock_all (KEYDB_HANDLE hd)
-{
- int i;
-
- if (!hd->locked)
- return;
-
- for (i=hd->used-1; i >= 0; i--)
- {
- switch (hd->active[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- if (hd->active[i].lockhandle)
- release_dotlock (hd->active[i].lockhandle);
- break;
- }
- }
- hd->locked = 0;
-}
-
-
-#if 0
-/*
- * Return the last found keybox. Caller must free it.
- * The returned keyblock has the kbode flag bit 0 set for the node with
- * the public key used to locate the keyblock or flag bit 1 set for
- * the user ID node.
- */
-int
-keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
-{
- int rc = 0;
-
- if (!hd)
- return G10ERR_INV_ARG;
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
-
- switch (hd->active[hd->found].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = G10ERR_GENERAL; /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
- break;
- }
-
- return rc;
-}
-
-/*
- * update the current keyblock with KB
- */
-int
-keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
-{
- int rc = 0;
-
- if (!hd)
- return G10ERR_INV_ARG;
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
-
- if( opt.dry_run )
- return 0;
-
- if (!hd->locked)
- return gpg_error (GPG_ERR_NOT_LOCKED);
-
- switch (hd->active[hd->found].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = G10ERR_GENERAL; /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_update_keyblock (hd->active[hd->found].u.kr, kb);
- break;
- }
-
- unlock_all (hd);
- return rc;
-}
-
-
-/*
- * Insert a new KB into one of the resources.
- */
-int
-keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
-{
- int rc = -1;
- int idx;
-
- if (!hd)
- return G10ERR_INV_ARG;
-
- if( opt.dry_run )
- return 0;
-
- if ( hd->found >= 0 && hd->found < hd->used)
- idx = hd->found;
- else if ( hd->current >= 0 && hd->current < hd->used)
- idx = hd->current;
- else
- return G10ERR_GENERAL;
-
- rc = lock_all (hd);
- if (rc)
- return rc;
-
- switch (hd->active[idx].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = G10ERR_GENERAL; /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_insert_keyblock (hd->active[idx].u.kr, kb);
- break;
- }
-
- unlock_all (hd);
- return rc;
-}
-
-#endif /*disabled code*/
-
-
-
-/*
- Return the last found object. Caller must free it. The returned
- keyblock has the kbode flag bit 0 set for the node with the public
- key used to locate the keyblock or flag bit 1 set for the user ID
- node. */
-int
-keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert)
-{
- int rc = 0;
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
-
- switch (hd->active[hd->found].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = gpg_error (GPG_ERR_GENERAL); /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_get_cert (hd->active[hd->found].u.kr, r_cert);
- break;
- }
-
- return rc;
-}
-
-/* Return a flag of the last found object. WHICH is the flag requested;
- it should be one of the KEYBOX_FLAG_ values. If the operation is
- successful, the flag value will be stored at the address given by
- VALUE. Return 0 on success or an error code. */
-gpg_error_t
-keydb_get_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int *value)
-{
- int err = 0;
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return gpg_error (GPG_ERR_NOTHING_FOUND);
-
- switch (hd->active[hd->found].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- err = gpg_error (GPG_ERR_GENERAL); /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- err = keybox_get_flags (hd->active[hd->found].u.kr, which, idx, value);
- break;
- }
-
- return err;
-}
-
-/* Set a flag of the last found object. WHICH is the flag to be set; it
- should be one of the KEYBOX_FLAG_ values. If the operation is
- successful, the flag value will be stored in the keybox. Note,
- that some flag values can't be updated and thus may return an
- error, some other flag values may be masked out before an update.
- Returns 0 on success or an error code. */
-gpg_error_t
-keydb_set_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int value)
-{
- int err = 0;
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return gpg_error (GPG_ERR_NOTHING_FOUND);
-
- if (!hd->locked)
- return gpg_error (GPG_ERR_NOT_LOCKED);
-
- switch (hd->active[hd->found].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- err = gpg_error (GPG_ERR_GENERAL); /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- err = keybox_set_flags (hd->active[hd->found].u.kr, which, idx, value);
- break;
- }
-
- return err;
-}
-
-/*
- * Insert a new Certificate into one of the resources.
- */
-int
-keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
-{
- int rc = -1;
- int idx;
- char digest[20];
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- if (opt.dry_run)
- return 0;
-
- if ( hd->found >= 0 && hd->found < hd->used)
- idx = hd->found;
- else if ( hd->current >= 0 && hd->current < hd->used)
- idx = hd->current;
- else
- return gpg_error (GPG_ERR_GENERAL);
-
- rc = lock_all (hd);
- if (rc)
- return rc;
-
- gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
-
- switch (hd->active[idx].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = gpg_error (GPG_ERR_GENERAL);
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_insert_cert (hd->active[idx].u.kr, cert, digest);
- break;
- }
-
- unlock_all (hd);
- return rc;
-}
-
-
-
-/* update the current keyblock with KB */
-int
-keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
-{
- int rc = 0;
- char digest[20];
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
-
- if (opt.dry_run)
- return 0;
-
- rc = lock_all (hd);
- if (rc)
- return rc;
-
- gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
-
- switch (hd->active[hd->found].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = gpg_error (GPG_ERR_GENERAL); /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest);
- break;
- }
-
- unlock_all (hd);
- return rc;
-}
-
-
-/*
- * The current keyblock or cert will be deleted.
- */
-int
-keydb_delete (KEYDB_HANDLE hd)
-{
- int rc = -1;
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
-
- if( opt.dry_run )
- return 0;
-
- if (!hd->locked)
- return gpg_error (GPG_ERR_NOT_LOCKED);
-
- switch (hd->active[hd->found].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = gpg_error (GPG_ERR_GENERAL);
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_delete (hd->active[hd->found].u.kr);
- break;
- }
-
- unlock_all (hd);
- return rc;
-}
-
-
-
-/*
- * Locate the default writable key resource, so that the next
- * operation (which is only relevant for inserts) will be done on this
- * resource.
- */
-int
-keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
-{
- int rc;
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- rc = keydb_search_reset (hd); /* this does reset hd->current */
- if (rc)
- return rc;
-
- for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
- {
- switch (hd->active[hd->current].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- BUG();
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- if (keybox_is_writable (hd->active[hd->current].token))
- return 0; /* found (hd->current is set to it) */
- break;
- }
- }
-
- return -1;
-}
-
-/*
- * Rebuild the caches of all key resources.
- */
-void
-keydb_rebuild_caches (void)
-{
- int i;
-
- for (i=0; i < used_resources; i++)
- {
- if (all_resources[i].secret)
- continue;
- switch (all_resources[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
-/* rc = keybox_rebuild_cache (all_resources[i].token); */
-/* if (rc) */
-/* log_error (_("failed to rebuild keybox cache: %s\n"), */
-/* g10_errstr (rc)); */
- break;
- }
- }
-}
-
-
-
-/*
- * Start the next search on this handle right at the beginning
- */
-int
-keydb_search_reset (KEYDB_HANDLE hd)
-{
- int i, rc = 0;
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- hd->current = 0;
- hd->found = -1;
- /* and reset all resources */
- for (i=0; !rc && i < hd->used; i++)
- {
- switch (hd->active[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_search_reset (hd->active[i].u.kr);
- break;
- }
- }
- return rc; /* fixme: we need to map error codes or share them with
- all modules*/
-}
-
-/*
- * Search through all keydb resources, starting at the current position,
- * for a keyblock which contains one of the keys described in the DESC array.
- */
-int
-keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
-{
- int rc = -1;
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- while (rc == -1 && hd->current >= 0 && hd->current < hd->used)
- {
- switch (hd->active[hd->current].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- BUG(); /* we should never see it here */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc);
- break;
- }
- if (rc == -1) /* EOF -> switch to next resource */
- hd->current++;
- else if (!rc)
- hd->found = hd->current;
- }
-
- return rc;
-}
-
-
-int
-keydb_search_first (KEYDB_HANDLE hd)
-{
- KEYDB_SEARCH_DESC desc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_FIRST;
- return keydb_search (hd, &desc, 1);
-}
-
-int
-keydb_search_next (KEYDB_HANDLE hd)
-{
- KEYDB_SEARCH_DESC desc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_NEXT;
- return keydb_search (hd, &desc, 1);
-}
-
-int
-keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
-{
- KEYDB_SEARCH_DESC desc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
-/* desc.u.kid[0] = kid[0]; */
-/* desc.u.kid[1] = kid[1]; */
- return keydb_search (hd, &desc, 1);
-}
-
-int
-keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
-{
- KEYDB_SEARCH_DESC desc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_FPR;
- memcpy (desc.u.fpr, fpr, 20);
- return keydb_search (hd, &desc, 1);
-}
-
-int
-keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer)
-{
- KEYDB_SEARCH_DESC desc;
- int rc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_ISSUER;
- desc.u.name = issuer;
- rc = keydb_search (hd, &desc, 1);
- return rc;
-}
-
-int
-keydb_search_issuer_sn (KEYDB_HANDLE hd,
- const char *issuer, ksba_const_sexp_t serial)
-{
- KEYDB_SEARCH_DESC desc;
- int rc;
- const unsigned char *s;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_ISSUER_SN;
- s = serial;
- if (*s !='(')
- return gpg_error (GPG_ERR_INV_VALUE);
- s++;
- for (desc.snlen = 0; digitp (s); s++)
- desc.snlen = 10*desc.snlen + atoi_1 (s);
- if (*s !=':')
- return gpg_error (GPG_ERR_INV_VALUE);
- desc.sn = s+1;
- desc.u.name = issuer;
- rc = keydb_search (hd, &desc, 1);
- return rc;
-}
-
-int
-keydb_search_subject (KEYDB_HANDLE hd, const char *name)
-{
- KEYDB_SEARCH_DESC desc;
- int rc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_SUBJECT;
- desc.u.name = name;
- rc = keydb_search (hd, &desc, 1);
- return rc;
-}
-
-
-static int
-hextobyte (const unsigned char *s)
-{
- int c;
-
- if( *s >= '0' && *s <= '9' )
- c = 16 * (*s - '0');
- else if ( *s >= 'A' && *s <= 'F' )
- c = 16 * (10 + *s - 'A');
- else if ( *s >= 'a' && *s <= 'f' )
- c = 16 * (10 + *s - 'a');
- else
- return -1;
- s++;
- if ( *s >= '0' && *s <= '9' )
- c += *s - '0';
- else if ( *s >= 'A' && *s <= 'F' )
- c += 10 + *s - 'A';
- else if ( *s >= 'a' && *s <= 'f' )
- c += 10 + *s - 'a';
- else
- return -1;
- return c;
-}
-
-
-static int
-classify_user_id (const char *name,
- KEYDB_SEARCH_DESC *desc,
- int *force_exact )
-{
- const char *s;
- int hexprefix = 0;
- int hexlength;
- int mode = 0;
-
- /* clear the structure so that the mode field is set to zero unless
- * we set it to the correct value right at the end of this function */
- memset (desc, 0, sizeof *desc);
- *force_exact = 0;
- /* Skip leading spaces. Fixme: what about trailing white space? */
- for(s = name; *s && spacep (s); s++ )
- ;
-
- switch (*s)
- {
- case 0: /* empty string is an error */
- return 0;
-
- case '.': /* an email address, compare from end */
- mode = KEYDB_SEARCH_MODE_MAILEND;
- s++;
- desc->u.name = s;
- break;
-
- case '<': /* an email address */
- mode = KEYDB_SEARCH_MODE_MAIL;
- s++;
- desc->u.name = s;
- break;
-
- case '@': /* part of an email address */
- mode = KEYDB_SEARCH_MODE_MAILSUB;
- s++;
- desc->u.name = s;
- break;
-
- case '=': /* exact compare */
- mode = KEYDB_SEARCH_MODE_EXACT;
- s++;
- desc->u.name = s;
- break;
-
- case '*': /* case insensitive substring search */
- mode = KEYDB_SEARCH_MODE_SUBSTR;
- s++;
- desc->u.name = s;
- break;
-
- case '+': /* compare individual words */
- mode = KEYDB_SEARCH_MODE_WORDS;
- s++;
- desc->u.name = s;
- break;
-
- case '/': /* subject's DN */
- s++;
- if (!*s || spacep (s))
- return 0; /* no DN or prefixed with a space */
- desc->u.name = s;
- mode = KEYDB_SEARCH_MODE_SUBJECT;
- break;
-
- case '#':
- {
- const char *si;
-
- s++;
- if ( *s == '/')
- { /* "#/" indicates an issuer's DN */
- s++;
- if (!*s || spacep (s))
- return 0; /* no DN or prefixed with a space */
- desc->u.name = s;
- mode = KEYDB_SEARCH_MODE_ISSUER;
- }
- else
- { /* serialnumber + optional issuer ID */
- for (si=s; *si && *si != '/'; si++)
- {
- if (!strchr("01234567890abcdefABCDEF", *si))
- return 0; /* invalid digit in serial number*/
- }
- desc->sn = s;
- desc->snlen = -1;
- if (!*si)
- mode = KEYDB_SEARCH_MODE_SN;
- else
- {
- s = si+1;
- if (!*s || spacep (s))
- return 0; /* no DN or prefixed with a space */
- desc->u.name = s;
- mode = KEYDB_SEARCH_MODE_ISSUER_SN;
- }
- }
- }
- break;
-
- case ':': /*Unified fingerprint */
- {
- const char *se, *si;
- int i;
-
- se = strchr (++s,':');
- if (!se)
- return 0;
- for (i=0,si=s; si < se; si++, i++ )
- {
- if (!strchr("01234567890abcdefABCDEF", *si))
- return 0; /* invalid digit */
- }
- if (i != 32 && i != 40)
- return 0; /* invalid length of fpr*/
- for (i=0,si=s; si < se; i++, si +=2)
- desc->u.fpr[i] = hextobyte(si);
- for (; i < 20; i++)
- desc->u.fpr[i]= 0;
- s = se + 1;
- mode = KEYDB_SEARCH_MODE_FPR;
- }
- break;
-
- default:
- if (s[0] == '0' && s[1] == 'x')
- {
- hexprefix = 1;
- s += 2;
- }
-
- hexlength = strspn(s, "0123456789abcdefABCDEF");
- if (hexlength >= 8 && s[hexlength] =='!')
- {
- *force_exact = 1;
- hexlength++; /* just for the following check */
- }
-
- /* check if a hexadecimal number is terminated by EOS or blank */
- if (hexlength && s[hexlength] && !spacep (s+hexlength))
- {
- if (hexprefix) /* a "0x" prefix without correct */
- return 0; /* termination is an error */
- /* The first chars looked like a hex number, but really is
- not */
- hexlength = 0;
- }
-
- if (*force_exact)
- hexlength--; /* remove the bang */
-
- if (hexlength == 8
- || (!hexprefix && hexlength == 9 && *s == '0'))
- { /* short keyid */
- unsigned long kid;
- if (hexlength == 9)
- s++;
- kid = strtoul( s, NULL, 16 );
- desc->u.kid[4] = kid >> 24;
- desc->u.kid[5] = kid >> 16;
- desc->u.kid[6] = kid >> 8;
- desc->u.kid[7] = kid;
- mode = KEYDB_SEARCH_MODE_SHORT_KID;
- }
- else if (hexlength == 16
- || (!hexprefix && hexlength == 17 && *s == '0'))
- { /* complete keyid */
- unsigned long kid0, kid1;
- char buf[9];
- if (hexlength == 17)
- s++;
- mem2str(buf, s, 9 );
- kid0 = strtoul (buf, NULL, 16);
- kid1 = strtoul (s+8, NULL, 16);
- desc->u.kid[0] = kid0 >> 24;
- desc->u.kid[1] = kid0 >> 16;
- desc->u.kid[2] = kid0 >> 8;
- desc->u.kid[3] = kid0;
- desc->u.kid[4] = kid1 >> 24;
- desc->u.kid[5] = kid1 >> 16;
- desc->u.kid[6] = kid1 >> 8;
- desc->u.kid[7] = kid1;
- mode = KEYDB_SEARCH_MODE_LONG_KID;
- }
- else if (hexlength == 32
- || (!hexprefix && hexlength == 33 && *s == '0'))
- { /* md5 fingerprint */
- int i;
- if (hexlength == 33)
- s++;
- memset(desc->u.fpr+16, 0, 4);
- for (i=0; i < 16; i++, s+=2)
- {
- int c = hextobyte(s);
- if (c == -1)
- return 0;
- desc->u.fpr[i] = c;
- }
- mode = KEYDB_SEARCH_MODE_FPR16;
- }
- else if (hexlength == 40
- || (!hexprefix && hexlength == 41 && *s == '0'))
- { /* sha1/rmd160 fingerprint */
- int i;
- if (hexlength == 41)
- s++;
- for (i=0; i < 20; i++, s+=2)
- {
- int c = hextobyte(s);
- if (c == -1)
- return 0;
- desc->u.fpr[i] = c;
- }
- mode = KEYDB_SEARCH_MODE_FPR20;
- }
- else if (!hexprefix)
- {
- /* The fingerprint in an X.509 listing is often delimited by
- colons, so we try to single this case out. */
- mode = 0;
- hexlength = strspn (s, ":0123456789abcdefABCDEF");
- if (hexlength == 59 && (!s[hexlength] || spacep (s+hexlength)))
- {
- int i;
-
- for (i=0; i < 20; i++, s += 3)
- {
- int c = hextobyte(s);
- if (c == -1 || (i < 19 && s[2] != ':'))
- break;
- desc->u.fpr[i] = c;
- }
- if (i == 20)
- mode = KEYDB_SEARCH_MODE_FPR20;
- }
- if (!mode) /* default is substring search */
- {
- *force_exact = 0;
- desc->u.name = s;
- mode = KEYDB_SEARCH_MODE_SUBSTR;
- }
- }
- else
- { /* hex number with a prefix but a wrong length */
- return 0;
- }
- }
-
- desc->mode = mode;
- return mode;
-}
-
-
-int
-keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc)
-{
- int dummy;
- KEYDB_SEARCH_DESC dummy_desc;
-
- if (!desc)
- desc = &dummy_desc;
-
- if (!classify_user_id (name, desc, &dummy))
- return gpg_error (GPG_ERR_INV_NAME);
- return 0;
-}
-
-
-/* Store the certificate in the key DB but make sure that it does not
- already exists. We do this simply by comparing the fingerprint.
- If EXISTED is not NULL it will be set to true if the certificate
- was already in the DB. */
-int
-keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed)
-{
- KEYDB_HANDLE kh;
- int rc;
- unsigned char fpr[20];
-
- if (existed)
- *existed = 0;
-
- if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
- {
- log_error (_("failed to get the fingerprint\n"));
- return gpg_error (GPG_ERR_GENERAL);
- }
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error (_("failed to allocate keyDB handle\n"));
- return gpg_error (GPG_ERR_ENOMEM);;
- }
-
- if (ephemeral)
- keydb_set_ephemeral (kh, 1);
-
- rc = keydb_search_fpr (kh, fpr);
- if (rc != -1)
- {
- keydb_release (kh);
- if (!rc)
- {
- if (existed)
- *existed = 1;
- return 0; /* okay */
- }
- log_error (_("problem looking for existing certificate: %s\n"),
- gpg_strerror (rc));
- return rc;
- }
-
- rc = keydb_locate_writable (kh, 0);
- if (rc)
- {
- log_error (_("error finding writable keyDB: %s\n"), gpg_strerror (rc));
- keydb_release (kh);
- return rc;
- }
-
- rc = keydb_insert_cert (kh, cert);
- if (rc)
- {
- log_error (_("error storing certificate: %s\n"), gpg_strerror (rc));
- keydb_release (kh);
- return rc;
- }
- keydb_release (kh);
- return 0;
-}
-
-
-/* This is basically keydb_set_flags but it implements a complete
- transaction by locating the certificate in the DB and updating the
- flags. */
-gpg_error_t
-keydb_set_cert_flags (ksba_cert_t cert, int which, int idx, unsigned int value)
-{
- KEYDB_HANDLE kh;
- gpg_error_t err;
- unsigned char fpr[20];
- unsigned int old_value;
-
- if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
- {
- log_error (_("failed to get the fingerprint\n"));
- return gpg_error (GPG_ERR_GENERAL);
- }
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error (_("failed to allocate keyDB handle\n"));
- return gpg_error (GPG_ERR_ENOMEM);;
- }
-
- err = keydb_lock (kh);
- if (err)
- {
- log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
- keydb_release (kh);
- return err;
- }
-
- err = keydb_search_fpr (kh, fpr);
- if (err)
- {
- log_error (_("problem re-searching certificate: %s\n"),
- gpg_strerror (err));
- keydb_release (kh);
- return err;
- }
-
- err = keydb_get_flags (kh, which, idx, &old_value);
- if (err)
- {
- log_error (_("error getting stored flags: %s\n"), gpg_strerror (err));
- keydb_release (kh);
- return err;
- }
- if (value != old_value)
- {
- err = keydb_set_flags (kh, which, idx, value);
- if (err)
- {
- log_error (_("error storing flags: %s\n"), gpg_strerror (err));
- keydb_release (kh);
- return err;
- }
- }
- keydb_release (kh);
- return 0;
-}
-
-
-/* Reset all the certificate flags we have stored with the certificates
- for performance reasons. */
-void
-keydb_clear_some_cert_flags (ctrl_t ctrl, STRLIST names)
-{
- gpg_error_t err;
- KEYDB_HANDLE hd = NULL;
- KEYDB_SEARCH_DESC *desc = NULL;
- int ndesc;
- STRLIST sl;
- int rc=0;
- unsigned int old_value, value;
-
- hd = keydb_new (0);
- if (!hd)
- {
- log_error ("keydb_new failed\n");
- goto leave;
- }
-
- if (!names)
- ndesc = 1;
- else
- {
- for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
- ;
- }
-
- desc = xtrycalloc (ndesc, sizeof *desc);
- if (!ndesc)
- {
- log_error ("allocating memory failed: %s\n",
- gpg_strerror (OUT_OF_CORE (errno)));
- goto leave;
- }
-
- if (!names)
- desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
- else
- {
- for (ndesc=0, sl=names; sl; sl = sl->next)
- {
- rc = keydb_classify_name (sl->d, desc+ndesc);
- if (rc)
- {
- log_error ("key `%s' not found: %s\n",
- sl->d, gpg_strerror (rc));
- rc = 0;
- }
- else
- ndesc++;
- }
- }
-
- err = keydb_lock (hd);
- if (err)
- {
- log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
- goto leave;
- }
-
- while (!(rc = keydb_search (hd, desc, ndesc)))
- {
- if (!names)
- desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
-
- err = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &old_value);
- if (err)
- {
- log_error (_("error getting stored flags: %s\n"),
- gpg_strerror (err));
- goto leave;
- }
-
- value = (old_value & ~VALIDITY_REVOKED);
- if (value != old_value)
- {
- err = keydb_set_flags (hd, KEYBOX_FLAG_VALIDITY, 0, value);
- if (err)
- {
- log_error (_("error storing flags: %s\n"), gpg_strerror (err));
- goto leave;
- }
- }
- }
- if (rc && rc != -1)
- log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
-
- leave:
- xfree (desc);
- keydb_release (hd);
-}
-
-
diff --git a/sm/keydb.h b/sm/keydb.h
deleted file mode 100644
index 924ad77c4..000000000
--- a/sm/keydb.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* keydb.h - Key database
- * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef GNUPG_KEYDB_H
-#define GNUPG_KEYDB_H
-
-#include <ksba.h>
-
-#include "../kbx/keybox-search-desc.h"
-
-typedef struct keydb_handle *KEYDB_HANDLE;
-
-/* Flag value used with KEYBOX_FLAG_VALIDITY. */
-#define VALIDITY_REVOKED (1<<5)
-
-
-/*-- keydb.c --*/
-int keydb_add_resource (const char *url, int force, int secret);
-KEYDB_HANDLE keydb_new (int secret);
-void keydb_release (KEYDB_HANDLE hd);
-int keydb_set_ephemeral (KEYDB_HANDLE hd, int yes);
-const char *keydb_get_resource_name (KEYDB_HANDLE hd);
-gpg_error_t keydb_lock (KEYDB_HANDLE hd);
-
-#if 0 /* pgp stuff */
-int keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb);
-int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb);
-int keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb);
-#endif
-
-gpg_error_t keydb_get_flags (KEYDB_HANDLE hd, int which, int idx,
- unsigned int *value);
-gpg_error_t keydb_set_flags (KEYDB_HANDLE hd, int which, int idx,
- unsigned int value);
-int keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert);
-int keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert);
-int keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert);
-
-int keydb_delete (KEYDB_HANDLE hd);
-
-int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved);
-void keydb_rebuild_caches (void);
-
-int keydb_search_reset (KEYDB_HANDLE hd);
-int keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
-int keydb_search_first (KEYDB_HANDLE hd);
-int keydb_search_next (KEYDB_HANDLE hd);
-int keydb_search_kid (KEYDB_HANDLE hd, u32 *kid);
-int keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr);
-int keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer);
-int keydb_search_issuer_sn (KEYDB_HANDLE hd,
- const char *issuer, const unsigned char *serial);
-int keydb_search_subject (KEYDB_HANDLE hd, const char *issuer);
-
-int keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc);
-
-int keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed);
-gpg_error_t keydb_set_cert_flags (ksba_cert_t cert, int which, int idx,
- unsigned int value);
-
-void keydb_clear_some_cert_flags (ctrl_t ctrl, STRLIST names);
-
-
-#endif /*GNUPG_KEYDB_H*/
-
-
-
-
diff --git a/sm/keylist.c b/sm/keylist.c
deleted file mode 100644
index 27c67ded3..000000000
--- a/sm/keylist.c
+++ /dev/null
@@ -1,1252 +0,0 @@
-/* keylist.c
- * Copyright (C) 1998, 1999, 2000, 2001, 2003,
- * 2004 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
-#include "i18n.h"
-
-struct list_external_parm_s {
- ctrl_t ctrl;
- FILE *fp;
- int print_header;
- int with_colons;
- int with_chain;
- int raw_mode;
-};
-
-
-/* This table is to map Extended Key Usage OIDs to human readable
- names. */
-struct {
- const char *oid;
- const char *name;
-} key_purpose_map[] = {
- { "1.3.6.1.5.5.7.3.1", "serverAuth" },
- { "1.3.6.1.5.5.7.3.2", "clientAuth" },
- { "1.3.6.1.5.5.7.3.3", "codeSigning" },
- { "1.3.6.1.5.5.7.3.4", "emailProtection" },
- { "1.3.6.1.5.5.7.3.5", "ipsecEndSystem" },
- { "1.3.6.1.5.5.7.3.6", "ipsecTunnel" },
- { "1.3.6.1.5.5.7.3.7", "ipsecUser" },
- { "1.3.6.1.5.5.7.3.8", "timeStamping" },
- { "1.3.6.1.5.5.7.3.9", "ocspSigning" },
- { "1.3.6.1.5.5.7.3.10", "dvcs" },
- { "1.3.6.1.5.5.7.3.11", "sbgpCertAAServerAuth" },
- { "1.3.6.1.5.5.7.3.13", "eapOverPPP" },
- { "1.3.6.1.5.5.7.3.14", "wlanSSID" },
- { NULL, NULL }
-};
-
-
-/* A table mapping OIDs to a descriptive string. */
-static struct {
- char *oid;
- char *name;
- unsigned int flag;
-} oidtranstbl[] = {
-
- /* Algorithms. */
- { "1.2.840.10040.4.1", "dsa" },
- { "1.2.840.10040.4.3", "dsaWithSha1" },
-
- { "1.2.840.113549.1.1.1", "rsaEncryption" },
- { "1.2.840.113549.1.1.2", "md2WithRSAEncryption" },
- { "1.2.840.113549.1.1.3", "md4WithRSAEncryption" },
- { "1.2.840.113549.1.1.4", "md5WithRSAEncryption" },
- { "1.2.840.113549.1.1.5", "sha1WithRSAEncryption" },
- { "1.2.840.113549.1.1.7", "rsaOAEP" },
- { "1.2.840.113549.1.1.8", "rsaOAEP-MGF" },
- { "1.2.840.113549.1.1.9", "rsaOAEP-pSpecified" },
- { "1.2.840.113549.1.1.10", "rsaPSS" },
- { "1.2.840.113549.1.1.11", "sha256WithRSAEncryption" },
- { "1.2.840.113549.1.1.12", "sha384WithRSAEncryption" },
- { "1.2.840.113549.1.1.13", "sha512WithRSAEncryption" },
-
- { "1.3.14.3.2.26", "sha1" },
- { "1.3.14.3.2.29", "sha-1WithRSAEncryption" },
- { "1.3.36.3.3.1.2", "rsaSignatureWithripemd160" },
-
-
- /* Telesec extensions. */
- { "0.2.262.1.10.12.0", "certExtensionLiabilityLimitationExt" },
- { "0.2.262.1.10.12.1", "telesecCertIdExt" },
- { "0.2.262.1.10.12.2", "telesecPolicyIdentifier" },
- { "0.2.262.1.10.12.3", "telesecPolicyQualifierID" },
- { "0.2.262.1.10.12.4", "telesecCRLFilteredExt" },
- { "0.2.262.1.10.12.5", "telesecCRLFilterExt"},
- { "0.2.262.1.10.12.6", "telesecNamingAuthorityExt" },
-
- /* PKIX private extensions. */
- { "1.3.6.1.5.5.7.1.1", "authorityInfoAccess" },
- { "1.3.6.1.5.5.7.1.2", "biometricInfo" },
- { "1.3.6.1.5.5.7.1.3", "qcStatements" },
- { "1.3.6.1.5.5.7.1.4", "acAuditIdentity" },
- { "1.3.6.1.5.5.7.1.5", "acTargeting" },
- { "1.3.6.1.5.5.7.1.6", "acAaControls" },
- { "1.3.6.1.5.5.7.1.7", "sbgp-ipAddrBlock" },
- { "1.3.6.1.5.5.7.1.8", "sbgp-autonomousSysNum" },
- { "1.3.6.1.5.5.7.1.9", "sbgp-routerIdentifier" },
- { "1.3.6.1.5.5.7.1.10", "acProxying" },
- { "1.3.6.1.5.5.7.1.11", "subjectInfoAccess" },
-
- /* X.509 id-ce */
- { "2.5.29.14", "subjectKeyIdentifier"},
- { "2.5.29.15", "keyUsage", 1 },
- { "2.5.29.16", "privateKeyUsagePeriod" },
- { "2.5.29.17", "subjectAltName", 1 },
- { "2.5.29.18", "issuerAltName", 1 },
- { "2.5.29.19", "basicConstraints", 1},
- { "2.5.29.20", "cRLNumber" },
- { "2.5.29.21", "cRLReason" },
- { "2.5.29.22", "expirationDate" },
- { "2.5.29.23", "instructionCode" },
- { "2.5.29.24", "invalidityDate" },
- { "2.5.29.27", "deltaCRLIndicator" },
- { "2.5.29.28", "issuingDistributionPoint" },
- { "2.5.29.29", "certificateIssuer" },
- { "2.5.29.30", "nameConstraints" },
- { "2.5.29.31", "cRLDistributionPoints", 1 },
- { "2.5.29.32", "certificatePolicies", 1 },
- { "2.5.29.32.0", "anyPolicy" },
- { "2.5.29.33", "policyMappings" },
- { "2.5.29.35", "authorityKeyIdentifier", 1 },
- { "2.5.29.36", "policyConstraints" },
- { "2.5.29.37", "extKeyUsage", 1 },
- { "2.5.29.46", "freshestCRL" },
- { "2.5.29.54", "inhibitAnyPolicy" },
-
- /* Netscape certificate extensions. */
- { "2.16.840.1.113730.1.1", "netscape-cert-type" },
- { "2.16.840.1.113730.1.2", "netscape-base-url" },
- { "2.16.840.1.113730.1.3", "netscape-revocation-url" },
- { "2.16.840.1.113730.1.4", "netscape-ca-revocation-url" },
- { "2.16.840.1.113730.1.7", "netscape-cert-renewal-url" },
- { "2.16.840.1.113730.1.8", "netscape-ca-policy-url" },
- { "2.16.840.1.113730.1.9", "netscape-homePage-url" },
- { "2.16.840.1.113730.1.10", "netscape-entitylogo" },
- { "2.16.840.1.113730.1.11", "netscape-userPicture" },
- { "2.16.840.1.113730.1.12", "netscape-ssl-server-name" },
- { "2.16.840.1.113730.1.13", "netscape-comment" },
-
- { NULL }
-};
-
-
-/* Return the description for OID; if no description is available
- NULL is returned. */
-static const char *
-get_oid_desc (const char *oid, unsigned int *flag)
-{
- int i;
-
- if (oid)
- for (i=0; oidtranstbl[i].oid; i++)
- if (!strcmp (oidtranstbl[i].oid, oid))
- {
- if (flag)
- *flag = oidtranstbl[i].flag;
- return oidtranstbl[i].name;
- }
- if (flag)
- *flag = 0;
- return NULL;
-}
-
-
-static void
-print_key_data (ksba_cert_t cert, FILE *fp)
-{
-#if 0
- int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
- int i;
-
- for(i=0; i < n; i++ )
- {
- fprintf (fp, "pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
- mpi_print(stdout, pk->pkey[i], 1 );
- putchar(':');
- putchar('\n');
- }
-#endif
-}
-
-static void
-print_capabilities (ksba_cert_t cert, FILE *fp)
-{
- gpg_error_t err;
- unsigned int use;
-
- err = ksba_cert_get_key_usage (cert, &use);
- if (gpg_err_code (err) == GPG_ERR_NO_DATA)
- {
- putc ('e', fp);
- putc ('s', fp);
- putc ('c', fp);
- putc ('E', fp);
- putc ('S', fp);
- putc ('C', fp);
- return;
- }
- if (err)
- {
- log_error (_("error getting key usage information: %s\n"),
- gpg_strerror (err));
- return;
- }
-
- if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
- putc ('e', fp);
- if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
- putc ('s', fp);
- if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
- putc ('c', fp);
- if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
- putc ('E', fp);
- if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
- putc ('S', fp);
- if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
- putc ('C', fp);
-}
-
-
-static void
-print_time (gnupg_isotime_t t, FILE *fp)
-{
- if (!t || !*t)
- ;
- else
- fputs (t, fp);
-}
-
-
-/* return an allocated string with the email address extracted from a
- DN */
-static char *
-email_kludge (const char *name)
-{
- const unsigned char *p;
- unsigned char *buf;
- int n;
-
- if (strncmp (name, "1.2.840.113549.1.9.1=#", 22))
- return NULL;
- /* This looks pretty much like an email address in the subject's DN
- we use this to add an additional user ID entry. This way,
- openSSL generated keys get a nicer and usable listing */
- name += 22;
- for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
- ;
- if (*p != '#' || !n)
- return NULL;
- buf = xtrymalloc (n+3);
- if (!buf)
- return NULL; /* oops, out of core */
- *buf = '<';
- for (n=1, p=name; *p != '#'; p +=2, n++)
- buf[n] = xtoi_2 (p);
- buf[n++] = '>';
- buf[n] = 0;
- return buf;
-}
-
-
-
-
-/* List one certificate in colon mode */
-static void
-list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
- FILE *fp, int have_secret)
-{
- int rc;
- int idx;
- char truststring[2];
- char *p;
- ksba_sexp_t sexp;
- char *fpr;
- ksba_isotime_t t;
- gpg_error_t valerr;
- int algo;
- unsigned int nbits;
- const char *chain_id;
- char *chain_id_buffer = NULL;
- int is_root = 0;
-
- if (ctrl->with_validation)
- valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL, 0);
- else
- valerr = 0;
-
-
- /* We need to get the fingerprint and the chaining ID in advance. */
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- {
- ksba_cert_t next;
-
- rc = gpgsm_walk_cert_chain (cert, &next);
- if (!rc) /* We known the issuer's certificate. */
- {
- p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1);
- chain_id_buffer = p;
- chain_id = chain_id_buffer;
- ksba_cert_release (next);
- }
- else if (rc == -1) /* We have reached the root certificate. */
- {
- chain_id = fpr;
- is_root = 1;
- }
- else
- chain_id = NULL;
- }
-
-
- fputs (have_secret? "crs:":"crt:", fp);
- truststring[0] = 0;
- truststring[1] = 0;
- if ((validity & VALIDITY_REVOKED)
- || gpg_err_code (valerr) == GPG_ERR_CERT_REVOKED)
- *truststring = 'r';
- else if (gpg_err_code (valerr) == GPG_ERR_CERT_EXPIRED)
- *truststring = 'e';
- else if (valerr)
- *truststring = 'i';
- else
- {
- /* Lets also check whether the certificate under question
- expired. This is merely a hack until we found a proper way
- to store the expiration flag in the keybox. */
- ksba_isotime_t current_time, not_after;
-
- gnupg_get_isotime (current_time);
- if (!opt.ignore_expiration
- && !ksba_cert_get_validity (cert, 1, not_after)
- && *not_after && strcmp (current_time, not_after) > 0 )
- *truststring = 'e';
- }
-
- /* Is we have no truststring yet (i.e. the certificate might be
- good) and this is a root certificate, we ask the agent whether
- this is a trusted root certificate. */
- if (!*truststring && is_root)
- {
- rc = gpgsm_agent_istrusted (ctrl, cert);
- if (!rc)
- *truststring = 'u'; /* Yes, we trust this one (ultimately). */
- else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
- *truststring = 'n'; /* No, we do not trust this one. */
- /* (in case of an error we can't tell anything.) */
- }
-
- if (*truststring)
- fputs (truststring, fp);
-
- algo = gpgsm_get_key_algo_info (cert, &nbits);
- fprintf (fp, ":%u:%d:%s:", nbits, algo, fpr+24);
-
- /* We assume --fixed-list-mode for gpgsm */
- ksba_cert_get_validity (cert, 0, t);
- print_time (t, fp);
- putc (':', fp);
- ksba_cert_get_validity (cert, 1, t);
- print_time ( t, fp);
- putc (':', fp);
- /* Field 8, serial number: */
- if ((sexp = ksba_cert_get_serial (cert)))
- {
- int len;
- const unsigned char *s = sexp;
-
- if (*s == '(')
- {
- s++;
- for (len=0; *s && *s != ':' && digitp (s); s++)
- len = len*10 + atoi_1 (s);
- if (*s == ':')
- for (s++; len; len--, s++)
- fprintf (fp,"%02X", *s);
- }
- xfree (sexp);
- }
- putc (':', fp);
- /* Field 9, ownertrust - not used here */
- putc (':', fp);
- /* field 10, old user ID - we use it here for the issuer DN */
- if ((p = ksba_cert_get_issuer (cert,0)))
- {
- print_sanitized_string (fp, p, ':');
- xfree (p);
- }
- putc (':', fp);
- /* Field 11, signature class - not used */
- putc (':', fp);
- /* Field 12, capabilities: */
- print_capabilities (cert, fp);
- putc (':', fp);
- putc ('\n', fp);
-
- /* FPR record */
- fprintf (fp, "fpr:::::::::%s:::", fpr);
- /* Print chaining ID (field 13)*/
- if (chain_id)
- fputs (chain_id, fp);
- putc (':', fp);
- putc ('\n', fp);
- xfree (fpr); fpr = NULL; chain_id = NULL;
- xfree (chain_id_buffer); chain_id_buffer = NULL;
-
- if (opt.with_key_data)
- {
- if ( (p = gpgsm_get_keygrip_hexstring (cert)))
- {
- fprintf (fp, "grp:::::::::%s:\n", p);
- xfree (p);
- }
- print_key_data (cert, fp);
- }
-
- for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
- {
- fprintf (fp, "uid:%s::::::::", truststring);
- print_sanitized_string (fp, p, ':');
- putc (':', fp);
- putc (':', fp);
- putc ('\n', fp);
- if (!idx)
- {
- /* It would be better to get the faked email address from
- the keydb. But as long as we don't have a way to pass
- the meta data back, we just check it the same way as the
- code used to create the keybox meta data does */
- char *pp = email_kludge (p);
- if (pp)
- {
- fprintf (fp, "uid:%s::::::::", truststring);
- print_sanitized_string (fp, pp, ':');
- putc (':', fp);
- putc (':', fp);
- putc ('\n', fp);
- xfree (pp);
- }
- }
- xfree (p);
- }
-}
-
-
-static void
-print_name_raw (FILE *fp, const char *string)
-{
- if (!string)
- fputs ("[error]", fp);
- else
- print_sanitized_string (fp, string, 0);
-}
-
-static void
-print_names_raw (FILE *fp, int indent, ksba_name_t name)
-{
- int idx;
- const char *s;
- int indent_all;
-
- if ((indent_all = (indent < 0)))
- indent = - indent;
-
- if (!name)
- {
- fputs ("none\n", fp);
- return;
- }
-
- for (idx=0; (s = ksba_name_enum (name, idx)); idx++)
- {
- char *p = ksba_name_get_uri (name, idx);
- printf ("%*s%s\n", idx||indent_all?indent:0, "", p?p:s);
- xfree (p);
- }
-}
-
-
-/* List one certificate in raw mode useful to have a closer look at
- the certificate. This one does not beautification and only minimal
- output sanitation. It is mainly useful for debugging. */
-static void
-list_cert_raw (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret,
- int with_validation)
-{
- gpg_error_t err;
- size_t off, len;
- ksba_sexp_t sexp;
- char *dn;
- ksba_isotime_t t;
- int idx, i;
- int is_ca, chainlen;
- unsigned int kusage;
- char *string, *p, *pend;
- const char *oid, *s;
- ksba_name_t name, name2;
- unsigned int reason;
-
- sexp = ksba_cert_get_serial (cert);
- fputs ("Serial number: ", fp);
- gpgsm_print_serial (fp, sexp);
- ksba_free (sexp);
- putc ('\n', fp);
-
- dn = ksba_cert_get_issuer (cert, 0);
- fputs (" Issuer: ", fp);
- print_name_raw (fp, dn);
- ksba_free (dn);
- putc ('\n', fp);
- for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
- {
- fputs (" aka: ", fp);
- print_name_raw (fp, dn);
- ksba_free (dn);
- putc ('\n', fp);
- }
-
- dn = ksba_cert_get_subject (cert, 0);
- fputs (" Subject: ", fp);
- print_name_raw (fp, dn);
- ksba_free (dn);
- putc ('\n', fp);
- for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
- {
- fputs (" aka: ", fp);
- print_name_raw (fp, dn);
- ksba_free (dn);
- putc ('\n', fp);
- }
-
- dn = gpgsm_get_fingerprint_string (cert, 0);
- fprintf (fp, " sha1_fpr: %s\n", dn?dn:"error");
- xfree (dn);
-
- dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
- fprintf (fp, " md5_fpr: %s\n", dn?dn:"error");
- xfree (dn);
-
- ksba_cert_get_validity (cert, 0, t);
- fputs (" notBefore: ", fp);
- gpgsm_print_time (fp, t);
- putc ('\n', fp);
- fputs (" notAfter: ", fp);
- ksba_cert_get_validity (cert, 1, t);
- gpgsm_print_time (fp, t);
- putc ('\n', fp);
-
- oid = ksba_cert_get_digest_algo (cert);
- s = get_oid_desc (oid, NULL);
- fprintf (fp, " hashAlgo: %s%s%s%s\n", oid, s?" (":"",s?s:"",s?")":"");
-
- {
- const char *algoname;
- unsigned int nbits;
-
- algoname = gcry_pk_algo_name (gpgsm_get_key_algo_info (cert, &nbits));
- fprintf (fp, " keyType: %u bit %s\n", nbits, algoname? algoname:"?");
- }
-
- /* authorityKeyIdentifier */
- fputs (" authKeyId: ", fp);
- err = ksba_cert_get_auth_key_id (cert, NULL, &name, &sexp);
- if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
- {
- if (gpg_err_code (err) == GPG_ERR_NO_DATA || !name)
- fputs ("[none]\n", fp);
- else
- {
- gpgsm_print_serial (fp, sexp);
- ksba_free (sexp);
- putc ('\n', fp);
- print_names_raw (fp, -15, name);
- ksba_name_release (name);
- }
- }
- else
- fputs ("[?]\n", fp);
-
- fputs (" keyUsage:", fp);
- err = ksba_cert_get_key_usage (cert, &kusage);
- if (gpg_err_code (err) != GPG_ERR_NO_DATA)
- {
- if (err)
- fprintf (fp, " [error: %s]", gpg_strerror (err));
- else
- {
- if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
- fputs (" digitalSignature", fp);
- if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))
- fputs (" nonRepudiation", fp);
- if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
- fputs (" keyEncipherment", fp);
- if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
- fputs (" dataEncipherment", fp);
- if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))
- fputs (" keyAgreement", fp);
- if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
- fputs (" certSign", fp);
- if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))
- fputs (" crlSign", fp);
- if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
- fputs (" encipherOnly", fp);
- if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))
- fputs (" decipherOnly", fp);
- }
- putc ('\n', fp);
- }
- else
- fputs ("[none]\n", fp);
-
- fputs (" extKeyUsage: ", fp);
- err = ksba_cert_get_ext_key_usages (cert, &string);
- if (gpg_err_code (err) != GPG_ERR_NO_DATA)
- {
- if (err)
- fprintf (fp, "[error: %s]", gpg_strerror (err));
- else
- {
- p = string;
- while (p && (pend=strchr (p, ':')))
- {
- *pend++ = 0;
- for (i=0; key_purpose_map[i].oid; i++)
- if ( !strcmp (key_purpose_map[i].oid, p) )
- break;
- fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
- p = pend;
- if (*p != 'C')
- fputs (" (suggested)", fp);
- if ((p = strchr (p, '\n')))
- {
- p++;
- fputs ("\n ", fp);
- }
- }
- xfree (string);
- }
- putc ('\n', fp);
- }
- else
- fputs ("[none]\n", fp);
-
-
- fputs (" policies: ", fp);
- err = ksba_cert_get_cert_policies (cert, &string);
- if (gpg_err_code (err) != GPG_ERR_NO_DATA)
- {
- if (err)
- fprintf (fp, "[error: %s]", gpg_strerror (err));
- else
- {
- p = string;
- while (p && (pend=strchr (p, ':')))
- {
- *pend++ = 0;
- for (i=0; key_purpose_map[i].oid; i++)
- if ( !strcmp (key_purpose_map[i].oid, p) )
- break;
- fputs (p, fp);
- p = pend;
- if (*p == 'C')
- fputs (" (critical)", fp);
- if ((p = strchr (p, '\n')))
- {
- p++;
- fputs ("\n ", fp);
- }
- }
- xfree (string);
- }
- putc ('\n', fp);
- }
- else
- fputs ("[none]\n", fp);
-
- fputs (" chainLength: ", fp);
- err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
- if (err || is_ca)
- {
- if (err)
- fprintf (fp, "[error: %s]", gpg_strerror (err));
- else if (chainlen == -1)
- fputs ("unlimited", fp);
- else
- fprintf (fp, "%d", chainlen);
- putc ('\n', fp);
- }
- else
- fputs ("not a CA\n", fp);
-
-
- /* CRL distribution point */
- for (idx=0; !(err=ksba_cert_get_crl_dist_point (cert, idx, &name, &name2,
- &reason)) ;idx++)
- {
- fputs (" crlDP: ", fp);
- print_names_raw (fp, 15, name);
- if (reason)
- {
- fputs (" reason: ", fp);
- if ( (reason & KSBA_CRLREASON_UNSPECIFIED))
- fputs (" unused", stdout);
- if ( (reason & KSBA_CRLREASON_KEY_COMPROMISE))
- fputs (" keyCompromise", stdout);
- if ( (reason & KSBA_CRLREASON_CA_COMPROMISE))
- fputs (" caCompromise", stdout);
- if ( (reason & KSBA_CRLREASON_AFFILIATION_CHANGED))
- fputs (" affiliationChanged", stdout);
- if ( (reason & KSBA_CRLREASON_SUPERSEDED))
- fputs (" superseded", stdout);
- if ( (reason & KSBA_CRLREASON_CESSATION_OF_OPERATION))
- fputs (" cessationOfOperation", stdout);
- if ( (reason & KSBA_CRLREASON_CERTIFICATE_HOLD))
- fputs (" certificateHold", stdout);
- putchar ('\n');
- }
- fputs (" issuer: ", fp);
- print_names_raw (fp, 23, name2);
- ksba_name_release (name);
- ksba_name_release (name2);
- }
- if (err && gpg_err_code (err) != GPG_ERR_EOF)
- fputs (" crlDP: [error]\n", fp);
- else if (!idx)
- fputs (" crlDP: [none]\n", fp);
-
-
- /* authorityInfoAccess. */
- for (idx=0; !(err=ksba_cert_get_authority_info_access (cert, idx, &string,
- &name)); idx++)
- {
- fputs (" authInfo: ", fp);
- s = get_oid_desc (string, NULL);
- fprintf (fp, "%s%s%s%s\n", string, s?" (":"", s?s:"", s?")":"");
- print_names_raw (fp, -15, name);
- ksba_name_release (name);
- ksba_free (string);
- }
- if (err && gpg_err_code (err) != GPG_ERR_EOF)
- fputs (" authInfo: [error]\n", fp);
- else if (!idx)
- fputs (" authInfo: [none]\n", fp);
-
- /* subjectInfoAccess. */
- for (idx=0; !(err=ksba_cert_get_subject_info_access (cert, idx, &string,
- &name)); idx++)
- {
- fputs (" subjectInfo: ", fp);
- s = get_oid_desc (string, NULL);
- fprintf (fp, "%s%s%s%s\n", string, s?" (":"", s?s:"", s?")":"");
- print_names_raw (fp, -15, name);
- ksba_name_release (name);
- ksba_free (string);
- }
- if (err && gpg_err_code (err) != GPG_ERR_EOF)
- fputs (" subjInfo: [error]\n", fp);
- else if (!idx)
- fputs (" subjInfo: [none]\n", fp);
-
-
- for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
- &oid, &i, &off, &len));idx++)
- {
- unsigned int flag;
-
- s = get_oid_desc (oid, &flag);
-
- if (!(flag & 1))
- fprintf (fp, " %s: %s%s%s%s [%d octets]\n",
- i? "critExtn":" extn",
- oid, s?" (":"", s?s:"", s?")":"", (int)len);
- }
-
-
- if (with_validation)
- {
- err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0);
- if (!err)
- fprintf (fp, " [certificate is good]\n");
- else
- fprintf (fp, " [certificate is bad: %s]\n", gpg_strerror (err));
- }
-}
-
-
-
-
-/* List one certificate in standard mode */
-static void
-list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret,
- int with_validation)
-{
- gpg_error_t err;
- ksba_sexp_t sexp;
- char *dn;
- ksba_isotime_t t;
- int idx, i;
- int is_ca, chainlen;
- unsigned int kusage;
- char *string, *p, *pend;
-
- sexp = ksba_cert_get_serial (cert);
- fputs ("Serial number: ", fp);
- gpgsm_print_serial (fp, sexp);
- ksba_free (sexp);
- putc ('\n', fp);
-
- dn = ksba_cert_get_issuer (cert, 0);
- fputs (" Issuer: ", fp);
- gpgsm_print_name (fp, dn);
- ksba_free (dn);
- putc ('\n', fp);
- for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
- {
- fputs (" aka: ", fp);
- gpgsm_print_name (fp, dn);
- ksba_free (dn);
- putc ('\n', fp);
- }
-
- dn = ksba_cert_get_subject (cert, 0);
- fputs (" Subject: ", fp);
- gpgsm_print_name (fp, dn);
- ksba_free (dn);
- putc ('\n', fp);
- for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
- {
- fputs (" aka: ", fp);
- gpgsm_print_name (fp, dn);
- ksba_free (dn);
- putc ('\n', fp);
- }
-
- ksba_cert_get_validity (cert, 0, t);
- fputs (" validity: ", fp);
- gpgsm_print_time (fp, t);
- fputs (" through ", fp);
- ksba_cert_get_validity (cert, 1, t);
- gpgsm_print_time (fp, t);
- putc ('\n', fp);
-
-
- {
- const char *algoname;
- unsigned int nbits;
-
- algoname = gcry_pk_algo_name (gpgsm_get_key_algo_info (cert, &nbits));
- fprintf (fp, " key type: %u bit %s\n", nbits, algoname? algoname:"?");
- }
-
-
- err = ksba_cert_get_key_usage (cert, &kusage);
- if (gpg_err_code (err) != GPG_ERR_NO_DATA)
- {
- fputs (" key usage:", fp);
- if (err)
- fprintf (fp, " [error: %s]", gpg_strerror (err));
- else
- {
- if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
- fputs (" digitalSignature", fp);
- if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))
- fputs (" nonRepudiation", fp);
- if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
- fputs (" keyEncipherment", fp);
- if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
- fputs (" dataEncipherment", fp);
- if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))
- fputs (" keyAgreement", fp);
- if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
- fputs (" certSign", fp);
- if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))
- fputs (" crlSign", fp);
- if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
- fputs (" encipherOnly", fp);
- if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))
- fputs (" decipherOnly", fp);
- }
- putc ('\n', fp);
- }
-
- err = ksba_cert_get_ext_key_usages (cert, &string);
- if (gpg_err_code (err) != GPG_ERR_NO_DATA)
- {
- fputs ("ext key usage: ", fp);
- if (err)
- fprintf (fp, "[error: %s]", gpg_strerror (err));
- else
- {
- p = string;
- while (p && (pend=strchr (p, ':')))
- {
- *pend++ = 0;
- for (i=0; key_purpose_map[i].oid; i++)
- if ( !strcmp (key_purpose_map[i].oid, p) )
- break;
- fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
- p = pend;
- if (*p != 'C')
- fputs (" (suggested)", fp);
- if ((p = strchr (p, '\n')))
- {
- p++;
- fputs (", ", fp);
- }
- }
- xfree (string);
- }
- putc ('\n', fp);
- }
-
- err = ksba_cert_get_cert_policies (cert, &string);
- if (gpg_err_code (err) != GPG_ERR_NO_DATA)
- {
- fputs (" policies: ", fp);
- if (err)
- fprintf (fp, "[error: %s]", gpg_strerror (err));
- else
- {
- for (p=string; *p; p++)
- {
- if (*p == '\n')
- *p = ',';
- }
- print_sanitized_string (fp, string, 0);
- xfree (string);
- }
- putc ('\n', fp);
- }
-
- err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
- if (err || is_ca)
- {
- fputs (" chain length: ", fp);
- if (err)
- fprintf (fp, "[error: %s]", gpg_strerror (err));
- else if (chainlen == -1)
- fputs ("unlimited", fp);
- else
- fprintf (fp, "%d", chainlen);
- putc ('\n', fp);
- }
-
- if (opt.with_md5_fingerprint)
- {
- dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
- fprintf (fp, " md5 fpr: %s\n", dn?dn:"error");
- xfree (dn);
- }
-
- dn = gpgsm_get_fingerprint_string (cert, 0);
- fprintf (fp, " fingerprint: %s\n", dn?dn:"error");
- xfree (dn);
-
- if (with_validation)
- {
- err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0);
- if (!err)
- fprintf (fp, " [certificate is good]\n");
- else
- fprintf (fp, " [certificate is bad: %s]\n", gpg_strerror (err));
- }
-}
-
-
-/* Same as standard mode mode list all certifying certs too. */
-static void
-list_cert_chain (ctrl_t ctrl, ksba_cert_t cert, int raw_mode,
- FILE *fp, int with_validation)
-{
- ksba_cert_t next = NULL;
-
- if (raw_mode)
- list_cert_raw (ctrl, cert, fp, 0, with_validation);
- else
- list_cert_std (ctrl, cert, fp, 0, with_validation);
- ksba_cert_ref (cert);
- while (!gpgsm_walk_cert_chain (cert, &next))
- {
- ksba_cert_release (cert);
- fputs ("Certified by\n", fp);
- if (raw_mode)
- list_cert_raw (ctrl, next, fp, 0, with_validation);
- else
- list_cert_std (ctrl, next, fp, 0, with_validation);
- cert = next;
- }
- ksba_cert_release (cert);
- putc ('\n', fp);
-}
-
-
-
-/* List all internal keys or just the keys given as NAMES. MODE is a
- bit vector to specify what keys are to be included; see
- gpgsm_list_keys (below) for details. If RAW_MODE is true, the raw
- output mode will be used intead of the standard beautified one.
- */
-static gpg_error_t
-list_internal_keys (ctrl_t ctrl, STRLIST names, FILE *fp,
- unsigned int mode, int raw_mode)
-{
- KEYDB_HANDLE hd;
- KEYDB_SEARCH_DESC *desc = NULL;
- STRLIST sl;
- int ndesc;
- ksba_cert_t cert = NULL;
- gpg_error_t rc = 0;
- const char *lastresname, *resname;
- int have_secret;
-
- hd = keydb_new (0);
- if (!hd)
- {
- log_error ("keydb_new failed\n");
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- if (!names)
- ndesc = 1;
- else
- {
- for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
- ;
- }
-
- desc = xtrycalloc (ndesc, sizeof *desc);
- if (!ndesc)
- {
- rc = gpg_error_from_errno (errno);
- log_error ("out of core\n");
- goto leave;
- }
-
- if (!names)
- desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
- else
- {
- for (ndesc=0, sl=names; sl; sl = sl->next)
- {
- rc = keydb_classify_name (sl->d, desc+ndesc);
- if (rc)
- {
- log_error ("key `%s' not found: %s\n",
- sl->d, gpg_strerror (rc));
- rc = 0;
- }
- else
- ndesc++;
- }
-
- }
-
- /* It would be nice to see which of the given users did actually
- match one in the keyring. To implement this we need to have a
- found flag for each entry in desc and to set this we must check
- all those entries after a match to mark all matched one -
- currently we stop at the first match. To do this we need an
- extra flag to enable this feature so */
-
- lastresname = NULL;
- while (!(rc = keydb_search (hd, desc, ndesc)))
- {
- unsigned int validity;
-
- if (!names)
- desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
-
- rc = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &validity);
- if (rc)
- {
- log_error ("keydb_get_flags failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- rc = keydb_get_cert (hd, &cert);
- if (rc)
- {
- log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- resname = keydb_get_resource_name (hd);
-
- if (lastresname != resname )
- {
- int i;
-
- if (ctrl->no_server)
- {
- fprintf (fp, "%s\n", resname );
- for (i=strlen(resname); i; i-- )
- putchar('-');
- putc ('\n', fp);
- lastresname = resname;
- }
- }
-
- have_secret = 0;
- if (mode)
- {
- char *p = gpgsm_get_keygrip_hexstring (cert);
- if (p)
- {
- rc = gpgsm_agent_havekey (ctrl, p);
- if (!rc)
- have_secret = 1;
- else if ( gpg_err_code (rc) != GPG_ERR_NO_SECKEY)
- goto leave;
- rc = 0;
- xfree (p);
- }
- }
-
- if (!mode
- || ((mode & 1) && !have_secret)
- || ((mode & 2) && have_secret) )
- {
- if (ctrl->with_colons)
- list_cert_colon (ctrl, cert, validity, fp, have_secret);
- else if (ctrl->with_chain)
- list_cert_chain (ctrl, cert, raw_mode, fp, ctrl->with_validation);
- else
- {
- if (raw_mode)
- list_cert_raw (ctrl, cert, fp, have_secret,
- ctrl->with_validation);
- else
- list_cert_std (ctrl, cert, fp, have_secret,
- ctrl->with_validation);
- putc ('\n', fp);
- }
- }
- ksba_cert_release (cert);
- cert = NULL;
- }
- if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1 )
- rc = 0;
- if (rc)
- log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
-
- leave:
- ksba_cert_release (cert);
- xfree (desc);
- keydb_release (hd);
- return rc;
-}
-
-
-
-static void
-list_external_cb (void *cb_value, ksba_cert_t cert)
-{
- struct list_external_parm_s *parm = cb_value;
-
- if (keydb_store_cert (cert, 1, NULL))
- log_error ("error storing certificate as ephemeral\n");
-
- if (parm->print_header)
- {
- const char *resname = "[external keys]";
- int i;
-
- fprintf (parm->fp, "%s\n", resname );
- for (i=strlen(resname); i; i-- )
- putchar('-');
- putc ('\n', parm->fp);
- parm->print_header = 0;
- }
-
- if (parm->with_colons)
- list_cert_colon (parm->ctrl, cert, 0, parm->fp, 0);
- else if (parm->with_chain)
- list_cert_chain (parm->ctrl, cert, parm->raw_mode, parm->fp, 0);
- else
- {
- if (parm->raw_mode)
- list_cert_raw (parm->ctrl, cert, parm->fp, 0, 0);
- else
- list_cert_std (parm->ctrl, cert, parm->fp, 0, 0);
- putc ('\n', parm->fp);
- }
-}
-
-
-/* List external keys similar to internal one. Note: mode does not
- make sense here because it would be unwise to list external secret
- keys */
-static gpg_error_t
-list_external_keys (CTRL ctrl, STRLIST names, FILE *fp, int raw_mode)
-{
- int rc;
- struct list_external_parm_s parm;
-
- parm.fp = fp;
- parm.ctrl = ctrl,
- parm.print_header = ctrl->no_server;
- parm.with_colons = ctrl->with_colons;
- parm.with_chain = ctrl->with_chain;
- parm.raw_mode = raw_mode;
-
- rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm);
- if (rc)
- log_error ("listing external keys failed: %s\n", gpg_strerror (rc));
- return rc;
-}
-
-/* List all keys or just the key given as NAMES.
- MODE controls the operation mode:
- Bit 0-2:
- 0 = list all public keys but don't flag secret ones
- 1 = list only public keys
- 2 = list only secret keys
- 3 = list secret and public keys
- Bit 6: list internal keys
- Bit 7: list external keys
- Bit 8: Do a raw format dump.
- */
-gpg_error_t
-gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
-{
- gpg_error_t err = 0;
-
- if ((mode & (1<<6)))
- err = list_internal_keys (ctrl, names, fp, (mode & 3), (mode&256));
- if (!err && (mode & (1<<7)))
- err = list_external_keys (ctrl, names, fp, (mode&256));
- return err;
-}
diff --git a/sm/misc.c b/sm/misc.c
deleted file mode 100644
index 281056177..000000000
--- a/sm/misc.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/* misc.c - Miscellaneous fucntions
- * Copyright (C) 2004 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#ifdef HAVE_LOCALE_H
-#include <locale.h>
-#endif
-
-#include "gpgsm.h"
-
-
-/* Setup the environment so that the pinentry is able to get all
- required information. This is used prior to an exec of the
- protect-tool. */
-void
-setup_pinentry_env (void)
-{
- char *lc;
-
- if (opt.display)
- setenv ("DISPLAY", opt.display, 1);
- if (opt.ttyname)
- setenv ("GPG_TTY", opt.ttyname, 1);
- if (opt.ttytype)
- setenv ("TERM", opt.ttytype, 1);
-
- if (opt.lc_ctype)
- setenv ("LC_CTYPE", opt.lc_ctype, 1);
-#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
- else if ( (lc = setlocale (LC_CTYPE, "")) )
- setenv ("LC_CTYPE", lc, 1);
-#endif
-
- if (opt.lc_messages)
- setenv ("LC_MESSAGES", opt.lc_messages, 1);
-#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
- else if ( (lc = setlocale (LC_MESSAGES, "")) )
- setenv ("LC_MESSAGES", lc, 1);
-#endif
-
-}
-
diff --git a/sm/server.c b/sm/server.c
deleted file mode 100644
index 72bf74afa..000000000
--- a/sm/server.c
+++ /dev/null
@@ -1,1121 +0,0 @@
-/* server.c - Server mode and main entry point
- * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <unistd.h>
-
-#include <assuan.h>
-
-#include "gpgsm.h"
-
-#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
-
-
-/* The filepointer for status message used in non-server mode */
-static FILE *statusfp;
-
-/* Data used to assuciate an Assuan context with local server data */
-struct server_local_s {
- assuan_context_t assuan_ctx;
- int message_fd;
- int list_internal;
- int list_external;
- certlist_t recplist;
- certlist_t signerlist;
- certlist_t default_recplist; /* As set by main() - don't release. */
-};
-
-
-
-/* Note that it is sufficient to allocate the target string D as
- long as the source string S, i.e.: strlen(s)+1; */
-static void
-strcpy_escaped_plus (char *d, const unsigned char *s)
-{
- while (*s)
- {
- if (*s == '%' && s[1] && s[2])
- {
- s++;
- *d++ = xtoi_2 ( s);
- s += 2;
- }
- else if (*s == '+')
- *d++ = ' ', s++;
- else
- *d++ = *s++;
- }
- *d = 0;
-}
-
-
-
-
-/* Check whether the option NAME appears in LINE */
-static int
-has_option (const char *line, const char *name)
-{
- const char *s;
- int n = strlen (name);
-
- s = strstr (line, name);
- return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
-}
-
-
-static void
-close_message_fd (CTRL ctrl)
-{
- if (ctrl->server_local->message_fd != -1)
- {
- close (ctrl->server_local->message_fd);
- ctrl->server_local->message_fd = -1;
- }
-}
-
-
-static int
-option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
-
- if (!strcmp (key, "include-certs"))
- {
- int i = *value? atoi (value) : -1;
- if (ctrl->include_certs < -2)
- return ASSUAN_Parameter_Error;
- ctrl->include_certs = i;
- }
- else if (!strcmp (key, "display"))
- {
- if (opt.display)
- free (opt.display);
- opt.display = strdup (value);
- if (!opt.display)
- return ASSUAN_Out_Of_Core;
- }
- else if (!strcmp (key, "ttyname"))
- {
- if (opt.ttyname)
- free (opt.ttyname);
- opt.ttyname = strdup (value);
- if (!opt.ttyname)
- return ASSUAN_Out_Of_Core;
- }
- else if (!strcmp (key, "ttytype"))
- {
- if (opt.ttytype)
- free (opt.ttytype);
- opt.ttytype = strdup (value);
- if (!opt.ttytype)
- return ASSUAN_Out_Of_Core;
- }
- else if (!strcmp (key, "lc-ctype"))
- {
- if (opt.lc_ctype)
- free (opt.lc_ctype);
- opt.lc_ctype = strdup (value);
- if (!opt.lc_ctype)
- return ASSUAN_Out_Of_Core;
- }
- else if (!strcmp (key, "lc-messages"))
- {
- if (opt.lc_messages)
- free (opt.lc_messages);
- opt.lc_messages = strdup (value);
- if (!opt.lc_messages)
- return ASSUAN_Out_Of_Core;
- }
- else if (!strcmp (key, "list-mode"))
- {
- int i = *value? atoi (value) : 0;
- if (!i || i == 1) /* default and mode 1 */
- {
- ctrl->server_local->list_internal = 1;
- ctrl->server_local->list_external = 0;
- }
- else if (i == 2)
- {
- ctrl->server_local->list_internal = 0;
- ctrl->server_local->list_external = 1;
- }
- else if (i == 3)
- {
- ctrl->server_local->list_internal = 1;
- ctrl->server_local->list_external = 1;
- }
- else
- return ASSUAN_Parameter_Error;
- }
- else if (!strcmp (key, "with-validation"))
- {
- int i = *value? atoi (value) : 0;
- ctrl->with_validation = i;
- }
- else
- return ASSUAN_Invalid_Option;
-
- return 0;
-}
-
-
-
-
-static void
-reset_notify (ASSUAN_CONTEXT ctx)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
-
- gpgsm_release_certlist (ctrl->server_local->recplist);
- gpgsm_release_certlist (ctrl->server_local->signerlist);
- ctrl->server_local->recplist = NULL;
- ctrl->server_local->signerlist = NULL;
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
-}
-
-
-static void
-input_notify (ASSUAN_CONTEXT ctx, const char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
-
- ctrl->autodetect_encoding = 0;
- ctrl->is_pem = 0;
- ctrl->is_base64 = 0;
- if (strstr (line, "--armor"))
- ctrl->is_pem = 1;
- else if (strstr (line, "--base64"))
- ctrl->is_base64 = 1;
- else if (strstr (line, "--binary"))
- ;
- else
- ctrl->autodetect_encoding = 1;
-}
-
-static void
-output_notify (ASSUAN_CONTEXT ctx, const char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
-
- ctrl->create_pem = 0;
- ctrl->create_base64 = 0;
- if (strstr (line, "--armor"))
- ctrl->create_pem = 1;
- else if (strstr (line, "--base64"))
- ctrl->create_base64 = 1; /* just the raw output */
-}
-
-
-
-/* RECIPIENT <userID>
-
- Set the recipient for the encryption. <userID> should be the
- internal representation of the key; the server may accept any other
- way of specification [we will support this]. If this is a valid and
- trusted recipient the server does respond with OK, otherwise the
- return is an ERR with the reason why the recipient can't be used,
- the encryption will then not be done for this recipient. If the
- policy is not to encrypt at all if not all recipients are valid, the
- client has to take care of this. All RECIPIENT commands are
- cumulative until a RESET or an successful ENCRYPT command. */
-static int
-cmd_recipient (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
-
- rc = gpgsm_add_to_certlist (ctrl, line, 0, &ctrl->server_local->recplist, 0);
- if (rc)
- {
- gpg_err_code_t r = gpg_err_code (rc);
- gpgsm_status2 (ctrl, STATUS_INV_RECP,
- r == -1? "1":
- r == GPG_ERR_NO_PUBKEY? "1":
- r == GPG_ERR_AMBIGUOUS_NAME? "2":
- r == GPG_ERR_WRONG_KEY_USAGE? "3":
- r == GPG_ERR_CERT_REVOKED? "4":
- r == GPG_ERR_CERT_EXPIRED? "5":
- r == GPG_ERR_NO_CRL_KNOWN? "6":
- r == GPG_ERR_CRL_TOO_OLD? "7":
- r == GPG_ERR_NO_POLICY_MATCH? "8":
- "0",
- line, NULL);
- }
-
- return map_to_assuan_status (rc);
-}
-
-/* SIGNER <userID>
-
- Set the signer's keys for the signature creation. <userID> should
- be the internal representation of the key; the server may accept any
- other way of specification [we will support this]. If this is a
- valid and usable signing key the server does respond with OK,
- otherwise it returns an ERR with the reason why the key can't be
- used, the signing will then not be done for this key. If the policy
- is not to sign at all if not all signer keys are valid, the client
- has to take care of this. All SIGNER commands are cumulative until
- a RESET but they are *not* reset by an SIGN command becuase it can
- be expected that set of signers are used for more than one sign
- operation.
-
- Note that this command returns an INV_RECP status which is a bit
- strange, but they are very similar. */
-static int
-cmd_signer (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
-
- rc = gpgsm_add_to_certlist (ctrl, line, 1,
- &ctrl->server_local->signerlist, 0);
- if (rc)
- {
- gpg_err_code_t r = gpg_err_code (rc);
- gpgsm_status2 (ctrl, STATUS_INV_RECP,
- r == -1? "1":
- r == GPG_ERR_NO_PUBKEY? "1":
- r == GPG_ERR_AMBIGUOUS_NAME? "2":
- r == GPG_ERR_WRONG_KEY_USAGE? "3":
- r == GPG_ERR_CERT_REVOKED? "4":
- r == GPG_ERR_CERT_EXPIRED? "5":
- r == GPG_ERR_NO_CRL_KNOWN? "6":
- r == GPG_ERR_CRL_TOO_OLD? "7":
- r == GPG_ERR_NO_POLICY_MATCH? "8":
- r == GPG_ERR_NO_SECKEY? "9":
- "0",
- line, NULL);
- }
- return map_to_assuan_status (rc);
-}
-
-
-/* ENCRYPT
-
- Do the actual encryption process. Takes the plaintext from the INPUT
- command, writes to the ciphertext to the file descriptor set with
- the OUTPUT command, take the recipients form all the recipients set
- so far. If this command fails the clients should try to delete all
- output currently done or otherwise mark it as invalid. GPGSM does
- ensure that there won't be any security problem with leftover data
- on the output in this case.
-
- This command should in general not fail, as all necessary checks
- have been done while setting the recipients. The input and output
- pipes are closed. */
-static int
-cmd_encrypt (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- certlist_t cl;
- int inp_fd, out_fd;
- FILE *out_fp;
- int rc;
-
- inp_fd = assuan_get_input_fd (ctx);
- if (inp_fd == -1)
- return set_error (No_Input, NULL);
- out_fd = assuan_get_output_fd (ctx);
- if (out_fd == -1)
- return set_error (No_Output, NULL);
-
- out_fp = fdopen ( dup(out_fd), "w");
- if (!out_fp)
- return set_error (General_Error, "fdopen() failed");
-
- /* Now add all encrypt-to marked recipients from the default
- list. */
- rc = 0;
- if (!opt.no_encrypt_to)
- {
- for (cl=ctrl->server_local->recplist; !rc && cl; cl = cl->next)
- if (cl->is_encrypt_to)
- rc = gpgsm_add_cert_to_certlist (ctrl, cl->cert,
- &ctrl->server_local->recplist, 1);
- }
- if (!rc)
- rc = gpgsm_encrypt (assuan_get_pointer (ctx),
- ctrl->server_local->recplist,
- inp_fd, out_fp);
- fclose (out_fp);
-
- gpgsm_release_certlist (ctrl->server_local->recplist);
- ctrl->server_local->recplist = NULL;
- /* Close and reset the fd */
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
- return map_to_assuan_status (rc);
-}
-
-/* DECRYPT
-
- This performs the decrypt operation after doing some check on the
- internal state. (e.g. that only needed data has been set). Because
- it utilizes the GPG-Agent for the session key decryption, there is
- no need to ask the client for a protecting passphrase - GpgAgent
- does take care of this by requesting this from the user. */
-static int
-cmd_decrypt (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int inp_fd, out_fd;
- FILE *out_fp;
- int rc;
-
- inp_fd = assuan_get_input_fd (ctx);
- if (inp_fd == -1)
- return set_error (No_Input, NULL);
- out_fd = assuan_get_output_fd (ctx);
- if (out_fd == -1)
- return set_error (No_Output, NULL);
-
- out_fp = fdopen ( dup(out_fd), "w");
- if (!out_fp)
- return set_error (General_Error, "fdopen() failed");
- rc = gpgsm_decrypt (ctrl, inp_fd, out_fp);
- fclose (out_fp);
-
- /* close and reset the fd */
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
-
- return map_to_assuan_status (rc);
-}
-
-
-/* VERIFY
-
- This does a verify operation on the message send to the input-FD.
- The result is written out using status lines. If an output FD was
- given, the signed text will be written to that.
-
- If the signature is a detached one, the server will inquire about
- the signed material and the client must provide it.
- */
-static int
-cmd_verify (ASSUAN_CONTEXT ctx, char *line)
-{
- int rc;
- CTRL ctrl = assuan_get_pointer (ctx);
- int fd = assuan_get_input_fd (ctx);
- int out_fd = assuan_get_output_fd (ctx);
- FILE *out_fp = NULL;
-
- if (fd == -1)
- return set_error (No_Input, NULL);
-
- if (out_fd != -1)
- {
- out_fp = fdopen ( dup(out_fd), "w");
- if (!out_fp)
- return set_error (General_Error, "fdopen() failed");
- }
-
- rc = gpgsm_verify (assuan_get_pointer (ctx), fd,
- ctrl->server_local->message_fd, out_fp);
- if (out_fp)
- fclose (out_fp);
-
- /* close and reset the fd */
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
-
- return map_to_assuan_status (rc);
-}
-
-
-/* SIGN [--detached]
-
- Sign the data set with the INPUT command and write it to the sink
- set by OUTPUT. With "--detached" specified, a detached signature is
- created (surprise). */
-static int
-cmd_sign (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int inp_fd, out_fd;
- FILE *out_fp;
- int detached;
- int rc;
-
- inp_fd = assuan_get_input_fd (ctx);
- if (inp_fd == -1)
- return set_error (No_Input, NULL);
- out_fd = assuan_get_output_fd (ctx);
- if (out_fd == -1)
- return set_error (No_Output, NULL);
-
- detached = has_option (line, "--detached");
-
- out_fp = fdopen ( dup(out_fd), "w");
- if (!out_fp)
- return set_error (General_Error, "fdopen() failed");
-
- rc = gpgsm_sign (assuan_get_pointer (ctx), ctrl->server_local->signerlist,
- inp_fd, detached, out_fp);
- fclose (out_fp);
-
- /* close and reset the fd */
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
-
- return map_to_assuan_status (rc);
-}
-
-
-/* IMPORT
-
- Import the certificates read form the input-fd, return status
- message for each imported one. The import checks the validity of
- the certificate but not of the entire chain. It is possible to
- import expired certificates. */
-static int
-cmd_import (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
- int fd = assuan_get_input_fd (ctx);
-
- if (fd == -1)
- return set_error (No_Input, NULL);
-
- rc = gpgsm_import (assuan_get_pointer (ctx), fd);
-
- /* close and reset the fd */
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
-
- return map_to_assuan_status (rc);
-}
-
-
-static int
-cmd_export (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int fd = assuan_get_output_fd (ctx);
- FILE *out_fp;
- char *p;
- STRLIST list, sl;
-
- if (fd == -1)
- return set_error (No_Output, NULL);
-
- /* break the line down into an STRLIST */
- list = NULL;
- for (p=line; *p; line = p)
- {
- while (*p && *p != ' ')
- p++;
- if (*p)
- *p++ = 0;
- if (*line)
- {
- sl = xtrymalloc (sizeof *sl + strlen (line));
- if (!sl)
- {
- free_strlist (list);
- return ASSUAN_Out_Of_Core;
- }
- sl->flags = 0;
- strcpy_escaped_plus (sl->d, line);
- sl->next = list;
- list = sl;
- }
- }
-
- out_fp = fdopen ( dup(fd), "w");
- if (!out_fp)
- {
- free_strlist (list);
- return set_error (General_Error, "fdopen() failed");
- }
-
- gpgsm_export (ctrl, list, out_fp);
- fclose (out_fp);
- free_strlist (list);
- /* close and reset the fd */
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
- return 0;
-}
-
-
-static int
-cmd_delkeys (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- char *p;
- STRLIST list, sl;
- int rc;
-
- /* break the line down into an STRLIST */
- list = NULL;
- for (p=line; *p; line = p)
- {
- while (*p && *p != ' ')
- p++;
- if (*p)
- *p++ = 0;
- if (*line)
- {
- sl = xtrymalloc (sizeof *sl + strlen (line));
- if (!sl)
- {
- free_strlist (list);
- return ASSUAN_Out_Of_Core;
- }
- sl->flags = 0;
- strcpy_escaped_plus (sl->d, line);
- sl->next = list;
- list = sl;
- }
- }
-
- rc = gpgsm_delete (ctrl, list);
- free_strlist (list);
-
- /* close and reset the fd */
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
-
- return map_to_assuan_status (rc);
-}
-
-
-
-/* MESSAGE FD=<n>
-
- Set the file descriptor to read a message which is used with
- detached signatures */
-static int
-cmd_message (ASSUAN_CONTEXT ctx, char *line)
-{
- char *endp;
- int fd;
- CTRL ctrl = assuan_get_pointer (ctx);
-
- if (strncmp (line, "FD=", 3))
- return set_error (Syntax_Error, "FD=<n> expected");
- line += 3;
- if (!digitp (line))
- return set_error (Syntax_Error, "number required");
- fd = strtoul (line, &endp, 10);
- if (*endp)
- return set_error (Syntax_Error, "garbage found");
- if (fd == -1)
- return set_error (No_Input, NULL);
-
- ctrl->server_local->message_fd = fd;
- return 0;
-}
-
-
-static int
-do_listkeys (ASSUAN_CONTEXT ctx, char *line, int mode)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- FILE *fp = assuan_get_data_fp (ctx);
- char *p;
- STRLIST list, sl;
- unsigned int listmode;
- gpg_error_t err;
-
- if (!fp)
- return set_error (General_Error, "no data stream");
-
- /* break the line down into an STRLIST */
- list = NULL;
- for (p=line; *p; line = p)
- {
- while (*p && *p != ' ')
- p++;
- if (*p)
- *p++ = 0;
- if (*line)
- {
- sl = xtrymalloc (sizeof *sl + strlen (line));
- if (!sl)
- {
- free_strlist (list);
- return ASSUAN_Out_Of_Core;
- }
- sl->flags = 0;
- strcpy_escaped_plus (sl->d, line);
- sl->next = list;
- list = sl;
- }
- }
-
- ctrl->with_colons = 1;
- listmode = mode;
- if (ctrl->server_local->list_internal)
- listmode |= (1<<6);
- if (ctrl->server_local->list_external)
- listmode |= (1<<7);
- err = gpgsm_list_keys (assuan_get_pointer (ctx), list, fp, listmode);
- free_strlist (list);
- return map_to_assuan_status (err);
-}
-
-static int
-cmd_listkeys (ASSUAN_CONTEXT ctx, char *line)
-{
- return do_listkeys (ctx, line, 3);
-}
-
-static int
-cmd_listsecretkeys (ASSUAN_CONTEXT ctx, char *line)
-{
- return do_listkeys (ctx, line, 2);
-}
-
-
-/* GENKEY
-
- Read the parameters in native format from the input fd and write a
- certificate request to the output.
- */
-static int
-cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int inp_fd, out_fd;
- FILE *out_fp;
- int rc;
-
- inp_fd = assuan_get_input_fd (ctx);
- if (inp_fd == -1)
- return set_error (No_Input, NULL);
- out_fd = assuan_get_output_fd (ctx);
- if (out_fd == -1)
- return set_error (No_Output, NULL);
-
- out_fp = fdopen ( dup(out_fd), "w");
- if (!out_fp)
- return set_error (General_Error, "fdopen() failed");
- rc = gpgsm_genkey (ctrl, inp_fd, out_fp);
- fclose (out_fp);
-
- /* close and reset the fds */
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
-
- return map_to_assuan_status (rc);
-}
-
-
-
-
-
-/* Tell the assuan library about our commands */
-static int
-register_commands (ASSUAN_CONTEXT ctx)
-{
- static struct {
- const char *name;
- int (*handler)(ASSUAN_CONTEXT, char *line);
- } table[] = {
- { "RECIPIENT", cmd_recipient },
- { "SIGNER", cmd_signer },
- { "ENCRYPT", cmd_encrypt },
- { "DECRYPT", cmd_decrypt },
- { "VERIFY", cmd_verify },
- { "SIGN", cmd_sign },
- { "IMPORT", cmd_import },
- { "EXPORT", cmd_export },
- { "INPUT", NULL },
- { "OUTPUT", NULL },
- { "MESSAGE", cmd_message },
- { "LISTKEYS", cmd_listkeys },
- { "LISTSECRETKEYS",cmd_listsecretkeys },
- { "GENKEY", cmd_genkey },
- { "DELKEYS", cmd_delkeys },
- { NULL }
- };
- int i, rc;
-
- for (i=0; table[i].name; i++)
- {
- rc = assuan_register_command (ctx, table[i].name, table[i].handler);
- if (rc)
- return rc;
- }
- return 0;
-}
-
-/* Startup the server. DEFAULT_RECPLIST is the list of recipients as
- set from the command line or config file. We only require those
- marked as encrypt-to. */
-void
-gpgsm_server (certlist_t default_recplist)
-{
- int rc;
- int filedes[2];
- ASSUAN_CONTEXT ctx;
- struct server_control_s ctrl;
- static const char hello[] = ("GNU Privacy Guard's S/M server "
- VERSION " ready");
-
- memset (&ctrl, 0, sizeof ctrl);
- gpgsm_init_default_ctrl (&ctrl);
-
- /* For now we use a simple pipe based server so that we can work
- from scripts. We will later add options to run as a daemon and
- wait for requests on a Unix domain socket */
- filedes[0] = 0;
- filedes[1] = 1;
- rc = assuan_init_pipe_server (&ctx, filedes);
- if (rc)
- {
- log_error ("failed to initialize the server: %s\n",
- assuan_strerror(rc));
- gpgsm_exit (2);
- }
- rc = register_commands (ctx);
- if (rc)
- {
- log_error ("failed to the register commands with Assuan: %s\n",
- assuan_strerror(rc));
- gpgsm_exit (2);
- }
- if (opt.verbose || opt.debug)
- {
- char *tmp = NULL;
- const char *s1 = getenv ("GPG_AGENT_INFO");
- const char *s2 = getenv ("DIRMNGR_INFO");
-
- if (asprintf (&tmp,
- "Home: %s\n"
- "Config: %s\n"
- "AgentInfo: %s\n"
- "DirmngrInfo: %s\n"
- "%s",
- opt.homedir,
- opt.config_filename,
- s1?s1:"[not set]",
- s2?s2:"[not set]",
- hello) > 0)
- {
- assuan_set_hello_line (ctx, tmp);
- free (tmp);
- }
- }
- else
- assuan_set_hello_line (ctx, hello);
-
- assuan_register_reset_notify (ctx, reset_notify);
- assuan_register_input_notify (ctx, input_notify);
- assuan_register_output_notify (ctx, output_notify);
- assuan_register_option_handler (ctx, option_handler);
-
- assuan_set_pointer (ctx, &ctrl);
- ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
- ctrl.server_local->assuan_ctx = ctx;
- ctrl.server_local->message_fd = -1;
- ctrl.server_local->list_internal = 1;
- ctrl.server_local->list_external = 0;
- ctrl.server_local->default_recplist = default_recplist;
-
- if (DBG_ASSUAN)
- assuan_set_log_stream (ctx, log_get_stream ());
-
- for (;;)
- {
- rc = assuan_accept (ctx);
- if (rc == -1)
- {
- break;
- }
- else if (rc)
- {
- log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
- break;
- }
-
- rc = assuan_process (ctx);
- if (rc)
- {
- log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
- continue;
- }
- }
-
- gpgsm_release_certlist (ctrl.server_local->recplist);
- ctrl.server_local->recplist = NULL;
- gpgsm_release_certlist (ctrl.server_local->signerlist);
- ctrl.server_local->signerlist = NULL;
-
- assuan_deinit_server (ctx);
-}
-
-
-static const char *
-get_status_string ( int no )
-{
- const char *s;
-
- switch (no)
- {
- case STATUS_ENTER : s = "ENTER"; break;
- case STATUS_LEAVE : s = "LEAVE"; break;
- case STATUS_ABORT : s = "ABORT"; break;
- case STATUS_NEWSIG : s = "NEWSIG"; break;
- case STATUS_GOODSIG: s = "GOODSIG"; break;
- case STATUS_SIGEXPIRED: s = "SIGEXPIRED"; break;
- case STATUS_KEYREVOKED: s = "KEYREVOKED"; break;
- case STATUS_BADSIG : s = "BADSIG"; break;
- case STATUS_ERRSIG : s = "ERRSIG"; break;
- case STATUS_BADARMOR : s = "BADARMOR"; break;
- case STATUS_RSA_OR_IDEA : s= "RSA_OR_IDEA"; break;
- case STATUS_TRUST_UNDEFINED: s = "TRUST_UNDEFINED"; break;
- case STATUS_TRUST_NEVER : s = "TRUST_NEVER"; break;
- case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL"; break;
- case STATUS_TRUST_FULLY : s = "TRUST_FULLY"; break;
- case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE"; break;
- case STATUS_GET_BOOL : s = "GET_BOOL"; break;
- case STATUS_GET_LINE : s = "GET_LINE"; break;
- case STATUS_GET_HIDDEN : s = "GET_HIDDEN"; break;
- case STATUS_GOT_IT : s = "GOT_IT"; break;
- case STATUS_SHM_INFO : s = "SHM_INFO"; break;
- case STATUS_SHM_GET : s = "SHM_GET"; break;
- case STATUS_SHM_GET_BOOL : s = "SHM_GET_BOOL"; break;
- case STATUS_SHM_GET_HIDDEN : s = "SHM_GET_HIDDEN"; break;
- case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE"; break;
- case STATUS_VALIDSIG : s = "VALIDSIG"; break;
- case STATUS_SIG_ID : s = "SIG_ID"; break;
- case STATUS_ENC_TO : s = "ENC_TO"; break;
- case STATUS_NODATA : s = "NODATA"; break;
- case STATUS_BAD_PASSPHRASE : s = "BAD_PASSPHRASE"; break;
- case STATUS_NO_PUBKEY : s = "NO_PUBKEY"; break;
- case STATUS_NO_SECKEY : s = "NO_SECKEY"; break;
- case STATUS_NEED_PASSPHRASE_SYM: s = "NEED_PASSPHRASE_SYM"; break;
- case STATUS_DECRYPTION_FAILED: s = "DECRYPTION_FAILED"; break;
- case STATUS_DECRYPTION_OKAY: s = "DECRYPTION_OKAY"; break;
- case STATUS_MISSING_PASSPHRASE: s = "MISSING_PASSPHRASE"; break;
- case STATUS_GOOD_PASSPHRASE : s = "GOOD_PASSPHRASE"; break;
- case STATUS_GOODMDC : s = "GOODMDC"; break;
- case STATUS_BADMDC : s = "BADMDC"; break;
- case STATUS_ERRMDC : s = "ERRMDC"; break;
- case STATUS_IMPORTED : s = "IMPORTED"; break;
- case STATUS_IMPORT_OK : s = "IMPORT_OK"; break;
- case STATUS_IMPORT_RES : s = "IMPORT_RES"; break;
- case STATUS_FILE_START : s = "FILE_START"; break;
- case STATUS_FILE_DONE : s = "FILE_DONE"; break;
- case STATUS_FILE_ERROR : s = "FILE_ERROR"; break;
- case STATUS_BEGIN_DECRYPTION:s = "BEGIN_DECRYPTION"; break;
- case STATUS_END_DECRYPTION : s = "END_DECRYPTION"; break;
- case STATUS_BEGIN_ENCRYPTION:s = "BEGIN_ENCRYPTION"; break;
- case STATUS_END_ENCRYPTION : s = "END_ENCRYPTION"; break;
- case STATUS_DELETE_PROBLEM : s = "DELETE_PROBLEM"; break;
- case STATUS_PROGRESS : s = "PROGRESS"; break;
- case STATUS_SIG_CREATED : s = "SIG_CREATED"; break;
- case STATUS_SESSION_KEY : s = "SESSION_KEY"; break;
- case STATUS_NOTATION_NAME : s = "NOTATION_NAME" ; break;
- case STATUS_NOTATION_DATA : s = "NOTATION_DATA" ; break;
- case STATUS_POLICY_URL : s = "POLICY_URL" ; break;
- case STATUS_BEGIN_STREAM : s = "BEGIN_STREAM"; break;
- case STATUS_END_STREAM : s = "END_STREAM"; break;
- case STATUS_KEY_CREATED : s = "KEY_CREATED"; break;
- case STATUS_UNEXPECTED : s = "UNEXPECTED"; break;
- case STATUS_INV_RECP : s = "INV_RECP"; break;
- case STATUS_NO_RECP : s = "NO_RECP"; break;
- case STATUS_ALREADY_SIGNED : s = "ALREADY_SIGNED"; break;
- case STATUS_EXPSIG : s = "EXPSIG"; break;
- case STATUS_EXPKEYSIG : s = "EXPKEYSIG"; break;
- case STATUS_TRUNCATED : s = "TRUNCATED"; break;
- case STATUS_ERROR : s = "ERROR"; break;
- case STATUS_IMPORT_PROBLEM : s = "IMPORT_PROBLEM"; break;
- default: s = "?"; break;
- }
- return s;
-}
-
-
-void
-gpgsm_status2 (CTRL ctrl, int no, ...)
-{
- va_list arg_ptr;
- const char *text;
-
- va_start (arg_ptr, no);
-
- if (ctrl->no_server)
- {
- if (ctrl->status_fd == -1)
- return; /* no status wanted */
- if (!statusfp)
- {
- if (ctrl->status_fd == 1)
- statusfp = stdout;
- else if (ctrl->status_fd == 2)
- statusfp = stderr;
- else
- statusfp = fdopen (ctrl->status_fd, "w");
-
- if (!statusfp)
- {
- log_fatal ("can't open fd %d for status output: %s\n",
- ctrl->status_fd, strerror(errno));
- }
- }
-
- fputs ("[GNUPG:] ", statusfp);
- fputs (get_status_string (no), statusfp);
-
- while ( (text = va_arg (arg_ptr, const char*) ))
- {
- putc ( ' ', statusfp );
- for (; *text; text++)
- {
- if (*text == '\n')
- fputs ( "\\n", statusfp );
- else if (*text == '\r')
- fputs ( "\\r", statusfp );
- else
- putc ( *(const byte *)text, statusfp );
- }
- }
- putc ('\n', statusfp);
- fflush (statusfp);
- }
- else
- {
- ASSUAN_CONTEXT ctx = ctrl->server_local->assuan_ctx;
- char buf[950], *p;
- size_t n;
-
- p = buf;
- n = 0;
- while ( (text = va_arg (arg_ptr, const char *)) )
- {
- if (n)
- {
- *p++ = ' ';
- n++;
- }
- for ( ; *text && n < DIM (buf)-2; n++)
- *p++ = *text++;
- }
- *p = 0;
- assuan_write_status (ctx, get_status_string (no), buf);
- }
-
- va_end (arg_ptr);
-}
-
-void
-gpgsm_status (CTRL ctrl, int no, const char *text)
-{
- gpgsm_status2 (ctrl, no, text, NULL);
-}
-
-void
-gpgsm_status_with_err_code (CTRL ctrl, int no, const char *text,
- gpg_err_code_t ec)
-{
- char buf[30];
-
- sprintf (buf, "%u", (unsigned int)ec);
- if (text)
- gpgsm_status2 (ctrl, no, text, buf, NULL);
- else
- gpgsm_status2 (ctrl, no, buf, NULL);
-}
-
-#if 0
-/*
- * Write a status line with a buffer using %XX escapes. If WRAP is >
- * 0 wrap the line after this length. If STRING is not NULL it will
- * be prepended to the buffer, no escaping is done for string.
- * A wrap of -1 forces spaces not to be encoded as %20.
- */
-void
-write_status_text_and_buffer ( int no, const char *string,
- const char *buffer, size_t len, int wrap )
-{
- const char *s, *text;
- int esc, first;
- int lower_limit = ' ';
- size_t n, count, dowrap;
-
- if( !statusfp )
- return; /* not enabled */
-
- if (wrap == -1) {
- lower_limit--;
- wrap = 0;
- }
-
- text = get_status_string (no);
- count = dowrap = first = 1;
- do {
- if (dowrap) {
- fprintf (statusfp, "[GNUPG:] %s ", text );
- count = dowrap = 0;
- if (first && string) {
- fputs (string, statusfp);
- count += strlen (string);
- }
- first = 0;
- }
- for (esc=0, s=buffer, n=len; n && !esc; s++, n-- ) {
- if ( *s == '%' || *(const byte*)s <= lower_limit
- || *(const byte*)s == 127 )
- esc = 1;
- if ( wrap && ++count > wrap ) {
- dowrap=1;
- break;
- }
- }
- if (esc) {
- s--; n++;
- }
- if (s != buffer)
- fwrite (buffer, s-buffer, 1, statusfp );
- if ( esc ) {
- fprintf (statusfp, "%%%02X", *(const byte*)s );
- s++; n--;
- }
- buffer = s;
- len = n;
- if ( dowrap && len )
- putc ( '\n', statusfp );
- } while ( len );
-
- putc ('\n',statusfp);
- fflush (statusfp);
-}
-#endif
diff --git a/sm/sign.c b/sm/sign.c
deleted file mode 100644
index 5deef6088..000000000
--- a/sm/sign.c
+++ /dev/null
@@ -1,666 +0,0 @@
-/* sign.c - Sign a message
- * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-
-static void
-hash_data (int fd, gcry_md_hd_t md)
-{
- FILE *fp;
- char buffer[4096];
- int nread;
-
- fp = fdopen ( dup (fd), "rb");
- if (!fp)
- {
- log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
- return;
- }
-
- do
- {
- nread = fread (buffer, 1, DIM(buffer), fp);
- gcry_md_write (md, buffer, nread);
- }
- while (nread);
- if (ferror (fp))
- log_error ("read error on fd %d: %s\n", fd, strerror (errno));
- fclose (fp);
-}
-
-static int
-hash_and_copy_data (int fd, gcry_md_hd_t md, ksba_writer_t writer)
-{
- gpg_error_t err;
- FILE *fp;
- char buffer[4096];
- int nread;
- int rc = 0;
- int any = 0;
-
- fp = fdopen ( dup (fd), "rb");
- if (!fp)
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
- return tmperr;
- }
-
- do
- {
- nread = fread (buffer, 1, DIM(buffer), fp);
- if (nread)
- {
- any = 1;
- gcry_md_write (md, buffer, nread);
- err = ksba_writer_write_octet_string (writer, buffer, nread, 0);
- if (err)
- {
- log_error ("write failed: %s\n", gpg_strerror (err));
- rc = err;
- }
- }
- }
- while (nread && !rc);
- if (ferror (fp))
- {
- rc = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("read error on fd %d: %s\n", fd, strerror (errno));
- }
- fclose (fp);
- if (!any)
- {
- /* We can't allow to sign an empty message because it does not
- make much sense and more seriously, ksba-cms_build has
- already written the tag for data and now expects an octet
- string but an octet string of zeize 0 is illegal. */
- log_error ("cannot sign an empty message\n");
- rc = gpg_error (GPG_ERR_NO_DATA);
- }
- if (!rc)
- {
- err = ksba_writer_write_octet_string (writer, NULL, 0, 1);
- if (err)
- {
- log_error ("write failed: %s\n", gpg_strerror (err));
- rc = err;
- }
- }
-
- return rc;
-}
-
-
-/* Get the default certificate which is defined as the first one our
- keyDB returns and has a secret key available. */
-int
-gpgsm_get_default_cert (ctrl_t ctrl, ksba_cert_t *r_cert)
-{
- KEYDB_HANDLE hd;
- ksba_cert_t cert = NULL;
- int rc;
- char *p;
-
- hd = keydb_new (0);
- if (!hd)
- return gpg_error (GPG_ERR_GENERAL);
- rc = keydb_search_first (hd);
- if (rc)
- {
- keydb_release (hd);
- return rc;
- }
-
- do
- {
- rc = keydb_get_cert (hd, &cert);
- if (rc)
- {
- log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
- keydb_release (hd);
- return rc;
- }
-
- p = gpgsm_get_keygrip_hexstring (cert);
- if (p)
- {
- if (!gpgsm_agent_havekey (ctrl, p))
- {
- xfree (p);
- keydb_release (hd);
- *r_cert = cert;
- return 0; /* got it */
- }
- xfree (p);
- }
-
- ksba_cert_release (cert);
- cert = NULL;
- }
- while (!(rc = keydb_search_next (hd)));
- if (rc && rc != -1)
- log_error ("keydb_search_next failed: %s\n", gpg_strerror (rc));
-
- ksba_cert_release (cert);
- keydb_release (hd);
- return rc;
-}
-
-
-static ksba_cert_t
-get_default_signer (ctrl_t ctrl)
-{
- KEYDB_SEARCH_DESC desc;
- ksba_cert_t cert = NULL;
- KEYDB_HANDLE kh = NULL;
- int rc;
-
- if (!opt.local_user)
- {
- rc = gpgsm_get_default_cert (ctrl, &cert);
- if (rc)
- {
- if (rc != -1)
- log_debug ("failed to find default certificate: %s\n",
- gpg_strerror (rc));
- return NULL;
- }
- return cert;
- }
-
- rc = keydb_classify_name (opt.local_user, &desc);
- if (rc)
- {
- log_error ("failed to find default signer: %s\n", gpg_strerror (rc));
- return NULL;
- }
-
- kh = keydb_new (0);
- if (!kh)
- return NULL;
-
- rc = keydb_search (kh, &desc, 1);
- if (rc)
- {
- log_debug ("failed to find default certificate: rc=%d\n", rc);
- }
- else
- {
- rc = keydb_get_cert (kh, &cert);
- if (rc)
- {
- log_debug ("failed to get cert: rc=%d\n", rc);
- }
- }
-
- keydb_release (kh);
- return cert;
-}
-
-/* Depending on the options in CTRL add the certificate CERT as well as
- other certificate up in the chain to the Root-CA to the CMS
- object. */
-static int
-add_certificate_list (CTRL ctrl, ksba_cms_t cms, ksba_cert_t cert)
-{
- gpg_error_t err;
- int rc = 0;
- ksba_cert_t next = NULL;
- int n;
- int not_root = 0;
-
- ksba_cert_ref (cert);
-
- n = ctrl->include_certs;
- log_debug ("adding certificates at level %d\n", n);
- if (n == -2)
- {
- not_root = 1;
- n = -1;
- }
- if (n < 0 || n > 50)
- n = 50; /* We better apply an upper bound */
-
- /* First add my own certificate unless we don't want any certificate
- included at all. */
- if (n)
- {
- if (not_root && gpgsm_is_root_cert (cert))
- err = 0;
- else
- err = ksba_cms_add_cert (cms, cert);
- if (err)
- goto ksba_failure;
- if (n>0)
- n--;
- }
- /* Walk the chain to include all other certificates. Note that a -1
- used for N makes sure that there is no limit and all certs get
- included. */
- while ( n-- && !(rc = gpgsm_walk_cert_chain (cert, &next)) )
- {
- if (not_root && gpgsm_is_root_cert (next))
- err = 0;
- else
- err = ksba_cms_add_cert (cms, next);
- ksba_cert_release (cert);
- cert = next; next = NULL;
- if (err)
- goto ksba_failure;
- }
- ksba_cert_release (cert);
-
- return rc == -1? 0: rc;
-
- ksba_failure:
- ksba_cert_release (cert);
- log_error ("ksba_cms_add_cert failed: %s\n", gpg_strerror (err));
- return err;
-}
-
-
-
-
-/* Perform a sign operation.
-
- Sign the data received on DATA-FD in embedded mode or in detached
- mode when DETACHED is true. Write the signature to OUT_FP. The
- keys used to sign are taken from SIGNERLIST or the default one will
- be used if the value of this argument is NULL. */
-int
-gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
- int data_fd, int detached, FILE *out_fp)
-{
- int i, rc;
- gpg_error_t err;
- Base64Context b64writer = NULL;
- ksba_writer_t writer;
- ksba_cms_t cms = NULL;
- ksba_stop_reason_t stopreason;
- KEYDB_HANDLE kh = NULL;
- gcry_md_hd_t data_md = NULL;
- int signer;
- const char *algoid;
- int algo;
- ksba_isotime_t signed_at;
- CERTLIST cl;
- int release_signerlist = 0;
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- ctrl->pem_name = "SIGNED MESSAGE";
- rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
- if (rc)
- {
- log_error ("can't create writer: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- err = ksba_cms_new (&cms);
- if (err)
- {
- rc = err;
- goto leave;
- }
-
- err = ksba_cms_set_reader_writer (cms, NULL, writer);
- if (err)
- {
- log_debug ("ksba_cms_set_reader_writer failed: %s\n",
- gpg_strerror (err));
- rc = err;
- goto leave;
- }
-
- /* We are going to create signed data with data as encap. content */
- err = ksba_cms_set_content_type (cms, 0, KSBA_CT_SIGNED_DATA);
- if (!err)
- err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA);
- if (err)
- {
- log_debug ("ksba_cms_set_content_type failed: %s\n",
- gpg_strerror (err));
- rc = err;
- goto leave;
- }
-
- /* If no list of signers is given, use a default one. */
- if (!signerlist)
- {
- ksba_cert_t cert = get_default_signer (ctrl);
- if (!cert)
- {
- log_error ("no default signer found\n");
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- /* Although we don't check for ambigious specification we will
- check that the signer's certificate is is usable and
- valid. */
- rc = gpgsm_cert_use_sign_p (cert);
- if (!rc)
- rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0);
- if (rc)
- goto leave;
-
- /* That one is fine - create signerlist. */
- signerlist = xtrycalloc (1, sizeof *signerlist);
- if (!signerlist)
- {
- rc = OUT_OF_CORE (errno);
- ksba_cert_release (cert);
- goto leave;
- }
- signerlist->cert = cert;
- release_signerlist = 1;
- }
-
-
- /* Gather certificates of signers and store them in the CMS object. */
- for (cl=signerlist; cl; cl = cl->next)
- {
- rc = gpgsm_cert_use_sign_p (cl->cert);
- if (rc)
- goto leave;
-
- err = ksba_cms_add_signer (cms, cl->cert);
- if (err)
- {
- log_error ("ksba_cms_add_signer failed: %s\n", gpg_strerror (err));
- rc = err;
- goto leave;
- }
- rc = add_certificate_list (ctrl, cms, cl->cert);
- if (rc)
- {
- log_error ("failed to store list of certificates: %s\n",
- gpg_strerror(rc));
- goto leave;
- }
- /* Set the hash algorithm we are going to use */
- err = ksba_cms_add_digest_algo (cms, "1.3.14.3.2.26" /*SHA-1*/);
- if (err)
- {
- log_debug ("ksba_cms_add_digest_algo failed: %s\n",
- gpg_strerror (err));
- rc = err;
- goto leave;
- }
- }
-
- /* Prepare hashing (actually we are figuring out what we have set above)*/
- rc = gcry_md_open (&data_md, 0, 0);
- if (rc)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- if (DBG_HASHING)
- gcry_md_start_debug (data_md, "sign.data");
-
- for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
- {
- algo = gcry_md_map_name (algoid);
- if (!algo)
- {
- log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?");
- rc = gpg_error (GPG_ERR_BUG);
- goto leave;
- }
- gcry_md_enable (data_md, algo);
- }
-
- if (detached)
- { /* we hash the data right now so that we can store the message
- digest. ksba_cms_build() takes this as an flag that detached
- data is expected. */
- unsigned char *digest;
- size_t digest_len;
- /* Fixme do this for all signers and get the algo to use from
- the signer's certificate - does not make mich sense, but we
- should do this consistent as we have already done it above. */
- algo = GCRY_MD_SHA1;
- hash_data (data_fd, data_md);
- digest = gcry_md_read (data_md, algo);
- digest_len = gcry_md_get_algo_dlen (algo);
- if ( !digest || !digest_len)
- {
- log_error ("problem getting the hash of the data\n");
- rc = gpg_error (GPG_ERR_BUG);
- goto leave;
- }
- for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
- {
- err = ksba_cms_set_message_digest (cms, signer, digest, digest_len);
- if (err)
- {
- log_error ("ksba_cms_set_message_digest failed: %s\n",
- gpg_strerror (err));
- rc = err;
- goto leave;
- }
- }
- }
-
- gnupg_get_isotime (signed_at);
- for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
- {
- err = ksba_cms_set_signing_time (cms, signer, signed_at);
- if (err)
- {
- log_error ("ksba_cms_set_signing_time failed: %s\n",
- gpg_strerror (err));
- rc = err;
- goto leave;
- }
- }
-
- /* We need to write at least a minimal list of our capabilities to
- try to convince some MUAs to use 3DEs and not the crippled
- RC2. Our list is:
-
- aes128-CBC
- des-EDE3-CBC
- */
- err = ksba_cms_add_smime_capability (cms, "2.16.840.1.101.3.4.1.2", NULL, 0);
- if (!err)
- err = ksba_cms_add_smime_capability (cms, "1.2.840.113549.3.7", NULL, 0);
- if (err)
- {
- log_error ("ksba_cms_add_smime_capability failed: %s\n",
- gpg_strerror (err));
- goto leave;
- }
-
-
- /* Main building loop. */
- do
- {
- err = ksba_cms_build (cms, &stopreason);
- if (err)
- {
- log_debug ("ksba_cms_build failed: %s\n", gpg_strerror (err));
- rc = err;
- goto leave;
- }
-
- if (stopreason == KSBA_SR_BEGIN_DATA)
- { /* hash the data and store the message digest */
- unsigned char *digest;
- size_t digest_len;
-
- assert (!detached);
- /* Fixme: get the algo to use from the signer's certificate
- - does not make much sense, but we should do this
- consistent as we have already done it above. Code is
- mostly duplicated above. */
-
- algo = GCRY_MD_SHA1;
- rc = hash_and_copy_data (data_fd, data_md, writer);
- if (rc)
- goto leave;
- digest = gcry_md_read (data_md, algo);
- digest_len = gcry_md_get_algo_dlen (algo);
- if ( !digest || !digest_len)
- {
- log_error ("problem getting the hash of the data\n");
- rc = gpg_error (GPG_ERR_BUG);
- goto leave;
- }
- for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
- {
- err = ksba_cms_set_message_digest (cms, signer,
- digest, digest_len);
- if (err)
- {
- log_error ("ksba_cms_set_message_digest failed: %s\n",
- gpg_strerror (err));
- rc = err;
- goto leave;
- }
- }
- }
- else if (stopreason == KSBA_SR_NEED_SIG)
- { /* calculate the signature for all signers */
- gcry_md_hd_t md;
-
- algo = GCRY_MD_SHA1;
- rc = gcry_md_open (&md, algo, 0);
- if (rc)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- if (DBG_HASHING)
- gcry_md_start_debug (md, "sign.attr");
- ksba_cms_set_hash_function (cms, HASH_FNC, md);
- for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
- {
- char *sigval = NULL;
- char *buf, *fpr;
-
- if (signer)
- gcry_md_reset (md);
- rc = ksba_cms_hash_signed_attrs (cms, signer);
- if (rc)
- {
- log_debug ("hashing signed attrs failed: %s\n",
- gpg_strerror (rc));
- gcry_md_close (md);
- goto leave;
- }
-
- rc = gpgsm_create_cms_signature (ctrl, cl->cert,
- md, algo, &sigval);
- if (rc)
- {
- gcry_md_close (md);
- goto leave;
- }
-
- err = ksba_cms_set_sig_val (cms, signer, sigval);
- xfree (sigval);
- if (err)
- {
- log_error ("failed to store the signature: %s\n",
- gpg_strerror (err));
- rc = err;
- gcry_md_close (md);
- goto leave;
- }
-
- /* write a status message */
- fpr = gpgsm_get_fingerprint_hexstring (cl->cert, GCRY_MD_SHA1);
- if (!fpr)
- {
- rc = gpg_error (GPG_ERR_ENOMEM);
- gcry_md_close (md);
- goto leave;
- }
- {
- int pkalgo = gpgsm_get_key_algo_info (cl->cert, NULL);
- rc = asprintf (&buf, "%c %d %d 00 %s %s",
- detached? 'D':'S',
- pkalgo,
- algo,
- signed_at,
- fpr);
- }
- xfree (fpr);
- if (rc < 0)
- {
- rc = gpg_error (GPG_ERR_ENOMEM);
- gcry_md_close (md);
- goto leave;
- }
- rc = 0;
- gpgsm_status (ctrl, STATUS_SIG_CREATED, buf);
- free (buf); /* yes, we must use the regular free() here */
- }
- gcry_md_close (md);
-
- }
- }
- while (stopreason != KSBA_SR_READY);
-
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- log_info ("signature created\n");
-
-
- leave:
- if (rc)
- log_error ("error creating signature: %s <%s>\n",
- gpg_strerror (rc), gpg_strsource (rc) );
- if (release_signerlist)
- gpgsm_release_certlist (signerlist);
- ksba_cms_release (cms);
- gpgsm_destroy_writer (b64writer);
- keydb_release (kh);
- gcry_md_close (data_md);
- return rc;
-}
diff --git a/sm/verify.c b/sm/verify.c
deleted file mode 100644
index 410e86de7..000000000
--- a/sm/verify.c
+++ /dev/null
@@ -1,540 +0,0 @@
-/* verify.c - Verify a messages signature
- * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-static char *
-strtimestamp_r (ksba_isotime_t atime)
-{
- char *buffer = xmalloc (15);
-
- if (!atime || !*atime)
- strcpy (buffer, "none");
- else
- sprintf (buffer, "%.4s-%.2s-%.2s", atime, atime+4, atime+6);
- return buffer;
-}
-
-
-
-/* Hash the data for a detached signature */
-static void
-hash_data (int fd, gcry_md_hd_t md)
-{
- FILE *fp;
- char buffer[4096];
- int nread;
-
- fp = fdopen ( dup (fd), "rb");
- if (!fp)
- {
- log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
- return;
- }
-
- do
- {
- nread = fread (buffer, 1, DIM(buffer), fp);
- gcry_md_write (md, buffer, nread);
- }
- while (nread);
- if (ferror (fp))
- log_error ("read error on fd %d: %s\n", fd, strerror (errno));
- fclose (fp);
-}
-
-
-
-
-/* Perform a verify operation. To verify detached signatures, data_fd
- must be different than -1. With OUT_FP given and a non-detached
- signature, the signed material is written to that stream. */
-int
-gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
-{
- int i, rc;
- Base64Context b64reader = NULL;
- Base64Context b64writer = NULL;
- ksba_reader_t reader;
- ksba_writer_t writer = NULL;
- ksba_cms_t cms = NULL;
- ksba_stop_reason_t stopreason;
- ksba_cert_t cert;
- KEYDB_HANDLE kh;
- gcry_md_hd_t data_md = NULL;
- int signer;
- const char *algoid;
- int algo;
- int is_detached;
- FILE *fp = NULL;
- char *p;
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
-
- fp = fdopen ( dup (in_fd), "rb");
- if (!fp)
- {
- rc = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("fdopen() failed: %s\n", strerror (errno));
- goto leave;
- }
-
- rc = gpgsm_create_reader (&b64reader, ctrl, fp, 0, &reader);
- if (rc)
- {
- log_error ("can't create reader: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- if (out_fp)
- {
- rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
- if (rc)
- {
- log_error ("can't create writer: %s\n", gpg_strerror (rc));
- goto leave;
- }
- }
-
- rc = ksba_cms_new (&cms);
- if (rc)
- goto leave;
-
- rc = ksba_cms_set_reader_writer (cms, reader, writer);
- if (rc)
- {
- log_error ("ksba_cms_set_reader_writer failed: %s\n",
- gpg_strerror (rc));
- goto leave;
- }
-
- rc = gcry_md_open (&data_md, 0, 0);
- if (rc)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- if (DBG_HASHING)
- gcry_md_start_debug (data_md, "vrfy.data");
-
- is_detached = 0;
- do
- {
- rc = ksba_cms_parse (cms, &stopreason);
- if (rc)
- {
- log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- if (stopreason == KSBA_SR_NEED_HASH)
- {
- is_detached = 1;
- if (opt.verbose)
- log_info ("detached signature\n");
- }
-
- if (stopreason == KSBA_SR_NEED_HASH
- || stopreason == KSBA_SR_BEGIN_DATA)
- { /* We are now able to enable the hash algorithms */
- for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
- {
- algo = gcry_md_map_name (algoid);
- if (!algo)
- log_error ("unknown hash algorithm `%s'\n",
- algoid? algoid:"?");
- else
- gcry_md_enable (data_md, algo);
- }
- if (is_detached)
- {
- if (data_fd == -1)
- log_info ("detached signature w/o data "
- "- assuming certs-only\n");
- else
- hash_data (data_fd, data_md);
- }
- else
- {
- ksba_cms_set_hash_function (cms, HASH_FNC, data_md);
- }
- }
- else if (stopreason == KSBA_SR_END_DATA)
- { /* The data bas been hashed */
-
- }
- }
- while (stopreason != KSBA_SR_READY);
-
- if (b64writer)
- {
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- }
-
- if (data_fd != -1 && !is_detached)
- {
- log_error ("data given for a non-detached signature\n");
- rc = gpg_error (GPG_ERR_CONFLICT);
- goto leave;
- }
-
- for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
- {
- /* Fixme: it might be better to check the validity of the
- certificate first before entering it into the DB. This way
- we would avoid cluttering the DB with invalid
- certificates. */
- keydb_store_cert (cert, 0, NULL);
- ksba_cert_release (cert);
- }
-
- cert = NULL;
- for (signer=0; ; signer++)
- {
- char *issuer = NULL;
- ksba_sexp_t sigval = NULL;
- ksba_isotime_t sigtime, keyexptime;
- ksba_sexp_t serial;
- char *msgdigest = NULL;
- size_t msgdigestlen;
- char *ctattr;
-
- rc = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
- if (!signer && gpg_err_code (rc) == GPG_ERR_NO_DATA
- && data_fd == -1 && is_detached)
- {
- log_info ("certs-only message accepted\n");
- rc = 0;
- break;
- }
- if (rc)
- {
- if (signer && rc == -1)
- rc = 0;
- break;
- }
-
- gpgsm_status (ctrl, STATUS_NEWSIG, NULL);
-
- if (DBG_X509)
- {
- log_debug ("signer %d - issuer: `%s'\n",
- signer, issuer? issuer:"[NONE]");
- log_debug ("signer %d - serial: ", signer);
- gpgsm_dump_serial (serial);
- log_printf ("\n");
- }
-
- rc = ksba_cms_get_signing_time (cms, signer, sigtime);
- if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
- *sigtime = 0;
- else if (rc)
- {
- log_error ("error getting signing time: %s\n", gpg_strerror (rc));
- *sigtime = 0; /* (we can't encode an error in the time string.) */
- }
-
- rc = ksba_cms_get_message_digest (cms, signer,
- &msgdigest, &msgdigestlen);
- if (!rc)
- {
- size_t is_enabled;
-
- algoid = ksba_cms_get_digest_algo (cms, signer);
- algo = gcry_md_map_name (algoid);
- if (DBG_X509)
- log_debug ("signer %d - digest algo: %d\n", signer, algo);
- is_enabled = sizeof algo;
- if ( gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED,
- &algo, &is_enabled)
- || !is_enabled)
- {
- log_error ("digest algo %d has not been enabled\n", algo);
- goto next_signer;
- }
- }
- else if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
- {
- assert (!msgdigest);
- rc = 0;
- algoid = NULL;
- algo = 0;
- }
- else /* real error */
- break;
-
- rc = ksba_cms_get_sigattr_oids (cms, signer,
- "1.2.840.113549.1.9.3", &ctattr);
- if (!rc)
- {
- const char *s;
-
- if (DBG_X509)
- log_debug ("signer %d - content-type attribute: %s",
- signer, ctattr);
-
- s = ksba_cms_get_content_oid (cms, 1);
- if (!s || strcmp (ctattr, s))
- {
- log_error ("content-type attribute does not match "
- "actual content-type\n");
- ksba_free (ctattr);
- ctattr = NULL;
- goto next_signer;
- }
- ksba_free (ctattr);
- ctattr = NULL;
- }
- else if (rc != -1)
- {
- log_error ("error getting content-type attribute: %s\n",
- gpg_strerror (rc));
- goto next_signer;
- }
- rc = 0;
-
-
- sigval = ksba_cms_get_sig_val (cms, signer);
- if (!sigval)
- {
- log_error ("no signature value available\n");
- goto next_signer;
- }
- if (DBG_X509)
- log_debug ("signer %d - signature available", signer);
-
- /* Find the certificate of the signer */
- keydb_search_reset (kh);
- rc = keydb_search_issuer_sn (kh, issuer, serial);
- if (rc)
- {
- if (rc == -1)
- {
- log_error ("certificate not found\n");
- rc = gpg_error (GPG_ERR_NO_PUBKEY);
- }
- else
- log_error ("failed to find the certificate: %s\n",
- gpg_strerror(rc));
- {
- char numbuf[50];
- sprintf (numbuf, "%d", rc);
-
- gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey",
- numbuf, NULL);
- }
- /* fixme: we might want to append the issuer and serial
- using our standard notation */
- goto next_signer;
- }
-
- rc = keydb_get_cert (kh, &cert);
- if (rc)
- {
- log_error ("failed to get cert: %s\n", gpg_strerror (rc));
- goto next_signer;
- }
-
- log_info (_("Signature made "));
- if (*sigtime)
- gpgsm_dump_time (sigtime);
- else
- log_printf (_("[date not given]"));
- log_printf (_(" using certificate ID %08lX\n"),
- gpgsm_get_short_fingerprint (cert));
-
-
- if (msgdigest)
- { /* Signed attributes are available. */
- gcry_md_hd_t md;
- unsigned char *s;
-
- /* check that the message digest in the signed attributes
- matches the one we calculated on the data */
- s = gcry_md_read (data_md, algo);
- if ( !s || !msgdigestlen
- || gcry_md_get_algo_dlen (algo) != msgdigestlen
- || !s || memcmp (s, msgdigest, msgdigestlen) )
- {
- char *fpr;
-
- log_error ("invalid signature: message digest attribute "
- "does not match calculated one\n");
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- gpgsm_status (ctrl, STATUS_BADSIG, fpr);
- xfree (fpr);
- goto next_signer;
- }
-
- rc = gcry_md_open (&md, algo, 0);
- if (rc)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (rc));
- goto next_signer;
- }
- if (DBG_HASHING)
- gcry_md_start_debug (md, "vrfy.attr");
-
- ksba_cms_set_hash_function (cms, HASH_FNC, md);
- rc = ksba_cms_hash_signed_attrs (cms, signer);
- if (rc)
- {
- log_error ("hashing signed attrs failed: %s\n",
- gpg_strerror (rc));
- gcry_md_close (md);
- goto next_signer;
- }
- rc = gpgsm_check_cms_signature (cert, sigval, md, algo);
- gcry_md_close (md);
- }
- else
- {
- rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo);
- }
-
- if (rc)
- {
- char *fpr;
-
- log_error ("invalid signature: %s\n", gpg_strerror (rc));
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- gpgsm_status (ctrl, STATUS_BADSIG, fpr);
- xfree (fpr);
- goto next_signer;
- }
- rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/
- if (rc)
- {
- gpgsm_status_with_err_code (ctrl, STATUS_ERROR, "verify.keyusage",
- gpg_err_code (rc));
- rc = 0;
- }
-
- if (DBG_X509)
- log_debug ("signature okay - checking certs\n");
- rc = gpgsm_validate_chain (ctrl, cert, keyexptime, 0, NULL, 0);
- if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED)
- {
- gpgsm_status (ctrl, STATUS_EXPKEYSIG, NULL);
- rc = 0;
- }
- else
- gpgsm_status (ctrl, STATUS_GOODSIG, NULL);
-
- {
- char *buf, *fpr, *tstr;
-
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- tstr = strtimestamp_r (sigtime);
- buf = xmalloc ( strlen(fpr) + strlen (tstr) + 120);
- sprintf (buf, "%s %s %s %s", fpr, tstr,
- *sigtime? sigtime : "0",
- *keyexptime? keyexptime : "0" );
- xfree (tstr);
- xfree (fpr);
- gpgsm_status (ctrl, STATUS_VALIDSIG, buf);
- xfree (buf);
- }
-
- if (rc) /* of validate_chain */
- {
- log_error ("invalid certification chain: %s\n", gpg_strerror (rc));
- if (gpg_err_code (rc) == GPG_ERR_BAD_CERT_CHAIN
- || gpg_err_code (rc) == GPG_ERR_BAD_CERT
- || gpg_err_code (rc) == GPG_ERR_BAD_CA_CERT
- || gpg_err_code (rc) == GPG_ERR_CERT_REVOKED)
- gpgsm_status_with_err_code (ctrl, STATUS_TRUST_NEVER, NULL,
- gpg_err_code (rc));
- else
- gpgsm_status_with_err_code (ctrl, STATUS_TRUST_UNDEFINED, NULL,
- gpg_err_code (rc));
- goto next_signer;
- }
-
- for (i=0; (p = ksba_cert_get_subject (cert, i)); i++)
- {
- log_info (!i? _("Good signature from")
- : _(" aka"));
- log_printf (" \"");
- gpgsm_print_name (log_get_stream (), p);
- log_printf ("\"\n");
- ksba_free (p);
- }
-
- gpgsm_status (ctrl, STATUS_TRUST_FULLY, NULL);
-
-
- next_signer:
- rc = 0;
- xfree (issuer);
- xfree (serial);
- xfree (sigval);
- xfree (msgdigest);
- ksba_cert_release (cert);
- cert = NULL;
- }
- rc = 0;
-
- leave:
- ksba_cms_release (cms);
- gpgsm_destroy_reader (b64reader);
- gpgsm_destroy_writer (b64writer);
- keydb_release (kh);
- gcry_md_close (data_md);
- if (fp)
- fclose (fp);
-
- if (rc)
- {
- char numbuf[50];
- sprintf (numbuf, "%d", rc );
- gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave",
- numbuf, NULL);
- }
-
- return rc;
-}
-