diff options
Diffstat (limited to 'sm')
-rw-r--r-- | sm/ChangeLog | 1220 | ||||
-rw-r--r-- | sm/Makefile.am | 56 | ||||
-rw-r--r-- | sm/base64.c | 655 | ||||
-rw-r--r-- | sm/call-agent.c | 635 | ||||
-rw-r--r-- | sm/call-dirmngr.c | 785 | ||||
-rw-r--r-- | sm/certchain.c | 976 | ||||
-rw-r--r-- | sm/certcheck.c | 303 | ||||
-rw-r--r-- | sm/certdump.c | 696 | ||||
-rw-r--r-- | sm/certlist.c | 427 | ||||
-rw-r--r-- | sm/certreqgen.c | 739 | ||||
-rw-r--r-- | sm/decrypt.c | 512 | ||||
-rw-r--r-- | sm/delete.c | 172 | ||||
-rw-r--r-- | sm/encrypt.c | 511 | ||||
-rw-r--r-- | sm/export.c | 736 | ||||
-rw-r--r-- | sm/fingerprint.c | 331 | ||||
-rw-r--r-- | sm/gpgsm.c | 1700 | ||||
-rw-r--r-- | sm/gpgsm.h | 311 | ||||
-rw-r--r-- | sm/import.c | 725 | ||||
-rw-r--r-- | sm/keydb.c | 1532 | ||||
-rw-r--r-- | sm/keydb.h | 85 | ||||
-rw-r--r-- | sm/keylist.c | 1252 | ||||
-rw-r--r-- | sm/misc.c | 65 | ||||
-rw-r--r-- | sm/server.c | 1121 | ||||
-rw-r--r-- | sm/sign.c | 666 | ||||
-rw-r--r-- | sm/verify.c | 540 |
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; -} - |