Page MenuHome GnuPG

No OneTemporary

diff --git a/agent/ChangeLog b/agent/ChangeLog
index 242ee150e..fba539763 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,2578 +1,2583 @@
+2011-07-22 Werner Koch <wk@g10code.com>
+
+ * command-ssh.c (ssh_receive_key): Do not init comment to an empty
+ static string; in the error case it would be freed.
+
2011-04-29 Werner Koch <wk@g10code.com>
* gpg-agent.c: Include estream.h
(main): s/pth_kill/es_pth_kill/.
2010-11-11 Werner Koch <wk@g10code.com>
* agent.h (opt): Add field SIGUSR2_ENABLED.
* gpg-agent.c (handle_connections): Set that flag.
* call-scd.c (start_scd): Enable events depending on this flag.
2010-09-30 Werner Koch <wk@g10code.com>
* findkey.c (unprotect): Do not put the passphrase into the cache
if it has been changed.
2010-09-24 Werner Koch <wk@g10code.com>
* gpg-agent.c (main, reread_configuration): Always test whether
the default configuration file has been created in the meantime.
Fixes bug#1285.
2010-08-11 Werner Koch <wk@g10code.com>
* call-pinentry.c (agent_askpin, agent_get_passphrase): Fix
setting of confidential flag.
* call-scd.c (agent_card_scd): Pass assuan comment lines to the
caller.
(ASSUAN_CONVEY_COMMENTS): Provide replacement if needed.
2010-05-12 Werner Koch <wk@g10code.com>
* preset-passphrase.c (forget_passphrase): Actually implement
this. Fixes bug#1198.
* gpg-agent.c (handle_tick): Do not print die message with option -q.
2010-05-11 Werner Koch <wk@g10code.com>
* 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-04 Werner Koch <wk@g10code.com>
* gpg-agent.c (main): Add command --use-standard-socket-p.
2010-05-03 Werner Koch <wk@g10code.com>
* gpg-agent.c (check_own_socket_thread): Do not release SOCKNAME
too early.
2010-03-17 Werner Koch <wk@g10code.com>
* call-scd.c (unlock_scd): Send a BYE under certain conditions.
2010-02-19 Werner Koch <wk@g10code.com>
* call-pinentry.c (start_pinentry): Remove a translation prefix.
2010-02-18 Werner Koch <wk@g10code.com>
* protect.c (agent_unprotect): Initialize CLEARTEXT.
* command.c (register_commands): Unconditionally use
assuan_register_post_cmd_notify.
(start_command_handler): Undocumented use assuan_set_io_monitor.
2010-02-17 Werner Koch <wk@g10code.com>
* call-pinentry.c (start_pinentry): Always free OPTSTR. Send
default-xxx strings.
2010-02-11 Marcus Brinkmann <marcus@g10code.de>
From trunk 2009-09-23, 2009-11-02, 2009-11-04, 2009-11-05, 2009-11-25,
2009-12-08:
* Makefile.am (gpg_agent_CFLAGS, gpg_agent_LDADD): Use libassuan
instead of libassuan-pth.
* gpg-agent.c: Invoke ASSUAN_SYSTEM_PTH_IMPL.
(main): Update to new API. Call assuan_set_system_hooks and
assuan_sock_init. Fix invocation of assuan_socket_connect.
Call assuan_set_assuan_log_stream here.
(parse_rereadable_options): Don't set global assuan log
file (there ain't one anymore).
(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. Update use of
assuan_socket_connect.
* command.c: Include "scdaemon.h" before <assuan.h> 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.
Use assuan_handler_t type. Add NULL arg to assuan_register_command.
Add help arg to assuan_register_command. Convert all command
comments to help strings.
(start_command_handler): Allocate assuan context before starting
server. Change assuan_init_socket_server_ext into
assuan_init_socket_server. Use assuan_fd_t and assuan_fdopen on fds.
Do not call assuan_set_log_stream anymore.
(reset_notify): Take LINE arg and return error.
* call-pinentry.c: Include "scdaemon.h" before <assuan.h> 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 assuan_pipe_connect, notassuan_pipe_connect_ext.
Convert posix fd to assuan fd.
* 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.
Update use of assuan_socket_connect and assuan_pipe_connect.
Convert posix fd to assuan fd.
2010-01-26 Werner Koch <wk@g10code.com>
* protect.c (do_encryption): Encode the s2kcount and do not use a
static value of 96.
2009-12-21 Werner Koch <wk@g10code.com>
* command.c (cmd_getinfo): Add sub-command "s2k_count".
2009-12-14 Werner Koch <wk@g10code.com>
* 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-03 Werner Koch <wk@g10code.com>
* gpg-agent.c (set_debug): Allow for numerical debug leveles. Print
active debug flags.
2009-12-02 Werner Koch <wk@g10code.com>
* 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-09-04 Marcus Brinkmann <marcus@g10code.com>
* command.c (start_command_handler): Add comment about gap in
implementation (in dead code), for future reference.
2009-08-11 Werner Koch <wk@g10code.com>
* divert-scd.c (ask_for_card): I18n a prompt string.
2009-07-06 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* learncard.c (send_cert_back): Ignore certain error codes.
2009-06-05 Werner Koch <wk@g10code.com>
* protect-tool.c (store_private_key): Fix last change by appending
a ".key".
2009-06-03 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* gpg-agent.c (main): Run pth_kill after fork. Fixes bug#1066.
2009-05-19 Werner Koch <wk@g10code.com>
* gpg-agent.c (JNLIB_NEED_AFLOCAL): Define.
(create_server_socket): Use SUN_LEN macro.
2009-05-15 Werner Koch <wk@g10code.com>
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 <wk@g10code.com>
* 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 <marcus@g10code.de>
* call-pinentry.c (agent_get_confirmation): Try SETNOTOK command
with pinentry.
2009-04-01 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* learncard.c (agent_handle_learn): Add new certtype 111.
2009-03-26 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <ueno@unixuser.org>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* command.c (cmd_get_passphrase): Implement option --no-ask.
2008-12-09 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* gpg-agent.c (handle_connections): Sync the ticker to the next
full second. This is bug#871.
2008-12-05 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* gpg-agent.c (make_libversion): New.
(my_strusage): Print libgcrypt version
2008-11-11 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* command.c (cmd_killagent): Stop the agent immediately.
(start_command_handler): Take care of GPG_ERR_EOF.
2008-10-29 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* call-scd.c (start_scd) [W32]: Use snprintf again because we now
always use the estream variant.
2008-10-15 Werner Koch <wk@g10code.com>
* call-scd.c (start_scd): Enable assuan loggging if requested.
(agent_scd_check_aliveness) [W32]: Fix use of GetExitCodeProcess.
2008-10-14 Werner Koch <wk@g10code.com>
* gpg-agent.c (get_agent_scd_notify_event): Need to use a manual
reset event.
2008-09-29 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* divert-scd.c (getpin_cb): Support a Reset Code style PINs..
2008-09-03 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* trustlist.c (insert_colons): Fix stupidly wrong allocation size
computation.
2008-05-26 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* agent.h (agent_inq_pinentry_launched): New prototype.
* call-pinentry.c: Include sys/types.h and signal.h.
2008-02-14 Werner Koch <wk@g10code.com>
* 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 <marcus@g10code.de>
* call-pinentry.c (start_pinentry): Start pinentry in detached
mode.
2007-12-04 Werner Koch <wk@g10code.com>
* call-pinentry.c (agent_askpin): Use gnupg_get_help_string.
2007-12-03 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* call-pinentry.c (agent_askpin): Set the tooltip for the quality
bar.
2007-11-15 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* call-scd.c (start_scd) [W32]: Take care of fflush peculiarities.
2007-11-07 Werner Koch <wk@g10code.com>
* agent.h: Remove errors.h.
2007-10-24 Werner Koch <wk@g10code.com>
* genkey.c (check_passphrase_constraints): Changed the wording of
the warning messages.
2007-10-19 Werner Koch <wk@g10code.com>
* protect-tool.c (get_passphrase): Use new utf8 switch fucntions.
2007-10-15 Daiki Ueno <ueno@unixuser.org> (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 <wk@g10code.com>
* command.c (cmd_getinfo): Add "pid" subcommand.
2007-10-01 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <marcus@g10code.de>
* call-pinentry.c (agent_popup_message_stop): Implement kill for
Windows.
2007-08-28 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* trustlist.c (read_one_trustfile): Add flag "cm".
(agent_istrusted): Ditto.
2007-08-02 Werner Koch <wk@g10code.com>
* gpg-agent.c: Include gc-opt-flags.h and remove their definition
here.
2007-07-13 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* call-scd.c (struct inq_needpin_s): New.
(inq_needpin): Pass unknown inquiries up.
2007-07-04 Werner Koch <wk@g10code.com>
* gpg-agent.c (TIMERTICK_INTERVAL): New.
(fixed_gcry_pth_init, main): Kludge to fix Pth initialization.
2007-07-03 Werner Koch <wk@g10code.com>
* gpg-agent.c (handle_connections): Do not use FD_SETSIZE for
select but compute the correct number.
2007-07-02 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* gpg-agent.c (create_directories) [W32]: Made it work.
2007-06-21 Werner Koch <wk@g10code.com>
* 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 <marcus@g10code.de>
* gpg-agent.c (main): Percent escape pathname in --gpgconf-list
output.
2007-06-18 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <marcus@g10code.de>
* protect-tool.c (get_passphrase): Free ORIG_CODESET on error.
2007-05-14 Werner Koch <wk@g10code.com>
* protect.c (make_shadow_info): Replace sprintf by smklen.
2007-04-20 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* trustlist.c (read_trustfiles): Take a missing trustlist as an
empty one.
2007-03-20 Werner Koch <wk@g10code.com>
* protect-tool.c: New option --p12-charset.
* minip12.c (p12_build): Implement it.
2007-03-19 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* gpg-agent.c (main) <gpgconf>: Add entries for all ttl options.
2007-02-20 Werner Koch <wk@g10code.com>
* call-pinentry.c (start_pinentry): Fix for OS X to allow loading
of the bundle. Tested by Benjamin Donnachie.
2007-02-14 Werner Koch <wk@g10code.com>
* 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 <moritz@g10code.com> (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 <wk@g10code.com>
* command-ssh.c (start_command_handler_ssh):
* Makefile.am (t_common_ldadd): Add LIBICONV.
2007-01-25 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <dshaw@jabberwocky.com>
* Makefile.am: Link to iconv for jnlib dependency.
2006-11-20 Werner Koch <wk@g10code.com>
* call-pinentry.c (agent_popup_message_stop): Use SIGKILL.
* call-scd.c (inq_needpin): Implement POPUPKEYPADPROMPT and
DISMISSKEYPADPROMPT.
2006-11-15 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* protect-tool.c (my_strusage): Fixed typo.
2006-10-23 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* Makefile.am (t_common_ldadd): Use GPG_ERROR_LIBS instead -o just -l
2006-10-19 Werner Koch <wk@g10code.com>
* findkey.c (unprotect): Use it to avoid unnecessary calls to
agent_askpin.
* call-pinentry.c (pinentry_active_p): New.
2006-10-17 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* protect-tool.c (get_passphrase): Fix if !HAVE_LANGINFO_CODESET.
2006-10-06 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* learncard.c (agent_handle_learn): Send back the keypair
information.
2006-09-25 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* Makefile.am: Changes to allow parallel make runs.
2006-09-15 Werner Koch <wk@g10code.com>
* trustlist.c: Entirely rewritten.
(agent_trustlist_housekeeping): Removed and removed all calls.
2006-09-14 Werner Koch <wk@g10code.com>
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 <wk@g10code.com>
* preset-passphrase.c (main) [W32]: Check for WSAStartup error.
2006-09-08 Werner Koch <wk@g10code.com>
* call-scd.c: Add signal.h as we are referencing SIGUSR2.
2006-09-06 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (AM_CFLAGS): Add $(GPG_ERR_CFLAGS).
(gpg_agent_LDADD): Replace -lgpg-error with $(GPG_ERROR_LIBS).
2006-09-06 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* command.c (percent_plus_unescape): New.
(cmd_get_val, cmd_putval): New.
2006-08-29 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* preset-passphrase.c (make_hexstring): For consistency use
xtrymalloc and changed caller to use xfree. Fixed function
comment.
2006-07-29 Marcus Brinkmann <marcus@g10code.de>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* gpg-agent.c (handle_signal): Print info for SIGUSR2 only in
verbose mode.
2006-06-22 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* minip12.c (create_final): New arg PW. Add code to calculate the
MAC.
2006-06-09 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (gpg_agent_LDADD): Add $(NETLIBS).
(gpg_protect_tool_LDADD): Likewise.
(gpg_preset_passphrase_LDADD): Likewise.
2006-04-09 Moritz Schulte <moritz@g10code.com>
* command-ssh.c (ssh_request_process): Removed FIXME mentioning a
possible DoS attack.
2006-04-01 Moritz Schulte <moritz@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* minip12.c (p12_parse): Fixed for case that the key object comes
prior to the certificate.
2005-10-19 Werner Koch <wk@g10code.com>
* 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 <marcus@g10code.de>
* 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 <wk@g10code.com>
* minip12.c (build_key_sequence, build_cert_sequence): Fixed
padding.
2005-09-15 Moritz Schulte <moritz@g10code.com>
* t-protect.c (test_agent_protect): Implemented.
(main): Disable use of secure memory.
2005-09-09 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* minip12.c (build_cert_bag): Use a non constructed object.
i.e. 0x80 and not 0xa0.
2005-08-16 Werner Koch <wk@g10code.com>
* gpg-agent.c (main): Use a default file name for --write-env-file.
2005-07-25 Werner Koch <wk@g10code.com>
* findkey.c (agent_public_key_from_file): Fixed array assignment.
This was the cause for random segvs.
2005-06-29 Werner Koch <wk@g10code.com>
* command-ssh.c (data_sign): Removed empty statement.
2005-06-21 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* command-ssh.c (start_command_handler_ssh): Reset the SCD.
2005-06-09 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* gpg-agent.c: Include setenv.h.
2005-05-31 Werner Koch <wk@g10code.com>
* agent.h (out_of_core): s/__inline__/inine. Noted by Ray Link.
2005-05-25 Werner Koch <wk@g10code.com>
* gpg-agent.c (main): Do not unset the DISPLAY when we are
continuing as child.
2005-05-24 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* protect-tool.c: New option --canonical.
(show_file): Implement it.
* keyformat.txt: Define the created-at attribute for keys.
2005-05-18 Werner Koch <wk@g10code.com>
* divert-scd.c (ask_for_card): Removed the card reset kludge.
2005-05-17 Werner Koch <wk@g10code.com>
* 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 <moritz@g10code.com>
* 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 <moritz@g10code.com>
* command-ssh.c (ssh_handler_request_identities): Removed
debugging code (sleep call), which was commited unintenionally.
2005-04-20 Werner Koch <wk@g10code.com>
* 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 <moritz@g10code.com>
* 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 <moritz@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <moritz@g10code.com>
* 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 <moritz@g10code.com>
* 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 <wk@g10code.com>
* findkey.c (modify_description): Don't increment OUT_LEN during
the second pass.
2005-02-14 Moritz Schulte <moritz@g10code.com>
* 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 <wk@g10code.com>
* 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 <moritz@g10code.com>
* 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 <moritz@g10code.com>
* 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 <moritz@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <marcus@g10code.de>
* 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 <wk@g10code.com>
* gpg-agent.c (main): Use default_homedir().
* protect-tool.c (main): Ditto.
2004-12-20 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <moritz@g10code.com>
* query.c: Undo change from 2004-12-05.
2004-12-15 Werner Koch <wk@g10code.com>
* 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 <moritz@g10code.com>
* query.c (start_pinentry): Allow CTRL be NULL.
2004-10-22 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* Makefile.am: Adjusted from gettext 1.14.
2004-09-29 Werner Koch <wk@g10code.com>
* minip12.c (parse_bag_encrypted_data): Print error if a bad
passphrase has been given.
2004-09-28 Werner Koch <wk@g10code.com>
* protect.c (agent_unprotect): Fixed wiping of CLEARTEXT. Thanks
to Moritz for pointing this out.
2004-09-25 Moritz Schulte <moritz@g10code.com>
* 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 <wk@g10code.de>
* 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 <wk@g10code.de>
* 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 <wk@g10code.de>
* 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 <wk@g10code.de>
* 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 <moritz@g10code.com>
* gpg-agent.c: Include <sys/stat.h> (build fix for BSD).
2004-05-11 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* call-scd.c (start_scd): Do not register an event signal if we
are running as a pipe server.
2004-04-21 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* gpg-agent.c (main): Tell the logging code that we are running
detached.
2004-04-06 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main): Use new libgcrypt thread library register
scheme.
2004-03-23 Marcus Brinkmann <marcus@g10code.de>
* gpg-agent.c (main): For now, always print the default config
file name for --gpgconf-list.
2004-03-17 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main) <gpgconf>: Fixed default value quoting.
2004-03-16 Werner Koch <wk@gnupg.org>
* gpg-agent.c (parse_rereadable_options): Use the new
DEFAULT_CACHE_TTL macro.
(main): Updated --gpgconf-list output.
2004-02-21 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* minip12.c (crypt_block): Add arg CIPHER_ALGO; changed all callers.
(set_key_iv): Add arg KEYBYTES; changed caller.
2004-02-03 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* trustlist.c (agent_marktrusted): Check whether the trustlist is
writable.
2004-01-27 Werner Koch <wk@gnupg.org>
* sexp-parse.h: Moved to ../common.
2004-01-24 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* gpg-agent.c (main): Set the prefixes for assuan logging.
2003-12-15 Werner Koch <wk@gnupg.org>
* protect.c (do_encryption): Use gcry_create_nonce instad of the
obsolete WEAK_RANDOM.
2003-11-20 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* command.c (cmd_get_confirmation): New command.
2003-08-20 Timo Schulz <twoaday@freakmail.de>
* pksign.c (do_encode_md): Allocate enough space. Cast md
byte to unsigned char to prevent sign extension.
2003-08-14 Timo Schulz <twoaday@freakmail.de>
* 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 <wk@gnupg.org>
* Makefile.am (gpg_agent_LDADD): Added INTLLIBS.
(gpg_protect_tool_SOURCES): Added simple-pwquery.[ch]
2003-07-27 Werner Koch <wk@gnupg.org>
Adjusted for gcry_mpi_print and gcry_mpi_scan API change.
2003-07-15 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* gpg-agent.c (handle_connections): Kludge to allow use of Pth 1
and 2.
2003-06-30 Werner Koch <wk@gnupg.org>
* call-scd.c (learn_status_cb): Store the serialno in PARM.
2003-06-26 Werner Koch <wk@gnupg.org>
* call-scd.c (agent_card_serialno): Don't do a RESET anymore.
2003-06-25 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
Renamed error codes from INVALID to INV and removed _ERROR suffixes.
2003-06-03 Werner Koch <wk@gnupg.org>
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 <wk@gnupg.org>
* command.c (register_commands): Adjusted for new Assuan semantics.
* Makefile.am: Don't override LDFLAGS.
2002-12-04 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* command.c (option_handler): Fix keep_tty check.
2002-11-06 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <neal@cs.uml.edu>
* gpg-agent.c (main) [USE_GNU_PTH]: No need to call
assuan_set_io_func as assuan is smart.
2002-09-25 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* gpg-agent.c (create_private_keys_directory)
(create_directories): New.
(main): Try to create a home directory.
2002-09-04 Neal H. Walfield <neal@g10code.de>
* gpg-agent.c (main): Use sigaction, not signal.
2002-09-03 Neal H. Walfield <neal@g10code.de>
* findkey.c: Include <fcntl.h>.
(agent_write_private_key): Prefer POSIX compatibity, open and
fdopen, over the simplicity of GNU extensions, fopen(file, "x").
2002-08-22 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* query.c (start_pinentry): Use GNUPG_DERAULT_PINENTRY.
* call-scd.c (start_scd): Use GNUPG_DEFAULT_SCDAEMON.
2002-06-28 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* protect-tool.c (read_file): New.
(read_key): Factored most code out to read_file.
2002-06-17 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* gpg-agent.c (main): New option --disable-pth.
2002-06-11 Werner Koch <wk@gnupg.org>
* protect-tool.c: Add command --show-keygrip
(show_keygrip): New.
2002-05-23 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* cache.c (housekeeping, agent_put_cache): Use our time() wrapper.
2002-04-26 Werner Koch <wk@gnupg.org>
* 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 <marcus@g10code.de>
* 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 <marcus@g10code.de>
* 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 <wk@gnupg.org>
* protect-tool.c (show_file): New. Used as default action.
2002-03-28 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* learncard.c (kpinfo_cb): Remove the content restrictions from
the keyID.
2002-03-06 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* call-scd.c (inq_needpin): New.
(agent_card_pksign): Add getpin_cb args.
(agent_card_pkdecrypt): New.
2002-03-04 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* cache.c (housekeeping): Fixed linking in the remove case.
2002-02-01 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* protect.c: New.
(hash_passphrase): Based on the GnuPG 1.0.6 version.
* protect-tool.c: New
2002-01-29 Werner Koch <wk@gnupg.org>
* findkey.c (agent_key_available): New.
* command.c (cmd_havekey): New.
(register_commands): And register new command.
2002-01-20 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* trustlist.c: New.
* command.c (cmd_istrusted, cmd_listtrusted, cmd_marktrusted): New.
2002-01-07 Werner Koch <wk@gnupg.org>
* genkey.c: Store the secret part and return the public part.
2002-01-03 Werner Koch <wk@gnupg.org>
* command.c (cmd_get_passphrase): New.
(cmd_clear_passphrase): New.
* query.c (agent_get_passphrase): New.
2002-01-02 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* keyformat.txt: New.
2001-12-19 Marcus Brinkmann <marcus@g10code.de>
* query.c (start_pinentry): Add new argument to assuan_pipe_connect.
2001-12-18 Werner Koch <wk@gnupg.org>
* Makefile.am: Use LIBGCRYPT macros
2001-12-14 Werner Koch <wk@gnupg.org>
* 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 <marcus@g10code.de>
* query.c (LINELENGTH): Removed.
(agent_askpin): Use ASSUAN_LINELENGTH, not LINELENGTH.
2001-11-19 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@openit.de>
* 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 <wk@openit.de>
* 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/command-ssh.c b/agent/command-ssh.c
index 12fe60a15..7eb581458 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -1,2984 +1,2979 @@
/* command-ssh.c - gpg-agent's ssh-agent emulation layer
* Copyright (C) 2004, 2005, 2006, 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 <http://www.gnu.org/licenses/>.
*/
/* Only v2 of the ssh-agent protocol is implemented. */
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <assert.h>
#include "agent.h"
#include "estream.h"
#include "i18n.h"
/* Request types. */
#define SSH_REQUEST_REQUEST_IDENTITIES 11
#define SSH_REQUEST_SIGN_REQUEST 13
#define SSH_REQUEST_ADD_IDENTITY 17
#define SSH_REQUEST_REMOVE_IDENTITY 18
#define SSH_REQUEST_REMOVE_ALL_IDENTITIES 19
#define SSH_REQUEST_LOCK 22
#define SSH_REQUEST_UNLOCK 23
#define SSH_REQUEST_ADD_ID_CONSTRAINED 25
/* Options. */
#define SSH_OPT_CONSTRAIN_LIFETIME 1
#define SSH_OPT_CONSTRAIN_CONFIRM 2
/* Response types. */
#define SSH_RESPONSE_SUCCESS 6
#define SSH_RESPONSE_FAILURE 5
#define SSH_RESPONSE_IDENTITIES_ANSWER 12
#define SSH_RESPONSE_SIGN_RESPONSE 14
/* Other constants. */
#define SSH_DSA_SIGNATURE_PADDING 20
#define SSH_DSA_SIGNATURE_ELEMS 2
#define SPEC_FLAG_USE_PKCS1V2 (1 << 0)
/* The blurb we put into the header of a newly created control file. */
static const char sshcontrolblurb[] =
"# List of allowed ssh keys. Only keys present in this file are used\n"
"# in the SSH protocol. The ssh-add tool may add new entries to this\n"
"# file to enable them; you may also add them manually. Comment\n"
"# lines, like this one, as well as empty lines are ignored. Lines do\n"
-"# have a certain length limit but this is not serious limitation as\n"
+"# have a certain length limit but this is not serious limitation as\n"
"# the format of the entries is fixed and checked by gpg-agent. A\n"
"# non-comment line starts with optional white spaces, followed by the\n"
"# keygrip of the key given as 40 hex digits, optionally followed by a\n"
"# the caching TTL in seconds and another optional field for arbitrary\n"
"# flags. Prepend the keygrip with an '!' mark to disable it.\n"
"\n";
/* Macros. */
/* Return a new uint32 with b0 being the most significant byte and b3
being the least significant byte. */
#define uint32_construct(b0, b1, b2, b3) \
((b0 << 24) | (b1 << 16) | (b2 << 8) | b3)
/*
* Basic types.
*/
/* Type for a request handler. */
typedef gpg_error_t (*ssh_request_handler_t) (ctrl_t ctrl,
estream_t request,
estream_t response);
/* Type, which is used for associating request handlers with the
appropriate request IDs. */
typedef struct ssh_request_spec
{
unsigned char type;
ssh_request_handler_t handler;
const char *identifier;
unsigned int secret_input;
} ssh_request_spec_t;
/* Type for "key modifier functions", which are necessary since
OpenSSH and GnuPG treat key material slightly different. A key
modifier is called right after a new key identity has been received
in order to "sanitize" the material. */
typedef gpg_error_t (*ssh_key_modifier_t) (const char *elems,
gcry_mpi_t *mpis);
/* The encoding of a generated signature is dependent on the
algorithm; therefore algorithm specific signature encoding
functions are necessary. */
typedef gpg_error_t (*ssh_signature_encoder_t) (estream_t signature_blob,
gcry_mpi_t *mpis);
/* Type, which is used for boundling all the algorithm specific
information together in a single object. */
typedef struct ssh_key_type_spec
{
/* Algorithm identifier as used by OpenSSH. */
const char *ssh_identifier;
/* Algorithm identifier as used by GnuPG. */
const char *identifier;
/* List of MPI names for secret keys; order matches the one of the
agent protocol. */
const char *elems_key_secret;
/* List of MPI names for public keys; order matches the one of the
agent protocol. */
const char *elems_key_public;
/* List of MPI names for signature data. */
const char *elems_signature;
/* List of MPI names for secret keys; order matches the one, which
is required by gpg-agent's key access layer. */
const char *elems_sexp_order;
/* Key modifier function. Key modifier functions are necessary in
order to fix any inconsistencies between the representation of
keys on the SSH and on the GnuPG side. */
ssh_key_modifier_t key_modifier;
/* Signature encoder function. Signature encoder functions are
necessary since the encoding of signatures depends on the used
algorithm. */
ssh_signature_encoder_t signature_encoder;
/* Misc flags. */
unsigned int flags;
} ssh_key_type_spec_t;
/* Prototypes. */
static gpg_error_t ssh_handler_request_identities (ctrl_t ctrl,
estream_t request,
estream_t response);
static gpg_error_t ssh_handler_sign_request (ctrl_t ctrl,
estream_t request,
estream_t response);
static gpg_error_t ssh_handler_add_identity (ctrl_t ctrl,
estream_t request,
estream_t response);
static gpg_error_t ssh_handler_remove_identity (ctrl_t ctrl,
estream_t request,
estream_t response);
static gpg_error_t ssh_handler_remove_all_identities (ctrl_t ctrl,
estream_t request,
estream_t response);
static gpg_error_t ssh_handler_lock (ctrl_t ctrl,
estream_t request,
estream_t response);
static gpg_error_t ssh_handler_unlock (ctrl_t ctrl,
estream_t request,
estream_t response);
static gpg_error_t ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis);
static gpg_error_t ssh_signature_encoder_rsa (estream_t signature_blob,
gcry_mpi_t *mpis);
static gpg_error_t ssh_signature_encoder_dsa (estream_t signature_blob,
gcry_mpi_t *mpis);
/* Global variables. */
-
+
/* Associating request types with the corresponding request
handlers. */
static ssh_request_spec_t request_specs[] =
{
#define REQUEST_SPEC_DEFINE(id, name, secret_input) \
{ SSH_REQUEST_##id, ssh_handler_##name, #name, secret_input }
REQUEST_SPEC_DEFINE (REQUEST_IDENTITIES, request_identities, 1),
REQUEST_SPEC_DEFINE (SIGN_REQUEST, sign_request, 0),
REQUEST_SPEC_DEFINE (ADD_IDENTITY, add_identity, 1),
REQUEST_SPEC_DEFINE (ADD_ID_CONSTRAINED, add_identity, 1),
REQUEST_SPEC_DEFINE (REMOVE_IDENTITY, remove_identity, 0),
REQUEST_SPEC_DEFINE (REMOVE_ALL_IDENTITIES, remove_all_identities, 0),
REQUEST_SPEC_DEFINE (LOCK, lock, 0),
REQUEST_SPEC_DEFINE (UNLOCK, unlock, 0)
#undef REQUEST_SPEC_DEFINE
};
/* Table holding key type specifications. */
static ssh_key_type_spec_t ssh_key_types[] =
{
{
"ssh-rsa", "rsa", "nedupq", "en", "s", "nedpqu",
ssh_key_modifier_rsa, ssh_signature_encoder_rsa,
SPEC_FLAG_USE_PKCS1V2
},
{
"ssh-dss", "dsa", "pqgyx", "pqgy", "rs", "pqgyx",
NULL, ssh_signature_encoder_dsa,
0
},
};
/*
- General utility functions.
+ General utility functions.
*/
/* A secure realloc, i.e. it makes sure to allocate secure memory if A
is NULL. This is required because the standard gcry_realloc does
not know whether to allocate secure or normal if NULL is passed as
existing buffer. */
static void *
realloc_secure (void *a, size_t n)
{
void *p;
-
+
if (a)
p = gcry_realloc (a, n);
else
p = gcry_malloc_secure (n);
return p;
}
/* Create and return a new C-string from DATA/DATA_N (i.e.: add
NUL-termination); return NULL on OOM. */
static char *
make_cstring (const char *data, size_t data_n)
{
char *s;
s = xtrymalloc (data_n + 1);
if (s)
{
memcpy (s, data, data_n);
s[data_n] = 0;
}
return s;
}
-/*
- Primitive I/O functions.
+/*
+ Primitive I/O functions.
*/
/* Read a byte from STREAM, store it in B. */
static gpg_error_t
stream_read_byte (estream_t stream, unsigned char *b)
{
gpg_error_t err;
int ret;
ret = es_fgetc (stream);
if (ret == EOF)
{
if (es_ferror (stream))
err = gpg_error_from_syserror ();
else
err = gpg_error (GPG_ERR_EOF);
*b = 0;
}
else
{
*b = ret & 0xFF;
err = 0;
}
return err;
}
/* Write the byte contained in B to STREAM. */
static gpg_error_t
stream_write_byte (estream_t stream, unsigned char b)
{
gpg_error_t err;
int ret;
ret = es_fputc (b, stream);
if (ret == EOF)
err = gpg_error_from_syserror ();
else
err = 0;
return err;
}
/* Read a uint32 from STREAM, store it in UINT32. */
static gpg_error_t
stream_read_uint32 (estream_t stream, u32 *uint32)
{
unsigned char buffer[4];
size_t bytes_read;
gpg_error_t err;
int ret;
ret = es_read (stream, buffer, sizeof (buffer), &bytes_read);
if (ret)
err = gpg_error_from_syserror ();
else
{
if (bytes_read != sizeof (buffer))
err = gpg_error (GPG_ERR_EOF);
else
{
u32 n;
n = uint32_construct (buffer[0], buffer[1], buffer[2], buffer[3]);
*uint32 = n;
err = 0;
}
}
return err;
}
/* Write the uint32 contained in UINT32 to STREAM. */
static gpg_error_t
stream_write_uint32 (estream_t stream, u32 uint32)
{
unsigned char buffer[4];
gpg_error_t err;
int ret;
buffer[0] = uint32 >> 24;
buffer[1] = uint32 >> 16;
buffer[2] = uint32 >> 8;
buffer[3] = uint32 >> 0;
ret = es_write (stream, buffer, sizeof (buffer), NULL);
if (ret)
err = gpg_error_from_syserror ();
else
err = 0;
return err;
}
/* Read SIZE bytes from STREAM into BUFFER. */
static gpg_error_t
stream_read_data (estream_t stream, unsigned char *buffer, size_t size)
{
gpg_error_t err;
size_t bytes_read;
int ret;
ret = es_read (stream, buffer, size, &bytes_read);
if (ret)
err = gpg_error_from_syserror ();
else
{
if (bytes_read != size)
err = gpg_error (GPG_ERR_EOF);
else
err = 0;
}
return err;
}
/* Write SIZE bytes from BUFFER to STREAM. */
static gpg_error_t
stream_write_data (estream_t stream, const unsigned char *buffer, size_t size)
{
gpg_error_t err;
int ret;
ret = es_write (stream, buffer, size, NULL);
if (ret)
err = gpg_error_from_syserror ();
else
err = 0;
return err;
}
/* Read a binary string from STREAM into STRING, store size of string
in STRING_SIZE; depending on SECURE use secure memory for
string. */
static gpg_error_t
stream_read_string (estream_t stream, unsigned int secure,
unsigned char **string, u32 *string_size)
{
gpg_error_t err;
unsigned char *buffer = NULL;
u32 length = 0;
/* Read string length. */
err = stream_read_uint32 (stream, &length);
if (err)
goto out;
/* Allocate space. */
if (secure)
buffer = xtrymalloc_secure (length + 1);
else
buffer = xtrymalloc (length + 1);
if (! buffer)
{
err = gpg_error_from_syserror ();
goto out;
}
/* Read data. */
err = stream_read_data (stream, buffer, length);
if (err)
goto out;
/* Finalize string object. */
buffer[length] = 0;
*string = buffer;
if (string_size)
*string_size = length;
out:
if (err)
xfree (buffer);
return err;
}
/* Read a C-string from STREAM, store copy in STRING. */
static gpg_error_t
stream_read_cstring (estream_t stream, char **string)
{
unsigned char *buffer;
gpg_error_t err;
err = stream_read_string (stream, 0, &buffer, NULL);
if (err)
goto out;
-
+
*string = (char *) buffer;
out:
return err;
}
/* Write a binary string from STRING of size STRING_N to STREAM. */
static gpg_error_t
stream_write_string (estream_t stream,
const unsigned char *string, u32 string_n)
{
gpg_error_t err;
err = stream_write_uint32 (stream, string_n);
if (err)
goto out;
err = stream_write_data (stream, string, string_n);
out:
return err;
}
/* Write a C-string from STRING to STREAM. */
static gpg_error_t
stream_write_cstring (estream_t stream, const char *string)
{
gpg_error_t err;
err = stream_write_string (stream,
(const unsigned char *) string, strlen (string));
return err;
-}
+}
/* Read an MPI from STREAM, store it in MPINT. Depending on SECURE
use secure memory. */
static gpg_error_t
stream_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint)
{
unsigned char *mpi_data;
u32 mpi_data_size;
gpg_error_t err;
gcry_mpi_t mpi;
mpi_data = NULL;
err = stream_read_string (stream, secure, &mpi_data, &mpi_data_size);
if (err)
goto out;
/* To avoid excessive use of secure memory we check that an MPI is
not too large. */
if (mpi_data_size > 520)
{
log_error (_("ssh keys greater than %d bits are not supported\n"), 4096);
err = GPG_ERR_TOO_LARGE;
goto out;
}
err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_STD, mpi_data, mpi_data_size, NULL);
if (err)
goto out;
*mpint = mpi;
out:
xfree (mpi_data);
return err;
}
/* Write the MPI contained in MPINT to STREAM. */
static gpg_error_t
stream_write_mpi (estream_t stream, gcry_mpi_t mpint)
{
unsigned char *mpi_buffer;
size_t mpi_buffer_n;
gpg_error_t err;
mpi_buffer = NULL;
err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &mpi_buffer, &mpi_buffer_n, mpint);
if (err)
goto out;
err = stream_write_string (stream, mpi_buffer, mpi_buffer_n);
out:
xfree (mpi_buffer);
return err;
}
/* Copy data from SRC to DST until EOF is reached. */
static gpg_error_t
stream_copy (estream_t dst, estream_t src)
{
char buffer[BUFSIZ];
size_t bytes_read;
gpg_error_t err;
int ret;
err = 0;
while (1)
{
ret = es_read (src, buffer, sizeof (buffer), &bytes_read);
if (ret || (! bytes_read))
{
if (ret)
err = gpg_error_from_syserror ();
break;
}
ret = es_write (dst, buffer, bytes_read, NULL);
if (ret)
{
err = gpg_error_from_syserror ();
break;
}
}
return err;
}
/* Read the content of the file specified by FILENAME into a newly
create buffer, which is to be stored in BUFFER; store length of
buffer in BUFFER_N. */
static gpg_error_t
file_to_buffer (const char *filename, unsigned char **buffer, size_t *buffer_n)
{
unsigned char *buffer_new;
struct stat statbuf;
estream_t stream;
gpg_error_t err;
int ret;
*buffer = NULL;
*buffer_n = 0;
buffer_new = NULL;
err = 0;
-
+
stream = es_fopen (filename, "r");
if (! stream)
{
err = gpg_error_from_syserror ();
goto out;
}
ret = fstat (es_fileno (stream), &statbuf);
if (ret)
{
err = gpg_error_from_syserror ();
goto out;
}
buffer_new = xtrymalloc (statbuf.st_size);
if (! buffer_new)
{
err = gpg_error_from_syserror ();
goto out;
}
err = stream_read_data (stream, buffer_new, statbuf.st_size);
if (err)
goto out;
*buffer = buffer_new;
*buffer_n = statbuf.st_size;
out:
if (stream)
es_fclose (stream);
if (err)
xfree (buffer_new);
return err;
}
/* Open the ssh control file and create it if not available. With
APPEND passed as true the file will be opened in append mode,
otherwise in read only mode. On success a file pointer is stored
at the address of R_FP. */
static gpg_error_t
open_control_file (FILE **r_fp, int append)
{
gpg_error_t err;
char *fname;
FILE *fp;
/* Note: As soon as we start to use non blocking functions here
(i.e. where Pth might switch threads) we need to employ a
mutex. */
*r_fp = NULL;
fname = make_filename (opt.homedir, "sshcontrol", NULL);
/* FIXME: With "a+" we are not able to check whether this will will
be created and thus the blurb needs to be written first. */
fp = fopen (fname, append? "a+":"r");
if (!fp && errno == ENOENT)
{
/* Fixme: "x" is a GNU extension. We might want to use the es_
functions here. */
- fp = fopen (fname, "wx");
+ fp = fopen (fname, "wx");
if (!fp)
{
err = gpg_error (gpg_err_code_from_errno (errno));
log_error (_("can't create `%s': %s\n"), fname, gpg_strerror (err));
xfree (fname);
return err;
}
fputs (sshcontrolblurb, fp);
fclose (fp);
fp = fopen (fname, append? "a+":"r");
}
if (!fp)
{
err = gpg_error (gpg_err_code_from_errno (errno));
log_error (_("can't open `%s': %s\n"), fname, gpg_strerror (err));
xfree (fname);
return err;
}
-
- *r_fp = fp;
+
+ *r_fp = fp;
return 0;
}
/* Search the file at stream FP from the beginning until a matching
HEXGRIP is found; return success in this case and store true at
DISABLED if the found key has been disabled. If R_TTL is not NULL
a specified TTL for that key is stored there. */
static gpg_error_t
-search_control_file (FILE *fp, const char *hexgrip,
+search_control_file (FILE *fp, const char *hexgrip,
int *r_disabled, int *r_ttl)
{
int c, i;
char *p, *pend, line[256];
long ttl;
assert (strlen (hexgrip) == 40 );
rewind (fp);
*r_disabled = 0;
next_line:
do
{
if (!fgets (line, DIM(line)-1, fp) )
{
if (feof (fp))
return gpg_error (GPG_ERR_EOF);
return gpg_error (gpg_err_code_from_errno (errno));
}
-
+
if (!*line || line[strlen(line)-1] != '\n')
{
/* Eat until end of line */
while ( (c=getc (fp)) != EOF && c != '\n')
;
return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
: GPG_ERR_INCOMPLETE_LINE);
}
-
+
/* Allow for empty lines and spaces */
for (p=line; spacep (p); p++)
;
}
while (!*p || *p == '\n' || *p == '#');
-
+
*r_disabled = 0;
if (*p == '!')
{
*r_disabled = 1;
for (p++; spacep (p); p++)
;
}
for (i=0; hexdigitp (p) && i < 40; p++, i++)
if (hexgrip[i] != (*p >= 'a'? (*p & 0xdf): *p))
goto next_line;
if (i != 40 || !(spacep (p) || *p == '\n'))
{
log_error ("invalid formatted line in ssh control file\n");
return gpg_error (GPG_ERR_BAD_DATA);
}
ttl = strtol (p, &pend, 10);
p = pend;
if (!(spacep (p) || *p == '\n') || ttl < -1)
{
log_error ("invalid TTL value in ssh control file; assuming 0\n");
ttl = 0;
}
if (r_ttl)
*r_ttl = ttl;
- /* Here is the place to parse flags if we need them. */
+ /* Here is the place to parse flags if we need them. */
return 0; /* Okay: found it. */
}
/* Add an entry to the control file to mark the key with the keygrip
HEXGRIP as usable for SSH; i.e. it will be returned when ssh asks
for it. This function is in general used to add a key received
through the ssh-add function. We can assume that the user wants to
allow ssh using this key. */
static gpg_error_t
add_control_entry (ctrl_t ctrl, const char *hexgrip, int ttl)
{
gpg_error_t err;
FILE *fp;
int disabled;
(void)ctrl;
err = open_control_file (&fp, 1);
if (err)
return err;
err = search_control_file (fp, hexgrip, &disabled, NULL);
if (err && gpg_err_code(err) == GPG_ERR_EOF)
{
struct tm *tp;
time_t atime = time (NULL);
/* Not yet in the file - add it. Because the file has been
opened in append mode, we simply need to write to it. */
tp = localtime (&atime);
fprintf (fp, "# Key added on %04d-%02d-%02d %02d:%02d:%02d\n%s %d\n",
1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
tp->tm_hour, tp->tm_min, tp->tm_sec,
hexgrip, ttl);
-
+
}
fclose (fp);
return 0;
}
/* Scan the sshcontrol file and return the TTL. */
static int
ttl_from_sshcontrol (const char *hexgrip)
{
FILE *fp;
int disabled, ttl;
if (!hexgrip || strlen (hexgrip) != 40)
return 0; /* Wrong input: Use global default. */
if (open_control_file (&fp, 0))
return 0; /* Error: Use the global default TTL. */
if (search_control_file (fp, hexgrip, &disabled, &ttl)
|| disabled)
ttl = 0; /* Use the global default if not found or disabled. */
- fclose (fp);
+ fclose (fp);
return ttl;
}
/*
- MPI lists.
+ MPI lists.
*/
/* Free the list of MPIs MPI_LIST. */
static void
mpint_list_free (gcry_mpi_t *mpi_list)
{
if (mpi_list)
{
unsigned int i;
for (i = 0; mpi_list[i]; i++)
gcry_mpi_release (mpi_list[i]);
xfree (mpi_list);
}
}
/* Receive key material MPIs from STREAM according to KEY_SPEC;
depending on SECRET expect a public key or secret key. The newly
allocated list of MPIs is stored in MPI_LIST. Returns usual error
code. */
static gpg_error_t
ssh_receive_mpint_list (estream_t stream, int secret,
ssh_key_type_spec_t key_spec, gcry_mpi_t **mpi_list)
{
unsigned int elems_public_n;
const char *elems_public;
unsigned int elems_n;
const char *elems;
int elem_is_secret;
gcry_mpi_t *mpis;
gpg_error_t err;
unsigned int i;
mpis = NULL;
err = 0;
-
+
if (secret)
elems = key_spec.elems_key_secret;
else
elems = key_spec.elems_key_public;
elems_n = strlen (elems);
elems_public = key_spec.elems_key_public;
elems_public_n = strlen (elems_public);
mpis = xtrycalloc (elems_n + 1, sizeof *mpis );
if (!mpis)
{
err = gpg_error_from_syserror ();
goto out;
}
elem_is_secret = 0;
for (i = 0; i < elems_n; i++)
{
if (secret)
elem_is_secret = ! strchr (elems_public, elems[i]);
err = stream_read_mpi (stream, elem_is_secret, &mpis[i]);
if (err)
break;
}
if (err)
goto out;
*mpi_list = mpis;
out:
if (err)
mpint_list_free (mpis);
return err;
}
/* Key modifier function for RSA. */
static gpg_error_t
ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis)
{
gcry_mpi_t p;
gcry_mpi_t q;
gcry_mpi_t u;
if (strcmp (elems, "nedupq"))
/* Modifying only necessary for secret keys. */
goto out;
u = mpis[3];
p = mpis[4];
q = mpis[5];
if (gcry_mpi_cmp (p, q) > 0)
{
/* P shall be smaller then Q! Swap primes. iqmp becomes u. */
gcry_mpi_t tmp;
tmp = mpis[4];
mpis[4] = mpis[5];
mpis[5] = tmp;
}
else
/* U needs to be recomputed. */
gcry_mpi_invm (u, p, q);
out:
return 0;
}
/* Signature encoder function for RSA. */
static gpg_error_t
ssh_signature_encoder_rsa (estream_t signature_blob, gcry_mpi_t *mpis)
{
unsigned char *data;
size_t data_n;
gpg_error_t err;
gcry_mpi_t s;
s = mpis[0];
err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, s);
if (err)
goto out;
err = stream_write_string (signature_blob, data, data_n);
xfree (data);
out:
return err;
}
/* Signature encoder function for DSA. */
static gpg_error_t
ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis)
{
unsigned char buffer[SSH_DSA_SIGNATURE_PADDING * SSH_DSA_SIGNATURE_ELEMS];
unsigned char *data;
size_t data_n;
gpg_error_t err;
int i;
data = NULL;
for (i = 0; i < 2; i++)
{
err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, mpis[i]);
if (err)
break;
if (data_n > SSH_DSA_SIGNATURE_PADDING)
{
err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */
break;
}
-
+
memset (buffer + (i * SSH_DSA_SIGNATURE_PADDING), 0,
SSH_DSA_SIGNATURE_PADDING - data_n);
memcpy (buffer + (i * SSH_DSA_SIGNATURE_PADDING)
+ (SSH_DSA_SIGNATURE_PADDING - data_n), data, data_n);
xfree (data);
data = NULL;
}
if (err)
goto out;
err = stream_write_string (signature_blob, buffer, sizeof (buffer));
out:
xfree (data);
return err;
}
-/*
- S-Expressions.
+/*
+ S-Expressions.
*/
/* This function constructs a new S-Expression for the key identified
by the KEY_SPEC, SECRET, MPIS and COMMENT, which is to be stored in
*SEXP. Returns usual error code. */
static gpg_error_t
sexp_key_construct (gcry_sexp_t *sexp,
ssh_key_type_spec_t key_spec, int secret,
gcry_mpi_t *mpis, const char *comment)
{
const char *key_identifier[] = { "public-key", "private-key" };
gcry_sexp_t sexp_new;
char *sexp_template;
size_t sexp_template_n;
gpg_error_t err;
const char *elems;
size_t elems_n;
unsigned int i;
unsigned int j;
void **arg_list;
err = 0;
sexp_new = NULL;
arg_list = NULL;
if (secret)
elems = key_spec.elems_sexp_order;
else
elems = key_spec.elems_key_public;
elems_n = strlen (elems);
/*
Calculate size for sexp_template_n:
"(%s(%s<mpis>)(comment%s))" -> 20 + sizeof (<mpis>).
mpi: (X%m) -> 5.
*/
sexp_template_n = 20 + (elems_n * 5);
sexp_template = xtrymalloc (sexp_template_n);
if (! sexp_template)
{
err = gpg_error_from_syserror ();
goto out;
}
/* Key identifier, algorithm identifier, mpis, comment. */
arg_list = xtrymalloc (sizeof (*arg_list) * (2 + elems_n + 1));
if (! arg_list)
{
err = gpg_error_from_syserror ();
goto out;
}
i = 0;
arg_list[i++] = &key_identifier[secret];
arg_list[i++] = &key_spec.identifier;
*sexp_template = 0;
sexp_template_n = 0;
sexp_template_n = sprintf (sexp_template + sexp_template_n, "(%%s(%%s");
for (i = 0; i < elems_n; i++)
{
sexp_template_n += sprintf (sexp_template + sexp_template_n, "(%c%%m)",
elems[i]);
if (secret)
{
for (j = 0; j < elems_n; j++)
if (key_spec.elems_key_secret[j] == elems[i])
break;
}
else
j = i;
arg_list[i + 2] = &mpis[j];
}
sexp_template_n += sprintf (sexp_template + sexp_template_n,
")(comment%%s))");
arg_list[i + 2] = &comment;
err = gcry_sexp_build_array (&sexp_new, NULL, sexp_template, arg_list);
if (err)
goto out;
*sexp = sexp_new;
out:
xfree (arg_list);
xfree (sexp_template);
return err;
}
/* This functions breaks up the key contained in the S-Expression SEXP
according to KEY_SPEC. The MPIs are bundled in a newly create
list, which is to be stored in MPIS; a newly allocated string
holding the comment will be stored in COMMENT; SECRET will be
filled with a boolean flag specifying what kind of key it is.
Returns usual error code. */
static gpg_error_t
sexp_key_extract (gcry_sexp_t sexp,
ssh_key_type_spec_t key_spec, int *secret,
gcry_mpi_t **mpis, char **comment)
{
gpg_error_t err;
gcry_sexp_t value_list;
gcry_sexp_t value_pair;
gcry_sexp_t comment_list;
unsigned int i;
char *comment_new;
const char *data;
size_t data_n;
int is_secret;
size_t elems_n;
const char *elems;
gcry_mpi_t *mpis_new;
gcry_mpi_t mpi;
err = 0;
value_list = NULL;
value_pair = NULL;
comment_list = NULL;
comment_new = NULL;
mpis_new = NULL;
data = gcry_sexp_nth_data (sexp, 0, &data_n);
if (! data)
{
err = gpg_error (GPG_ERR_INV_SEXP);
goto out;
}
if ((data_n == 10 && !strncmp (data, "public-key", 10))
|| (data_n == 21 && !strncmp (data, "protected-private-key", 21))
|| (data_n == 20 && !strncmp (data, "shadowed-private-key", 20)))
{
is_secret = 0;
elems = key_spec.elems_key_public;
}
else if (data_n == 11 && !strncmp (data, "private-key", 11))
{
is_secret = 1;
elems = key_spec.elems_key_secret;
}
else
{
err = gpg_error (GPG_ERR_INV_SEXP);
goto out;
}
elems_n = strlen (elems);
mpis_new = xtrycalloc (elems_n + 1, sizeof *mpis_new );
if (!mpis_new)
{
err = gpg_error_from_syserror ();
goto out;
}
value_list = gcry_sexp_find_token (sexp, key_spec.identifier, 0);
if (! value_list)
{
err = gpg_error (GPG_ERR_INV_SEXP);
goto out;
}
for (i = 0; i < elems_n; i++)
{
value_pair = gcry_sexp_find_token (value_list, elems + i, 1);
if (! value_pair)
{
err = gpg_error (GPG_ERR_INV_SEXP);
break;
}
/* Note that we need to use STD format; i.e. prepend a 0x00 to
indicate a positive number if the high bit is set. */
mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_STD);
if (! mpi)
{
err = gpg_error (GPG_ERR_INV_SEXP);
break;
}
mpis_new[i] = mpi;
gcry_sexp_release (value_pair);
value_pair = NULL;
}
if (err)
goto out;
/* We do not require a comment sublist to be present here. */
data = NULL;
data_n = 0;
comment_list = gcry_sexp_find_token (sexp, "comment", 0);
if (comment_list)
data = gcry_sexp_nth_data (comment_list, 1, &data_n);
if (! data)
{
data = "(none)";
data_n = 6;
}
comment_new = make_cstring (data, data_n);
if (! comment_new)
{
err = gpg_error_from_syserror ();
goto out;
}
if (secret)
*secret = is_secret;
*mpis = mpis_new;
*comment = comment_new;
out:
gcry_sexp_release (value_list);
gcry_sexp_release (value_pair);
gcry_sexp_release (comment_list);
-
+
if (err)
{
xfree (comment_new);
mpint_list_free (mpis_new);
}
return err;
}
-/* Extract the car from SEXP, and create a newly created C-string
+/* Extract the car from SEXP, and create a newly created C-string
which is to be stored in IDENTIFIER. */
static gpg_error_t
sexp_extract_identifier (gcry_sexp_t sexp, char **identifier)
{
char *identifier_new;
gcry_sexp_t sublist;
const char *data;
size_t data_n;
gpg_error_t err;
identifier_new = NULL;
err = 0;
-
+
sublist = gcry_sexp_nth (sexp, 1);
if (! sublist)
{
err = gpg_error (GPG_ERR_INV_SEXP);
goto out;
}
data = gcry_sexp_nth_data (sublist, 0, &data_n);
if (! data)
{
err = gpg_error (GPG_ERR_INV_SEXP);
goto out;
}
identifier_new = make_cstring (data, data_n);
if (! identifier_new)
{
err = gpg_err_code_from_errno (errno);
goto out;
}
*identifier = identifier_new;
out:
gcry_sexp_release (sublist);
return err;
}
/*
Key I/O.
*/
/* Search for a key specification entry. If SSH_NAME is not NULL,
search for an entry whose "ssh_name" is equal to SSH_NAME;
otherwise, search for an entry whose "name" is equal to NAME.
Store found entry in SPEC on success, return error otherwise. */
static gpg_error_t
ssh_key_type_lookup (const char *ssh_name, const char *name,
ssh_key_type_spec_t *spec)
{
gpg_error_t err;
unsigned int i;
for (i = 0; i < DIM (ssh_key_types); i++)
if ((ssh_name && (! strcmp (ssh_name, ssh_key_types[i].ssh_identifier)))
|| (name && (! strcmp (name, ssh_key_types[i].identifier))))
break;
-
+
if (i == DIM (ssh_key_types))
err = gpg_error (GPG_ERR_NOT_FOUND);
else
{
*spec = ssh_key_types[i];
err = 0;
}
return err;
}
/* Receive a key from STREAM, according to the key specification given
as KEY_SPEC. Depending on SECRET, receive a secret or a public
key. If READ_COMMENT is true, receive a comment string as well.
Constructs a new S-Expression from received data and stores it in
KEY_NEW. Returns zero on success or an error code. */
static gpg_error_t
ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret,
int read_comment, ssh_key_type_spec_t *key_spec)
{
gpg_error_t err;
- char *key_type;
- char *comment;
- gcry_sexp_t key;
+ char *key_type = NULL;
+ char *comment = NULL;
+ gcry_sexp_t key = NULL;
ssh_key_type_spec_t spec;
- gcry_mpi_t *mpi_list;
+ gcry_mpi_t *mpi_list = NULL;
const char *elems;
- mpi_list = NULL;
- key_type = NULL;
- comment = "";
- key = NULL;
-
+
err = stream_read_cstring (stream, &key_type);
if (err)
goto out;
err = ssh_key_type_lookup (key_type, NULL, &spec);
if (err)
goto out;
err = ssh_receive_mpint_list (stream, secret, spec, &mpi_list);
if (err)
goto out;
if (read_comment)
{
err = stream_read_cstring (stream, &comment);
if (err)
goto out;
}
if (secret)
elems = spec.elems_key_secret;
else
elems = spec.elems_key_public;
if (spec.key_modifier)
{
err = (*spec.key_modifier) (elems, mpi_list);
if (err)
goto out;
}
- err = sexp_key_construct (&key, spec, secret, mpi_list, comment);
+ err = sexp_key_construct (&key, spec, secret, mpi_list, comment? comment:"");
if (err)
goto out;
if (key_spec)
*key_spec = spec;
*key_new = key;
-
+
out:
mpint_list_free (mpi_list);
xfree (key_type);
- if (read_comment)
- xfree (comment);
+ xfree (comment);
return err;
}
/* Converts a key of type TYPE, whose key material is given in MPIS,
into a newly created binary blob, which is to be stored in
BLOB/BLOB_SIZE. Returns zero on success or an error code. */
static gpg_error_t
ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size,
const char *type, gcry_mpi_t *mpis)
{
unsigned char *blob_new;
long int blob_size_new;
estream_t stream;
gpg_error_t err;
unsigned int i;
*blob = NULL;
*blob_size = 0;
blob_new = NULL;
stream = NULL;
err = 0;
stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
if (! stream)
{
err = gpg_error_from_syserror ();
goto out;
}
err = stream_write_cstring (stream, type);
if (err)
goto out;
for (i = 0; mpis[i] && (! err); i++)
err = stream_write_mpi (stream, mpis[i]);
if (err)
goto out;
blob_size_new = es_ftell (stream);
if (blob_size_new == -1)
{
err = gpg_error_from_syserror ();
goto out;
}
-
+
err = es_fseek (stream, 0, SEEK_SET);
if (err)
goto out;
blob_new = xtrymalloc (blob_size_new);
if (! blob_new)
{
err = gpg_error_from_syserror ();
goto out;
}
err = stream_read_data (stream, blob_new, blob_size_new);
if (err)
goto out;
*blob = blob_new;
*blob_size = blob_size_new;
out:
if (stream)
es_fclose (stream);
if (err)
xfree (blob_new);
return err;
}
-
+
/* Write the public key KEY_PUBLIC to STREAM in SSH key format. If
OVERRIDE_COMMENT is not NULL, it will be used instead of the
comment stored in the key. */
static gpg_error_t
ssh_send_key_public (estream_t stream, gcry_sexp_t key_public,
const char *override_comment)
{
ssh_key_type_spec_t spec;
gcry_mpi_t *mpi_list;
char *key_type;
char *comment;
unsigned char *blob;
size_t blob_n;
gpg_error_t err;
key_type = NULL;
mpi_list = NULL;
comment = NULL;
blob = NULL;
err = sexp_extract_identifier (key_public, &key_type);
if (err)
goto out;
err = ssh_key_type_lookup (NULL, key_type, &spec);
if (err)
goto out;
err = sexp_key_extract (key_public, spec, NULL, &mpi_list, &comment);
if (err)
goto out;
err = ssh_convert_key_to_blob (&blob, &blob_n,
spec.ssh_identifier, mpi_list);
if (err)
goto out;
-
+
err = stream_write_string (stream, blob, blob_n);
if (err)
goto out;
err = stream_write_cstring (stream,
override_comment? override_comment : comment);
-
+
out:
mpint_list_free (mpi_list);
xfree (key_type);
xfree (comment);
xfree (blob);
return err;
}
/* Read a public key out of BLOB/BLOB_SIZE according to the key
specification given as KEY_SPEC, storing the new key in KEY_PUBLIC.
Returns zero on success or an error code. */
static gpg_error_t
ssh_read_key_public_from_blob (unsigned char *blob, size_t blob_size,
gcry_sexp_t *key_public,
ssh_key_type_spec_t *key_spec)
{
estream_t blob_stream;
gpg_error_t err;
err = 0;
-
+
blob_stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
if (! blob_stream)
{
err = gpg_error_from_syserror ();
goto out;
}
err = stream_write_data (blob_stream, blob, blob_size);
if (err)
goto out;
err = es_fseek (blob_stream, 0, SEEK_SET);
if (err)
goto out;
err = ssh_receive_key (blob_stream, key_public, 0, 0, key_spec);
out:
if (blob_stream)
es_fclose (blob_stream);
return err;
}
/* This function calculates the key grip for the key contained in the
S-Expression KEY and writes it to BUFFER, which must be large
enough to hold it. Returns usual error code. */
static gpg_error_t
ssh_key_grip (gcry_sexp_t key, unsigned char *buffer)
{
if (!gcry_pk_get_keygrip (key, buffer))
return gpg_error (GPG_ERR_INTERNAL);
return 0;
}
/* Converts the secret key KEY_SECRET into a public key, storing it in
KEY_PUBLIC. SPEC is the according key specification. Returns zero
on success or an error code. */
static gpg_error_t
key_secret_to_public (gcry_sexp_t *key_public,
ssh_key_type_spec_t spec, gcry_sexp_t key_secret)
{
char *comment;
gcry_mpi_t *mpis;
gpg_error_t err;
int is_secret;
comment = NULL;
mpis = NULL;
err = sexp_key_extract (key_secret, spec, &is_secret, &mpis, &comment);
if (err)
goto out;
err = sexp_key_construct (key_public, spec, 0, mpis, comment);
out:
mpint_list_free (mpis);
xfree (comment);
return err;
}
/* Check whether a smartcard is available and whether it has a usable
key. Store a copy of that key at R_PK and return 0. If no key is
available store NULL at R_PK and return an error code. If CARDSN
is not NULL, a string with the serial number of the card will be
a malloced and stored there. */
static gpg_error_t
card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn)
{
gpg_error_t err;
char *authkeyid;
char *serialno = NULL;
unsigned char *pkbuf;
size_t pkbuflen;
gcry_sexp_t s_pk;
unsigned char grip[20];
*r_pk = NULL;
if (cardsn)
*cardsn = NULL;
/* First see whether a card is available and whether the application
is supported. */
err = agent_card_getattr (ctrl, "$AUTHKEYID", &authkeyid);
if ( gpg_err_code (err) == GPG_ERR_CARD_REMOVED )
{
/* Ask for the serial number to reset the card. */
err = agent_card_serialno (ctrl, &serialno);
if (err)
{
if (opt.verbose)
log_info (_("error getting serial number of card: %s\n"),
gpg_strerror (err));
return err;
}
log_info (_("detected card with S/N: %s\n"), serialno);
err = agent_card_getattr (ctrl, "$AUTHKEYID", &authkeyid);
}
if (err)
{
log_error (_("error getting default authentication keyID of card: %s\n"),
gpg_strerror (err));
xfree (serialno);
return err;
}
/* Get the S/N if we don't have it yet. Use the fast getattr method. */
if (!serialno && (err = agent_card_getattr (ctrl, "SERIALNO", &serialno)) )
{
log_error (_("error getting serial number of card: %s\n"),
gpg_strerror (err));
xfree (authkeyid);
return err;
}
/* Read the public key. */
err = agent_card_readkey (ctrl, authkeyid, &pkbuf);
if (err)
{
if (opt.verbose)
log_info (_("no suitable card key found: %s\n"), gpg_strerror (err));
xfree (serialno);
xfree (authkeyid);
return err;
}
pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
err = gcry_sexp_sscan (&s_pk, NULL, (char*)pkbuf, pkbuflen);
if (err)
{
log_error ("failed to build S-Exp from received card key: %s\n",
gpg_strerror (err));
xfree (pkbuf);
xfree (serialno);
xfree (authkeyid);
return err;
}
err = ssh_key_grip (s_pk, grip);
if (err)
{
log_debug ("error computing keygrip from received card key: %s\n",
gcry_strerror (err));
xfree (pkbuf);
gcry_sexp_release (s_pk);
xfree (serialno);
xfree (authkeyid);
return err;
}
if ( agent_key_available (grip) )
{
/* (Shadow)-key is not available in our key storage. */
unsigned char *shadow_info;
unsigned char *tmp;
-
+
shadow_info = make_shadow_info (serialno, authkeyid);
if (!shadow_info)
{
err = gpg_error_from_syserror ();
xfree (pkbuf);
gcry_sexp_release (s_pk);
xfree (serialno);
xfree (authkeyid);
return err;
}
err = agent_shadow_key (pkbuf, shadow_info, &tmp);
xfree (shadow_info);
if (err)
{
log_error (_("shadowing the key failed: %s\n"), gpg_strerror (err));
xfree (pkbuf);
gcry_sexp_release (s_pk);
xfree (serialno);
xfree (authkeyid);
return err;
}
xfree (pkbuf);
pkbuf = tmp;
pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
assert (pkbuflen);
err = agent_write_private_key (grip, pkbuf, pkbuflen, 0);
if (err)
{
log_error (_("error writing key: %s\n"), gpg_strerror (err));
xfree (pkbuf);
gcry_sexp_release (s_pk);
xfree (serialno);
xfree (authkeyid);
return err;
}
}
if (cardsn)
{
char *dispsn;
/* If the card handler is able to return a short serialnumber,
use that one, else use the complete serialno. */
if (!agent_card_getattr (ctrl, "$DISPSERIALNO", &dispsn))
{
*cardsn = xtryasprintf ("cardno:%s", dispsn);
xfree (dispsn);
}
else
*cardsn = xtryasprintf ("cardno:%s", serialno);
if (!*cardsn)
{
err = gpg_error_from_syserror ();
xfree (pkbuf);
gcry_sexp_release (s_pk);
xfree (serialno);
xfree (authkeyid);
return err;
}
}
xfree (pkbuf);
xfree (serialno);
xfree (authkeyid);
*r_pk = s_pk;
return 0;
}
/*
Request handler. Each handler is provided with a CTRL context, a
REQUEST object and a RESPONSE object. The actual request is to be
read from REQUEST, the response needs to be written to RESPONSE.
*/
/* Handler for the "request_identities" command. */
static gpg_error_t
ssh_handler_request_identities (ctrl_t ctrl,
estream_t request, estream_t response)
{
char *key_type;
ssh_key_type_spec_t spec;
struct dirent *dir_entry;
char *key_directory;
size_t key_directory_n;
char *key_path;
unsigned char *buffer;
size_t buffer_n;
u32 key_counter;
estream_t key_blobs;
gcry_sexp_t key_secret;
gcry_sexp_t key_public;
DIR *dir;
gpg_error_t err;
int ret;
FILE *ctrl_fp = NULL;
char *cardsn;
gpg_error_t ret_err;
(void)request;
/* Prepare buffer stream. */
key_directory = NULL;
key_secret = NULL;
key_public = NULL;
key_type = NULL;
key_path = NULL;
key_counter = 0;
buffer = NULL;
dir = NULL;
err = 0;
key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
if (! key_blobs)
{
err = gpg_error_from_syserror ();
goto out;
}
/* Open key directory. */
key_directory = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL);
if (! key_directory)
{
err = gpg_err_code_from_errno (errno);
goto out;
}
key_directory_n = strlen (key_directory);
-
+
key_path = xtrymalloc (key_directory_n + 46);
if (! key_path)
{
err = gpg_err_code_from_errno (errno);
goto out;
}
sprintf (key_path, "%s/", key_directory);
sprintf (key_path + key_directory_n + 41, ".key");
dir = opendir (key_directory);
if (! dir)
{
err = gpg_err_code_from_errno (errno);
goto out;
}
/* First check whether a key is currently available in the card
reader - this should be allowed even without being listed in
sshcontrol. */
if (!card_key_available (ctrl, &key_public, &cardsn))
{
err = ssh_send_key_public (key_blobs, key_public, cardsn);
gcry_sexp_release (key_public);
key_public = NULL;
xfree (cardsn);
if (err)
goto out;
-
+
key_counter++;
}
/* Then look at all the registered an allowed keys. */
/* Fixme: We should better iterate over the control file and check
whether the key file is there. This is better in resepct to
performance if tehre are a lot of key sin our key storage. */
/* FIXME: make sure that buffer gets deallocated properly. */
err = open_control_file (&ctrl_fp, 0);
if (err)
goto out;
while ( (dir_entry = readdir (dir)) )
{
if ((strlen (dir_entry->d_name) == 44)
&& (! strncmp (dir_entry->d_name + 40, ".key", 4)))
{
char hexgrip[41];
int disabled;
/* We do only want to return keys listed in our control
file. */
strncpy (hexgrip, dir_entry->d_name, 40);
hexgrip[40] = 0;
if ( strlen (hexgrip) != 40 )
continue;
if (search_control_file (ctrl_fp, hexgrip, &disabled, NULL)
|| disabled)
continue;
strncpy (key_path + key_directory_n + 1, dir_entry->d_name, 40);
/* Read file content. */
err = file_to_buffer (key_path, &buffer, &buffer_n);
if (err)
goto out;
-
+
err = gcry_sexp_sscan (&key_secret, NULL, (char*)buffer, buffer_n);
if (err)
goto out;
xfree (buffer);
buffer = NULL;
err = sexp_extract_identifier (key_secret, &key_type);
if (err)
goto out;
err = ssh_key_type_lookup (NULL, key_type, &spec);
if (err)
goto out;
xfree (key_type);
key_type = NULL;
err = key_secret_to_public (&key_public, spec, key_secret);
if (err)
goto out;
gcry_sexp_release (key_secret);
key_secret = NULL;
-
+
err = ssh_send_key_public (key_blobs, key_public, NULL);
if (err)
goto out;
gcry_sexp_release (key_public);
key_public = NULL;
key_counter++;
}
}
-
+
ret = es_fseek (key_blobs, 0, SEEK_SET);
if (ret)
{
err = gpg_error_from_syserror ();
goto out;
}
out:
/* Send response. */
gcry_sexp_release (key_secret);
gcry_sexp_release (key_public);
if (! err)
{
ret_err = stream_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER);
if (ret_err)
goto leave;
ret_err = stream_write_uint32 (response, key_counter);
if (ret_err)
goto leave;
ret_err = stream_copy (response, key_blobs);
if (ret_err)
goto leave;
}
else
{
ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
goto leave;
};
leave:
if (key_blobs)
es_fclose (key_blobs);
if (dir)
closedir (dir);
if (ctrl_fp)
fclose (ctrl_fp);
xfree (key_directory);
xfree (key_path);
xfree (buffer);
xfree (key_type);
return ret_err;
}
/* This function hashes the data contained in DATA of size DATA_N
according to the message digest algorithm specified by MD_ALGORITHM
and writes the message digest to HASH, which needs to large enough
for the digest. */
static gpg_error_t
data_hash (unsigned char *data, size_t data_n,
int md_algorithm, unsigned char *hash)
{
gcry_md_hash_buffer (md_algorithm, hash, data, data_n);
return 0;
}
/* This function signs the data contained in CTRL, stores the created
signature in newly allocated memory in SIG and it's size in SIG_N;
SIG_ENCODER is the signature encoder to use. */
static gpg_error_t
data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder,
unsigned char **sig, size_t *sig_n)
{
gpg_error_t err;
gcry_sexp_t signature_sexp = NULL;
estream_t stream = NULL;
gcry_sexp_t valuelist = NULL;
gcry_sexp_t sublist = NULL;
gcry_mpi_t sig_value = NULL;
unsigned char *sig_blob = NULL;
size_t sig_blob_n = 0;
char *identifier = NULL;
const char *identifier_raw;
size_t identifier_n;
ssh_key_type_spec_t spec;
int ret;
unsigned int i;
const char *elems;
size_t elems_n;
gcry_mpi_t *mpis = NULL;
*sig = NULL;
*sig_n = 0;
ctrl->use_auth_call = 1;
err = agent_pksign_do (ctrl,
_("Please enter the passphrase "
"for the ssh key%0A %c"), &signature_sexp,
CACHE_MODE_SSH, ttl_from_sshcontrol);
ctrl->use_auth_call = 0;
if (err)
goto out;
valuelist = gcry_sexp_nth (signature_sexp, 1);
if (! valuelist)
{
err = gpg_error (GPG_ERR_INV_SEXP);
goto out;
}
stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
if (! stream)
{
err = gpg_error_from_syserror ();
goto out;
}
identifier_raw = gcry_sexp_nth_data (valuelist, 0, &identifier_n);
if (! identifier_raw)
{
err = gpg_error (GPG_ERR_INV_SEXP);
goto out;
}
identifier = make_cstring (identifier_raw, identifier_n);
if (! identifier)
{
err = gpg_error_from_syserror ();
goto out;
}
err = ssh_key_type_lookup (NULL, identifier, &spec);
if (err)
goto out;
err = stream_write_cstring (stream, spec.ssh_identifier);
if (err)
goto out;
elems = spec.elems_signature;
elems_n = strlen (elems);
mpis = xtrycalloc (elems_n + 1, sizeof *mpis);
if (!mpis)
{
err = gpg_error_from_syserror ();
goto out;
}
for (i = 0; i < elems_n; i++)
{
sublist = gcry_sexp_find_token (valuelist, spec.elems_signature + i, 1);
if (! sublist)
{
err = gpg_error (GPG_ERR_INV_SEXP);
break;
}
sig_value = gcry_sexp_nth_mpi (sublist, 1, GCRYMPI_FMT_USG);
if (! sig_value)
{
err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */
break;
}
gcry_sexp_release (sublist);
sublist = NULL;
mpis[i] = sig_value;
}
if (err)
goto out;
err = (*sig_encoder) (stream, mpis);
if (err)
goto out;
sig_blob_n = es_ftell (stream);
if (sig_blob_n == -1)
{
err = gpg_error_from_syserror ();
goto out;
}
sig_blob = xtrymalloc (sig_blob_n);
if (! sig_blob)
{
err = gpg_error_from_syserror ();
goto out;
}
ret = es_fseek (stream, 0, SEEK_SET);
if (ret)
{
err = gpg_error_from_syserror ();
goto out;
- }
+ }
err = stream_read_data (stream, sig_blob, sig_blob_n);
if (err)
goto out;
-
+
*sig = sig_blob;
*sig_n = sig_blob_n;
-
+
out:
if (err)
xfree (sig_blob);
if (stream)
es_fclose (stream);
gcry_sexp_release (valuelist);
gcry_sexp_release (signature_sexp);
gcry_sexp_release (sublist);
mpint_list_free (mpis);
xfree (identifier);
return err;
}
/* Handler for the "sign_request" command. */
static gpg_error_t
ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response)
{
gcry_sexp_t key;
ssh_key_type_spec_t spec;
unsigned char hash[MAX_DIGEST_LEN];
unsigned int hash_n;
unsigned char key_grip[20];
unsigned char *key_blob;
u32 key_blob_size;
unsigned char *data;
unsigned char *sig;
size_t sig_n;
u32 data_size;
u32 flags;
gpg_error_t err;
gpg_error_t ret_err;
key_blob = NULL;
data = NULL;
sig = NULL;
key = NULL;
/* Receive key. */
-
+
err = stream_read_string (request, 0, &key_blob, &key_blob_size);
if (err)
goto out;
err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, &spec);
if (err)
goto out;
/* Receive data to sign. */
err = stream_read_string (request, 0, &data, &data_size);
if (err)
goto out;
/* FIXME? */
err = stream_read_uint32 (request, &flags);
if (err)
goto out;
/* Hash data. */
hash_n = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
if (! hash_n)
{
err = gpg_error (GPG_ERR_INTERNAL);
goto out;
}
err = data_hash (data, data_size, GCRY_MD_SHA1, hash);
if (err)
goto out;
/* Calculate key grip. */
err = ssh_key_grip (key, key_grip);
if (err)
goto out;
/* Sign data. */
ctrl->digest.algo = GCRY_MD_SHA1;
memcpy (ctrl->digest.value, hash, hash_n);
ctrl->digest.valuelen = hash_n;
ctrl->digest.raw_value = ! (spec.flags & SPEC_FLAG_USE_PKCS1V2);
ctrl->have_keygrip = 1;
memcpy (ctrl->keygrip, key_grip, 20);
err = data_sign (ctrl, spec.signature_encoder, &sig, &sig_n);
-
+
out:
/* Done. */
if (! err)
{
ret_err = stream_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE);
if (ret_err)
goto leave;
ret_err = stream_write_string (response, sig, sig_n);
if (ret_err)
goto leave;
}
else
{
ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
if (ret_err)
goto leave;
}
-
+
leave:
gcry_sexp_release (key);
xfree (key_blob);
xfree (data);
xfree (sig);
return ret_err;
}
/* This function extracts the comment contained in the key
S-Expression KEY and stores a copy in COMMENT. Returns usual error
code. */
static gpg_error_t
ssh_key_extract_comment (gcry_sexp_t key, char **comment)
{
gcry_sexp_t comment_list;
char *comment_new;
const char *data;
size_t data_n;
gpg_error_t err;
comment_list = gcry_sexp_find_token (key, "comment", 0);
if (! comment_list)
{
err = gpg_error (GPG_ERR_INV_SEXP);
goto out;
}
-
+
data = gcry_sexp_nth_data (comment_list, 1, &data_n);
if (! data)
{
err = gpg_error (GPG_ERR_INV_SEXP);
goto out;
}
comment_new = make_cstring (data, data_n);
if (! comment_new)
{
err = gpg_error_from_syserror ();
goto out;
}
*comment = comment_new;
err = 0;
out:
gcry_sexp_release (comment_list);
return err;
}
/* This function converts the key contained in the S-Expression KEY
into a buffer, which is protected by the passphrase PASSPHRASE.
Returns usual error code. */
static gpg_error_t
ssh_key_to_protected_buffer (gcry_sexp_t key, const char *passphrase,
unsigned char **buffer, size_t *buffer_n)
{
unsigned char *buffer_new;
unsigned int buffer_new_n;
gpg_error_t err;
err = 0;
buffer_new_n = gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, NULL, 0);
buffer_new = xtrymalloc_secure (buffer_new_n);
if (! buffer_new)
{
err = gpg_error_from_syserror ();
goto out;
}
-
+
gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, buffer_new, buffer_new_n);
/* FIXME: guarantee? */
err = agent_protect (buffer_new, passphrase, buffer, buffer_n);
out:
xfree (buffer_new);
return err;
}
/* 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;
}
/* Store the ssh KEY into our local key storage and protect it after
asking for a passphrase. Cache that passphrase. TTL is the
maximum caching time for that key. If the key already exists in
our key storage, don't do anything. When entering a new key also
add an entry to the sshcontrol file. */
static gpg_error_t
ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
{
gpg_error_t err;
unsigned char key_grip_raw[20];
char key_grip[41];
unsigned char *buffer = NULL;
size_t buffer_n;
char *description = NULL;
const char *description2 = _("Please re-enter this passphrase");
char *comment = NULL;
const char *initial_errtext = NULL;
unsigned int i;
struct pin_entry_info_s *pi = NULL, *pi2;
err = ssh_key_grip (key, key_grip_raw);
if (err)
goto out;
/* Check whether the key is already in our key storage. Don't do
anything then. */
if ( !agent_key_available (key_grip_raw) )
goto out; /* Yes, key is available. */
-
+
err = ssh_key_extract_comment (key, &comment);
if (err)
goto out;
if ( asprintf (&description,
_("Please enter a passphrase to protect"
" the received secret key%%0A"
" %s%%0A"
"within gpg-agent's key storage"),
comment ? comment : "?") < 0)
{
err = gpg_error_from_syserror ();
goto out;
}
pi = gcry_calloc_secure (2, sizeof (*pi) + 100 + 1);
if (!pi)
{
err = gpg_error_from_syserror ();
goto out;
}
pi2 = pi + (sizeof *pi + 100 + 1);
pi->max_length = 100;
pi->max_tries = 1;
pi2->max_length = 100;
pi2->max_tries = 1;
pi2->check_cb = reenter_compare_cb;
pi2->check_cb_arg = pi->pin;
next_try:
err = agent_askpin (ctrl, description, NULL, initial_errtext, pi);
initial_errtext = NULL;
if (err)
goto out;
/* Unless the passphrase is empty, ask to confirm it. */
if (pi->pin && *pi->pin)
{
err = agent_askpin (ctrl, description2, 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;
}
}
err = ssh_key_to_protected_buffer (key, pi->pin, &buffer, &buffer_n);
if (err)
goto out;
/* Store this key to our key storage. */
err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0);
if (err)
goto out;
/* Cache this passphrase. */
for (i = 0; i < 20; i++)
sprintf (key_grip + 2 * i, "%02X", key_grip_raw[i]);
err = agent_put_cache (key_grip, CACHE_MODE_SSH, pi->pin, ttl);
if (err)
goto out;
/* And add an entry to the sshcontrol file. */
err = add_control_entry (ctrl, key_grip, ttl);
out:
if (pi && pi->max_length)
wipememory (pi->pin, pi->max_length);
xfree (pi);
xfree (buffer);
xfree (comment);
- xfree (description);
+ xfree (description);
return err;
}
/* This function removes the key contained in the S-Expression KEY
from the local key storage, in case it exists there. Returns usual
error code. FIXME: this function is a stub. */
static gpg_error_t
ssh_identity_drop (gcry_sexp_t key)
{
unsigned char key_grip[21] = { 0 };
gpg_error_t err;
err = ssh_key_grip (key, key_grip);
if (err)
goto out;
key_grip[sizeof (key_grip) - 1] = 0;
/* FIXME: What to do here - forgetting the passphrase or deleting
the key from key cache? */
out:
return err;
}
/* Handler for the "add_identity" command. */
static gpg_error_t
ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response)
{
gpg_error_t ret_err;
gpg_error_t err;
gcry_sexp_t key;
unsigned char b;
int confirm;
int ttl;
-
+
confirm = 0;
key = NULL;
ttl = 0;
/* FIXME? */
err = ssh_receive_key (request, &key, 1, 1, NULL);
if (err)
goto out;
while (1)
{
err = stream_read_byte (request, &b);
if (gpg_err_code (err) == GPG_ERR_EOF)
{
err = 0;
break;
}
switch (b)
{
case SSH_OPT_CONSTRAIN_LIFETIME:
{
u32 n = 0;
err = stream_read_uint32 (request, &n);
if (! err)
ttl = n;
break;
}
case SSH_OPT_CONSTRAIN_CONFIRM:
{
confirm = 1;
break;
}
default:
/* FIXME: log/bad? */
break;
}
}
if (err)
goto out;
/* FIXME: are constraints used correctly? */
err = ssh_identity_register (ctrl, key, ttl);
out:
gcry_sexp_release (key);
if (! err)
ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
else
ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
return ret_err;
}
/* Handler for the "remove_identity" command. */
static gpg_error_t
ssh_handler_remove_identity (ctrl_t ctrl,
estream_t request, estream_t response)
{
unsigned char *key_blob;
u32 key_blob_size;
gcry_sexp_t key;
gpg_error_t ret_err;
gpg_error_t err;
(void)ctrl;
/* Receive key. */
key_blob = NULL;
key = NULL;
-
+
err = stream_read_string (request, 0, &key_blob, &key_blob_size);
if (err)
goto out;
err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, NULL);
if (err)
goto out;
-
+
err = ssh_identity_drop (key);
out:
xfree (key_blob);
gcry_sexp_release (key);
if (! err)
ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
else
ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
return ret_err;
}
/* FIXME: stub function. Actually useful? */
static gpg_error_t
ssh_identities_remove_all (void)
{
gpg_error_t err;
err = 0;
/* FIXME: shall we remove _all_ cache entries or only those
registered through the ssh emulation? */
-
+
return err;
}
/* Handler for the "remove_all_identities" command. */
static gpg_error_t
ssh_handler_remove_all_identities (ctrl_t ctrl,
estream_t request, estream_t response)
{
gpg_error_t ret_err;
gpg_error_t err;
(void)ctrl;
(void)request;
-
+
err = ssh_identities_remove_all ();
if (! err)
ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
else
ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
return ret_err;
}
/* Lock agent? FIXME: stub function. */
static gpg_error_t
ssh_lock (void)
{
gpg_error_t err;
/* FIXME */
log_error ("ssh-agent's lock command is not implemented\n");
err = 0;
return err;
}
/* Unock agent? FIXME: stub function. */
static gpg_error_t
ssh_unlock (void)
{
gpg_error_t err;
log_error ("ssh-agent's unlock command is not implemented\n");
err = 0;
return err;
}
/* Handler for the "lock" command. */
static gpg_error_t
ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response)
{
gpg_error_t ret_err;
gpg_error_t err;
(void)ctrl;
(void)request;
-
+
err = ssh_lock ();
if (! err)
ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
else
ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
return ret_err;
}
/* Handler for the "unlock" command. */
static gpg_error_t
ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response)
{
gpg_error_t ret_err;
gpg_error_t err;
-
+
(void)ctrl;
(void)request;
err = ssh_unlock ();
if (! err)
ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
else
ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
return ret_err;
}
/* Return the request specification for the request identified by TYPE
or NULL in case the requested request specification could not be
found. */
static ssh_request_spec_t *
request_spec_lookup (int type)
{
ssh_request_spec_t *spec;
unsigned int i;
for (i = 0; i < DIM (request_specs); i++)
if (request_specs[i].type == type)
break;
if (i == DIM (request_specs))
{
if (opt.verbose)
log_info ("ssh request %u is not supported\n", type);
spec = NULL;
}
else
spec = request_specs + i;
return spec;
}
/* Process a single request. The request is read from and the
response is written to STREAM_SOCK. Uses CTRL as context. Returns
zero in case of success, non zero in case of failure. */
static int
ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
{
ssh_request_spec_t *spec;
estream_t response;
estream_t request;
unsigned char request_type;
gpg_error_t err;
int send_err;
int ret;
unsigned char *request_data;
u32 request_data_size;
u32 response_size;
request_data = NULL;
response = NULL;
request = NULL;
send_err = 0;
/* Create memory streams for request/response data. The entire
request will be stored in secure memory, since it might contain
secret key material. The response does not have to be stored in
- secure memory, since we never give out secret keys.
+ secure memory, since we never give out secret keys.
Note: we only have little secure memory, but there is NO
possibility of DoS here; only trusted clients are allowed to
connect to the agent. What could happen is that the agent
returns out-of-secure-memory errors on requests in case the
agent's owner floods his own agent with many large messages.
-moritz */
/* Retrieve request. */
err = stream_read_string (stream_sock, 1, &request_data, &request_data_size);
if (err)
goto out;
if (opt.verbose > 1)
log_info ("received ssh request of length %u\n",
(unsigned int)request_data_size);
if (! request_data_size)
{
send_err = 1;
goto out;
/* Broken request; FIXME. */
}
request_type = request_data[0];
spec = request_spec_lookup (request_type);
if (! spec)
{
send_err = 1;
goto out;
/* Unknown request; FIXME. */
}
if (spec->secret_input)
request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+");
else
request = es_mopen (NULL, 0, 0, 1, gcry_realloc, gcry_free, "r+");
if (! request)
{
err = gpg_error_from_syserror ();
goto out;
}
ret = es_setvbuf (request, NULL, _IONBF, 0);
if (ret)
{
err = gpg_error_from_syserror ();
goto out;
}
err = stream_write_data (request, request_data + 1, request_data_size - 1);
if (err)
goto out;
es_rewind (request);
response = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
if (! response)
{
err = gpg_error_from_syserror ();
goto out;
}
if (opt.verbose)
log_info ("ssh request handler for %s (%u) started\n",
spec->identifier, spec->type);
err = (*spec->handler) (ctrl, request, response);
if (opt.verbose)
{
if (err)
log_info ("ssh request handler for %s (%u) failed: %s\n",
spec->identifier, spec->type, gpg_strerror (err));
else
log_info ("ssh request handler for %s (%u) ready\n",
spec->identifier, spec->type);
}
if (err)
{
send_err = 1;
goto out;
}
response_size = es_ftell (response);
if (opt.verbose > 1)
log_info ("sending ssh response of length %u\n",
(unsigned int)response_size);
err = es_fseek (response, 0, SEEK_SET);
if (err)
{
send_err = 1;
goto out;
}
err = stream_write_uint32 (stream_sock, response_size);
if (err)
{
send_err = 1;
goto out;
}
err = stream_copy (stream_sock, response);
if (err)
goto out;
err = es_fflush (stream_sock);
if (err)
goto out;
out:
if (err && es_feof (stream_sock))
log_error ("error occured while processing request: %s\n",
gpg_strerror (err));
if (send_err)
{
if (opt.verbose > 1)
log_info ("sending ssh error response\n");
err = stream_write_uint32 (stream_sock, 1);
if (err)
goto leave;
err = stream_write_byte (stream_sock, SSH_RESPONSE_FAILURE);
if (err)
goto leave;
}
leave:
if (request)
es_fclose (request);
if (response)
es_fclose (response);
xfree (request_data); /* FIXME? */
return !!err;
}
/* Start serving client on SOCK_CLIENT. */
void
start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
{
estream_t stream_sock = NULL;
gpg_error_t err = 0;
int ret;
/* Because the ssh protocol does not send us information about the
the current TTY setting, we resort here to use those from startup
or those explictly set. */
{
- static const char *names[] =
+ static const char *names[] =
{"GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL};
int idx;
const char *value;
for (idx=0; !err && names[idx]; idx++)
if (!session_env_getenv (ctrl->session_env, names[idx])
&& (value = session_env_getenv (opt.startup_env, names[idx])))
err = session_env_setenv (ctrl->session_env, names[idx], value);
-
+
if (!err && !ctrl->lc_ctype && opt.startup_lc_ctype)
if (!(ctrl->lc_ctype = xtrystrdup (opt.startup_lc_ctype)))
err = gpg_error_from_syserror ();
if (!err && !ctrl->lc_messages && opt.startup_lc_messages)
if (!(ctrl->lc_messages = xtrystrdup (opt.startup_lc_messages)))
err = gpg_error_from_syserror ();
if (err)
{
- log_error ("error setting default session environment: %s\n",
+ log_error ("error setting default session environment: %s\n",
gpg_strerror (err));
goto out;
}
}
/* Create stream from socket. */
stream_sock = es_fdopen (FD2INT(sock_client), "r+");
if (!stream_sock)
{
err = gpg_error_from_syserror ();
log_error (_("failed to create stream from socket: %s\n"),
gpg_strerror (err));
goto out;
}
/* We have to disable the estream buffering, because the estream
core doesn't know about secure memory. */
ret = es_setvbuf (stream_sock, NULL, _IONBF, 0);
if (ret)
{
err = gpg_error_from_syserror ();
log_error ("failed to disable buffering "
"on socket stream: %s\n", gpg_strerror (err));
goto out;
}
/* Main processing loop. */
while ( !ssh_request_process (ctrl, stream_sock) )
{
/* Check wether we have reached EOF before trying to read
another request. */
int c;
c = es_fgetc (stream_sock);
if (c == EOF)
break;
es_ungetc (c, stream_sock);
}
/* Reset the SCD in case it has been used. */
agent_reset_scd (ctrl);
out:
if (stream_sock)
es_fclose (stream_sock);
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jan 20, 1:33 AM (20 h, 51 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
88/98/2bf2c0660e1f9de012bf03601a26

Event Timeline