diff --git a/agent/ChangeLog b/agent/ChangeLog index e0b8b8d10..c4aa1c299 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,2675 +1,2680 @@ +2010-06-24 Werner Koch + + * genkey.c (check_passphrase_pattern): Use HANG option for + gnupg_wait_progress. Fixes regression from 2010-06-09. + 2010-06-21 Werner Koch * protect-tool.c (export_p12_file, import_p12_cert_cb) (import_p12_file, sexp_to_kparms, store_private_key): Remove unused code. 2010-06-18 Werner Koch * protect-tool.c (store_private_key, rsa_key_check): Remove. * command.c (cmd_export_key): New. 2010-06-15 Werner Koch * command.c (cmd_keywrap_key, cmd_import_key): New. * genkey.c (agent_genkey, agent_protect_and_store): Factor common code out to... (agent_ask_new_passphrase): .. new. * findkey.c (agent_write_private_key): Return GPG_ERR_EEXIST instead of GPG_ERR_GENERAL. 2010-06-14 Werner Koch * protect-tool.c: Remove commands --p12-import and --p12-export. * minip12.c, minip12.h: Move to ../sm. * Makefile.am (gpg_protect_tool_SOURCES): Remove them. * preset-passphrase.c: Remove unneeded minip12.h. * command.c (cmd_keywrap_key): New. * command.c (leave_cmd): New. (cmd_istrusted, cmd_listtrusted, cmd_marktrusted, cmd_pksign) (cmd_pkdecrypt, cmd_genkey, cmd_readkey, cmd_keyinfo) (cmd_get_passphrase, cmd_get_confirmation, cmd_learn) (cmd_passwd, cmd_preset_passphrase, cmd_getval, cmd_putval): Use it. 2010-05-12 Werner Koch * preset-passphrase.c (forget_passphrase): Actually implement this. Fixes bug#1198. 2010-05-11 Werner Koch * agent.h (opt): Add field USE_STANDARD_SOCKET. * gpg-agent.c (use_standard_socket): Remove. Use new option instead. * command.c (cmd_killagent, cmd_reloadagent): Provide command also for non-W32 platforms. (cmd_getinfo): New subcommands std_session_env and std_startup_env. 2010-05-03 Werner Koch * gpg-agent.c (check_own_socket_thread): Do not release SOCKNAME too early. 2010-04-30 Werner Koch * gpg-agent.c (main): Add command --use-standard-socket-p. 2010-04-26 Werner Koch * gpg-agent.c (create_server_socket) [W32]: Also check for EEXIST. 2010-04-19 Werner Koch * pksign.c (get_dsa_qbits, do_encode_dsa): New. (agent_pksign_do): Detect DSA keys and use do_encode_dsa. * findkey.c (agent_public_key_from_file): Factor some code out to .. (key_parms_from_sexp): New. (agent_is_dsa_key): New. * command.c (cmd_sethash): Clear digeest.RAW_VALUE. 2010-04-14 Werner Koch * Makefile.am (libexec_PROGRAMS) [W32CE]: Do not build gpg-preset-passphrase for now. (pwquery_libs) [W32CE]: Set to empty. * trustlist.c (read_one_trustfile): Use estream. 2010-04-13 Werner Koch * findkey.c (read_key_file): Use estream. (agent_write_private_key): Ditto. 2010-04-07 Werner Koch * gpg-agent.c (handle_connections) [W32]: Assume that PTh support the handle event. Use a dummy event for W32CE. (get_agent_scd_notify_event) [W32CE]: Do not build. * call-pinentry.c: Remove setenv.h. Include sysutils.h. (atfork_cb): s/setenv/gnupg_setenv/. * gpg-agent.c: Do not include setenv.h. (main): s/unsetenv/gnupg_unsetenv/. * protect.c (calibrate_get_time) [W32CE]: Use GetThreadTimes. 2010-04-06 Werner Koch * call-scd.c [!HAVE_SIGNAL_H]: Do not include signal.h. * findkey.c (agent_write_private_key): s/remove/gnupg_remove/. * command-ssh.c (search_control_file): Replace rewind by fseek and clearerr. * genkey.c (check_passphrase_pattern): Ditto. * gpg-agent.c [!HAVE_SIGNAL_H]: Do not include signal.h. (remove_socket): s/remove/gnupg_remove/. (create_private_keys_directory): Use gnupg_mkdir. 2010-03-11 Werner Koch * gpg-agent.c: Include "asshelp.h". (main): Remove assuan_set_assuan_log_prefix. Add assuan_set_log_cb. (handle_signal): Disable pth ctrl dumping. (parse_rereadable_options, main): Remove assuan_set_assuan_log_stream. * call-scd.c (start_scd): Remove assuan_set_log_stream. 2010-03-10 Werner Koch * Makefile.am (common_libs): Remove libjnlib.a. * trustlist.c, protect-tool.c, command-ssh.c: Remove estream.h. 2010-02-17 Werner Koch * call-pinentry.c (start_pinentry): Always free OPTSTR. Send default-xxx strings. 2010-01-26 Werner Koch * protect.c (do_encryption): Encode the s2kcount and no not use a static value of 96. 2009-12-21 Werner Koch * command.c (cmd_getinfo): Add sub-command s2k_count. 2009-12-14 Werner Koch * protect.c (agent_unprotect): Decode the S2K count here and take care of the new unencoded values. Add a lower limit sanity check. (hash_passphrase): Do not decode here. (get_standard_s2k_count, calibrate_s2k_count): New. (calibrate_get_time, calibrate_elapsed_time): New. (do_encryption): Use get_standard_s2k_count. 2009-12-08 Werner Koch * protect.c (agent_unprotect): Avoid compiler warning. 2009-12-08 Marcus Brinkmann * call-pinentry.c (start_pinentry): Convert posix fd to assuan fd. * call-scd.c (start_scd): Likewise. 2009-12-03 Werner Koch * gpg-agent.c (set_debug): Allow for numerical debug leveles. Print active debug flags. 2009-12-02 Werner Koch * trustlist.c (read_trustfiles): Store the pointer returned from shrinking the memory and not the orginal one. Fixes bug#1163. Reported by TAKAHASHI Tamotsu. Also return correct error after memory failure. 2009-11-27 Marcus Brinkmann * command.c (start_command_handler): Do not call assuan_set_log_stream anymore. * gpg-agent.c (main): But call assuan_set_assuan_log_stream here. 2009-11-25 Marcus Brinkmann * command.c (start_command_handler): Use assuan_fd_t and assuan_fdopen on fds. 2009-11-05 Marcus Brinkmann * call-pinentry.c (start_pinentry): Call assuan_pipe_connect, not assuan_pipe_connect_ext. * command.c (start_command_handler): Change assuan_init_socket_server_ext into assuan_init_socket_server. * call-scd.c (start_scd): Update use of assuan_socket_connect and assuan_pipe_connect. * gpg-agent.c (check_own_socket_thread, check_for_running_agent): Update use of assuan_socket_connect. 2009-11-04 Werner Koch * command.c (register_commands): Add help arg to assuan_register_command. Convert all command comments to help strings. 2009-11-02 Marcus Brinkmann * command.c (reset_notify): Take LINE arg and return error. (register_commands): Use assuan_handler_t type. 2009-10-16 Marcus Brinkmann * gpg_agent_CFLAGS, gpg_agent_LDADD: Use libassuan instead of libassuan-pth. * gpg-agent.c: Invoke ASSUAN_SYSTEM_PTH_IMPL. (main): Call assuan_set_system_hooks and assuan_sock_init. Fix invocation of assuan_socket_connect. 2009-09-23 Werner Koch * command.c (register_commands) [HAVE_ASSUAN_SET_IO_MONITOR]: Remove cpp condition. (start_command_handler) [HAVE_ASSUAN_SET_IO_MONITOR]: Ditto. 2009-09-23 Marcus Brinkmann * gpg-agent.c (parse_rereadable_options): Don't set global assuan log file (there ain't one anymore). (main): Update to new API. (check_own_socket_pid_cb): Return gpg_error_t instead of int. (check_own_socket_thread, check_for_running_agent): Create assuan context before connecting to server. * command.c: Include "scdaemon.h" before because of GPG_ERR_SOURCE_DEFAULT check. (write_and_clear_outbuf): Use gpg_error_t instead of assuan_error_t. (cmd_geteventcounter, cmd_istrusted, cmd_listtrusted) (cmd_marktrusted, cmd_havekey, cmd_sigkey, cmd_setkeydesc) (cmd_sethash, cmd_pksign, cmd_pkdecrypt, cmd_genkey, cmd_readkey) (cmd_keyinfo, cmd_get_passphrase, cmd_clear_passphrase) (cmd_get_confirmation, cmd_learn, cmd_passwd) (cmd_preset_passphrase, cmd_scd, cmd_getval, cmd_putval) (cmd_updatestartuptty, cmd_killagent, cmd_reloadagent) (cmd_getinfo, option_handler): Return gpg_error_t instead of int. (post_cmd_notify): Change type of ERR to gpg_error_t from int. (io_monitor): Add hook argument. Use symbols for constants. (register_commands): Change return type of HANDLER to gpg_error_t. (start_command_handler): Allocate assuan context before starting server. * call-pinentry.c: Include "scdaemon.h" before because of GPG_ERR_SOURCE_DEFAULT check. (unlock_pinentry): Call assuan_release instead of assuan_disconnect. (getinfo_pid_cb, getpin_cb): Return gpg_error_t instead of int. (start_pinentry): Allocate assuan context before connecting to server. * call-scd.c (membuf_data_cb, learn_status_cb, get_serialno_cb) (membuf_data_cb, inq_needpin, card_getattr_cb, pass_status_thru) (pass_data_thru): Change return type to gpg_error_t. (start_scd): Allocate assuan context before connecting to server. 2009-09-04 Marcus Brinkmann * command.c (start_command_handler): Add comment about gap in implementation (in dead code), for future reference. 2009-08-11 Werner Koch * divert-scd.c (ask_for_card): I18n a prompt string. 2009-07-06 Werner Koch * agent.h: Include session-env.h. (opt): Replace most of the startup_xxx fields by a session_env_t. (struct server_control_s): Likewise. * gpg-agent.c (main): Rewrite setting of the startup fields. (handle_connections, main): Allocate SESSION_ENV. (agent_init_default_ctrl, agent_deinit_default_ctrl): Change accordingly. * command.c (option_handler): Ditto. (cmd_updatestartuptty): Change accordingly. Protect old values from out of core failures. * command-ssh.c (start_command_handler_ssh): Ditto. (start_command_handler_ssh): Replace strdup by xtrystrdup. * call-pinentry.c (atfork_cb): Pass new envrinmnet variables. (start_pinentry): Use session_env stuff. * protect-tool.c (main): Adjust call to gnupg_prepare_get_passphrase. 2009-06-24 Werner Koch * genkey.c (agent_protect_and_store): Return RC and not 0. * protect.c (do_encryption): Fix ignored error code from malloc. Reported by Fabian Keil. 2009-06-17 Werner Koch * call-pinentry.c (agent_get_confirmation): Add arg WITH_CANCEL. Change all callers. * trustlist.c (agent_marktrusted): Use WITH_CANCEL 2009-06-09 Werner Koch * learncard.c (send_cert_back): Ignore certain error codes. 2009-06-05 Werner Koch * protect-tool.c (store_private_key): Fix last change by appending a ".key". 2009-06-03 Werner Koch * protect-tool.c: Include estream.h. (store_private_key): Replace stdio streams by estream functions for a portable use of the "x" mode. * trustlist.c: Include estream.h. (agent_marktrusted): Replace stdio stream by estream functions. * protect-tool.c (store_private_key): Use bin2hex. 2009-06-02 Werner Koch * gpg-agent.c (main): Run pth_kill after fork. Fixes bug#1066. 2009-05-19 Werner Koch * gpg-agent.c (JNLIB_NEED_AFLOCAL): Define. (create_server_socket): Use SUN_LEN macro. 2009-05-15 Werner Koch Fix bug #1053. * agent.h (lookup_ttl_t): New. * findkey.c (unprotect): Add arg LOOKUP_TTL. (agent_key_from_file): Ditto. * pksign.c (agent_pksign_do): Ditto. * command-ssh.c (ttl_from_sshcontrol): New. (data_sign): Pass new function to agent_pksign_do. (search_control_file): Add new arg R_TTL. 2009-05-14 Werner Koch * command.c (cmd_get_passphrase): Add option --qualitybar. * call-pinentry.c (agent_askpin): Factor some code out to ... (setup_qualitybar): .. new. (agent_get_passphrase): Add arg WITH_QUALITYBAR and implement it. 2009-04-14 Marcus Brinkmann * call-pinentry.c (agent_get_confirmation): Try SETNOTOK command with pinentry. 2009-04-01 Werner Koch * protect-tool.c (pe_opt): New. (opts): Add option --agent-program. Use ARGPARSE macros. (get_new_passphrase): Remove. (get_passphrase): Use gpg-agent directly. Remove arg OPT_CHECK and change all callers. * Makefile.am (gpg_protect_tool_LDADD): Replace pwquery_libs by LIBASSUAN_LIBS. (gpg_protect_tool_CFLAGS): New. * command.c (percent_plus_unescape): Remove. (cmd_putval): Use percent_plus_unescape_inplace. * call-scd.c (unescape_status_string): Remove. (card_getattr_cb): Use percent_plus_unescape. * protect-tool.c (main): Use percent_plus_unescape from common/. (percent_plus_unescape, percent_plus_unescape_string): Remove. 2009-03-27 Werner Koch * learncard.c (agent_handle_learn): Add new certtype 111. 2009-03-26 Werner Koch * agent.h (MAX_DIGEST_LEN): Change to 64. * command.c (cmd_sethash): Allow digest length of 48 and 64. (cmd_sethash): Allow more hash algos. * trustlist.c (reformat_name): New. (agent_marktrusted): Use a reformatted name. Reload the table before the update and always reload it at the end. (agent_istrusted): Check early for the disabled flag. 2009-03-25 Werner Koch * pkdecrypt.c (agent_pkdecrypt): Return a specific error message if the key is not available. * gpg-agent.c (main): Print a started message to show the real pid. 2009-03-20 Werner Koch * learncard.c (struct kpinfo_cp_parm_s): Add field CTRL. (struct certinfo_cb_parm_s): Ditto. (agent_handle_learn): Set CTRL field. (kpinfo_cb, certinfo_cb): Send progress status. * agent.h (agent_write_status): Flag with GNUPG_GCC_A_SENTINEL. 2009-03-19 Werner Koch * trustlist.c (struct trustitem_s): Add field DISABLED. (read_one_trustfile): Parse the '!' flag. (agent_istrusted, agent_listtrusted): Check flag. (agent_istrusted): Add arg R_DISABLED. Change all callers. (agent_marktrusted): Do not ask if flagged as disabled. Reverse the order of the questions. Store the disabled flag. * gpg-agent.c (main): Save signal mask and open fds. Restore mask and close all fds prior to the exec. Fixes bug#1013. 2009-03-17 Werner Koch * command.c (cmd_get_passphrase): Break repeat loop on error. Show error message. (cmd_getinfo): Add subcommand "cmd_has_option". (command_has_option): New. 2009-03-17 Daiki Ueno * command.c (option_value): New function. (cmd_get_passphrase): Accept new option --repeat, which makes gpg-agent to ask passphrase several times. 2009-03-06 Werner Koch * command.c (cmd_keyinfo): New command. (register_commands): Register it. (agent_write_status): Make sure not to print LR or CR. * divert-scd.c (ask_for_card): Factor shadow info parsing out to ... * protect.c (parse_shadow_info): New. * findkey.c (agent_key_from_file): Use make_canon_sexp. (agent_write_private_key, unprotect, read_key_file) (agent_key_available): Use bin2hex. (agent_key_info_from_file): New. (read_key_file): Log no error message for ENOENT. 2009-03-05 Werner Koch * divert-scd.c (getpin_cb): Support flag 'P'. Change max_digits from 8 to 16. Append a message about keypads. * findkey.c (unprotect): Change max digits to 16. 2009-03-02 Werner Koch * command.c (cmd_getinfo): Add subcommand "scd_running". * call-scd.c (agent_scd_check_running): New. * gpg-agent.c: Add missing option strings for "--batch" and "--homedir". Reported by Petr Uzel. * protect-tool.c (import_p12_file): Take care of canceled passphrase entry. Fixes bug#1003. (export_p12_file): Ditto. 2008-12-17 Werner Koch * gpg-agent.c (handle_connections): Set action of all pth event handled signals to SIG_IGN. Use a different pth_sigmask strategy. 2008-12-10 Werner Koch * command.c (cmd_get_passphrase): Implement option --no-ask. 2008-12-09 Werner Koch * gpg-agent.c (main): Call i18n_init before init_common_subsystems. * preset-passphrase.c (main): Ditto. * protect-tool.c (main): Ditto. * command.c (cmd_preset_passphrase): Allow an arbitrary string for the cache id. 2008-12-08 Werner Koch * gpg-agent.c (handle_connections): Sync the ticker to the next full second. This is bug#871. 2008-12-05 Werner Koch * minip12.c (decrypt_block): Fix const modified of CHARSETS. * learncard.c (sinfo_cb_parm_s): Remove superflous semicolon. Reported by Stoyan Angelov. 2008-11-18 Werner Koch * gpg-agent.c (make_libversion): New. (my_strusage): Print libgcrypt version 2008-11-11 Werner Koch * call-scd.c (membuf_data_cb): Change return type to assuan_error_t to avoid warnings with newer libassuan versions. 2008-11-04 Werner Koch * command.c (cmd_killagent): Stop the agent immediately. (start_command_handler): Take care of GPG_ERR_EOF. 2008-10-29 Werner Koch * gpg-agent.c (main): Move USE_STANDARD_SOCKET to the outer scope. (create_socket_name): Remove arg USE_STANDARD_SOCKET. Change all callers. (create_server_socket): Remove IS_STANDARD_NAME and replace it by USE_STANDARD_SOCKET. Change all callers. (check_own_socket_running): New. (check_own_socket, check_own_socket_thread): New. (handle_tick): Check server socket once a minute. (handle_connections): Remove the extra pth_wait in the shutdown case. 2008-10-20 Werner Koch * command.c (cmd_geteventcounter): Mark unused arg. (cmd_listtrusted, cmd_pksign, cmd_pkdecrypt, cmd_genkey): Ditto. (cmd_updatestartuptty, post_cmd_notify): Ditto. * command-ssh.c (add_control_entry) (ssh_handler_request_identities, ssh_handler_remove_identity) (ssh_handler_remove_all_identities, ssh_handler_lock) (ssh_handler_unlock): Ditto. * call-pinentry.c (pinentry_active_p, popup_message_thread) (agent_popup_message_stop): Ditto. * findkey.c (agent_public_key_from_file): Ditto. * genkey.c (check_passphrase_pattern): Ditto. * call-scd.c (atfork_cb): Ditto. * protect-tool.c (import_p12_cert_cb): Ditto. * t-protect.c (main): Ditto. 2008-10-17 Werner Koch * call-scd.c (start_scd) [W32]: Use snprintf again because we now always use the estream variant. 2008-10-15 Werner Koch * call-scd.c (start_scd): Enable assuan loggging if requested. (agent_scd_check_aliveness) [W32]: Fix use of GetExitCodeProcess. 2008-10-14 Werner Koch * gpg-agent.c (get_agent_scd_notify_event): Need to use a manual reset event. 2008-09-29 Werner Koch * agent.h (GCRY_MD_USER): Rename to GCRY_MODULE_ID_USER. (GCRY_MD_USER_TLS_MD5SHA1): Rename to MD_USER_TLS_MD5SHA1 and change all users. 2008-09-25 Werner Koch * divert-scd.c (getpin_cb): Support a Reset Code style PINs.. 2008-09-03 Werner Koch * command.c (parse_keygrip): Use hex2bin. (cmd_preset_passphrase): Decode the passphrase. Reported by Kiss Gabor. Fixes #679 again. * preset-passphrase.c (make_hexstring): Remove. (preset_passphrase): Use bin2hex. 2008-05-27 Werner Koch * trustlist.c (insert_colons): Fix stupidly wrong allocation size computation. 2008-05-26 Werner Koch * gpg-agent.c (main): Re-initialize default assuan log stream if a log file is used. * trustlist.c (agent_marktrusted): Use xtryasprintf and xfree. * gpg-agent.c (main, agent_deinit_default_ctrl): Always use xfree because our asprintf is mapped to an xmalloc style function in util.h. Replace xstrdup by xtrystrdup. * w32main.c (build_argv): Ditto. * preset-passphrase.c (preset_passphrase): Ditto. * divert-scd.c (ask_for_card): Ditto. * command.c (option_handler): Ditto. * command-ssh.c (ssh_handler_request_identities): Ditto. * call-pinentry.c (start_pinentry): Ditto. * gpg-agent.c (start_connection_thread) (start_connection_thread_ssh): Use pth_thread_id for useful output under W32. (pth_thread_id) [!PTH_HAVE_PTH_THREAD_ID]: New. 2008-03-17 Werner Koch * agent.h (agent_inq_pinentry_launched): New prototype. * call-pinentry.c: Include sys/types.h and signal.h. 2008-02-14 Werner Koch * command.c (agent_inq_pinentry_launched): New. (option_handler): Add option allow-pinentry-notify. * call-pinentry.c (getinfo_pid_cb): New. (start_pinentry): Ask for the PID and notify the client. 2008-01-15 Marcus Brinkmann * call-pinentry.c (start_pinentry): Start pinentry in detached mode. 2007-12-04 Werner Koch * call-pinentry.c (agent_askpin): Use gnupg_get_help_string. 2007-12-03 Werner Koch * gpg-agent.c (main): s/standard_socket/use_standard_socket/ for clarity. (create_server_socket): New arg IS_SSH to avoid testing with assuan commands. 2007-11-20 Werner Koch * gpg-agent.c (get_agent_scd_notify_event): New. (handle_signal): Factor SIGUSR2 code out to: (agent_sigusr2_action): .. New. (agent_sighup_action): Print info message here and not in handle_signal. (handle_connections) [PTH_EVENT_HANDLE]: Call agent_sigusr2_action. * call-scd.c (agent_scd_check_aliveness) [W32]: Implemented. (start_scd) [W32]: Send event-signal option. 2007-11-19 Werner Koch * call-pinentry.c (agent_askpin): Set the tooltip for the quality bar. 2007-11-15 Werner Koch * agent.h (struct server_control_s): Add XAUTHORITY and PINENTRY_USER_DATA. * gpg-agent.c: New option --xauthority. (main, agent_init_default_ctrl) (agent_deinit_default_ctrl): Implemented * command.c (cmd_updatestartuptty): Ditto. * command-ssh.c (start_command_handler_ssh): Ditto. * call-pinentry.c (atfork_cb): Set the environment. (start_pinentry): Pass CTRL as arg to atfork_cb. 2007-11-14 Werner Koch * call-scd.c (start_scd) [W32]: Take care of fflush peculiarities. 2007-11-07 Werner Koch * agent.h: Remove errors.h. 2007-10-24 Werner Koch * genkey.c (check_passphrase_constraints): Changed the wording of the warning messages. 2007-10-19 Werner Koch * protect-tool.c (get_passphrase): Use new utf8 switch fucntions. 2007-10-15 Daiki Ueno (wk) * command-ssh.c (reenter_compare_cb): New function; imported from genkey.c. (ssh_identity_register): Ask initial passphrase twice. 2007-10-02 Werner Koch * command.c (cmd_getinfo): Add "pid" subcommand. 2007-10-01 Werner Koch * agent.h (struct server_control_s): Remove unused CONNECTION_FD. * gpg-agent.c: Remove w32-afunix.h. Include mkdtemp.h. (socket_nonce, socket_nonce_ssh): New. (create_server_socket): Use assuan socket wrappers. Remove W32 specific stuff. Save the server nonce. (check_nonce): New. (start_connection_thread, start_connection_thread_ssh): Call it. (handle_connections): Change args to gnupg_fd_t. * command.c (start_command_handler): Change LISTEN_FD to gnupg_fd_t. * command-ssh.c (start_command_handler_ssh): Ditto. 2007-09-18 Werner Koch * agent.h (struct pin_entry_info_s): Add element WITH_QUALITYBAR. * genkey.c (check_passphrase_constraints): New arg SILENT. Changed all callers. (agent_protect_and_store, agent_genkey): Enable qualitybar. * call-pinentry.c (agent_askpin): Send that option. (unescape_passphrase_string): New. (inq_quality): New. (estimate_passphrase_quality): New. 2007-09-14 Marcus Brinkmann * call-pinentry.c (agent_popup_message_stop): Implement kill for Windows. 2007-08-28 Werner Koch * gpg-agent.c (main): Add option --faked-system-time. * protect-tool.c (read_and_unprotect): Print the protected-at date. * agent.h (struct server_control_s): Add member IN_PASSWD. * command.c (cmd_passwd): Set it. * findkey.c (try_unprotect_cb): Use it. * protect.c (do_encryption): Replace asprintf by xtryasprint. (agent_protect): Create the protected-at item. (agent_unprotect): Add optional arg PROTECTED_AT. (merge_lists): Add args CUTOFF and CUTLEN. (agent_unprotect): Use them. * findkey.c (try_unprotect_cb): Add code to test for expired keys. (unprotect): Allow changing the passphrase. 2007-08-27 Werner Koch * gpg-agent.c: Add options --min-passphrase-nonalpha, --check-passphrase-pattern and --enforce-passphrase-constraints. (MIN_PASSPHRASE_NONALPHA): Init nonalpha option to 1. (main): Declare options for gpgconf. * agent.h (struct): Add members MIN_PASSPHRASE_NONALPHA, ENFORCE_PASSPHRASE_CONSTRAINTS and CHECK_PASSPHRASE_PATTERN. * genkey.c (nonalpha_charcount): New. (check_passphrase_pattern): New. (check_passphrase_constraints): Implement. Factor some code out... (take_this_one_anyway, take_this_one_anyway2): .. New. * call-pinentry.c (agent_show_message): New. (agent_askpin): We better reset the pin buffer before asking. * trustlist.c (insert_colons): New. (agent_marktrusted): Pretty print the fpr. 2007-08-22 Werner Koch * findkey.c (O_BINARY): Make sure it is defined. (agent_write_private_key): Use O_BINARY * protect-tool.c (import_p12_file): Add hack to allow importing of gnupg 2.0.4 generated files. 2007-08-06 Werner Koch * trustlist.c (read_one_trustfile): Add flag "cm". (agent_istrusted): Ditto. 2007-08-02 Werner Koch * gpg-agent.c: Include gc-opt-flags.h and remove their definition here. 2007-07-13 Werner Koch * genkey.c (check_passphrase_constraints): Require a confirmation for an empty passphrase. (agent_genkey, agent_protect_and_store): No need to repeat an empty passphrase. 2007-07-05 Werner Koch * call-scd.c (struct inq_needpin_s): New. (inq_needpin): Pass unknown inquiries up. 2007-07-04 Werner Koch * gpg-agent.c (TIMERTICK_INTERVAL): New. (fixed_gcry_pth_init, main): Kludge to fix Pth initialization. 2007-07-03 Werner Koch * gpg-agent.c (handle_connections): Do not use FD_SETSIZE for select but compute the correct number. 2007-07-02 Werner Koch * command.c (cmd_reloadagent) [W32]: New. (register_commands) [W32]: New command RELOADAGENT. * Makefile.am (gpg_agent_SOURCES): Remove w32main.c and w32main.h. (gpg_agent_res_ldflags): Remove icon file as we don't have a proper icon yet. * gpg-agent.c (main): do not include w32main.h. Remove all calls to w32main.c. (agent_sighup_action): New. (handle_signal): Use it. 2007-06-26 Werner Koch * gpg-agent.c (create_directories) [W32]: Made it work. 2007-06-21 Werner Koch * agent.h (ctrl_t): Remove. It is now declared in ../common/util.h. * gpg-agent.c (check_for_running_agent): New arg SILENT. Changed all callers. (create_server_socket): If the standard socket is in use check whether a agent is running and avoid starting another one. 2007-06-18 Marcus Brinkmann * gpg-agent.c (main): Percent escape pathname in --gpgconf-list output. 2007-06-18 Werner Koch * w32main.c (build_argv): New. (WinMain): Use it. * command.c (cmd_killagent) [W32]: New. (cmd_getinfo): New. * gpg-agent.c (get_agent_ssh_socket_name): New. (no_force_standard_socket) New. (create_server_socket): Use it. * Makefile.am (gpg_agent_res_ldflags): Pass windows option to ld. 2007-06-14 Werner Koch * protect-tool.c (main): Setup default socket name for simple-pwquery. (MAP_SPWQ_ERROR_IMPL): New. Use map_spwq_error for spqw related error codes. * preset-passphrase.c (main): Setup default socket name for simple-pwquery. (map_spwq_error): Remove. (MAP_SPWQ_ERROR_IMPL): New. * call-pinentry.c (start_pinentry): Use gnupg_module_name. * call-scd.c (start_scd): Ditto. 2007-06-12 Werner Koch * taskbar.c: New. * trustlist.c (read_one_trustfile): Replace GNUPG_SYSCONFDIR by a function call. (read_trustfiles): Ditto. * gpg-agent.c (main): Replace some calls by init_common_subsystems. * preset-passphrase.c (main): Ditto. * protect-tool.c (main): Ditto. 2007-06-11 Werner Koch * Makefile.am (common_libs): Use libcommonstd macro. (commonpth_libs): Use libcommonpth macro. * protect-tool.c (main) [W32]: Call pth_init. * preset-passphrase.c (main) [W32]: Replace the explicit Winsocket init by a call to pth_init. * trustlist.c (initialize_module_trustlist): New. * gpg-agent.c (main): Call it. * call-pinentry.c (initialize_module_query): Rename to initialize_module_call_pinentry. * minip12.c: Remove iconv.h. Add utf8conf.h. Changed all iconv calss to use these jnlib wrappers. 2007-06-06 Werner Koch * minip12.c (enum): Rename CONTEXT to ASNCONTEXT as winnt.h defines such a symbol to access the process context. * call-pinentry.c (dump_mutex_state) [W32]: Handle the W32Pth case. * call-scd.c (dump_mutex_state): Ditto. * protect-tool.c (i18n_init): Remove. * preset-passphrase.c (i18n_init): Remove. * gpg-agent.c (i18n_init): Remove. 2007-05-19 Marcus Brinkmann * protect-tool.c (get_passphrase): Free ORIG_CODESET on error. 2007-05-14 Werner Koch * protect.c (make_shadow_info): Replace sprintf by smklen. 2007-04-20 Werner Koch * gpg-agent.c (my_gcry_logger, my_gcry_outofcore_handler): Removed. (main): Call the setup_libgcrypt_logging helper. * protect-tool.c (my_gcry_logger): Removed. (main): Call the setup_libgcrypt_logging helper. 2007-04-03 Werner Koch * trustlist.c (read_trustfiles): Take a missing trustlist as an empty one. 2007-03-20 Werner Koch * protect-tool.c: New option --p12-charset. * minip12.c (p12_build): Implement it. 2007-03-19 Werner Koch * minip12.c: Include iconv.h. (decrypt_block): New. (parse_bag_encrypted_data, parse_bag_data): Use it here. (bag_data_p, bag_decrypted_data_p): New helpers. 2007-03-06 Werner Koch * gpg-agent.c (main) : Add entries for all ttl options. 2007-02-20 Werner Koch * call-pinentry.c (start_pinentry): Fix for OS X to allow loading of the bundle. Tested by Benjamin Donnachie. 2007-02-14 Werner Koch * gpg-agent.c: New option --pinentry-touch-file. (get_agent_socket_name): New. * agent.h (opt): Add pinentry_touch_file. * call-pinentry.c (start_pinentry): Send new option to the pinentry. 2007-01-31 Moritz Schulte (wk) * command-ssh.c (stream_read_string): Initialize LENGTH to zero. (start_command_handler_ssh): Use es_fgetc/es_ungetc to check if EOF has been reached before trying to process another request. 2007-01-31 Werner Koch * command-ssh.c (start_command_handler_ssh): * Makefile.am (t_common_ldadd): Add LIBICONV. 2007-01-25 Werner Koch * genkey.c (check_passphrase_constraints): Get ngettext call right and use UTF-8 aware strlen. * protect-tool.c (get_passphrase): New arg OPT_CHECK. (get_new_passphrase): Enable OPT_CHECK on the first call. * command.c (cmd_get_passphrase): Implement option --check. 2007-01-24 Werner Koch * gpg-agent.c (MIN_PASSPHRASE_LEN): New (parse_rereadable_options): New option --min-passphrase-len. * genkey.c (check_passphrase_constraints): New. (agent_genkey, agent_protect_and_store): Call new function. Fix memory leak. * call-pinentry.c (agent_askpin): Allow translation of the displayed error message. (agent_popup_message_start): Remove arg CANCEL_BTN. (popup_message_thread): Use --one-button option. * command.c (cmd_passwd): Now that we don't distinguish between assuan and regular error codes we can jump to the end on error. 2006-12-07 David Shaw * Makefile.am: Link to iconv for jnlib dependency. 2006-11-20 Werner Koch * call-pinentry.c (agent_popup_message_stop): Use SIGKILL. * call-scd.c (inq_needpin): Implement POPUPKEYPADPROMPT and DISMISSKEYPADPROMPT. 2006-11-15 Werner Koch * protect.c (make_shadow_info): Cast printf arg to unsigned int. * minip12.c (parse_bag_encrypted_data): Ditto. (parse_bag_data, p12_parse): Ditto. * command-ssh.c (ssh_identity_register): Changed buffer_n to size_t. * agent.h (struct server_control_s): New field thread_startup. * command.c (start_command_handler): Moved CTRL init code to .. * gpg-agent.c (start_connection_thread): .. here. (agent_deinit_default_ctrl): New. (agent_init_default_ctrl): Made static. (handle_connections): Allocate CTRL and pass it pth_spawn. * command-ssh.c (start_command_handler_ssh): Moved CTRL init code to .. * gpg-agent.c (start_connection_thread_ssh): .. here. 2006-11-14 Werner Koch * command.c (bump_key_eventcounter): New. (bump_card_eventcounter): New. (cmd_geteventcounter): New command. * gpg-agent.c (handle_signal): Call bump_card_eventcounter. * findkey.c (agent_write_private_key): Call bump_key_eventcounter. * trustlist.c (agent_reload_trustlist): Ditto. * command.c (post_cmd_notify, io_monitor): New. (register_commands, start_command_handler): Register them. 2006-11-09 Werner Koch * gpg-agent.c (main): In detached mode connect standard descriptors to /dev/null. * trustlist.c (read_trustfiles): Make sure not to pass a zero size to realloc as the C standards says that this behaves like free. 2006-11-06 Werner Koch * protect-tool.c (my_strusage): Fixed typo. 2006-10-23 Werner Koch * gpg-agent.c (main): New command --gpgconf-test. * minip12.c (parse_bag_encrypted_data, parse_bag_data): Allow for a salt of 20 bytes. 2006-10-20 Werner Koch * Makefile.am (t_common_ldadd): Use GPG_ERROR_LIBS instead -o just -l 2006-10-19 Werner Koch * findkey.c (unprotect): Use it to avoid unnecessary calls to agent_askpin. * call-pinentry.c (pinentry_active_p): New. 2006-10-17 Werner Koch * Makefile.am (gpg_agent_LDADD): Link to libcommonpth. (gpg_agent_CFLAGS): New. This allows to only link this with Pth. 2006-10-16 Werner Koch * call-pinentry.c (agent_get_confirmation): Map Cancel code here too. * trustlist.c (agent_marktrusted): Return Cancel instead of Not_Confirmed for the first question. 2006-10-12 Werner Koch * protect-tool.c (get_passphrase): Fix if !HAVE_LANGINFO_CODESET. 2006-10-06 Werner Koch * Makefile.am (AM_CFLAGS): Use PTH version of libassuan. (gpg_agent_LDADD): Ditto. * divert-scd.c (divert_pksign): Use PKAUTH for the TLS algo. 2006-10-05 Werner Koch * command.c (has_option_name): New. (cmd_sethash): New --hash option. * pksign.c (do_encode_raw_pkcs1): New. (agent_pksign_do): Use it here for the TLS algo. * agent.h (GCRY_MD_USER_TLS_MD5SHA1): New. * divert-scd.c (pksign): Add case for tls-md5sha1. * divert-scd.c (encode_md_for_card): Check that the algo is valid. 2006-10-04 Werner Koch * call-pinentry.c (agent_get_passphrase): Changed to return the unencoded passphrase. (agent_askpin, agent_get_passphrase, agent_get_confirmation): Need to map the cancel error. * command.c (send_back_passphrase): New. (cmd_get_passphrase): Use it here. Also implement --data option. (skip_options): New. 2006-09-26 Werner Koch * learncard.c (agent_handle_learn): Send back the keypair information. 2006-09-25 Werner Koch * trustlist.c (read_one_trustfile): Allow extra flags. (struct trustitem_s): Replaced KEYFLAGS by a FLAGS struct. Changed all code to use this. (agent_istrusted): New arg CTRL. Changed all callers. Send back flags. * command.c (agent_write_status): New. 2006-09-20 Werner Koch * Makefile.am: Changes to allow parallel make runs. 2006-09-15 Werner Koch * trustlist.c: Entirely rewritten. (agent_trustlist_housekeeping): Removed and removed all calls. 2006-09-14 Werner Koch Replaced all call gpg_error_from_errno(errno) by gpg_error_from_syserror(). * call-pinentry.c (start_pinentry): Replaced pipe_connect2 by pipe_connect_ext. * call-scd.c (start_scd): Ditto. * command.c (start_command_handler): Replaced init_connected_socket_server by init_socket_server_ext. 2006-09-13 Werner Koch * preset-passphrase.c (main) [W32]: Check for WSAStartup error. 2006-09-08 Werner Koch * call-scd.c: Add signal.h as we are referencing SIGUSR2. 2006-09-06 Marcus Brinkmann * Makefile.am (AM_CFLAGS): Add $(GPG_ERR_CFLAGS). (gpg_agent_LDADD): Replace -lgpg-error with $(GPG_ERROR_LIBS). 2006-09-06 Werner Koch * query.c: Renamed to .. * call-pinentry.c: .. this. * agent.h (out_of_core): Removed. (CTRL): Removed and changed everywhere to ctrl_t. Replaced all Assuan error codes by libgpg-error codes. Removed all map_to_assuan_status and map_assuan_err. * gpg-agent.c (main): Call assuan_set_assuan_err_source to have Assuan switch to gpg-error codes. * command.c (set_error): Adjusted. 2006-09-04 Werner Koch * command.c (percent_plus_unescape): New. (cmd_get_val, cmd_putval): New. 2006-08-29 Werner Koch * command-ssh.c (stream_read_mpi): Sanity check for early detecting of too large keys. * gpg-agent.c (my_gcry_outofcore_handler): New. (main): Register it. (main): No allocate 32k secure memory (was 16k). 2006-07-31 Werner Koch * preset-passphrase.c (make_hexstring): For consistency use xtrymalloc and changed caller to use xfree. Fixed function comment. 2006-07-29 Marcus Brinkmann * preset-passphrase.c (preset_passphrase): Do not strip off last character of passphrase. (make_hexstring): New function. * command.c (cmd_preset_passphrase): Use parse_hexstring to syntax check passphrase argument. Truncate passphrase at delimiter. 2006-07-24 Werner Koch * minip12.c (build_key_bag): New args SHA1HASH and KEYIDSTR. Append bag Attributes if these args are given. (build_cert_sequence): ditto. (p12_build): Calculate certificate hash and pass to build functions. 2006-07-21 Werner Koch * minip12.c (oid_pkcs_12_keyBag): New. (parse_bag_encrypted_data): New arg R_RESULT. Support keybags and return the key object. (p12_parse): Take new arg into account. Free RESULT on error. 2006-06-26 Werner Koch * gpg-agent.c (handle_signal): Print info for SIGUSR2 only in verbose mode. 2006-06-22 Werner Koch * command-ssh.c (make_cstring): Use memcpy instead of strncpy. (ssh_receive_mpint_list, sexp_key_extract, data_sign): Use xtrycalloc instead of xtrymalloc followed by memset. 2006-06-20 Werner Koch * minip12.c (create_final): New arg PW. Add code to calculate the MAC. 2006-06-09 Marcus Brinkmann * Makefile.am (gpg_agent_LDADD): Add $(NETLIBS). (gpg_protect_tool_LDADD): Likewise. (gpg_preset_passphrase_LDADD): Likewise. 2006-04-09 Moritz Schulte * command-ssh.c (ssh_request_process): Removed FIXME mentioning a possible DoS attack. 2006-04-01 Moritz Schulte * command-ssh.c (ssh_identity_register): Make KEY_GRIP_RAW be 20 instead of 21 bytes long; do not fill KEY_GRIP_RAW[20] with NUL byte - KEY_GRIP_RAW is a raw binary string anyway. 2006-02-09 Werner Koch * call-scd.c (struct scd_local_s): New field next_local. (scd_local_list): New. (start_scd): Put new local into list. (agent_reset_scd): Remove it from the list. (agent_scd_check_aliveness): Here is the actual reason why we need all this stuff. (agent_reset_scd): Send the new command RESTART instead of RESET. 2005-12-16 Werner Koch * minip12.c (cram_octet_string): New (p12_parse): Use it for NDEFed bags. (parse_bag_data): Ditto. (string_to_key, set_key_iv, crypt_block): New arg SALTLEN. (p12_build): Use old value 8 for new arg. (parse_bag_encrypted_data, parse_bag_data): Allow for salts of 8 to 16 bytes. Add new arg R_CONSUMED. 2005-11-24 Werner Koch * minip12.c (p12_parse): Fixed for case that the key object comes prior to the certificate. 2005-10-19 Werner Koch * divert-scd.c (getpin_cb): Hack to use it for a keypad message. * call-scd.c (inq_needpin): Reworked to support the new KEYPADINFO. * query.c (start_pinentry): Keep track of the owner. (popup_message_thread, agent_popup_message_start) (agent_popup_message_stop, agent_reset_query): New. * command.c (start_command_handler): Make sure a popup window gets closed. 2005-10-08 Marcus Brinkmann * Makefile.am (gpg_protect_tool_LDADD): Add ../gl/libgnu.a. (gpg_preset_passphrase_LDADD, t_common_ldadd): Likewise. (gpg_agent_LDADD): Add ../gl/libgnu.a after ../common/libcommon.a. 2005-09-16 Werner Koch * minip12.c (build_key_sequence, build_cert_sequence): Fixed padding. 2005-09-15 Moritz Schulte * t-protect.c (test_agent_protect): Implemented. (main): Disable use of secure memory. 2005-09-09 Werner Koch * minip12.c (p12_build): Oops, array needs to be larger for the certificate. (build_cert_bag): Fixed yesterdays change. * command-ssh.c (card_key_available): Let the card handler decide whether the card is supported here. Also get a short serial number to return from the card handler. 2005-09-08 Werner Koch * minip12.c (build_cert_bag): Use a non constructed object. i.e. 0x80 and not 0xa0. 2005-08-16 Werner Koch * gpg-agent.c (main): Use a default file name for --write-env-file. 2005-07-25 Werner Koch * findkey.c (agent_public_key_from_file): Fixed array assignment. This was the cause for random segvs. 2005-06-29 Werner Koch * command-ssh.c (data_sign): Removed empty statement. 2005-06-21 Werner Koch * minip12.c (create_final): Cast size_t to ulong for printf. (build_key_bag, build_cert_bag, build_cert_sequence): Ditto. 2005-06-16 Werner Koch * protect-tool.c (make_advanced): Makde RESULT a plain char. * call-scd.c (unescape_status_string): Need to cast unsigned char* for strcpy. (agent_card_pksign): Made arg R_BUF an unsigned char**. * divert-scd.c (divert_pksign): Made SIGVAL unsigned char*. (encode_md_for_card): Initialize R_VAL and R_LEN. * genkey.c (store_key): Made BUF unsigned. * protect.c (do_encryption): Ditto. (do_encryption): Made arg PROTBEGIN unsigned. Initialize RESULT and RESULTLEN even on error. (merge_lists): Need to cast unsigned char * for strcpy. Initialize RESULTand RESULTLEN even on error. (agent_unprotect): Likewise for strtoul. (make_shadow_info): Made P and INFO plain char. (agent_shadow_key): Made P plain char. 2005-06-15 Werner Koch * query.c (agent_get_passphrase): Made HEXSTRING a char*. * command-ssh.c (ssh_key_grip): Made arg BUFFER unsigned. (ssh_key_grip): Simplified. (data_sign): Initialize variables with the definition. (ssh_convert_key_to_blob): Make sure that BLOB and BLOB_SIZE are set to NULL on error. Cool, gcc-4 detects uninitialized stuff beyond function boundaries; well it can't know that we do error proper error handling so that this was not a real error. (file_to_buffer): Likewise for BUFFER and BUFFER_N. (data_sign): Likewise for SIG and SIG_N. (stream_read_byte): Set B to a value even on error. * command.c (cmd_genkey): Changed VALUE to char. (cmd_readkey): Cast arg for gcry_sexp_sprint. * agent.h (struct server_control_s): Made KEYGRIP unsigned. 2005-06-13 Werner Koch * command-ssh.c (start_command_handler_ssh): Reset the SCD. 2005-06-09 Werner Koch * gpg-agent.c (create_socket_name): New option --max-cache-ttl-ssh. * cache.c (housekeeping): Use it. (agent_put_cache): Use a switch to get the default ttl so that it is easier to add more cases. 2005-06-06 Werner Koch * gpg-agent.c: New option --default-cache-ttl-ssh. * agent.h (cache_mode_t): New. * pksign.c (agent_pksign_do): New arg CACHE_MODE to replace the ARG IGNORE_CACHE. Changed all callers. (agent_pksign): Ditto. * findkey.c (agent_key_from_file): Ditto. Canged all callers. (unprotect): Ditto. * command-ssh.c (data_sign): Use CACHE_MODE_SSH. * cache.c (agent_get_cache): New arg CACHE_MODE. (agent_put_cache): Ditto. Store it in the cache. * query.c (agent_query_dump_state, dump_mutex_state): New. (unlock_pinentry): Reset the global context before releasing the mutex. * gpg-agent.c (handle_signal): Dump query.c info on SIGUSR1. * call-scd.c (agent_scd_check_aliveness): Always do a waitpid and add a timeout to the locking. 2005-06-03 Werner Koch * command.c (cmd_updatestartuptty): New. * gpg-agent.c: New option --write-env-file. * gpg-agent.c (handle_connections): Make sure that the signals we are handling are not blocked.Block signals while creating new threads. 2005-06-02 Werner Koch * call-scd.c (agent_scd_dump_state, dump_mutex_state): New. * gpg-agent.c (handle_signal): Print it on SIGUSR1. (handle_connections): Include the file descriptor into the threadnames. 2005-06-01 Werner Koch * gpg-agent.c: Include setenv.h. 2005-05-31 Werner Koch * agent.h (out_of_core): s/__inline__/inine. Noted by Ray Link. 2005-05-25 Werner Koch * gpg-agent.c (main): Do not unset the DISPLAY when we are continuing as child. 2005-05-24 Werner Koch * call-scd.c (inq_needpin): Skip leading spaces in of PIN description. * divert-scd.c (getpin_cb): Enhanced to cope with description flags. * query.c (agent_askpin): Add arg PROMPT_TEXT. Changed all callers. 2005-05-21 Werner Koch * call-scd.c (start_scd): Don't test for an alive scdaemon here. (agent_scd_check_aliveness): New. * gpg-agent.c (handle_tick): Test for an alive scdaemon. (handle_signal): Print thread info on SIGUSR1. 2005-05-20 Werner Koch * protect-tool.c: New option --canonical. (show_file): Implement it. * keyformat.txt: Define the created-at attribute for keys. 2005-05-18 Werner Koch * divert-scd.c (ask_for_card): Removed the card reset kludge. 2005-05-17 Werner Koch * call-scd.c (unlock_scd): Add new arg CTRL. Changed all callers. (start_scd): Reoworked to allow for additional connections. * agent.h (ctrl_t): Add local data for the SCdaemon. * command.c (start_command_handler): Release SERVER_LOCAL. * gpg-agent.c (create_server_socket): Use xmalloc. (main): Removed option --disable-pth a dummy. Removed non-pth code path. (cleanup_sh): Removed. Not needed anymore. 2005-05-05 Moritz Schulte * command-ssh.c (ssh_key_to_buffer): Rename to ... (ssh_key_to_protected_buffer): ... this; change callers. Improved documentation. Use ssh_key_grip(), where gcry_pk_get_keygrip() has been used before. (ssh_handler_sign_request): Removed unusued variable P. 2005-04-20 Moritz Schulte * command-ssh.c (ssh_handler_request_identities): Removed debugging code (sleep call), which was commited unintenionally. 2005-04-20 Werner Koch * minip12.c (parse_bag_encrypted_data): Fix the unpadding hack. * gpg-agent.c: New option --disable-scdaemon. (handle_connections): Add time event to drive ... (handle_tick): New function. (main): Record the parent PID. Fixed segv when using ssh and a command. * call-scd.c (start_scd): Take care of this option. 2005-04-03 Moritz Schulte * command-ssh.c (ssh_request_spec): New member: secret_input. (REQUEST_SPEC_DEFINE): New argument: secret_input. (request_specs): Add secret_input flag. (request_spec_lookup): New function ... (ssh_request_process): ... use it here; depending on secret_input flag allocate secure or non-secure memory. 2005-03-02 Moritz Schulte * command-ssh.c (sexp_key_extract): Removed FIXME, since xtrymallos does set errno correctly by now. (sexp_extract_identifier): Remove const attribute from identifier. (ssh_handler_request_identities): Remove const attribute from key_type; removes ugly casts and FIXME. (sexp_key_extract): Remove const attribute from comment. (ssh_send_key_public): Remove const attribute from key_type/comment; removes ugly cast. (data_sign): Remove const attribute from identifier; removes ugly cast. (key_secret_to_public): Remove const attribute from comment; removes ugly cast. (ssh_handler_sign_request): Remove const attribute from p. (sexp_key_extract): Use make_cstring(). (ssh_key_extract_comment): Likewise. (ssh_key_to_buffer): Use secure memory for memory area to hold the key S-Expression. Added more comments. 2005-02-25 Werner Koch * findkey.c (modify_description): Keep invalid % escapes, so that %0A may pass through. * agent.h (server_control_s): New field USE_AUTH_CALL. * call-scd.c (agent_card_pksign): Make use of it. * command-ssh.c (data_sign): Set the flag. (ssh_send_key_public): New arg OVERRIDE_COMMENT. (card_key_available): Add new arg CARDSN. (ssh_handler_request_identities): Use the card s/n as comment. (sexp_key_extract): Use GCRYMPI_FMT_STD. (data_sign): Ditto. * learncard.c (make_shadow_info): Moved to .. * protect.c (make_shadow_info): .. here. Return NULL on malloc failure. Made global. * agent.h: Add prototype. 2005-02-24 Werner Koch * call-scd.c (unescape_status_string): New. Actual a copy of ../g10/call-agent.c (card_getattr_cb, agent_card_getattr): New. * command-ssh.c (card_key_available): New. (ssh_handler_request_identities): First see whether a card key is available. * gpg-agent.c (handle_connections): Need to check for events if select returns with -1. 2005-02-23 Werner Koch * command-ssh.c (get_passphrase): Removed. (ssh_identity_register): Partly rewritten. (open_control_file, search_control_file, add_control_entry): New. (ssh_handler_request_identities): Return only files listed in our control file. * findkey.c (unprotect): Check for allocation error. * agent.h (opt): Add fields to record the startup terminal settings. * gpg-agent.c (main): Record them and do not force keep display with --enable-ssh-support. * command-ssh.c (start_command_handler_ssh): Use them here. * gpg-agent.c: Renamed option --ssh-support to --enable-ssh-support. * command.c (cmd_readkey): New. (register_commands): Register new command "READKEY". * command-ssh.c (ssh_request_process): Improved logging. * findkey.c (agent_write_private_key): Always use plain open. Don't depend on an umask for permissions. (agent_key_from_file): Factored file reading code out to .. (read_key_file): .. new function. (agent_public_key_from_file): New. 2005-02-22 Werner Koch * command-ssh.c (stream_read_string): Removed call to abort on memory error because the CVS version of libgcrypt makes sure that ERRNO gets always set on error even with a faulty user supplied function. 2005-02-19 Moritz Schulte * command-ssh.c (ssh_receive_mpint_list): Slightly rewritten, do not use elems_secret member of key_spec. (ssh_key_type_spec): Removed member: elems_secret. (ssh_key_types): Removed elems_secret data. (ssh_sexp_construct): Renamed to ... (sexp_key_construct): ... this; changed callers. (ssh_sexp_extract): Renamed to ... (sexp_key_extract): ... this; changed callers. (ssh_sexp_extract_key_type): Renamed to ... (sexp_extract_identifier): ... this; changed callers; use make_cstring(). Added more comments. 2005-02-18 Moritz Schulte * command-ssh.c (ssh_sexp_construct): Rewritten generation of sexp template, clarified. (ssh_sexp_extract): Support shadowed-private-key-sexp; treat protected-private key and shadowed-private-key as public keys. (key_secret_to_public): Rewritten: simply use ssh_sexp_extract() and ssh_sexp_construct(). 2005-02-15 Werner Koch * findkey.c (modify_description): Don't increment OUT_LEN during the second pass. 2005-02-14 Moritz Schulte * command-ssh.c (es_read_byte): Renamed to ... (stream_es_read_byte): ... this; changed callers. (es_write_byte): Renamed to ... (stream_write_byte): ... this; changed callers. (es_read_uint32): Renamed to ... (stream_read_uint32): ... this; changed callers. (es_write_uint32): Renamed to ... (stream_write_uint32): ... this; changed callers. (es_read_data): Renamed to ... (stream_read_data): ... this; changed callers. (es_write_data): Renamed to ... (stream_write_data): ... this; changed callers. (es_read_string): Renamed to ... (stream_read_string): ... this; changed callers. (es_read_cstring): Renamed to ... (stream_read_cstring): ... this; changed callers. (es_write_string): Renamed to ... (stream_write_string): ... this; changed callers. (es_write_cstring): Renamed to ... (stream_write_cstring): ... this; changed callers. (es_read_mpi): Renamed to ... (stream_read_mpi): ... this; changed callers. (es_write_mpi): Renamed to ... (stream_write_mpi): ... this; changed callers. (es_copy): Renamed to ... (stream_copy): ... this; changed callers. (es_read_file): Renamed to ... (file_to_buffer): ... this; changed callers. (ssh_identity_register): Removed variable description_length; changed code to use asprintf for description. (stream_write_uint32): Do not filter out the last byte of shift expression. (uint32_construct): New macro ... (stream_read_uint32): ... use it; removed unnecessary cast. 2005-02-03 Werner Koch * agent.h (agent_exit): Add JNLIB_GCC_A_NR to indicate that this function won't return. * gpg-agent.c (check_for_running_agent): Initialize pid to a default value if not needed. * command-ssh.c: Removed stdint.h. s/byte_t/unsigned char/, s/uint32/u32/ becuase that is what we have always used in GnuPG. (ssh_request_specs): Moved to top of file. (ssh_key_types): Ditto. (make_cstring): Ditto. (data_sign): Don't use a variable for the passphrase prompt, make it translatable. (ssh_request_process): * findkey.c (modify_description): Renamed arguments for clarity, polished documentation. Make comment a C-string. Fixed case of DESCRIPTION being just "%". (agent_key_from_file): Make sure comment string to a C-string. * gpg-agent.c (create_socket_name): Cleanup the implemntation, use DIMof, agent_exit, removed superflous args and return the allocated string as value. Documented. Changed callers. (create_server_socket): Cleanups similar to above. Changed callers. (cleanup_do): Renamed to .. (remove_socket): .. this. Changed caller. (handle_connections): The signals are to be handled in the select and not in the accept. Test all FDs after returning from a select. Remove the event tests from the accept calls. The select already assured that the accept won't block. 2005-01-29 Moritz Schulte * command-ssh.c (ssh_handler_request_identities) (ssh_handler_sign_request, ssh_handler_add_identity) (ssh_handler_remove_identity, ssh_handler_remove_all_identities) (ssh_handler_lock, ssh_handler_unlock): Changed to return an error code instead of a boolean. (ssh_request_process): Changed to return a boolean instead of an error; adjust caller. (ssh_request_handle_t): Adjusted type. (ssh_request_spec): New member: identifier. (REQUEST_SPEC_DEFINE): New macro; use it for initialization of request_specs[]. (ssh_request_process): In debugging mode, log identifier of handler to execute. (start_command_handler_ssh): Moved most of the stream handling code ... (ssh_request_process): ... here. 2005-01-28 Moritz Schulte * command-ssh.c (ssh_handler_add_identity): Pass ctrl to ssh_identity_register(). (ssh_identity_register): New argument: ctrl; pass ctrl to get_passphrase(). (get_passphrase): Pass ctrl instead of NULL to agent_askpin(). (start_command_handler_ssh): Use agent_init_default_ctrl(); deallocate structure members, which might be dynamically allocated. (lifetime_default): Removed variable. (ssh_handler_add_identity): Fix ttl handling; renamed variable `death' to `ttl'. (ssh_identity_register): Fix key grip handling. 2005-01-26 Moritz Schulte * command-ssh.c (ssh_handler_sign_request): Confirm to agent protocol in case of failure. * command-ssh.c: New file. * Makefile.am (gpg_agent_SOURCES): New source file: command-ssh.c. * findkey.c (modify_description): New function. (agent_key_from_file): Support comment field in key s-expressions. * gpg-agent.c (enum cmd_and_opt_values): New item: oSSHSupport. (opts) New entry for oSSHSupport. New variable: socket_name_ssh. (cleanup_do): New function based on cleanup(). (cleanup): Use cleanup_do() for socket_name and socket_name_ssh. (main): New switch case for oSSHSupport. (main): Move socket name creation code to ... (create_socket_name): ... this new function. (main): Use create_socket_name() for creating socket names for socket_name and for socket_name_ssh in case ssh support is enabled. Move socket creation code to ... (create_server_socket): ... this new function. (main): Use create_server_socket() for creating sockets. In case standard_socket is set, do not only store a socket name in socket_name, but also in socket_name_ssh. Generate additional environment info strings for ssh support. Pass additional ssh socket argument to handle_connections. (start_connection_thread_ssh): New function. (handle_connections): Use select to multiplex between gpg-agent and ssh-agent protocol. * agent.h (struct opt): New member: ssh_support. (start_command_handler_ssh): Add prototype. 2005-01-04 Werner Koch * trustlist.c (agent_marktrusted): Use "Cancel" for the first confirmation and made the strings translatable. * cache.c (agent_put_cache): Fix the test for using the default TTL. 2004-12-21 Werner Koch * preset-passphrase.c (preset_passphrase): Handle --passphrase. * Makefile.am (gpg_preset_passphrase_LDADD): Reorder libs so that pwquery may use stuff from jnlib. Conditionally add -lwsock2 (gpg_protect_tool_LDADD): Ditto. * preset-passphrase.c (main): Use default_homedir(). (main) [W32]: Initialize sockets. 2004-12-21 Marcus Brinkmann * Makefile.am (libexec_PROGRAMS): Add gpg-preset-passphrase. (gpg_preset_passphrase_SOURCES, gpg_preset_passphrase_LDADD): New targets. * agent.h (opt): New member allow_cache_passphrase. * cache.c (housekeeping): Check if R->ttl is not negative. (agent_put_cache): Allow ttl to be negative. * command.c (parse_hexstring): Allow something to follow the hexstring. (cmd_cache_passphrase): New function. (register_commands): Add it. * gpg-agent.c: Handle --allow-preset-passphrase. * preset-passphrase.c: New file. 2004-12-21 Werner Koch * gpg-agent.c (main): Use default_homedir(). * protect-tool.c (main): Ditto. 2004-12-20 Werner Koch * gpg-agent.c (main) [W32]: Now that Mutexes work we can remove the pth_init kludge. (main): Add new options --[no-]use-standard-socket. (check_for_running_agent): Check whether it is running on the standard socket. * call-scd.c (init_membuf, put_membuf, get_membuf): Removed. We now use the identical implementation from ../common/membuf.c. * pksign.c (agent_pksign): Changed arg OUTFP to OUTBUF and use membuf functions to return the value. * pkdecrypt.c (agent_pkdecrypt): Ditto. * genkey.c (agent_genkey): Ditto. * command.c (cmd_pksign, cmd_pkdecrypt, cmd_genkey): Replaced assuan_get_data_fp() by a the membuf scheme. (clear_outbuf, write_and_clear_outbuf): New. 2004-12-19 Werner Koch * query.c (initialize_module_query): New. * call-scd.c (initialize_module_call_scd): New. * gpg-agent.c (main): Call them. 2004-12-18 Werner Koch * gpg-agent.c (main): Remove special Pth initialize. * agent.h (map_assuan_err): Define in terms of map_assuan_err_with_source. 2004-12-17 Moritz Schulte * query.c: Undo change from 2004-12-05. 2004-12-15 Werner Koch * gpg-agent.c [W32]: Various hacks to make it work. * findkey.c (agent_write_private_key) [W32]: Adjust open call. * call-scd.c (start_scd) [W32]: Don't check whether the daemon didn't died. To hard to do under Windows. (start_scd) [W32]: Disable sending of the event signal option. * protect-tool.c (read_file, export_p12_file) [W32]: Use setmode to get stdout and stin into binary mode. 2004-12-05 Moritz Schulte * query.c (start_pinentry): Allow CTRL be NULL. 2004-10-22 Werner Koch * gpg-agent.c (parse_rereadable_options): Return "not handled" when the log file has not beend hadled. This is will let the main option processing continue. Fixed a bug introduced on 2004-09-4 resulting in logging to stderr until a HUP has been given. (main): Don't close the listen FD. 2004-09-30 Werner Koch * Makefile.am: Adjusted from gettext 1.14. 2004-09-29 Werner Koch * minip12.c (parse_bag_encrypted_data): Print error if a bad passphrase has been given. 2004-09-28 Werner Koch * protect.c (agent_unprotect): Fixed wiping of CLEARTEXT. Thanks to Moritz for pointing this out. 2004-09-25 Moritz Schulte * agent.h: Declare: agent_pksign_do. (struct server_control_s): New member: raw_value. * pksign.c (do_encode_md): New argument: raw_value; support generation of raw (non-pkcs1) data objects; adjust callers. (agent_pksign_do): New function, based on code ripped out from agent_pksign. (agent_pksign): Use agent_pksign_do. * command.c (start_command_handler): Set ctrl.digest.raw_value. 2004-09-09 Werner Koch * gpg-agent.c (check_for_running_agent): New. (main): The default action is now to check for an already running agent. (parse_rereadable_options): Set logfile only on reread. (main): Do not print the "is development version" note. 2004-08-20 Werner Koch * gpg-agent.c: New option --max-cache-ttl. Suggested by Alexander Belopolsky. * cache.c (housekeeping): Use it here instead of the hardwired default of 1 hour. * query.c (start_pinentry): Use a timeout for the pinentry lock. 2004-08-18 Werner Koch * protect-tool.c (get_passphrase): Make sure that the default prompts passed to gpg-agent are utf-8 encoded. Add new prompt values. (import_p12_file, import_p12_file, export_p12_file): Changed calls to get_passphrase so that better prompts are displayed. (get_new_passphrase): New. 2004-07-22 Werner Koch * trustlist.c (read_list): Allow colons in the fingerprint. (headerblurb): Rephrased. * gpg-agent.c (handle_connections): Increase the stack size ot 256k. 2004-06-20 Moritz Schulte * gpg-agent.c: Include (build fix for BSD). 2004-05-11 Werner Koch * gpg-agent.c (handle_signal): Reload the trustlist on SIGHUP. (start_connection_thread): Hack to simulate a ticker. * trustlist.c (agent_trustlist_housekeeping) (agent_reload_trustlist): New. Protected all global functions here with a simple counter which is sufficient for Pth. 2004-05-03 Werner Koch * gpg-agent.c: Remove help texts for options lile --lc-ctype. (main): New option --allow-mark-trusted. * trustlist.c (agent_marktrusted): Use it here. 2004-04-30 Werner Koch * protect-tool.c: New option --enable-status-msg. (store_private_key): Print status messages for imported keys. (read_and_unprotect): Ditto for bad passphrase. * gpg-agent.c (parse_rereadable_options): New arg REREAD. Allow changing oLogFile. (current_logfile): New. 2004-04-26 Werner Koch * call-scd.c (start_scd): Do not register an event signal if we are running as a pipe server. 2004-04-21 Werner Koch * call-scd.c (start_scd): Send event-signal option. Always check that the scdaemon is still running. * gpg-agent.c (handle_signal): Do not use SIGUSR{1,2} anymore for changing the verbosity. 2004-04-16 Werner Koch * gpg-agent.c (main): Tell the logging code that we are running detached. 2004-04-06 Werner Koch * gpg-agent.c (main): Use new libgcrypt thread library register scheme. 2004-03-23 Marcus Brinkmann * gpg-agent.c (main): For now, always print the default config file name for --gpgconf-list. 2004-03-17 Werner Koch * gpg-agent.c (main) : Fixed default value quoting. 2004-03-16 Werner Koch * gpg-agent.c (parse_rereadable_options): Use the new DEFAULT_CACHE_TTL macro. (main): Updated --gpgconf-list output. 2004-02-21 Werner Koch * command.c (cmd_passwd): Take acount of a key description. * genkey.c (reenter_compare_cb): Do not set the error text. (agent_protect_and_store, agent_genkey): Force a re-enter after a non-matching passphrase. * query.c (agent_askpin): Add new arg INITIAL_ERRTEXT; changed all callers. 2004-02-19 Werner Koch * protect-tool.c: New options --have-cert and --prompt. (export_p12_file): Read a certificate from STDIN and pass it to p12_build. Detect a keygrip and construct the filename in that case. Unprotcet a key if needed. Print error messages for key formats we can't handle. (release_passphrase): New. (get_passphrase): New arg PROMPTNO. Return the allocated string. Changed all callers. * minip12.c: Revamped the build part. (p12_build): New args CERT and CERTLEN. 2004-02-18 Werner Koch * protect-tool.c (main): Setup the used character set. * gpg-agent.c (main): Ditto. * gpg-agent.c (set_debug): New. New option --debug-level. (main): New option --gpgconf-list. 2004-02-17 Werner Koch * pksign.c (do_encode_md): Cleaned up by using gcry_sexp_build. * Makefile.am (gpg_protect_tool_SOURCES): Removed simple-pwquery.[ch], as we once moved it to ../common. 2004-02-13 Werner Koch * command.c (cmd_setkeydesc): New. (register_commands): Add command SETKEYDESC. (cmd_pksign, cmd_pkdecrypt): Use the key description. (reset_notify): Reset the description. * findkey.c (unprotect): Add arg DESC_TEXT. (agent_key_from_file): Ditto. * pksign.c (agent_pksign): Ditto. * pkdecrypt.c (agent_pkdecrypt): Ditto. Made CIPHERTEXT an unsigned char*. * protect-tool.c (main): New options --no-fail-on-exist, --homedir. (store_private_key): Use them here. 2004-02-12 Werner Koch * protect-tool.c (read_file, main): Allow reading from stdin. * Makefile.am: Include cmacros.am for common flags. (libexec_PROGRAMS): Put gpg-protect-tool there. 2004-02-10 Werner Koch * minip12.c (parse_bag_encrypted_data): Finished implementation. (p12_parse): Add callback args. * protect-tool.c (import_p12_cert_cb): New. (import_p12_file): Use it. 2004-02-06 Werner Koch * minip12.c (crypt_block): Add arg CIPHER_ALGO; changed all callers. (set_key_iv): Add arg KEYBYTES; changed caller. 2004-02-03 Werner Koch * findkey.c (agent_key_from_file): Extra paranoid wipe. * protect.c (agent_unprotect): Ditto. (merge_lists): Ditto. Add arg RESULTLEN. * pkdecrypt.c (agent_pkdecrypt): Don't show the secret key even in debug mode. * protect.c: Add DSA and Elgamal description. 2004-01-29 Werner Koch * agent.h (server_control_s): Add connection_fd field. * command.c (start_command_handler): Init it here. * gpg-agent.c (agent_init_default_ctrl): and here. * call-scd.c: Add the CTRL arg to all functions calling start_scd and pass it to start_scd. Changed all callers (start_scd): Keep track of the current active connection. (agent_reset_scd): New. * command.c (start_command_handler): Call it here. * learncard.c (agent_handle_learn): Add arg CTRL; changed caller. (send_cert_back): Ditto. 2004-01-28 Werner Koch * trustlist.c (agent_marktrusted): Check whether the trustlist is writable. 2004-01-27 Werner Koch * sexp-parse.h: Moved to ../common. 2004-01-24 Werner Koch * call-scd.c (atfork_cb): New. (start_scd): Make sure secmem gets cleared. * query.c (atfork_cb): New. (start_pinentry): Make sure secmem gets cleared. 2004-01-16 Werner Koch * findkey.c (agent_key_from_file): Now return an error code so that we have more detailed error messages in the upper layers. This fixes the handling of pinentry's cancel button. * pksign.c (agent_pksign): Changed accordingly. * pkdecrypt.c (agent_pkdecrypt): Ditto. * command.c (cmd_passwd): Ditto. 2003-12-16 Werner Koch * gpg-agent.c (main): Set the prefixes for assuan logging. 2003-12-15 Werner Koch * protect.c (do_encryption): Use gcry_create_nonce instad of the obsolete WEAK_RANDOM. 2003-11-20 Werner Koch * sexp-parse.h (snext): Don't use atoi_1 and digitp macros, so that this file is useful by other applications too. 2003-10-27 Werner Koch * command.c (cmd_get_confirmation): New command. 2003-08-20 Timo Schulz * pksign.c (do_encode_md): Allocate enough space. Cast md byte to unsigned char to prevent sign extension. 2003-08-14 Timo Schulz * pksign.c (do_encode_md): Due to the fact pkcs#1 padding is now in Libgcrypt, use the new interface. 2003-07-31 Werner Koch * Makefile.am (gpg_agent_LDADD): Added INTLLIBS. (gpg_protect_tool_SOURCES): Added simple-pwquery.[ch] 2003-07-27 Werner Koch Adjusted for gcry_mpi_print and gcry_mpi_scan API change. 2003-07-15 Werner Koch * simple-pwquery.c, simple-pwquery.h: Moved to ../common. * Makefile.am (gpg_protect_tool_LDADD): Add simple-pwquery.o. Removed it from xx_SOURCES. 2003-07-04 Werner Koch * gpg-agent.c (handle_connections): Kludge to allow use of Pth 1 and 2. 2003-06-30 Werner Koch * call-scd.c (learn_status_cb): Store the serialno in PARM. 2003-06-26 Werner Koch * call-scd.c (agent_card_serialno): Don't do a RESET anymore. 2003-06-25 Werner Koch * command.c (cmd_scd): New. * call-scd.c (agent_card_scd): New. * divert-scd.c (divert_generic_cmd): New * call-scd.c (agent_card_learn): New callback args SINFO. (learn_status_cb): Pass all other status lines to the sinfo callback. * learncard.c (release_sinfo, sinfo_cb): New. (agent_handle_learn): Pass the new cb to the learn function and pass the collected information back to the client's assuan connection. * gpg-agent.c (main): Moved pth_init before gcry_check_version. 2003-06-24 Werner Koch * gpg-agent.c (handle_connections): Adjusted for Pth 2.0 Adjusted for changes in the libgcrypt API. Some more fixes for the libgpg-error stuff. 2003-06-04 Werner Koch Renamed error codes from INVALID to INV and removed _ERROR suffixes. 2003-06-03 Werner Koch Changed all error codes in all files to the new libgpg-error scheme. * agent.h: Include gpg-error.h and errno.h * Makefile.am: Link with libgpg-error * query.c: assuan.h is now a system header. * genkey.c (agent_genkey): Fixed silly use of xmalloc by xtrymalloc. 2003-04-29 Werner Koch * command.c (register_commands): Adjusted for new Assuan semantics. * Makefile.am: Don't override LDFLAGS. 2002-12-04 Werner Koch * gpg-agent.c: New variable config_filename. (parse_rereadable_options): New. (main): Use it here. Add setting of default values, set config_filename. (reread_configuration): Filled with actual code. 2002-12-03 Werner Koch * protect-tool.c (read_key): Don't run make_canonical on a NULL buffer. * command.c (parse_hexstring): New. (cmd_sethash): Use it. (parse_keygrip): New. (cmd_havekey, cmd_sigkey): Use it. (cmd_passwd): New. * genkey.c (agent_protect_and_store): New. (store_key): Add arg FORCE. (agent_genkey): Pass false to this force of store_key. 2002-11-13 Werner Koch * gpg-agent.c (main): Switch all messages to utf-8. * simple-pwquery.c (agent_send_all_options): Use $GPG_TTY and stdin with ttyname. * cache.c (new_data): Uiih - /sizeof d/sizeof *d/. 2002-11-10 Werner Koch * command.c (option_handler): Fix keep_tty check. 2002-11-06 Werner Koch * gpg-agent.c (main): Make sure we have a default ttyname. * command.c (option_handler): Check opt.keep_tty here * query.c (start_pinentry): but not anymore here. 2002-11-05 Werner Koch * agent.h (opt,server_control_s): Move display and lc_ variables to the control struct so that they are per connection. * gpg-agent.c (agent_init_default_ctrl): New. (main): Assign those command line options to new default_* variables. Reset DISPLAY in server mode so that tehre is no implicit default. * command.c (start_command_handler): Initialize and deinitialize the control values. (option_handler): Work on the ctrl values and not on the opt. * query.c (start_pinentry): New argument CTRL to set the display connection specific. Changed all callers to pass this value. (agent_askpin,agent_get_passphrase,agent_get_confirmation): Add CTRL arg and pass it ot start_pinentry. * command.c (cmd_get_passphrase): Pass CTRL argument. * trustlist.c (agent_marktrusted): Add CTRL argument * command.c (cmd_marktrusted): Pass CTRL argument * divert-scd.c (ask_for_card): Add CTRL arg. (divert_pksign,divert_pkdecrypt): Ditto. Changed caller. (getpin_cb): Use OPAQUE to pass the CTRL variable. Changed both users. * findkey.c (unprotect): Add CTRL arg. (agent_key_from_file): Ditto. * query.c (unlock_pinentry): Disconnect the pinentry so that we start a new one for each request. This is required to support clients with different environments (e.g. X magic cookies). 2002-09-05 Neal H. Walfield * gpg-agent.c (main) [USE_GNU_PTH]: No need to call assuan_set_io_func as assuan is smart. 2002-09-25 Werner Koch * gpg-agent.c (handle_signal): Flush cache on SIGHUP. * cache.c (agent_flush_cache): New. * gpg-agent.c, agent.h: Add --keep-display and --keep-tty. * query.c (start_pinentry): Implement them. The option passing needs more thoughts. 2002-09-09 Werner Koch * gpg-agent.c (create_private_keys_directory) (create_directories): New. (main): Try to create a home directory. 2002-09-04 Neal H. Walfield * gpg-agent.c (main): Use sigaction, not signal. 2002-09-03 Neal H. Walfield * findkey.c: Include . (agent_write_private_key): Prefer POSIX compatibity, open and fdopen, over the simplicity of GNU extensions, fopen(file, "x"). 2002-08-22 Werner Koch * query.c (agent_askpin): Provide the default desc text depending on the pininfo. Do the basic PIN verification only when min_digits is set. 2002-08-21 Werner Koch * query.c (agent_askpin): Hack to show the right default prompt. (agent_get_passphrase): Ditto. * trans.c: Removed and replaced all usages with standard _() * divert-scd.c (getpin_cb): Pass a more descritive text to the pinentry. * Makefile.am: Renamed the binary protect-tool to gpg-protect-tool. * protect-tool.c: Removed the note about internal use only. * gpg-agent.c (main): New option --daemon so that the program is not accidently started in the background. 2002-08-16 Werner Koch * call-scd.c (learn_status_cb): Handle CERTINFO status. (agent_card_learn): Add args for certinfo cb. * learncard.c (release_certinfo,certinfo_cb): New. (send_cert_back): New. With factored out code from .. (agent_handle_learn): here. Return certinfo stuff. 2002-07-26 Werner Koch * gpg-agent.c (main): New option --ignore-cache-for-signing. * command.c (option_handler): New server option use-cache-for-signing defaulting to true. (cmd_pksign): handle global and per session option. * findkey.c (agent_key_from_file, unprotect): New arg ignore_cache. Changed all callers. * pksign.c (agent_pksign): Likewise. 2002-06-29 Werner Koch * query.c (start_pinentry): Use GNUPG_DERAULT_PINENTRY. * call-scd.c (start_scd): Use GNUPG_DEFAULT_SCDAEMON. 2002-06-28 Werner Koch * protect-tool.c (export_p12_file): New. (main): New command --p12-export. * minip12.c (create_final,p12_build,compute_tag_length): New. (store_tag_length): New. 2002-06-27 Werner Koch * minip12.c (crypt_block): Renamed from decrypt_block, add arg to allow encryption. * Makefile.am (pkglib_PROGRAMS): Put protect-tool there. * findkey.c (agent_write_private_key,agent_key_from_file) (agent_key_available): Use GNUPG_PRIVATE_KEYS_DIR constant. * gpg-agent.c (main): Use GNUPG_DEFAULT_HOMEDIR constant. * protect-tool.c (store_private_key): New. (import_p12_file): Store the new file if requested. (main): New options --force and --store. * gpg-agent.c (main): Set a global flag when running detached. * query.c (start_pinentry): Pass the list of FD to keep in the child when not running detached. * call-scd.c (start_scd): Ditto. 2002-06-26 Werner Koch * command.c (cmd_istrusted, cmd_listtrusted, cmd_marktrusted) (cmd_pksign, cmd_pkdecrypt, cmd_genkey, cmd_get_passphrase) (cmd_learn): Print an error message for a failed operation. * simple-pwquery.c, simple-pwquery.h: New. * protect-tool. (get_passphrase): New, used to get a passphrase from the agent if none was given on the command line. 2002-06-25 Werner Koch * protect-tool.c (rsa_key_check): New. (import_p12_file): New. (main): New command --p12-import. * minip12.c, minip12.h: New. 2002-06-24 Werner Koch * protect-tool.c (read_file): New. (read_key): Factored most code out to read_file. 2002-06-17 Werner Koch * agent.h: Add a callback function to the pin_entry_info structure. * query.c (agent_askpin): Use the callback to check for a correct PIN. Removed the start_err_text argument because it is not anymore needed; changed callers. * findkey.c (unprotect): Replace our own check loop by a callback. (try_unprotect_cb): New. * genkey.c (reenter_compare_cb): New. (agent_genkey): Use this callback here. Fixed setting of the pi2 variable and a segv in case of an empty PIN. * divert-scd.c (getpin_cb): Removed some unused stuff and explained what we still have to change. 2002-06-12 Werner Koch * gpg-agent.c (main): New option --disable-pth. 2002-06-11 Werner Koch * protect-tool.c: Add command --show-keygrip (show_keygrip): New. 2002-05-23 Werner Koch * call-scd.c: Seirialized all scdaeom access when using Pth. * cache.c: Made the cache Pth-thread-safe. (agent_unlock_cache_entry): New. * findkey.c (unprotect): Unlock the returned cache value. * command.c (cmd_get_passphrase): Ditto. * gpg-agent.c (main): Register pth_read/write with Assuan. 2002-05-22 Werner Koch * query.c: Serialized all pinentry access when using Pth. * gpg-agent.c (handle_signal,start_connection_thread) (handle_connections): New (main): Use the new Pth stuff to allow concurrent connections. * command.c (start_command_handler): Add new arg FD so that the fucntion can also be used for an already connected socket. * Makefile.am: Link with Pth. 2002-05-14 Werner Koch * cache.c (housekeeping, agent_put_cache): Use our time() wrapper. 2002-04-26 Werner Koch * cache.c (agent_put_cache): Reinitialize the creation time and the ttl when reusing a slot. * call-scd.c (start_scd): Print debug messages only with debug flags set. * query.c (start_pinentry): Ditto. 2002-04-25 Marcus Brinkmann * agent.h (agent_get_confirmation): Replace paramter prompt with two parameters ok and cancel. * query.c (agent_get_confirmation): Likewise. Implement this. * trustlist.c (agent_marktrusted): Fix invocation of agent_get_confirmation. * divert-scd.c (ask_for_card): Likewise. 2002-04-24 Marcus Brinkmann * agent.h (struct opt): Add members display, ttyname, ttytype, lc_ctype, and lc_messages. * gpg-agent.c (enum cmd_and_opt_values): Add oDisplay, oTTYname, oTTYtype, oLCctype, and LCmessages. (main): Handle these options. * command.c (option_handler): New function. (register_commands): Register option handler. * query.c (start_pinentry): Pass the various display and tty options to the pinentry. 2002-04-05 Werner Koch * protect-tool.c (show_file): New. Used as default action. 2002-03-28 Werner Koch * divert-scd.c (encode_md_for_card): Don't do the pkcs-1 padding, the scdaemon should take care of it. (ask_for_card): Hack to not display the trailing zero. 2002-03-11 Werner Koch * learncard.c (kpinfo_cb): Remove the content restrictions from the keyID. 2002-03-06 Werner Koch * learncard.c: New. * divert-scd.c (ask_for_card): The serial number is binary so convert it to hex here. * findkey.c (agent_write_private_key): New. * genkey.c (store_key): And use it here. * pkdecrypt.c (agent_pkdecrypt): Changed the way the diversion is done. * divert-scd.c (divert_pkdecrypt): Changed interface and implemented it. 2002-03-05 Werner Koch * call-scd.c (inq_needpin): New. (agent_card_pksign): Add getpin_cb args. (agent_card_pkdecrypt): New. 2002-03-04 Werner Koch * pksign.c (agent_pksign): Changed how the diversion is done. * divert-scd.c (divert_pksign): Changed interface and implemented it. (encode_md_for_card): New. * call-scd.c (agent_card_pksign): New. 2002-02-28 Werner Koch * pksign.c (agent_pksign): Detect whether a Smartcard is to be used and divert the operation in this case. * pkdecrypt.c (agent_pkdecrypt): Likewise * findkey.c (agent_key_from_file): Add optional arg shadow_info and have it return information about a shadowed key. * protect.c (agent_get_shadow_info): New. * protect.c (snext,sskip,smatch): Moved to * sexp-parse.h: New file. * divert-scd.c: New. 2002-02-27 Werner Koch * protect.c (agent_shadow_key): New. * command.c (cmd_learn): New command LEARN. * gpg-agent.c: New option --scdaemon-program. * call-scd.c (start_scd): New. Based on query.c * query.c: Add 2 more arguments to all uses of assuan_transact. 2002-02-18 Werner Koch * findkey.c (unprotect): Show an error message for a bad passphrase. * command.c (cmd_marktrusted): Implemented. * trustlist.c (agent_marktrusted): New. (open_list): Add APPEND arg. * query.c (agent_get_confirmation): New. 2002-02-06 Werner Koch * cache.c (housekeeping): Fixed linking in the remove case. 2002-02-01 Werner Koch * gpg-agent.c: New option --default-cache-ttl. * cache.c (agent_put_cache): Use it. * cache.c: Add a few debug outputs. * protect.c (agent_private_key_type): New. * agent.h: Add PRIVATE_KEY_ enums. * findkey.c (agent_key_from_file): Use it to decide whether we have to unprotect a key. (unprotect): Cache the passphrase. * findkey.c (agent_key_from_file,agent_key_available): The key files do now require a ".key" suffix to make a script's life easier. * genkey.c (store_key): Ditto. 2002-01-31 Werner Koch * genkey.c (store_key): Protect the key. (agent_genkey): Ask for the passphrase. * findkey.c (unprotect): Actually unprotect the key. * query.c (agent_askpin): Add an optional start_err_text. 2002-01-30 Werner Koch * protect.c: New. (hash_passphrase): Based on the GnuPG 1.0.6 version. * protect-tool.c: New 2002-01-29 Werner Koch * findkey.c (agent_key_available): New. * command.c (cmd_havekey): New. (register_commands): And register new command. 2002-01-20 Werner Koch * command.c (cmd_get_passphrase): Remove the plus signs. * query.c (start_pinentry): Send no-grab option to pinentry * gpg-agent.c (main): Move variable grab as no_grab to agent.h. 2002-01-19 Werner Koch * gpg-agent.c (main): Disable core dumps. * cache.c: New. * command.c (cmd_get_passphrase): Use the cache. (cmd_clear_passphrase): Ditto. * gpg-agent.c: Removed unused cruft and implement the socket based server. (my_strusage): Take bug report address from configure.ac. * command.c (start_command_handler): Add an argument to start as regular server. (start_command_handler): Enable Assuan logging. 2002-01-15 Werner Koch * trustlist.c: New. * command.c (cmd_istrusted, cmd_listtrusted, cmd_marktrusted): New. 2002-01-07 Werner Koch * genkey.c: Store the secret part and return the public part. 2002-01-03 Werner Koch * command.c (cmd_get_passphrase): New. (cmd_clear_passphrase): New. * query.c (agent_get_passphrase): New. 2002-01-02 Werner Koch * genkey.c: New. * command.c (cmd_genkey): New. * command.c (rc_to_assuan_status): Removed and changed all callers to use map_to_assuan_status. 2001-12-19 Werner Koch * keyformat.txt: New. 2001-12-19 Marcus Brinkmann * query.c (start_pinentry): Add new argument to assuan_pipe_connect. 2001-12-18 Werner Koch * Makefile.am: Use LIBGCRYPT macros 2001-12-14 Werner Koch * gpg-agent.c (main): New option --batch. New option --debug-wait n, so that it is possible to attach gdb when used in server mode. * query.c (agent_askpin): Don't ask in batch mode. * command.c: Removed the conversion macros as they are now in ../common/util.h. 2001-12-14 Marcus Brinkmann * query.c (LINELENGTH): Removed. (agent_askpin): Use ASSUAN_LINELENGTH, not LINELENGTH. 2001-11-19 Werner Koch * gpg-agent.c: Removed all GUI code, removed code for old protocol. New code to use the Assuan protocol as a server and also to communicate with a new ask-passphrase utility. 2000-11-22 Werner Koch * gpg-agent.c (main): csh support by Dan Winship, new options --sh and --csh and set default by consulting $SHELL. Mon Aug 21 17:59:17 CEST 2000 Werner Koch * gpg-agent.c (passphrase_dialog): Cleanup the window and added the user supplied text to the window. (main): Fixed segv in gtk_init when used without a command to start. * gpg-agent.c: --flush option. (req_flush): New. (req_clear_passphrase): Implemented. Fri Aug 18 14:27:14 CEST 2000 Werner Koch * gpg-agent.c: New. * Makefile.am: New. Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 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/agent/genkey.c b/agent/genkey.c index 7c6b44b96..b064c98ed 100644 --- a/agent/genkey.c +++ b/agent/genkey.c @@ -1,462 +1,462 @@ /* genkey.c - Generate a keypair * Copyright (C) 2002, 2003, 2004, 2007, 2010 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 3 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, see . */ #include #include #include #include #include #include #include #include "agent.h" #include "i18n.h" #include "exechelp.h" #include "sysutils.h" static int store_key (gcry_sexp_t private, const char *passphrase, int force) { int rc; unsigned char *buf; size_t len; unsigned char grip[20]; if ( !gcry_pk_get_keygrip (private, grip) ) { log_error ("can't calculate keygrip\n"); return gpg_error (GPG_ERR_GENERAL); } len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, NULL, 0); assert (len); buf = gcry_malloc_secure (len); if (!buf) return out_of_core (); len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, buf, len); assert (len); if (passphrase) { unsigned char *p; rc = agent_protect (buf, passphrase, &p, &len); if (rc) { xfree (buf); return rc; } xfree (buf); buf = p; } rc = agent_write_private_key (grip, buf, len, force); xfree (buf); return rc; } /* Count the number of non-alpha characters in S. Control characters and non-ascii characters are not considered. */ static size_t nonalpha_count (const char *s) { size_t n; for (n=0; *s; s++) if (isascii (*s) && ( isdigit (*s) || ispunct (*s) )) n++; return n; } /* Check PW against a list of pattern. Return 0 if PW does not match these pattern. */ static int check_passphrase_pattern (ctrl_t ctrl, const char *pw) { gpg_error_t err = 0; const char *pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CHECK_PATTERN); FILE *infp; const char *argv[10]; pid_t pid; int result, i; (void)ctrl; infp = gnupg_tmpfile (); if (!infp) { err = gpg_error_from_syserror (); log_error (_("error creating temporary file: %s\n"), strerror (errno)); return 1; /* Error - assume password should not be used. */ } if (fwrite (pw, strlen (pw), 1, infp) != 1) { err = gpg_error_from_syserror (); log_error (_("error writing to temporary file: %s\n"), strerror (errno)); fclose (infp); return 1; /* Error - assume password should not be used. */ } fseek (infp, 0, SEEK_SET); clearerr (infp); i = 0; argv[i++] = "--null"; argv[i++] = "--", argv[i++] = opt.check_passphrase_pattern, argv[i] = NULL; assert (i < sizeof argv); if (gnupg_spawn_process_fd (pgmname, argv, fileno (infp), -1, -1, &pid)) result = 1; /* Execute error - assume password should no be used. */ - else if (gnupg_wait_process (pgmname, pid, 0, NULL)) + else if (gnupg_wait_process (pgmname, pid, 1, NULL)) result = 1; /* Helper returned an error - probably a match. */ else result = 0; /* Success; i.e. no match. */ gnupg_release_process (pid); /* Overwrite our temporary file. */ fseek (infp, 0, SEEK_SET); clearerr (infp); for (i=((strlen (pw)+99)/100)*100; i > 0; i--) putc ('\xff', infp); fflush (infp); fclose (infp); return result; } static int take_this_one_anyway2 (ctrl_t ctrl, const char *desc, const char *anyway_btn) { gpg_error_t err; if (opt.enforce_passphrase_constraints) { err = agent_show_message (ctrl, desc, _("Enter new passphrase")); if (!err) err = gpg_error (GPG_ERR_CANCELED); } else err = agent_get_confirmation (ctrl, desc, anyway_btn, _("Enter new passphrase"), 0); return err; } static int take_this_one_anyway (ctrl_t ctrl, const char *desc) { return take_this_one_anyway2 (ctrl, desc, _("Take this one anyway")); } /* Check whether the passphrase PW is suitable. Returns 0 if the passphrase is suitable and true if it is not and the user should be asked to provide a different one. If SILENT is set, no message are displayed. */ int check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent) { gpg_error_t err; unsigned int minlen = opt.min_passphrase_len; unsigned int minnonalpha = opt.min_passphrase_nonalpha; if (!pw) pw = ""; if (utf8_charcount (pw) < minlen ) { char *desc; if (silent) return gpg_error (GPG_ERR_INV_PASSPHRASE); desc = xtryasprintf ( ngettext ("Warning: You have entered an insecure passphrase.%%0A" "A passphrase should be at least %u character long.", "Warning: You have entered an insecure passphrase.%%0A" "A passphrase should be at least %u characters long.", minlen), minlen ); if (!desc) return gpg_error_from_syserror (); err = take_this_one_anyway (ctrl, desc); xfree (desc); if (err) return err; } if (nonalpha_count (pw) < minnonalpha ) { char *desc; if (silent) return gpg_error (GPG_ERR_INV_PASSPHRASE); desc = xtryasprintf ( ngettext ("Warning: You have entered an insecure passphrase.%%0A" "A passphrase should contain at least %u digit or%%0A" "special character.", "Warning: You have entered an insecure passphrase.%%0A" "A passphrase should contain at least %u digits or%%0A" "special characters.", minnonalpha), minnonalpha ); if (!desc) return gpg_error_from_syserror (); err = take_this_one_anyway (ctrl, desc); xfree (desc); if (err) return err; } /* If configured check the passphrase against a list of know words and pattern. The actual test is done by an external program. The warning message is generic to give the user no hint on how to circumvent this list. */ if (*pw && opt.check_passphrase_pattern && check_passphrase_pattern (ctrl, pw)) { const char *desc = /* */ _("Warning: You have entered an insecure passphrase.%%0A" "A passphrase may not be a known term or match%%0A" "certain pattern."); if (silent) return gpg_error (GPG_ERR_INV_PASSPHRASE); err = take_this_one_anyway (ctrl, desc); if (err) return err; } /* The final check is to warn about an empty passphrase. */ if (!*pw) { const char *desc = (opt.enforce_passphrase_constraints? _("You have not entered a passphrase!%0A" "An empty passphrase is not allowed.") : _("You have not entered a passphrase - " "this is in general a bad idea!%0A" "Please confirm that you do not want to " "have any protection on your key.")); if (silent) return gpg_error (GPG_ERR_INV_PASSPHRASE); err = take_this_one_anyway2 (ctrl, desc, _("Yes, protection is not needed")); if (err) return err; } return 0; } /* Callback function to compare the first entered PIN with the one currently being entered. */ static int reenter_compare_cb (struct pin_entry_info_s *pi) { const char *pin1 = pi->check_cb_arg; if (!strcmp (pin1, pi->pin)) return 0; /* okay */ return -1; } /* Ask the user for a new passphrase using PROMPT. On success the function returns 0 and store the passphrase at R_PASSPHRASE; if the user opted not to use a passphrase NULL will be stored there. The user needs to free the returned string. In case of an error and error code is returned and NULL stored at R_PASSPHRASE. */ gpg_error_t agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt, char **r_passphrase) { gpg_error_t err; const char *text1 = prompt; const char *text2 = _("Please re-enter this passphrase"); const char *initial_errtext = NULL; struct pin_entry_info_s *pi, *pi2; *r_passphrase = NULL; pi = gcry_calloc_secure (2, sizeof (*pi) + 100); pi2 = pi + (sizeof *pi + 100); pi->max_length = 100; pi->max_tries = 3; pi->with_qualitybar = 1; pi2->max_length = 100; pi2->max_tries = 3; pi2->check_cb = reenter_compare_cb; pi2->check_cb_arg = pi->pin; next_try: err = agent_askpin (ctrl, text1, NULL, initial_errtext, pi); initial_errtext = NULL; if (!err) { if (check_passphrase_constraints (ctrl, pi->pin, 0)) { pi->failed_tries = 0; pi2->failed_tries = 0; goto next_try; } /* Unless the passphrase is empty, ask to confirm it. */ if (pi->pin && *pi->pin) { err = agent_askpin (ctrl, text2, NULL, NULL, pi2); if (err == -1) { /* The re-entered one did not match and the user did not hit cancel. */ initial_errtext = _("does not match - try again"); goto next_try; } } } if (!err && *pi->pin) { /* User wants a passphrase. */ *r_passphrase = xtrystrdup (pi->pin); if (!*r_passphrase) err = gpg_error_from_syserror (); } xfree (pi); return err; } /* Generate a new keypair according to the parameters given in KEYPARAM */ int agent_genkey (ctrl_t ctrl, const char *keyparam, size_t keyparamlen, membuf_t *outbuf) { gcry_sexp_t s_keyparam, s_key, s_private, s_public; char *passphrase = NULL; int rc; size_t len; char *buf; rc = gcry_sexp_sscan (&s_keyparam, NULL, keyparam, keyparamlen); if (rc) { log_error ("failed to convert keyparam: %s\n", gpg_strerror (rc)); return gpg_error (GPG_ERR_INV_DATA); } /* Get the passphrase now, cause key generation may take a while. */ rc = agent_ask_new_passphrase (ctrl, _("Please enter the passphrase to%0A" "to protect your new key"), &passphrase); if (rc) return rc; rc = gcry_pk_genkey (&s_key, s_keyparam ); gcry_sexp_release (s_keyparam); if (rc) { log_error ("key generation failed: %s\n", gpg_strerror (rc)); xfree (passphrase); return rc; } /* break out the parts */ s_private = gcry_sexp_find_token (s_key, "private-key", 0); if (!s_private) { log_error ("key generation failed: invalid return value\n"); gcry_sexp_release (s_key); xfree (passphrase); return gpg_error (GPG_ERR_INV_DATA); } s_public = gcry_sexp_find_token (s_key, "public-key", 0); if (!s_public) { log_error ("key generation failed: invalid return value\n"); gcry_sexp_release (s_private); gcry_sexp_release (s_key); xfree (passphrase); return gpg_error (GPG_ERR_INV_DATA); } gcry_sexp_release (s_key); s_key = NULL; /* store the secret key */ if (DBG_CRYPTO) log_debug ("storing private key\n"); rc = store_key (s_private, passphrase, 0); xfree (passphrase); passphrase = NULL; gcry_sexp_release (s_private); if (rc) { gcry_sexp_release (s_public); return rc; } /* return the public key */ if (DBG_CRYPTO) log_debug ("returning public key\n"); len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, NULL, 0); assert (len); buf = xtrymalloc (len); if (!buf) { gpg_error_t tmperr = out_of_core (); gcry_sexp_release (s_private); gcry_sexp_release (s_public); return tmperr; } len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, buf, len); assert (len); put_membuf (outbuf, buf, len); gcry_sexp_release (s_public); xfree (buf); return 0; } /* Apply a new passphrase to the key S_SKEY and store it. */ int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey) { int rc; char *passphrase; rc = agent_ask_new_passphrase (ctrl, _("Please enter the new passphrase"), &passphrase); if (!rc) { rc = store_key (s_skey, passphrase, 1); xfree (passphrase); } return rc; } diff --git a/common/ChangeLog b/common/ChangeLog index 1f5637845..dd8c0a3a2 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,1990 +1,1996 @@ +2010-06-24 Werner Koch + + * asshelp.c (lock_agent_spawning) [W32]: Use CreateMutexW. + (start_new_gpg_agent): Use HANG option for gnupg_wait_progress. + Fixes regression from 2010-06-09. + 2010-06-21 Werner Koch * util.h (xfree_fnc): New. 2010-06-18 Werner Koch * util.h (GPG_ERR_MISSING_KEY) [!GPG_ERR_MISSING_KEY]: New. * sexputil.c (make_canon_sexp_pad): Add arg SECURE. 2010-06-17 Werner Koch * sexputil.c (make_canon_sexp_pad): New. 2010-06-14 Werner Koch * membuf.c (put_membuf): Add shortcut for !LEN. 2010-06-11 Marcus Brinkmann * sysutils.c (translate_sys2libc_fd): Revert last change. (translate_sys2libc_fd_int): Revert last change. 2010-06-10 Marcus Brinkmann * sysutils.c (translate_sys2libc_fd) [HAVE_W32CE_SYSTEM]: Implement. (translate_sys2libc_fd_int) [HAVE_W32CE_SYSTEM]: Don't call translate_sys2libc_fd. * estream.c (_es_get_std_stream): Fix cut&paste bug. 2010-06-09 Werner Koch * exechelp-posix.c, exechelp-w32.c * exechelp-w32ce.c (gnupg_wait_process): Add new arg HANG. Change all callers. (gnupg_release_process): New. Use it after all calls to gnupg_wait_process. * util.h (GNUPG_MODULE_NAME_DIRMNGR_LDAP): New. * homedir.c (gnupg_cachedir): New. (w32_try_mkdir): New. - (dirmngr_socket_name): Chanmge standard socket name. + (dirmngr_socket_name): Change standard socket name. (gnupg_module_name): Support GNUPG_MODULE_NAME_DIRMNGR_LDAP. * logging.c (log_set_get_tid_callback): Replace by ... (log_set_pid_suffix_cb): .. new. (do_logv): Change accordingly. 2010-06-08 Marcus Brinkmann * Makefile.am (AM_CFLAGS): Add $(LIBASSUAN_CFLAGS). (t_common_ldadd): Add $(LIBASSUAN_LIBS). * sysutils.c: Include . (translate_sys2libc_fd_int): Cast to silence gcc warning. * iobuf.c: Include (translate_file_handle): Fix syntax error. 2010-06-08 Werner Koch * iobuf.c (translate_file_handle) [W32CE]: Handle rendezvous ids. 2010-06-07 Werner Koch * sysutils.c [W32CE]: Finish pipe creation. * estream.c (es_fname_get, es_fname_set): New. (fname_set_internal): New. (struct estream_internal): Add fields printable_fname and printable_fname_inuse. (_es_get_std_stream): Set stream name. (es_fopen, es_freopen, es_deinitialize): Set fname. * exechelp-posix.c (gnupg_spawn_process): Allow passing INFILE or OUTFILE as NULL. * exechelp-w32.c (gnupg_spawn_process): Ditto. * exechelp-w32ce.c (gnupg_spawn_process): Return an error for INFILE or OUTFILE passed as NULL. 2010-06-01 Werner Koch * logging.c (log_get_stream): Make sture a log stream is available. 2010-05-30 Werner Koch * init.c (writestring_via_estream): New. (init_common_subsystems): Register with argparse. * argparse.c (argparse_register_outfnc): New. (writestrings, flushstrings): New. Use them instead of stdout or stderr based functions. 2010-05-04 Werner Koch * estream.c (_es_get_std_stream): Re-use registered standard fds. (IS_INVALID_FD, ESTREAM_SYS_YIELD): New. (es_func_fd_read, es_func_fd_write, es_func_fd_seek) (es_func_fd_destroy): Implement a dummy stream. * exechelp-w32ce.c (build_w32_commandline): Add args FD0_ISNULL and FD1_ISNULL. Remove arg PGMNAME. Change callers. (gnupg_spawn_process_detached): Implement. (gnupg_spawn_process_fd): Implement one special case for now. 2010-05-03 Werner Koch * asshelp.c (lock_agent_spawning, unlock_agent_spawning): New. (start_new_gpg_agent): Test for configured standard socket and try to fire up the agent in this case. * exechelp-posix.c (gnupg_wait_process): Do not log a message if EXITCODE is given. (gnupg_spawn_process_detached): Do not reuse PID for the second fork. 2010-04-26 Werner Koch * utf8conv.c (load_libiconv) [W32CE]: No libiconv warning * init.c (init_common_subsystems) [W32CE]: Register the sleep function before es_init. 2010-04-20 Werner Koch * estream.c (es_deinit): New. (es_init_do): Install atexit handler to flush all streams. * Makefile.am (common_sources): Add gettime.h. 2010-04-20 Marcus Brinkmann * logging.c (do_log_ignore_arg): New helper function. (log_string): Use it to remove ugly volatile hack that causes gcc warning. (log_flush): Likewise. * sysutils.c (gnupg_unsetenv) [!HAVE_W32CE_SYSTEM]: Return something. (gnupg_setenv) [!HAVE_W32CE_SYSTEM]: Likewise. * pka.c (get_pka_info): Solve strict aliasing rule violation. * t-exechelp.c (test_close_all_fds): Use dummy variables to silence gcc warning. 2010-04-15 Werner Koch * util.h: Factor time related functions out to ... * gettime.h: New. (gnupg_copy_time): Move to ... * gettime.c (gnupg_copy_time): New. * sysutils.c (gnupg_setenv) [!W32CE]: Add missing return. (gnupg_unsetenv) [!W32CE]: Add missing return. 2010-04-14 Werner Koch * Makefile.am (noinst_LIBRARIES) [W32CE]: Exclude libsimple-pwquery. * w32help.h (umask) [W32CE]: New. * sysutils.c (_gnupg_isatty): New. * util.h (gnupg_isatty): New. * asshelp.c (setup_libassuan_logging): Read ASSUAN_DEBUG envvar. (my_libassuan_log_handler): Use it. * sysutils.c (_gnupg_getenv): Implement ASSUAN_DEBUG. 2010-04-08 Werner Koch * w32help.h (_setmode, setmode) [W32CE]: Provide prototype and macro. 2010-04-07 Werner Koch * mischelp.c (timegm): Replace unsetenv/putenv by gnupg_unsetenv. * sysutils.c: Include setenv.h. (gnupg_setenv, gnupg_unsetenv): New. 2010-04-06 Werner Koch * sysutils.c (gnupg_mkdir): New. 2010-03-29 Werner Koch * init.c (sleep_on_exit): Change to 400ms. 2010-03-25 Werner Koch * init.c (sleep_on_exit) [W32CE]: New. (init_common_subsystems): Call it. 2010-03-24 Werner Koch * stringhelp.c (change_slashes, compare_filenames): Replace HAVE_DRIVE_LETTERS by HAVE_DOSISH_SYSTEM. (make_basename, make_dirname): Detect backslashes and drive letters separately. * dotlock.c (make_dotlock, create_dotlock, release_dotlock): Use LockFileEx and UnlockFileEx to support W32CE. * ttyio.c (USE_W32_CONSOLE): Replace all _WIN32 by this. (init_ttyfp) [W32CE]: Use stderr. * iobuf.c (FD_FOR_STDIN, FD_FOR_STDOUT) [W32CE]: Use estream. (translate_file_handle) [W32CE]: Remove handle translation. 2010-03-23 Werner Koch * sysutils.c (gnupg_remove): New. 2010-03-22 Werner Koch * exechelp-w32ce.c (build_w32_commandline): Replace by code from libassuan. (create_inheritable_pipe): Use _assuan_w32ce_prepare_pipe. (build_w32_commandline_copy, do_create_pipe): Remove. * exechelp-posix.c (gnupg_spawn_process): Change to use estream also for INFILE and STATUSFILE. * exechelp-w32.c (gnupg_spawn_process): Ditto. 2010-03-22 Werner Koch * exechelp.c: Remove after factoring all code out to ... * exechelp-posix.c, exechelp-w32.c, exechelp-w32ce.c: .. new. * exechelp.c (create_inheritable_pipe_r) (create_inheritable_pipe_w): Fold both into ... (create_inheritable_pipe): .. New. Change callers to use this. (gnupg_create_inbound_pipe, gnupg_create_outbound_pipe): Factor code out to ... (do_create_pipe): .. New. * init.c (parse_std_file_handles): Change to use rendezvous ids. 2010-03-15 Werner Koch * init.c (init_common_subsystems): Add args ARGCP and ARGVP. Change all callers to provide them. (parse_std_file_handles): New. * t-sysutils.c (rewind) [W32CE]: Provide a replacement. * Makefile.am (module_tests) [W32CE]: Don't build t-exechelp for now. * sysutils.c (gnupg_allow_set_foregound_window) [W32CE]: Don't call AllowSetForegroundWindow. * logging.c (isatty) [W32CE]: New. (fun_writer, set_file_fd): Use estream even for the internal error messages. (log_string, log_flush): Make DUMMY_ARG_PTR static. 2010-03-15 Werner Koch * asshelp.c (send_pinentry_environment) [!HAVE_SETLOCALE]: Do not define OLD_LC. * http.c (connect_server) [!USE_DNS_SRV]: Mark SRVTAG unused. * dns-cert.c (get_dns_cert) [!USE_DNS_CERT]: Mark args unused. * pka.c (get_pka_info): Ditto. * signal.c (pause_on_sigusr): Remove. It was used in ancient gpg version with shared memory IPC. Last caller removed on 2006-04-18. (do_block) [W32]: Mark arg unused. * exechelp.c (w32_open_null): Use CreateFileW. * init.c (init_common_subsystems): Add args ARGCP and ARGVP. Change all callers to pass them. * logging.c (S_IRGRP, S_IROTH, S_IWGRP, S_IWOTH) [W32]: New. (fun_writer, set_file_fd) [W32]: Disable socket code. * localename.c: Include gpg-error.h. * util.h (GPG_ERR_NOT_ENABLED): Remove this temporary definition. 2010-03-12 Werner Koch * status.h (STATUS_ENTER): New. * ttyio.c (tty_fprintf): Change to use estream. * miscellaneous.c (print_utf8_string): Rename to print_utf8_buffer and change FP arg to an estream. Change all callers. (print_utf8_string2): Ditto; new name is to print_utf8_buffer2. 2010-03-11 Werner Koch * miscellaneous.c (print_string): Remove. * estream.c (es_setvbuf): Fix parameter check. (es_set_buffering): Allow a SIZE of 0. * asshelp.c (setup_libassuan_logging, my_libassuan_log_handler): New. * logging.c (do_logv): Add arg IGNORE_ARG_PTR. Change all callers. (log_string): New. (log_flush): New. (set_file_fd): Simplify by using estreams es_stderr. * estream.h (es_stdout, es_stderr, es_stdin): New. 2010-03-10 Werner Koch * estream.c (es_func_fp_read, es_func_fp_write, es_func_fp_seek) (es_func_fp_destroy): Allow a NULL FP to implement a dummy stream. (do_fpopen): Ditto. (es_vfprintf_unlocked): New. (es_fprintf_unlocked): Make public. (es_fputs_unlocked): New. * logging.h: Replace FILE* by estream_t. * logging.c: Remove USE_FUNWRITER cpp conditional because we now use estream. (my_funopen_hook_ret_t, my_funopen_hook_size_t): Replace by ssize_t. (log_get_stream): Change to return an estream_t. (set_file_fd): Always close the log stream because it can't be assigned to stderr or stdout directly. Use a dummy estream as last resort log stream. (log_test_fd, log_get_fd): Use es_fileno. (log_get_stream): Assert that we have a log stream. (do_logv): Use estream functions and lock the output. 2010-03-10 Werner Koch * util.h: Replace jnlib path part by common. (snprintf): Use the replacement macro on all platforms. * Makefile.am (jnlib_sources): New. (libcommon_a_SOURCES, libcommonpth_a_SOURCES): Add jnlib_sources. (jnlib_tests): New. (noinst_PROGRAMS, TESTS): Add jnlib_tests. (t_common_ldadd): Remove libjnlib.a. * README.jnlib, ChangeLog.jnlib, libjnlib-config.h, argparse.c * argparse.h, dotlock.c, dotlock.h, dynload.h, logging.c * logging.h, mischelp.c, mischelp.h, stringhelp.c, stringhelp.h * strlist.c, strlist.h, types.h, utf8conv.c, utf8conv.h * w32-afunix.c, w32-afunix.h, w32-reg.c, w32help.h, xmalloc.c * xmalloc.h, t-stringhelp.c, t-support.c, t-support.h * t-timestuff.c, t-w32-reg.c: Move from jnlib to here. * init.c: Remove "estream.h". * util.h: Include "estream.h". * xasprintf.c, ttyio.c: Remove "estream-printf.h". 2010-03-08 Werner Koch * exechelp.c [!HAVE_SIGNAL_H]: Do not include signal.h. (DETACHED_PROCESS, CREATE_NEW_PROCESS_GROUP) [W32CE]: Provide stubs. * iobuf.h (iobuf_ioctl_t): New. Use the new macros instead of the hard wired values. * iobuf.c (iobuf_append): Remove. (iobuf_fdopen): Factor code out to ... (do_iobuf_fdopen): ... new. (iobuf_fdopen_nc): New. (iobuf_open_fd_or_name): Implement using iobuf_fdopen_nc. * iobuf.c (INVALID_FD): Replace by GNUPG_INVALID_FD. (fp_or_fd_t): Replace by gnupg_fd_t. (my_fileno): Replace by the FD2INT macro. (FILEP_OR_FD_FOR_STDIN, FILEP_OR_FD_FOR_STDOUT): Rename to FD_FOR_STDIN, FD_FOR_STDOUT. (file_filter): Make full use of FD_FOR_STDIN. (USE_SETMODE): Remove. Not needed without stdio. (my_fopen_ro, my_fopen): Replace unneeded macros. * iobuf.c [FILE_FILTER_USES_STDIO]: Remove all code. It has not been used for a long time. * exechelp.h: Include "estream.h". * exechelp.c (gnupg_spawn_process): Change OUTFILE to an estream_t. 2010-03-02 Werner Koch * estream.c, estream.h, estream-printf.c, estream-printf.h: Update from libestream. 2010-03-01 Werner Koch * signal.c [!HAVE_SIGNAL_H]: Don't include signal.h. * iobuf.c (direct_open) [W32CE]: Make filename to wchar_t. (iobuf_cancel) [W32CE]: Use DeleteFile. * gettime.c (dump_isotime): Use "%s" to print "none". * homedir.c (standard_homedir) [W32CE]: Use wchar_t to create the directory. (w32_rootdir) [W32CE]: Likewise. * sysutils.c (translate_sys2libc_fd) [W32CE]: Add support. (gnupg_tmpfile) [W32CE]: Ditto. (_gnupg_getenv) [W32CE]: New. * util.h (getpid, getenv) [W32CE]: New. * i18n.c (i18n_switchto_utf8) (i18n_switchback) [USE_SIMPLE_GETTEXT]: Use new function from libgpg-error which supports proper restoring. * sysutils.c (get_session_marker): Simplified by using gcrypt. 2009-12-08 Marcus Brinkmann * Makefile.am (audit-events.h, status.h) [!MAINTAINER_MODE]: No longer include these rules if not in maintainer mode. 2009-12-08 Werner Koch * userids.h, userids.c: New. (classify_user_id): Merged from similar fucntions in sm/ and g10/. * dns-cert.c (get_dns_cert): Add support for ADNS. 2009-12-08 Marcus Brinkmann * asshelp.c (start_new_gpg_agent): Convert posix FD to assuan FD. * asshelp.c (start_new_gpg_agent) [HAVE_W32_SYSTEM]: Add missing argument in assuan_socket_connect invocation. * iobuf.c (iobuf_open_fd_or_name): Fix type of FD in function declaration. 2009-12-07 Werner Koch * pka.c (get_pka_info): Add support for ADNS. * src.v (getsrv): Add support for ADNS. * srv.c (getsrv): s/xrealloc/xtryrealloc/. 2009-12-04 Werner Koch * Makefile.am (audit-events.h, status-codes.h): Create files in the source dir. Fixes bug#1164. 2009-12-02 Werner Koch * audit.c (proc_type_decrypt, proc_type_sign): Implemented. (proc_type_verify): Print hash algo infos. * audit.h (AUDIT_DATA_CIPHER_ALGO, AUDIT_BAD_DATA_CIPHER_ALSO) (AUDIT_NEW_RECP, AUDIT_DECRYPTION_RESULT, AUDIT_RECP_RESULT) (AUDIT_ATTR_HASH_ALGO, AUDIT_SIGNED_BY, AUDIT_SIGNING_DONE): 2009-11-05 Marcus Brinkmann * asshelp.c (start_new_gpg_agent): Update use of assuan_socket_connect and assuan_pipe_connect. 2009-11-02 Marcus Brinkmann * get-passphrase.c (default_inq_cb, membuf_data_cb): Change return type to gpg_error_t. 2009-10-28 Werner Koch * status.h (STATUS_MOUNTPOINT): New. 2009-10-16 Marcus Brinkmann * Makefile.am (libcommon_a_CFLAGS): Use LIBASSUAN_CFLAGS instead of LIBASSUAN_PTH_CFLAGS. 2009-10-13 Werner Koch * exechelp.c (gnupg_kill_process): New. 2009-09-29 Werner Koch * exechelp.c (create_inheritable_pipe): Rename to create_inheritable_pipe_w. (create_inheritable_pipe_r): New. (gnupg_create_outbound_pipe): New. * iobuf.h: Include "sysutils.h" * iobuf.c (iobuf_open_fd_or_name): New. (iobuf_get_fname_nonnull): New. 2009-09-23 Marcus Brinkmann * asshelp.c (start_new_gpg_agent): Allocate assuan context before starting server. 2009-09-03 Werner Koch Update from libestream: * estream-printf.c: Include stdint.h only if HAVE_STDINT_H is defined. * estream-printf.c: Remove all test code. Use macro DEBUG instead of TEST for debugging. * estream-printf.c (pr_float): Make buffer larger for silly high numbers. 2009-08-11 David Shaw * ttyio.h, ttyio.c (tty_enable_completion): Some ifdefs around HAVE_LIBREADLINE to allow building when readline isn't available. 2009-08-06 Werner Koch * status.h (STATUS_INV_SGNR, STATUS_NO_SGNR): New. * status.c (get_inv_recpsgnr_code): New. 2009-07-23 David Shaw * srv.c (getsrv): Fix type-punning warning. 2009-07-23 Werner Koch * util.h (GPG_ERR_NOT_ENABLED): New. * audit.h (enum): Add AUDIT_CRL_CHECK. * audit.c (proc_type_verify): Show CRL check result. 2009-07-06 Werner Koch * get-passphrase.c (struct agentargs): Add SESSION_ENV and remove obsolete args. (gnupg_prepare_get_passphrase): Ditto. * session-env.c, session-env.h: New. * t-session-env.c: New. * Makefile.am (common_sources, module_tests): Add them. * asshelp.h: Include "session-env.h" * asshelp.c (send_one_option): Add arg PUTENV. (send_pinentry_environment): Replace most args by SESSION_ENV and rewrite fucntion. (start_new_gpg_agent): Likewise. * t-exechelp.c (test_close_all_fds): Remove debug code. 2009-07-01 Werner Koch * sexputil.c (get_pk_algo_from_canon_sexp): New. 2009-06-29 Werner Koch * estream.c (BUFFER_ROUND_TO_BLOCK): Remove unused macro. (es_func_mem_write): Rewrite reallocation part. * estream.c (es_write_sanitized_utf8_buffer): Typo typo fix. 2009-06-25 Werner Koch * estream.c (es_write_sanitized_utf8_buffer): Typo fix. 2009-06-24 Werner Koch * estream.c (es_read_line): In the malloc error case, set MAX_LENGTH to 0 only if requested. * xreadline.c (read_line): Ditto. * estream.c (es_write_sanitized_utf8_buffer): Pass on error from es_fputs. * sexputil.c (get_rsa_pk_from_canon_sexp): Check for error after the loop. Reported by Fabian Keil. 2009-06-22 Werner Koch * estream.c (es_pth_read, es_pth_write) [W32]: New. (ESTREAM_SYS_READ, ESTREAM_SYS_WRITE) [HAVE_PTH]: Use them. 2009-06-03 Werner Koch * estream.c (es_convert_mode): Rewrite and support the "x" flag. 2009-05-28 David Shaw From 1.4: * http.h, http.c (send_request) Pass in a STRLIST for additional headers. Change all callers. 2009-05-27 David Shaw From 1.4: * http.h, http.c (send_request): Pass in srvtag and make its presence sufficient to turn the feature on. (http_open): From here. (http_document): And here. * srv.c (getsrv): Raise maximum packet size to 2048, as PACKETSZ is too small these days. 2009-05-22 Werner Koch * ttyio.c (tty_cleanup_after_signal): New. 2009-05-19 Werner Koch * simple-pwquery.c (agent_open): Use SUN_LEN (JNLIB_NEED_AFLOCAL): Define and include mischelp.h. 2009-05-07 Werner Koch * sexputil.c (get_rsa_pk_from_canon_sexp): New. * t-sexputil.c (test_make_canon_sexp_from_rsa_pk): Extend the test. 2009-04-28 Werner Koch * sexputil.c (make_canon_sexp_from_rsa_pk): New. * t-sexputil.c (test_make_canon_sexp_from_rsa_pk): New. 2009-04-01 Werner Koch * iobuf.c: Port David's changes from 1.4: (fd_cache_invalidate): Pass return code from close back. (direct_open, iobuf_ioctl): Check that return value. (fd_cache_synchronize): New. (iobuf_ioctl): Add new sub command 4 (fsync). * iobuf.c (fd_cache_strcmp): New. Taken from 1.4. (fd_cache_invalidate, fd_cache_close, fd_cache_open): Use it. * exechelp.c (gnupg_spawn_process): Implement new flag bit 6. * sysutils.c (gnupg_allow_set_foregound_window): Allow the use of ASFW_ANY. * membuf.c (put_membuf, get_membuf): Wipe memory on out of core. 2009-03-31 Werner Koch * percent.c (percent_unescape, percent_plus_unescape): New. (percent_plus_unescape_inplace, percent_unescape_inplace): New. (do_plus_or_plain_unescape, count_unescape, do_unescape): New. (do_unescape_inplace): New. * t-percent.c (test_percent_plus_escape): Test percent_plus_unescape. * get-passphrase.c, get-passphrase.h: New. * Makefile.am (without_pth_sources): New. 2009-03-18 Werner Koch * exechelp.c: Include sys/resource.h and sys/stat.h. (get_max_open_fds): New. (do_exec): Use it. (get_all_open_fds): New. (close_all_fds): New. (do_exec): Use close_all_fds. * t-exechelp.c: New. 2009-03-13 David Shaw * http.c (do_parse_uri): Properly handle IPv6 literal addresses as per RFC-2732. Adapted from patch by Phil Pennock. 2009-03-12 Werner Koch * gettime.c: Include i18n.h. (dump_isotime): New. 2009-03-06 Werner Koch * sexputil.c (make_canon_sexp): New. 2009-03-03 Werner Koch * exechelp.c (do_exec): Make sure that /dev/null connected FDs are not closed. 2009-01-19 Werner Koch * audit.c (writeout_li): Translate a few more result strings. Fixes bug#970. * convert.c (hex2str): Fix optimization to append a nul character. 2008-12-05 Werner Koch * percent.c, t-percent.c: New. * exechelp.c (gnupg_spawn_process, gnupg_spawn_process_fd) (gnupg_spawn_process_detached) [W32]: Remove debug output. 2008-11-20 Werner Koch * audit.c (writeout_li): Translate OKTEXT. 2008-11-04 Werner Koch * i18n.c (i18n_init) [USE_SIMPLE_GETTEXT]: Adjust for changed w32-gettext.c. * homedir.c (gnupg_localedir): New. 2008-10-20 Werner Koch * http.c (http_register_tls_callback) [!HTTP_USE_GNUTLS]: Mark unused arg. * localename.c (do_nl_locale_name): Ditto. * audit.c (event2str): Silent gcc warning. * sysutils.c (translate_sys2libc_fd): Mark unused arg. (translate_sys2libc_fd_int): Ditto. * iobuf.c (translate_file_handle): Ditto. * asshelp.c (send_one_option): Ditto. * exechelp.c (gnupg_spawn_process): Ditto. * signal.c (got_usr_signal): Ditto * estream.c (es_func_fd_create) [!W32]: Ditto. (es_func_fp_create) [!W32]: Ditto. (es_write_hexstring): Ditto. (dummy_mutex_call_void, dummy_mutex_call_int) [HAVE_PTH]: New. (ESTREAM_MUTEX_LOCK, ESTREAM_MUTEX_UNLOCK, ESTREAM_MUTEX_TRYLOCK) (ESTREAM_MUTEX_INITIALIZE) [HAVE_PTH]: Use dummy calls so to mark unused arg. 2008-10-19 Werner Koch * estream-printf.c (estream_vsnprintf): Fix return value. (check_snprintf): Add a new test. (one_test) [W32]: Disable test. 2008-10-17 Werner Koch * util.h (snprintf) [W32]: Redefine to estream_snprintf. 2008-09-03 Werner Koch * convert.c (hex2str): New. (hex2str_alloc): New. * t-convert.c (test_hex2str): New. 2008-08-19 Werner Koch * iobuf.c: Avoid passing a NULL (iobuf_t)->desc to the log function. Should in general never be NULL, but well. Reported by M. Heneka. 2008-06-26 Werner Koch * estream.c (es_write_sanitized): Loose check for control characters to better cope with utf-8. The range 0x80..0x9f is nowadays not anymore accidently used for control charaters. 2008-06-25 Marcus Brinkmann Revert last three changes related to handle translation. * sysutils.c: (FD_TRANSLATE_MAX, fd_translate, fd_translate_len) (translate_table_init, translate_table_lookup): Removed. * iobuf.c (check_special_filename): Do not use translate_table_lookup. * sysutils.h (translate_table_init, translate_table_lookup): Remove prototypes. 2008-06-19 Werner Koch * sysutils.c: Remove . (fd_translate_max): Use macro for the size. (translate_table_init): Protect read against EINTR and replace isspace by spacep. 2008-06-18 Marcus Brinkmann * sysutils.c (TRANS_MAX): Bump up to 350 to be on the safe side. * sysutils.h (translate_table_init, translate_table_lookup): New prototypes. * sysutils.c: Include . (FD_TRANSLATE_MAX): New macro. (fd_translate, fd_translate_len): New static variables. (translate_table_init, translate_table_lookup): New functions. (translate_sys2libc_fd_int): Translate file descriptor. * iobuf.c (check_special_filename): Translate handle values from special filenames. 2008-06-16 Werner Koch * homedir.c (w32_commondir): New. (gnupg_sysconfdir): Use it. 2008-06-09 Werner Koch * b64dec.c: New. 2008-06-05 Werner Koch * util.h (gnupg_copy_time): Replace strcpy by memcpy. 2008-05-26 Werner Koch * asshelp.c (send_one_option, send_pinentry_environment): use xfree and xtrystrdup. * i18n.c (i18n_switchto_utf8) [USE_SIMPLE_GETTEXT]: Return NULL. * homedir.c (gnupg_module_name): Add GNUPG_MODULE_NAME_CONNECT_AGENT and GNUPG_MODULE_NAME_GPGCONF. 2008-04-21 Werner Koch * http.c (http_wait_response) [W32]: Use DuplicateHandle because it is a socket. (cookie_read) [W32]: Use recv in place of read. 2008-04-08 Werner Koch * i18n.c (i18n_switchto_utf8, i18n_switchback) [USE_SIMPLE_GETTEXT]: Implement. 2008-04-07 Werner Koch * b64enc.c (b64enc_start): Detect PGP mode. (b64enc_finish): Write PGP CRC. * util.h (struct b64state): Add field CRC. * t-b64.c: New. * pka.c (get_pka_info): Use xtrymalloc and check result. 2008-03-25 Werner Koch * localename.c: Strip all W32 code. Include w32help.h. (gnupg_messages_locale_name) [W32]: Use the gettext_localename. 2008-03-17 Werner Koch * iobuf.c (IOBUF_BUFFER_SIZE): Actually use this macro. * simple-pwquery.c (agent_send_all_options): Fix last change. 2008-03-06 Werner Koch * simple-pwquery.c (agent_send_all_options): Add support for XAUTHORITY and PINENTRY_USER_DATA. 2008-02-15 Marcus Brinkmann * exechelp.c (gnupg_spawn_process_fd): Add flag DETACHED_PROCESS unconditionally (required for all callers at the moment). 2008-02-14 Werner Koch * sysutils.c (gnupg_allow_set_foregound_window): New. (WINVER) [W32]: Define. 2008-01-31 Werner Koch * audit.c (audit_print_result): Make sure that the output is always UTF8. 2008-01-27 Werner Koch * exechelp.c (gnupg_spawn_process): Add arg FLAGS and changed all callers to pass 0 for it. 2007-12-13 Werner Koch * sexputil.c (hash_algo_from_sigval): New. * t-sexputil.c: New. * Makefile.am (module_tests): Add it. 2007-12-11 Werner Koch * asshelp.c (send_pinentry_environment): Allow using of old gpg-agents not capabale of the xauthority and pinentry_user_data options. 2007-12-04 Werner Koch * Makefile.am (t_helpfile_LDADD, module_maint_tests): New. * t-helpfile.c: New. * helpfile.c: New. * membuf.h (is_membuf_ready, MEMBUF_ZERO): New. * localename.c: New. Taken from gettext with modifications as done for GpgOL. Export one new function. * util.h (gnupg_messages_locale_name, gnupg_get_help_string): Added. * sysutils.c (gnupg_reopen_std): New. Taken from ../g10/gpg.c. 2007-11-27 Werner Koch * Makefile.am (CLEANFILES): New. * homedir.c (dirmngr_socket_name): Use CSIDL_WINDOWS. 2007-11-15 Werner Koch * asshelp.c (send_pinentry_environment): Add args XAUTHORITY and PINENTRY_USER_DATA. (start_new_gpg_agent): Ditto. 2007-11-07 Werner Koch * status.h: New. * errors.h: Remove. 2007-11-05 Werner Koch * audit.c, audit.h: New. * Makefile.am: Add rules to build audit-events.h. * exaudit.awk: New. * mkstrtable.awk: New. Taken from libgpg-error. 2007-10-19 Werner Koch * i18n.c (i18n_switchto_utf8, i18n_switchback): New. 2007-10-01 Werner Koch * sysutils.h (FD2INT, INT2FD): New. 2007-09-21 Werner Koch * homedir.c (default_homedir): Make registry work. Reported by Marc Mutz. 2007-08-29 Werner Koch * exechelp.c (gnupg_wait_process): Add arg EXITCODE. Changed all callers. (gnupg_create_inbound_pipe): New. * util.h (GNUPG_MODULE_NAME_GPGSM, GNUPG_MODULE_NAME_GPG): New. * homedir.c (gnupg_module_name): Add them 2007-08-28 Werner Koch * gettime.c (check_isotime, add_isotime): New. Originally written for DirMngr by me. (add_days_to_isotime): New. (date2jd, jd2date, days_per_month, days_per_year): New. Taken from my ancient (1988) code used in Wedit (time2.c). 2007-08-27 Werner Koch * util.h (GNUPG_MODULE_NAME_CHECK_PATTERN): New. * homedir.c (gnupg_module_name): Add it. * exechelp.c (w32_fd_or_null) [W32]: New. (gnupg_spawn_process_fd): New. (gnupg_wait_process) [W32]: Close the handle after if the process has returned. 2007-08-22 Werner Koch Updated estream from libestream. * estream.c (mem_malloc, mem_realloc, mem_free): New. Use them instead of the ES_MEM_foo. * estream.c (estream_cookie_mem): Remove members DONT_FREE, APPEND_ZERO, PTR and SIZE. Add MEMORY_LIMIT. Put GROW into a new FLAGS struct. (es_func_mem_create): Remove APPEND_ZERO, DONT_FREE, PTR and SIZE. Add MEMORY_LIMIT. (es_func_mem_write, es_func_mem_seek, es_func_mem_destroy): Revamp. (es_open_memstream): Change API to just take a memory limit and a mode argument. Rename to .. (es_fopenmem): .. this. (HAVE_W32_SYSTEM) [_WIN32]: Define if not defined. (tmpfd) [W32]: Implement directly using the W32 API. (es_fgets): Rewrite without using doreadline. 2007-08-21 Werner Koch * sysutils.c (gnupg_tmpfile): New. * t-sysutils.c: New. * Makefile.am (module_tests): Add t-sysutils. 2007-08-20 Werner Koch * exechelp.c [W32]: Redefine X_OK to F_OK. 2007-08-16 Werner Koch * Makefile.am (t_convert_DEPENDENCIES): Remove ($(PROGRAMS)): Remove. (t_common_ldadd): Use libcommon.a and not the macro. 2007-08-14 Werner Koch * homedir.c (dirmngr_socket_name): New. 2007-08-07 Werner Koch * tlv.c, tlv.h: Move from ../scd/. * tlv.c (parse_sexp, parse_ber_header): Add ERRSOURCE arg and prefix name with a _. * tlv.h: Use macro to convey ERRSOURCE. 2007-08-02 Werner Koch * gc-opt-flags.h: New. 2007-08-01 Werner Koch * estream-printf.c (read_dummy_value): Removed as it is useless now. (read_values): Remove check on !vaargs which is not anymore needed and anyway not portable. Reported by Peter O'Gorman. 2007-07-16 Werner Koch * estream.c (es_func_file_create): Clear NO_CLOSE flag. 2007-07-12 Werner Koch * sysutils.h (gnupg_fd_t): New. * sysutils.c (translate_sys2libc_fd): Use that type instead of int. (translate_sys2libc_fd_int): New. 2007-07-09 Werner Koch * t-gettime.c (test_isotime2epoch): Use time_t and not u32. 2007-07-05 Werner Koch * t-gettime.c: New. * gettime.c (isotime2epoch, epoch2isotime): New. 2007-07-04 Werner Koch * estream.c (es_init_do): Do not throw an error if pth has already been initialized. 2007-06-26 Werner Koch * Makefile.am ($(PROGRAMS)): New. * util.h (init_common_subsystems): Moved to .. * init.h: .. New. * util.h: Include init.h. * homedir.c (standard_homedir): New. (default_homedir) [W32]: Reimplemented in terms of standard_homedir. Fixed memory leak. 2007-06-25 Werner Koch * iobuf.c: Add more documentation and slighly restructured macro defintion for better readability. (FILEP_OR_FD): Rename to fp_or_fd_t. (CLOSE_CACHE): Rename to close_cache_t. * sysutils.c (translate_sys2libc_fd): New using the code from iobuf.c. * iobuf.c: Include sysutils.h. (iobuf_translate_file_handle): Remove. (translate_file_handle): Use new function. * estream-printf.c [TEST]: Header including fixes. (do_format): Do not append a trailing Nul. This avoids spurious Nuls in the es_printf output. (estream_vsnprintf, estream_vasprintf): Take this in account. * estream.h (struct es__stream): Change FLAGS to a bit structure. (ES__FLAG_WRITING): Replace by a bit from FLAGS. * estream.c (struct estream_internal): Rename FLAGS to MODEFLAGS so that they are not confused with the estream flags. (es_initialize, es_create): Add arg MODEFLAGS so that we can setup the intial writemode. Changed all callers to pass them. (es_convert_mode): Set O_BINARY. (es_func_fd_create, es_func_fp_create, es_func_file_create) [W32]: Call setmode if requested. 2007-06-24 Werner Koch * estream.c (do_fpopen, es_fpopen, es_fpopen_nc): New. (es_func_fp_create, es_func_fp_read, es_func_fp_write) (es_func_fp_seek, es_func_fp_destroy): New. 2007-06-22 Werner Koch * estream.c (es_fdopen): Factored code out to.. (do_fdopen): .. new. (es_fdopen_nc): New. (estream_cookie_fd): Add field NO_CLOSE. (es_func_fd_create): Add arg NO_CLOSE and changed all callers. (es_func_fd_destroy): Handle the new flag. * homedir.c (gnupg_libexecdir) [W32]: Factor code out to .. (w32_rootdir): .. new. (gnupg_sysconfdir, gnupg_libdir, gnupg_datadir) [W32]: Return name based on w32_rootdir(). 2007-06-21 Werner Koch * membuf.h (get_membuf_len): New. * membuf.c (init_membuf_secure): Really allocate in secure memory. (put_membuf_str): New. * ttyio.c (tty_getf): New. * util.h (ctrl_t): Declare it here. * asshelp.c (start_new_gpg_agent): New. Based on code from ../sm/call-agent.c 2007-06-20 Werner Koch * sysutils.c (gnupg_sleep): New. * sysutils.h [W32]: Remove _sleep wrapper. Changed all callers to use gnupg_sleep. * exechelp.c (build_w32_commandline_copy): New. (build_w32_commandline): Factored some code out to new function and correctly process a PGMNAME with spaces. (gnupg_spawn_process_detached) [W32]: Implement. 2007-06-14 Werner Koch * simple-pwquery.h (MAP_SPWQ_ERROR_IMPL): New. (SPWQ_NO_PIN_ENTRY): New. * simple-pwquery.c (simple_pw_set_socket): New. (agent_open): Use it if GPG_AGENT_INFO is not set. (simple_pwquery): Extended to allow returning of otehyr error codes. * util.h (GNUPG_MODULE_NAME_AGENT, GNUPG_MODULE_NAME_PINENTRY) (GNUPG_MODULE_NAME_SCDAEMON, GNUPG_MODULE_NAME_DIRMNGR) (GNUPG_MODULE_NAME_PROTECT_TOOL): New. * homedir.c (gnupg_module_name): New. (gnupg_bindir): New. 2007-06-12 Werner Koch * homedir.c (gnupg_sysconfdir): New. (gnupg_libexecdir): New. Taken from g10/misc.c:get_libexecdir. (gnupg_datadir): New. (gnupg_libdir): New. * http.c (connect_server) [W32]: Do not call init_sockets if HTTP_NO_WSASTARTUP is defined. * init.c: New. * estream.c (es_init_do): Init stream lock here because we can't use a static initialization with W32pth. 2007-06-11 Werner Koch * Makefile.am (t_common_ldadd): Use libcommonstd macro. 2007-06-06 Werner Koch * Makefile.am: Include am/cmacros.am. * sysutils.h [W32]: Remove prototypes for the registry access. * w32reg.c: Move to ../jnlib/w32-reg.c. * i18n.c (i18n_init): New. * simple-gettext.c: Remove. * iobuf.c (iobuf_get_filelength): Rename SIZE to EXSIZE to silent shadowing warning. 2007-06-04 Werner Koch * http.c [W32]: Include unistd.h also in this case. (write_server) [W32]: Fixed error code. (init_sockets): Fixed syntax error. (cookie_close): Replace close by sock_close macro. * estream.c [w32]: Do not init Mutex. * Makefile.am (common_sources) [USE_SNS_SRV]: Build srv.c only when needed. * ttyio.c (init_ttyfp) [W32]: Do not use TTYFP. * util.h: Include ../jnlib/dynload.h. * dynload.h: Move to ../jnlib. 2007-05-30 Werner Koch * estream.c (MEM_FREE, MEM_ALLOC, MEM_REALLOC): Prefix with ES_ as windows.h also has such definitions, 2007-05-15 Werner Koch * util.h: Do not include gnulib's vasprintf. Redefine asprintf and vasprintf. * xasprintf.c (xasprintf, xtryasprintf): Use estream_vasprintf. * estream-printf.h, estream-printf.c: New. Taken from current libestream SVN. * Makefile.am (common_sources): Add them. 2007-05-14 Werner Koch * sexp-parse.h (smklen): New. * sexputil.c: Include sexp-parse.h. (make_simple_sexp_from_hexstr): Replace sprintf by smklen. 2007-05-07 Werner Koch * signal.c (got_fatal_signal): Protect SIG from being clobbered by a faulty signal implementaion. Suggested by James Juran. 2007-04-25 Werner Koch * i18n.h (ngettext): New. * simple-gettext.c (ngettext): New. 2007-04-20 Werner Koch * miscellaneous.c (my_gcry_logger, my_gcry_outofcore_handler): Moved from gpg-agent to here. (my_gcry_fatalerror_handler): new. (setup_libgcrypt_logging): New. 2007-03-19 Werner Koch * miscellaneous.c (print_hexstring): New. * estream.c (es_fprintf_unlocked): New. (es_write_sanitized): New. (es_write_hexstring): New. (es_write_sanitized_utf8_buffer) [GNUPG_MAJOR_VERSION]: New. 2007-03-09 David Shaw From STABLE-BRANCH-1-4 * http.c (do_parse_uri): Remove the hkp port 11371 detection. We implement hkp in the keyserver handler, and the support here makes it appear like a bad hkp request actually succeeded. 2007-01-31 Werner Koch * Makefile.am (t_common_ldadd): Add LIBINCONV and LIBINTL. 2007-01-25 Werner Koch * simple-pwquery.c (simple_pwquery): New arg OPT_CHECK. 2006-12-13 David Shaw * Makefile.am (AM_CPPFLAGS): Include intl/ so we can reference the built-in headers. 2006-11-23 Werner Koch * http.c: Include i18n.h 2006-11-21 Werner Koch * estream.c: Remove explicit Pth soft mapping diabling becuase it is now done in config.h. 2006-11-15 Werner Koch * estream.c: Disabled Pth soft mapping. (my_funopen_hook_ret_t): New. (print_fun_writer): Use it here. * iobuf.c (fd_cache_close): Use %d instead of %p for debug output. 2006-11-03 Werner Koch * Makefile.am (t_convert_DEPENDENCIES): Add libcommon. From Gentoo. 2006-10-24 Marcus Brinkmann * Makefile.am (libcommon_a_CFLAGS): Add $(LIBASSUAN_CFLAGS). (libsimple_pwquery_a_CFLAGS): New variable. 2006-10-20 Werner Koch * convert.c (hex2bin): New. 2006-10-17 Werner Koch * estream.c (struct estream_internal, es_initialize) (es_deinitialize, print_fun_writer, es_print): New and modified functions to avoid tempfiles for printf style printing. * Makefile.am (libcommonpth_a_SOURCES): New. We now build a secon version of the library with explicit Pth support. * exechelp.c, estream.c: Make use of WITHOUT_GNU_PTH. 2006-10-08 Werner Koch * gpgrlhelp.c: Trun all functions into dummies if readline is not available. 2006-10-06 Werner Koch * Makefile.am (AM_CFLAGS): Use PTH version of libassuan. * util.h (GNUPG_GCC_A_SENTINEL): Defined for gcc >= 4. 2006-10-04 David Shaw * gpgrlhelp.c: readline requires stdio.h. 2006-10-04 Werner Koch * membuf.c (init_membuf_secure): New. (put_membuf): Make sure that ERRNO is set even if the underlying malloc code does not work properly. (get_membuf): Set ERRNO on error. (get_membuf): Allow to pass LEN as NULL. 2006-10-02 Werner Koch * iobuf.c (iobuf_unread): Removed. This code is not required. Also removed the entire unget buffer stuff. 2006-09-27 Werner Koch * util.h: Do not include strsep.h and strpbrk.h. (isascii): Removed as it is now in jnlib. * iobuf.c (pop_filter, underflow, iobuf_close): Free the unget buffer. 2006-09-27 Florian Weimer (wk) * iobuf.c (iobuf_unread): New. 2006-09-22 Werner Koch * i18n.h: Changed license to an all permissive one. * ttyio.c (tty_get): We need to use readline too. Added two more hooks. 2006-09-21 Werner Koch * ttyio.c (tty_private_set_rl_hooks): New. (tty_enable_completion, tty_disable_completion): Use a hook to enable readline support. Now always available. (tty_cleanup_rl_after_signal): New. * ttyio.h: Removed readline specific stuff. Included util.h. * common-defs.h: New. 2006-09-15 Werner Koch * convert.c: New. (hexcolon2bin): New. (bin2hex, bin2hexcolon, do_binhex): New. * t-convert.c: New 2006-09-14 Werner Koch * util.h (out_of_core): Use new gpg_error_from_syserror function. * http.c (init_sockets): Changed it to require 2.2 unless it is build within gnupg 1 where we require 1.1 (and not anymore allow for 1.0). 2006-09-07 Werner Koch * exechelp.c (gnupg_spawn_process): Factor out post fork code to .. (do_exec): .. new function. Allow passing of -1 for the fds. (gnupg_spawn_process): Terminate gcrypt's secure memory in the child. (gnupg_spawn_process_detached): New. 2006-09-06 Werner Koch * maperror.c: Removed. * util.h (out_of_core): New. 2006-09-04 Werner Koch * http.c (http_get_header): New. (capitalize_header_name, store_header): New. (parse_response): Store headers away. (send_request): Return GPG_ERR_NOT_FOUND if connect_server failed. * http.h: New flag HTTP_FLAG_NEED_HEADER. 2006-08-21 Werner Koch * Makefile.am (libcommon_a_SOURCES): Added keyserver.h * openpgpdefs.h: New. Stripped from ..g10/packet.h. 2006-08-16 Werner Koch * keyserver.h: Moved from ../include to here. * http.c: Include srv.h. * srv.c, srv.h: New. Taken from GnuPG 1.4 2006-08-14 Werner Koch * http.h (struct http_context_s): Moved to implementation. * http.c (http_open): Changed call to return a context. (http_open_document): Ditto. (http_get_read_ptr, http_get_read_ptr, http_get_status_code): New. (do_parse_uri): Replaced strlwr by straight code to ease standalone use of this file. (http_wait_response): Removed arg STATUS_CODE as it is available through an accessor function. Adjusted caller. (http_escape_string): New. * estream.c (es_read_line): Renamed to .. (doreadline): .. this. Changed all callers. (es_read_line): New. This is theusual limited getline variabnt as used at several places. Here taken and adjusted from xreadline.c (es_free): New. 2006-08-11 Werner Koch * http.c: Major internal changes to optionallly support GNUTLS and ESTREAM. (http_open): Move initialization of the stream ... (send_request): .. here. (http_register_tls_callback): New. * estream.c (es_writen): Try to seek only is a seek function has been registered. 2006-08-09 Werner Koch * http.c, http.h: New. Taken from gnupg 1.4.5, merged with changes done for the Dirmngr project (by g10 Code) and cleaned up some stuff. (make_header_line): New. Change all caller to make user of the new * Makefile.am (libcommon_a_SOURCES): Added http.c and http.h. 2006-05-23 Werner Koch * gettime.c (isotimestamp): New. * ttyio.c (tty_get_ttyname): Posixly correct usage of ctermid. * dns-cert.c: New. Taken from 1.4.3's util/cert.c. * dns-cert.h: New. 2006-05-22 Werner Koch * pka.c: New. Taked from 1.4.3. * pka.h: New. * Makefile.am: Added pka. 2006-05-19 Werner Koch * yesno.c (answer_is_yes_no_default, answer_is_yes_no_quit): Updated from 1.4.3. (answer_is_okay_cancel): new. From 1.4.3. * miscellaneous.c (match_multistr): New. Taken from 1.4.3. * ttyio.c (tty_enable_completion, tty_disable_completion): New dummy functions. * ttyio.h: Add prototypes and stubs. 2006-04-19 Werner Koch * iobuf.c (iobuf_get_fd): New. Taken from 1.4.3. (iobuf_is_pipe_filename): New. (pop_filter): Made static. (iobuf_skip_rest): New. Orginal patch by Florian Weimer. Added new argument PARTIAL. (block_filter): Remove the old gpg indeterminate length mode. (block_filter): Properly handle a partial body stream that ends with a 5-byte length that happens to be zero. (iobuf_set_block_mode, iobuf_in_block_mode): Removed as superfluous. (iobuf_get_filelength): New arg OVERFLOW. (iobuf_get_filelength) [W32]: Use GetFileSizeEx if available * miscellaneous.c (is_file_compressed): Take care of OVERFLOW. 2006-04-18 Werner Koch * homedir.c (w32_shgetfolderpath): New. Taken from gpg 1.4.3. (default_homedir): Use it. 2005-10-08 Marcus Brinkmann * signal.c (get_signal_name): Check value of HAVE_DECL_SYS_SIGLIST instead of just if it is defined. 2005-09-28 Marcus Brinkmann * Makefile.am (AM_CFLAGS): Add $(LIBASSUAN_CFLAGS). 2005-07-04 Marcus Brinkmann * simple-pwquery.h (simple_pwclear): New prototype. * simple-pwquery.c (simple_pwclear): New function. 2005-06-15 Werner Koch * miscellaneous.c (make_printable_string): Made P a void*. * sexputil.c (keygrip_from_canon_sexp, cmp_simple_canon_sexp): Fixed signed/unsigned pointer mismatch. (make_simple_sexp_from_hexstr): Ditto. This is all too ugly; I wonder why gcc-4's default is to warn about them and forcing us to use cast the warning away. * iobuf.c (block_filter): Ditto. (iobuf_flush): Ditto. (iobuf_read_line): Ditto. (iobuf_read): Make BUFFER a void *. (iobuf_write): Make BUFFER a const void *. * ttyio.c (tty_print_utf8_string2): Ditto. * estream.c (estream_cookie_mem): Make MEMORY unsigned char*. (es_write): Make BUFFER a void *. (es_writen): Ditto. (es_func_fd_read, es_func_fd_write, es_func_mem_read) (es_func_mem_write): Ditto. (es_read, es_readn): Ditto. (es_func_mem_write): Made MEMORY_NEW an unsigned char *. * estream.h (es_cookie_read_function_t) (es_cookie_write_function_t): Changed buffer arg to void*. 2005-06-03 Werner Koch * estream.c: Use HAVE_CONFIG_H and not USE_CONFIG_H! (es_func_fd_read, es_func_fd_write): Protect against EINTR. 2005-06-01 Werner Koch * Makefile.am (AM_CPPFLAGS): Added. * util.h: Add some includes for gnulib. (ttyname, isascii): Define them inline. * fseeko.c, ftello.c: Removed. * strsep.c, mkdtemp.c: Removed. * ttyname.c, isascii.c: Removed. 2005-05-31 Werner Koch * dynload.h: s/__inline__/inline/. 2005-05-13 Werner Koch * signal.c (got_fatal_signal): Print the signal number if we can't get a name for it. (get_signal_name): Return NULL if no name is available. Fixed conditional for sys_siglist to the correct one. 2005-04-17 Werner Koch * sexputil.c (cmp_simple_canon_sexp): New. (make_simple_sexp_from_hexstr): New. 2005-04-07 Werner Koch * sexputil.c: New. 2005-04-11 Marcus Brinkmann * simple-pwquery.c (simple_pwquery): Use spwq_secure_free. 2005-03-03 Werner Koch * Makefile.am (AM_CFLAGS): Added PTH_CFLAGS. Noted by Kazu Yamamoto. 2005-02-25 Werner Koch * xasprintf.c (xtryasprintf): New. 2005-01-26 Moritz Schulte * Makefile.am (libcommon_a_SOURCES): New source files: estream.c, estream.h. * estream.c, estream.h: New files. 2005-01-03 Werner Koch * asshelp.c (send_pinentry_environment): Fixed changed from 2004-12-18; cut+paste error for lc-messages. 2004-12-21 Werner Koch * simple-pwquery.c (agent_open) [W32]: Implement for W32. (readline) [W32]: Use recv instead of read. (writen) [W32]: Use send instead of write. (my_stpcpy): Define a stpcpy replacement so that this file continues to be self-contained. (agent_send_all_options) [W32]: Don't call ttyname. 2004-12-21 Marcus Brinkmann * simple-pwquery.h (simple_query): Add prototype. * simple-pwquery.c (simple_query): New function. 2004-12-21 Werner Koch * signal.c (got_fatal_signal, got_usr_signal) (got_fatal_signal) [DOSISH]: Don't build. * simple-gettext.c: Include sysutils.h * homedir.c: New. Use CSIDL_APPDATA for W32 as the default home directory. * Makefile.am (libcommon_a_SOURCES): Add it. (EXTRA_DIST): Removed mkerror and mkerrtok. 2004-12-20 Werner Koch * sysutils.h [W32]: Define sleep. * util.h: Add prototype for mkdtemp. * membuf.c (put_membuf): Wipe out buffer after a failed realloc. 2004-12-19 Werner Koch * maperror.c (map_assuan_err_with_source): Oops, args were swapped. 2004-12-18 Werner Koch * maperror.c (map_assuan_err): Renamed to .. (map_assuan_err_with_source): .. this and add arg SOURCE.c * asshelp.c (send_pinentry_environment, send_one_option): Add arg ERRSOURCE. 2004-12-15 Werner Koch * sysutils.h [W32]: Prototypes for registry functions. * w32reg.c: Include sysutils.h * simple-pwquery.c [W32]: Dummy code to allow a build. * exechelp.c [W32]: Implemented for W32 . * ttyname.c: New. * asshelp.c (send_one_option): New. (send_pinentry_environment): Cleaned up and made sure that empty values are not send. 2004-12-07 Werner Koch * asshelp.c (send_pinentry_environment) [W32]: Do not use ttyname. 2004-12-06 Werner Koch * exechelp.h, exechelp.c: New. Based on code from ../sm/import.c. 2004-12-03 Werner Koch * strsep.c: Fixed copyright comments. 2004-11-26 Werner Koch * simple-gettext.c: New taken from gnupg 1.3.x * simple-pwquery.c [_WIN32]: Include winsock2.h. (agent_open): Disable it until we have our AF_UNIX implementation ready. * fseeko.c, ftello.c: Include sys/types for the sake of W32. 2004-11-23 Werner Koch * b64enc.c: Include stdio.h and string.h 2004-08-18 Werner Koch * simple-pwquery.c (simple_pwquery): Handle gpg-error style return code for canceled. 2004-07-20 Werner Koch * maperror.c: Removed header ksba.h. Not required anymore. 2004-06-14 Werner Koch * xreadline.c: New. Based on the iobuf_read_line function. 2004-05-12 Werner Koch * util.h (xtrycalloc_secure,xtrymalloc_secure): New. 2004-05-11 Werner Koch * sysutils.c (disable_core_dumps): Only set the current limit. (enable_core_dumps): New. 2004-04-13 Werner Koch * simple-pwquery.c (copy_and_escape): Relaxed quoting. 2004-04-05 Werner Koch * errors.h (STATUS_NEWSIG): New. 2004-03-11 Werner Koch * dynload.h [__MINGW32__]: Define RTLD_LAZY. 2004-03-09 Werner Koch * maperror.c (map_assuan_err): Map the Locale_Problem item. 2004-03-03 Werner Koch * asshelp.c, asshelp.h: New. (send_pinentry_environment): New. Code taken from ../sm/call-agent.c. 2004-02-19 Werner Koch * simple-pwquery.c (agent_open): Don't mangle INFOSTR. 2004-02-17 Werner Koch * simple-pwquery.c (agent_open): Ignore an empty GPG_AGENT_INFO. * errors.h: Added STATUS_IMPORT_OK. 2004-02-10 Werner Koch * b64enc.c: New. Based on code from ../sm/base64.c. 2004-01-30 Marcus Brinkmann * Makefile.am (libcommon_a_SOURCES): Add xasprintf.c. * miscellaneous.c (xasprintf): Moved to ... * xasprintf (xasprintf): ... here. New file. This allows to use xasprintf without sucking in gpg-error. 2004-01-27 Werner Koch * sexp-parse.h: New; moved from../agent. * util.h (xtoi_4): New. 2003-12-23 Werner Koch * maperror.c (map_assuan_err): Prepared for a new error code. 2003-12-17 Werner Koch * gettime.c (asctimestamp): Add a note on a non-avoidable gcc warning. * util.h [!HAVE_VASPRINTF]: Add printf format attribute to the replacement function. * miscellaneous.c (xasprintf): New. 2003-11-14 Werner Koch * mkdtemp.c (mkdtemp): Use gcry_create_nonce. * cryptmiss.c: Removed. 2003-11-13 Werner Koch * util.h (vasprintf): Also fixed the prototype. * vasprintf.c (vasprintf): ARGS should not be a pointer. Fixed segv on Solaris. Reported by Andrew J. Schorr. 2003-11-12 Werner Koch * maperror.c (map_ksba_err, map_gcry_err, map_kbx_err): Removed. 2003-10-31 Werner Koch * util.h (gnupg_isotime_t): New. (gnupg_copy_time): New. * gettime.c (gnupg_get_isotime): New. 2003-09-23 Werner Koch * iobuf.c (check_special_filename): Replaced is isdigit by digitp to avoid passing negative values and potential locale problems. Problem noted by Christian Biere. * util.h (ascii_isspace): New. 2003-09-18 Werner Koch * ttyio.c (tty_fprintf): New. (tty_print_string, tty_print_utf8_string2) (tty_print_utf8_string): Made P argument const byte*. 2003-08-20 Marcus Brinkmann * maperror.c (map_ksba_err): Map -1. Use gpg_err_make to set the error source. 2003-08-14 Timo Schulz * dynload.h. New. W32 wrapper around the dynload mechanism. 2003-07-15 Werner Koch * simple-pwquery.c, simple-pwquery.h: New; moved from ../agent. * Makefile.am (libsimple_pwquery_a_LIBADD): New. 2003-06-25 Werner Koch * maperror.c (map_to_assuan_status): Directly map 0 to 0. 2003-06-17 Werner Koch * gettime.c (scan_isodatestr,add_days_to_timestamp,strtimevalue) (strtimestamp,asctimestamp): New. Code taken from gnupg 1.3.2 mischelp.c. * yesno.c: New. Code taken from gnupg 1.3.2 mischelp.c * miscellaneous.c: New. * util.h: Include utf8conf.h 2003-06-16 Werner Koch * gettime.c (make_timestamp): New. * ttyio.c: New. Taken from gnupg 1.2. * ttyio.h: Move from ../include. 2003-06-13 Werner Koch * util.h (seterr): Removed macro. (xmalloc_secure,xcalloc_secure): New. 2003-06-11 Werner Koch * iobuf.c (iobuf_writebyte,iobuf_write): Return error code from iobuf_flush. (iobuf_writestr): Ditto. 2003-06-10 Werner Koch * iobuf.c, iobuf.h: New. Taken from current gnupg 1.3 CVS. Run indent on it and adjusted error handling to libgpg-error style. Replaced IOBUF by iobuf_t. Renamed malloc functions. 2003-06-04 Werner Koch * errors.h: Removed all error codes. We keep the status codes for now. * Makefile.am: Do not create errors.c anymore; remove it from the sources. * maperror.c: Don't include error.h. Change all error codes to libgpg-error style. (map_assuan_err): Changed to new Assuan error code convention. (map_to_assuan_status): Likewise. (map_gcry_err,map_kbx_err): Not needed. For now dummy functions. * membuf.c, membuf.h: New. Code taken from ../sm/call-agent.h. * Makefile.am: Added above. 2003-04-29 Werner Koch * util.h (fopencokokie): Removed prototype and struct. * fopencookie.c: Removed. * maperror.c: Use system assuan.h 2002-10-31 Neal H. Walfield * isascii.c: New file. * putc_unlocked.c: Likewise. 2002-10-28 Neal H. Walfield * signal.c (caught_fatal_sig): Remove superfluous zero initializer. (caught_sigusr1): Likewise. 2002-09-04 Neal H. Walfield * vasprintf.c (vasprintf) [va_copy]: Use va_copy. [!va_copy && __va_copy]: Use __va_copy. [!va_copy && !__va_copy]: Only now fall back to using memcpy. 2002-08-21 Werner Koch * errors.h: Added STATUS_IMPORT_PROBLEM. 2002-08-20 Werner Koch * vasprintf.c: Hack to handle NULL for %s. 2002-08-09 Werner Koch * signal.c: New. Taken from GnuPG 1.1.91. 2002-07-23 Werner Koch * util.h (_IO_cookie_io_functions_t): Fixed typo. Noted by Richard Lefebvre. 2002-07-22 Werner Koch * fseeko.c, ftello.c: New. 2002-06-28 Werner Koch * maperror.c (map_to_assuan_status): Map more errorcodes to Bad Certificate. 2002-06-26 Werner Koch * maperror.c (map_to_assuan_status): Map EOF to No_Data_Available. 2002-06-10 Werner Koch * errors.h (gnupg_error_token): Add new prototype. (STATUS_ERROR): New. * mkerrtok: New. * Makefile.am: Use it to create the new error token function. 2002-06-04 Werner Koch * maperror.c (map_to_assuan_status): Map Bad_CA_Certificate. 2002-05-23 Werner Koch * no-pth.c, Makefile.am: Removed. 2002-05-22 Werner Koch * mkdtemp.c: Replaced byte by unsigned char because it is no longer defined in gcrypt.h. 2002-05-21 Werner Koch * maperror.c (map_gcry_err): Add libgcrypt's new S-expression errors. (map_ksba_err): Add a few mappings. 2002-05-14 Werner Koch * gettime.c: New. 2002-05-03 Werner Koch * errors.h: Added STARUS_EXPSIG and STATUS_EXPKEYSIG. 2002-04-15 Werner Koch * cryptmiss.c: New. 2002-02-14 Werner Koch * maperror.c: Add more assuan<->gnupg mappings. 2002-02-12 Werner Koch * fopencookie.c: Dummy function. * vasprintf.c: New. Taken from binutils-2.9.1 and dropped all non ANSI-C stuff. Merged with asprintf version. * no-pth.c: New. 2002-01-23 Werner Koch * mkdtemp.c: Copied from gnupg-1.0.6c and changed to use libgcrypt. 2002-01-19 Werner Koch * sysutils.c: New. This is the misc.c file from gnupg 1.0.6 with the OpenPGP stuff removed. * sysutils.h: New. 2002-01-15 Werner Koch * maperror.c: Add mapping for Not_Trusted. 2002-01-11 Werner Koch * maperror.c (map_assuan_err): Codes for CRL 2002-01-08 Werner Koch * util.h (spacep): New. 2002-01-02 Werner Koch * maperror.c (map_to_assuan_status): New. Merged from ../agent and ../sm. 2001-12-20 Werner Koch * maperror.c (map_gcry_err): Add some mappings. 2001-12-18 Werner Koch * Makefile.am (AM_CPPFLAGS): Include flags for gcrypt and ksba 2001-12-14 Werner Koch * util.h (digitp, hexdigitp): New ctype like macros. (atoi_1,atoi_2,atoi_4,xtoi_1,xtoi_2): New. Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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/common/asshelp.c b/common/asshelp.c index bd7aa8de9..882c15479 100644 --- a/common/asshelp.c +++ b/common/asshelp.c @@ -1,505 +1,505 @@ /* asshelp.c - Helper functions for Assuan * Copyright (C) 2002, 2004, 2007, 2009, 2010 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 3 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, see . */ #include #include #include #include #include #include #ifdef HAVE_LOCALE_H #include #endif #define JNLIB_NEED_LOG_LOGV #include "i18n.h" #include "util.h" #include "exechelp.h" #include "sysutils.h" #include "status.h" #include "asshelp.h" /* The type we use for lock_agent_spawning. */ #ifdef HAVE_W32_SYSTEM # define lock_agent_t HANDLE #else # define lock_agent_t dotlock_t #endif /* A bitfield that specifies the assuan categories to log. This is identical to the default log handler of libassuan. We need to do it ourselves because we use a custom log handler and want to use the same assuan variables to select the categories to log. */ static int log_cats; #define TEST_LOG_CAT(x) (!! (log_cats & (1 << (x - 1)))) static int my_libassuan_log_handler (assuan_context_t ctx, void *hook, unsigned int cat, const char *msg) { unsigned int dbgval; (void)ctx; if (! TEST_LOG_CAT (cat)) return 0; dbgval = hook? *(unsigned int*)hook : 0; if (!(dbgval & 1024)) return 0; /* Assuan debugging is not enabled. */ if (msg) log_string (JNLIB_LOG_DEBUG, msg); return 1; } /* Setup libassuan to use our own logging functions. Should be used early at startup. */ void setup_libassuan_logging (unsigned int *debug_var_address) { char *flagstr; flagstr = getenv ("ASSUAN_DEBUG"); if (flagstr) log_cats = atoi (flagstr); else /* Default to log the control channel. */ log_cats = (1 << (ASSUAN_LOG_CONTROL - 1)); assuan_set_log_cb (my_libassuan_log_handler, debug_var_address); } static gpg_error_t send_one_option (assuan_context_t ctx, gpg_err_source_t errsource, const char *name, const char *value, int use_putenv) { gpg_error_t err; char *optstr; (void)errsource; if (!value || !*value) err = 0; /* Avoid sending empty strings. */ else if (asprintf (&optstr, "OPTION %s%s=%s", use_putenv? "putenv=":"", name, value) < 0) err = gpg_error_from_syserror (); else { err = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); xfree (optstr); } return err; } /* Send the assuan commands pertaining to the pinentry environment. The OPT_* arguments are optional and may be used to override the defaults taken from the current locale. */ gpg_error_t send_pinentry_environment (assuan_context_t ctx, gpg_err_source_t errsource, const char *opt_lc_ctype, const char *opt_lc_messages, session_env_t session_env) { gpg_error_t err = 0; #if defined(HAVE_SETLOCALE) char *old_lc = NULL; #endif char *dft_lc = NULL; const char *dft_ttyname; int iterator; const char *name, *assname, *value; int is_default; iterator = 0; while ((name = session_env_list_stdenvnames (&iterator, &assname))) { value = session_env_getenv_or_default (session_env, name, NULL); if (!value) continue; if (assname) err = send_one_option (ctx, errsource, assname, value, 0); else { err = send_one_option (ctx, errsource, name, value, 1); if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION) err = 0; /* Server too old; can't pass the new envvars. */ } if (err) return err; } dft_ttyname = session_env_getenv_or_default (session_env, "GPG_TTY", &is_default); if (dft_ttyname && !is_default) dft_ttyname = NULL; /* We need the default value. */ /* Send the value for LC_CTYPE. */ #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE) old_lc = setlocale (LC_CTYPE, NULL); if (old_lc) { old_lc = xtrystrdup (old_lc); if (!old_lc) return gpg_error_from_syserror (); } dft_lc = setlocale (LC_CTYPE, ""); #endif if (opt_lc_ctype || (dft_ttyname && dft_lc)) { err = send_one_option (ctx, errsource, "lc-ctype", opt_lc_ctype ? opt_lc_ctype : dft_lc, 0); } #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE) if (old_lc) { setlocale (LC_CTYPE, old_lc); xfree (old_lc); } #endif if (err) return err; /* Send the value for LC_MESSAGES. */ #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES) old_lc = setlocale (LC_MESSAGES, NULL); if (old_lc) { old_lc = xtrystrdup (old_lc); if (!old_lc) return gpg_error_from_syserror (); } dft_lc = setlocale (LC_MESSAGES, ""); #endif if (opt_lc_messages || (dft_ttyname && dft_lc)) { err = send_one_option (ctx, errsource, "lc-messages", opt_lc_messages ? opt_lc_messages : dft_lc, 0); } #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES) if (old_lc) { setlocale (LC_MESSAGES, old_lc); xfree (old_lc); } #endif if (err) return err; return 0; } /* Lock the agent spawning process. The caller needs to provide the address of a variable to store the lock information. */ static gpg_error_t lock_agent_spawning (lock_agent_t *lock, const char *homedir) { #ifdef HAVE_W32_SYSTEM int waitrc; (void)homedir; /* Not required. */ - *lock = CreateMutex (NULL, FALSE, "GnuPG_spawn_agent_sentinel"); + *lock = CreateMutexW (NULL, FALSE, L"GnuPG_spawn_agent_sentinel"); if (!*lock) { log_error ("failed to create the spawn_agent mutex: %s\n", w32_strerror (-1)); return gpg_error (GPG_ERR_GENERAL); } waitrc = WaitForSingleObject (*lock, 5000); if (waitrc == WAIT_OBJECT_0) return 0; if (waitrc == WAIT_TIMEOUT) log_info ("error waiting for the spawn_agent mutex: timeout\n"); else log_info ("error waiting for the spawn_agent mutex: " "(code=%d) %s\n", waitrc, w32_strerror (-1)); return gpg_error (GPG_ERR_GENERAL); #else /*!HAVE_W32_SYSTEM*/ char *fname; *lock = NULL; fname = make_filename (homedir, "gnupg_spawn_agent_sentinel", NULL); if (!fname) return gpg_error_from_syserror (); *lock = create_dotlock (fname); xfree (fname); if (!*lock) return gpg_error_from_syserror (); /* FIXME: We should use a timeout of 5000 here - however make_dotlock does not yet support values other than -1 and 0. */ if (make_dotlock (*lock, -1)) return gpg_error_from_syserror (); return 0; #endif /*!HAVE_W32_SYSTEM*/ } /* Unlock the spawning process. */ static void unlock_agent_spawning (lock_agent_t *lock) { if (*lock) { #ifdef HAVE_W32_SYSTEM if (!ReleaseMutex (*lock)) log_error ("failed to release the spawn_agent mutex: %s\n", w32_strerror (-1)); CloseHandle (*lock); #else /*!HAVE_W32_SYSTEM*/ destroy_dotlock (*lock); #endif /*!HAVE_W32_SYSTEM*/ *lock = NULL; } } /* Try to connect to the agent via socket or fork it off and work by pipes. Handle the server's initial greeting. Returns a new assuan context at R_CTX or an error code. */ gpg_error_t start_new_gpg_agent (assuan_context_t *r_ctx, gpg_err_source_t errsource, const char *homedir, const char *agent_program, const char *opt_lc_ctype, const char *opt_lc_messages, session_env_t session_env, int verbose, int debug, gpg_error_t (*status_cb)(ctrl_t, int, ...), ctrl_t status_cb_arg) { /* If we ever failed to connect via a socket we will force the use of the pipe based server for the lifetime of the process. */ static int force_pipe_server = 0; gpg_error_t err = 0; char *infostr, *p; assuan_context_t ctx; *r_ctx = NULL; err = assuan_new (&ctx); if (err) { log_error ("error allocating assuan context: %s\n", gpg_strerror (err)); return err; } restart: infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO"); if (!infostr || !*infostr) { char *sockname; const char *argv[3]; pid_t pid; int excode; /* First check whether we can connect at the standard socket. */ sockname = make_filename (homedir, "S.gpg-agent", NULL); err = assuan_socket_connect (ctx, sockname, 0, 0); if (err) { /* With no success start a new server. */ if (verbose) log_info (_("no running gpg-agent - starting one\n")); if (status_cb) status_cb (status_cb_arg, STATUS_PROGRESS, "starting_agent ? 0 0", NULL); if (fflush (NULL)) { gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); log_error ("error flushing pending output: %s\n", strerror (errno)); xfree (sockname); assuan_release (ctx); return tmperr; } if (!agent_program || !*agent_program) agent_program = gnupg_module_name (GNUPG_MODULE_NAME_AGENT); argv[0] = "--use-standard-socket-p"; argv[1] = NULL; err = gnupg_spawn_process_fd (agent_program, argv, -1, -1, -1, &pid); if (err) log_debug ("starting `%s' for testing failed: %s\n", agent_program, gpg_strerror (err)); - else if ((err = gnupg_wait_process (agent_program, pid, 0, &excode))) + else if ((err = gnupg_wait_process (agent_program, pid, 1, &excode))) { if (excode == -1) - log_debug ("running `%s' for testing failed: %s\n", + log_debug ("running `%s' for testing failed (wait): %s\n", agent_program, gpg_strerror (err)); } gnupg_release_process (pid); if (!err && !excode) { /* If the agent has been configured for use with a standard socket, an environment variable is not required and thus we we can savely start the agent here. */ lock_agent_t lock; argv[0] = "--daemon"; argv[1] = "--use-standard-socket"; argv[2] = NULL; if (!(err = lock_agent_spawning (&lock, homedir)) && assuan_socket_connect (ctx, sockname, 0, 0)) { err = gnupg_spawn_process_detached (agent_program, argv,NULL); if (err) log_error ("failed to start agent `%s': %s\n", agent_program, gpg_strerror (err)); else { int i; if (verbose) log_info (_("waiting %d seconds for the agent " "to come up\n"), 5); for (i=0; i < 5; i++) { gnupg_sleep (1); err = assuan_socket_connect (ctx, sockname, 0, 0); if (!err) break; } } } unlock_agent_spawning (&lock); } else { /* If using the standard socket is not the default we start the agent as a pipe server which gives us most of the required features except for passphrase caching etc. */ const char *pgmname; int no_close_list[3]; int i; if ( !(pgmname = strrchr (agent_program, '/'))) pgmname = agent_program; else pgmname++; argv[0] = pgmname; argv[1] = "--server"; argv[2] = NULL; i=0; if (log_get_fd () != -1) no_close_list[i++] = assuan_fd_from_posix_fd (log_get_fd ()); no_close_list[i++] = assuan_fd_from_posix_fd (fileno (stderr)); no_close_list[i] = -1; /* Connect to the agent and perform initial handshaking. */ err = assuan_pipe_connect (ctx, agent_program, argv, no_close_list, NULL, NULL, 0); } } xfree (sockname); } else { int prot; int pid; infostr = xstrdup (infostr); if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr) { log_error (_("malformed GPG_AGENT_INFO environment variable\n")); xfree (infostr); force_pipe_server = 1; goto restart; } *p++ = 0; pid = atoi (p); while (*p && *p != PATHSEP_C) 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; goto restart; } err = assuan_socket_connect (ctx, infostr, pid, 0); xfree (infostr); if (gpg_err_code (err) == GPG_ERR_ASS_CONNECT_FAILED) { log_info (_("can't connect to the agent - trying fall back\n")); force_pipe_server = 1; goto restart; } } if (err) { log_error ("can't connect to the agent: %s\n", gpg_strerror (err)); assuan_release (ctx); return gpg_error (GPG_ERR_NO_AGENT); } if (debug) log_debug ("connection to agent established\n"); err = assuan_transact (ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL); if (!err) err = send_pinentry_environment (ctx, errsource, opt_lc_ctype, opt_lc_messages, session_env); if (err) { assuan_release (ctx); return err; } *r_ctx = ctx; return 0; } diff --git a/g13/be-encfs.c b/g13/be-encfs.c index fb695e1be..dd8e53657 100644 --- a/g13/be-encfs.c +++ b/g13/be-encfs.c @@ -1,470 +1,470 @@ /* be-encfs.c - The EncFS based backend * Copyright (C) 2009 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 3 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, see . */ #include #include #include #include #include #include #include #include "g13.h" #include "i18n.h" #include "keyblob.h" #include "be-encfs.h" #include "runner.h" #include "../common/exechelp.h" /* Command values used to run the encfs tool. */ enum encfs_cmds { ENCFS_CMD_CREATE, ENCFS_CMD_MOUNT, ENCFS_CMD_UMOUNT }; /* An object to keep the private state of the encfs tool. It is released by encfs_handler_cleanup. */ struct encfs_parm_s { enum encfs_cmds cmd; /* The current command. */ tupledesc_t tuples; /* NULL or the tuples object. */ char *mountpoint; /* The mountpoint. */ }; typedef struct encfs_parm_s *encfs_parm_t; static gpg_error_t send_cmd_bin (runner_t runner, const void *data, size_t datalen) { return runner_send_line (runner, data, datalen); } static gpg_error_t send_cmd (runner_t runner, const char *string) { log_debug ("sending command -->%s<--\n", string); return send_cmd_bin (runner, string, strlen (string)); } static void run_umount_helper (const char *mountpoint) { gpg_error_t err; const char pgmname[] = FUSERMOUNT; const char *args[3]; args[0] = "-u"; args[1] = mountpoint; args[2] = NULL; err = gnupg_spawn_process_detached (pgmname, args, NULL); if (err) log_error ("failed to run `%s': %s\n", pgmname, gpg_strerror (err)); } /* Handle one line of the encfs tool's output. This function is allowed to modify the content of BUFFER. */ static gpg_error_t handle_status_line (runner_t runner, const char *line, enum encfs_cmds cmd, tupledesc_t tuples) { gpg_error_t err; /* Check that encfs understands our new options. */ if (!strncmp (line, "$STATUS$", 8)) { for (line +=8; *line && spacep (line); line++) ; log_info ("got status `%s'\n", line); if (!strcmp (line, "fuse_main_start")) { /* Send a special error code back to let the caller know that everything has been setup by encfs. */ err = gpg_error (GPG_ERR_UNFINISHED); } else err = 0; } else if (!strncmp (line, "$PROMPT$", 8)) { for (line +=8; *line && spacep (line); line++) ; log_info ("got prompt `%s'\n", line); if (!strcmp (line, "create_root_dir")) err = send_cmd (runner, cmd == ENCFS_CMD_CREATE? "y":"n"); else if (!strcmp (line, "create_mount_point")) err = send_cmd (runner, "y"); else if (!strcmp (line, "passwd") || !strcmp (line, "new_passwd")) { if (tuples) { size_t n; const void *value; value = find_tuple (tuples, KEYBLOB_TAG_ENCKEY, &n); if (!value) err = gpg_error (GPG_ERR_INV_SESSION_KEY); else if ((err = send_cmd_bin (runner, value, n))) { if (gpg_err_code (err) == GPG_ERR_BUG && gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT) err = gpg_error (GPG_ERR_INV_SESSION_KEY); } } else err = gpg_error (GPG_ERR_NO_DATA); } else err = send_cmd (runner, ""); /* Default to send an empty line. */ } else if (strstr (line, "encfs: unrecognized option '")) err = gpg_error (GPG_ERR_INV_ENGINE); else err = 0; return err; } /* The main processing function as used by the runner. */ static gpg_error_t encfs_handler (void *opaque, runner_t runner, const char *status_line) { encfs_parm_t parm = opaque; gpg_error_t err; if (!parm || !runner) return gpg_error (GPG_ERR_BUG); if (!status_line) { /* Runner requested internal flushing - nothing to do here. */ return 0; } err = handle_status_line (runner, status_line, parm->cmd, parm->tuples); if (gpg_err_code (err) == GPG_ERR_UNFINISHED && gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT) { err = 0; /* No more need for the tuples. */ destroy_tupledesc (parm->tuples); parm->tuples = NULL; if (parm->cmd == ENCFS_CMD_CREATE) { /* The encfs tool keeps on running after creation of the container. We don't want that and thus need to stop the encfs process. */ run_umount_helper (parm->mountpoint); /* In case the umount helper does not work we try to kill the engine. FIXME: We should figure out how to make fusermount work. */ runner_cancel (runner); } } return err; } /* Called by the runner to cleanup the private data. */ static void encfs_handler_cleanup (void *opaque) { encfs_parm_t parm = opaque; if (!parm) return; destroy_tupledesc (parm->tuples); xfree (parm->mountpoint); xfree (parm); } /* Run the encfs tool. */ static gpg_error_t run_encfs_tool (ctrl_t ctrl, enum encfs_cmds cmd, const char *rawdir, const char *mountpoint, tupledesc_t tuples, unsigned int *r_id) { gpg_error_t err; encfs_parm_t parm; runner_t runner = NULL; int outbound[2] = { -1, -1 }; int inbound[2] = { -1, -1 }; const char *pgmname; const char *argv[10]; pid_t pid = (pid_t)(-1); int idx; (void)ctrl; parm = xtrycalloc (1, sizeof *parm); if (!parm) { err = gpg_error_from_syserror (); goto leave; } parm->cmd = cmd; parm->tuples = ref_tupledesc (tuples); parm->mountpoint = xtrystrdup (mountpoint); if (!parm->mountpoint) { err = gpg_error_from_syserror (); goto leave; } err = runner_new (&runner, "encfs"); if (err) goto leave; err = gnupg_create_inbound_pipe (inbound); if (!err) err = gnupg_create_outbound_pipe (outbound); if (err) { log_error (_("error creating a pipe: %s\n"), gpg_strerror (err)); goto leave; } pgmname = ENCFS; idx = 0; argv[idx++] = "-f"; if (opt.verbose) argv[idx++] = "-v"; argv[idx++] = "--stdinpass"; argv[idx++] = "--annotate"; argv[idx++] = rawdir; argv[idx++] = mountpoint; argv[idx++] = NULL; assert (idx <= DIM (argv)); err = gnupg_spawn_process_fd (pgmname, argv, outbound[0], -1, inbound[1], &pid); if (err) { log_error ("error spawning `%s': %s\n", pgmname, gpg_strerror (err)); goto leave; } close (outbound[0]); outbound[0] = -1; close ( inbound[1]); inbound[1] = -1; runner_set_fds (runner, inbound[0], outbound[1]); inbound[0] = -1; /* Now owned by RUNNER. */ outbound[1] = -1; /* Now owned by RUNNER. */ runner_set_handler (runner, encfs_handler, encfs_handler_cleanup, parm); parm = NULL; /* Now owned by RUNNER. */ runner_set_pid (runner, pid); pid = (pid_t)(-1); /* The process is now owned by RUNNER. */ err = runner_spawn (runner); if (err) goto leave; *r_id = runner_get_rid (runner); log_info ("running `%s' in the background\n", pgmname); leave: if (inbound[0] != -1) close (inbound[0]); if (inbound[1] != -1) close (inbound[1]); if (outbound[0] != -1) close (outbound[0]); if (outbound[1] != -1) close (outbound[1]); if (pid != (pid_t)(-1)) { - gnupg_wait_process (pgmname, pid, 0, NULL); + gnupg_wait_process (pgmname, pid, 1, NULL); gnupg_release_process (pid); } runner_release (runner); encfs_handler_cleanup (parm); return err; } /* See be_get_detached_name for a description. Note that the dispatcher code makes sure that NULL is stored at R_NAME before calling us. */ gpg_error_t be_encfs_get_detached_name (const char *fname, char **r_name, int *r_isdir) { char *result; if (!fname || !*fname) return gpg_error (GPG_ERR_INV_ARG); result = strconcat (fname, ".d", NULL); if (!result) return gpg_error_from_syserror (); *r_name = result; *r_isdir = 1; return 0; } /* Create a new session key and append it as a tuple to the memory buffer MB. The EncFS daemon takes a passphrase from stdin and internally mangles it by means of some KDF from OpenSSL. We want to store a binary key but we need to make sure that certain characters are not used because the EncFS utility reads it from stdin and obviously acts on some of the characters. This we replace CR (in case of an MSDOS version of EncFS), LF (the delimiter used by EncFS) and Nul (because it is unlikely to work). We use 32 bytes (256 bit) because that is sufficient for the largest cipher (AES-256) and in addition gives enough margin for a possible entropy degradation by the KDF. */ gpg_error_t be_encfs_create_new_keys (membuf_t *mb) { char *buffer; int i, j; /* Allocate a buffer of 32 bytes plus 8 spare bytes we may need to replace the unwanted values. */ buffer = xtrymalloc_secure (32+8); if (!buffer) return gpg_error_from_syserror (); /* Randomize the buffer. STRONG random should be enough as it is a good compromise between security and performance. The anticipated usage of this tool is the quite often creation of new containers and thus this should not deplete the system's entropy tool too much. */ gcry_randomize (buffer, 32+8, GCRY_STRONG_RANDOM); for (i=j=0; i < 32; i++) { if (buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == 0 ) { /* Replace. */ if (j == 8) { /* Need to get more random. */ gcry_randomize (buffer+32, 8, GCRY_STRONG_RANDOM); j = 0; } buffer[i] = buffer[32+j]; j++; } } /* Store the key. */ append_tuple (mb, KEYBLOB_TAG_ENCKEY, buffer, 32); /* Free the temporary buffer. */ wipememory (buffer, 32+8); /* A failsafe extra wiping. */ xfree (buffer); return 0; } /* Create the container described by the filename FNAME and the keyblob information in TUPLES. */ gpg_error_t be_encfs_create_container (ctrl_t ctrl, const char *fname, tupledesc_t tuples, unsigned int *r_id) { gpg_error_t err; int dummy; char *containername = NULL; char *mountpoint = NULL; err = be_encfs_get_detached_name (fname, &containername, &dummy); if (err) goto leave; mountpoint = xtrystrdup ("/tmp/.#g13_XXXXXX"); if (!mountpoint) { err = gpg_error_from_syserror (); goto leave; } if (!mkdtemp (mountpoint)) { err = gpg_error_from_syserror (); log_error (_("can't create directory `%s': %s\n"), "/tmp/.#g13_XXXXXX", gpg_strerror (err)); goto leave; } err = run_encfs_tool (ctrl, ENCFS_CMD_CREATE, containername, mountpoint, tuples, r_id); /* In any case remove the temporary mount point. */ if (rmdir (mountpoint)) log_error ("error removing temporary mount point `%s': %s\n", mountpoint, gpg_strerror (gpg_error_from_syserror ())); leave: xfree (containername); xfree (mountpoint); return err; } /* Mount the container described by the filename FNAME and the keyblob information in TUPLES. On success the runner id is stored at R_ID. */ gpg_error_t be_encfs_mount_container (ctrl_t ctrl, const char *fname, const char *mountpoint, tupledesc_t tuples, unsigned int *r_id) { gpg_error_t err; int dummy; char *containername = NULL; if (!mountpoint) { log_error ("the encfs backend requires an explicit mountpoint\n"); err = gpg_error (GPG_ERR_NOT_SUPPORTED); goto leave; } err = be_encfs_get_detached_name (fname, &containername, &dummy); if (err) goto leave; err = run_encfs_tool (ctrl, ENCFS_CMD_MOUNT, containername, mountpoint, tuples, r_id); leave: xfree (containername); return err; } diff --git a/g13/runner.c b/g13/runner.c index 3ffe523ca..720cd9e58 100644 --- a/g13/runner.c +++ b/g13/runner.c @@ -1,538 +1,538 @@ /* runner.c - Run and watch the backend engines * Copyright (C) 2009 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 3 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, see . */ #include #include #include #include #include #include #include #include #include "g13.h" #include "i18n.h" #include "keyblob.h" #include "runner.h" #include "../common/exechelp.h" #include "mountinfo.h" /* The runner object. */ struct runner_s { char *name; /* The name of this runner. */ unsigned int identifier; /* The runner identifier. */ int spawned; /* True if runner_spawn has been called. */ pth_t threadid; /* The TID of the runner thread. */ runner_t next_running; /* Builds a list of all running threads. */ int canceled; /* Set if a cancel has already been send once. */ int cancel_flag; /* If set the thread should terminate itself. */ /* We use a reference counter to know when it is safe to remove the object. Lacking an explicit ref function this counter will take only these two values: 1 = Thread not running or only the thread is still running. 2 = Thread is running and someone is holding a reference. */ int refcount; pid_t pid; /* PID of the backend's process (the engine). */ int in_fd; /* File descriptors to read from the engine. */ int out_fd; /* File descriptors to write to the engine. */ engine_handler_fnc_t handler; /* The handler functions. */ engine_handler_cleanup_fnc_t handler_cleanup; void *handler_data; /* Private data of HANDLER and HANDLER_CLEANUP. */ /* Instead of IN_FD we use an estream. Note that the runner thread may close the stream and set status_fp to NULL at any time. Thus it won't be a good idea to use it while the runner thread is running. */ estream_t status_fp; }; /* The head of the list of all running threads. */ static runner_t running_threads; /* Write NBYTES of BUF to file descriptor FD. */ static int writen (int fd, const void *buf, size_t nbytes) { size_t nleft = nbytes; int nwritten; while (nleft > 0) { nwritten = pth_write (fd, buf, nleft); if (nwritten < 0) { if (errno == EINTR) nwritten = 0; else return -1; } nleft -= nwritten; buf = (const char*)buf + nwritten; } return 0; } static int check_already_spawned (runner_t runner, const char *funcname) { if (runner->spawned) { log_error ("BUG: runner already spawned - ignoring call to %s\n", funcname); return 1; } else return 0; } /* Return the number of active threads. */ unsigned int runner_get_threads (void) { unsigned int n = 0; runner_t r; for (r = running_threads; r; r = r->next_running) n++; return n; } /* The public release function. */ void runner_release (runner_t runner) { gpg_error_t err; if (!runner) return; if (!--runner->refcount) return; err = mountinfo_del_mount (NULL, NULL, runner->identifier); if (err) log_error ("failed to remove mount with rid %u from mtab: %s\n", runner->identifier, gpg_strerror (err)); es_fclose (runner->status_fp); if (runner->in_fd != -1) close (runner->in_fd); if (runner->out_fd != -1) close (runner->out_fd); /* Fixme: close the process. */ /* Tell the engine to release its data. */ if (runner->handler_cleanup) runner->handler_cleanup (runner->handler_data); if (runner->pid != (pid_t)(-1)) { /* The process has not been cleaned up - do it now. */ gnupg_kill_process (runner->pid); /* (Actually we should use the program name and not the arbitrary NAME of the runner object. However it does not matter because that information is only used for diagnostics.) */ - gnupg_wait_process (runner->name, runner->pid, 0, NULL); + gnupg_wait_process (runner->name, runner->pid, 1, NULL); gnupg_release_process (runner->pid); } xfree (runner->name); xfree (runner); } /* Create a new runner context. On success a new runner object is stored at R_RUNNER. On failure NULL is stored at this address and an error code returned. */ gpg_error_t runner_new (runner_t *r_runner, const char *name) { static unsigned int namecounter; /* Global name counter. */ char *namebuffer; runner_t runner, r; *r_runner = NULL; runner = xtrycalloc (1, sizeof *runner); if (!runner) return gpg_error_from_syserror (); /* Bump up the namecounter. In case we ever had an overflow we check that this number is currently not in use. The algorithm is a bit lame but should be sufficient because such an wrap is not very likely: Assuming that we do a mount 10 times a second, then we would overwrap on a 32 bit system after 13 years. */ do { namecounter++; for (r = running_threads; r; r = r->next_running) if (r->identifier == namecounter) break; } while (r); runner->identifier = namecounter; runner->name = namebuffer = xtryasprintf ("%s-%d", name, namecounter); if (!runner->name) { xfree (runner); return gpg_error_from_syserror (); } runner->refcount = 1; runner->pid = (pid_t)(-1); runner->in_fd = -1; runner->out_fd = -1; *r_runner = runner; return 0; } /* Return the identifier of RUNNER. */ unsigned int runner_get_rid (runner_t runner) { return runner->identifier; } /* Find a runner by its rid. Returns the runner object. The caller must release the runner object. */ runner_t runner_find_by_rid (unsigned int rid) { runner_t r; for (r = running_threads; r; r = r->next_running) if (r->identifier == rid) { r->refcount++; return r; } return NULL; } /* A runner usually maintains two file descriptors to control the backend engine. This function is used to set these file descriptors. The function takes ownership of these file descriptors. IN_FD will be used to read from engine and OUT_FD to send data to the engine. */ void runner_set_fds (runner_t runner, int in_fd, int out_fd) { if (check_already_spawned (runner, "runner_set_fds")) return; if (runner->in_fd != -1) close (runner->in_fd); if (runner->out_fd != -1) close (runner->out_fd); runner->in_fd = in_fd; runner->out_fd = out_fd; } /* Set the PID of the backend engine. After this call the engine is owned by the runner object. */ void runner_set_pid (runner_t runner, pid_t pid) { if (check_already_spawned (runner, "runner_set_fds")) return; runner->pid = pid; } /* Register the engine handler fucntions HANDLER and HANDLER_CLEANUP and its private HANDLER_DATA with RUNNER. */ void runner_set_handler (runner_t runner, engine_handler_fnc_t handler, engine_handler_cleanup_fnc_t handler_cleanup, void *handler_data) { if (check_already_spawned (runner, "runner_set_handler")) return; runner->handler = handler; runner->handler_cleanup = handler_cleanup; runner->handler_data = handler_data; } /* The thread spawned by runner_spawn. */ static void * runner_thread (void *arg) { runner_t runner = arg; gpg_error_t err = 0; log_debug ("starting runner thread\n"); /* If a status_fp is available, the thread's main task is to read from that stream and invoke the backend's handler function. This is done on a line by line base and the line length is limited to a reasonable value (about 1000 characters). Other work will continue either due to an EOF of the stream or by demand of the engine. */ if (runner->status_fp) { int c, cont_line; unsigned int pos; char buffer[1024]; estream_t fp = runner->status_fp; pos = 0; cont_line = 0; while (!err && !runner->cancel_flag && (c=es_getc (fp)) != EOF) { buffer[pos++] = c; if (pos >= sizeof buffer - 5 || c == '\n') { buffer[pos - (c == '\n')] = 0; if (opt.verbose) log_info ("%s%s: %s\n", runner->name, cont_line? "(cont)":"", buffer); /* We handle only complete lines and ignore any stuff we possibly had to truncate. That is - at least for the encfs engine - not an issue because our changes to the tool make sure that only relatively short prompt lines are of interest. */ if (!cont_line && runner->handler) err = runner->handler (runner->handler_data, runner, buffer); pos = 0; cont_line = (c != '\n'); } } if (!err && runner->cancel_flag) log_debug ("runner thread noticed cancel flag\n"); else log_debug ("runner thread saw EOF\n"); if (pos) { buffer[pos] = 0; if (opt.verbose) log_info ("%s%s: %s\n", runner->name, cont_line? "(cont)":"", buffer); if (!cont_line && !err && runner->handler) err = runner->handler (runner->handler_data, runner, buffer); } if (!err && es_ferror (fp)) { err = gpg_error_from_syserror (); log_error ("error reading from %s: %s\n", runner->name, gpg_strerror (err)); } runner->status_fp = NULL; es_fclose (fp); log_debug ("runner thread closed status fp\n"); } /* Now wait for the process to finish. */ if (!err && runner->pid != (pid_t)(-1)) { int exitcode; log_debug ("runner thread waiting ...\n"); - err = gnupg_wait_process (runner->name, runner->pid, 0, &exitcode); + err = gnupg_wait_process (runner->name, runner->pid, 1, &exitcode); gnupg_release_process (runner->pid); runner->pid = (pid_t)(-1); if (err) log_error ("running `%s' failed (exitcode=%d): %s\n", runner->name, exitcode, gpg_strerror (err)); log_debug ("runner thread waiting finished\n"); } /* Get rid of the runner object (note: it is refcounted). */ log_debug ("runner thread releasing runner ...\n"); { runner_t r, rprev; for (r = running_threads, rprev = NULL; r; rprev = r, r = r->next_running) if (r == runner) { if (!rprev) running_threads = r->next_running; else rprev->next_running = r->next_running; r->next_running = NULL; break; } } runner_release (runner); log_debug ("runner thread runner released\n"); return NULL; } /* Spawn a new thread to let RUNNER work as a coprocess. */ gpg_error_t runner_spawn (runner_t runner) { gpg_error_t err; pth_attr_t tattr; pth_t tid; if (check_already_spawned (runner, "runner_spawn")) return gpg_error (GPG_ERR_BUG); /* In case we have an input fd, open it as an estream so that the Pth scheduling will work. The stdio functions don't work with Pth because they don't call the pth counterparts of read and write unless linker tricks are used. */ if (runner->in_fd != -1) { estream_t fp; fp = es_fdopen (runner->in_fd, "r"); if (!fp) { err = gpg_error_from_syserror (); log_error ("can't fdopen pipe for reading: %s\n", gpg_strerror (err)); return err; } runner->status_fp = fp; runner->in_fd = -1; /* Now owned by status_fp. */ } tattr = pth_attr_new (); pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 128*1024); pth_attr_set (tattr, PTH_ATTR_NAME, runner->name); tid = pth_spawn (tattr, runner_thread, runner); if (!tid) { err = gpg_error_from_syserror (); log_error ("error spawning runner thread: %s\n", gpg_strerror (err)); return err; } /* The scheduler has not yet kicked in, thus we can safely set the spawned flag and the tid. */ runner->spawned = 1; runner->threadid = tid; runner->next_running = running_threads; running_threads = runner; pth_attr_destroy (tattr); /* The runner thread is now runnable. */ return 0; } /* Cancel a running thread. */ void runner_cancel (runner_t runner) { /* Warning: runner_cancel_all has knowledge of this code. */ if (runner->spawned) { runner->canceled = 1; /* Mark that we canceled this one already. */ /* FIXME: This does only work if the thread emits status lines. We need to change the trhead to wait on an event. */ runner->cancel_flag = 1; /* For now we use the brutal way and kill the process. */ gnupg_kill_process (runner->pid); } } /* Cancel all runner threads. */ void runner_cancel_all (void) { runner_t r; do { for (r = running_threads; r; r = r->next_running) if (r->spawned && !r->canceled) { runner_cancel (r); break; } } while (r); } /* Send a line of data down to the engine. This line may not contain a binary Nul or a LF character. This function is used by the engine's handler. */ gpg_error_t runner_send_line (runner_t runner, const void *data, size_t datalen) { gpg_error_t err = 0; if (!runner->spawned) { log_error ("BUG: runner for %s not spawned\n", runner->name); err = gpg_error (GPG_ERR_INTERNAL); } else if (runner->out_fd == -1) { log_error ("no output file descriptor for runner %s\n", runner->name); err = gpg_error (GPG_ERR_EBADF); } else if (data && datalen) { if (memchr (data, '\n', datalen)) { log_error ("LF detected in response data\n"); err = gpg_error (GPG_ERR_BUG); } else if (memchr (data, 0, datalen)) { log_error ("Nul detected in response data\n"); err = gpg_error (GPG_ERR_BUG); } else if (writen (runner->out_fd, data, datalen)) err = gpg_error_from_syserror (); } if (!err) if (writen (runner->out_fd, "\n", 1)) err = gpg_error_from_syserror (); return err; } diff --git a/tools/ChangeLog b/tools/ChangeLog index c1206d591..d3238b28c 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,1123 +1,1129 @@ +2010-06-24 Werner Koch + + * gpgconf-comp.c (gpg_agent_runtime_change) + (scdaemon_runtime_change, retrieve_options_from_program): Use HANG + option for gnupg_wait_progress. Fixes regression from 2010-06-09. + 2010-06-07 Werner Koch * gpgtar.c, gpgtar.h, gpgtar-list.c, gpgtar-create.c * gpgtar-extract.c: New. * Makefile.am (commonpth_libs): New. (gpgtar_SOURCES, gpgtar_CFLAGS, gpgtar_LDADD): New. (bin_PROGRAMS) [!W32CE]: Add gpgtar. 2010-04-20 Marcus Brinkmann * gpgconf-comp.c (option_check_validity): Use dummy variables to silence gcc warning. 2010-04-14 Werner Koch * Makefile.am (bin_PROGRAMS) [W32CE]: Exclude gpgkey2ssh. (noinst_PROGRAMS) [W32CE]: Don't build them. (pwquery_libs) [W32CE]: Set to empty. 2010-03-25 Werner Koch * Makefile.am (opt_libassuan_libs) [W32CE]: New. (gpgconf_LDADD): Use it. * gpgconf-comp.c: Include signal.h only if available. Use gpg_err_set_errno. (key_matches_user_or_group) [W32CE]: Do not match any user. 2010-03-15 Werner Koch * gpgconf-comp.c (my_dgettext): s/gettext_select_utf8/gettext_use_utf8/. 2010-03-10 Werner Koch * Makefile.am (common_libs): Remove libjnlib.a. 2010-03-08 Werner Koch * no-libgcrypt.c (gcry_create_nonce): New. 2010-02-26 Werner Koch * gpg-connect-agent.c (main): New option --tcp-socket. 2010-01-10 Werner Koch * symcryptrun.c (utmp.h): Remove header; it is not used. 2009-12-18 Werner Koch * applygnupgdefaults (errorfile): Use mktemp. Fixes bug#1146. 2009-12-08 Marcus Brinkmann * gpg-connect-agent.c (main): Convert posix fd to assuan fd. 2009-12-07 Werner Koch * no-libgcrypt.c (gcry_strdup): Actually copy the string. 2009-11-23 Werner Koch * gpgconf-comp.c (gc_options_gpg): Add default_pubkey_algo. 2009-11-05 Marcus Brinkmann * gpg-connect-agent.c (start_agent): Update use of assuan_socket_connect and assuan_pipe_connect. 2009-11-04 Werner Koch * gpg-connect-agent.c (read_and_print_response): Add arg WITHHASH. (main): Pass true for WITHHASH for the HELP command. 2009-09-23 Marcus Brinkmann * gpg-connect-agent.c (getinfo_pid_cb, read_and_print_response) (main): Update to new Assuan API. 2009-07-21 Werner Koch * gpgsplit.c (my_strusage): Remove i18n stuff. 2009-07-07 Werner Koch * gpg-connect-agent.c (start_agent): Adjust for changed args of send_pinentry_environment. 2009-06-30 Werner Koch * ccidmon.c (parse_line_sniffusb): Take also TAB as delimiter. 2009-06-29 Werner Koch * ccidmon.c (parse_line_sniffusb): New. (main): Add option --sniffusb. 2009-06-08 Werner Koch * gpgconf.c (main): Call gnupg_reopen_std. Should fix bug#1072. 2009-05-19 Werner Koch * watchgnupg.c: Include jnlib/mischelp.h if required. (main): Use SUN_LEN. 2009-04-17 Werner Koch * ccidmon.c: New. 2009-03-03 Werner Koch * gpgconf.c: New command --reload. * gpgconf-comp.c (gc_component_reload): New. 2009-03-02 Werner Koch * gpgconf-comp.c (scdaemon_runtime_change): Killsc d only if it is not running. 2009-02-27 Werner Koch * gpgconf-comp.c (gpg_agent_runtime_change): Declare static. (scdaemon_runtime_change): New. (gc_backend_scdaemon): Register new function. (gc_options_scdaemon): Make most options runtime changable. 2009-01-20 Werner Koch * gpgconf.c (main): Print more directories. 2008-12-09 Werner Koch * gpg-check-pattern.c (main): Call i18n_init before init_common_subsystems. * gpg-connect-agent.c (main): Ditto. * gpgconf.c (main): Ditto. * symcryptrun.c (main): Ditto. 2008-12-08 Werner Koch * gpgkey2ssh.c (main): Change order of output for RSA. Change name of DSA identifier. Reported by Daniel Kahn Gillmor. This is bug#901. 2008-12-05 Werner Koch * gpg-connect-agent.c (opts): Use ARGPARSE_ macros. (start_agent) [W32]: Start agent if not running. 2008-12-03 Werner Koch * gpgconf-comp.c : Add option --card-timeout. Remove unused option --disable-opensc. 2008-10-20 Werner Koch * gpgsplit.c (write_part): Remove unused arg FNAME. Change caller. (do_split): Ditto. * no-libgcrypt.c (gcry_control): Mark unused arg. * gpg-connect-agent.c (do_recvfd): Ditto. * gpgparsemail.c (mime_signed_begin, mime_encrypted_begin): Ditto. (pkcs7_begin): Ditto. 2008-10-01 Werner Koch * gpg-connect-agent.c (main): New command datafile. (read_and_print_response): Print to the defined datafile. 2008-09-30 Werner Koch * gpgconf.c (main) : Print the bindir. 2008-08-06 Marcus Brinkmann * gpgconf-comp.c (gc_options_gpgsm): Change type of keyserver option to GC_ARG_TYPE_LDAP_SERVER. * gpgconf-comp.c (retrieve_options_from_file): Transfer the NO_CHANGE flag from the file name option to the list option. 2008-06-19 Werner Koch * gpgconf-comp.c (GC_ARG_TYPE_ALIAS_LIST): New. (gc_arg_type): Add fallback type. (gc_options_gpg): Add option "group". 2008-06-12 Marcus Brinkmann * gpgconf-comp.c (gc_options_gpgsm): Add option keyserver. 2008-05-26 Marcus Brinkmann * gpgconf-comp.c: Replace pathname by filename everywhere. * gpgconf.c (enum cmd_and_opt_values): Add aListDirs. (opts): Add aListDirs option. (main): Handle aListDirs. * gpgconf.h (gc_percent_escape): New declaration. * gpgconf-comp.c (my_percent_escape): Make non-static and rename to ... (gc_percent_escape): ... this. Change all callers. 2008-05-26 Werner Koch * gpgconf-comp.c (gpg_agent_runtime_change) [W32]: Issue "reloadagent" command to gpg-agent. * gpg-connect-agent.c (main): Allow server command on the command line. 2008-05-20 Marcus Brinkmann * gpgconf.h (gc_component_check_programs): Rename to ... (gc_check_programs): ... this. (gc_component_change_options): Add argument OUT. (gc_component_check_options): New function. * gpgconf.c (enum cmd_and_opt_values): New option aCheckOptions. (opts): Add new option aCheckOptions (aka --check-options). (main): Handle new option aCheckOptions. * gpgconf-comp.c (gc_component_check_programs): Rename to ... (gc_check_programs): ... this. Refactor core of it to ... (gc_component_check_options): ... this new function. (gc_component_change_options): Add new argument OUT. Externally verify all changes. Implement option --dry-run. 2008-05-09 Werner Koch * gpgconf-comp.c (my_dgettext) [USE_SIMPLE_GETTEXT]: Hack to parly support translations. 2008-04-08 Werner Koch * gpgconf-comp.c (gc_options_gpg): Add --auto-key-locate. 2008-03-26 Werner Koch * make-dns-cert.c: Include unistd.h. Use config.h if requested. (cert_key): Protect read against EINTR. (main): Print SVN revision for standalone version. 2008-03-05 Werner Koch * gpg-connect-agent.c (arithmetic_op): Add logical not, or and and. (get_var_ext): Add functions errcode, errsource and errstring. (read_and_print_response): Store server reply in $? variable. (main): Implement IF command. 2008-02-27 Marcus Brinkmann * gpgconf-comp.c (option_check_validity): For now, error out on empty strings. (enum): Add GC_ARG_TYPE_PUB_KEY and GC_ARG_TYPE_SEC_KEY. 2008-02-01 Marcus Brinkmann * gpgconf-comp.c (gc_component_list_options): Fix memcpy. Reported by Marc Mutz. 2008-01-22 Werner Koch * gpgconf-comp.c: Use gnupg domain for honor-http-proxy. Make "LDAP server list" group title translatable. 2008-01-17 Marcus Brinkmann * gpgconf-comp.c (change_options_program): Strip duplicated utf8-strings entries for gnupg backend. Don't create them either. 2007-12-10 Marcus Brinkmann * gpgconf-comp.c (gc_component_list_options): Fix up expert level of group. 2007-12-04 Marcus Brinkmann * gpgconf-comp.c (gc_component_list_components): Do not print a trailing semi-colon to ensure forward compatibility, as this would indicate another empty field. (gc_process_gpgconf_conf): Likewise. 2007-11-15 Werner Koch * gpg-connect-agent.c (start_agent): Adjust changed send_pinentry_environment. 2007-10-24 Werner Koch * gpg-connect-agent.c (substitute_line): Restore temporary nul marker. (main): Add /while command. 2007-10-23 Werner Koch * gpgconf-comp.c (gc_process_gpgconf_conf): Add arg LISTFP. Changed all callers. * gpgconf.h: Add gc_error. * gpgconf.c: Add command --list-config. (get_outfp): New. (main): Make --output work. * gpgconf-comp.c (gc_options_gpg_agent): Replace accidently used GC_BACKEND_SCDAEMON. We should consider to create these tables from plain files. 2007-10-22 Werner Koch * gpgconf-comp.c (retrieve_options_from_program): Replace use of popen by our gnupg_spawn_process_fd. This is required because popen under Windows can't handle long filenames. 2007-10-19 Werner Koch * symcryptrun.c (confucius_get_pass): Use utf8 switching functions. * gpg-connect-agent.c (get_var_ext): New. (substitute_line): Use it. (assign_variable): Implement /slet in terms of get_var_ext. (main): New option -s/--subst. (add_definq): Add arg IS_VAR. Change all callers. (main): Add command /definq. (handle_inquire): Implement new command. (substitute_line_copy): New. (unescape_string, unpercent_string): New. * no-libgcrypt.c (gcry_set_outofcore_handler) (gcry_set_fatalerror_handler, gcry_set_log_handler): New. * Makefile.am (gpg_connect_agent_LDADD): Link to libreadline. * gpgconf-comp.c (retrieve_options_from_file): Don't call fclose with NULL. Fixes bug 842. 2007-10-12 Werner Koch * gpg-connect-agent.c (substitute_line): Allow ${foo} syntax. 2007-10-11 Werner Koch * gpg-connect-agent.c (get_var): Expand environment variables. Suggested by Marc Mutz. (set_var): Return the value. (assign_variable): Add arg syslet. (main): New command /slet. (gnu_getcwd): New. (assign_variable): Add tag cwd, and *dir. 2007-10-02 Werner Koch * no-libgcrypt.c (gcry_malloc_secure): New. * gpg-connect-agent.c (set_var, set_int_var, get_var) (substitute_line, show_variables, assign_variable) (do_open, do_close, do_showopen): New. (main): Add new commands /nosubst, /subst, /let, /showvar, /open, /close and /showopen. (main): New commands /run and /bye. 2007-10-01 Werner Koch * gpg-connect-agent.c (do_sendfd): Use INT2FD for assuan_sendfd. 2007-09-26 Werner Koch * gpg-connect-agent.c (main): Print the first response from the server. 2007-09-14 Werner Koch * gpgconf-comp.c: Make a string translatable. 2007-09-04 Moritz Schulte * gpgsm-gencert.sh: Use printf instead of echo. 2007-09-04 Moritz Schulte * gpgkey2ssh.c: Include sysutils.h so that gnupg_tmpfile() is declared. 2007-08-31 Werner Koch * gpgparsemail.c: Support PGP/MIME signed messages. * gpgconf-comp.c (gc_component_list_components): List the programs names. 2007-08-29 Werner Koch * gpgconf.c: New command --check-programs. * gpgconf-comp.c (gc_component_check_programs): New. (gc_backend): Add member MODULE_NAME and add these module names. (retrieve_options_from_program): Use module name so that we use an absolute file name and don't rely on $PATH. (collect_error_output): New. * no-libgcrypt.c (gcry_control): New. 2007-08-28 Werner Koch * gpgconf-comp.c : Add options --max-passphrase-days and --enable-passphrase-history. 2007-08-27 Werner Koch * gpg-check-pattern.c: New * Makefile.am (libexec_PROGRAMS): Add unless DISABLE_REGEX. 2007-08-24 Werner Koch * gpgconf-comp.c : Add options --check-passphrase-pattern, --min-passphrase-nonalpha and --enforce-passphrase-constraints and move them into a new "passphrase policy" group. (gc_component) [W32]: Enable dirmngr. 2007-08-21 Werner Koch * gpgkey2ssh.c (key_to_blob): Use gnupg_tmpfile(). 2007-08-02 Werner Koch * gpgconf-comp.c: Factor the public GC_OPT_FLAG constants out and include gc-opt-flags.h. 2007-07-17 Werner Koch * gpgconf-comp.c: Add --encrypt-to and --default-key to gpg and gpgsm. 2007-07-16 Marcus Brinkmann * gpg-connect-agent.c (main): Bail out if write fails. 2007-07-05 Marcus Brinkmann * symcryptrun.c (confucius_get_pass): Define orig_codeset if [ENABLE_NLS], not [HAVE_LANGINFO_CODESET]. 2007-06-26 Werner Koch * gpgconf-comp.c (key_matches_user_or_group) [W32]: Implement user name matching. (GPGNAME): New. Use it instead of "gpg". (gc_component) [W32]: Disable dirmngr for now. (gc_component_retrieve_options): Ignore components without options. (gc_component_change_options): Ditto. (gc_component_list_options): Ditto. (gc_component_find, gc_component_list_components): Ditto. 2007-06-19 Werner Koch * gpgconf-comp.c (percent_escape): Rename to my_percent_escape. Changed all callers. 2007-06-18 Marcus Brinkmann * gpgconf-comp.c (retrieve_options_from_file): Close LIST_FILE. (copy_file): In error case, save/restore errno. Close SRC and DST. (gc_component_change_options): Catch error from unlink(). Remove target backup file before rename(). 2007-06-15 Marcus Brinkmann * gpgconf-comp.c (copy_file) [HAVE_W32_SYSTEM]: New function. (change_options_file, change_options_program) [HAVE_W32_SYSTEM]: Copy backup file. (gc_component_change_options) [HAVE_W32_SYSTEM]: Non-atomic replace. (gc_process_gpgconf_conf): Rename fname to fname_arg and fname_buffer to fname, initialize fname with fname_arg, discarding const qualifier. 2007-06-15 Werner Koch * Makefile.am (symcryptrun_LDADD): It is LIBICONV and not LIBINCONV. (gpgconf_LDADD, symcryptrun_LDADD): Add W32SOCKLIBS. 2007-06-14 Werner Koch * symcryptrun.c (main): Setup default socket name for simple-pwquery. (MAP_SPWQ_ERROR_IMPL): New. Use it for all spwq error returns. 2007-06-12 Werner Koch * gpgconf-comp.c (gc_process_gpgconf_conf): Replace GNUPG_SYSCONFDIR by a function call. * gpg-connect-agent.c (main): Replace some calls by init_common_subsystems. * gpgconf.c (main): Ditto. * symcryptrun.c (main): Ditto. 2007-06-11 Werner Koch * symcryptrun.c (main) [W32]: Call pth_init. * gpgconf.c (main) [W32]: Call pth_init * gpg-connect-agent.c (main) [W32]: Call pth_init. 2007-06-06 Werner Koch * Makefile.am (bin_PROGRAMS) [W32]: Do not build gpgparsemail. * gpgconf-comp.c [W32]: Do not include pwd.h and grp.h. (key_matches_user_or_group) [W32]: For now always return false. * symcryptrun.c (i18n_init): Remove. * gpgconf.c (i18n_init): Remove. * gpg-connect-agent.c (i18n_init): Remove. 2007-05-19 Marcus Brinkmann * symcryptrun.c (confucius_get_pass): Free ORIG_CODESET on error. 2007-05-08 Werner Koch * sockprox.c: New. It needs to be build manually. By Moritz Schulte. 2007-04-20 Werner Koch * symcryptrun.c (my_gcry_logger): Removed. (main): Call setup_libgcrypt_logging. 2007-04-03 Werner Koch * gpgconf-comp.c: Allow changing of --allow-mark-trusted. * gpg-connect-agent.c (main): New option --decode and commands decode and undecode. (read_and_print_response): Implement option. 2007-03-20 Werner Koch * gpgconf-comp.c (gc_options_gpgsm): Add p12-charset. 2007-03-07 Werner Koch * applygnupgdefaults: New. * Makefile.am (sbin_SCRIPTS): Add it 2007-03-06 Werner Koch * gpgconf-comp.c: Include pwd.h and grp.h. (GC_OPT_FLAG_NO_CHANGE): New. (gc_component_change_options): Implement it. (gc_options_gpg_agent): Add options for all ttl values and min-passphrase-length. Apply new flag to some of them. (gc_process_gpgconf_conf, key_matches_user_or_group): New. (gc_component_change_options): Factor some code out to .. (change_one_value): .. new. (gc_component_retrieve_options): Allow -1 for COMPONENT to iterate over al components. * gpgconf.c (main): New commands --check-config and --apply-defaults. Call gc_process_gpgconf_conf. 2007-01-31 Werner Koch * Makefile.am (symcryptrun_LDADD): Add LIBICONV. (gpgkey2ssh_LDADD): Ditto. 2006-12-13 David Shaw * Makefile.am (gpgsplit_LDADD): Link to LIBINTL if we're using the built-in code. 2006-12-07 David Shaw * Makefile.am: Link to iconv for jnlib dependency. 2006-11-23 Werner Koch * Makefile.am (gpg_connect_agent_LDADD): Add NETLIBS. 2006-11-21 Werner Koch * gpgconf-comp.c (list_one_option): Cast print size_t arg. 2006-11-17 Werner Koch * gpgconf-comp.c: Made disable-keypad a basic option. 2006-11-03 Werner Koch * symcryptrun.c: Include signal.h and include pth.h only if test asserts that it exists. 2006-10-23 Werner Koch * gpgconf-comp.c : Add --cipher-algo. 2006-10-20 Werner Koch * gpgsm-gencert.sh: Enhanced the main menu. 2006-10-12 Werner Koch * Makefile.am (gpg-zip, gpgsplit): Do not install due to a conflict with gpg1. 2006-10-11 Werner Koch * gpgsm-gencert.sh: Allow generation of card keys. 2006-10-08 Werner Koch * Makefile.am (gpgkey2ssh_LDADD): Add LIBINTL. Suggested by Andreas Metzler. 2006-09-22 Werner Koch * no-libgcrypt.c: Changed license to a simple all permissive one. 2006-09-20 Werner Koch * Makefile.am: Changes to allow parallel make runs. 2006-09-12 Werner Koch Replaced all call gpg_error_from_errno(errno) by gpg_error_from_syserror(). * gpg-connect-agent.c (read_and_print_response): With verbosity level 2 also print comment lines. 2006-09-06 Werner Koch * gpg-connect-agent.c: Switch everything to new Assuan error code style. * no-libgcrypt.c (out_of_core): Reanmed to ... (out_of_memory): .. this to avoid name clash with util.h. 2006-08-21 Werner Koch * gpgsplit.c: New. Taken from 1.4. Adjusted to GnuPG2. * Makefile.am (noinst_PROGRAMS): New. 2006-06-09 Marcus Brinkmann * Makefile.am (gpgconf_LDADD): Add $(GPG_ERROR_LIBS). (gpgkey2ssh_LDADD): Add ../jnlib/libjnlib.a. 2006-05-23 Werner Koch * gpgparsemail.c: Include config.h if available (stpcpy): Conditional include it. * gpgconf-comp.c (hextobyte): Removed as it is now availble in jnlib. 2005-12-20 Werner Koch * gpgconf-comp.c (gc_options_gpg): Add allow-pka-lookup. 2005-12-14 Werner Koch * Makefile.am (bin_PROGRAMS): Build gpgparsemail. * gpgparsemail.c (pkcs7_begin): New. (parse_message, message_cb): Add support of direct pkcs signatures. 2005-10-19 Werner Koch * gpgconf-comp.c (gc_options_scdaemon): New option --disable-keypad. 2005-09-22 Werner Koch * rfc822parse.c (parse_field): Tread Content-Disposition special. 2005-10-08 Marcus Brinkmann * Makefile.am (watchgnupg_LDADD): New variable. * Makefile.am (gpgconf_LDADD): Add ../gl/libgnu.a after ../common/libcommon.a. (symcryptrun_LDADD, gpg_connect_agent_LDADD, gpgkey2ssh_LDADD): Likewise. 2005-09-29 Marcus Brinkmann * Makefile.am (AM_CFLAGS): Add $(LIBGCRYPT_CFLAGS). 2005-09-06 Werner Koch * rfc822parse.c, rfc822parse.h: Changed license to LGPL. 2005-08-01 Werner Koch * gpgsm-gencert.sh: Allow entering a keygrip to generate a CSR from an existing key. 2005-07-21 Werner Koch * gpgsm-gencert.sh: Reworked to allow for multiple email addresses as well as DNsanmes and URi. Present the parameter file before creating the certificate. 2005-07-04 Marcus Brinkmann * symcryptrun.c (SYMC_BAD_PASSPHRASE, SYMC_CANCELED): New symbols, use instead constants. (hash_string): New function copied from simple-gettext.c. (confucius_get_pass): Take new argument CACHEID. (confucius_process): Calculate cacheid and pass it to confucius_get_pass. Clear passphrase from cache if necessary. 2005-06-16 Werner Koch * gpg-connect-agent.c (read_and_print_response): Made LINELEN a size_t. 2005-06-04 Marcus Brinkmann * symcryptrun.c (main): Allow any number of arguments, don't use first argument as input file name. Pass extra arguments to confucius_main. (confucius_main): Accept new arguments argc and argv and pass them to confucius_process. (confucius_process): Accept new arguments argc and argv and pass them to the confucius process. 2005-06-01 Werner Koch * symcryptrun.c: Include mkdtemp.h. 2005-05-31 Werner Koch * watchgnupg.c: Make sure that PF_LCOAL and AF_LOCAL are defines. Noted by Ray Link. 2005-05-28 Moritz Schulte * gpgkey2ssh.c: New file. * Makefile.am (bin_PROGRAMS): Added gpgkey2ssh. 2005-05-20 Werner Koch * gpg-connect-agent.c (add_definq, show_definq, clear_definq) (handle_inquire): New. (read_and_print_response): Handle INQUIRE command. (main): Implement control commands. 2005-04-21 Werner Koch * symcryptrun.c (main): Optionally allow the input file as command line argument. * gpgconf-comp.c: Add gpgsm option disable-trusted-cert-crl-check. 2005-04-20 Werner Koch * gpgconf-comp.c: Add gpg-agent:disable-scdaemon. 2005-04-19 Marcus Brinkmann * symcryptrun.c: Add --input option. 2005-04-15 Marcus Brinkmann * symcryptrun.c (TEMP_FAILURE_RETRY): Define if not defined. * symcryptrun.c (remove_file): New function. (confucius_copy_file): Accept new argument PLAIN and shred the file if it is set on error. * Makefile.am: Define symcryptrun make variable depending on BUILD_SYMCRYPTUN. (bin_PROGRAMS): Add ${symcryptrun} instead symcryptrun. (symcryptrun_LDADD): Use $(LIBUTIL_LIBS) instead of -lutil. 2005-04-11 Werner Koch * symcryptrun.c (confucius_mktmpdir): Changed to use mkdtmp(3). 2005-04-11 Marcus Brinkmann * symcryptrun.c: Implement config file parsing. * Makefile.am (bin_PROGRAMS): Add symcryptrun. (symcryptrun_SOURCES, symcryptrun_LDADD): New variables. * symcryptrun.c: New file. 2005-03-31 Werner Koch * gpg-connect-agent.c (start_agent): Use PATHSEP_C instead of ':'. 2005-03-09 Werner Koch * gpgconf-comp.c : Add honor-http-proxy. 2005-02-25 Werner Koch * no-libgcrypt.c (gcry_strdup): New. 2005-02-24 Werner Koch * gpg-connect-agent.c: New. * Makefile.am: Add it. 2004-12-21 Werner Koch * gpgconf-comp.c (get_config_pathname) [DOSISH]: Detect absolute pathnames with a drive letter. 2004-12-15 Werner Koch * Makefile.am (bin_PROGRAMS) [W32]: Do not build watchgnupg. * gpgconf-comp.c (gpg_agent_runtime_change) [W32]: No way yet to send a signal. Disable. (change_options_file, change_options_program) [W32]: No link(2), so we disable it. (gc_component_change_options): Use rename instead of link. 2004-12-13 Werner Koch * gpgconf-comp.c : Fixed typo. 2004-11-24 Werner Koch * gpgconf-comp.c : Add --ignore-http-dp, --ignore-ldap-dp and --ignore-ocsp-service-url. 2004-11-23 Werner Koch * gpgconf-comp.c : Add the proxy options. : Add --prefer-system-daemon. 2004-11-11 Werner Koch * watchgnupg.c (main): Fixed test for read error. 2004-10-22 Werner Koch * Makefile.am (bin_SCRIPTS): Add gpgsm-gencert.sh * gpgsm-gencert.sh: Fixed copyright; its part of GnuPG thus FSF. 2004-10-01 Werner Koch * gpgconf-comp.c: Made all strings for --log-file read the same. 2004-10-01 Werner Koch * gpgconf-comp.c (my_dgettext): Also switch codeset and directory for the other used domains (i.e. dirmngr). * gpgconf.c (main): Fixed translation markers. 2004-09-30 Werner Koch * gpgconf.c (i18n_init): Always use LC_ALL. * Makefile.am: Adjusted for gettext 0.14. 2004-09-29 Werner Koch * gpgconf-comp.c: Made the entries fro GROUPs translatable. Include i18n.h. (my_dgettext): Hack to use the gnupg2 domain. 2004-08-09 Moritz Schulte * gpgsm-gencert.sh: New file. 2004-06-16 Werner Koch * rfc822parse.c (rfc822parse_get_field): Add arg VALUEOFF. 2004-06-14 Werner Koch * no-libgcrypt.c (gcry_realloc, gcry_xmalloc, gcry_xcalloc): New. * gpgconf-comp.c (retrieve_options_from_program) (retrieve_options_from_file, change_options_file) (change_options_program, gc_component_change_options): Replaced getline by read_line and test for allocation failure. 2004-05-21 Marcus Brinkmann * gpgconf-comp.c (gc_options_dirmngr): Remove CRL group, put its only option "max-replies" into LDAP group. (gc_component): Change description of dirmngr to "Directory Manager". * gpgconf-comp.c (gc_component_change_options): Move the per-process backup file into a standard location. 2004-05-03 Werner Koch * gpgconf-comp.c: Add --allow-mark-trusted for the gpg-agent. 2004-04-30 Werner Koch * gpgconf-comp.c: Added more runtime flags for the gpg-agent backend. 2004-04-29 Marcus Brinkmann * gpgconf-comp.c (change_options_program): Turn on utf8-strings in the gpgconf specific part of the config file for the GnuPG backend. 2004-04-28 Werner Koch * gpgconf-comp.c: Add --ocsp-signer for the dirmngr backend. 2004-04-20 Marcus Brinkmann * gpgconf-comp.c (gc_options_gpg_agent): Change type of ignore-cache-for-signing option to GC_ARG_TYPE_NONE. 2004-04-07 Werner Koch * gpgconf-comp.c (my_dgettext): Switch the codeset once to utf-8. Allow building with out NLS. 2004-03-23 Marcus Brinkmann * gpgconf-comp.c (gc_options_dirmngr): Set GC_OPT_FLAG_ARG_OPT for "LDAP Server". (change_options_file): Remove assertion that tests that this flag is not present. Handle an empty string in OPTION->new_value. * gpgconf.c (main): Remove obsolete warning. 2004-03-23 Werner Koch * gpgconf-comp.c (gc_options_gpg): New. (gc_component_t, gc_component): Add GC_BACKEND_GPG. (gc_options_dirmngr): Add allow-ocsp. 2004-03-23 Marcus Brinkmann * gpgconf-comp.c (gc_flag): Add missing flags. * gpgconf-comp.c: Include . (gc_backend): Add new member runtime_change. (gpg_agent_runtime_change): New function. (gc_component_change_options): New variable runtime. Initialize it. If an option is changed that has the GC_OPT_FLAG_RUNTIME bit set, also set the corresponding runtime variable. Finally, call the runtime_change callback of the backend if needed. 2004-03-16 Werner Koch * gpgconf-comp.c (gc_options_gpg_agent): Implemented. (gc_options_gpgsm, gc_options_scdaemon): Implemented. (gc_backend_t): Add GC_BACKEND_SCDAEMON. 2004-03-12 Marcus Brinkmann * gpgconf-comp.c (gc_component_change_options): Set the filenames of the option's backend, not of the component. Also use GC_BACKEND_NR, not GC_COMPONENT_NR. 2004-03-09 Werner Koch * gpgconf-comp.c [_riscos_]: Removed special code for RISC OS; we don't want to clutter our code with system dependent stuff. 2004-03-08 Marcus Brinkmann * gpgconf-comp.c (retrieve_options_from_file): Quote each string in the list, not only the first. 2004-02-26 Marcus Brinkmann * gpgconf-comp.c (gc_component_list_options): Do not print empty groups. * gpgconf-comp.c (option_check_validity): Check if option is active. (change_options_file): Implement. * gpgconf-comp.c (retrieve_options_from_program): Remove broken string handling. * gpgconf-comp.c (change_options_program): Support all types of options, including list types. * README.gpgconf: Fix description of arguments. * gpgconf-comp.c (option_check_validity): Rewritten to properly support optional arguments in lists. * README.gpgconf: Add info about optional arg and arg type 0. * gpgconf-comp.c (gc_component_change_options): Parse list of arg type 0 options. (option_check_validity): Add new argument NEW_VALUE_NR. Perform rigorous validity checks. (change_options_program): Disable an option also if we have a new value for it. 2004-02-25 Marcus Brinkmann * gpgconf-comp.c (gc_component_list_options): Correct output for lists of arg type none. (struct gc_option): Add new member new_flags. (option_check_validity): Check OPTION->new_flags beside OPTION->new_value. Add new argument FLAGS. (gc_component_change_options): Support default flag correctly. (change_options_program): Likewise. 2004-02-24 Marcus Brinkmann * README.gpgconf: Revert last change. Add new flags "default", "default desc" and "no arg desc". Add new field ARGDEF. Add new field FLAG to backend interface. * gpgconf-comp.c (struct gc_option): Make flags of type unsigned long. (gc_component_list_options): Adjust type for flags. Add default argument field. (retrieve_options_from_program): Use "1" as value for non-option arguments, not "Y". (gc_component_change_options): Read in flags from input. 2004-02-23 Marcus Brinkmann * README.gpgconf: Change meaning of type 0 options value if it is the empty string or "0". * gpgconf.h (struct): Add member runtime. * gpgconf.c: Add new option oRuntime. (main): Same here. * gpgconf-comp.c (hextobyte): New function. (percent_deescape): New function. (get_config_pathname): Percent deescape pathname if taken from option (default) value. Use default value only if it exists and is not empty. Use empty string otherwise. Don't include leading quote in pathname. (change_options_program): Percent deescape string before writing it out. * gpgconf-comp.c (gc_component_list_options): Do not skip groups on output. 2004-02-18 Werner Koch * gpgconf-comp.c: Added empty components for gpgsm and scdaemon. 2004-02-12 Werner Koch * watchgnupg.c (main): Implement option "--". (print_version): New. * Makefile.am: Include cmacros.am for common flags. 2004-02-03 Werner Koch * addgnupghome: Try to use getent, so that it also works for NIS setups. 2004-01-31 Marcus Brinkmann * gpgconf-comp.c: Some bug fixes, parse only defaults from the program, and read the current values from the configuration file directly. 2004-01-30 Marcus Brinkmann * gpgconf-comp.c (gc_error): New function, use it instead of error() throughout. * gpgconf-comp.c: Use xmalloc, libcommon's asctimestamp and gnupg_get_time, fix error() invocation and use getline() consistently. 2004-01-30 Werner Koch * addgnupghome: Also set the group of copied files. 2004-01-30 Werner Koch * Makefile.am (sbin_SCRIPTS): New, to install addgnupghome. (EXTRA_DIST): Added rfc822parse.c rfc822parse.h gpgparsemail.c which might be useful for debugging. 2004-01-29 Werner Koch * addgnupghome: New. 2004-01-29 Marcus Brinkmann * gpgconf-list.c: File removed. * README.gpgconf: New file. * gpgconf-comp.c: New file. * Makefile.am (gpgconf_SOURCES): Remove gpgconf-list.c, add gpgconf-comp.c. 2004-01-16 Werner Koch * watchgnupg.c (main): Need to use FD_ISSET for the client descriptors too; aiiih. Set the listening socket to non-blocking. 2004-01-10 Werner Koch * Makefile.am: Use GPG_ERROR_CFLAGS 2004-01-05 Werner Koch * Manifest: New. * gpgconf.c, gpgconf.h, gpgconf-list.c: New. A skeleton for now. * no-libgcrypt.c: New. * Makefile.am: Add above. 2003-12-23 Werner Koch * Makefile.am: New. * watchgnupg.c: New. Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 505ca465a..f37a929aa 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -1,3652 +1,3652 @@ /* gpgconf-comp.c - Configuration utility for GnuPG. * Copyright (C) 2004, 2007, 2008, 2009, 2010 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 3 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 GnuPG; if not, see . */ #if HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SIGNAL_H # include #endif #include #ifdef HAVE_W32_SYSTEM # define WIN32_LEAN_AND_MEAN 1 # include #else # include # include #endif /* For log_logv(), asctimestamp(), gnupg_get_time (). */ #define JNLIB_NEED_LOG_LOGV #include "util.h" #include "i18n.h" #include "exechelp.h" #include "gc-opt-flags.h" #include "gpgconf.h" /* There is a problem with gpg 1.4 under Windows: --gpgconf-list returns a plain filename without escaping. As long as we have not fixed that we need to use gpg2 - it might actually be better to use gpg2 in any case. */ #ifdef HAVE_W32_SYSTEM #define GPGNAME "gpg2" #else #define GPGNAME "gpg" #endif /* TODO: Components: Add more components and their options. Robustness: Do more validation. Call programs to do validation for us. Add options to change backend binary path. Extract binary path for some backends from gpgsm/gpg config. */ #if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )) void gc_error (int status, int errnum, const char *fmt, ...) \ __attribute__ ((format (printf, 3, 4))); #endif /* Output a diagnostic message. If ERRNUM is not 0, then the output is followed by a colon, a white space, and the error string for the error number ERRNUM. In any case the output is finished by a newline. The message is prepended by the program name, a colon, and a whitespace. The output may be further formatted or redirected by the jnlib logging facility. */ void gc_error (int status, int errnum, const char *fmt, ...) { va_list arg_ptr; va_start (arg_ptr, fmt); log_logv (JNLIB_LOG_ERROR, fmt, arg_ptr); va_end (arg_ptr); if (errnum) log_printf (": %s\n", strerror (errnum)); else log_printf ("\n"); if (status) { log_printf (NULL); log_printf ("fatal error (exit status %i)\n", status); exit (status); } } /* Forward declaration. */ static void gpg_agent_runtime_change (void); static void scdaemon_runtime_change (void); /* Backend configuration. Backends are used to decide how the default and current value of an option can be determined, and how the option can be changed. To every option in every component belongs exactly one backend that controls and determines the option. Some backends are programs from the GPG system. Others might be implemented by GPGConf itself. If you change this enum, don't forget to update GC_BACKEND below. */ typedef enum { /* Any backend, used for find_option (). */ GC_BACKEND_ANY, /* The Gnu Privacy Guard. */ GC_BACKEND_GPG, /* The Gnu Privacy Guard for S/MIME. */ GC_BACKEND_GPGSM, /* The GPG Agent. */ GC_BACKEND_GPG_AGENT, /* The GnuPG SCDaemon. */ GC_BACKEND_SCDAEMON, /* The Aegypten directory manager. */ GC_BACKEND_DIRMNGR, /* The LDAP server list file for the Aegypten director manager. */ GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST, /* The number of the above entries. */ GC_BACKEND_NR } gc_backend_t; /* To be able to implement generic algorithms for the various backends, we collect all information about them in this struct. */ static struct { /* The name of the backend. */ const char *name; /* The name of the program that acts as the backend. Some backends don't have an associated program, but are implemented directly by GPGConf. In this case, PROGRAM is NULL. */ char *program; /* The module name (GNUPG_MODULE_NAME_foo) as defined by ../common/util.h. This value is used to get the actual installed path of the program. 0 is used if no backedn program is available. */ char module_name; /* The runtime change callback. */ void (*runtime_change) (void); /* The option name for the configuration filename of this backend. This must be an absolute filename. It can be an option from a different backend (but then ordering of the options might matter). Note: This must be unique among all components. */ const char *option_config_filename; /* If this is a file backend rather than a program backend, then this is the name of the option associated with the file. */ const char *option_name; } gc_backend[GC_BACKEND_NR] = { { NULL }, /* GC_BACKEND_ANY dummy entry. */ { "GnuPG", GPGNAME, GNUPG_MODULE_NAME_GPG, NULL, "gpgconf-gpg.conf" }, { "GPGSM", "gpgsm", GNUPG_MODULE_NAME_GPGSM, NULL, "gpgconf-gpgsm.conf" }, { "GPG Agent", "gpg-agent", GNUPG_MODULE_NAME_AGENT, gpg_agent_runtime_change, "gpgconf-gpg-agent.conf" }, { "SCDaemon", "scdaemon", GNUPG_MODULE_NAME_SCDAEMON, scdaemon_runtime_change, "gpgconf-scdaemon.conf" }, { "DirMngr", "dirmngr", GNUPG_MODULE_NAME_DIRMNGR, NULL, "gpgconf-dirmngr.conf" }, { "DirMngr LDAP Server List", NULL, 0, NULL, "ldapserverlist-file", "LDAP Server" }, }; /* Option configuration. */ /* An option might take an argument, or not. Argument types can be basic or complex. Basic types are generic and easy to validate. Complex types provide more specific information about the intended use, but can be difficult to validate. If you add to this enum, don't forget to update GC_ARG_TYPE below. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING ENTRIES, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ typedef enum { /* Basic argument types. */ /* No argument. */ GC_ARG_TYPE_NONE = 0, /* A String argument. */ GC_ARG_TYPE_STRING = 1, /* A signed integer argument. */ GC_ARG_TYPE_INT32 = 2, /* An unsigned integer argument. */ GC_ARG_TYPE_UINT32 = 3, /* ADD NEW BASIC TYPE ENTRIES HERE. */ /* Complex argument types. */ /* A complete filename. */ GC_ARG_TYPE_FILENAME = 32, /* An LDAP server in the format HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN. */ GC_ARG_TYPE_LDAP_SERVER = 33, /* A 40 character fingerprint. */ GC_ARG_TYPE_KEY_FPR = 34, /* A user ID or key ID or fingerprint for a certificate. */ GC_ARG_TYPE_PUB_KEY = 35, /* A user ID or key ID or fingerprint for a certificate with a key. */ GC_ARG_TYPE_SEC_KEY = 36, /* A alias list made up of a key, an equal sign and a space separated list of values. */ GC_ARG_TYPE_ALIAS_LIST = 37, /* ADD NEW COMPLEX TYPE ENTRIES HERE. */ /* The number of the above entries. */ GC_ARG_TYPE_NR } gc_arg_type_t; /* For every argument, we record some information about it in the following struct. */ static struct { /* For every argument type exists a basic argument type that can be used as a fallback for input and validation purposes. */ gc_arg_type_t fallback; /* Human-readable name of the type. */ const char *name; } gc_arg_type[GC_ARG_TYPE_NR] = { /* The basic argument types have their own types as fallback. */ { GC_ARG_TYPE_NONE, "none" }, { GC_ARG_TYPE_STRING, "string" }, { GC_ARG_TYPE_INT32, "int32" }, { GC_ARG_TYPE_UINT32, "uint32" }, /* Reserved basic type entries for future extension. */ { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, /* The complex argument types have a basic type as fallback. */ { GC_ARG_TYPE_STRING, "filename" }, { GC_ARG_TYPE_STRING, "ldap server" }, { GC_ARG_TYPE_STRING, "key fpr" }, { GC_ARG_TYPE_STRING, "pub key" }, { GC_ARG_TYPE_STRING, "sec key" }, { GC_ARG_TYPE_STRING, "alias list" }, }; /* Every option has an associated expert level, than can be used to hide advanced and expert options from beginners. If you add to this list, don't forget to update GC_LEVEL below. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING ENTRIES, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ typedef enum { /* The basic options should always be displayed. */ GC_LEVEL_BASIC, /* The advanced options may be hidden from beginners. */ GC_LEVEL_ADVANCED, /* The expert options should only be displayed to experts. */ GC_LEVEL_EXPERT, /* The invisible options should normally never be displayed. */ GC_LEVEL_INVISIBLE, /* The internal options are never exported, they mark options that are recorded for internal use only. */ GC_LEVEL_INTERNAL, /* ADD NEW ENTRIES HERE. */ /* The number of the above entries. */ GC_LEVEL_NR } gc_expert_level_t; /* A description for each expert level. */ static struct { const char *name; } gc_level[] = { { "basic" }, { "advanced" }, { "expert" }, { "invisible" }, { "internal" } }; /* Option flags. The flags which are used by the backends are defined by gc-opt-flags.h, included above. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ /* Some entries in the option list are not options, but mark the beginning of a new group of options. These entries have the GROUP flag set. */ #define GC_OPT_FLAG_GROUP (1UL << 0) /* The ARG_OPT flag for an option indicates that the argument is optional. This is never set for GC_ARG_TYPE_NONE options. */ #define GC_OPT_FLAG_ARG_OPT (1UL << 1) /* The LIST flag for an option indicates that the option can occur several times. A comma separated list of arguments is used as the argument value. */ #define GC_OPT_FLAG_LIST (1UL << 2) /* The NO_CHANGE flag for an option indicates that the user should not be allowed to change this option using the standard gpgconf method. Frontends using gpgconf should grey out such options, so that only the current value is displayed. */ #define GC_OPT_FLAG_NO_CHANGE (1UL <<7) /* A human-readable description for each flag. */ static struct { const char *name; } gc_flag[] = { { "group" }, { "optional arg" }, { "list" }, { "runtime" }, { "default" }, { "default desc" }, { "no arg desc" }, { "no change" } }; /* To each option, or group marker, the information in the GC_OPTION struct is provided. If you change this, don't forget to update the option list of each component. */ struct gc_option { /* If this is NULL, then this is a terminator in an array of unknown length. Otherwise, if this entry is a group marker (see FLAGS), then this is the name of the group described by this entry. Otherwise it is the name of the option described by this entry. The name must not contain a colon. */ const char *name; /* The option flags. If the GROUP flag is set, then this entry is a group marker, not an option, and only the fields LEVEL, DESC_DOMAIN and DESC are valid. In all other cases, this entry describes a new option and all fields are valid. */ unsigned long flags; /* The expert level. This field is valid for options and groups. A group has the expert level of the lowest-level option in the group. */ gc_expert_level_t level; /* A gettext domain in which the following description can be found. If this is NULL, then DESC is not translated. Valid for groups and options. Note that we try to keep the description of groups within the gnupg domain. IMPORTANT: If you add a new domain please make sure to add a code set switching call to the function my_dgettext further below. */ const char *desc_domain; /* A gettext description for this group or option. If it starts with a '|', then the string up to the next '|' describes the argument, and the description follows the second '|'. In general enclosing these description in N_() is not required because the description should be identical to the one in the help menu of the respective program. */ const char *desc; /* The following fields are only valid for options. */ /* The type of the option argument. */ gc_arg_type_t arg_type; /* The backend that implements this option. */ gc_backend_t backend; /* The following fields are set to NULL at startup (because all option's are declared as static variables). They are at the end of the list so that they can be omitted from the option declarations. */ /* This is true if the option is supported by this version of the backend. */ int active; /* The default value for this option. This is NULL if the option is not present in the backend, the empty string if no default is available, and otherwise a quoted string. */ char *default_value; /* The default argument is only valid if the "optional arg" flag is set, and specifies the default argument (value) that is used if the argument is omitted. */ char *default_arg; /* The current value of this option. */ char *value; /* The new flags for this option. The only defined flag is actually GC_OPT_FLAG_DEFAULT, and it means that the option should be deleted. In this case, NEW_VALUE is NULL. */ unsigned long new_flags; /* The new value of this option. */ char *new_value; }; typedef struct gc_option gc_option_t; /* Use this macro to terminate an option list. */ #define GC_OPTION_NULL { NULL } /* The options of the GC_COMPONENT_GPG_AGENT component. */ static gc_option_t gc_options_gpg_agent[] = { /* The configuration file to which we write the changes. */ { "gpgconf-gpg-agent.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT }, { "Monitor", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Options controlling the diagnostic output") }, { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "verbose", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, { "quiet", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "be somewhat more quiet", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, NULL, NULL, GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, { "Configuration", GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, "gnupg", N_("Options controlling the configuration") }, { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "|FILE|read options from FILE", GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT }, { "disable-scdaemon", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "gnupg", "do not use the SCdaemon", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, "gnupg", N_("Options useful for debugging") }, { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_GPG_AGENT }, { "log-file", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", N_("|FILE|write server mode logs to FILE"), GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT }, { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, NULL, NULL, GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, { "Security", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Options controlling the security") }, { "default-cache-ttl", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "|N|expire cached PINs after N seconds", GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, { "default-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", N_("|N|expire SSH keys after N seconds"), GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, { "max-cache-ttl", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", N_("|N|set maximum PIN cache lifetime to N seconds"), GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, { "max-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", N_("|N|set maximum SSH key lifetime to N seconds"), GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, { "ignore-cache-for-signing", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "do not use the PIN cache when signing", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, { "allow-mark-trusted", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", "allow clients to mark keys as \"trusted\"", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, { "no-grab", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", "do not grab keyboard and mouse", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, { "Passphrase policy", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, "gnupg", N_("Options enforcing a passphrase policy") }, { "enforce-passphrase-constraints", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", N_("do not allow to bypass the passphrase policy"), GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, { "min-passphrase-len", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", N_("|N|set minimal required length for new passphrases to N"), GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, { "min-passphrase-nonalpha", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", N_("|N|require at least N non-alpha characters for a new passphrase"), GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, { "check-passphrase-pattern", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", N_("|FILE|check new passphrases against pattern in FILE"), GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT }, { "max-passphrase-days", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", N_("|N|expire the passphrase after N days"), GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, { "enable-passphrase-history", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", N_("do not allow the reuse of old passphrases"), GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, GC_OPTION_NULL }; /* The options of the GC_COMPONENT_SCDAEMON component. */ static gc_option_t gc_options_scdaemon[] = { /* The configuration file to which we write the changes. */ { "gpgconf-scdaemon.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON }, { "Monitor", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Options controlling the diagnostic output") }, { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "verbose", GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", "be somewhat more quiet", GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, NULL, NULL, GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, { "Configuration", GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, "gnupg", N_("Options controlling the configuration") }, { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "|FILE|read options from FILE", GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON }, { "reader-port", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "|N|connect to reader at port N", GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, { "ctapi-driver", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", "|NAME|use NAME as ct-API driver", GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, { "pcsc-driver", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", "|NAME|use NAME as PC/SC driver", GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, { "disable-ccid", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", "do not use the internal CCID driver", GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, { "disable-keypad", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "do not use a reader's keypad", GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, { "card-timeout", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "|N|disconnect the card after N seconds of inactivity", GC_ARG_TYPE_UINT32, GC_BACKEND_SCDAEMON }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, "gnupg", N_("Options useful for debugging") }, { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, { "log-file", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", N_("|FILE|write a log to FILE"), GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON }, { "Security", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Options controlling the security") }, { "deny-admin", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "deny the use of admin card commands", GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, GC_OPTION_NULL }; /* The options of the GC_COMPONENT_GPG component. */ static gc_option_t gc_options_gpg[] = { /* The configuration file to which we write the changes. */ { "gpgconf-gpg.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG }, { "Monitor", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Options controlling the diagnostic output") }, { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, "gnupg", "verbose", GC_ARG_TYPE_NONE, GC_BACKEND_GPG }, { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", "be somewhat more quiet", GC_ARG_TYPE_NONE, GC_BACKEND_GPG }, { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, NULL, NULL, GC_ARG_TYPE_NONE, GC_BACKEND_GPG }, { "Configuration", GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, "gnupg", N_("Options controlling the configuration") }, { "default-key", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", N_("|NAME|use NAME as default secret key"), GC_ARG_TYPE_STRING, GC_BACKEND_GPG }, { "encrypt-to", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", N_("|NAME|encrypt to user ID NAME as well"), GC_ARG_TYPE_STRING, GC_BACKEND_GPG }, { "group", GC_OPT_FLAG_LIST, GC_LEVEL_ADVANCED, "gnupg", N_("|SPEC|set up email aliases"), GC_ARG_TYPE_ALIAS_LIST, GC_BACKEND_GPG }, { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "|FILE|read options from FILE", GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG }, { "default_pubkey_algo", (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE, NULL, NULL, GC_ARG_TYPE_STRING, GC_BACKEND_GPG }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, "gnupg", N_("Options useful for debugging") }, { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, "gnupg", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_GPG }, { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "gnupg", N_("|FILE|write server mode logs to FILE"), GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG }, /* { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, */ /* NULL, NULL, */ /* GC_ARG_TYPE_UINT32, GC_BACKEND_GPG }, */ { "Keyserver", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Configuration for Keyservers") }, { "keyserver", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", N_("|URL|use keyserver at URL"), GC_ARG_TYPE_STRING, GC_BACKEND_GPG }, { "allow-pka-lookup", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", N_("allow PKA lookups (DNS requests)"), GC_ARG_TYPE_NONE, GC_BACKEND_GPG }, { "auto-key-locate", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "gnupg", N_("|MECHANISMS|use MECHANISMS to locate keys by mail address"), GC_ARG_TYPE_STRING, GC_BACKEND_GPG }, GC_OPTION_NULL }; /* The options of the GC_COMPONENT_GPGSM component. */ static gc_option_t gc_options_gpgsm[] = { /* The configuration file to which we write the changes. */ { "gpgconf-gpgsm.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM }, { "Monitor", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Options controlling the diagnostic output") }, { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, "gnupg", "verbose", GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", "be somewhat more quiet", GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, NULL, NULL, GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, { "Configuration", GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, "gnupg", N_("Options controlling the configuration") }, { "default-key", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", N_("|NAME|use NAME as default secret key"), GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM }, { "encrypt-to", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", N_("|NAME|encrypt to user ID NAME as well"), GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM }, { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "|FILE|read options from FILE", GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM }, { "prefer-system-dirmngr", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "gnupg", "use system's dirmngr if available", GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, { "disable-dirmngr", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", N_("disable all access to the dirmngr"), GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, { "p12-charset", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "gnupg", N_("|NAME|use encoding NAME for PKCS#12 passphrases"), GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM }, { "keyserver", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, "gnupg", N_("|SPEC|use this keyserver to lookup keys"), GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_GPGSM }, { "default_pubkey_algo", (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE, NULL, NULL, GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, "gnupg", N_("Options useful for debugging") }, { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, "gnupg", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM }, { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "gnupg", N_("|FILE|write server mode logs to FILE"), GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM }, { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, NULL, NULL, GC_ARG_TYPE_UINT32, GC_BACKEND_GPGSM }, { "Security", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Options controlling the security") }, { "disable-crl-checks", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", "never consult a CRL", GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, { "disable-trusted-cert-crl-check", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", N_("do not check CRLs for root certificates"), GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, { "enable-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "gnupg", "check validity using OCSP", GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, { "include-certs", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "|N|number of certificates to include", GC_ARG_TYPE_INT32, GC_BACKEND_GPGSM }, { "disable-policy-checks", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "gnupg", "do not check certificate policies", GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, { "auto-issuer-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", "fetch missing issuer certificates", GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, { "cipher-algo", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "gnupg", "|NAME|use cipher algorithm NAME", GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM }, GC_OPTION_NULL }; /* The options of the GC_COMPONENT_DIRMNGR component. */ static gc_option_t gc_options_dirmngr[] = { /* The configuration file to which we write the changes. */ { "gpgconf-dirmngr.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR }, { "Monitor", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Options controlling the diagnostic output") }, { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, "dirmngr", "verbose", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "be somewhat more quiet", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, NULL, NULL, GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "Format", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Options controlling the format of the output") }, { "sh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "sh-style command output", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "csh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "csh-style command output", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "Configuration", GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, "gnupg", N_("Options controlling the configuration") }, { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "dirmngr", "|FILE|read options from FILE", GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, "gnupg", N_("Options useful for debugging") }, { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, "dirmngr", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, { "no-detach", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "do not detach from the console", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", N_("|FILE|write server mode logs to FILE"), GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR }, { "debug-wait", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, NULL, NULL, GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR }, { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, NULL, NULL, GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR }, { "Enforcement", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Options controlling the interactivity and enforcement") }, { "batch", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "run without asking a user", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "force", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "force loading of outdated CRLs", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "HTTP", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, "gnupg", N_("Configuration for HTTP servers") }, { "disable-http", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "inhibit the use of HTTP", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "ignore-http-dp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "ignore HTTP CRL distribution points", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "|URL|redirect all HTTP requests to URL", GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, { "honor-http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "gnupg", N_("use system's HTTP proxy setting"), GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "LDAP", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Configuration of LDAP servers to use") }, { "disable-ldap", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "inhibit the use of LDAP", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "ignore-ldap-dp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "ignore LDAP CRL distribution points", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "ldap-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "|HOST|use HOST for LDAP queries", GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, { "only-ldap-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "do not use fallback hosts with --ldap-proxy", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "add-servers", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "add new servers discovered in CRL distribution points" " to serverlist", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "ldaptimeout", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "|N|set LDAP timeout to N seconds", GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR }, /* The following entry must not be removed, as it is required for the GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST. */ { "ldapserverlist-file", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, "dirmngr", "|FILE|read LDAP server list from FILE", GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR }, /* This entry must come after at least one entry for GC_BACKEND_DIRMNGR in this component, so that the entry for "ldapserverlist-file will be initialized before this one. */ { "LDAP Server", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, "gnupg", N_("LDAP server list"), GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST }, { "max-replies", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "|N|do not return more than N items in one query", GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR }, { "OCSP", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, "gnupg", N_("Configuration for OCSP") }, { "allow-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "allow sending OCSP requests", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "ignore-ocsp-service-url", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "ignore certificate contained OCSP service URLs", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "ocsp-responder", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "|URL|use OCSP responder at URL", GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, { "ocsp-signer", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "|FPR|OCSP response signed by FPR", GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, GC_OPTION_NULL }; /* Component system. Each component is a set of options that can be configured at the same time. If you change this, don't forget to update GC_COMPONENT below. */ typedef enum { /* The classic GPG for OpenPGP. */ GC_COMPONENT_GPG, /* The GPG Agent. */ GC_COMPONENT_GPG_AGENT, /* The Smardcard Daemon. */ GC_COMPONENT_SCDAEMON, /* GPG for S/MIME. */ GC_COMPONENT_GPGSM, /* The LDAP Directory Manager for CRLs. */ GC_COMPONENT_DIRMNGR, /* The number of components. */ GC_COMPONENT_NR } gc_component_t; /* The information associated with each component. */ static struct { /* The name of this component. Must not contain a colon (':') character. */ const char *name; /* The gettext domain for the description DESC. If this is NULL, then the description is not translated. */ const char *desc_domain; /* The description for this domain. */ const char *desc; /* The list of options for this component, terminated by GC_OPTION_NULL. */ gc_option_t *options; } gc_component[] = { { "gpg", NULL, "GPG for OpenPGP", gc_options_gpg }, { "gpg-agent", NULL, "GPG Agent", gc_options_gpg_agent }, { "scdaemon", NULL, "Smartcard Daemon", gc_options_scdaemon }, { "gpgsm", NULL, "GPG for S/MIME", gc_options_gpgsm }, { "dirmngr", NULL, "Directory Manager", gc_options_dirmngr } }; /* Structure used to collect error output of the backend programs. */ struct error_line_s; typedef struct error_line_s *error_line_t; struct error_line_s { error_line_t next; /* Link to next item. */ const char *fname; /* Name of the config file (points into BUFFER). */ unsigned int lineno; /* Line number of the config file. */ const char *errtext; /* Text of the error message (points into BUFFER). */ char buffer[1]; /* Helper buffer. */ }; /* Engine specific support. */ static void gpg_agent_runtime_change (void) { #ifndef HAVE_W32_SYSTEM char *agent = getenv ("GPG_AGENT_INFO"); char *pid_str; unsigned long pid_long; char *tail; pid_t pid; if (!agent) return; pid_str = strchr (agent, ':'); if (!pid_str) return; pid_str++; errno = 0; pid_long = strtoul (pid_str, &tail, 0); if (errno || (*tail != ':' && *tail != '\0')) return; pid = (pid_t) pid_long; /* Check for overflow. */ if (pid_long != (unsigned long) pid) return; /* Ignore any errors here. */ kill (pid, SIGHUP); #else gpg_error_t err; const char *pgmname; const char *argv[2]; pid_t pid; pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT); argv[0] = "reloadagent"; argv[1] = NULL; err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid); if (!err) - err = gnupg_wait_process (pgmname, pid, 0, NULL); + err = gnupg_wait_process (pgmname, pid, 1, NULL); if (err) gc_error (0, 0, "error running `%s%s': %s", pgmname, " reloadagent", gpg_strerror (err)); gnupg_release_process (pid); #endif /*!HAVE_W32_SYSTEM*/ } static void scdaemon_runtime_change (void) { gpg_error_t err; const char *pgmname; const char *argv[6]; pid_t pid; /* We use "GETINFO app_running" to see whether the agent is already running and kill it only in this case. This avoids an explicit starting of the agent in case it is not yet running. There is obviously a race condition but that should not harm too much. */ pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT); argv[0] = "-s"; argv[1] = "GETINFO scd_running"; argv[2] = "/if ${! $?}"; argv[3] = "scd killscd"; argv[4] = "/end"; argv[5] = NULL; err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid); if (!err) - err = gnupg_wait_process (pgmname, pid, 0, NULL); + err = gnupg_wait_process (pgmname, pid, 1, NULL); if (err) gc_error (0, 0, "error running `%s%s': %s", pgmname, " scd killscd", gpg_strerror (err)); gnupg_release_process (pid); } /* Unconditionally reload COMPONENT or all components if COMPONENT is -1. */ void gc_component_reload (int component) { int runtime[GC_BACKEND_NR]; gc_option_t *option; gc_backend_t backend; /* Set a flag for the backends to be reloaded. */ for (backend = 0; backend < GC_BACKEND_NR; backend++) runtime[backend] = 0; if (component == -1) { for (component = 0; component < GC_COMPONENT_NR; component++) { option = gc_component[component].options; for (; option && option->name; option++) runtime[option->backend] = 1; } } else { assert (component < GC_COMPONENT_NR); option = gc_component[component].options; for (; option && option->name; option++) runtime[option->backend] = 1; } /* Do the reload for all selected backends. */ for (backend = 0; backend < GC_BACKEND_NR; backend++) { if (runtime[backend] && gc_backend[backend].runtime_change) (*gc_backend[backend].runtime_change) (); } } /* More or less Robust version of dgettext. It has the side effect of switching the codeset to utf-8 because this is what we want to output. In theory it is posible to keep the orginal code set and switch back for regular disgnostic output (redefine "_(" for that) but given the natur of this tool, being something invoked from other pograms, it does not make much sense. */ static const char * my_dgettext (const char *domain, const char *msgid) { #ifdef USE_SIMPLE_GETTEXT if (domain) { static int switched_codeset; char *text; if (!switched_codeset) { switched_codeset = 1; gettext_use_utf8 (1); } if (!strcmp (domain, "gnupg")) domain = PACKAGE_GT; /* FIXME: we have no dgettext, thus we can't switch. */ text = (char*)gettext (msgid); return text ? text : msgid; } #elif defined(ENABLE_NLS) if (domain) { static int switched_codeset; char *text; if (!switched_codeset) { switched_codeset = 1; bind_textdomain_codeset (PACKAGE_GT, "utf-8"); bindtextdomain ("dirmngr", LOCALEDIR); bind_textdomain_codeset ("dirmngr", "utf-8"); } /* Note: This is a hack to actually use the gnupg2 domain as long we are in a transition phase where gnupg 1.x and 1.9 may coexist. */ if (!strcmp (domain, "gnupg")) domain = PACKAGE_GT; text = dgettext (domain, msgid); return text ? text : msgid; } else #endif return msgid; } /* Percent-Escape special characters. The string is valid until the next invocation of the function. */ char * gc_percent_escape (const char *src) { static char *esc_str; static int esc_str_len; int new_len = 3 * strlen (src) + 1; char *dst; if (esc_str_len < new_len) { char *new_esc_str = realloc (esc_str, new_len); if (!new_esc_str) gc_error (1, errno, "can not escape string"); esc_str = new_esc_str; esc_str_len = new_len; } dst = esc_str; while (*src) { if (*src == '%') { *(dst++) = '%'; *(dst++) = '2'; *(dst++) = '5'; } else if (*src == ':') { /* The colon is used as field separator. */ *(dst++) = '%'; *(dst++) = '3'; *(dst++) = 'a'; } else if (*src == ',') { /* The comma is used as list separator. */ *(dst++) = '%'; *(dst++) = '2'; *(dst++) = 'c'; } else *(dst++) = *(src); src++; } *dst = '\0'; return esc_str; } /* Percent-Deescape special characters. The string is valid until the next invocation of the function. */ static char * percent_deescape (const char *src) { static char *str; static int str_len; int new_len = 3 * strlen (src) + 1; char *dst; if (str_len < new_len) { char *new_str = realloc (str, new_len); if (!new_str) gc_error (1, errno, "can not deescape string"); str = new_str; str_len = new_len; } dst = str; while (*src) { if (*src == '%') { int val = hextobyte (src + 1); if (val < 0) gc_error (1, 0, "malformed end of string %s", src); *(dst++) = (char) val; src += 3; } else *(dst++) = *(src++); } *dst = '\0'; return str; } /* List all components that are available. */ void gc_component_list_components (FILE *out) { gc_component_t component; gc_option_t *option; gc_backend_t backend; int backend_seen[GC_BACKEND_NR]; const char *desc; const char *pgmname; for (component = 0; component < GC_COMPONENT_NR; component++) { option = gc_component[component].options; if (option) { for (backend = 0; backend < GC_BACKEND_NR; backend++) backend_seen[backend] = 0; pgmname = ""; for (; option && option->name; option++) { if ((option->flags & GC_OPT_FLAG_GROUP)) continue; backend = option->backend; if (backend_seen[backend]) continue; backend_seen[backend] = 1; assert (backend != GC_BACKEND_ANY); if (gc_backend[backend].program && !gc_backend[backend].module_name) continue; pgmname = gnupg_module_name (gc_backend[backend].module_name); break; } desc = gc_component[component].desc; desc = my_dgettext (gc_component[component].desc_domain, desc); fprintf (out, "%s:%s:", gc_component[component].name, gc_percent_escape (desc)); fprintf (out, "%s\n", gc_percent_escape (pgmname)); } } } static int all_digits_p (const char *p, size_t len) { if (!len) return 0; /* No. */ for (; len; len--, p++) if (!isascii (*p) || !isdigit (*p)) return 0; /* No. */ return 1; /* Yes. */ } /* Collect all error lines from file descriptor FD. Only lines prefixed with TAG are considered. Close that file descriptor then. Returns a list of error line items (which may be empty). There is no error return. */ static error_line_t collect_error_output (int fd, const char *tag) { FILE *fp; char buffer[1024]; char *p, *p2, *p3; int c, cont_line; unsigned int pos; error_line_t eitem, errlines, *errlines_tail; size_t taglen = strlen (tag); fp = fdopen (fd, "r"); if (!fp) gc_error (1, errno, "can't fdopen pipe for reading"); errlines = NULL; errlines_tail = &errlines; pos = 0; cont_line = 0; while ((c=getc (fp)) != EOF) { buffer[pos++] = c; if (pos >= sizeof buffer - 5 || c == '\n') { buffer[pos - (c == '\n')] = 0; if (cont_line) ; /*Ignore continuations of previous line. */ else if (!strncmp (buffer, tag, taglen) && buffer[taglen] == ':') { /* "gpgsm: foo:4: bla" */ /* Yep, we are interested in this line. */ p = buffer + taglen + 1; while (*p == ' ' || *p == '\t') p++; if (!*p) ; /* Empty lines are ignored. */ else if ( (p2 = strchr (p, ':')) && (p3 = strchr (p2+1, ':')) && all_digits_p (p2+1, p3 - (p2+1))) { /* Line in standard compiler format. */ p3++; while (*p3 == ' ' || *p3 == '\t') p3++; eitem = xmalloc (sizeof *eitem + strlen (p)); eitem->next = NULL; strcpy (eitem->buffer, p); eitem->fname = eitem->buffer; eitem->buffer[p2-p] = 0; eitem->errtext = eitem->buffer + (p3 - p); /* (we already checked that there are only ascii digits followed by a colon) */ eitem->lineno = 0; for (p2++; isdigit (*p2); p2++) eitem->lineno = eitem->lineno*10 + (*p2 - '0'); *errlines_tail = eitem; errlines_tail = &eitem->next; } else { /* Other error output. */ eitem = xmalloc (sizeof *eitem + strlen (p)); eitem->next = NULL; strcpy (eitem->buffer, p); eitem->fname = NULL; eitem->errtext = eitem->buffer; eitem->lineno = 0; *errlines_tail = eitem; errlines_tail = &eitem->next; } } pos = 0; /* If this was not a complete line mark that we are in a continuation. */ cont_line = (c != '\n'); } } /* We ignore error lines not terminated by a LF. */ fclose (fp); return errlines; } /* Check the options of a single component. Returns 0 if everything is OK. */ int gc_component_check_options (int component, FILE *out, const char *conf_file) { gpg_error_t err; unsigned int result; int backend_seen[GC_BACKEND_NR]; gc_backend_t backend; gc_option_t *option; const char *pgmname; const char *argv[4]; int i; pid_t pid; int exitcode; int filedes[2]; error_line_t errlines; /* We use a temporary file to collect the error output. It would be better to use a pipe here but as of now we have no suitable fucntion to create a portable pipe outside of exechelp. Thus it is easier to use the tempfile approach. */ for (backend = 0; backend < GC_BACKEND_NR; backend++) backend_seen[backend] = 0; option = gc_component[component].options; for (; option && option->name; option++) { if ((option->flags & GC_OPT_FLAG_GROUP)) continue; backend = option->backend; if (backend_seen[backend]) continue; backend_seen[backend] = 1; assert (backend != GC_BACKEND_ANY); if (!gc_backend[backend].program) continue; if (!gc_backend[backend].module_name) continue; break; } if (! option || ! option->name) return 0; pgmname = gnupg_module_name (gc_backend[backend].module_name); i = 0; if (conf_file) { argv[i++] = "--options"; argv[i++] = conf_file; } argv[i++] = "--gpgconf-test"; argv[i++] = NULL; err = gnupg_create_inbound_pipe (filedes); if (err) gc_error (1, 0, _("error creating a pipe: %s\n"), gpg_strerror (err)); result = 0; errlines = NULL; if (gnupg_spawn_process_fd (pgmname, argv, -1, -1, filedes[1], &pid)) { close (filedes[0]); close (filedes[1]); result |= 1; /* Program could not be run. */ } else { close (filedes[1]); errlines = collect_error_output (filedes[0], gc_component[component].name); - if (gnupg_wait_process (pgmname, pid, 0, &exitcode)) + if (gnupg_wait_process (pgmname, pid, 1, &exitcode)) { if (exitcode == -1) result |= 1; /* Program could not be run or it terminated abnormally. */ result |= 2; /* Program returned an error. */ } gnupg_release_process (pid); } /* If the program could not be run, we can't tell whether the config file is good. */ if (result & 1) result |= 2; if (out) { const char *desc; error_line_t errptr; desc = gc_component[component].desc; desc = my_dgettext (gc_component[component].desc_domain, desc); fprintf (out, "%s:%s:", gc_component[component].name, gc_percent_escape (desc)); fputs (gc_percent_escape (pgmname), out); fprintf (out, ":%d:%d:", !(result & 1), !(result & 2)); for (errptr = errlines; errptr; errptr = errptr->next) { if (errptr != errlines) fputs ("\n:::::", out); /* Continuation line. */ if (errptr->fname) fputs (gc_percent_escape (errptr->fname), out); putc (':', out); if (errptr->fname) fprintf (out, "%u", errptr->lineno); putc (':', out); fputs (gc_percent_escape (errptr->errtext), out); putc (':', out); } putc ('\n', out); } while (errlines) { error_line_t tmp = errlines->next; xfree (errlines); errlines = tmp; } return result; } /* Check all components that are available. */ void gc_check_programs (FILE *out) { gc_component_t component; for (component = 0; component < GC_COMPONENT_NR; component++) gc_component_check_options (component, out, NULL); } /* Find the component with the name NAME. Returns -1 if not found. */ int gc_component_find (const char *name) { gc_component_t idx; for (idx = 0; idx < GC_COMPONENT_NR; idx++) { if (gc_component[idx].options && !strcmp (name, gc_component[idx].name)) return idx; } return -1; } /* List the option OPTION. */ static void list_one_option (const gc_option_t *option, FILE *out) { const char *desc = NULL; char *arg_name = NULL; if (option->desc) { desc = my_dgettext (option->desc_domain, option->desc); if (*desc == '|') { const char *arg_tail = strchr (&desc[1], '|'); if (arg_tail) { int arg_len = arg_tail - &desc[1]; arg_name = xmalloc (arg_len + 1); memcpy (arg_name, &desc[1], arg_len); arg_name[arg_len] = '\0'; desc = arg_tail + 1; } } } /* YOU MUST NOT REORDER THE FIELDS IN THIS OUTPUT, AS THEIR ORDER IS PART OF THE EXTERNAL INTERFACE. YOU MUST NOT REMOVE ANY FIELDS. */ /* The name field. */ fprintf (out, "%s", option->name); /* The flags field. */ fprintf (out, ":%lu", option->flags); if (opt.verbose) { putc (' ', out); if (!option->flags) fprintf (out, "none"); else { unsigned long flags = option->flags; unsigned long flag = 0; unsigned long first = 1; while (flags) { if (flags & 1) { if (first) first = 0; else putc (',', out); fprintf (out, "%s", gc_flag[flag].name); } flags >>= 1; flag++; } } } /* The level field. */ fprintf (out, ":%u", option->level); if (opt.verbose) fprintf (out, " %s", gc_level[option->level].name); /* The description field. */ fprintf (out, ":%s", desc ? gc_percent_escape (desc) : ""); /* The type field. */ fprintf (out, ":%u", option->arg_type); if (opt.verbose) fprintf (out, " %s", gc_arg_type[option->arg_type].name); /* The alternate type field. */ fprintf (out, ":%u", gc_arg_type[option->arg_type].fallback); if (opt.verbose) fprintf (out, " %s", gc_arg_type[gc_arg_type[option->arg_type].fallback].name); /* The argument name field. */ fprintf (out, ":%s", arg_name ? gc_percent_escape (arg_name) : ""); if (arg_name) xfree (arg_name); /* The default value field. */ fprintf (out, ":%s", option->default_value ? option->default_value : ""); /* The default argument field. */ fprintf (out, ":%s", option->default_arg ? option->default_arg : ""); /* The value field. */ if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE && (option->flags & GC_OPT_FLAG_LIST) && option->value) /* The special format "1,1,1,1,...,1" is converted to a number here. */ fprintf (out, ":%u", (unsigned int)((strlen (option->value) + 1) / 2)); else fprintf (out, ":%s", option->value ? option->value : ""); /* ADD NEW FIELDS HERE. */ putc ('\n', out); } /* List all options of the component COMPONENT. */ void gc_component_list_options (int component, FILE *out) { const gc_option_t *option = gc_component[component].options; while (option && option->name) { /* Do not output unknown or internal options. */ if (!(option->flags & GC_OPT_FLAG_GROUP) && (!option->active || option->level == GC_LEVEL_INTERNAL)) { option++; continue; } if (option->flags & GC_OPT_FLAG_GROUP) { const gc_option_t *group_option = option + 1; gc_expert_level_t level = GC_LEVEL_NR; /* The manual states that the group level is always the minimum of the levels of all contained options. Due to different active options, and because it is hard to maintain manually, we calculate it here. The value in the global static table is ignored. */ while (group_option->name) { if (group_option->flags & GC_OPT_FLAG_GROUP) break; if (group_option->level < level) level = group_option->level; group_option++; } /* Check if group is empty. */ if (level != GC_LEVEL_NR) { gc_option_t opt_copy; /* Fix up the group level. */ memcpy (&opt_copy, option, sizeof (opt_copy)); opt_copy.level = level; list_one_option (&opt_copy, out); } } else list_one_option (option, out); option++; } } /* Find the option NAME in component COMPONENT, for the backend BACKEND. If BACKEND is GC_BACKEND_ANY, any backend will match. */ static gc_option_t * find_option (gc_component_t component, const char *name, gc_backend_t backend) { gc_option_t *option = gc_component[component].options; while (option->name) { if (!(option->flags & GC_OPT_FLAG_GROUP) && !strcmp (option->name, name) && (backend == GC_BACKEND_ANY || option->backend == backend)) break; option++; } return option->name ? option : NULL; } /* Determine the configuration filename for the component COMPONENT and backend BACKEND. */ static char * get_config_filename (gc_component_t component, gc_backend_t backend) { char *filename = NULL; gc_option_t *option = find_option (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY); assert (option); assert (option->arg_type == GC_ARG_TYPE_FILENAME); assert (!(option->flags & GC_OPT_FLAG_LIST)); if (!option->active || !option->default_value) gc_error (1, 0, "Option %s, needed by backend %s, was not initialized", gc_backend[backend].option_config_filename, gc_backend[backend].name); if (option->value && *option->value) filename = percent_deescape (&option->value[1]); else if (option->default_value && *option->default_value) filename = percent_deescape (&option->default_value[1]); else filename = ""; #ifdef HAVE_DOSISH_SYSTEM if (!(filename[0] && filename[1] == ':' && (filename[2] == '/' || filename[2] == '\\'))) #else if (filename[0] != '/') #endif gc_error (1, 0, "Option %s, needed by backend %s, is not absolute", gc_backend[backend].option_config_filename, gc_backend[backend].name); return filename; } /* Retrieve the options for the component COMPONENT from backend BACKEND, which we already know is a program-type backend. */ static void retrieve_options_from_program (gc_component_t component, gc_backend_t backend) { gpg_error_t err; int filedes[2]; const char *pgmname; const char *argv[2]; int exitcode; pid_t pid; char *line = NULL; size_t line_len = 0; ssize_t length; FILE *config; char *config_filename; err = gnupg_create_inbound_pipe (filedes); if (err) gc_error (1, 0, _("error creating a pipe: %s\n"), gpg_strerror (err)); pgmname = (gc_backend[backend].module_name ? gnupg_module_name (gc_backend[backend].module_name) : gc_backend[backend].program ); argv[0] = "--gpgconf-list"; argv[1] = NULL; err = gnupg_spawn_process_fd (pgmname, argv, -1, filedes[1], -1, &pid); if (err) { close (filedes[0]); close (filedes[1]); gc_error (1, 0, "could not gather active options from `%s': %s", pgmname, gpg_strerror (err)); } close (filedes[1]); config = fdopen (filedes[0], "r"); if (!config) gc_error (1, errno, "can't fdopen pipe for reading"); while ((length = read_line (config, &line, &line_len, NULL)) > 0) { gc_option_t *option; char *linep; unsigned long flags = 0; char *default_value = NULL; /* Strip newline and carriage return, if present. */ while (length > 0 && (line[length - 1] == '\n' || line[length - 1] == '\r')) line[--length] = '\0'; linep = strchr (line, ':'); if (linep) *(linep++) = '\0'; /* Extract additional flags. Default to none. */ if (linep) { char *end; char *tail; end = strchr (linep, ':'); if (end) *(end++) = '\0'; gpg_err_set_errno (0); flags = strtoul (linep, &tail, 0); if (errno) gc_error (1, errno, "malformed flags in option %s from %s", line, pgmname); if (!(*tail == '\0' || *tail == ':' || *tail == ' ')) gc_error (1, 0, "garbage after flags in option %s from %s", line, pgmname); linep = end; } /* Extract default value, if present. Default to empty if not. */ if (linep) { char *end; end = strchr (linep, ':'); if (end) *(end++) = '\0'; if (flags & GC_OPT_FLAG_DEFAULT) default_value = linep; linep = end; } /* Look up the option in the component and install the configuration data. */ option = find_option (component, line, backend); if (option) { if (option->active) gc_error (1, errno, "option %s returned twice from %s", line, pgmname); option->active = 1; option->flags |= flags; if (default_value && *default_value) option->default_value = xstrdup (default_value); } } if (length < 0 || ferror (config)) gc_error (1, errno, "error reading from %s",pgmname); if (fclose (config) && ferror (config)) gc_error (1, errno, "error closing %s", pgmname); - err = gnupg_wait_process (pgmname, pid, 0, &exitcode); + err = gnupg_wait_process (pgmname, pid, 1, &exitcode); if (err) gc_error (1, 0, "running %s failed (exitcode=%d): %s", pgmname, exitcode, gpg_strerror (err)); gnupg_release_process (pid); /* At this point, we can parse the configuration file. */ config_filename = get_config_filename (component, backend); config = fopen (config_filename, "r"); if (!config) gc_error (0, errno, "warning: can not open config file %s", config_filename); else { while ((length = read_line (config, &line, &line_len, NULL)) > 0) { char *name; char *value; gc_option_t *option; name = line; while (*name == ' ' || *name == '\t') name++; if (!*name || *name == '#' || *name == '\r' || *name == '\n') continue; value = name; while (*value && *value != ' ' && *value != '\t' && *value != '#' && *value != '\r' && *value != '\n') value++; if (*value == ' ' || *value == '\t') { char *end; *(value++) = '\0'; while (*value == ' ' || *value == '\t') value++; end = value; while (*end && *end != '#' && *end != '\r' && *end != '\n') end++; while (end > value && (end[-1] == ' ' || end[-1] == '\t')) end--; *end = '\0'; } else *value = '\0'; /* Look up the option in the component and install the configuration data. */ option = find_option (component, line, backend); if (option) { char *opt_value; if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE) { if (*value) gc_error (0, 0, "warning: ignoring argument %s for option %s", value, name); opt_value = xstrdup ("1"); } else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING) opt_value = xasprintf ("\"%s", gc_percent_escape (value)); else { /* FIXME: Verify that the number is sane. */ opt_value = xstrdup (value); } /* Now enter the option into the table. */ if (!(option->flags & GC_OPT_FLAG_LIST)) { if (option->value) free (option->value); option->value = opt_value; } else { if (!option->value) option->value = opt_value; else { char *opt_val = opt_value; option->value = xasprintf ("%s,%s", option->value, opt_val); xfree (opt_value); } } } } if (length < 0 || ferror (config)) gc_error (1, errno, "error reading from %s", config_filename); if (fclose (config) && ferror (config)) gc_error (1, errno, "error closing %s", config_filename); } xfree (line); } /* Retrieve the options for the component COMPONENT from backend BACKEND, which we already know is of type file list. */ static void retrieve_options_from_file (gc_component_t component, gc_backend_t backend) { gc_option_t *list_option; gc_option_t *config_option; char *list_filename; FILE *list_file; char *line = NULL; size_t line_len = 0; ssize_t length; char *list = NULL; list_option = find_option (component, gc_backend[backend].option_name, GC_BACKEND_ANY); assert (list_option); assert (!list_option->active); list_filename = get_config_filename (component, backend); list_file = fopen (list_filename, "r"); if (!list_file) gc_error (0, errno, "warning: can not open list file %s", list_filename); else { while ((length = read_line (list_file, &line, &line_len, NULL)) > 0) { char *start; char *end; char *new_list; start = line; while (*start == ' ' || *start == '\t') start++; if (!*start || *start == '#' || *start == '\r' || *start == '\n') continue; end = start; while (*end && *end != '#' && *end != '\r' && *end != '\n') end++; /* Walk back to skip trailing white spaces. Looks evil, but works because of the conditions on START and END imposed at this point (END is at least START + 1, and START is not a whitespace character). */ while (*(end - 1) == ' ' || *(end - 1) == '\t') end--; *end = '\0'; /* FIXME: Oh, no! This is so lame! Should use realloc and really append. */ if (list) { new_list = xasprintf ("%s,\"%s", list, gc_percent_escape (start)); xfree (list); list = new_list; } else list = xasprintf ("\"%s", gc_percent_escape (start)); } if (length < 0 || ferror (list_file)) gc_error (1, errno, "can not read list file %s", list_filename); } list_option->active = 1; list_option->value = list; /* Fix up the read-only flag. */ config_option = find_option (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY); if (config_option->flags & GC_OPT_FLAG_NO_CHANGE) list_option->flags |= GC_OPT_FLAG_NO_CHANGE; if (list_file && fclose (list_file) && ferror (list_file)) gc_error (1, errno, "error closing %s", list_filename); xfree (line); } /* Retrieve the currently active options and their defaults from all involved backends for this component. Using -1 for component will retrieve all options from all components. */ void gc_component_retrieve_options (int component) { int process_all = 0; int backend_seen[GC_BACKEND_NR]; gc_backend_t backend; gc_option_t *option; for (backend = 0; backend < GC_BACKEND_NR; backend++) backend_seen[backend] = 0; if (component == -1) { process_all = 1; component = 0; assert (component < GC_COMPONENT_NR); } do { option = gc_component[component].options; while (option && option->name) { if (!(option->flags & GC_OPT_FLAG_GROUP)) { backend = option->backend; if (backend_seen[backend]) { option++; continue; } backend_seen[backend] = 1; assert (backend != GC_BACKEND_ANY); if (gc_backend[backend].program) retrieve_options_from_program (component, backend); else retrieve_options_from_file (component, backend); } option++; } } while (process_all && ++component < GC_COMPONENT_NR); } /* Perform a simple validity check based on the type. Return in NEW_VALUE_NR the value of the number in NEW_VALUE if OPTION is of type GC_ARG_TYPE_NONE. */ static void option_check_validity (gc_option_t *option, unsigned long flags, char *new_value, unsigned long *new_value_nr) { char *arg; if (!option->active) gc_error (1, 0, "option %s not supported by backend %s", option->name, gc_backend[option->backend].name); if (option->new_flags || option->new_value) gc_error (1, 0, "option %s already changed", option->name); if (flags & GC_OPT_FLAG_DEFAULT) { if (*new_value) gc_error (1, 0, "argument %s provided for deleted option %s", new_value, option->name); return; } /* GC_ARG_TYPE_NONE options have special list treatment. */ if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE) { char *tail; gpg_err_set_errno (0); *new_value_nr = strtoul (new_value, &tail, 0); if (errno) gc_error (1, errno, "invalid argument for option %s", option->name); if (*tail) gc_error (1, 0, "garbage after argument for option %s", option->name); if (!(option->flags & GC_OPT_FLAG_LIST)) { if (*new_value_nr != 1) gc_error (1, 0, "argument for non-list option %s of type 0 " "(none) must be 1", option->name); } else { if (*new_value_nr == 0) gc_error (1, 0, "argument for option %s of type 0 (none) " "must be positive", option->name); } return; } arg = new_value; do { if (*arg == '\0' || *arg == ',') { if (!(option->flags & GC_OPT_FLAG_ARG_OPT)) gc_error (1, 0, "argument required for option %s", option->name); if (*arg == ',' && !(option->flags & GC_OPT_FLAG_LIST)) gc_error (1, 0, "list found for non-list option %s", option->name); } else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING) { if (*arg != '"') gc_error (1, 0, "string argument for option %s must begin " "with a quote (\") character", option->name); /* FIXME: We do not allow empty string arguments for now, as we do not quote arguments in configuration files, and thus no argument is indistinguishable from the empty string. */ if (arg[1] == '\0' || arg[1] == ',') gc_error (1, 0, "empty string argument for option %s is " "currently not allowed. Please report this!", option->name); } else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32) { long res; gpg_err_set_errno (0); res = strtol (arg, &arg, 0); (void) res; if (errno) gc_error (1, errno, "invalid argument for option %s", option->name); if (*arg != '\0' && *arg != ',') gc_error (1, 0, "garbage after argument for option %s", option->name); } else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32) { unsigned long res; gpg_err_set_errno (0); res = strtoul (arg, &arg, 0); (void) res; if (errno) gc_error (1, errno, "invalid argument for option %s", option->name); if (*arg != '\0' && *arg != ',') gc_error (1, 0, "garbage after argument for option %s", option->name); } arg = strchr (arg, ','); if (arg) arg++; } while (arg && *arg); } #ifdef HAVE_W32_SYSTEM int copy_file (const char *src_name, const char *dst_name) { #define BUF_LEN 4096 char buffer[BUF_LEN]; int len; FILE *src; FILE *dst; src = fopen (src_name, "r"); if (src == NULL) return -1; dst = fopen (dst_name, "w"); if (dst == NULL) { int saved_err = errno; fclose (src); gpg_err_set_errno (saved_err); return -1; } do { int written; len = fread (buffer, 1, BUF_LEN, src); if (len == 0) break; written = fwrite (buffer, 1, len, dst); if (written != len) break; } while (!feof (src) && !ferror (src) && !ferror (dst)); if (ferror (src) || ferror (dst) || !feof (src)) { int saved_errno = errno; fclose (src); fclose (dst); unlink (dst_name); gpg_err_set_errno (saved_errno); return -1; } if (fclose (dst) && ferror (dst)) gc_error (1, errno, "error closing %s", dst_name); if (fclose (src) && ferror (src)) gc_error (1, errno, "error closing %s", src_name); return 0; } #endif /* HAVE_W32_SYSTEM */ /* Create and verify the new configuration file for the specified backend and component. Returns 0 on success and -1 on error. */ static int change_options_file (gc_component_t component, gc_backend_t backend, char **src_filenamep, char **dest_filenamep, char **orig_filenamep) { static const char marker[] = "###+++--- GPGConf ---+++###"; /* True if we are within the marker in the config file. */ int in_marker = 0; gc_option_t *option; char *line = NULL; size_t line_len; ssize_t length; int res; int fd; FILE *src_file = NULL; FILE *dest_file = NULL; char *src_filename; char *dest_filename; char *orig_filename; char *arg; char *cur_arg = NULL; option = find_option (component, gc_backend[backend].option_name, GC_BACKEND_ANY); assert (option); assert (option->active); assert (gc_arg_type[option->arg_type].fallback != GC_ARG_TYPE_NONE); /* FIXME. Throughout the function, do better error reporting. */ /* Note that get_config_filename() calls percent_deescape(), so we call this before processing the arguments. */ dest_filename = xstrdup (get_config_filename (component, backend)); src_filename = xasprintf ("%s.gpgconf.%i.new", dest_filename, (int)getpid ()); orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename,(int)getpid ()); arg = option->new_value; if (arg && arg[0] == '\0') arg = NULL; else if (arg) { char *end; arg++; end = strchr (arg, ','); if (end) *end = '\0'; cur_arg = percent_deescape (arg); if (end) { *end = ','; arg = end + 1; } else arg = NULL; } #ifdef HAVE_W32_SYSTEM res = copy_file (dest_filename, orig_filename); #else res = link (dest_filename, orig_filename); #endif if (res < 0 && errno != ENOENT) return -1; if (res < 0) { xfree (orig_filename); orig_filename = NULL; } /* We now initialize the return strings, so the caller can do the cleanup for us. */ *src_filenamep = src_filename; *dest_filenamep = dest_filename; *orig_filenamep = orig_filename; /* Use open() so that we can use O_EXCL. */ fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644); if (fd < 0) return -1; src_file = fdopen (fd, "w"); res = errno; if (!src_file) { gpg_err_set_errno (res); return -1; } /* Only if ORIG_FILENAME is not NULL did the configuration file exist already. In this case, we will copy its content into the new configuration file, changing it to our liking in the process. */ if (orig_filename) { dest_file = fopen (dest_filename, "r"); if (!dest_file) goto change_file_one_err; while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0) { int disable = 0; char *start; if (!strncmp (marker, line, sizeof (marker) - 1)) { if (!in_marker) in_marker = 1; else break; } start = line; while (*start == ' ' || *start == '\t') start++; if (*start && *start != '\r' && *start != '\n' && *start != '#') { char *end; char *endp; char saved_end; endp = start; end = endp; /* Search for the end of the line. */ while (*endp && *endp != '#' && *endp != '\r' && *endp != '\n') { endp++; if (*endp && *endp != ' ' && *endp != '\t' && *endp != '\r' && *endp != '\n' && *endp != '#') end = endp + 1; } saved_end = *end; *end = '\0'; if ((option->new_flags & GC_OPT_FLAG_DEFAULT) || !cur_arg || strcmp (start, cur_arg)) disable = 1; else { /* Find next argument. */ if (arg) { char *arg_end; arg++; arg_end = strchr (arg, ','); if (arg_end) *arg_end = '\0'; cur_arg = percent_deescape (arg); if (arg_end) { *arg_end = ','; arg = arg_end + 1; } else arg = NULL; } else cur_arg = NULL; } *end = saved_end; } if (disable) { if (!in_marker) { fprintf (src_file, "# GPGConf disabled this option here at %s\n", asctimestamp (gnupg_get_time ())); if (ferror (src_file)) goto change_file_one_err; fprintf (src_file, "# %s", line); if (ferror (src_file)) goto change_file_one_err; } } else { fprintf (src_file, "%s", line); if (ferror (src_file)) goto change_file_one_err; } } if (length < 0 || ferror (dest_file)) goto change_file_one_err; } if (!in_marker) { /* There was no marker. This is the first time we edit the file. We add our own marker at the end of the file and proceed. Note that we first write a newline, this guards us against files which lack the newline at the end of the last line, while it doesn't hurt us in all other cases. */ fprintf (src_file, "\n%s\n", marker); if (ferror (src_file)) goto change_file_one_err; } /* At this point, we have copied everything up to the end marker into the new file, except for the arguments we are going to add. Now, dump the new arguments and write the end marker, possibly followed by the rest of the original file. */ while (cur_arg) { fprintf (src_file, "%s\n", cur_arg); /* Find next argument. */ if (arg) { char *end; arg++; end = strchr (arg, ','); if (end) *end = '\0'; cur_arg = percent_deescape (arg); if (end) { *end = ','; arg = end + 1; } else arg = NULL; } else cur_arg = NULL; } fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ())); if (ferror (src_file)) goto change_file_one_err; if (!in_marker) { fprintf (src_file, "# GPGConf edited this configuration file.\n"); if (ferror (src_file)) goto change_file_one_err; fprintf (src_file, "# It will disable options before this marked " "block, but it will\n"); if (ferror (src_file)) goto change_file_one_err; fprintf (src_file, "# never change anything below these lines.\n"); if (ferror (src_file)) goto change_file_one_err; } if (dest_file) { while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0) { fprintf (src_file, "%s", line); if (ferror (src_file)) goto change_file_one_err; } if (length < 0 || ferror (dest_file)) goto change_file_one_err; } xfree (line); line = NULL; res = fclose (src_file); if (res) { res = errno; close (fd); if (dest_file) fclose (dest_file); gpg_err_set_errno (res); return -1; } close (fd); if (dest_file) { res = fclose (dest_file); if (res) return -1; } return 0; change_file_one_err: xfree (line); res = errno; if (src_file) { fclose (src_file); close (fd); } if (dest_file) fclose (dest_file); gpg_err_set_errno (res); return -1; } /* Create and verify the new configuration file for the specified backend and component. Returns 0 on success and -1 on error. */ static int change_options_program (gc_component_t component, gc_backend_t backend, char **src_filenamep, char **dest_filenamep, char **orig_filenamep) { static const char marker[] = "###+++--- GPGConf ---+++###"; /* True if we are within the marker in the config file. */ int in_marker = 0; gc_option_t *option; char *line = NULL; size_t line_len; ssize_t length; int res; int fd; FILE *src_file = NULL; FILE *dest_file = NULL; char *src_filename; char *dest_filename; char *orig_filename; /* Special hack for gpg, see below. */ int utf8strings_seen = 0; /* FIXME. Throughout the function, do better error reporting. */ dest_filename = xstrdup (get_config_filename (component, backend)); src_filename = xasprintf ("%s.gpgconf.%i.new", dest_filename, (int)getpid ()); orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename,(int)getpid ()); #ifdef HAVE_W32_SYSTEM res = copy_file (dest_filename, orig_filename); #else res = link (dest_filename, orig_filename); #endif if (res < 0 && errno != ENOENT) return -1; if (res < 0) { xfree (orig_filename); orig_filename = NULL; } /* We now initialize the return strings, so the caller can do the cleanup for us. */ *src_filenamep = src_filename; *dest_filenamep = dest_filename; *orig_filenamep = orig_filename; /* Use open() so that we can use O_EXCL. */ fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644); if (fd < 0) return -1; src_file = fdopen (fd, "w"); res = errno; if (!src_file) { gpg_err_set_errno (res); return -1; } /* Only if ORIG_FILENAME is not NULL did the configuration file exist already. In this case, we will copy its content into the new configuration file, changing it to our liking in the process. */ if (orig_filename) { dest_file = fopen (dest_filename, "r"); if (!dest_file) goto change_one_err; while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0) { int disable = 0; char *start; if (!strncmp (marker, line, sizeof (marker) - 1)) { if (!in_marker) in_marker = 1; else break; } else if (backend == GC_BACKEND_GPG && in_marker && ! strcmp ("utf8-strings\n", line)) { /* Strip duplicated entries. */ if (utf8strings_seen) disable = 1; else utf8strings_seen = 1; } start = line; while (*start == ' ' || *start == '\t') start++; if (*start && *start != '\r' && *start != '\n' && *start != '#') { char *end; char saved_end; end = start; while (*end && *end != ' ' && *end != '\t' && *end != '\r' && *end != '\n' && *end != '#') end++; saved_end = *end; *end = '\0'; option = find_option (component, start, backend); *end = saved_end; if (option && ((option->new_flags & GC_OPT_FLAG_DEFAULT) || option->new_value)) disable = 1; } if (disable) { if (!in_marker) { fprintf (src_file, "# GPGConf disabled this option here at %s\n", asctimestamp (gnupg_get_time ())); if (ferror (src_file)) goto change_one_err; fprintf (src_file, "# %s", line); if (ferror (src_file)) goto change_one_err; } } else { fprintf (src_file, "%s", line); if (ferror (src_file)) goto change_one_err; } } if (length < 0 || ferror (dest_file)) goto change_one_err; } if (!in_marker) { /* There was no marker. This is the first time we edit the file. We add our own marker at the end of the file and proceed. Note that we first write a newline, this guards us against files which lack the newline at the end of the last line, while it doesn't hurt us in all other cases. */ fprintf (src_file, "\n%s\n", marker); if (ferror (src_file)) goto change_one_err; } /* At this point, we have copied everything up to the end marker into the new file, except for the options we are going to change. Now, dump the changed options (except for those we are going to revert to their default), and write the end marker, possibly followed by the rest of the original file. */ /* We have to turn on UTF8 strings for GnuPG. */ if (backend == GC_BACKEND_GPG && ! utf8strings_seen) fprintf (src_file, "utf8-strings\n"); option = gc_component[component].options; while (option->name) { if (!(option->flags & GC_OPT_FLAG_GROUP) && option->backend == backend && option->new_value) { char *arg = option->new_value; do { if (*arg == '\0' || *arg == ',') { fprintf (src_file, "%s\n", option->name); if (ferror (src_file)) goto change_one_err; } else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE) { assert (*arg == '1'); fprintf (src_file, "%s\n", option->name); if (ferror (src_file)) goto change_one_err; arg++; } else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING) { char *end; assert (*arg == '"'); arg++; end = strchr (arg, ','); if (end) *end = '\0'; fprintf (src_file, "%s %s\n", option->name, percent_deescape (arg)); if (ferror (src_file)) goto change_one_err; if (end) *end = ','; arg = end; } else { char *end; end = strchr (arg, ','); if (end) *end = '\0'; fprintf (src_file, "%s %s\n", option->name, arg); if (ferror (src_file)) goto change_one_err; if (end) *end = ','; arg = end; } assert (arg == NULL || *arg == '\0' || *arg == ','); if (arg && *arg == ',') arg++; } while (arg && *arg); } option++; } fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ())); if (ferror (src_file)) goto change_one_err; if (!in_marker) { fprintf (src_file, "# GPGConf edited this configuration file.\n"); if (ferror (src_file)) goto change_one_err; fprintf (src_file, "# It will disable options before this marked " "block, but it will\n"); if (ferror (src_file)) goto change_one_err; fprintf (src_file, "# never change anything below these lines.\n"); if (ferror (src_file)) goto change_one_err; } if (dest_file) { while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0) { fprintf (src_file, "%s", line); if (ferror (src_file)) goto change_one_err; } if (length < 0 || ferror (dest_file)) goto change_one_err; } xfree (line); line = NULL; res = fclose (src_file); if (res) { res = errno; close (fd); if (dest_file) fclose (dest_file); gpg_err_set_errno (res); return -1; } close (fd); if (dest_file) { res = fclose (dest_file); if (res) return -1; } return 0; change_one_err: xfree (line); res = errno; if (src_file) { fclose (src_file); close (fd); } if (dest_file) fclose (dest_file); gpg_err_set_errno (res); return -1; } /* Common code for gc_component_change_options and gc_process_gpgconf_conf. */ static void change_one_value (gc_option_t *option, int *runtime, unsigned long flags, char *new_value) { unsigned long new_value_nr = 0; option_check_validity (option, flags, new_value, &new_value_nr); if (option->flags & GC_OPT_FLAG_RUNTIME) runtime[option->backend] = 1; option->new_flags = flags; if (!(flags & GC_OPT_FLAG_DEFAULT)) { if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE && (option->flags & GC_OPT_FLAG_LIST)) { char *str; /* We convert the number to a list of 1's for convenient list handling. */ assert (new_value_nr > 0); option->new_value = xmalloc ((2 * (new_value_nr - 1) + 1) + 1); str = option->new_value; *(str++) = '1'; while (--new_value_nr > 0) { *(str++) = ','; *(str++) = '1'; } *(str++) = '\0'; } else option->new_value = xstrdup (new_value); } } /* Read the modifications from IN and apply them. If IN is NULL the modifications are expected to already have been set to the global table. */ void gc_component_change_options (int component, FILE *in, FILE *out) { int err = 0; int runtime[GC_BACKEND_NR]; char *src_filename[GC_BACKEND_NR]; char *dest_filename[GC_BACKEND_NR]; char *orig_filename[GC_BACKEND_NR]; gc_backend_t backend; gc_option_t *option; char *line = NULL; size_t line_len = 0; ssize_t length; for (backend = 0; backend < GC_BACKEND_NR; backend++) { runtime[backend] = 0; src_filename[backend] = NULL; dest_filename[backend] = NULL; orig_filename[backend] = NULL; } if (in) { /* Read options from the file IN. */ while ((length = read_line (in, &line, &line_len, NULL)) > 0) { char *linep; unsigned long flags = 0; char *new_value = ""; /* Strip newline and carriage return, if present. */ while (length > 0 && (line[length - 1] == '\n' || line[length - 1] == '\r')) line[--length] = '\0'; linep = strchr (line, ':'); if (linep) *(linep++) = '\0'; /* Extract additional flags. Default to none. */ if (linep) { char *end; char *tail; end = strchr (linep, ':'); if (end) *(end++) = '\0'; gpg_err_set_errno (0); flags = strtoul (linep, &tail, 0); if (errno) gc_error (1, errno, "malformed flags in option %s", line); if (!(*tail == '\0' || *tail == ':' || *tail == ' ')) gc_error (1, 0, "garbage after flags in option %s", line); linep = end; } /* Don't allow setting of the no change flag. */ flags &= ~GC_OPT_FLAG_NO_CHANGE; /* Extract default value, if present. Default to empty if not. */ if (linep) { char *end; end = strchr (linep, ':'); if (end) *(end++) = '\0'; new_value = linep; linep = end; } option = find_option (component, line, GC_BACKEND_ANY); if (!option) gc_error (1, 0, "unknown option %s", line); if ((option->flags & GC_OPT_FLAG_NO_CHANGE)) { gc_error (0, 0, "ignoring new value for option %s", option->name); continue; } change_one_value (option, runtime, flags, new_value); } } /* Now that we have collected and locally verified the changes, write them out to new configuration files, verify them externally, and then commit them. */ option = gc_component[component].options; while (option && option->name) { /* Go on if we have already seen this backend, or if there is nothing to do. */ if (src_filename[option->backend] || !(option->new_flags || option->new_value)) { option++; continue; } if (gc_backend[option->backend].program) { err = change_options_program (component, option->backend, &src_filename[option->backend], &dest_filename[option->backend], &orig_filename[option->backend]); if (! err) { /* External verification. */ err = gc_component_check_options (component, out, src_filename[option->backend]); if (err) { gc_error (0, 0, _("External verification of component %s failed"), gc_component[component].name); gpg_err_set_errno (EINVAL); } } } else err = change_options_file (component, option->backend, &src_filename[option->backend], &dest_filename[option->backend], &orig_filename[option->backend]); if (err) break; option++; } if (! err && ! opt.dry_run) { int i; for (i = 0; i < GC_BACKEND_NR; i++) { if (src_filename[i]) { /* FIXME: Make a verification here. */ assert (dest_filename[i]); if (orig_filename[i]) { #ifdef HAVE_W32_SYSTEM /* There is no atomic update on W32. */ err = unlink (dest_filename[i]); #endif /* HAVE_W32_SYSTEM */ if (!err) err = rename (src_filename[i], dest_filename[i]); } else { #ifdef HAVE_W32_SYSTEM /* We skip the unlink if we expect the file not to be there. */ err = rename (src_filename[i], dest_filename[i]); #else /* HAVE_W32_SYSTEM */ /* This is a bit safer than rename() because we expect DEST_FILENAME not to be there. If it happens to be there, this will fail. */ err = link (src_filename[i], dest_filename[i]); if (!err) err = unlink (src_filename[i]); #endif /* !HAVE_W32_SYSTEM */ } if (err) break; src_filename[i] = NULL; } } } if (err || opt.dry_run) { int i; int saved_errno = errno; /* An error occured or a dry-run is requested. */ for (i = 0; i < GC_BACKEND_NR; i++) { if (src_filename[i]) { /* The change was not yet committed. */ unlink (src_filename[i]); if (orig_filename[i]) unlink (orig_filename[i]); } else { /* The changes were already committed. FIXME: This is a tad dangerous, as we don't know if we don't overwrite a version of the file that is even newer than the one we just installed. */ if (orig_filename[i]) { #ifdef HAVE_W32_SYSTEM /* There is no atomic update on W32. */ unlink (dest_filename[i]); #endif /* HAVE_W32_SYSTEM */ rename (orig_filename[i], dest_filename[i]); } else unlink (dest_filename[i]); } } if (err) gc_error (1, saved_errno, "could not commit changes"); /* Fall-through for dry run. */ goto leave; } /* If it all worked, notify the daemons of the changes. */ if (opt.runtime) for (backend = 0; backend < GC_BACKEND_NR; backend++) { if (runtime[backend] && gc_backend[backend].runtime_change) (*gc_backend[backend].runtime_change) (); } /* Move the per-process backup file into its place. */ for (backend = 0; backend < GC_BACKEND_NR; backend++) if (orig_filename[backend]) { char *backup_filename; assert (dest_filename[backend]); backup_filename = xasprintf ("%s.gpgconf.bak", dest_filename[backend]); #ifdef HAVE_W32_SYSTEM /* There is no atomic update on W32. */ unlink (backup_filename); #endif /* HAVE_W32_SYSTEM */ rename (orig_filename[backend], backup_filename); } leave: xfree (line); } /* Check whether USER matches the current user of one of its group. This function may change USER. Returns true is there is a match. */ static int key_matches_user_or_group (char *user) { char *group; if (*user == '*' && user[1] == 0) return 1; /* A single asterisk matches all users. */ group = strchr (user, ':'); if (group) *group++ = 0; #ifdef HAVE_W32_SYSTEM /* Under Windows we don't support groups. */ if (group && *group) gc_error (0, 0, _("Note that group specifications are ignored\n")); #ifndef HAVE_W32CE_SYSTEM if (*user) { static char *my_name; if (!my_name) { char tmp[1]; DWORD size = 1; GetUserNameA (tmp, &size); my_name = xmalloc (size); if (!GetUserNameA (my_name, &size)) gc_error (1,0, "error getting current user name: %s", w32_strerror (-1)); } if (!strcmp (user, my_name)) return 1; /* Found. */ } #endif /*HAVE_W32CE_SYSTEM*/ #else /*!HAVE_W32_SYSTEM*/ /* First check whether the user matches. */ if (*user) { static char *my_name; if (!my_name) { struct passwd *pw = getpwuid ( getuid () ); if (!pw) gc_error (1, errno, "getpwuid failed for current user"); my_name = xstrdup (pw->pw_name); } if (!strcmp (user, my_name)) return 1; /* Found. */ } /* If that failed, check whether a group matches. */ if (group && *group) { static char *my_group; static char **my_supgroups; int n; if (!my_group) { struct group *gr = getgrgid ( getgid () ); if (!gr) gc_error (1, errno, "getgrgid failed for current user"); my_group = xstrdup (gr->gr_name); } if (!strcmp (group, my_group)) return 1; /* Found. */ if (!my_supgroups) { int ngids; gid_t *gids; ngids = getgroups (0, NULL); gids = xcalloc (ngids+1, sizeof *gids); ngids = getgroups (ngids, gids); if (ngids < 0) gc_error (1, errno, "getgroups failed for current user"); my_supgroups = xcalloc (ngids+1, sizeof *my_supgroups); for (n=0; n < ngids; n++) { struct group *gr = getgrgid ( gids[n] ); if (!gr) gc_error (1, errno, "getgrgid failed for supplementary group"); my_supgroups[n] = xstrdup (gr->gr_name); } xfree (gids); } for (n=0; my_supgroups[n]; n++) if (!strcmp (group, my_supgroups[n])) return 1; /* Found. */ } #endif /*!HAVE_W32_SYSTEM*/ return 0; /* No match. */ } /* Read and process the global configuration file for gpgconf. This optional file is used to update our internal tables at runtime and may also be used to set new default values. If FNAME is NULL the default name will be used. With UPDATE set to true the internal tables are actually updated; if not set, only a syntax check is done. If DEFAULTS is true the global options are written to the configuration files. If LISTFP is set, no changes are done but the configuration file is printed to LISTFP in a colon separated format. Returns 0 on success or if the config file is not present; -1 is returned on error. */ int gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults, FILE *listfp) { int result = 0; char *line = NULL; size_t line_len = 0; ssize_t length; FILE *config; int lineno = 0; int in_rule = 0; int got_match = 0; int runtime[GC_BACKEND_NR]; int used_components[GC_COMPONENT_NR]; int backend_id, component_id; char *fname; if (fname_arg) fname = xstrdup (fname_arg); else fname = make_filename (gnupg_sysconfdir (), "gpgconf.conf", NULL); for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++) runtime[backend_id] = 0; for (component_id = 0; component_id < GC_COMPONENT_NR; component_id++) used_components[component_id] = 0; config = fopen (fname, "r"); if (!config) { /* Do not print an error if the file is not available, except when running in syntax check mode. */ if (errno != ENOENT || !update) { gc_error (0, errno, "can not open global config file `%s'", fname); result = -1; } xfree (fname); return result; } while ((length = read_line (config, &line, &line_len, NULL)) > 0) { char *key, *component, *option, *flags, *value; char *empty; gc_option_t *option_info = NULL; char *p; int is_continuation; lineno++; key = line; while (*key == ' ' || *key == '\t') key++; if (!*key || *key == '#' || *key == '\r' || *key == '\n') continue; is_continuation = (key != line); /* Parse the key field. */ if (!is_continuation && got_match) break; /* Finish after the first match. */ else if (!is_continuation) { in_rule = 0; for (p=key+1; *p && !strchr (" \t\r\n", *p); p++) ; if (!*p) { gc_error (0, 0, "missing rule at `%s', line %d", fname, lineno); result = -1; continue; } *p++ = 0; component = p; } else if (!in_rule) { gc_error (0, 0, "continuation but no rule at `%s', line %d", fname, lineno); result = -1; continue; } else { component = key; key = NULL; } in_rule = 1; /* Parse the component. */ while (*component == ' ' || *component == '\t') component++; for (p=component; *p && !strchr (" \t\r\n", *p); p++) ; if (p == component) { gc_error (0, 0, "missing component at `%s', line %d", fname, lineno); result = -1; continue; } empty = p; *p++ = 0; option = p; component_id = gc_component_find (component); if (component_id < 0) { gc_error (0, 0, "unknown component at `%s', line %d", fname, lineno); result = -1; } /* Parse the option name. */ while (*option == ' ' || *option == '\t') option++; for (p=option; *p && !strchr (" \t\r\n", *p); p++) ; if (p == option) { gc_error (0, 0, "missing option at `%s', line %d", fname, lineno); result = -1; continue; } *p++ = 0; flags = p; if ( component_id != -1) { option_info = find_option (component_id, option, GC_BACKEND_ANY); if (!option_info) { gc_error (0, 0, "unknown option at `%s', line %d", fname, lineno); result = -1; } } /* Parse the optional flags. */ while (*flags == ' ' || *flags == '\t') flags++; if (*flags == '[') { flags++; p = strchr (flags, ']'); if (!p) { gc_error (0, 0, "syntax error in rule at `%s', line %d", fname, lineno); result = -1; continue; } *p++ = 0; value = p; } else /* No flags given. */ { value = flags; flags = NULL; } /* Parse the optional value. */ while (*value == ' ' || *value == '\t') value++; for (p=value; *p && !strchr ("\r\n", *p); p++) ; if (p == value) value = empty; /* No value given; let it point to an empty string. */ else { /* Strip trailing white space. */ *p = 0; for (p--; p > value && (*p == ' ' || *p == '\t'); p--) *p = 0; } /* Check flag combinations. */ if (!flags) ; else if (!strcmp (flags, "default")) { if (*value) { gc_error (0, 0, "flag \"default\" may not be combined " "with a value at `%s', line %d", fname, lineno); result = -1; } } else if (!strcmp (flags, "change")) ; else if (!strcmp (flags, "no-change")) ; else { gc_error (0, 0, "unknown flag at `%s', line %d", fname, lineno); result = -1; } /* In list mode we print out all records. */ if (listfp && !result) { /* If this is a new ruleset, print a key record. */ if (!is_continuation) { char *group = strchr (key, ':'); if (group) { *group++ = 0; if ((p = strchr (group, ':'))) *p = 0; /* We better strip any extra stuff. */ } fprintf (listfp, "k:%s:", gc_percent_escape (key)); fprintf (listfp, "%s\n", group? gc_percent_escape (group):""); } /* All other lines are rule records. */ fprintf (listfp, "r:::%s:%s:%s:", gc_component[component_id].name, option_info->name? option_info->name : "", flags? flags : ""); if (value != empty) fprintf (listfp, "\"%s", gc_percent_escape (value)); putc ('\n', listfp); } /* Check whether the key matches but do this only if we are not running in syntax check mode. */ if ( update && !result && !listfp && (got_match || (key && key_matches_user_or_group (key))) ) { int newflags = 0; got_match = 1; /* Apply the flags from gpgconf.conf. */ if (!flags) ; else if (!strcmp (flags, "default")) newflags |= GC_OPT_FLAG_DEFAULT; else if (!strcmp (flags, "no-change")) option_info->flags |= GC_OPT_FLAG_NO_CHANGE; else if (!strcmp (flags, "change")) option_info->flags &= ~GC_OPT_FLAG_NO_CHANGE; if (defaults) { assert (component_id >= 0 && component_id < GC_COMPONENT_NR); used_components[component_id] = 1; /* Here we explicitly allow to update the value again. */ if (newflags) { option_info->new_flags = 0; } if (*value) { xfree (option_info->new_value); option_info->new_value = NULL; } change_one_value (option_info, runtime, newflags, value); } } } if (length < 0 || ferror (config)) { gc_error (0, errno, "error reading from `%s'", fname); result = -1; } if (fclose (config) && ferror (config)) gc_error (0, errno, "error closing `%s'", fname); xfree (line); /* If it all worked, process the options. */ if (!result && update && defaults && !listfp) { /* We need to switch off the runtime update, so that we can do it later all at once. */ int save_opt_runtime = opt.runtime; opt.runtime = 0; for (component_id = 0; component_id < GC_COMPONENT_NR; component_id++) { gc_component_change_options (component_id, NULL, NULL); } opt.runtime = save_opt_runtime; if (opt.runtime) { for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++) if (runtime[backend_id] && gc_backend[backend_id].runtime_change) (*gc_backend[backend_id].runtime_change) (); } } xfree (fname); return result; }