diff options
author | Repo Admin <nobody@gnupg.org> | 2002-10-19 09:55:27 +0200 |
---|---|---|
committer | Repo Admin <nobody@gnupg.org> | 2002-10-19 09:55:27 +0200 |
commit | 82a17c9fb3d64ccdd474c3bedf564368f77e84a4 (patch) | |
tree | 0c01ee8cea5f6f77e830955c6b97024752740a2b /sm | |
parent | Bumped version number for cvs version (diff) | |
download | gnupg2-82a17c9fb3d64ccdd474c3bedf564368f77e84a4.tar.xz gnupg2-82a17c9fb3d64ccdd474c3bedf564368f77e84a4.zip |
This commit was manufactured by cvs2svn to create branch
'GNUPG-1-9-BRANCH'.
Diffstat (limited to 'sm')
-rw-r--r-- | sm/ChangeLog | 741 | ||||
-rw-r--r-- | sm/Makefile.am | 57 | ||||
-rw-r--r-- | sm/base64.c | 624 | ||||
-rw-r--r-- | sm/call-agent.c | 751 | ||||
-rw-r--r-- | sm/call-dirmngr.c | 495 | ||||
-rw-r--r-- | sm/certchain.c | 786 | ||||
-rw-r--r-- | sm/certcheck.c | 301 | ||||
-rw-r--r-- | sm/certdump.c | 457 | ||||
-rw-r--r-- | sm/certlist.c | 313 | ||||
-rw-r--r-- | sm/certreqgen.c | 699 | ||||
-rw-r--r-- | sm/decrypt.c | 502 | ||||
-rw-r--r-- | sm/delete.c | 165 | ||||
-rw-r--r-- | sm/encrypt.c | 549 | ||||
-rw-r--r-- | sm/export.c | 248 | ||||
-rw-r--r-- | sm/fingerprint.c | 271 | ||||
-rw-r--r-- | sm/gpgsm.c | 1388 | ||||
-rw-r--r-- | sm/gpgsm.h | 261 | ||||
-rw-r--r-- | sm/import.c | 349 | ||||
-rw-r--r-- | sm/keydb.c | 1282 | ||||
-rw-r--r-- | sm/keylist.c | 616 | ||||
-rw-r--r-- | sm/server.c | 1057 | ||||
-rw-r--r-- | sm/sign.c | 622 | ||||
-rw-r--r-- | sm/verify.c | 510 |
23 files changed, 0 insertions, 13044 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog deleted file mode 100644 index 8e11e0ddf..000000000 --- a/sm/ChangeLog +++ /dev/null @@ -1,741 +0,0 @@ -2002-09-19 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * gpgsm.c (main): Disable the internal libgcrypt locking. - -2002-08-21 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * certcheck.c (gpgsm_check_cert_sig): Implement proper cleanup. - (gpgsm_check_cms_signature): Ditto. - -2002-07-22 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * server.c (cmd_recipient): Add more reason codes. - -2002-06-27 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * import.c (gpgsm_import): Print an STATUS_IMPORTED. - - * gpgsm.c: --debug-no-path-validation does not take an argument. - -2002-06-25 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * certreqgen.c (read_parameters): Improved error handling. - (gpgsm_genkey): Print error message. - -2002-06-13 Werner Koch <wk@gnupg.org> - - * gpgsm.c (main): New option --log-file. - -2002-06-12 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * gpgsm.c (main): Don't print the "go ahead" message for an - invalid command. - -2002-05-23 Werner Koch <wk@gnupg.org> - - * import.c (gpgsm_import): Add error messages. - -2002-05-21 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * call-agent.c (start_agent): Make copies of old locales and check - for setlocale. - -2002-04-25 Marcus Brinkmann <marcus@g10code.de> - - * call-agent.c (start_agent): Fix error handling logic so the - locale is always correctly reset. - -2002-04-25 Marcus Brinkmann <marcus@g10code.de> - - * 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 <marcus@g10code.de> - - * 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 <wk@gnupg.org> - - * certreqgen.c (gpgsm_genkey): Write status output on success. - -2002-04-15 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * export.c: New. - * gpgsm.c: Add command --export. - * server.c (cmd_export): New. - -2002-03-13 Werner Koch <wk@gnupg.org> - - * decrypt.c (gpgsm_decrypt): Allow multiple recipients. - -2002-03-12 Werner Koch <wk@gnupg.org> - - * certpath.c (check_cert_policy): Print the policy list. - - * verify.c (gpgsm_verify): Detect certs-only message. - -2002-03-11 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * call-dirmngr.c, call-agent.c: Add 2 more arguments to all uses - of assuan_transact. - -2002-02-25 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <marcus@g10code.de> - - * sign.c (gpgsm_sign): Do not release certificate twice. - -2002-01-29 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * certreqgen.c (create_request): Store the email address in the req. - -2002-01-25 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * server.c (option_handler): New. - (gpgsm_server): Register it with assuan. - -2002-01-19 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * call-dirmngr.c (inq_certificate): Changed for new interface semantic. - * certlist.c (gpgsm_find_cert): New. - -2002-01-13 Werner Koch <wk@gnupg.org> - - * fingerprint.c (gpgsm_get_certid): Print the serial and not the - hash after the dot. - -2002-01-11 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * base64.c (gpgsm_create_writer): Allow to set the object name - -2002-01-08 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * server.c (rc_to_assuan_status): Removed and changed all callers - to use map_to_assuan_status. - -2001-12-20 Werner Koch <wk@gnupg.org> - - * 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 <marcus@g10code.de> - - * call-agent.c (start_agent): Add new argument to assuan_pipe_connect. - -2001-12-18 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <marcus@g10code.de> - - * call-agent.c (LINELENGTH): Removed. - (gpgsm_agent_pksign): Use ASSUAN_LINELENGTH, not LINELENGTH. - (gpgsm_agent_pkdecrypt): Likewise. - -2001-12-13 Werner Koch <wk@gnupg.org> - - * keylist.c (list_cert_colon): Print alternative names of subject - and a few other values. - -2001-12-12 Werner Koch <wk@gnupg.org> - - * gpgsm.c (main): New options --assume-{armor,base64,binary}. - * base64.c (base64_reader_cb): Fixed non-autodetection mode. - -2001-12-04 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 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 5c137fbb8..000000000 --- a/sm/Makefile.am +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (C) 2001, 2002 Free Software Foundation, Inc. -# -# This file is part of GnuPG. -# -# GnuPG is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# GnuPG is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - -## Process this file with automake to produce Makefile.in - -localedir = $(datadir)/locale -INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" - -bin_PROGRAMS = gpgsm - -AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl \ - $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) -LDFLAGS = @LDFLAGS@ - -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 ../assuan/libassuan.a ../kbx/libkeybox.a \ - ../common/libcommon.a $(LIBGCRYPT_LIBS) $(KSBA_LIBS) - - diff --git a/sm/base64.c b/sm/base64.c deleted file mode 100644 index f70615e97..000000000 --- a/sm/base64.c +++ /dev/null @@ -1,624 +0,0 @@ -/* base64.c - * 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 <ksba.h> - -#include "gpgsm.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 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; - - 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) - { - 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; - /* let us return 0 */ - } - 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) - { - 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) ? KSBA_Write_Error: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)? GNUPG_Write_Error : 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. */ -int -gpgsm_create_reader (Base64Context *ctx, - CTRL ctrl, FILE *fp, KsbaReader *r_reader) -{ - int rc; - KsbaReader r; - - *r_reader = NULL; - *ctx = xtrycalloc (1, sizeof **ctx); - if (!*ctx) - return seterr (Out_Of_Core); - - r = ksba_reader_new (); - if (!r) - { - xfree (*ctx); *ctx = NULL; - return seterr (Out_Of_Core); - } - - (*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 map_ksba_err (rc); - } - - *r_reader = r; - return 0; -} - - -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, KsbaWriter *r_writer) -{ - int rc; - KsbaWriter w; - - *r_writer = NULL; - *ctx = xtrycalloc (1, sizeof **ctx); - if (!*ctx) - return seterr (Out_Of_Core); - - w = ksba_writer_new (); - if (!w) - { - xfree (*ctx); *ctx = NULL; - return seterr (Out_Of_Core); - } - - 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 map_ksba_err (rc); - } - - *r_writer = w; - return 0; -} - - -int -gpgsm_finish_writer (Base64Context ctx) -{ - struct writer_cb_parm_s *parm; - - if (!ctx) - return GNUPG_Invalid_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 6cb2fb505..000000000 --- a/sm/call-agent.c +++ /dev/null @@ -1,751 +0,0 @@ -/* call-agent.c - divert operations to the agent - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> -#include <time.h> -#include <assert.h> -#include <gcrypt.h> -#ifdef HAVE_LOCALE_H -#include <locale.h> -#endif - -#include "gpgsm.h" -#include "../assuan/assuan.h" -#include "i18n.h" -#include "keydb.h" /* fixme: Move this to import.c */ - -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; - struct membuf *data; -}; - -struct membuf { - size_t len; - size_t size; - char *buf; - int out_of_core; -}; - - - -/* A simple implemnation 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_agent (void) -{ - int rc = 0; - char *infostr, *p; - ASSUAN_CONTEXT ctx; - char *dft_display = NULL; - char *dft_ttyname = NULL; - char *dft_ttytype = NULL; - char *old_lc = NULL; - char *dft_lc = NULL; - - 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) - { - 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")); - - if (fflush (NULL)) - { - log_error ("error flushing pending output: %s\n", strerror (errno)); - return seterr (Write_Error); - } - - 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 (); - } - *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 (); - } - - 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 (); - } - } - - if (rc) - { - log_error ("can't connect to the agent: %s\n", assuan_strerror (rc)); - return seterr (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); - - dft_display = getenv ("DISPLAY"); - if (opt.display || dft_display) - { - char *optstr; - if (asprintf (&optstr, "OPTION display=%s", - opt.display ? opt.display : dft_display) < 0) - return GNUPG_Out_Of_Core; - rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL, - NULL); - free (optstr); - if (rc) - return map_assuan_err (rc); - } - if (!opt.ttyname && ttyname (1)) - dft_ttyname = ttyname (1); - if (opt.ttyname || dft_ttyname) - { - char *optstr; - if (asprintf (&optstr, "OPTION ttyname=%s", - opt.ttyname ? opt.ttyname : dft_ttyname) < 0) - return GNUPG_Out_Of_Core; - rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL, - NULL); - free (optstr); - if (rc) - return map_assuan_err (rc); - } - dft_ttytype = getenv ("TERM"); - if (opt.ttytype || (dft_ttyname && dft_ttytype)) - { - char *optstr; - if (asprintf (&optstr, "OPTION ttytype=%s", - opt.ttyname ? opt.ttytype : dft_ttytype) < 0) - return GNUPG_Out_Of_Core; - rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL, - NULL); - free (optstr); - if (rc) - return map_assuan_err (rc); - } -#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE) - old_lc = setlocale (LC_CTYPE, NULL); - if (old_lc) - { - old_lc = strdup (old_lc); - if (!old_lc) - return GNUPG_Out_Of_Core; - } - dft_lc = setlocale (LC_CTYPE, ""); -#endif - if (opt.lc_ctype || (dft_ttyname && dft_lc)) - { - char *optstr; - if (asprintf (&optstr, "OPTION lc-ctype=%s", - opt.lc_ctype ? opt.lc_ctype : dft_lc) < 0) - rc = GNUPG_Out_Of_Core; - else - { - rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL, - NULL); - free (optstr); - if (rc) - rc = map_assuan_err (rc); - } - } -#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE) - if (old_lc) - { - setlocale (LC_CTYPE, old_lc); - free (old_lc); - } -#endif - if (rc) - return rc; -#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES) - old_lc = setlocale (LC_MESSAGES, NULL); - if (old_lc) - { - old_lc = strdup (old_lc); - if (!old_lc) - return GNUPG_Out_Of_Core; - } - dft_lc = setlocale (LC_MESSAGES, ""); -#endif - if (opt.lc_messages || (dft_ttyname && dft_lc)) - { - char *optstr; - if (asprintf (&optstr, "OPTION lc-messages=%s", - opt.lc_messages ? opt.lc_messages : dft_lc) < 0) - rc = GNUPG_Out_Of_Core; - else - { - rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL, - NULL); - free (optstr); - if (rc) - rc = map_assuan_err (rc); - } - } -#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES) - if (old_lc) - { - setlocale (LC_MESSAGES, old_lc); - free (old_lc); - } -#endif - - return rc; -} - - -static AssuanError -membuf_data_cb (void *opaque, const void *buffer, size_t length) -{ - struct membuf *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 (const char *keygrip, - unsigned char *digest, size_t digestlen, int digestalgo, - char **r_buf, size_t *r_buflen ) -{ - int rc, i; - char *p, line[ASSUAN_LINELENGTH]; - struct membuf data; - size_t len; - - *r_buf = NULL; - rc = start_agent (); - if (rc) - return rc; - - if (digestlen*2 + 50 > DIM(line)) - return seterr (General_Error); - - 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); - - 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 GNUPG_Invalid_Value; - } - - return *r_buf? 0 : GNUPG_Out_Of_Core; -} - - - - -/* 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 (const char *keygrip, - KsbaConstSexp ciphertext, - char **r_buf, size_t *r_buflen ) -{ - int rc; - char line[ASSUAN_LINELENGTH]; - struct membuf 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 GNUPG_Invalid_Value; - *r_buf = NULL; - - ciphertextlen = gcry_sexp_canon_len (ciphertext, 0, NULL, NULL); - if (!ciphertextlen) - return GNUPG_Invalid_Value; - - rc = start_agent (); - 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); - - 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 seterr (Out_Of_Core); - /* 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 seterr (Invalid_Sexp); - endp++; - if (endp-buf+n > len) - return seterr (Invalid_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 (KsbaConstSexp keyparms, KsbaSexp *r_pubkey) -{ - int rc; - struct genkey_parm_s gk_parm; - struct membuf data; - size_t len; - char *buf; - - *r_pubkey = NULL; - rc = start_agent (); - 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 GNUPG_Invalid_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 GNUPG_Out_Of_Core; - if (!gcry_sexp_canon_len (buf, len, NULL, NULL)) - { - xfree (buf); - return GNUPG_Invalid_Sexp; - } - *r_pubkey = buf; - return 0; -} - - -/* Ask the agent whether the certificate is in the list of trusted - keys */ -int -gpgsm_agent_istrusted (KsbaCert cert) -{ - int rc; - char *fpr; - char line[ASSUAN_LINELENGTH]; - - rc = start_agent (); - if (rc) - return rc; - - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - if (!fpr) - { - log_error ("error getting the fingerprint\n"); - return seterr (General_Error); - } - - 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 (KsbaCert cert) -{ - int rc; - char *fpr, *dn; - char line[ASSUAN_LINELENGTH]; - - rc = start_agent (); - if (rc) - return rc; - - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - if (!fpr) - { - log_error ("error getting the fingerprint\n"); - return seterr (General_Error); - } - - dn = ksba_cert_get_issuer (cert, 0); - if (!dn) - { - xfree (fpr); - return seterr (General_Error); - } - 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 (const char *hexkeygrip) -{ - int rc; - char line[ASSUAN_LINELENGTH]; - - rc = start_agent (); - if (rc) - return rc; - - if (!hexkeygrip || strlen (hexkeygrip) != 40) - return GNUPG_Invalid_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; - KsbaCert 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 = GNUPG_Out_Of_Core; - return 0; - } - - - /* FIXME: this should go into import.c */ - cert = ksba_cert_new (); - if (!cert) - { - parm->error = GNUPG_Out_Of_Core; - return 0; - } - rc = ksba_cert_init_from_mem (cert, buf, len); - if (rc) - { - log_error ("failed to parse a certificate: %s\n", ksba_strerror (rc)); - ksba_cert_release (cert); - parm->error = map_ksba_err (rc); - return 0; - } - - rc = gpgsm_basic_cert_check (cert); - if (rc == GNUPG_Missing_Certificate) - { /* 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", gnupg_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 () -{ - int rc; - struct learn_parm_s learn_parm; - struct membuf data; - size_t len; - - rc = start_agent (); - 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; -} - diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c deleted file mode 100644 index a1d94e25b..000000000 --- a/sm/call-dirmngr.c +++ /dev/null @@ -1,495 +0,0 @@ -/* call-dirmngr.c - communication with the dromngr - * 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 <gcrypt.h> - -#include "gpgsm.h" -#include "../assuan/assuan.h" -#include "i18n.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; - KsbaCert cert; -}; - -struct lookup_parm_s { - CTRL ctrl; - ASSUAN_CONTEXT ctx; - void (*cb)(void *, KsbaCert); - void *cb_value; - struct membuf data; - int error; -}; - - - - -/* 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 */ - - infostr = force_pipe_server? NULL : getenv ("DIRMNGR_INFO"); - if (!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)) - { - log_error ("error flushing pending output: %s\n", strerror (errno)); - return seterr (Write_Error); - } - - 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 seterr (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; - - if (!(!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]))) - { - log_error ("unsupported inquiry `%s'\n", line); - return ASSUAN_Inquire_Unknown; - } - line += 8; - - if (!*line) - { /* send the current certificate */ - der = ksba_cert_get_image (parm->cert, &derlen); - if (!der) - rc = ASSUAN_Inquire_Error; - else - rc = assuan_send_data (parm->ctx, der, derlen); - } - else - { /* send the given certificate */ - int err; - KsbaCert cert; - - err = gpgsm_find_cert (line, &cert); - if (err) - { - log_error ("certificate not found: %s\n", gnupg_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; -} - - - -/* Call the directory manager to check whether the certificate is valid - Returns 0 for valid or usually one of the errors: - - GNUPG_Certificate_Revoked - GNUPG_No_CRL_Known - GNUPG_CRL_Too_Old - */ -int -gpgsm_dirmngr_isvalid (KsbaCert cert) -{ - int rc; - char *certid; - char line[ASSUAN_LINELENGTH]; - struct inq_certificate_parm_s parm; - - rc = start_dirmngr (); - if (rc) - return rc; - - certid = gpgsm_get_certid (cert); - if (!certid) - { - log_error ("error getting the certificate ID\n"); - return seterr (General_Error); - } - - if (opt.verbose > 1) - { - char *fpr = gpgsm_get_fingerprint_string (cert, GCRY_MD_SHA1); - log_info ("asking dirmngr about %s\n", fpr); - xfree (fpr); - } - - parm.ctx = dirmngr_ctx; - parm.cert = cert; - - 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, NULL, NULL); - if (opt.verbose > 1) - log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay"); - return map_assuan_err (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; - KsbaCert 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 = GNUPG_Out_Of_Core; - return 0; - } - - cert = ksba_cert_new (); - if (!cert) - { - parm->error = GNUPG_Out_Of_Core; - return 0; - } - rc = ksba_cert_init_from_mem (cert, buf, len); - if (rc) - { - log_error ("failed to parse a certificate: %s\n", ksba_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 apptern - 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*, KsbaCert), 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 GNUPG_Out_Of_Core; - 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; -} - - diff --git a/sm/certchain.c b/sm/certchain.c deleted file mode 100644 index b01398f18..000000000 --- a/sm/certchain.c +++ /dev/null @@ -1,786 +0,0 @@ -/* certchain.c - certificate chain validation - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> -#include <time.h> -#include <assert.h> - -#include <gcrypt.h> -#include <ksba.h> - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - -static int -unknown_criticals (KsbaCert cert) -{ - static const char *known[] = { - "2.5.29.15", /* keyUsage */ - "2.5.29.19", /* basic Constraints */ - "2.5.29.32", /* certificatePolicies */ - NULL - }; - int rc = 0, i, idx, crit; - const char *oid; - KsbaError 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]) - { - log_error (_("critical certificate extension %s is not supported\n"), - oid); - rc = GNUPG_Unsupported_Certificate; - } - } - if (err && err != -1) - rc = map_ksba_err (err); - - return rc; -} - -static int -allowed_ca (KsbaCert cert, int *chainlen) -{ - KsbaError err; - int flag; - - err = ksba_cert_is_ca (cert, &flag, chainlen); - if (err) - return map_ksba_err (err); - if (!flag) - { - log_error (_("issuer certificate is not marked as a CA\n")); - return GNUPG_Bad_CA_Certificate; - } - return 0; -} - - -static int -check_cert_policy (KsbaCert cert) -{ - KsbaError err; - char *policies; - FILE *fp; - int any_critical; - - err = ksba_cert_get_cert_policies (cert, &policies); - if (err == KSBA_No_Data) - return 0; /* no policy given */ - if (err) - return map_ksba_err (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) - 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) - { - log_error ("critical marked policy without configured policies\n"); - return GNUPG_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); - return GNUPG_No_Policy_Match; - } - - for (;;) - { - int c; - char *p, line[256]; - char *haystack, *allowed; - - /* read line */ - do - { - if (!fgets (line, DIM(line)-1, fp) ) - { - xfree (policies); - if (feof (fp)) - { - fclose (fp); - /* with no critical policies this is only a warning */ - if (!any_critical) - { - log_info (_("note: certificate policy not allowed\n")); - return 0; - } - log_error (_("certificate policy not allowed\n")); - return GNUPG_No_Policy_Match; - } - fclose (fp); - return GNUPG_Read_Error; - } - - if (!*line || line[strlen(line)-1] != '\n') - { - /* eat until end of line */ - while ( (c=getc (fp)) != EOF && c != '\n') - ; - fclose (fp); - xfree (policies); - return *line? GNUPG_Line_Too_Long: GNUPG_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 GNUPG_Configuration_Error; - } - *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, KsbaCert 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, KsbaCert cert, const char *issuer) -{ - KsbaName authid; - KsbaSexp 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); - if (rc == -1) - { /* And try the ephemeral DB. */ - 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 becuase 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) - { - /* 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) - { - 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 has 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 GNUPG_Out_Of_Core; - 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", gnupg_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 (KsbaCert start, KsbaCert *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 = GNUPG_General_Error; - 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 = GNUPG_Bad_Certificate; - goto leave; - } - if (!subject) - { - log_error ("no subject found in certificate\n"); - rc = GNUPG_Bad_Certificate; - goto leave; - } - - if (!strcmp (issuer, subject)) - { - rc = -1; /* we are at the root */ - goto leave; - } - - rc = find_up (kh, start, issuer); - 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 = GNUPG_Missing_Certificate; - goto leave; - } - - rc = keydb_get_cert (kh, r_next); - if (rc) - { - log_error ("failed to get cert: rc=%d\n", rc); - rc = GNUPG_General_Error; - } - - 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 (KsbaCert 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; -} - - -/* Validate a chain and optionally return the nearest expiration time - in R_EXPTIME */ -int -gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, time_t *r_exptime) -{ - int rc = 0, depth = 0, maxdepth; - char *issuer = NULL; - char *subject = NULL; - KEYDB_HANDLE kh = keydb_new (0); - KsbaCert subject_cert = NULL, issuer_cert = NULL; - time_t current_time = gnupg_get_time (); - time_t exptime = 0; - 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; - - if (r_exptime) - *r_exptime = 0; - - if (opt.no_chain_validation) - { - log_info ("WARNING: bypassing certificate chain validation\n"); - return 0; - } - - if (!kh) - { - log_error (_("failed to allocated keyDB handle\n")); - rc = GNUPG_General_Error; - goto leave; - } - - if (DBG_X509) - 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) - { - log_error ("no issuer found in certificate\n"); - rc = GNUPG_Bad_Certificate; - goto leave; - } - - { - time_t not_before, not_after; - - not_before = ksba_cert_get_validity (subject_cert, 0); - not_after = ksba_cert_get_validity (subject_cert, 1); - if (not_before == (time_t)(-1) || not_after == (time_t)(-1)) - { - log_error ("certificate with invalid validity\n"); - rc = GNUPG_Bad_Certificate; - goto leave; - } - - if (not_after) - { - if (!exptime) - exptime = not_after; - else if (not_after < exptime) - exptime = not_after; - } - - if (not_before && current_time < not_before) - { - log_error ("certificate too young; valid from "); - gpgsm_dump_time (not_before); - log_printf ("\n"); - rc = GNUPG_Certificate_Too_Young; - goto leave; - } - if (not_after && current_time > not_after) - { - log_error ("certificate has expired at "); - gpgsm_dump_time (not_after); - log_printf ("\n"); - any_expired = 1; - } - } - - rc = unknown_criticals (subject_cert); - if (rc) - goto leave; - - if (!opt.no_policy_check) - { - rc = check_cert_policy (subject_cert); - if (rc == GNUPG_No_Policy_Match) - { - any_no_policy_match = 1; - rc = 1; - } - else if (rc) - goto leave; - } - - if (!opt.no_crl_check) - { - rc = gpgsm_dirmngr_isvalid (subject_cert); - if (rc) - { - switch (rc) - { - case GNUPG_Certificate_Revoked: - log_error (_("the certificate has been revoked\n")); - any_revoked = 1; - break; - case GNUPG_No_CRL_Known: - log_error (_("no CRL found for certificate\n")); - any_no_crl = 1; - break; - case GNUPG_CRL_Too_Old: - log_error (_("the available CRL is too old\n")); - log_info (_("please make sure that the " - "\"dirmngr\" is properly installed\n")); - any_crl_too_old = 1; - break; - default: - log_error (_("checking the CRL failed: %s\n"), - gnupg_strerror (rc)); - goto leave; - } - rc = 0; - } - } - - if (subject && !strcmp (issuer, subject)) - { - if (gpgsm_check_cert_sig (subject_cert, subject_cert) ) - { - log_error ("selfsigned certificate has a BAD signatures\n"); - rc = depth? GNUPG_Bad_Certificate_Chain : GNUPG_Bad_Certificate; - goto leave; - } - rc = allowed_ca (subject_cert, NULL); - if (rc) - goto leave; - - rc = gpgsm_agent_istrusted (subject_cert); - if (!rc) - ; - else if (rc == GNUPG_Not_Trusted) - { - int rc2; - - char *fpr = gpgsm_get_fingerprint_string (subject_cert, - GCRY_MD_SHA1); - log_info (_("root certificate is not marked trusted\n")); - log_info (_("fingerprint=%s\n"), fpr? fpr : "?"); - xfree (fpr); - rc2 = gpgsm_agent_marktrusted (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 enter it manually into " - "\"~/.gnupg-test/trustlist.txt\"\n"); - } - } - else - { - log_error (_("checking the trust list failed: %s\n"), - gnupg_strerror (rc)); - } - - break; /* okay, a self-signed certicate is an end-point */ - } - - depth++; - if (depth > maxdepth) - { - log_error (_("certificate chain too long\n")); - rc = GNUPG_Bad_Certificate_Chain; - goto leave; - } - - /* find the next cert up the tree */ - keydb_search_reset (kh); - rc = find_up (kh, subject_cert, issuer); - 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 = GNUPG_Missing_Certificate; - 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 = GNUPG_General_Error; - goto leave; - } - - if (DBG_X509) - { - log_debug ("got issuer's certificate:\n"); - gpgsm_dump_cert ("issuer", issuer_cert); - } - - if (gpgsm_check_cert_sig (issuer_cert, subject_cert) ) - { - log_error ("certificate has a BAD signatures\n"); - rc = GNUPG_Bad_Certificate_Chain; - goto leave; - } - - { - int chainlen; - rc = allowed_ca (issuer_cert, &chainlen); - if (rc) - goto leave; - if (chainlen >= 0 && (depth - 1) > chainlen) - { - log_error (_("certificate chain longer than allowed by CA (%d)\n"), - chainlen); - rc = GNUPG_Bad_Certificate_Chain; - goto leave; - } - } - - rc = gpgsm_cert_use_cert_p (issuer_cert); - if (rc) - { - gpgsm_status2 (ctrl, STATUS_ERROR, "certcert.issuer.keyusage", - gnupg_error_token (rc), NULL); - rc = 0; - } - - if (opt.verbose) - log_info ("certificate is good\n"); - - keydb_search_reset (kh); - subject_cert = issuer_cert; - issuer_cert = NULL; - } - - if (opt.no_policy_check) - log_info ("policies not checked due to --disable-policy-checks option\n"); - if (opt.no_crl_check) - log_info ("CRLs not checked due to --disable-crl-checks option\n"); - - if (!rc) - { /* If we encountered an error somewhere during the checks, set - the error code to the most critical one */ - if (any_revoked) - rc = GNUPG_Certificate_Revoked; - else if (any_no_crl) - rc = GNUPG_No_CRL_Known; - else if (any_crl_too_old) - rc = GNUPG_CRL_Too_Old; - else if (any_no_policy_match) - rc = GNUPG_No_Policy_Match; - else if (any_expired) - rc = GNUPG_Certificate_Expired; - } - - leave: - if (r_exptime) - *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 (KsbaCert cert) -{ - int rc = 0; - char *issuer = NULL; - char *subject = NULL; - KEYDB_HANDLE kh = keydb_new (0); - KsbaCert 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 = GNUPG_General_Error; - 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 = GNUPG_Bad_Certificate; - goto leave; - } - - if (subject && !strcmp (issuer, subject)) - { - if (gpgsm_check_cert_sig (cert, cert) ) - { - log_error ("selfsigned certificate has a BAD signatures\n"); - rc = GNUPG_Bad_Certificate; - goto leave; - } - } - else - { - /* find the next cert up the tree */ - keydb_search_reset (kh); - rc = find_up (kh, cert, issuer); - 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 = GNUPG_Missing_Certificate; - 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 = GNUPG_General_Error; - goto leave; - } - - if (gpgsm_check_cert_sig (issuer_cert, cert) ) - { - log_error ("certificate has a BAD signatures\n"); - rc = GNUPG_Bad_Certificate; - 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 37d2b00df..000000000 --- a/sm/certcheck.c +++ /dev/null @@ -1,301 +0,0 @@ -/* certcheck.c - check one certificate - * 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 <gcrypt.h> -#include <ksba.h> - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - - -static int -do_encode_md (GCRY_MD_HD md, int algo, unsigned int nbits, - GCRY_MPI *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 GNUPG_Internal_Error; - } - - 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 GNUPG_Internal_Error; - } - - /* 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 GNUPG_Out_Of_Core; - 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, &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 (KsbaCert issuer_cert, KsbaCert cert) -{ - const char *algoid; - GCRY_MD_HD md; - int rc, algo; - GCRY_MPI frame; - KsbaSexp p; - size_t n; - GCRY_SEXP 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 GNUPG_General_Error; - } - md = gcry_md_open (algo, 0); - if (!md) - { - log_error ("md_open failed: %s\n", gcry_strerror (-1)); - return GNUPG_General_Error; - } - 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", ksba_strerror (rc)); - gcry_md_close (md); - return map_ksba_err (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 GNUPG_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", gcry_strerror (rc)); - gcry_md_close (md); - return map_gcry_err (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 GNUPG_Bug; - } - rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n); - ksba_free (p); - if (rc) - { - log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc)); - gcry_md_close (md); - gcry_sexp_release (s_sig); - return map_gcry_err (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", gcry_strerror (rc)); - gcry_md_close (md); - gcry_sexp_release (s_sig); - gcry_sexp_release (s_hash); - gcry_sexp_release (s_pkey); - return map_gcry_err (rc); -} - - - -int -gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval, - GCRY_MD_HD md, int algo) -{ - int rc; - KsbaSexp p; - GCRY_MPI frame; - GCRY_SEXP 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 GNUPG_Bug; - } - rc = gcry_sexp_sscan (&s_sig, NULL, sigval, n); - if (rc) - { - log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc)); - return map_gcry_err (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 GNUPG_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", gcry_strerror (rc)); - gcry_sexp_release (s_sig); - return map_gcry_err (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", gcry_strerror (rc)); - gcry_sexp_release (s_sig); - gcry_sexp_release (s_hash); - gcry_sexp_release (s_sig); - return map_gcry_err (rc); -} - - - -int -gpgsm_create_cms_signature (KsbaCert cert, GCRY_MD_HD md, int mdalgo, - char **r_sigval) -{ - int rc; - char *grip; - size_t siglen; - - grip = gpgsm_get_keygrip_hexstring (cert); - if (!grip) - return seterr (Bad_Certificate); - - rc = gpgsm_agent_pksign (grip, gcry_md_read(md, mdalgo), - gcry_md_get_algo_dlen (mdalgo), mdalgo, - r_sigval, &siglen); - xfree (grip); - return rc; -} - - - diff --git a/sm/certdump.c b/sm/certdump.c deleted file mode 100644 index 9afb1154d..000000000 --- a/sm/certdump.c +++ /dev/null @@ -1,457 +0,0 @@ -/* certdump.c - Dump a certificate for debugging - * 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 <gcrypt.h> -#include <ksba.h> - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - -struct dn_array_s { - char *key; - char *value; -}; - - -/* print the first element of an S-Expression */ -void -gpgsm_print_serial (FILE *fp, KsbaConstSexp p) -{ - unsigned long n; - KsbaConstSexp endp; - - if (!p) - fputs (_("none"), fp); - else if (*p != '(') - fputs ("[Internal error - not an S-expression]", fp); - else - { - p++; - n = strtoul (p, (char**)&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 (KsbaConstSexp p) -{ - unsigned long n; - KsbaConstSexp endp; - - if (!p) - log_printf ("none"); - else if (*p != '(') - log_printf ("ERROR - not an S-expression"); - else - { - p++; - n = strtoul (p, (char**)&endp, 10); - p = endp; - if (*p!=':') - log_printf ("ERROR - invalid S-expression"); - else - { - for (p++; n; n--, p++) - log_printf ("%02X", *p); - } - } -} - -void -gpgsm_print_time (FILE *fp, time_t t) -{ - if (!t) - fputs (_("none"), fp); - else if ( t == (time_t)(-1) ) - fputs ("[Error - Invalid time]", fp); - else - { - struct tm *tp; - - tp = gmtime (&t); - fprintf (fp, "%04d-%02d-%02d %02d:%02d:%02d Z", - 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, - tp->tm_hour, tp->tm_min, tp->tm_sec); - assert (!tp->tm_isdst); - } -} - -void -gpgsm_dump_time (time_t t) -{ - - if (!t) - log_printf (_("[none]")); - else if ( t == (time_t)(-1) ) - log_printf (_("[error]")); - else - { - struct tm *tp; - - tp = gmtime (&t); - log_printf ("%04d-%02d-%02d %02d:%02d:%02d", - 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, - tp->tm_hour, tp->tm_min, tp->tm_sec); - assert (!tp->tm_isdst); - } -} - - - - -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 ( " ]"); - } - } -} - - -void -gpgsm_dump_cert (const char *text, KsbaCert cert) -{ - KsbaSexp sexp; - unsigned char *p; - char *dn; - time_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"); - - t = ksba_cert_get_validity (cert, 0); - log_debug (" notBefore: "); - gpgsm_dump_time (t); - log_printf ("\n"); - t = ksba_cert_get_validity (cert, 1); - 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) -{ - const unsigned char *s, *s1; - size_t n; - unsigned char *p; - - /* parse attributeType */ - for (s = string+1; *s && *s != '='; s++) - ; - if (!*s) - return NULL; /* error */ - n = s - string; - if (!n) - return NULL; /* empty key */ - array->key = p = xtrymalloc (n+1); - if (!array->key) - return NULL; - memcpy (p, string, n); - p[n] = 0; - trim_trailing_spaces (p); - if ( !strcmp (p, "1.2.840.113549.1.9.1") ) - strcpy (p, "EMail"); - 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++ = xtoi_2 (s1); - *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); - arrayidx++; - if (!string) - goto failure; - while (*string == ' ') - string++; - 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) -{ - int any = 0; - - for (; dn->key; dn++) - { - if (!strcmp (dn->key, key) && dn->value && *dn->value) - { - putc ('/', fp); - if (any) - fputs (" + ", fp); - else - fprintf (fp, "%s=", key); - print_sanitized_utf8_string (fp, dn->value, '/'); - any = 1; - } - } -} - -/* 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++) - { - for (i=0; stdpart[i]; i++) - { - if (!strcmp (dn->key, stdpart[i])) - break; - } - if (!stdpart[i]) - 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); - } - } -} - - - diff --git a/sm/certlist.c b/sm/certlist.c deleted file mode 100644 index f31e6ee2b..000000000 --- a/sm/certlist.c +++ /dev/null @@ -1,313 +0,0 @@ -/* certlist.c - build list of certificates - * 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 <gcrypt.h> -#include <ksba.h> - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - -/* 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 (KsbaCert cert, int mode) -{ - KsbaError err; - unsigned int use; - - err = ksba_cert_get_key_usage (cert, &use); - if (err == KSBA_No_Data) - { - if (opt.verbose && mode < 2) - log_info (mode? - _("no key usage specified - accepted for encryption\n"): - _("no key usage specified - accepted for signing\n")); - return 0; - } - if (err) - { - log_error (_("error getting key usage information: %s\n"), - ksba_strerror (err)); - return map_ksba_err (err); - } - - if (mode == 4) - { - if ((use & (KSBA_KEYUSAGE_KEY_CERT_SIGN))) - return 0; - log_info ( _("certificate should have not been used certification\n")); - return GNUPG_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 GNUPG_Wrong_Key_Usage; -} - - -/* Return 0 if the cert is usable for signing */ -int -gpgsm_cert_use_sign_p (KsbaCert cert) -{ - return cert_usage_p (cert, 0); -} - - -/* Return 0 if the cert is usable for encryption */ -int -gpgsm_cert_use_encrypt_p (KsbaCert cert) -{ - return cert_usage_p (cert, 1); -} - -int -gpgsm_cert_use_verify_p (KsbaCert cert) -{ - return cert_usage_p (cert, 2); -} - -int -gpgsm_cert_use_decrypt_p (KsbaCert cert) -{ - return cert_usage_p (cert, 3); -} - -int -gpgsm_cert_use_cert_p (KsbaCert cert) -{ - return cert_usage_p (cert, 4); -} - - -static int -same_subject_issuer (const char *subject, const char *issuer, KsbaCert 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; -} - - - -/* 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 - avaibale for the certificate. */ -int -gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, - CERTLIST *listaddr) -{ - int rc; - KEYDB_SEARCH_DESC desc; - KEYDB_HANDLE kh = NULL; - KsbaCert cert = NULL; - - rc = keydb_classify_name (name, &desc); - if (!rc) - { - kh = keydb_new (0); - if (!kh) - rc = GNUPG_Out_Of_Core; - 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 (rc == GNUPG_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) - { - KsbaCert 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) - && ((secret? gpgsm_cert_use_sign_p (cert2): - gpgsm_cert_use_encrypt_p (cert2)) - == GNUPG_Wrong_Key_Usage)); - ksba_cert_release (cert2); - if (tmp) - goto next_ambigious; - } - rc = GNUPG_Ambiguous_Name; - } - } - xfree (subject); - xfree (issuer); - - if (!rc && secret) - { - char *p; - - rc = GNUPG_No_Secret_Key; - p = gpgsm_get_keygrip_hexstring (cert); - if (p) - { - if (!gpgsm_agent_havekey (p)) - rc = 0; - xfree (p); - } - } - if (!rc) - rc = gpgsm_validate_chain (ctrl, cert, NULL); - if (!rc) - { - CERTLIST cl = xtrycalloc (1, sizeof *cl); - if (!cl) - rc = GNUPG_Out_Of_Core; - else - { - cl->cert = cert; cert = NULL; - cl->next = *listaddr; - *listaddr = cl; - } - } - } - } - - keydb_release (kh); - ksba_cert_release (cert); - return rc == -1? GNUPG_No_Public_Key: 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, KsbaCert *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 = GNUPG_Out_Of_Core; - 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 = GNUPG_Ambiguous_Name; - ksba_cert_release (*r_cert); - *r_cert = NULL; - } - } - } - } - - keydb_release (kh); - return rc == -1? GNUPG_No_Public_Key: rc; -} - diff --git a/sm/certreqgen.c b/sm/certreqgen.c deleted file mode 100644 index 600a278bc..000000000 --- a/sm/certreqgen.c +++ /dev/null @@ -1,699 +0,0 @@ -/* certreqgen.c - Generate a key and a certification request - * 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 - */ - -/* -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: joe@foo.bar -# 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 <gcrypt.h> -#include <ksba.h> - -#include "gpgsm.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; - KsbaWriter writer; -}; - - -static int proc_parameters (struct para_data_s *para, - struct reqgen_ctrl_s *outctrl); -static int create_request (struct para_data_s *para, - KsbaConstSexp 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; - - 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 (FILE *fp, KsbaWriter 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 (; !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 (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 (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 = GNUPG_General_Error; - } - else if (ferror(fp)) - { - log_error ("line %d: read error: %s\n", outctrl.lnr, strerror(errno) ); - rc = GNUPG_General_Error; - } - else if (para) - { - rc = proc_parameters (para, &outctrl); - if (rc) - goto leave; - any = 1; - } - - if (!rc && !any) - rc = GNUPG_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 (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; - KsbaSexp 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 becuase 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 GNUPG_Invalid_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 GNUPG_Invalid_Parameter; - } - - /* check the usage */ - if (parse_parameter_usage (para, pKEYUSAGE)) - return GNUPG_Invalid_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 GNUPG_Invalid_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 GNUPG_Invalid_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 (keyparms, &public); - if (rc) - { - r = get_parameter (para, pKEYTYPE); - log_error ("line %d: key generation failed: %s\n", - r->lnr, gnupg_strerror (rc)); - return rc; - } - - rc = create_request (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 (struct para_data_s *para, KsbaConstSexp public, - struct reqgen_ctrl_s *outctrl) -{ - KsbaCertreq cr; - KsbaError err; - GCRY_MD_HD md; - KsbaStopReason stopreason; - int rc = 0; - const char *s; - - cr = ksba_certreq_new (); - if (!cr) - return seterr (Out_Of_Core); - - md = gcry_md_open (GCRY_MD_SHA1, 0); - if (!md) - { - log_error ("md_open failed: %s\n", gcry_strerror (-1)); - rc = map_gcry_err (gcry_errno ()); - 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", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - s = get_parameter_value (para, pNAMEEMAIL); - if (s) - { - char *buf = xtrymalloc (strlen (s) + 3); - - if (!buf) - { - rc = GNUPG_Out_Of_Core; - 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", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - } - - - err = ksba_certreq_set_public_key (cr, public); - if (err) - { - log_error ("error setting the public key: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - do - { - err = ksba_certreq_build (cr, &stopreason); - if (err) - { - log_error ("ksba_certreq_build failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - if (stopreason == KSBA_SR_NEED_SIG) - { - GCRY_SEXP 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 = GNUPG_Bug; - goto leave; - } - rc = gcry_sexp_sscan (&s_pkey, NULL, public, n); - if (rc) - { - log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc)); - rc = map_gcry_err (rc); - goto leave; - } - if ( !gcry_pk_get_keygrip (s_pkey, grip) ) - { - rc = seterr (General_Error); - 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 (hexgrip, - 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", gnupg_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", - ksba_strerror (err)); - rc = map_ksba_err (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 ctrl, int in_fd, FILE *out_fp) -{ - int rc; - FILE *in_fp; - Base64Context b64writer = NULL; - KsbaWriter writer; - - in_fp = fdopen (dup (in_fd), "rb"); - if (!in_fp) - { - log_error ("fdopen() failed: %s\n", strerror (errno)); - return seterr (IO_Error); - } - - 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", gnupg_strerror (rc)); - goto leave; - } - - rc = read_parameters (in_fp, writer); - if (rc) - { - log_error ("error creating certificate request: %s\n", - gnupg_strerror (rc)); - goto leave; - } - - rc = gpgsm_finish_writer (b64writer); - if (rc) - { - log_error ("write failed: %s\n", gnupg_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 012254e22..000000000 --- a/sm/decrypt.c +++ /dev/null @@ -1,502 +0,0 @@ -/* decrypt.c - Decrypt a message - * 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 <gcrypt.h> -#include <ksba.h> - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - -struct decrypt_filter_parm_s { - int algo; - int mode; - int blklen; - GCRY_CIPHER_HD 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 (const char *hexkeygrip, KsbaConstSexp enc_val, - struct decrypt_filter_parm_s *parm) -{ - char *seskey = NULL; - size_t n, seskeylen; - int rc; - - rc = gpgsm_agent_pkdecrypt (hexkeygrip, enc_val, - &seskey, &seskeylen); - if (rc) - { - log_error ("error decrypting session key: %s\n", gnupg_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. fixme! */ - } - else - { - if (n + 7 > seskeylen ) - { - rc = seterr (Invalid_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 rightway 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 = seterr (Invalid_Session_Key); - goto leave; - } - - for (n++; n < seskeylen && seskey[n]; n++) /* skip the random bytes */ - ; - n++; /* and the zero byte */ - if (n >= seskeylen ) - { - rc = seterr (Invalid_Session_Key); - goto leave; - } - } - - if (DBG_CRYPTO) - log_printhex ("session key:", seskey+n, seskeylen-n); - - parm->hd = gcry_cipher_open (parm->algo, parm->mode, 0); - if (!parm->hd) - { - rc = gcry_errno (); - log_error ("error creating decryptor: %s\n", gcry_strerror (rc)); - rc = map_gcry_err (rc); - goto leave; - } - - rc = gcry_cipher_setkey (parm->hd, seskey+n, seskeylen-n); - if (rc == GCRYERR_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", gcry_strerror(rc) ); - rc = map_gcry_err (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 KsbaError -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 KSBA_Bug; - - if (maxoutlen < 2*parm->blklen) - return KSBA_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 KSBA_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 ctrl, int in_fd, FILE *out_fp) -{ - int rc; - KsbaError err; - Base64Context b64reader = NULL; - Base64Context b64writer = NULL; - KsbaReader reader; - KsbaWriter writer; - KsbaCMS cms = NULL; - KsbaStopReason 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 = GNUPG_General_Error; - goto leave; - } - - - in_fp = fdopen ( dup (in_fd), "rb"); - if (!in_fp) - { - log_error ("fdopen() failed: %s\n", strerror (errno)); - rc = seterr (IO_Error); - goto leave; - } - - rc = gpgsm_create_reader (&b64reader, ctrl, in_fp, &reader); - if (rc) - { - log_error ("can't create reader: %s\n", gnupg_strerror (rc)); - goto leave; - } - - rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer); - if (rc) - { - log_error ("can't create writer: %s\n", gnupg_strerror (rc)); - goto leave; - } - - cms = ksba_cms_new (); - if (!cms) - { - rc = seterr (Out_Of_Core); - goto leave; - } - - err = ksba_cms_set_reader_writer (cms, reader, writer); - if (err) - { - log_debug ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - /* parser loop */ - do - { - err = ksba_cms_parse (cms, &stopreason); - if (err) - { - log_debug ("ksba_cms_parse failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); - 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 = GNUPG_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")); - gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm", - gnupg_error_token (rc), algoid?algoid:"?", NULL); - goto leave; - } - dfparm.algo = algo; - dfparm.mode = mode; - dfparm.blklen = gcry_cipher_get_algo_blklen (algo); - if (dfparm.blklen > sizeof (dfparm.helpblock)) - return GNUPG_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", ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - for (recp=0; !any_key; recp++) - { - char *issuer; - KsbaSexp serial; - KsbaSexp enc_val; - char *hexkeygrip = NULL; - - err = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial); - if (err == -1 && recp) - break; /* no more recipients */ - if (err) - log_error ("recp %d - error getting info: %s\n", - recp, ksba_strerror (err)); - else - { - KsbaCert 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", - gnupg_strerror(rc)); - goto oops; - } - - rc = keydb_get_cert (kh, &cert); - if (rc) - { - log_error ("failed to get cert: %s\n", gnupg_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) - { - gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.keyusage", - gnupg_error_token (rc), NULL); - rc = 0; - } - - hexkeygrip = gpgsm_get_keygrip_hexstring (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 (hexkeygrip, enc_val, &dfparm); - xfree (enc_val); - if (rc) - { - log_debug ("decrypting session key failed: %s\n", - gnupg_strerror (rc)); - } - else - { /* setup the bulk decrypter */ - any_key = 1; - ksba_writer_set_filter (writer, - decrypt_filter, - &dfparm); - } - } - } - if (!any_key) - { - rc = GNUPG_No_Secret_Key; - 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 = seterr (Invalid_Data); - goto leave; - } - rc = ksba_writer_write (writer, - dfparm.lastblock, - dfparm.blklen - npadding); - if (rc) - { - rc = map_ksba_err (rc); - goto leave; - } - for (i=dfparm.blklen - npadding; i < dfparm.blklen; i++) - { - if (dfparm.lastblock[i] != npadding) - { - log_error ("inconsistent padding\n"); - rc = seterr (Invalid_Data); - goto leave; - } - } - } - } - - } - while (stopreason != KSBA_SR_READY); - - rc = gpgsm_finish_writer (b64writer); - if (rc) - { - log_error ("write failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - gpgsm_status (ctrl, STATUS_DECRYPTION_OKAY, NULL); - - - leave: - if (rc) - gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL); - 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 cd1491a86..000000000 --- a/sm/delete.c +++ /dev/null @@ -1,165 +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 <gcrypt.h> -#include <ksba.h> - -#include "gpgsm.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; - KsbaCert cert = NULL; - int duplicates = 0; - - rc = keydb_classify_name (username, &desc); - if (rc) - { - log_error (_("certificate `%s' not found: %s\n"), - username, gnupg_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) - { - KsbaCert 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 = GNUPG_Ambiguous_Name; - } - } - if (rc) - { - if (rc == -1) - rc = GNUPG_No_Public_Key; - log_error (_("certificate `%s' not found: %s\n"), - username, gnupg_strerror (rc)); - gpgsm_status2 (ctrl, STATUS_DELETE_PROBLEM, "3", NULL); - goto leave; - } - - /* we need to search again to get back to the right position. */ - do - { - keydb_search_reset (kh); - rc = keydb_search (kh, &desc, 1); - if (rc) - { - log_error ("problem re-searching certificate: %s\n", - gnupg_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 GNUPG_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, gnupg_strerror (rc) ); - return rc; - } - } - - return 0; -} diff --git a/sm/encrypt.c b/sm/encrypt.c deleted file mode 100644 index 40e12582f..000000000 --- a/sm/encrypt.c +++ /dev/null @@ -1,549 +0,0 @@ -/* encrypt.c - Encrypt a message - * 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 <gcrypt.h> -#include <ksba.h> - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - - -struct dek_s { - const char *algoid; - int algo; - GCRY_CIPHER_HD 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 encryptionkey (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 GNUPG_Unsupported_Algorithm; - } - - dek->keylen = gcry_cipher_get_algo_keylen (dek->algo); - if (!dek->keylen || dek->keylen > sizeof (dek->key)) - return GNUPG_Bug; - - dek->ivlen = gcry_cipher_get_algo_blklen (dek->algo); - if (!dek->ivlen || dek->ivlen > sizeof (dek->iv)) - return GNUPG_Bug; - - if (dek->keylen < 100/8) - { /* make sure we don't use weak keys */ - log_error ("key length of `%s' too small\n", dek->algoid); - return GNUPG_Unsupported_Algorithm; - } - - dek->chd = gcry_cipher_open (dek->algo, mode, GCRY_CIPHER_SECURE); - if (!dek->chd) - { - log_error ("failed to create cipher context: %s\n", gcry_strerror (-1)); - return GNUPG_General_Error; - } - - 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 (rc != GCRYERR_WEAK_KEY) - break; - log_info(_("weak key created - retrying\n") ); - } - if (rc) - { - log_error ("failed to set the key: %s\n", gcry_strerror (rc)); - gcry_cipher_close (dek->chd); - dek->chd = NULL; - return map_gcry_err (rc); - } - - gcry_randomize (dek->iv, dek->ivlen, GCRY_STRONG_RANDOM); - rc = gcry_cipher_setiv (dek->chd, dek->iv, dek->ivlen); - if (rc) - { - log_error ("failed to set the IV: %s\n", gcry_strerror (rc)); - gcry_cipher_close (dek->chd); - dek->chd = NULL; - return map_gcry_err (rc); - } - - return 0; -} - - -/* Encode the session key. NBITS is the number of bits which should be - used for packing the session key. returns: An mpi with the session - key (caller must free) */ -static GCRY_MPI -encode_session_key (DEK dek, unsigned int nbits) -{ - int nframe = (nbits+7) / 8; - byte *p; - byte *frame; - int i,n; - MPI a; - - if (dek->keylen + 7 > nframe || !nframe) - log_bug ("can't encode a %d bit key in a %d bits frame\n", - dek->keylen*8, nbits ); - - /* We encode the session key in this way: - * - * 0 2 RND(n bytes) 0 KEY(k bytes) - * - * (But how can we store the leading 0 - the external representaion - * of MPIs doesn't allow leading zeroes =:-) - * - * RND are non-zero random bytes. - * KEY is the encryption key (session key) - */ - - frame = gcry_xmalloc_secure (nframe); - n = 0; - frame[n++] = 0; - frame[n++] = 2; - i = nframe - 3 - dek->keylen; - assert (i > 0); - p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM); - /* replace zero bytes by new values */ - for (;;) - { - int j, k; - byte *pp; - - /* count the zero bytes */ - for(j=k=0; j < i; j++ ) - { - if( !p[j] ) - k++; - } - if( !k ) - break; /* okay: no zero bytes */ - - k += k/128; /* better get some more */ - pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM); - for (j=0; j < i && k; j++) - { - if( !p[j] ) - p[j] = pp[--k]; - } - xfree (pp); - } - memcpy (frame+n, p, i); - xfree (p); - - n += i; - frame[n++] = 0; - memcpy (frame+n, dek->key, dek->keylen); - n += dek->keylen; - assert (n == nframe); - if (gcry_mpi_scan (&a, GCRYMPI_FMT_USG, frame, &nframe) ) - BUG (); - gcry_free(frame); - - return a; -} - - - -/* 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, KsbaCert cert, char **encval) -{ - GCRY_SEXP s_ciph, s_data, s_pkey; - int rc; - KsbaSexp 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 GNUPG_No_Public_Key; - } - len = gcry_sexp_canon_len (buf, 0, NULL, NULL); - if (!len) - { - log_error ("libksba did not return a proper S-Exp\n"); - return GNUPG_Bug; - } - rc = gcry_sexp_sscan (&s_pkey, NULL, buf, len); - xfree (buf); buf = NULL; - if (rc) - { - log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc)); - return map_gcry_err (rc); - } - - /* put the encoded cleartext into a simple list */ - { - /* fixme: actually the pkcs-1 encoding should go into libgcrypt */ - GCRY_MPI data = encode_session_key (dek, gcry_pk_get_nbits (s_pkey)); - if (!data) - { - gcry_mpi_release (data); - return GNUPG_General_Error; - } - if (gcry_sexp_build (&s_data, NULL, "%m", data)) - BUG (); - gcry_mpi_release (data); - } - - /* 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) - { - gcry_sexp_release (s_ciph); - return GNUPG_Out_Of_Core; - } - 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; - KsbaError err; - KsbaWriter writer; - KsbaReader reader = NULL; - KsbaCMS cms = NULL; - KsbaStopReason 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); - - if (!recplist) - { - log_error(_("no valid recipients given\n")); - gpgsm_status (ctrl, STATUS_NO_RECP, "0"); - rc = GNUPG_No_Public_Key; - goto leave; - } - - kh = keydb_new (0); - if (!kh) - { - log_error (_("failed to allocated keyDB handle\n")); - rc = GNUPG_General_Error; - goto leave; - } - - data_fp = fdopen ( dup (data_fd), "rb"); - if (!data_fp) - { - log_error ("fdopen() failed: %s\n", strerror (errno)); - rc = seterr (IO_Error); - goto leave; - } - - reader = ksba_reader_new (); - if (!reader) - rc = KSBA_Out_Of_Core; - if (!rc) - rc = ksba_reader_set_cb (reader, encrypt_cb, &encparm); - if (rc) - { - rc = map_ksba_err (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", gnupg_strerror (rc)); - goto leave; - } - - cms = ksba_cms_new (); - if (!cms) - { - rc = seterr (Out_Of_Core); - goto leave; - } - - err = ksba_cms_set_reader_writer (cms, reader, writer); - if (err) - { - log_debug ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (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", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - /* create a session key */ - dek = xtrycalloc (1, sizeof *dek); /* hmmm: should we put it into secmem?*/ - if (!dek) - rc = GNUPG_Out_Of_Core; - else - { - dek->algoid = opt.def_cipher_algoid; - rc = init_dek (dek); - } - if (rc) - { - log_error ("failed to create the session key: %s\n", - gnupg_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", - ksba_strerror (err)); - rc = map_ksba_err (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 = seterr (Out_Of_Core); - 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, gnupg_strerror (rc)); - goto leave; - } - - err = ksba_cms_add_recipient (cms, cl->cert); - if (err) - { - log_error ("ksba_cms_add_recipient failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (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", - ksba_strerror (err)); - rc = map_ksba_err (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", ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - } - while (stopreason != KSBA_SR_READY); - - if (encparm.readerror) - { - log_error ("error reading input: %s\n", strerror (encparm.readerror)); - rc = seterr (Read_Error); - goto leave; - } - - - rc = gpgsm_finish_writer (b64writer); - if (rc) - { - log_error ("write failed: %s\n", gnupg_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 042850752..000000000 --- a/sm/export.c +++ /dev/null @@ -1,248 +0,0 @@ -/* export.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 <gcrypt.h> -#include <ksba.h> - -#include "gpgsm.h" -#include "keydb.h" - -static void print_short_info (KsbaCert cert, FILE *fp); - - - -/* Export all certificates or just those given in NAMES. */ -void -gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp) -{ - KEYDB_HANDLE hd; - KEYDB_SEARCH_DESC *desc = NULL; - int ndesc; - Base64Context b64writer = NULL; - KsbaWriter writer; - STRLIST sl; - KsbaCert cert = NULL; - int rc=0; - int count = 0; - int i; - - 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 ("%s\n", gnupg_strerror (GNUPG_Out_Of_Core)); - 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, gnupg_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))) - { - const unsigned char *image; - size_t imagelen; - - 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", gnupg_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) - { - 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", gnupg_strerror (rc)); - goto leave; - } - } - - rc = ksba_writer_write (writer, image, imagelen); - if (rc) - { - log_error ("write error: %s\n", ksba_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", gnupg_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", gnupg_strerror (rc)); - else if (b64writer) - { - rc = gpgsm_finish_writer (b64writer); - if (rc) - { - log_error ("write failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - } - - leave: - 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 (KsbaCert cert, FILE *fp) -{ - char *p; - KsbaSexp 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); -} - - - - - - diff --git a/sm/fingerprint.c b/sm/fingerprint.c deleted file mode 100644 index 6a84966db..000000000 --- a/sm/fingerprint.c +++ /dev/null @@ -1,271 +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 <gcrypt.h> -#include <ksba.h> - -#include "gpgsm.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 (KsbaCert cert, int algo, char *array, int *r_len) -{ - GCRY_MD_HD 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; - - md = gcry_md_open (algo, 0); - if (!md) - { - log_error ("md_open failed: %s\n", gcry_strerror (-1)); - 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", ksba_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 (KsbaCert 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 (KsbaCert 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 (KsbaCert 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 (KsbaCert cert, char *array) -{ - GCRY_SEXP s_pkey; - int rc; - KsbaSexp 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: %s\n", p); - 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", gcry_strerror (rc)); - return NULL; - } - array = gcry_pk_get_keygrip (s_pkey, array); - gcry_sexp_release (s_pkey); - if (!array) - { - rc = seterr (General_Error); - 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 (KsbaCert 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; -} - - - -/* 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 - delimted from the has by a dot. - - The caller must free the string. -*/ -char * -gpgsm_get_certid (KsbaCert cert) -{ - KsbaSexp 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 bfcdeb741..000000000 --- a/sm/gpgsm.c +++ /dev/null @@ -1,1388 +0,0 @@ -/* gpgsm.c - GnuPG for S/MIME - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <unistd.h> -#include <fcntl.h> - -#include <gcrypt.h> -#include "gpgsm.h" -#include "../assuan/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', - oKOption = '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, - aListKeys, - aListExternalKeys, - aListSigs, - aListSecretKeys, - aSendKeys, - aRecvKeys, - aExport, - aCheckKeys, /* nyi */ - aServer, - aLearnCard, - - oOptions, - oDebug, - oDebugAll, - oDebugWait, - oDebugNoChainValidation, - oLogFile, - - oEnableSpecialFilenames, - - oAgentProgram, - oDisplay, - oTTYname, - oTTYtype, - oLCctype, - oLCmessages, - - oDirmngrProgram, - oFakedSystemTime, - - - oAssumeArmor, - oAssumeBase64, - oAssumeBinary, - - oBase64, - oNoArmor, - - oDisableCRLChecks, - oEnableCRLChecks, - - oIncludeCerts, - oPolicyFile, - oDisablePolicyChecks, - oEnablePolicyChecks, - oAutoIssuerKeyRetrieve, - - - oTextmode, - oFingerprint, - oWithFingerprint, - oAnswerYes, - oAnswerNo, - oKeyring, - oSecretKeyring, - oDefaultKey, - oDefRecipient, - oDefRecipientSelf, - oNoDefRecipient, - oStatusFD, - oNoComment, - oNoVersion, - oEmitVersion, - oCompletesNeeded, - oMarginalsNeeded, - oMaxCertDepth, - oLoadExtension, - oRFC1991, - oOpenPGP, - oCipherAlgo, - oDigestAlgo, - oCompressAlgo, - oPasswdFD, - oCommandFD, - oNoVerbose, - oTrustDBName, - oNoSecmemWarn, - oNoDefKeyring, - oNoGreeting, - oNoTTY, - oNoOptions, - oNoBatch, - oHomedir, - oWithColons, - oWithKeyData, - 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")}, - { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")}, - { 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")}, - { oLogFile, "log-file" ,2, N_("use a log file for the server")}, - - { 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, "@"}, - - { 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, "@" }, - { oEncryptTo, "encrypt-to", 2, "@" }, - { oNoEncryptTo, "no-encrypt-to", 0, "@" }, - -#endif - { 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") }, -#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, "@"}, - { oDebugAll, "debug-all" ,0, "@"}, - { oDebugWait, "debug-wait" ,1, "@"}, - { oDebugNoChainValidation, "debug-no-chain-validation" ,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, "@"}, - - { 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 , "@" }, - { oFakedSystemTime, "faked-system-time", 4, "@" }, /* (epoch time) */ - - - { oNoBatch, "no-batch", 0, "@" }, - { oWithColons, "with-colons", 0, "@"}, - { oWithKeyData,"with-key-data", 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 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); -#else -# ifdef ENABLE_NLS -# ifdef HAVE_LC_MESSAGES - setlocale (LC_TIME, ""); - setlocale (LC_MESSAGES, ""); -# else - setlocale (LC_ALL, "" ); -# endif - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); -# endif -#endif -} - - -static void -wrong_args (const char *text) -{ - fputs (_("usage: gpgsm [options] "), stderr); - fputs (text, stderr); - putc ('\n', stderr); - gpgsm_exit (2); -} - - -static void -set_debug(void) -{ - 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; -} - - -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 default_config =1; - int default_keyring = 1; - char *logfile = NULL; - int greeting = 0; - int nogreeting = 0; - int debug_wait = 0; - 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; - - /* 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); - /* 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; - } - - - /* 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); - 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 (optfile_parse (configfp, configname, &configlineno, &pargs, opts)) - { - switch (pargs.r_opt) - { - case aServer: - opt.batch = 1; - set_cmd (&cmd, aServer); - break; - - case aCheckKeys: set_cmd (&cmd, aCheckKeys); break; - case aImport: set_cmd (&cmd, aImport); break; - case aSendKeys: set_cmd (&cmd, aSendKeys); break; - case aRecvKeys: set_cmd (&cmd, aRecvKeys); break; - case aExport: set_cmd (&cmd, aExport); break; - case aListKeys: set_cmd (&cmd, aListKeys); break; - case aListExternalKeys: set_cmd (&cmd, aListExternalKeys); break; - case aListSecretKeys: set_cmd (&cmd, aListSecretKeys); break; - case aListSigs: set_cmd (&cmd, aListSigs); break; - - case aLearnCard: set_cmd (&cmd, aLearnCard); break; - - case aDeleteKey: - set_cmd (&cmd, aDeleteKey); - /*greeting=1;*/ - break; - - case aDetachedSign: - detached_sig = 1; - set_cmd (&cmd, aSign ); - break; - - case aSym: set_cmd (&cmd, aSym); break; - case aDecrypt: set_cmd (&cmd, aDecrypt); break; - case aEncr: set_cmd (&cmd, aEncr); break; - case aSign: set_cmd (&cmd, aSign ); break; - case aKeygen: set_cmd (&cmd, aKeygen); greeting=1; break; - case aClearsign: set_cmd (&cmd, aClearsign); break; - case aVerify: set_cmd (&cmd, aVerify); 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 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 oDebugWait: debug_wait = pargs.r.ret_int; break; - case oDebugNoChainValidation: opt.no_chain_validation = 1; break; - - case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break; - case oLoggerFD: log_set_fd (pargs.r.ret_int ); break; - 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 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 oSkipVerify: opt.skip_verify=1; break; - - case oNoEncryptTo: /*fixme: 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; - xfree (configname); - configname = NULL; - goto next_pass; - } - - xfree (configname); - configname = 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 ()) - { - log_info (_("WARNING: running with faked system time: ")); - gpgsm_dump_time (gnupg_get_time ()); - log_printf ("\n"); - } - -/*FIXME if (opt.batch) */ -/* tty_batchmode (1); */ - - gcry_control (GCRYCTL_RESUME_SECMEM_WARN); - - set_debug (); - - /* FIXME: should set filenames of libgcrypt explicitly - * gpg_opt_homedir = opt.homedir; */ - - /* 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); -#if 0 -#warning set_random_seed_file not yet available in Libgcrypt - set_random_seed_file(p); -#endif - 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); - - - for (sl = locusr; sl; sl = sl->next) - { - int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist); - if (rc) - { - log_error (_("can't sign using `%s': %s\n"), - sl->d, gnupg_strerror (rc)); - gpgsm_status2 (&ctrl, STATUS_INV_RECP, - rc == -1? "1": - rc == GNUPG_No_Public_Key? "1": - rc == GNUPG_Ambiguous_Name? "2": - rc == GNUPG_Wrong_Key_Usage? "3": - rc == GNUPG_Certificate_Revoked? "4": - rc == GNUPG_Certificate_Expired? "5": - rc == GNUPG_No_CRL_Known? "6": - rc == GNUPG_CRL_Too_Old? "7": - rc == GNUPG_No_Policy_Match? "8": - rc == GNUPG_No_Secret_Key? "9": - "0", - sl->d, NULL); - } - } - for (sl = remusr; sl; sl = sl->next) - { - int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 0, &recplist); - if (rc) - { - log_error (_("can't encrypt to `%s': %s\n"), - sl->d, gnupg_strerror (rc)); - gpgsm_status2 (&ctrl, STATUS_INV_RECP, - rc == -1? "1": - rc == GNUPG_No_Public_Key? "1": - rc == GNUPG_Ambiguous_Name? "2": - rc == GNUPG_Wrong_Key_Usage? "3": - rc == GNUPG_Certificate_Revoked? "4": - rc == GNUPG_Certificate_Expired? "5": - rc == GNUPG_No_CRL_Known? "6": - rc == GNUPG_CRL_Too_Old? "7": - rc == GNUPG_No_Policy_Match? "8": - "0", - sl->d, NULL); - } - } - if (log_get_errorcount(0)) - gpgsm_exit(1); /* must stop for invalid recipients */ - - - - fname = argc? *argv : NULL; - - switch (cmd) - { - 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 (); - 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 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 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 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 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 (); - if (rc) - log_error ("error learning card: %s\n", gnupg_strerror (rc)); - } - 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) -{ - #if 0 -#warning no update_random_seed_file - update_random_seed_file(); - #endif -#if 0 - /* at this time a bit annoying */ - 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 ); -#endif - 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 */ -} - - - -/* 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; -} diff --git a/sm/gpgsm.h b/sm/gpgsm.h deleted file mode 100644 index 50590206e..000000000 --- a/sm/gpgsm.h +++ /dev/null @@ -1,261 +0,0 @@ -/* gpgsm.h - Global definitions for GpgSM - * 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 - */ - -#ifndef GPGSM_H -#define GPGSM_H - -#include <ksba.h> -#include "../common/util.h" -#include "../common/errors.h" - -#define MAX_DIGEST_LEN 24 - -/* A large struct name "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 *agent_program; - char *display; - char *ttyname; - char *ttytype; - char *lc_ctype; - char *lc_messages; - - const char *dirmngr_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 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 */ - - 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 */ - - 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 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 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) */ -}; -typedef struct server_control_s *CTRL; - -/* data structure used in base64.c */ -typedef struct base64_context_s *Base64Context; - - -struct certlist_s { - struct certlist_s *next; - KsbaCert cert; -}; -typedef struct certlist_s *CERTLIST; - -/*-- gpgsm.c --*/ -void gpgsm_exit (int rc); -void gpgsm_init_default_ctrl (struct server_control_s *ctrl); - -/*-- server.c --*/ -void gpgsm_server (void); -void gpgsm_status (CTRL ctrl, int no, const char *text); -void gpgsm_status2 (CTRL ctrl, int no, ...); - -/*-- fingerprint --*/ -char *gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len); -char *gpgsm_get_fingerprint_string (KsbaCert cert, int algo); -char *gpgsm_get_fingerprint_hexstring (KsbaCert cert, int algo); -unsigned long gpgsm_get_short_fingerprint (KsbaCert cert); -char *gpgsm_get_keygrip (KsbaCert cert, char *array); -char *gpgsm_get_keygrip_hexstring (KsbaCert cert); -char *gpgsm_get_certid (KsbaCert cert); - - -/*-- base64.c --*/ -int gpgsm_create_reader (Base64Context *ctx, - CTRL ctrl, FILE *fp, KsbaReader *r_reader); -void gpgsm_destroy_reader (Base64Context ctx); -int gpgsm_create_writer (Base64Context *ctx, - CTRL ctrl, FILE *fp, KsbaWriter *r_writer); -int gpgsm_finish_writer (Base64Context ctx); -void gpgsm_destroy_writer (Base64Context ctx); - - -/*-- certdump.c --*/ -void gpgsm_print_serial (FILE *fp, KsbaConstSexp p); -void gpgsm_print_time (FILE *fp, time_t t); -void gpgsm_print_name (FILE *fp, const char *string); - -void gpgsm_dump_cert (const char *text, KsbaCert cert); -void gpgsm_dump_serial (KsbaConstSexp p); -void gpgsm_dump_time (time_t t); -void gpgsm_dump_string (const char *string); - - - -/*-- certcheck.c --*/ -int gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert); -int gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval, - GCRY_MD_HD md, int hash_algo); -/* fixme: move create functions to another file */ -int gpgsm_create_cms_signature (KsbaCert cert, GCRY_MD_HD md, int mdalgo, - char **r_sigval); - - -/*-- certchain.c --*/ -int gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next); -int gpgsm_is_root_cert (KsbaCert cert); -int gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, time_t *r_exptime); -int gpgsm_basic_cert_check (KsbaCert cert); - -/*-- certlist.c --*/ -int gpgsm_cert_use_sign_p (KsbaCert cert); -int gpgsm_cert_use_encrypt_p (KsbaCert cert); -int gpgsm_cert_use_verify_p (KsbaCert cert); -int gpgsm_cert_use_decrypt_p (KsbaCert cert); -int gpgsm_cert_use_cert_p (KsbaCert cert); -int gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, - CERTLIST *listaddr); -void gpgsm_release_certlist (CERTLIST list); -int gpgsm_find_cert (const char *name, KsbaCert *r_cert); - -/*-- keylist.c --*/ -void gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode); - -/*-- import.c --*/ -int gpgsm_import (CTRL ctrl, int in_fd); -int gpgsm_import_files (CTRL ctrl, int nfiles, char **files, - int (*of)(const char *fname)); - -/*-- export.c --*/ -void gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp); - -/*-- delete.c --*/ -int gpgsm_delete (CTRL ctrl, STRLIST names); - -/*-- verify.c --*/ -int gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp); - -/*-- sign.c --*/ -int gpgsm_get_default_cert (KsbaCert *r_cert); -int gpgsm_sign (CTRL ctrl, CERTLIST signerlist, - int data_fd, int detached, FILE *out_fp); - -/*-- encrypt.c --*/ -int gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int in_fd, FILE *out_fp); - -/*-- decrypt.c --*/ -int gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp); - -/*-- certreqgen.c --*/ -int gpgsm_genkey (CTRL ctrl, int in_fd, FILE *out_fp); - -/*-- call-agent.c --*/ -int gpgsm_agent_pksign (const char *keygrip, - unsigned char *digest, - size_t digestlen, - int digestalgo, - char **r_buf, size_t *r_buflen); -int gpgsm_agent_pkdecrypt (const char *keygrip, - KsbaConstSexp ciphertext, - char **r_buf, size_t *r_buflen); -int gpgsm_agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey); -int gpgsm_agent_istrusted (KsbaCert cert); -int gpgsm_agent_havekey (const char *hexkeygrip); -int gpgsm_agent_marktrusted (KsbaCert cert); -int gpgsm_agent_learn (void); - -/*-- call-dirmngr.c --*/ -int gpgsm_dirmngr_isvalid (KsbaCert cert); -int gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names, - void (*cb)(void*, KsbaCert), void *cb_value); - - - - - -#endif /*GPGSM_H*/ diff --git a/sm/import.c b/sm/import.c deleted file mode 100644 index 2fc6b1a79..000000000 --- a/sm/import.c +++ /dev/null @@ -1,349 +0,0 @@ -/* import.c - Import certificates - * 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 <gcrypt.h> -#include <ksba.h> - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - -struct stats_s { - unsigned long count; - unsigned long imported; - unsigned long unchanged; - unsigned long not_imported; -}; - - - -static void -print_imported_status (CTRL ctrl, KsbaCert cert) -{ - char *fpr; - - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - gpgsm_status2 (ctrl, STATUS_IMPORTED, fpr, "[X.509]", 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, KsbaCert 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->not_imported) - log_info (_(" not imported: %lu\n"), stats->not_imported); - } - - sprintf (buf, "%lu 0 %lu 0 %lu 0 0 0 0 0 0 0 0 %lu", - stats->count, - stats->imported, - stats->unchanged, - stats->not_imported - ); - gpgsm_status (ctrl, STATUS_IMPORT_RES, buf); -} - - - -static void -check_and_store (CTRL ctrl, struct stats_s *stats, KsbaCert cert, int depth) -{ - int rc; - - stats->count++; - if ( depth >= 50 ) - { - log_error (_("certificate chain too long\n")); - stats->not_imported++; - print_import_problem (ctrl, cert, 3); - return; - } - - rc = gpgsm_basic_cert_check (cert); - if (!rc) - { - int existed; - - if (!keydb_store_cert (cert, 0, &existed)) - { - KsbaCert next = NULL; - - if (!existed) - { - print_imported_status (ctrl, cert); - stats->imported++; - } - else - 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.*/ - else if (!gpgsm_walk_cert_chain (cert, &next)) - { - check_and_store (ctrl, stats, next, depth+1); - ksba_cert_release (next); - } - } - else - { - log_error (_("error storing certificate\n")); - stats->not_imported++; - print_import_problem (ctrl, cert, 4); - } - } - else - { - log_error (_("basic certificate checks failed - not imported\n")); - stats->not_imported++; - print_import_problem (ctrl, cert, - rc == GNUPG_Missing_Certificate? 2 : - rc == GNUPG_Bad_Certificate? 1 : 0); - } -} - - - - -static int -import_one (CTRL ctrl, struct stats_s *stats, int in_fd) -{ - int rc; - Base64Context b64reader = NULL; - KsbaReader reader; - KsbaCert cert = NULL; - KsbaCMS cms = NULL; - FILE *fp = NULL; - KsbaContentType ct; - - fp = fdopen ( dup (in_fd), "rb"); - if (!fp) - { - log_error ("fdopen() failed: %s\n", strerror (errno)); - rc = seterr (IO_Error); - goto leave; - } - - rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader); - if (rc) - { - log_error ("can't create reader: %s\n", gnupg_strerror (rc)); - goto leave; - } - - ct = ksba_cms_identify (reader); - if (ct == KSBA_CT_SIGNED_DATA) - { /* This is probably a signed-only message - import the certs */ - KsbaStopReason stopreason; - int i; - - cms = ksba_cms_new (); - if (!cms) - { - rc = seterr (Out_Of_Core); - goto leave; - } - - rc = ksba_cms_set_reader_writer (cms, reader, NULL); - if (rc) - { - log_error ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (rc)); - rc = map_ksba_err (rc); - goto leave; - } - - - do - { - rc = ksba_cms_parse (cms, &stopreason); - if (rc) - { - log_error ("ksba_cms_parse failed: %s\n", ksba_strerror (rc)); - rc = map_ksba_err (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 if (ct == KSBA_CT_NONE) - { /* Failed to identify this message - assume a certificate */ - - cert = ksba_cert_new (); - if (!cert) - { - rc = seterr (Out_Of_Core); - goto leave; - } - - rc = ksba_cert_read_der (cert, reader); - if (rc) - { - rc = map_ksba_err (rc); - goto leave; - } - - check_and_store (ctrl, stats, cert, 0); - } - else - { - log_error ("can't extract certificates from input\n"); - rc = GNUPG_No_Data; - } - - leave: - 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"), gnupg_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"), gnupg_strerror (rc)); - return rc; -} - - diff --git a/sm/keydb.c b/sm/keydb.c deleted file mode 100644 index 5b5722d3e..000000000 --- a/sm/keydb.c +++ /dev/null @@ -1,1282 +0,0 @@ -/* keydb.c - key database dispatcher - * 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 <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 = GNUPG_General_Error; - 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 = GNUPG_General_Error; - goto leave; - - case KEYDB_RESOURCE_TYPE_KEYBOX: - fp = fopen (filename, "rb"); - if (!fp && !force) - { - rc = GNUPG_File_Open_Error; - 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 = GNUPG_File_Open_Error; - *last_slash_in_filename = DIRSEP_C; - goto leave; - } - *last_slash_in_filename = DIRSEP_C; - } -#endif - fp = fopen (filename, "w"); - if (!fp) - { - log_error (_("error creating keybox `%s': %s\n"), - filename, strerror(errno)); - rc = GNUPG_File_Create_Error; - 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 = GNUPG_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); - - used_resources++; - } - } - break; - default: - log_error ("resource type of `%s' not supported\n", url); - rc = GNUPG_Not_Supported; - goto leave; - } - - /* fixme: check directory permissions and print a warning */ - - leave: - if (rc) - log_error ("keyblock resource `%s': %s\n", filename, gnupg_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; -} - - - -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 sequence by all processes. We are - cuurently 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; - - return rc; -} - -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; - - rc = lock_all (hd); - if (rc) - return rc; - - 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 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_cert (KEYDB_HANDLE hd, KsbaCert *r_cert) -{ - int rc = 0; - - if (!hd) - return GNUPG_Invalid_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 = GNUPG_General_Error; /* oops */ - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_get_cert (hd->active[hd->found].u.kr, r_cert); - break; - } - - return rc; -} - -/* - * Insert a new Certificate into one of the resources. - */ -int -keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert) -{ - int rc = -1; - int idx; - char digest[20]; - - if (!hd) - return GNUPG_Invalid_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 GNUPG_General_Error; - - 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 = GNUPG_General_Error; - 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, KsbaCert cert) -{ - int rc = 0; - char digest[20]; - - if (!hd) - return GNUPG_Invalid_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 = GNUPG_General_Error; /* 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 GNUPG_Invalid_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; - - switch (hd->active[hd->found].type) - { - case KEYDB_RESOURCE_TYPE_NONE: - rc = GNUPG_General_Error; - 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 GNUPG_Invalid_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 GNUPG_Invalid_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 GNUPG_Invalid_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, KsbaConstSexp 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 GNUPG_Invalid_Value; - s++; - for (desc.snlen = 0; digitp (s); s++) - desc.snlen = 10*desc.snlen + atoi_1 (s); - if (*s !=':') - return GNUPG_Invalid_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 GNUPG_Invalid_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 (KsbaCert 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 GNUPG_General_Error; - } - - kh = keydb_new (0); - if (!kh) - { - log_error (_("failed to allocate keyDB handle\n")); - return GNUPG_Out_Of_Core; - } - - 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"), - gnupg_strerror (rc)); - return rc; - } - - rc = keydb_locate_writable (kh, 0); - if (rc) - { - log_error (_("error finding writable keyDB: %s\n"), gnupg_strerror (rc)); - keydb_release (kh); - return rc; - } - - rc = keydb_insert_cert (kh, cert); - if (rc) - { - log_error (_("error storing certificate: %s\n"), gnupg_strerror (rc)); - keydb_release (kh); - return rc; - } - keydb_release (kh); - return 0; -} - - - diff --git a/sm/keylist.c b/sm/keylist.c deleted file mode 100644 index 96a8469ba..000000000 --- a/sm/keylist.c +++ /dev/null @@ -1,616 +0,0 @@ -/* keylist.c - * 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 - */ - -#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 <gcrypt.h> -#include <ksba.h> - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - -struct list_external_parm_s { - FILE *fp; - int print_header; - int with_colons; - int with_chain; -}; - - - -static void -print_key_data (KsbaCert 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 (KsbaCert cert, FILE *fp) -{ - KsbaError err; - unsigned int use; - - err = ksba_cert_get_key_usage (cert, &use); - if (err == KSBA_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"), - ksba_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 (time_t t, FILE *fp) -{ - if (!t) - ; - else if ( t == (time_t)(-1) ) - putc ('?', fp); - else - fprintf (fp, "%lu", (unsigned long)t); -} - - -/* 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 (KsbaCert cert, FILE *fp, int have_secret) -{ - int idx, trustletter = 0; - char *p; - KsbaSexp sexp; - char *fpr; - - fputs (have_secret? "crs:":"crt:", fp); - trustletter = 0; -#if 0 - if (is_not_valid (cert)) - putc ('i', fp); - else if ( is_revoked (cert) ) - putc ('r', fp); - else if ( has_expired (cert)) - putcr ('e', fp); - else -#endif - { - trustletter = '?'; /*get_validity_info ( pk, NULL );*/ - putc (trustletter, fp); - } - - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - fprintf (fp, ":%u:%d:%s:", - /*keylen_of_cert (cert)*/1024, - /* pubkey_algo_of_cert (cert)*/1, - fpr+24); - - /* we assume --fixed-list-mode for gpgsm */ - print_time ( ksba_cert_get_validity (cert, 0), fp); - putc (':', fp); - print_time ( ksba_cert_get_validity (cert, 1), 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); - xfree (fpr); fpr = NULL; - /* print chaining ID (field 13)*/ - { - KsbaCert next; - - if (!gpgsm_walk_cert_chain (cert, &next)) - { - p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1); - fputs (p, fp); - xfree (p); - ksba_cert_release (next); - } - } - putc (':', fp); - putc ('\n', fp); - - - 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:%c::::::::", trustletter); - 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:%c::::::::", trustletter); - print_sanitized_string (fp, pp, ':'); - putc (':', fp); - putc (':', fp); - putc ('\n', fp); - xfree (pp); - } - } - xfree (p); - } -} - - -/* List one certificate in standard mode */ -static void -list_cert_std (KsbaCert cert, FILE *fp, int have_secret) -{ - KsbaError kerr; - KsbaSexp sexp; - char *dn; - time_t t; - int idx; - int is_ca, chainlen; - unsigned int kusage; - char *string, *p; - - 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); - } - - t = ksba_cert_get_validity (cert, 0); - fputs (" validity: ", fp); - gpgsm_print_time (fp, t); - fputs (" through ", fp); - t = ksba_cert_get_validity (cert, 1); - gpgsm_print_time (fp, t); - putc ('\n', fp); - - kerr = ksba_cert_get_key_usage (cert, &kusage); - if (kerr != KSBA_No_Data) - { - fputs (" key usage:", fp); - if (kerr) - fprintf (fp, " [error: %s]", ksba_strerror (kerr)); - 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); - } - - kerr = ksba_cert_get_cert_policies (cert, &string); - if (kerr != KSBA_No_Data) - { - fputs (" policies: ", fp); - if (kerr) - fprintf (fp, "[error: %s]", ksba_strerror (kerr)); - else - { - for (p=string; *p; p++) - { - if (*p == '\n') - *p = ','; - } - print_sanitized_string (fp, string, 0); - xfree (string); - } - putc ('\n', fp); - } - - kerr = ksba_cert_is_ca (cert, &is_ca, &chainlen); - if (kerr || is_ca) - { - fputs (" chain length: ", fp); - if (kerr) - fprintf (fp, "[error: %s]", ksba_strerror (kerr)); - else if (chainlen == -1) - fputs ("unlimited", fp); - else - fprintf (fp, "%d", chainlen); - putc ('\n', fp); - } - - - dn = gpgsm_get_fingerprint_string (cert, 0); - fprintf (fp, " fingerprint: %s\n", dn?dn:"error"); - xfree (dn); -} - -/* Same as standard mode mode list all certifying certts too */ -static void -list_cert_chain (KsbaCert cert, FILE *fp) -{ - KsbaCert next = NULL; - - list_cert_std (cert, fp, 0); - ksba_cert_ref (cert); - while (!gpgsm_walk_cert_chain (cert, &next)) - { - ksba_cert_release (cert); - fputs ("Certified by\n", fp); - list_cert_std (next, fp, 0); - cert = next; - } - ksba_cert_release (cert); - putc ('\n', fp); -} - - - -/* List all internal keys or just the key given as NAMES. - */ -static void -list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) -{ - KEYDB_HANDLE hd; - KEYDB_SEARCH_DESC *desc = NULL; - STRLIST sl; - int ndesc; - KsbaCert cert = NULL; - int rc=0; - const char *lastresname, *resname; - int have_secret; - - 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 ("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, gnupg_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))) - { - 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", gnupg_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) - { - if (!gpgsm_agent_havekey (p)) - have_secret = 1; - xfree (p); - } - } - - if (!mode - || ((mode & 1) && !have_secret) - || ((mode & 2) && have_secret) ) - { - if (ctrl->with_colons) - list_cert_colon (cert, fp, have_secret); - else if (ctrl->with_chain) - list_cert_chain (cert, fp); - else - { - list_cert_std (cert, fp, have_secret); - putc ('\n', fp); - } - } - ksba_cert_release (cert); - cert = NULL; - } - if (rc && rc != -1) - log_error ("keydb_search failed: %s\n", gnupg_strerror (rc)); - - leave: - ksba_cert_release (cert); - xfree (desc); - keydb_release (hd); -} - - - -static void -list_external_cb (void *cb_value, KsbaCert 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 (cert, parm->fp, 0); - else if (parm->with_chain) - list_cert_chain (cert, parm->fp); - else - { - list_cert_std (cert, parm->fp, 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 void -list_external_keys (CTRL ctrl, STRLIST names, FILE *fp) -{ - int rc; - struct list_external_parm_s parm; - - parm.fp = fp; - parm.print_header = ctrl->no_server; - parm.with_colons = ctrl->with_colons; - parm.with_chain = ctrl->with_chain; - - rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm); - if (rc) - log_error ("listing external keys failed: %s\n", gnupg_strerror (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 - */ -void -gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) -{ - if ((mode & (1<<6))) - list_internal_keys (ctrl, names, fp, (mode & 3)); - if ((mode & (1<<7))) - list_external_keys (ctrl, names, fp); -} diff --git a/sm/server.c b/sm/server.c deleted file mode 100644 index e8200feda..000000000 --- a/sm/server.c +++ /dev/null @@ -1,1057 +0,0 @@ -/* server.c - Server mode and main entry point - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <ctype.h> -#include <unistd.h> - -#include "gpgsm.h" -#include "../assuan/assuan.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 assuan_ctx; - int message_fd; - int list_internal; - int list_external; - CERTLIST recplist; - CERTLIST signerlist; -}; - - - -/* 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 - 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); - if (rc) - gpgsm_status2 (ctrl, STATUS_INV_RECP, - rc == -1? "1": - rc == GNUPG_No_Public_Key? "1": - rc == GNUPG_Ambiguous_Name? "2": - rc == GNUPG_Wrong_Key_Usage? "3": - rc == GNUPG_Certificate_Revoked? "4": - rc == GNUPG_Certificate_Expired? "5": - rc == GNUPG_No_CRL_Known? "6": - rc == GNUPG_CRL_Too_Old? "7": - rc == GNUPG_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); - if (rc) - gpgsm_status2 (ctrl, STATUS_INV_RECP, - rc == -1? "1": - rc == GNUPG_No_Public_Key? "1": - rc == GNUPG_Ambiguous_Name? "2": - rc == GNUPG_Wrong_Key_Usage? "3": - rc == GNUPG_Certificate_Revoked? "4": - rc == GNUPG_Certificate_Expired? "5": - rc == GNUPG_No_CRL_Known? "6": - rc == GNUPG_CRL_Too_Old? "7": - rc == GNUPG_No_Policy_Match? "8": - rc == GNUPG_No_Secret_Key? "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); - 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_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; - - 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); - gpgsm_list_keys (assuan_get_pointer (ctx), list, fp, listmode); - free_strlist (list); - return 0; -} - -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 cmd_id; - int (*handler)(ASSUAN_CONTEXT, char *line); - } table[] = { - { "RECIPIENT", 0, cmd_recipient }, - { "SIGNER", 0, cmd_signer }, - { "ENCRYPT", 0, cmd_encrypt }, - { "DECRYPT", 0, cmd_decrypt }, - { "VERIFY", 0, cmd_verify }, - { "SIGN", 0, cmd_sign }, - { "IMPORT", 0, cmd_import }, - { "EXPORT", 0, cmd_export }, - { "", ASSUAN_CMD_INPUT, NULL }, - { "", ASSUAN_CMD_OUTPUT, NULL }, - { "MESSAGE", 0, cmd_message }, - { "LISTKEYS", 0, cmd_listkeys }, - { "LISTSECRETKEYS", 0, cmd_listsecretkeys }, - { "GENKEY", 0, cmd_genkey }, - { "DELKEYS", 0, cmd_delkeys }, - { NULL } - }; - int i, j, rc; - - for (i=j=0; table[i].name; i++) - { - rc = assuan_register_command (ctx, - table[i].cmd_id? table[i].cmd_id - : (ASSUAN_CMD_USER + j++), - table[i].name, table[i].handler); - if (rc) - return rc; - } - return 0; -} - -/* Startup the server */ -void -gpgsm_server (void) -{ - int rc; - int filedes[2]; - ASSUAN_CONTEXT ctx; - struct server_control_s ctrl; - - 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); - } - assuan_set_hello_line (ctx, "GNU Privacy Guard's S/M server ready"); - - 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; - - 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_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_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); -} - - - -#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 061dfeebc..000000000 --- a/sm/sign.c +++ /dev/null @@ -1,622 +0,0 @@ -/* sign.c - Sign a message - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> -#include <time.h> -#include <assert.h> - -#include <gcrypt.h> -#include <ksba.h> - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - - -static void -hash_data (int fd, GCRY_MD_HD 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 md, KsbaWriter writer) -{ - KsbaError err; - FILE *fp; - char buffer[4096]; - int nread; - int rc = 0; - int any = 0; - - fp = fdopen ( dup (fd), "rb"); - if (!fp) - { - log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno)); - return GNUPG_File_Open_Error; - } - - 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", ksba_strerror (err)); - rc = map_ksba_err (err); - } - } - } - while (nread && !rc); - if (ferror (fp)) - { - log_error ("read error on fd %d: %s\n", fd, strerror (errno)); - rc = GNUPG_Read_Error; - } - fclose (fp); - if (!any) - { - /* We can't allow to sign an empty message becuase it does not - make mnuch 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 = GNUPG_No_Data; - } - if (!rc) - { - err = ksba_writer_write_octet_string (writer, NULL, 0, 1); - if (err) - { - log_error ("write failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); - } - } - - return rc; -} - - -/* Get the default certificate which is defined as the first one our - keyDB retruns and has a secret key available */ -int -gpgsm_get_default_cert (KsbaCert *r_cert) -{ - KEYDB_HANDLE hd; - KsbaCert cert = NULL; - int rc; - char *p; - - hd = keydb_new (0); - if (!hd) - return GNUPG_General_Error; - 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", gnupg_strerror (rc)); - keydb_release (hd); - return rc; - } - - p = gpgsm_get_keygrip_hexstring (cert); - if (p) - { - if (!gpgsm_agent_havekey (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", gnupg_strerror (rc)); - - ksba_cert_release (cert); - keydb_release (hd); - return rc; -} - - -static KsbaCert -get_default_signer (void) -{ - KEYDB_SEARCH_DESC desc; - KsbaCert cert = NULL; - KEYDB_HANDLE kh = NULL; - int rc; - - if (!opt.local_user) - { - rc = gpgsm_get_default_cert (&cert); - if (rc) - { - if (rc != -1) - log_debug ("failed to find default certificate: %s\n", - gnupg_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", gnupg_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, KsbaCMS cms, KsbaCert cert) -{ - KsbaError err; - int rc = 0; - KsbaCert next = NULL; - int n; - int not_root = 0; - - ksba_cert_ref (cert); - - n = ctrl->include_certs; - if (n == -2) - { - not_root = 1; - n = -1; - } - if (n < 0 || n > 50) - n = 50; /* We better apply an upper bound */ - - 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; - } - 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", ksba_strerror (err)); - return map_ksba_err (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; - KsbaError err; - Base64Context b64writer = NULL; - KsbaWriter writer; - KsbaCMS cms = NULL; - KsbaStopReason stopreason; - KEYDB_HANDLE kh = NULL; - GCRY_MD_HD data_md = NULL; - int signer; - const char *algoid; - int algo; - time_t signed_at; - CERTLIST cl; - int release_signerlist = 0; - - kh = keydb_new (0); - if (!kh) - { - log_error (_("failed to allocated keyDB handle\n")); - rc = GNUPG_General_Error; - 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", gnupg_strerror (rc)); - goto leave; - } - - cms = ksba_cms_new (); - if (!cms) - { - rc = seterr (Out_Of_Core); - goto leave; - } - - err = ksba_cms_set_reader_writer (cms, NULL, writer); - if (err) - { - log_debug ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (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", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - /* If no list of signers is given, use a default one. */ - if (!signerlist) - { - KsbaCert cert = get_default_signer (); - if (!cert) - { - log_error ("no default signer found\n"); - rc = seterr (General_Error); - goto leave; - } - signerlist = xtrycalloc (1, sizeof *signerlist); - if (!signerlist) - { - rc = GNUPG_Out_Of_Core; - 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", ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - rc = add_certificate_list (ctrl, cms, cl->cert); - if (rc) - { - log_error ("failed to store list of certificates: %s\n", - gnupg_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", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - } - - /* Prepare hashing (actually we are figuring out what we have set above)*/ - data_md = gcry_md_open (0, 0); - if (!data_md) - { - rc = map_gcry_err (gcry_errno()); - log_error ("md_open failed: %s\n", gcry_strerror (-1)); - 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 = GNUPG_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, bu 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 = GNUPG_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", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - } - } - - signed_at = gnupg_get_time (); - 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", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - } - - do - { - err = ksba_cms_build (cms, &stopreason); - if (err) - { - log_debug ("ksba_cms_build failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (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 = GNUPG_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", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - } - } - else if (stopreason == KSBA_SR_NEED_SIG) - { /* calculate the signature for all signers */ - GCRY_MD_HD md; - - algo = GCRY_MD_SHA1; - md = gcry_md_open (algo, 0); - if (DBG_HASHING) - gcry_md_start_debug (md, "sign.attr"); - - if (!md) - { - log_error ("md_open failed: %s\n", gcry_strerror (-1)); - goto leave; - } - 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", - ksba_strerror (rc)); - gcry_md_close (md); - goto leave; - } - - rc = gpgsm_create_cms_signature (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", - ksba_strerror (err)); - rc = map_ksba_err (err); - gcry_md_close (md); - goto leave; - } - - /* write a status message */ - fpr = gpgsm_get_fingerprint_hexstring (cl->cert, GCRY_MD_SHA1); - if (!fpr) - { - rc = seterr (Out_Of_Core); - gcry_md_close (md); - goto leave; - } - rc = asprintf (&buf, "%c %d %d 00 %lu %s", - detached? 'D':'S', - GCRY_PK_RSA, /* FIXME: get pk algo from cert */ - algo, - (ulong)signed_at, - fpr); - xfree (fpr); - if (rc < 0) - { - rc = seterr (Out_Of_Core); - 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", gnupg_strerror (rc)); - goto leave; - } - - log_info ("signature created\n"); - - - leave: - 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 df7c8bfe8..000000000 --- a/sm/verify.c +++ /dev/null @@ -1,510 +0,0 @@ -/* verify.c - Verify a messages signature - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> -#include <time.h> -#include <assert.h> - -#include <gcrypt.h> -#include <ksba.h> - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - -/* fixme: Move this to jnlib */ -static char * -strtimestamp (time_t atime) -{ - char *buffer = xmalloc (15); - - if (atime < 0) - strcpy (buffer, "????" "-??" "-??"); - else if (!atime) - strcpy (buffer, "none"); - else - { - struct tm *tp; - - tp = gmtime( &atime ); - sprintf (buffer, "%04d-%02d-%02d", - 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday); - } - return buffer; -} - - - -/* Hash the data for a detached signature */ -static void -hash_data (int fd, GCRY_MD_HD 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; - KsbaError err; - KsbaReader reader; - KsbaWriter writer = NULL; - KsbaCMS cms = NULL; - KsbaStopReason stopreason; - KsbaCert cert; - KEYDB_HANDLE kh; - GCRY_MD_HD 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 = GNUPG_General_Error; - goto leave; - } - - - fp = fdopen ( dup (in_fd), "rb"); - if (!fp) - { - log_error ("fdopen() failed: %s\n", strerror (errno)); - rc = seterr (IO_Error); - goto leave; - } - - rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader); - if (rc) - { - log_error ("can't create reader: %s\n", gnupg_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", gnupg_strerror (rc)); - goto leave; - } - } - - cms = ksba_cms_new (); - if (!cms) - { - rc = seterr (Out_Of_Core); - goto leave; - } - - err = ksba_cms_set_reader_writer (cms, reader, writer); - if (err) - { - log_error ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - data_md = gcry_md_open (0, 0); - if (!data_md) - { - rc = map_gcry_err (gcry_errno()); - log_error ("md_open failed: %s\n", gcry_strerror (-1)); - goto leave; - } - if (DBG_HASHING) - gcry_md_start_debug (data_md, "vrfy.data"); - - is_detached = 0; - do - { - err = ksba_cms_parse (cms, &stopreason); - if (err) - { - log_error ("ksba_cms_parse failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); - 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", gnupg_strerror (rc)); - goto leave; - } - } - - if (data_fd != -1 && !is_detached) - { - log_error ("data given for a non-detached signature\n"); - rc = GNUPG_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; - err = 0; - for (signer=0; ; signer++) - { - char *issuer = NULL; - KsbaSexp sigval = NULL; - time_t sigtime, keyexptime; - KsbaSexp serial; - char *msgdigest = NULL; - size_t msgdigestlen; - - err = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial); - if (!signer && err == KSBA_No_Data && data_fd == -1 && is_detached) - { - log_info ("certs-only message accepted\n"); - err = 0; - break; - } - if (err) - { - if (signer && err == -1) - err = 0; - break; - } - 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"); - } - - err = ksba_cms_get_signing_time (cms, signer, &sigtime); - if (err == KSBA_No_Data) - sigtime = 0; - else if (err) - { - log_error ("error getting signing time: %s\n", ksba_strerror (err)); - sigtime = (time_t)-1; - } - - err = ksba_cms_get_message_digest (cms, signer, - &msgdigest, &msgdigestlen); - if (!err) - { - 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); - if ( !gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED, &algo, NULL) ) - { - log_error ("digest algo %d has not been enabled\n", algo); - goto next_signer; - } - } - else if (err == KSBA_No_Data) - { - assert (!msgdigest); - err = 0; - algoid = NULL; - algo = 0; - } - else /* real error */ - break; - - 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 = GNUPG_No_Public_Key; - } - else - log_error ("failed to find the certificate: %s\n", - gnupg_strerror(rc)); - gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey", - gnupg_error_token (rc), 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", gnupg_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 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; - } - - md = gcry_md_open (algo, 0); - if (!md) - { - log_error ("md_open failed: %s\n", gcry_strerror (-1)); - 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", - ksba_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", gnupg_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_status2 (ctrl, STATUS_ERROR, "verify.keyusage", - gnupg_error_token (rc), NULL); - rc = 0; - } - - if (DBG_X509) - log_debug ("signature okay - checking certs\n"); - rc = gpgsm_validate_chain (ctrl, cert, &keyexptime); - if (rc == GNUPG_Certificate_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 (sigtime); - buf = xmalloc ( strlen(fpr) + strlen (tstr) + 120); - sprintf (buf, "%s %s %lu %lu", fpr, tstr, - (unsigned long)sigtime, (unsigned long)keyexptime ); - xfree (tstr); - xfree (fpr); - gpgsm_status (ctrl, STATUS_VALIDSIG, buf); - xfree (buf); - } - - if (rc) /* of validate_chain */ - { - log_error ("invalid certification chain: %s\n", gnupg_strerror (rc)); - if (rc == GNUPG_Bad_Certificate_Chain - || rc == GNUPG_Bad_Certificate - || rc == GNUPG_Bad_CA_Certificate - || rc == GNUPG_Certificate_Revoked) - gpgsm_status (ctrl, STATUS_TRUST_NEVER, gnupg_error_token (rc)); - else - gpgsm_status (ctrl, STATUS_TRUST_UNDEFINED, gnupg_error_token (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; - if (err) - { - log_error ("ksba error: %s\n", ksba_strerror (err)); - rc = map_ksba_err (rc); - } - - - - 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) - gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave", - gnupg_error_token (rc), NULL); - return rc; -} - |