Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F36622889
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
211 KB
Subscribers
None
View Options
diff --git a/agent/ChangeLog b/agent/ChangeLog
index 06d7b85bf..cd19f35cf 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,1743 +1,1751 @@
+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 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/agent.h b/agent/agent.h
index c86ec1e5f..15830de27 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -1,332 +1,337 @@
/* agent.h - Global definitions for the agent
* Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef AGENT_H
#define AGENT_H
#ifdef GPG_ERR_SOURCE_DEFAULT
#error GPG_ERR_SOURCE_DEFAULT already defined
#endif
#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GPGAGENT
#include <gpg-error.h>
#define map_assuan_err(a) \
map_assuan_err_with_source (GPG_ERR_SOURCE_DEFAULT, (a))
#include <errno.h>
#include <gcrypt.h>
#include "../common/util.h"
#include "../common/errors.h"
#include "membuf.h"
/* To convey some special hash algorithms we use algorithm numbers
reserved for application use. */
#ifndef GCRY_MD_USER
#define GCRY_MD_USER 1024
#endif
#define GCRY_MD_USER_TLS_MD5SHA1 (GCRY_MD_USER+1)
/* Maximum length of a digest. */
#define MAX_DIGEST_LEN 36
/* A large struct name "opt" to keep global flags */
struct
{
unsigned int debug; /* Debug flags (DBG_foo_VALUE) */
int verbose; /* Verbosity level */
int quiet; /* Be as quiet as possible */
int dry_run; /* Don't change any persistent data */
int batch; /* Batch mode */
const char *homedir; /* Configuration directory name */
/* Environment setting gathered at program start or changed using the
Assuan command UPDATESTARTUPTTY. */
char *startup_display;
char *startup_ttyname;
char *startup_ttytype;
char *startup_lc_ctype;
char *startup_lc_messages;
const char *pinentry_program; /* Filename of the program to start as
pinentry. */
const char *scdaemon_program; /* Filename of the program to handle
smartcard tasks. */
int disable_scdaemon; /* Never use the SCdaemon. */
int no_grab; /* Don't let the pinentry grab the keyboard */
+ /* The name of the file pinentry shall tocuh before exiting. If
+ this is not set the filoe name of the standard socket is used. */
+ const char *pinentry_touch_file;
+
/* The default and maximum TTL of cache entries. */
unsigned long def_cache_ttl; /* Default. */
unsigned long def_cache_ttl_ssh; /* for SSH. */
unsigned long max_cache_ttl; /* Default. */
unsigned long max_cache_ttl_ssh; /* for SSH. */
/* The require minmum length of a passphrase. */
unsigned int min_passphrase_len;
int running_detached; /* We are running detached from the tty. */
int ignore_cache_for_signing;
int allow_mark_trusted;
int allow_preset_passphrase;
int keep_tty; /* Don't switch the TTY (for pinentry) on request */
int keep_display; /* Don't switch the DISPLAY (for pinentry) on request */
int ssh_support; /* Enable ssh-agent emulation. */
} opt;
#define DBG_COMMAND_VALUE 1 /* debug commands i/o */
#define DBG_MPI_VALUE 2 /* debug mpi details */
#define DBG_CRYPTO_VALUE 4 /* debug low level crypto */
#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */
#define DBG_CACHE_VALUE 64 /* debug the caching */
#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
#define DBG_HASHING_VALUE 512 /* debug hashing operations */
#define DBG_ASSUAN_VALUE 1024
#define DBG_COMMAND (opt.debug & DBG_COMMAND_VALUE)
#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE)
#define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE)
#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
#define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE)
struct server_local_s;
struct scd_local_s;
/* Collection of data per session (aka connection). */
struct server_control_s
{
/* Private data used to fire up the connection thread. We use this
structure do avoid an extra allocation for just a few bytes. */
struct {
int fd;
} thread_startup;
/* Private data of the server (command.c). */
struct server_local_s *server_local;
/* Private data of the SCdaemon (call-scd.c). */
struct scd_local_s *scd_local;
int connection_fd; /* -1 or an identifier for the current connection. */
char *display;
char *ttyname;
char *ttytype;
char *lc_ctype;
char *lc_messages;
struct {
int algo;
unsigned char value[MAX_DIGEST_LEN];
int valuelen;
int raw_value: 1;
} digest;
unsigned char keygrip[20];
int have_keygrip;
int use_auth_call; /* Hack to send the PKAUTH command instead of the
PKSIGN command to the scdaemon. */
};
typedef struct server_control_s *ctrl_t;
struct pin_entry_info_s
{
int min_digits; /* min. number of digits required or 0 for freeform entry */
int max_digits; /* max. number of allowed digits allowed*/
int max_tries;
int failed_tries;
int (*check_cb)(struct pin_entry_info_s *); /* CB used to check the PIN */
void *check_cb_arg; /* optional argument which might be of use in the CB */
const char *cb_errtext; /* used by the cb to displaye a specific error */
size_t max_length; /* allocated length of the buffer */
char pin[1];
};
enum
{
PRIVATE_KEY_UNKNOWN = 0,
PRIVATE_KEY_CLEAR = 1,
PRIVATE_KEY_PROTECTED = 2,
PRIVATE_KEY_SHADOWED = 3
};
/* Values for the cache_mode arguments. */
typedef enum
{
CACHE_MODE_IGNORE = 0, /* Special mode to by pass the cache. */
CACHE_MODE_ANY, /* Any mode except ignore matches. */
CACHE_MODE_NORMAL, /* Normal cache (gpg-agent). */
CACHE_MODE_USER, /* GET_PASSPHRASE related cache. */
CACHE_MODE_SSH /* SSH related cache. */
}
cache_mode_t;
/*-- gpg-agent.c --*/
void agent_exit (int rc) JNLIB_GCC_A_NR; /* Also implemented in other tools */
+const char *get_agent_socket_name (void);
/*-- command.c --*/
gpg_error_t agent_write_status (ctrl_t ctrl, const char *keyword, ...);
void bump_key_eventcounter (void);
void bump_card_eventcounter (void);
void start_command_handler (ctrl_t, int, int);
/*-- command-ssh.c --*/
void start_command_handler_ssh (ctrl_t, int);
/*-- findkey.c --*/
int agent_write_private_key (const unsigned char *grip,
const void *buffer, size_t length, int force);
gpg_error_t agent_key_from_file (ctrl_t ctrl,
const char *desc_text,
const unsigned char *grip,
unsigned char **shadow_info,
cache_mode_t cache_mode,
gcry_sexp_t *result);
gpg_error_t agent_public_key_from_file (ctrl_t ctrl,
const unsigned char *grip,
gcry_sexp_t *result);
int agent_key_available (const unsigned char *grip);
/*-- query.c --*/
void initialize_module_query (void);
void agent_query_dump_state (void);
void agent_reset_query (ctrl_t ctrl);
int pinentry_active_p (ctrl_t ctrl, int waitseconds);
int agent_askpin (ctrl_t ctrl,
const char *desc_text, const char *prompt_text,
const char *inital_errtext,
struct pin_entry_info_s *pininfo);
int agent_get_passphrase (ctrl_t ctrl, char **retpass,
const char *desc, const char *prompt,
const char *errtext);
int agent_get_confirmation (ctrl_t ctrl, const char *desc, const char *ok,
const char *cancel);
int agent_popup_message_start (ctrl_t ctrl,
const char *desc, const char *ok_btn);
void agent_popup_message_stop (ctrl_t ctrl);
/*-- cache.c --*/
void agent_flush_cache (void);
int agent_put_cache (const char *key, cache_mode_t cache_mode,
const char *data, int ttl);
const char *agent_get_cache (const char *key, cache_mode_t cache_mode,
void **cache_id);
void agent_unlock_cache_entry (void **cache_id);
/*-- pksign.c --*/
int agent_pksign_do (ctrl_t ctrl, const char *desc_text,
gcry_sexp_t *signature_sexp,
cache_mode_t cache_mode);
int agent_pksign (ctrl_t ctrl, const char *desc_text,
membuf_t *outbuf, cache_mode_t cache_mode);
/*-- pkdecrypt.c --*/
int agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
const unsigned char *ciphertext, size_t ciphertextlen,
membuf_t *outbuf);
/*-- genkey.c --*/
int check_passphrase_constraints (ctrl_t ctrl, const char *pw);
int agent_genkey (ctrl_t ctrl,
const char *keyparam, size_t keyparmlen, membuf_t *outbuf);
int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey);
/*-- protect.c --*/
int agent_protect (const unsigned char *plainkey, const char *passphrase,
unsigned char **result, size_t *resultlen);
int agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
unsigned char **result, size_t *resultlen);
int agent_private_key_type (const unsigned char *privatekey);
unsigned char *make_shadow_info (const char *serialno, const char *idstring);
int agent_shadow_key (const unsigned char *pubkey,
const unsigned char *shadow_info,
unsigned char **result);
int agent_get_shadow_info (const unsigned char *shadowkey,
unsigned char const **shadow_info);
/*-- trustlist.c --*/
gpg_error_t agent_istrusted (ctrl_t ctrl, const char *fpr);
gpg_error_t agent_listtrusted (void *assuan_context);
gpg_error_t agent_marktrusted (ctrl_t ctrl, const char *name,
const char *fpr, int flag);
void agent_reload_trustlist (void);
/*-- divert-scd.c --*/
int divert_pksign (ctrl_t ctrl,
const unsigned char *digest, size_t digestlen, int algo,
const unsigned char *shadow_info, unsigned char **r_sig);
int divert_pkdecrypt (ctrl_t ctrl,
const unsigned char *cipher,
const unsigned char *shadow_info,
char **r_buf, size_t *r_len);
int divert_generic_cmd (ctrl_t ctrl,
const char *cmdline, void *assuan_context);
/*-- call-scd.c --*/
void initialize_module_call_scd (void);
void agent_scd_dump_state (void);
void agent_scd_check_aliveness (void);
int agent_reset_scd (ctrl_t ctrl);
int agent_card_learn (ctrl_t ctrl,
void (*kpinfo_cb)(void*, const char *),
void *kpinfo_cb_arg,
void (*certinfo_cb)(void*, const char *),
void *certinfo_cb_arg,
void (*sinfo_cb)(void*, const char *,
size_t, const char *),
void *sinfo_cb_arg);
int agent_card_serialno (ctrl_t ctrl, char **r_serialno);
int agent_card_pksign (ctrl_t ctrl,
const char *keyid,
int (*getpin_cb)(void *, const char *, char*, size_t),
void *getpin_cb_arg,
const unsigned char *indata, size_t indatalen,
unsigned char **r_buf, size_t *r_buflen);
int agent_card_pkdecrypt (ctrl_t ctrl,
const char *keyid,
int (*getpin_cb)(void *, const char *, char*,size_t),
void *getpin_cb_arg,
const unsigned char *indata, size_t indatalen,
char **r_buf, size_t *r_buflen);
int agent_card_readcert (ctrl_t ctrl,
const char *id, char **r_buf, size_t *r_buflen);
int agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf);
gpg_error_t agent_card_getattr (ctrl_t ctrl, const char *name, char **result);
int agent_card_scd (ctrl_t ctrl, const char *cmdline,
int (*getpin_cb)(void *, const char *, char*, size_t),
void *getpin_cb_arg, void *assuan_context);
/*-- learncard.c --*/
int agent_handle_learn (ctrl_t ctrl, void *assuan_context);
#endif /*AGENT_H*/
diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c
index bb3b5deb5..8b527b2d5 100644
--- a/agent/call-pinentry.c
+++ b/agent/call-pinentry.c
@@ -1,740 +1,765 @@
/* call-pinnetry.c - fork of the pinentry to query stuff from the user
* Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <unistd.h>
#include <sys/stat.h>
#ifndef HAVE_W32_SYSTEM
#include <sys/wait.h>
#endif
#include <pth.h>
#include <assuan.h>
#include "agent.h"
#include "i18n.h"
#ifdef _POSIX_OPEN_MAX
#define MAX_OPEN_FDS _POSIX_OPEN_MAX
#else
#define MAX_OPEN_FDS 20
#endif
/* Because access to the pinentry must be serialized (it is and shall
be a global mutual dialog) we should better timeout further
requests after some time. 2 minutes seem to be a reasonable
time. */
#define LOCK_TIMEOUT (1*60)
/* The assuan context of the current pinentry. */
static assuan_context_t entry_ctx;
/* The control variable of the connection owning the current pinentry.
This is only valid if ENTRY_CTX is not NULL. Note, that we care
only about the value of the pointer and that it should never be
dereferenced. */
static ctrl_t entry_owner;
/* A mutex used to serialize access to the pinentry. */
static pth_mutex_t entry_lock;
/* The thread ID of the popup working thread. */
static pth_t popup_tid;
/* A flag used in communication between the popup working thread and
its stop function. */
static int popup_finished;
/* Data to be passed to our callbacks, */
struct entry_parm_s
{
int lines;
size_t size;
unsigned char *buffer;
};
/* This function must be called once to initialize this module. This
has to be done before a second thread is spawned. We can't do the
static initialization because Pth emulation code might not be able
to do a static init; in particular, it is not possible for W32. */
void
initialize_module_query (void)
{
static int initialized;
if (!initialized)
{
if (pth_mutex_init (&entry_lock))
initialized = 1;
}
}
static void
dump_mutex_state (pth_mutex_t *m)
{
if (!(m->mx_state & PTH_MUTEX_INITIALIZED))
log_printf ("not_initialized");
else if (!(m->mx_state & PTH_MUTEX_LOCKED))
log_printf ("not_locked");
else
log_printf ("locked tid=0x%lx count=%lu", (long)m->mx_owner, m->mx_count);
}
/* This function may be called to print infromation pertaining to the
current state of this module to the log. */
void
agent_query_dump_state (void)
{
log_info ("agent_query_dump_state: entry_lock=");
dump_mutex_state (&entry_lock);
log_printf ("\n");
log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n",
entry_ctx, (long)assuan_get_pid (entry_ctx), popup_tid);
}
/* Called to make sure that a popup window owned by the current
connection gets closed. */
void
agent_reset_query (ctrl_t ctrl)
{
if (entry_ctx && popup_tid && entry_owner == ctrl)
{
agent_popup_message_stop (ctrl);
}
}
/* Unlock the pinentry so that another thread can start one and
disconnect that pinentry - we do this after the unlock so that a
stalled pinentry does not block other threads. Fixme: We should
have a timeout in Assuan for the disconnect operation. */
static int
unlock_pinentry (int rc)
{
assuan_context_t ctx = entry_ctx;
entry_ctx = NULL;
if (!pth_mutex_release (&entry_lock))
{
log_error ("failed to release the entry lock\n");
if (!rc)
rc = gpg_error (GPG_ERR_INTERNAL);
}
assuan_disconnect (ctx);
return rc;
}
/* To make sure we leave no secrets in our image after forking of the
pinentry, we use this callback. */
static void
atfork_cb (void *opaque, int where)
{
if (!where)
gcry_control (GCRYCTL_TERM_SECMEM);
}
/* Fork off the pin entry if this has not already been done. Note,
that this function must always be used to aquire the lock for the
pinentry - we will serialize _all_ pinentry calls.
*/
static int
start_pinentry (ctrl_t ctrl)
{
int rc;
const char *pgmname;
assuan_context_t ctx;
const char *argv[5];
int no_close_list[3];
int i;
pth_event_t evt;
+ const char *tmpstr;
evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
if (!pth_mutex_acquire (&entry_lock, 0, evt))
{
if (pth_event_occurred (evt))
rc = gpg_error (GPG_ERR_TIMEOUT);
else
rc = gpg_error (GPG_ERR_INTERNAL);
pth_event_free (evt, PTH_FREE_THIS);
log_error (_("failed to acquire the pinentry lock: %s\n"),
gpg_strerror (rc));
return rc;
}
pth_event_free (evt, PTH_FREE_THIS);
entry_owner = ctrl;
if (entry_ctx)
return 0;
if (opt.verbose)
log_info ("starting a new PIN Entry\n");
if (fflush (NULL))
{
gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
log_error ("error flushing pending output: %s\n", strerror (errno));
return unlock_pinentry (tmperr);
}
if (!opt.pinentry_program || !*opt.pinentry_program)
opt.pinentry_program = GNUPG_DEFAULT_PINENTRY;
if ( !(pgmname = strrchr (opt.pinentry_program, '/')))
pgmname = opt.pinentry_program;
else
pgmname++;
argv[0] = pgmname;
if (ctrl->display && !opt.keep_display)
{
argv[1] = "--display";
argv[2] = ctrl->display;
argv[3] = NULL;
}
else
argv[1] = NULL;
i=0;
if (!opt.running_detached)
{
if (log_get_fd () != -1)
no_close_list[i++] = log_get_fd ();
no_close_list[i++] = fileno (stderr);
}
no_close_list[i] = -1;
/* Connect to the pinentry and perform initial handshaking */
rc = assuan_pipe_connect_ext (&ctx, opt.pinentry_program, argv,
no_close_list, atfork_cb, NULL, 0);
if (rc)
{
log_error ("can't connect to the PIN entry module: %s\n",
gpg_strerror (rc));
return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY));
}
entry_ctx = ctx;
if (DBG_ASSUAN)
log_debug ("connection to PIN entry established\n");
rc = assuan_transact (entry_ctx,
opt.no_grab? "OPTION no-grab":"OPTION grab",
NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (rc);
if (ctrl->ttyname)
{
char *optstr;
if (asprintf (&optstr, "OPTION ttyname=%s", ctrl->ttyname) < 0 )
return unlock_pinentry (out_of_core ());
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
free (optstr);
if (rc)
return unlock_pinentry (rc);
}
if (ctrl->ttytype)
{
char *optstr;
if (asprintf (&optstr, "OPTION ttytype=%s", ctrl->ttytype) < 0 )
return unlock_pinentry (out_of_core ());
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
if (rc)
return unlock_pinentry (rc);
}
if (ctrl->lc_ctype)
{
char *optstr;
if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
return unlock_pinentry (out_of_core ());
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
if (rc)
return unlock_pinentry (rc);
}
if (ctrl->lc_messages)
{
char *optstr;
if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
return unlock_pinentry (out_of_core ());
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
if (rc)
return unlock_pinentry (rc);
}
+
+
+ /* Tell the pinentry the name of a file it shall touch after having
+ messed with the tty. This is optional and only supported by
+ newer pinentries and thus we do no error checking. */
+ tmpstr = opt.pinentry_touch_file;
+ if (tmpstr && !strcmp (tmpstr, "/dev/null"))
+ tmpstr = NULL;
+ else if (!tmpstr)
+ tmpstr = get_agent_socket_name ();
+ if (tmpstr)
+ {
+ char *optstr;
+
+ if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
+ ;
+ else
+ {
+ assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
+ NULL);
+ free (optstr);
+ }
+ }
+
return 0;
}
/* Returns True is the pinentry is currently active. If WAITSECONDS is
greater than zero the function will wait for this many seconds
before returning. */
int
pinentry_active_p (ctrl_t ctrl, int waitseconds)
{
if (waitseconds > 0)
{
pth_event_t evt;
int rc;
evt = pth_event (PTH_EVENT_TIME, pth_timeout (waitseconds, 0));
if (!pth_mutex_acquire (&entry_lock, 0, evt))
{
if (pth_event_occurred (evt))
rc = gpg_error (GPG_ERR_TIMEOUT);
else
rc = gpg_error (GPG_ERR_INTERNAL);
pth_event_free (evt, PTH_FREE_THIS);
return rc;
}
pth_event_free (evt, PTH_FREE_THIS);
}
else
{
if (!pth_mutex_acquire (&entry_lock, 1, NULL))
return gpg_error (GPG_ERR_LOCKED);
}
if (!pth_mutex_release (&entry_lock))
log_error ("failed to release the entry lock at %d\n", __LINE__);
return 0;
}
static int
getpin_cb (void *opaque, const void *buffer, size_t length)
{
struct entry_parm_s *parm = opaque;
if (!buffer)
return 0;
/* we expect the pin to fit on one line */
if (parm->lines || length >= parm->size)
return gpg_error (GPG_ERR_ASS_TOO_MUCH_DATA);
/* fixme: we should make sure that the assuan buffer is allocated in
secure memory or read the response byte by byte */
memcpy (parm->buffer, buffer, length);
parm->buffer[length] = 0;
parm->lines++;
return 0;
}
static int
all_digitsp( const char *s)
{
for (; *s && *s >= '0' && *s <= '9'; s++)
;
return !*s;
}
/* Call the Entry and ask for the PIN. We do check for a valid PIN
number here and repeat it as long as we have invalid formed
numbers. */
int
agent_askpin (ctrl_t ctrl,
const char *desc_text, const char *prompt_text,
const char *initial_errtext,
struct pin_entry_info_s *pininfo)
{
int rc;
char line[ASSUAN_LINELENGTH];
struct entry_parm_s parm;
const char *errtext = NULL;
int is_pin = 0;
if (opt.batch)
return 0; /* fixme: we should return BAD PIN */
if (!pininfo || pininfo->max_length < 1)
return gpg_error (GPG_ERR_INV_VALUE);
if (!desc_text && pininfo->min_digits)
desc_text = _("Please enter your PIN, so that the secret key "
"can be unlocked for this session");
else if (!desc_text)
desc_text = _("Please enter your passphrase, so that the secret key "
"can be unlocked for this session");
if (prompt_text)
is_pin = !!strstr (prompt_text, "PIN");
else
is_pin = desc_text && strstr (desc_text, "PIN");
rc = start_pinentry (ctrl);
if (rc)
return rc;
snprintf (line, DIM(line)-1, "SETDESC %s", desc_text);
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (rc);
snprintf (line, DIM(line)-1, "SETPROMPT %s",
prompt_text? prompt_text : is_pin? "PIN:" : "Passphrase:");
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (rc);
if (initial_errtext)
{
snprintf (line, DIM(line)-1, "SETERROR %s", initial_errtext);
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line,
NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (rc);
}
for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
{
memset (&parm, 0, sizeof parm);
parm.size = pininfo->max_length;
parm.buffer = (unsigned char*)pininfo->pin;
if (errtext)
{
/* TRANLATORS: The string is appended to an error message in
the pinentry. The %s is the actual error message, the
two %d give the current and maximum number of tries. */
snprintf (line, DIM(line)-1, _("SETERROR %s (try %d of %d)"),
errtext, pininfo->failed_tries+1, pininfo->max_tries);
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line,
NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (rc);
errtext = NULL;
}
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
NULL, NULL, NULL, NULL);
/* Most pinentries out in the wild return the old Assuan error code
for canceled which gets translated to an assuan Cancel error and
not to the code for a user cancel. Fix this here. */
if (rc && gpg_err_source (rc)
&& gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
errtext = is_pin? _("PIN too long")
: _("Passphrase too long");
else if (rc)
return unlock_pinentry (rc);
if (!errtext && pininfo->min_digits)
{
/* do some basic checks on the entered PIN. */
if (!all_digitsp (pininfo->pin))
errtext = _("Invalid characters in PIN");
else if (pininfo->max_digits
&& strlen (pininfo->pin) > pininfo->max_digits)
errtext = _("PIN too long");
else if (strlen (pininfo->pin) < pininfo->min_digits)
errtext = _("PIN too short");
}
if (!errtext && pininfo->check_cb)
{
/* More checks by utilizing the optional callback. */
pininfo->cb_errtext = NULL;
rc = pininfo->check_cb (pininfo);
if (rc == -1 && pininfo->cb_errtext)
errtext = pininfo->cb_errtext;
else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
|| gpg_err_code (rc) == GPG_ERR_BAD_PIN)
errtext = (is_pin? _("Bad PIN")
: _("Bad Passphrase"));
else if (rc)
return unlock_pinentry (rc);
}
if (!errtext)
return unlock_pinentry (0); /* okay, got a PIN or passphrase */
}
return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
: GPG_ERR_BAD_PASSPHRASE));
}
/* Ask for the passphrase using the supplied arguments. The returned
passphrase needs to be freed by the caller. */
int
agent_get_passphrase (ctrl_t ctrl,
char **retpass, const char *desc, const char *prompt,
const char *errtext)
{
int rc;
char line[ASSUAN_LINELENGTH];
struct entry_parm_s parm;
*retpass = NULL;
if (opt.batch)
return gpg_error (GPG_ERR_BAD_PASSPHRASE);
rc = start_pinentry (ctrl);
if (rc)
return rc;
if (!prompt)
prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");
if (desc)
snprintf (line, DIM(line)-1, "SETDESC %s", desc);
else
snprintf (line, DIM(line)-1, "RESET");
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (rc);
snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (rc);
if (errtext)
{
snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (rc);
}
memset (&parm, 0, sizeof parm);
parm.size = ASSUAN_LINELENGTH/2 - 5;
parm.buffer = gcry_malloc_secure (parm.size+10);
if (!parm.buffer)
return unlock_pinentry (out_of_core ());
assuan_begin_confidential (entry_ctx);
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
NULL, NULL, NULL, NULL);
/* Most pinentries out in the wild return the old Assuan error code
for canceled which gets translated to an assuan Cancel error and
not to the code for a user cancel. Fix this here. */
if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
if (rc)
xfree (parm.buffer);
else
*retpass = parm.buffer;
return unlock_pinentry (rc);
}
/* Pop up the PIN-entry, display the text and the prompt and ask the
user to confirm this. We return 0 for success, ie. the user
confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
other error. */
int
agent_get_confirmation (ctrl_t ctrl,
const char *desc, const char *ok, const char *cancel)
{
int rc;
char line[ASSUAN_LINELENGTH];
rc = start_pinentry (ctrl);
if (rc)
return rc;
if (desc)
snprintf (line, DIM(line)-1, "SETDESC %s", desc);
else
snprintf (line, DIM(line)-1, "RESET");
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
/* Most pinentries out in the wild return the old Assuan error code
for canceled which gets translated to an assuan Cancel error and
not to the code for a user cancel. Fix this here. */
if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
if (rc)
return unlock_pinentry (rc);
if (ok)
{
snprintf (line, DIM(line)-1, "SETOK %s", ok);
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (rc);
}
if (cancel)
{
snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel);
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (rc);
}
rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
return unlock_pinentry (rc);
}
/* The thread running the popup message. */
static void *
popup_message_thread (void *arg)
{
/* We use the --one-button hack instead of the MESSAGE command to
allow the use of old Pinentries. Those old Pinentries will then
show an additional Cancel button but that is mostly a visual
annoyance. */
assuan_transact (entry_ctx, "CONFIRM --one-button",
NULL, NULL, NULL, NULL, NULL, NULL);
popup_finished = 1;
return NULL;
}
/* Pop up a message window similar to the confirm one but keep it open
until agent_popup_message_stop has been called. It is crucial for
the caller to make sure that the stop function gets called as soon
as the message is not anymore required because the message is
system modal and all other attempts to use the pinentry will fail
(after a timeout). */
int
agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
{
int rc;
char line[ASSUAN_LINELENGTH];
pth_attr_t tattr;
rc = start_pinentry (ctrl);
if (rc)
return rc;
if (desc)
snprintf (line, DIM(line)-1, "SETDESC %s", desc);
else
snprintf (line, DIM(line)-1, "RESET");
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (rc);
if (ok_btn)
{
snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
if (rc)
return unlock_pinentry (rc);
}
tattr = pth_attr_new();
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");
popup_finished = 0;
popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
if (!popup_tid)
{
rc = gpg_error_from_syserror ();
log_error ("error spawning popup message handler: %s\n",
strerror (errno) );
pth_attr_destroy (tattr);
return unlock_pinentry (rc);
}
pth_attr_destroy (tattr);
return 0;
}
/* Close a popup window. */
void
agent_popup_message_stop (ctrl_t ctrl)
{
int rc;
pid_t pid;
if (!popup_tid || !entry_ctx)
{
log_debug ("agent_popup_message_stop called with no active popup\n");
return;
}
pid = assuan_get_pid (entry_ctx);
if (pid == (pid_t)(-1))
; /* No pid available can't send a kill. */
else if (popup_finished)
; /* Already finished and ready for joining. */
else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
{ /* The daemon already died. No need to send a kill. However
because we already waited for the process, we need to tell
assuan that it should not wait again (done by
unlock_pinentry). */
if (rc == pid)
assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
}
else if (pid > 0)
kill (pid, SIGKILL); /* Need to use SIGKILL due to bad
interaction of SIGINT with Pth. */
/* Now wait for the thread to terminate. */
rc = pth_join (popup_tid, NULL);
if (!rc)
log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
strerror (errno));
popup_tid = NULL;
entry_owner = NULL;
/* Now we can close the connection. */
unlock_pinentry (0);
}
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 72a4013d6..c88e22cc1 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -1,1784 +1,1798 @@
/* gpg-agent.c - The GnuPG Agent
* Copyright (C) 2000, 2001, 2002, 2003, 2004,
* 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <time.h>
#include <fcntl.h>
#include <sys/stat.h>
#ifndef HAVE_W32_SYSTEM
#include <sys/socket.h>
#include <sys/un.h>
#endif /*HAVE_W32_SYSTEM*/
#include <unistd.h>
#include <signal.h>
#include <pth.h>
#define JNLIB_NEED_LOG_LOGV
#include "agent.h"
#include <assuan.h> /* Malloc hooks */
#include "i18n.h"
#include "sysutils.h"
#ifdef HAVE_W32_SYSTEM
#include "../jnlib/w32-afunix.h"
#endif
#include "setenv.h"
enum cmd_and_opt_values
{ aNull = 0,
oCsh = 'c',
oQuiet = 'q',
oSh = 's',
oVerbose = 'v',
oNoVerbose = 500,
aGPGConfList,
aGPGConfTest,
oOptions,
oDebug,
oDebugAll,
oDebugLevel,
oDebugWait,
oNoGreeting,
oNoOptions,
oHomedir,
oNoDetach,
oNoGrab,
oLogFile,
oServer,
oDaemon,
oBatch,
oPinentryProgram,
+ oPinentryTouchFile,
oDisplay,
oTTYname,
oTTYtype,
oLCctype,
oLCmessages,
oScdaemonProgram,
oDefCacheTTL,
oDefCacheTTLSSH,
oMaxCacheTTL,
oMaxCacheTTLSSH,
oMinPassphraseLen,
oUseStandardSocket,
oNoUseStandardSocket,
oIgnoreCacheForSigning,
oAllowMarkTrusted,
oAllowPresetPassphrase,
oKeepTTY,
oKeepDISPLAY,
oSSHSupport,
oDisableScdaemon,
oWriteEnvFile
};
static ARGPARSE_OPTS opts[] = {
{ aGPGConfList, "gpgconf-list", 256, "@" },
{ aGPGConfTest, "gpgconf-test", 256, "@" },
{ 301, NULL, 0, N_("@Options:\n ") },
{ oServer, "server", 0, N_("run in server mode (foreground)") },
{ oDaemon, "daemon", 0, N_("run in daemon mode (background)") },
{ oVerbose, "verbose", 0, N_("verbose") },
{ oQuiet, "quiet", 0, N_("be somewhat more quiet") },
{ oSh, "sh", 0, N_("sh-style command output") },
{ oCsh, "csh", 0, N_("csh-style command output") },
{ oOptions, "options" , 2, N_("|FILE|read options from FILE")},
{ oDebug, "debug" ,4|16, "@"},
{ oDebugAll, "debug-all" ,0, "@"},
{ oDebugLevel, "debug-level" ,2, "@"},
{ oDebugWait,"debug-wait",1, "@"},
{ oNoDetach, "no-detach" ,0, N_("do not detach from the console")},
{ oNoGrab, "no-grab" ,0, N_("do not grab keyboard and mouse")},
{ oLogFile, "log-file" ,2, N_("use a log file for the server")},
{ oUseStandardSocket, "use-standard-socket", 0,
N_("use a standard location for the socket")},
{ oNoUseStandardSocket, "no-use-standard-socket", 0, "@"},
{ oPinentryProgram, "pinentry-program", 2 ,
N_("|PGM|use PGM as the PIN-Entry program") },
+ { oPinentryTouchFile, "pinentry-touch-file", 2 , "@" },
{ oScdaemonProgram, "scdaemon-program", 2 ,
N_("|PGM|use PGM as the SCdaemon program") },
{ oDisableScdaemon, "disable-scdaemon", 0, N_("do not use the SCdaemon") },
{ oDisplay, "display", 2, "@" },
{ oTTYname, "ttyname", 2, "@" },
{ oTTYtype, "ttytype", 2, "@" },
{ oLCctype, "lc-ctype", 2, "@" },
{ oLCmessages, "lc-messages", 2, "@" },
{ oKeepTTY, "keep-tty", 0, N_("ignore requests to change the TTY")},
{ oKeepDISPLAY, "keep-display",
0, N_("ignore requests to change the X display")},
{ oDefCacheTTL, "default-cache-ttl", 4,
N_("|N|expire cached PINs after N seconds")},
{ oDefCacheTTLSSH, "default-cache-ttl-ssh", 4, "@" },
{ oMaxCacheTTL, "max-cache-ttl", 4, "@" },
{ oMaxCacheTTLSSH, "max-cache-ttl-ssh", 4, "@" },
{ oMinPassphraseLen, "min-passphrase-len", 4, "@" },
{ oIgnoreCacheForSigning, "ignore-cache-for-signing", 0,
N_("do not use the PIN cache when signing")},
{ oAllowMarkTrusted, "allow-mark-trusted", 0,
N_("allow clients to mark keys as \"trusted\"")},
{ oAllowPresetPassphrase, "allow-preset-passphrase", 0,
N_("allow presetting passphrase")},
{ oSSHSupport, "enable-ssh-support", 0, N_("enable ssh-agent emulation") },
{ oWriteEnvFile, "write-env-file", 2|8,
N_("|FILE|write environment settings also to FILE")},
{0}
};
#define DEFAULT_CACHE_TTL (10*60) /* 10 minutes */
#define DEFAULT_CACHE_TTL_SSH (30*60) /* 30 minutes */
#define MAX_CACHE_TTL (120*60) /* 2 hours */
#define MIN_PASSPHRASE_LEN (8)
/* flag to indicate that a shutdown was requested */
static int shutdown_pending;
/* It is possible that we are currently running under setuid permissions */
static int maybe_setuid = 1;
/* Name of the communication socket used for native gpg-agent requests. */
static char *socket_name;
/* Name of the communication socket used for ssh-agent-emulation. */
static char *socket_name_ssh;
/* Default values for options passed to the pinentry. */
static char *default_display;
static char *default_ttyname;
static char *default_ttytype;
static char *default_lc_ctype;
static char *default_lc_messages;
/* Name of a config file, which will be reread on a HUP if it is not NULL. */
static char *config_filename;
/* Helper to implement --debug-level */
static const char *debug_level;
/* Keep track of the current log file so that we can avoid updating
the log file after a SIGHUP if it didn't changed. Malloced. */
static char *current_logfile;
/* The handle_tick() function may test whether a parent is still
running. We record the PID of the parent here or -1 if it should be
watched. */
static pid_t parent_pid = (pid_t)(-1);
/*
Local prototypes.
*/
static char *create_socket_name (int use_standard_socket,
char *standard_name, char *template);
static int create_server_socket (int is_standard_name, const char *name);
static void create_directories (void);
static void agent_init_default_ctrl (ctrl_t ctrl);
static void agent_deinit_default_ctrl (ctrl_t ctrl);
static void handle_connections (int listen_fd, int listen_fd_ssh);
static int check_for_running_agent (int);
/* Pth wrapper function definitions. */
GCRY_THREAD_OPTION_PTH_IMPL;
/*
Functions.
*/
static const char *
my_strusage (int level)
{
const char *p;
switch (level)
{
case 11: p = "gpg-agent (GnuPG)";
break;
case 13: p = VERSION; break;
case 17: p = PRINTABLE_OS_NAME; break;
case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
break;
case 1:
case 40: p = _("Usage: gpg-agent [options] (-h for help)");
break;
case 41: p = _("Syntax: gpg-agent [options] [command [args]]\n"
"Secret key management for GnuPG\n");
break;
default: p = NULL;
}
return p;
}
static void
i18n_init (void)
{
#ifdef USE_SIMPLE_GETTEXT
set_gettext_file( PACKAGE_GT );
#else
#ifdef ENABLE_NLS
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE_GT, LOCALEDIR);
textdomain (PACKAGE_GT);
#endif
#endif
}
/* Used by gcry for logging */
static void
my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
{
/* translate the log levels */
switch (level)
{
case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break;
case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
default: level = JNLIB_LOG_ERROR; break;
}
log_logv (level, fmt, arg_ptr);
}
/* This function is called by libgcrypt if it ran out of core and
there is no way to return that error to the caller. We do our own
function here to make use of our logging functions. */
static int
my_gcry_outofcore_handler ( void *opaque, size_t req_n, unsigned int flags)
{
static int been_here; /* Used to protect against recursive calls. */
if (!been_here)
{
been_here = 1;
if ( (flags & 1) )
log_fatal (_("out of core in secure memory "
"while allocating %lu bytes"), (unsigned long)req_n);
else
log_fatal (_("out of core while allocating %lu bytes"),
(unsigned long)req_n);
}
return 0; /* Let libgcrypt call its own fatal error handler. */
}
/* Setup the debugging. With the global variable DEBUG_LEVEL set to NULL
only the active debug flags are propagated to the subsystems. With
DEBUG_LEVEL set, a specific set of debug flags is set; thus overriding
all flags already set. Note that we don't fail here, because it is
important to keep gpg-agent running even after re-reading the
options due to a SIGHUP. */
static void
set_debug (void)
{
if (!debug_level)
;
else if (!strcmp (debug_level, "none"))
opt.debug = 0;
else if (!strcmp (debug_level, "basic"))
opt.debug = DBG_ASSUAN_VALUE;
else if (!strcmp (debug_level, "advanced"))
opt.debug = DBG_ASSUAN_VALUE|DBG_COMMAND_VALUE;
else if (!strcmp (debug_level, "expert"))
opt.debug = (DBG_ASSUAN_VALUE|DBG_COMMAND_VALUE
|DBG_CACHE_VALUE);
else if (!strcmp (debug_level, "guru"))
opt.debug = ~0;
else
{
log_error (_("invalid debug-level `%s' given\n"), debug_level);
opt.debug = 0; /* Reset debugging, so that prior debug
statements won't have an undesired effect. */
}
if (opt.debug && !opt.verbose)
opt.verbose = 1;
if (opt.debug && opt.quiet)
opt.quiet = 0;
if (opt.debug & DBG_MPI_VALUE)
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2);
if (opt.debug & DBG_CRYPTO_VALUE )
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
}
/* Helper for cleanup to remove one socket with NAME. */
static void
remove_socket (char *name)
{
if (name && *name)
{
char *p;
remove (name);
p = strrchr (name, '/');
if (p)
{
*p = 0;
rmdir (name);
*p = '/';
}
*name = 0;
}
}
static void
cleanup (void)
{
remove_socket (socket_name);
remove_socket (socket_name_ssh);
}
/* Handle options which are allowed to be reset after program start.
Return true when the current option in PARGS could be handled and
false if not. As a special feature, passing a value of NULL for
PARGS, resets the options to the default. REREAD should be set
true if it is not the initial option parsing. */
static int
parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
{
if (!pargs)
{ /* reset mode */
opt.quiet = 0;
opt.verbose = 0;
opt.debug = 0;
opt.no_grab = 0;
opt.pinentry_program = NULL;
+ opt.pinentry_touch_file = NULL;
opt.scdaemon_program = NULL;
opt.def_cache_ttl = DEFAULT_CACHE_TTL;
opt.def_cache_ttl_ssh = DEFAULT_CACHE_TTL_SSH;
opt.max_cache_ttl = MAX_CACHE_TTL;
opt.max_cache_ttl_ssh = MAX_CACHE_TTL;
opt.min_passphrase_len = MIN_PASSPHRASE_LEN;
opt.ignore_cache_for_signing = 0;
opt.allow_mark_trusted = 0;
opt.disable_scdaemon = 0;
return 1;
}
switch (pargs->r_opt)
{
case oQuiet: opt.quiet = 1; break;
case oVerbose: opt.verbose++; break;
case oDebug: opt.debug |= pargs->r.ret_ulong; break;
case oDebugAll: opt.debug = ~0; break;
case oDebugLevel: debug_level = pargs->r.ret_str; break;
case oLogFile:
if (!reread)
return 0; /* not handeld */
if (!current_logfile || !pargs->r.ret_str
|| strcmp (current_logfile, pargs->r.ret_str))
{
log_set_file (pargs->r.ret_str);
xfree (current_logfile);
current_logfile = xtrystrdup (pargs->r.ret_str);
}
break;
case oNoGrab: opt.no_grab = 1; break;
case oPinentryProgram: opt.pinentry_program = pargs->r.ret_str; break;
+ case oPinentryTouchFile: opt.pinentry_touch_file = pargs->r.ret_str; break;
case oScdaemonProgram: opt.scdaemon_program = pargs->r.ret_str; break;
case oDisableScdaemon: opt.disable_scdaemon = 1; break;
case oDefCacheTTL: opt.def_cache_ttl = pargs->r.ret_ulong; break;
case oDefCacheTTLSSH: opt.def_cache_ttl_ssh = pargs->r.ret_ulong; break;
case oMaxCacheTTL: opt.max_cache_ttl = pargs->r.ret_ulong; break;
case oMaxCacheTTLSSH: opt.max_cache_ttl_ssh = pargs->r.ret_ulong; break;
case oMinPassphraseLen: opt.min_passphrase_len = pargs->r.ret_ulong; break;
case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break;
case oAllowMarkTrusted: opt.allow_mark_trusted = 1; break;
case oAllowPresetPassphrase: opt.allow_preset_passphrase = 1; break;
default:
return 0; /* not handled */
}
return 1; /* handled */
}
int
main (int argc, char **argv )
{
ARGPARSE_ARGS pargs;
int orig_argc;
int may_coredump;
char **orig_argv;
FILE *configfp = NULL;
char *configname = NULL;
const char *shell;
unsigned configlineno;
int parse_debug = 0;
int default_config =1;
int greeting = 0;
int nogreeting = 0;
int pipe_server = 0;
int is_daemon = 0;
int nodetach = 0;
int csh_style = 0;
char *logfile = NULL;
int debug_wait = 0;
int gpgconf_list = 0;
int standard_socket = 0;
gpg_error_t err;
const char *env_file_name = NULL;
set_strusage (my_strusage);
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
/* Please note that we may running SUID(ROOT), so be very CAREFUL
when adding any stuff between here and the call to INIT_SECMEM()
somewhere after the option parsing */
log_set_prefix ("gpg-agent", JNLIB_LOG_WITH_PREFIX|JNLIB_LOG_WITH_PID);
/* Try to auto set the character set. */
set_native_charset (NULL);
i18n_init ();
/* Libgcrypt requires us to register the threading model first.
Note that this will also do the pth_init. */
err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
if (err)
{
log_fatal ("can't register GNU Pth with Libgcrypt: %s\n",
gpg_strerror (err));
}
/* Check that the libraries are suitable. Do it here because
the option parsing may need services of the library. */
if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
{
log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
}
assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
assuan_set_assuan_log_stream (log_get_stream ());
assuan_set_assuan_log_prefix (log_get_prefix (NULL));
assuan_set_assuan_err_source (GPG_ERR_SOURCE_DEFAULT);
gcry_set_log_handler (my_gcry_logger, NULL);
gcry_set_outofcore_handler (my_gcry_outofcore_handler, NULL);
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
may_coredump = disable_core_dumps ();
/* Set default options. */
parse_rereadable_options (NULL, 0); /* Reset them to default values. */
#ifdef HAVE_W32_SYSTEM
standard_socket = 1; /* Under Windows we always use a standard
socket. */
#endif
shell = getenv ("SHELL");
if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
csh_style = 1;
opt.homedir = default_homedir ();
/* Record some of the original environment strings. */
opt.startup_display = getenv ("DISPLAY");
if (opt.startup_display)
opt.startup_display = xstrdup (opt.startup_display);
opt.startup_ttyname = ttyname (0);
if (opt.startup_ttyname)
opt.startup_ttyname = xstrdup (opt.startup_ttyname);
opt.startup_ttytype = getenv ("TERM");
if (opt.startup_ttytype)
opt.startup_ttytype = xstrdup (opt.startup_ttytype);
/* Fixme: Better use the locale function here. */
opt.startup_lc_ctype = getenv ("LC_CTYPE");
if (opt.startup_lc_ctype)
opt.startup_lc_ctype = xstrdup (opt.startup_lc_ctype);
opt.startup_lc_messages = getenv ("LC_MESSAGES");
if (opt.startup_lc_messages)
opt.startup_lc_messages = xstrdup (opt.startup_lc_messages);
/* Check whether we have a config file on the commandline */
orig_argc = argc;
orig_argv = argv;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */
while (arg_parse( &pargs, opts))
{
if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll)
parse_debug++;
else if (pargs.r_opt == oOptions)
{ /* yes there is one, so we do not try the default one, but
read the option file when it is encountered at the
commandline */
default_config = 0;
}
else if (pargs.r_opt == oNoOptions)
default_config = 0; /* --no-options */
else if (pargs.r_opt == oHomedir)
opt.homedir = pargs.r.ret_str;
}
/* Initialize the secure memory. */
gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0);
maybe_setuid = 0;
/*
Now we are now working under our real uid
*/
if (default_config)
configname = make_filename (opt.homedir, "gpg-agent.conf", NULL );
argc = orig_argc;
argv = orig_argv;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1; /* do not remove the args */
next_pass:
if (configname)
{
configlineno = 0;
configfp = fopen (configname, "r");
if (!configfp)
{
if (default_config)
{
if( parse_debug )
log_info (_("NOTE: no default option file `%s'\n"),
configname );
}
else
{
log_error (_("option file `%s': %s\n"),
configname, strerror(errno) );
exit(2);
}
xfree (configname);
configname = NULL;
}
if (parse_debug && configname )
log_info (_("reading options from `%s'\n"), configname );
default_config = 0;
}
while (optfile_parse( configfp, configname, &configlineno, &pargs, opts) )
{
if (parse_rereadable_options (&pargs, 0))
continue; /* Already handled */
switch (pargs.r_opt)
{
case aGPGConfList: gpgconf_list = 1; break;
case aGPGConfTest: gpgconf_list = 2; break;
case oBatch: opt.batch=1; break;
case oDebugWait: debug_wait = pargs.r.ret_int; break;
case oOptions:
/* config files may not be nested (silently ignore them) */
if (!configfp)
{
xfree(configname);
configname = xstrdup(pargs.r.ret_str);
goto next_pass;
}
break;
case oNoGreeting: nogreeting = 1; break;
case oNoVerbose: opt.verbose = 0; break;
case oNoOptions: break; /* no-options */
case oHomedir: opt.homedir = pargs.r.ret_str; break;
case oNoDetach: nodetach = 1; break;
case oLogFile: logfile = pargs.r.ret_str; break;
case oCsh: csh_style = 1; break;
case oSh: csh_style = 0; break;
case oServer: pipe_server = 1; break;
case oDaemon: is_daemon = 1; break;
case oDisplay: default_display = xstrdup (pargs.r.ret_str); break;
case oTTYname: default_ttyname = xstrdup (pargs.r.ret_str); break;
case oTTYtype: default_ttytype = xstrdup (pargs.r.ret_str); break;
case oLCctype: default_lc_ctype = xstrdup (pargs.r.ret_str); break;
case oLCmessages: default_lc_messages = xstrdup (pargs.r.ret_str);
break;
case oUseStandardSocket: standard_socket = 1; break;
case oNoUseStandardSocket: standard_socket = 0; break;
case oKeepTTY: opt.keep_tty = 1; break;
case oKeepDISPLAY: opt.keep_display = 1; break;
case oSSHSupport: opt.ssh_support = 1; break;
case oWriteEnvFile:
if (pargs.r_type)
env_file_name = pargs.r.ret_str;
else
env_file_name = make_filename ("~/.gpg-agent-info", NULL);
break;
default : pargs.err = configfp? 1:2; break;
}
}
if (configfp)
{
fclose( configfp );
configfp = NULL;
/* Keep a copy of the name so that it can be read on SIGHUP. */
config_filename = configname;
configname = NULL;
goto next_pass;
}
xfree (configname);
configname = NULL;
if (log_get_errorcount(0))
exit(2);
if (nogreeting )
greeting = 0;
if (greeting)
{
fprintf (stderr, "%s %s; %s\n",
strusage(11), strusage(13), strusage(14) );
fprintf (stderr, "%s\n", strusage(15) );
}
#ifdef IS_DEVELOPMENT_VERSION
/* We don't want to print it here because gpg-agent is useful of its
own and quite matured. */
/*log_info ("NOTE: this is a development version!\n");*/
#endif
set_debug ();
if (atexit (cleanup))
{
log_error ("atexit failed\n");
cleanup ();
exit (1);
}
initialize_module_query ();
initialize_module_call_scd ();
/* Try to create missing directories. */
create_directories ();
if (debug_wait && pipe_server)
{
log_debug ("waiting for debugger - my pid is %u .....\n",
(unsigned int)getpid());
sleep (debug_wait);
log_debug ("... okay\n");
}
if (gpgconf_list == 2)
agent_exit (0);
if (gpgconf_list)
{
char *filename;
/* List options and default values in the GPG Conf format. */
/* The following list is taken from gnupg/tools/gpgconf-comp.c. */
/* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING
FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */
#define GC_OPT_FLAG_NONE 0UL
/* The RUNTIME flag for an option indicates that the option can be
changed at runtime. */
#define GC_OPT_FLAG_RUNTIME (1UL << 3)
/* The DEFAULT flag for an option indicates that the option has a
default value. */
#define GC_OPT_FLAG_DEFAULT (1UL << 4)
/* The DEF_DESC flag for an option indicates that the option has a
default, which is described by the value of the default field. */
#define GC_OPT_FLAG_DEF_DESC (1UL << 5)
/* The NO_ARG_DESC flag for an option indicates that the argument has
a default, which is described by the value of the ARGDEF field. */
#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6)
filename = make_filename (opt.homedir, "gpg-agent.conf", NULL );
printf ("gpgconf-gpg-agent.conf:%lu:\"%s\n",
GC_OPT_FLAG_DEFAULT, filename);
xfree (filename);
printf ("verbose:%lu:\n"
"quiet:%lu:\n"
"debug-level:%lu:\"none:\n"
"log-file:%lu:\n",
GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME,
GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME,
GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME,
GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME );
printf ("default-cache-ttl:%lu:%d:\n",
GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, DEFAULT_CACHE_TTL );
printf ("no-grab:%lu:\n",
GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
printf ("ignore-cache-for-signing:%lu:\n",
GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
printf ("allow-mark-trusted:%lu:\n",
GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
printf ("disable-scdaemon:%lu:\n",
GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
agent_exit (0);
}
/* If this has been called without any options, we merely check
whether an agent is already running. We do this here so that we
don't clobber a logfile but print it directly to stderr. */
if (!pipe_server && !is_daemon)
{
log_set_prefix (NULL, JNLIB_LOG_WITH_PREFIX);
check_for_running_agent (0);
agent_exit (0);
}
#ifdef ENABLE_NLS
/* gpg-agent usually does not output any messages because it runs in
the background. For log files it is acceptable to have messages
always encoded in utf-8. We switch here to utf-8, so that
commands like --help still give native messages. It is far
easier to switch only once instead of for every message and it
actually helps when more then one thread is active (avoids an
extra copy step). */
bind_textdomain_codeset (PACKAGE_GT, "UTF-8");
#endif
/* Now start with logging to a file if this is desired. */
if (logfile)
{
log_set_file (logfile);
log_set_prefix (NULL, (JNLIB_LOG_WITH_PREFIX
|JNLIB_LOG_WITH_TIME
|JNLIB_LOG_WITH_PID));
current_logfile = xstrdup (logfile);
}
/* Make sure that we have a default ttyname. */
if (!default_ttyname && ttyname (1))
default_ttyname = xstrdup (ttyname (1));
if (!default_ttytype && getenv ("TERM"))
default_ttytype = xstrdup (getenv ("TERM"));
if (pipe_server)
{
/* This is the simple pipe based server */
ctrl_t ctrl;
ctrl = xtrycalloc (1, sizeof *ctrl);
if (!ctrl)
{
log_error ("error allocating connection control data: %s\n",
strerror (errno) );
agent_exit (1);
}
agent_init_default_ctrl (ctrl);
start_command_handler (ctrl, -1, -1);
agent_deinit_default_ctrl (ctrl);
xfree (ctrl);
}
else if (!is_daemon)
; /* NOTREACHED */
else
{ /* Regular server mode */
int fd;
int fd_ssh;
pid_t pid;
/* Remove the DISPLAY variable so that a pinentry does not
default to a specific display. There is still a default
display when gpg-agent was started using --display or a
client requested this using an OPTION command. Note, that we
don't do this when running in reverse daemon mode (i.e. when
exec the program given as arguments). */
#ifndef HAVE_W32_SYSTEM
if (!opt.keep_display && !argc)
unsetenv ("DISPLAY");
#endif
/* Create the sockets. */
socket_name = create_socket_name (standard_socket,
"S.gpg-agent",
"/tmp/gpg-XXXXXX/S.gpg-agent");
if (opt.ssh_support)
socket_name_ssh = create_socket_name (standard_socket,
"S.gpg-agent.ssh",
"/tmp/gpg-XXXXXX/S.gpg-agent.ssh");
fd = create_server_socket (standard_socket, socket_name);
if (opt.ssh_support)
fd_ssh = create_server_socket (standard_socket, socket_name_ssh);
else
fd_ssh = -1;
/* If we are going to exec a program in the parent, we record
the PID, so that the child may check whether the program is
still alive. */
if (argc)
parent_pid = getpid ();
fflush (NULL);
#ifdef HAVE_W32_SYSTEM
pid = getpid ();
printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid);
#else /*!HAVE_W32_SYSTEM*/
pid = fork ();
if (pid == (pid_t)-1)
{
log_fatal ("fork failed: %s\n", strerror (errno) );
exit (1);
}
else if (pid)
{ /* We are the parent */
char *infostr, *infostr_ssh_sock, *infostr_ssh_pid;
close (fd);
/* Create the info string: <name>:<pid>:<protocol_version> */
if (asprintf (&infostr, "GPG_AGENT_INFO=%s:%lu:1",
socket_name, (ulong)pid ) < 0)
{
log_error ("out of core\n");
kill (pid, SIGTERM);
exit (1);
}
if (opt.ssh_support)
{
if (asprintf (&infostr_ssh_sock, "SSH_AUTH_SOCK=%s",
socket_name_ssh) < 0)
{
log_error ("out of core\n");
kill (pid, SIGTERM);
exit (1);
}
if (asprintf (&infostr_ssh_pid, "SSH_AGENT_PID=%u",
pid) < 0)
{
log_error ("out of core\n");
kill (pid, SIGTERM);
exit (1);
}
}
*socket_name = 0; /* Don't let cleanup() remove the socket -
the child should do this from now on */
if (opt.ssh_support)
*socket_name_ssh = 0;
if (env_file_name)
{
FILE *fp;
fp = fopen (env_file_name, "w");
if (!fp)
log_error (_("error creating `%s': %s\n"),
env_file_name, strerror (errno));
else
{
fputs (infostr, fp);
putc ('\n', fp);
if (opt.ssh_support)
{
fputs (infostr_ssh_sock, fp);
putc ('\n', fp);
fputs (infostr_ssh_pid, fp);
putc ('\n', fp);
}
fclose (fp);
}
}
if (argc)
{ /* Run the program given on the commandline. */
if (putenv (infostr))
{
log_error ("failed to set environment: %s\n",
strerror (errno) );
kill (pid, SIGTERM );
exit (1);
}
if (opt.ssh_support && putenv (infostr_ssh_sock))
{
log_error ("failed to set environment: %s\n",
strerror (errno) );
kill (pid, SIGTERM );
exit (1);
}
if (opt.ssh_support && putenv (infostr_ssh_pid))
{
log_error ("failed to set environment: %s\n",
strerror (errno) );
kill (pid, SIGTERM );
exit (1);
}
execvp (argv[0], argv);
log_error ("failed to run the command: %s\n", strerror (errno));
kill (pid, SIGTERM);
exit (1);
}
else
{
/* Print the environment string, so that the caller can use
shell's eval to set it */
if (csh_style)
{
*strchr (infostr, '=') = ' ';
printf ("setenv %s\n", infostr);
if (opt.ssh_support)
{
*strchr (infostr_ssh_sock, '=') = ' ';
printf ("setenv %s\n", infostr_ssh_sock);
*strchr (infostr_ssh_pid, '=') = ' ';
printf ("setenv %s\n", infostr_ssh_pid);
}
}
else
{
printf ( "%s; export GPG_AGENT_INFO;\n", infostr);
if (opt.ssh_support)
{
printf ("%s; export SSH_AUTH_SOCK;\n", infostr_ssh_sock);
printf ("%s; export SSH_AGENT_PID;\n", infostr_ssh_pid);
}
}
free (infostr); /* (Note that a vanilla free is here correct.) */
if (opt.ssh_support)
{
free (infostr_ssh_sock);
free (infostr_ssh_pid);
}
exit (0);
}
/*NOTREACHED*/
} /* End parent */
/*
This is the child
*/
/* Detach from tty and put process into a new session */
if (!nodetach )
{
int i;
unsigned int oldflags;
/* Close stdin, stdout and stderr unless it is the log stream */
for (i=0; i <= 2; i++)
{
if (!log_test_fd (i) && i != fd )
{
if ( ! close (i)
&& open ("/dev/null", i? O_WRONLY : O_RDONLY) == -1)
{
log_error ("failed to open `%s': %s\n",
"/dev/null", strerror (errno));
cleanup ();
exit (1);
}
}
}
if (setsid() == -1)
{
log_error ("setsid() failed: %s\n", strerror(errno) );
cleanup ();
exit (1);
}
log_get_prefix (&oldflags);
log_set_prefix (NULL, oldflags | JNLIB_LOG_RUN_DETACHED);
opt.running_detached = 1;
}
if (chdir("/"))
{
log_error ("chdir to / failed: %s\n", strerror (errno));
exit (1);
}
{
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
sigaction (SIGPIPE, &sa, NULL);
}
#endif /*!HAVE_W32_SYSTEM*/
handle_connections (fd, opt.ssh_support ? fd_ssh : -1);
close (fd);
}
return 0;
}
void
agent_exit (int rc)
{
/*FIXME: update_random_seed_file();*/
#if 1
/* at this time a bit annoying */
if (opt.debug & DBG_MEMSTAT_VALUE)
{
gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
}
if (opt.debug)
gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
#endif
gcry_control (GCRYCTL_TERM_SECMEM );
rc = rc? rc : log_get_errorcount(0)? 2 : 0;
exit (rc);
}
static void
agent_init_default_ctrl (ctrl_t ctrl)
{
ctrl->connection_fd = -1;
/* Note we ignore malloc errors because we can't do much about it
and the request will fail anyway shortly after this
initialization. */
if (ctrl->display)
free (ctrl->display);
ctrl->display = default_display? strdup (default_display) : NULL;
if (ctrl->ttyname)
free (ctrl->ttyname);
ctrl->ttyname = default_ttyname? strdup (default_ttyname) : NULL;
if (ctrl->ttytype)
free (ctrl->ttytype);
ctrl->ttytype = default_ttytype? strdup (default_ttytype) : NULL;
if (ctrl->lc_ctype)
free (ctrl->lc_ctype);
ctrl->lc_ctype = default_lc_ctype? strdup (default_lc_ctype) : NULL;
if (ctrl->lc_messages)
free (ctrl->lc_messages);
ctrl->lc_messages = default_lc_messages? strdup (default_lc_messages) : NULL;
}
static void
agent_deinit_default_ctrl (ctrl_t ctrl)
{
if (ctrl->display)
free (ctrl->display);
if (ctrl->ttyname)
free (ctrl->ttyname);
if (ctrl->ttytype)
free (ctrl->ttytype);
if (ctrl->lc_ctype)
free (ctrl->lc_ctype);
if (ctrl->lc_messages)
free (ctrl->lc_messages);
}
/* Reread parts of the configuration. Note, that this function is
obviously not thread-safe and should only be called from the PTH
signal handler.
Fixme: Due to the way the argument parsing works, we create a
memory leak here for all string type arguments. There is currently
no clean way to tell whether the memory for the argument has been
allocated or points into the process' original arguments. Unless
we have a mechanism to tell this, we need to live on with this. */
static void
reread_configuration (void)
{
ARGPARSE_ARGS pargs;
FILE *fp;
unsigned int configlineno = 0;
int dummy;
if (!config_filename)
return; /* No config file. */
fp = fopen (config_filename, "r");
if (!fp)
{
log_error (_("option file `%s': %s\n"),
config_filename, strerror(errno) );
return;
}
parse_rereadable_options (NULL, 1); /* Start from the default values. */
memset (&pargs, 0, sizeof pargs);
dummy = 0;
pargs.argc = &dummy;
pargs.flags = 1; /* do not remove the args */
while (optfile_parse (fp, config_filename, &configlineno, &pargs, opts) )
{
if (pargs.r_opt < -1)
pargs.err = 1; /* Print a warning. */
else /* Try to parse this option - ignore unchangeable ones. */
parse_rereadable_options (&pargs, 1);
}
fclose (fp);
set_debug ();
}
+/* Return the file name of the socket we are using for native
+ requests. */
+const char *
+get_agent_socket_name (void)
+{
+ const char *s = socket_name;
+
+ return (s && *s)? s : NULL;
+}
+
/* Create a name for the socket. With USE_STANDARD_SOCKET given as
true using STANDARD_NAME in the home directory or if given has
false from the mkdir type name TEMPLATE. In the latter case a
unique name in a unique new directory will be created. In both
cases check for valid characters as well as against a maximum
allowed length for a unix domain socket is done. The function
terminates the process in case of an error. Returns: Pointer to an
allcoated string with the absolute name of the socket used. */
static char *
create_socket_name (int use_standard_socket,
char *standard_name, char *template)
{
char *name, *p;
if (use_standard_socket)
name = make_filename (opt.homedir, standard_name, NULL);
else
{
name = xstrdup (template);
p = strrchr (name, '/');
if (!p)
BUG ();
*p = 0;
if (!mkdtemp (name))
{
log_error (_("can't create directory `%s': %s\n"),
name, strerror (errno));
agent_exit (2);
}
*p = '/';
}
if (strchr (name, PATHSEP_C))
{
log_error (("`%s' are not allowed in the socket name\n"), PATHSEP_S);
agent_exit (2);
}
if (strlen (name) + 1 >= DIMof (struct sockaddr_un, sun_path) )
{
log_error (_("name of socket too long\n"));
agent_exit (2);
}
return name;
}
/* Create a Unix domain socket with NAME. IS_STANDARD_NAME indicates
whether a non-random socket is used. Returns the filedescriptor or
terminates the process in case of an error. */
static int
create_server_socket (int is_standard_name, const char *name)
{
struct sockaddr_un *serv_addr;
socklen_t len;
int fd;
int rc;
#ifdef HAVE_W32_SYSTEM
fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0);
#else
fd = socket (AF_UNIX, SOCK_STREAM, 0);
#endif
if (fd == -1)
{
log_error (_("can't create socket: %s\n"), strerror (errno));
agent_exit (2);
}
serv_addr = xmalloc (sizeof (*serv_addr));
memset (serv_addr, 0, sizeof *serv_addr);
serv_addr->sun_family = AF_UNIX;
assert (strlen (name) + 1 < sizeof (serv_addr->sun_path));
strcpy (serv_addr->sun_path, name);
len = (offsetof (struct sockaddr_un, sun_path)
+ strlen (serv_addr->sun_path) + 1);
#ifdef HAVE_W32_SYSTEM
rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len);
if (is_standard_name && rc == -1 )
{
remove (name);
rc = bind (fd, (struct sockaddr*) serv_addr, len);
}
#else
rc = bind (fd, (struct sockaddr*) serv_addr, len);
if (is_standard_name && rc == -1 && errno == EADDRINUSE)
{
remove (name);
rc = bind (fd, (struct sockaddr*) serv_addr, len);
}
#endif
if (rc == -1)
{
log_error (_("error binding socket to `%s': %s\n"),
serv_addr->sun_path, strerror (errno));
close (fd);
agent_exit (2);
}
if (listen (fd, 5 ) == -1)
{
log_error (_("listen() failed: %s\n"), strerror (errno));
close (fd);
agent_exit (2);
}
if (opt.verbose)
log_info (_("listening on socket `%s'\n"), serv_addr->sun_path);
return fd;
}
/* Check that the directory for storing the private keys exists and
create it if not. This function won't fail as it is only a
convenience function and not strictly necessary. */
static void
create_private_keys_directory (const char *home)
{
char *fname;
struct stat statbuf;
fname = make_filename (home, GNUPG_PRIVATE_KEYS_DIR, NULL);
if (stat (fname, &statbuf) && errno == ENOENT)
{
#ifdef HAVE_W32_SYSTEM /*FIXME: Setup proper permissions. */
if (!CreateDirectory (fname, NULL))
log_error (_("can't create directory `%s': %s\n"),
fname, w32_strerror (-1) );
#else
if (mkdir (fname, S_IRUSR|S_IWUSR|S_IXUSR ))
log_error (_("can't create directory `%s': %s\n"),
fname, strerror (errno) );
#endif
else if (!opt.quiet)
log_info (_("directory `%s' created\n"), fname);
}
xfree (fname);
}
/* Create the directory only if the supplied directory name is the
same as the default one. This way we avoid to create arbitrary
directories when a non-default home directory is used. To cope
with HOME, we compare only the suffix if we see that the default
homedir does start with a tilde. We don't stop here in case of
problems because other functions will throw an error anyway.*/
static void
create_directories (void)
{
struct stat statbuf;
const char *defhome = GNUPG_DEFAULT_HOMEDIR;
char *home;
home = make_filename (opt.homedir, NULL);
if ( stat (home, &statbuf) )
{
if (errno == ENOENT)
{
if ( (*defhome == '~'
&& (strlen (home) >= strlen (defhome+1)
&& !strcmp (home + strlen(home)
- strlen (defhome+1), defhome+1)))
|| (*defhome != '~' && !strcmp (home, defhome) )
)
{
#ifdef HAVE_W32_SYSTEM
if (!CreateDirectory (home, NULL))
log_error (_("can't create directory `%s': %s\n"),
home, w32_strerror (-1) );
#else
if (mkdir (home, S_IRUSR|S_IWUSR|S_IXUSR ))
log_error (_("can't create directory `%s': %s\n"),
home, strerror (errno) );
#endif
else
{
if (!opt.quiet)
log_info (_("directory `%s' created\n"), home);
create_private_keys_directory (home);
}
}
}
else
log_error (_("stat() failed for `%s': %s\n"), home, strerror (errno));
}
else if ( !S_ISDIR(statbuf.st_mode))
{
log_error (_("can't use `%s' as home directory\n"), home);
}
else /* exists and is a directory. */
{
create_private_keys_directory (home);
}
xfree (home);
}
/* This is the worker for the ticker. It is called every few seconds
and may only do fast operations. */
static void
handle_tick (void)
{
/* Check whether the scdaemon has died and cleanup in this case. */
agent_scd_check_aliveness ();
/* If we are running as a child of another process, check whether
the parent is still alive and shutdown if not. */
#ifndef HAVE_W32_SYSTEM
if (parent_pid != (pid_t)(-1))
{
if (kill (parent_pid, 0))
{
shutdown_pending = 2;
log_info ("parent process died - shutting down\n");
log_info ("%s %s stopped\n", strusage(11), strusage(13) );
cleanup ();
agent_exit (0);
}
}
#endif /*HAVE_W32_SYSTEM*/
}
static void
handle_signal (int signo)
{
switch (signo)
{
#ifndef HAVE_W32_SYSTEM
case SIGHUP:
log_info ("SIGHUP received - "
"re-reading configuration and flushing cache\n");
agent_flush_cache ();
reread_configuration ();
agent_reload_trustlist ();
break;
case SIGUSR1:
log_info ("SIGUSR1 received - printing internal information:\n");
pth_ctrl (PTH_CTRL_DUMPSTATE, log_get_stream ());
agent_query_dump_state ();
agent_scd_dump_state ();
break;
case SIGUSR2:
if (opt.verbose)
log_info ("SIGUSR2 received - checking smartcard status\n");
/* Nothing to check right now. We only increment a counter. */
bump_card_eventcounter ();
break;
case SIGTERM:
if (!shutdown_pending)
log_info ("SIGTERM received - shutting down ...\n");
else
log_info ("SIGTERM received - still %ld running threads\n",
pth_ctrl( PTH_CTRL_GETTHREADS ));
shutdown_pending++;
if (shutdown_pending > 2)
{
log_info ("shutdown forced\n");
log_info ("%s %s stopped\n", strusage(11), strusage(13) );
cleanup ();
agent_exit (0);
}
break;
case SIGINT:
log_info ("SIGINT received - immediate shutdown\n");
log_info( "%s %s stopped\n", strusage(11), strusage(13));
cleanup ();
agent_exit (0);
break;
#endif
default:
log_info ("signal %d received - no action defined\n", signo);
}
}
/* This is the standard connection thread's main function. */
static void *
start_connection_thread (void *arg)
{
ctrl_t ctrl = arg;
agent_init_default_ctrl (ctrl);
if (opt.verbose)
log_info (_("handler 0x%lx for fd %d started\n"),
(long)pth_self (), ctrl->thread_startup.fd);
start_command_handler (ctrl, -1, ctrl->thread_startup.fd);
if (opt.verbose)
log_info (_("handler 0x%lx for fd %d terminated\n"),
(long)pth_self (), ctrl->thread_startup.fd);
agent_deinit_default_ctrl (ctrl);
xfree (ctrl);
return NULL;
}
/* This is the ssh connection thread's main function. */
static void *
start_connection_thread_ssh (void *arg)
{
ctrl_t ctrl = arg;
agent_init_default_ctrl (ctrl);
if (opt.verbose)
log_info (_("ssh handler 0x%lx for fd %d started\n"),
(long)pth_self (), ctrl->thread_startup.fd);
start_command_handler_ssh (ctrl, ctrl->thread_startup.fd);
if (opt.verbose)
log_info (_("ssh handler 0x%lx for fd %d terminated\n"),
(long)pth_self (), ctrl->thread_startup.fd);
agent_deinit_default_ctrl (ctrl);
xfree (ctrl);
return NULL;
}
/* Connection handler loop. Wait for coecntion requests and spawn a
thread after accepting a connection. */
static void
handle_connections (int listen_fd, int listen_fd_ssh)
{
pth_attr_t tattr;
pth_event_t ev, time_ev;
sigset_t sigs;
int signo;
struct sockaddr_un paddr;
socklen_t plen;
fd_set fdset, read_fdset;
int ret;
int fd;
tattr = pth_attr_new();
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
#ifndef HAVE_W32_SYSTEM /* fixme */
/* Make sure that the signals we are going to handle are not blocked
and create an event object for them. */
sigemptyset (&sigs );
sigaddset (&sigs, SIGHUP);
sigaddset (&sigs, SIGUSR1);
sigaddset (&sigs, SIGUSR2);
sigaddset (&sigs, SIGINT);
sigaddset (&sigs, SIGTERM);
pth_sigmask (SIG_UNBLOCK, &sigs, NULL);
ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo);
#else
ev = NULL;
#endif
time_ev = NULL;
FD_ZERO (&fdset);
FD_SET (listen_fd, &fdset);
if (listen_fd_ssh != -1)
FD_SET (listen_fd_ssh, &fdset);
for (;;)
{
sigset_t oldsigs;
if (shutdown_pending)
{
if (pth_ctrl (PTH_CTRL_GETTHREADS) == 1)
break; /* ready */
/* Do not accept anymore connections and wait for existing
connections to terminate */
signo = 0;
pth_wait (ev);
if (pth_event_occurred (ev) && signo)
handle_signal (signo);
continue;
}
/* Create a timeout event if needed. */
if (!time_ev)
time_ev = pth_event (PTH_EVENT_TIME, pth_timeout (2, 0));
/* POSIX says that fd_set should be implemented as a structure,
thus a simple assignment is fine to copy the entire set. */
read_fdset = fdset;
if (time_ev)
pth_event_concat (ev, time_ev, NULL);
ret = pth_select_ev (FD_SETSIZE, &read_fdset, NULL, NULL, NULL, ev);
if (time_ev)
pth_event_isolate (time_ev);
if (ret == -1)
{
if (pth_event_occurred (ev)
|| (time_ev && pth_event_occurred (time_ev)))
{
if (pth_event_occurred (ev))
handle_signal (signo);
if (time_ev && pth_event_occurred (time_ev))
{
pth_event_free (time_ev, PTH_FREE_ALL);
time_ev = NULL;
handle_tick ();
}
continue;
}
log_error (_("pth_select failed: %s - waiting 1s\n"),
strerror (errno));
pth_sleep (1);
continue;
}
if (pth_event_occurred (ev))
{
handle_signal (signo);
}
if (time_ev && pth_event_occurred (time_ev))
{
pth_event_free (time_ev, PTH_FREE_ALL);
time_ev = NULL;
handle_tick ();
}
/* We now might create new threads and because we don't want any
signals - we are handling here - to be delivered to a new
thread. Thus we need to block those signals. */
pth_sigmask (SIG_BLOCK, &sigs, &oldsigs);
if (FD_ISSET (listen_fd, &read_fdset))
{
ctrl_t ctrl;
plen = sizeof paddr;
fd = pth_accept (listen_fd, (struct sockaddr *)&paddr, &plen);
if (fd == -1)
{
log_error ("accept failed: %s\n", strerror (errno));
}
else if ( !(ctrl = xtrycalloc (1, sizeof *ctrl)) )
{
log_error ("error allocating connection control data: %s\n",
strerror (errno) );
close (fd);
}
else
{
char threadname[50];
snprintf (threadname, sizeof threadname-1,
"conn fd=%d (gpg)", fd);
threadname[sizeof threadname -1] = 0;
pth_attr_set (tattr, PTH_ATTR_NAME, threadname);
ctrl->thread_startup.fd = fd;
if (!pth_spawn (tattr, start_connection_thread, ctrl))
{
log_error ("error spawning connection handler: %s\n",
strerror (errno) );
close (fd);
xfree (ctrl);
}
}
fd = -1;
}
if (listen_fd_ssh != -1 && FD_ISSET (listen_fd_ssh, &read_fdset))
{
ctrl_t ctrl;
plen = sizeof paddr;
fd = pth_accept (listen_fd_ssh, (struct sockaddr *)&paddr, &plen);
if (fd == -1)
{
log_error ("accept failed for ssh: %s\n", strerror (errno));
}
else if ( !(ctrl = xtrycalloc (1, sizeof *ctrl)) )
{
log_error ("error allocating connection control data: %s\n",
strerror (errno) );
close (fd);
}
else
{
char threadname[50];
agent_init_default_ctrl (ctrl);
snprintf (threadname, sizeof threadname-1,
"conn fd=%d (ssh)", fd);
threadname[sizeof threadname -1] = 0;
pth_attr_set (tattr, PTH_ATTR_NAME, threadname);
ctrl->thread_startup.fd = fd;
if (!pth_spawn (tattr, start_connection_thread_ssh, ctrl) )
{
log_error ("error spawning ssh connection handler: %s\n",
strerror (errno) );
close (fd);
xfree (ctrl);
}
}
fd = -1;
}
/* Restore the signal mask. */
pth_sigmask (SIG_SETMASK, &oldsigs, NULL);
}
pth_event_free (ev, PTH_FREE_ALL);
if (time_ev)
pth_event_free (time_ev, PTH_FREE_ALL);
cleanup ();
log_info (_("%s %s stopped\n"), strusage(11), strusage(13));
}
/* Figure out whether an agent is available and running. Prints an
error if not. Usually started with MODE 0. */
static int
check_for_running_agent (int mode)
{
int rc;
char *infostr, *p;
assuan_context_t ctx;
int prot, pid;
if (!mode)
{
infostr = getenv ("GPG_AGENT_INFO");
if (!infostr || !*infostr)
{
if (!check_for_running_agent (1))
return 0; /* Okay, its running on the standard socket. */
log_error (_("no gpg-agent running in this session\n"));
return -1;
}
infostr = xstrdup (infostr);
if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
{
xfree (infostr);
if (!check_for_running_agent (1))
return 0; /* Okay, its running on the standard socket. */
log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
return -1;
}
*p++ = 0;
pid = atoi (p);
while (*p && *p != PATHSEP_C)
p++;
prot = *p? atoi (p+1) : 0;
if (prot != 1)
{
xfree (infostr);
log_error (_("gpg-agent protocol version %d is not supported\n"),
prot);
if (!check_for_running_agent (1))
return 0; /* Okay, its running on the standard socket. */
return -1;
}
}
else /* MODE != 0 */
{
infostr = make_filename (opt.homedir, "S.gpg-agent", NULL);
pid = (pid_t)(-1);
}
rc = assuan_socket_connect (&ctx, infostr, pid);
xfree (infostr);
if (rc)
{
if (!mode && !check_for_running_agent (1))
return 0; /* Okay, its running on the standard socket. */
if (!mode)
log_error ("can't connect to the agent: %s\n", gpg_strerror (rc));
return -1;
}
if (!opt.quiet)
log_info ("gpg-agent running and available\n");
assuan_disconnect (ctx);
return 0;
}
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 1feda1bca..96dd2f66a 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,358 +1,362 @@
+2007-02-14 Werner Koch <wk@g10code.com>
+
+ * gpg-agent.texi (Agent Options): Doc --pinentry-touch-file.
+
2007-02-05 Werner Koch <wk@g10code.com>
* debugging.texi (Common Problems): Tell how to export a private
key without a certificate.
2007-01-30 Werner Koch <wk@g10code.com>
* com-certs.pem: Added the current root certifcates of D-Trust and
S-Trust.
2007-01-18 David Shaw <dshaw@jabberwocky.com>
* gpg.texi, specify-user-id.texi: Only some of the mentions of
exclamation marks have an example. Give examples to the rest.
2007-01-17 David Shaw <dshaw@jabberwocky.com>
* gpg.texi (GPG Configuration Options): Make http_proxy option
documentation match reality.
(BUGS): Warn about hibernate/safe-sleep/etc writing main RAM to
disk, despite locking.
2006-12-08 Werner Koch <wk@g10code.com>
* gnupg.texi (direntry): Rename gpg to gpg2.
2006-12-04 Werner Koch <wk@g10code.com>
* gpgv.texi: New.
* tools.texi: Include new file.
2006-12-02 David Shaw <dshaw@jabberwocky.com>
* gpg.texi (GPG Esoteric Options): Document --passphrase-repeat.
2006-11-14 Werner Koch <wk@g10code.com>
* gpgsm.texi (GPGSM EXPORT): Document changes.
2006-11-11 Werner Koch <wk@g10code.com>
* gnupg.texi (Top): Move gpg-agent part before gpg.
2006-11-05 David Shaw <dshaw@jabberwocky.com>
* gpg.texi: Reference to --s2k-count in --s2k-mode.
2006-10-30 Werner Koch <wk@g10code.com>
* faq.raw: Minor corrections.
2006-10-12 Werner Koch <wk@g10code.com>
* Makefile.am (man_MANS): Do not install gnupg.7 due to a conflict
with gpg1.
2006-10-12 David Shaw <dshaw@jabberwocky.com>
* gpg.texi: Document --s2k-count.
2006-09-25 Werner Koch <wk@g10code.com>
* gpg.texi (GPG Examples): Add markup to all options. This is
required to have the double dashs printed correclty.
2006-09-22 Werner Koch <wk@g10code.com>
* instguide.texi (Installation): New.
* assuan.texi (Assuan): Removed. Use the libassuan manual instead.
* gnupg.texi: Reflect these changes.
* gpg.texi: Make some parts depend on the "gpgone" set
command. This allows us to use the same source for gpg1 and gpg2.
* yat2m.c (parse_file): Better parsing of @ifset and ifclear.
(main): Allow definition of "-D gpgone".
(parse_file): Allow macro definitions.
(proc_texi_cmd): Expand macros.
(proc_texi_buffer): Process commands terminated by the closing
brace of the enclosing command.
2006-09-20 Werner Koch <wk@g10code.com>
* texi.css: New. Note that the current vesion of makeinfo has a
bug while copying the @import directive. A pacth has been send to
upstream.
2006-09-19 Werner Koch <wk@g10code.com>
* gpg.texi: Some restructuring.
* Makefile.am (online): New target.
2006-09-18 Werner Koch <wk@g10code.com>
* com-certs.pem: New.
2006-09-13 Werner Koch <wk@g10code.com>
* gpg.texi (GPG Esoteric Options): Fixed typo in
--require-cross-certification and made it the default.
2006-09-11 Werner Koch <wk@g10code.com>
* HACKING: Cleaned up.
2006-09-08 Werner Koch <wk@g10code.com>
* yat2m.c (parse_file): Ignore @node lines immediately.
(proc_texi_cmd): No special @end ifset processing anymore.
* specify-user-id.texi: New. Factored out of gpg.texi and ../README.
2006-09-07 Werner Koch <wk@g10code.com>
* scdaemon.texi (Scdaemon Configuration): New.
* examples/scd-event: Event handler for sdaemon.
* examples/: New directory
2006-08-22 Werner Koch <wk@g10code.com>
* yat2m.c (parse_file): Added code to skip a line after @mansect.
* gnupg7.texi: New.
2006-08-21 Werner Koch <wk@g10code.com>
* Makefile.am: Added other doc files from gpg 1.4.
2006-08-17 Werner Koch <wk@g10code.com>
* Makefile.am: Added rules to build man pages.
* yat2m.c: New.
2006-02-14 Werner Koch <wk@gnupg.org>
* gpgsm.texi (GPGSM Configuration): New section.
2005-11-14 Werner Koch <wk@g10code.com>
* qualified.txt: Added real information.
2005-11-13 Werner Koch <wk@g10code.com>
* qualified.txt: New.
* Makefile.am (dist_pkgdata_DATA): New.
2005-08-16 Werner Koch <wk@g10code.com>
* gpg-agent.texi (Agent Options): Note default file name for
--write-env-file.
2005-06-03 Werner Koch <wk@g10code.com>
* debugging.texi (Architecture Details): New section, mostly empty.
* gnupg-card-architecture.fig: New.
* Makefile.am: Rules to build png and eps versions.
* gpg-agent.texi (Agent UPDATESTARTUPTTY): New.
2005-05-17 Werner Koch <wk@g10code.com>
* gpg-agent.texi (Agent Options): Removed --disable-pth.
2005-04-27 Werner Koch <wk@g10code.com>
* tools.texi (symcryptrun): Added.
* scdaemon.texi: Removed OpenSC specific options.
2005-04-20 Werner Koch <wk@g10code.com>
* gpg-agent.texi (Agent Configuration): New section.
2005-02-24 Werner Koch <wk@g10code.com>
* tools.texi (gpg-connect-agent): New.
2005-02-14 Werner Koch <wk@g10code.com>
* gpgsm.texi (Certificate Management): Document --import.
2005-01-27 Moritz Schulte <moritz@g10code.com>
* gpg-agent.texi: Document ssh-agent emulation layer.
2005-01-04 Werner Koch <wk@g10code.com>
* gnupg.texi: Updated to use @copying.
2004-12-22 Werner Koch <wk@g10code.com>
* gnupg.texi: Reordered.
* contrib.texi: Updated.
2004-12-21 Werner Koch <wk@g10code.com>
* tools.texi (gpg-preset-passphrase): New section.
* gnupg-badge-openpgp.eps, gnupg-badge-openpgp.jpg: New
* gnupg.texi: Add a logo.
* sysnotes.texi: New.
2004-11-05 Werner Koch <wk@g10code.com>
* debugging.texi (Common Problems): Curses pinentry problem.
2004-10-22 Werner Koch <wk@g10code.com>
* tools.texi (Helper Tools): Document gpgsm-gencert.sh.
2004-10-05 Werner Koch <wk@g10code.com>
* gpg-agent.texi (Invoking GPG-AGENT): Tell that GPG_TTY needs to
be set in all cases.
2004-09-30 Werner Koch <wk@g10code.com>
* gpg.texi: New.
* gnupg.texi: Include gpg.texi
* tools.texi: Add a few @command markups.
* gpgsm.texi: Ditto
* gpg-agent.texi: Ditto.
* scdaemon.texi: Ditto.
2004-09-30 Marcus Brinkmann <marcus@g10code.de>
* tools.texi (Changing options): Add documentation for gpgconf.
* contrib.texi (Contributors): Add two missing periods.
2004-09-29 Werner Koch <wk@g10code.com>
* gpgsm.texi (Configuration Options): Add --log-file.
* gpg-agent.texi (Invoking GPG-AGENT): Add a few words about the
expected pinentry filename.
Changed license of the manual stuff to GPL.
* gnupg.texi (Top): New menu item Helper Tools.
* tools.texi (Helper Tools): New.
* Makefile.am (gnupg_TEXINFOS): Add tools.texi.
2004-08-05 Werner Koch <wk@g10code.de>
* scdaemon.texi (Card applications): New section.
2004-06-22 Werner Koch <wk@g10code.com>
* glossary.texi: New.
2004-06-18 Werner Koch <wk@gnupg.org>
* debugging.texi: New.
* gnupg.texi: Include it.
2004-05-11 Werner Koch <wk@gnupg.org>
* gpgsm.texi (Esoteric Options): Add --debug-allow-core-dump.
2004-05-03 Werner Koch <wk@gnupg.org>
* gpg-agent.texi (Agent Options): Add --allow-mark-trusted.
2004-02-03 Werner Koch <wk@gnupg.org>
* contrib.texi (Contributors): Updated from the gpg 1.2.3 thanks
list.
* gpgsm.texi, gpg-agent.texi, scdaemon.texi: Language cleanups.
2003-12-01 Werner Koch <wk@gnupg.org>
* gpgsm.texi (Certificate Options): Add --{enable,disable}-ocsp.
2003-11-17 Werner Koch <wk@gnupg.org>
* scdaemon.texi (Scdaemon Options): Added --allow-admin and
--deny-admin.
2003-10-27 Werner Koch <wk@gnupg.org>
* gpg-agent.texi (Agent GET_CONFIRMATION): New.
2002-12-04 Werner Koch <wk@gnupg.org>
* gpg-agent.texi (Agent Signals): New.
2002-12-03 Werner Koch <wk@gnupg.org>
* gpgsm.texi (Operational Commands): Add --passwd and
--call-protect-tool.
* gpg-agent.texi (Agent PASSWD): New
2002-11-13 Werner Koch <wk@gnupg.org>
* gpg-agent.texi (Invoking GPG-AGENT): Tell about GPG_TTY.
2002-11-12 Werner Koch <wk@gnupg.org>
* gpgsm.texi (Operational Commands): Add --call-dirmngr.
2002-09-25 Werner Koch <wk@gnupg.org>
* gpg-agent.texi (Agent Options): Add --keep-tty and --keep-display.
2002-09-12 Werner Koch <wk@gnupg.org>
* gpg-agent.texi (Invoking GPG-AGENT): Explained how to start only
one instance.
2002-08-28 Werner Koch <wk@gnupg.org>
* gpg-agent.texi (Agent Options): Explained more options.
* scdaemon.texi (Scdaemon Options): Ditto.
2002-08-09 Werner Koch <wk@gnupg.org>
* Makefile.am (gnupg_TEXINFOS): Include contrib.texi.
2002-08-06 Werner Koch <wk@gnupg.org>
* gpgsm.texi: Added more options.
2002-07-26 Werner Koch <wk@gnupg.org>
* assuan.texi: New.
* gpgsm.texi, scdaemon.texi, gpg-agent.texi: Documented the Assuan
protocol used.
2002-07-22 Werner Koch <wk@gnupg.org>
* gnupg.texi, scdaemon.texi, gpg-agent.texi: New.
* contrib.texi, gpl.texi, fdl.texi: New.
* gpgsm.texi: Made this an include file for gnupg.texi.
* Makefile.am: Build gnupg.info instead of gpgsm.info.
2002-06-04 Werner Koch <wk@gnupg.org>
* gpgsm.texi (Invocation): Described the various debug flags.
2002-05-14 Werner Koch <wk@gnupg.org>
* Makefile.am, gpgsm.texi: New.
Copyright 2002, 2004, 2005 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/doc/gpg-agent.texi b/doc/gpg-agent.texi
index 12c870588..4119d6601 100644
--- a/doc/gpg-agent.texi
+++ b/doc/gpg-agent.texi
@@ -1,1121 +1,1132 @@
@c Copyright (C) 2002 Free Software Foundation, Inc.
@c This is part of the GnuPG manual.
@c For copying conditions, see the file gnupg.texi.
@node Invoking GPG-AGENT
@chapter Invoking GPG-AGENT
@cindex GPG-AGENT command options
@cindex command options
@cindex options, GPG-AGENT command
@manpage gpg-agent.1
@ifset manverb
.B gpg-agent
\- Secret key management for GnuPG
@end ifset
@mansect synopsis
@ifset manverb
.B gpg-agent
.RB [ \-\-homedir
.IR dir ]
.RB [ \-\-options
.IR file ]
.RI [ options ]
.br
.B gpg-agent
.RB [ \-\-homedir
.IR dir ]
.RB [ \-\-options
.IR file ]
.RI [ options ]
.B \-\-server
.br
.B gpg-agent
.RB [ \-\-homedir
.IR dir ]
.RB [ \-\-options
.IR file ]
.RI [ options ]
.B \-\-daemon
.RI [ command_line ]
@end ifset
@mansect description
@command{gpg-agent} is a daemon to manage secret (private) keys
independently from any protocol. It is used as a backend for
@command{gpg} and @command{gpgsm} as well as for a couple of other
utilities.
@noindent
The usual way to run the agent is from the @code{~/.xsession} file:
@example
eval `gpg-agent --daemon`
@end example
@noindent
If you don't use an X server, you can also put this into your regular
startup file @code{~/.profile} or @code{.bash_profile}. It is best not
to run multiple instance of the @command{gpg-agent}, so you should make
sure that only one is running: @command{gpg-agent} uses an environment
variable to inform clients about the communication parameters. You can
write the content of this environment variable to a file so that you can
test for a running agent. This short script may do the job:
@smallexample
if test -f $HOME/.gpg-agent-info && \
kill -0 `cut -d: -f 2 $HOME/.gpg-agent-info` 2>/dev/null; then
GPG_AGENT_INFO=`cat $HOME/.gpg-agent-info`
export GPG_AGENT_INFO
else
eval `gpg-agent --daemon`
echo $GPG_AGENT_INFO >$HOME/.gpg-agent-info
fi
@end smallexample
@noindent
Note that the new option @option{--write-env-file} may be used instead.
@noindent
You should always add the following lines to your @code{.bashrc} or
whatever initialization file is used for all shell invocations:
@smallexample
GPG_TTY=`tty`
export GPG_TTY
@end smallexample
@noindent
It is important that this environment variable always reflects the
output of the @code{tty} command. For W32 systems this option is not
required.
Please make sure that a proper pinentry program has been installed
under the default filename (which is system dependant) or use the
option @code{pinentry-pgm} to specify the full name of that program.
It is often useful to install a symbolic link from the actual used
pinentry (e.g. @file{/usr/bin/pinentry-gtk}) to the expected
one (e.g. @file{/usr/bin/pinentry}).
@manpause
@noindent
@xref{Option Index},for an index to @command{GPG-AGENT}'s commands and options.
@mancont
@menu
* Agent Commands:: List of all commands.
* Agent Options:: List of all options.
* Agent Configuration:: Configuration files.
* Agent Signals:: Use of some signals.
* Agent Examples:: Some usage examples.
* Agent Protocol:: The protocol the agent uses.
@end menu
@mansect commands
@node Agent Commands
@section Commands
Commands are not distinguished from options execpt for the fact that
only one one command is allowed.
@table @gnupgtabopt
@item --version
@opindex version
Print the program version and licensing information. Not that you can
abbreviate this command.
@item --help
@itemx -h
@opindex help
Print a usage message summarizing the most useful command-line options.
Not that you can abbreviate this command.
@item --dump-options
@opindex dump-options
Print a list of all available options and commands. Not that you can
abbreviate this command.
@item --server
@opindex server
Run in server mode and wait for commands on the @code{stdin}. The
default mode is to create a socket and listen for commands there.
@item --daemon [@var{command line}]
@opindex daemon
Run the program in the background. This option is required to prevent
it from being accidently running in the background. A common way to do
this is:
@example
@end example
$ eval `gpg-agent --daemon`
@end table
@mansect options
@node Agent Options
@section Option Summary
@table @gnupgtabopt
@anchor{option --options}
@item --options @var{file}
@opindex options
Reads configuration from @var{file} instead of from the default
per-user configuration file. The default configuration file is named
@file{gpg-agent.conf} and expected in the @file{.gnupg} directory directly
below the home directory of the user.
@anchor{option --homedir}
@include opt-homedir.texi
@item -v
@item --verbose
@opindex v
@opindex verbose
Outputs additional information while running.
You can increase the verbosity by giving several
verbose commands to @command{gpgsm}, such as @samp{-vv}.
@item -q
@item --quiet
@opindex q
@opindex quiet
Try to be as quiet as possible.
@item --batch
@opindex batch
Don't invoke a pinentry or do any other thing requiring human interaction.
@item --faked-system-time @var{epoch}
@opindex faked-system-time
This option is only useful for testing; it sets the system time back or
forth to @var{epoch} which is the number of seconds elapsed since the year
1970.
@item --debug-level @var{level}
@opindex debug-level
Select the debug level for investigating problems. @var{level} may be
one of:
@table @code
@item none
no debugging at all.
@item basic
some basic debug messages
@item advanced
more verbose debug messages
@item expert
even more detailed messages
@item guru
all of the debug messages you can get
@end table
How these messages are mapped to the actual debugging flags is not
specified and may change with newer releaes of this program. They are
however carefully selected to best aid in debugging.
@item --debug @var{flags}
@opindex debug
This option is only useful for debugging and the behaviour may change at
any time without notice. FLAGS are bit encoded and may be given in
usual C-Syntax. The currently defined bits are:
@table @code
@item 0 (1)
X.509 or OpenPGP protocol related data
@item 1 (2)
values of big number integers
@item 2 (4)
low level crypto operations
@item 5 (32)
memory allocation
@item 6 (64)
caching
@item 7 (128)
show memory statistics.
@item 9 (512)
write hashed data to files named @code{dbgmd-000*}
@item 10 (1024)
trace Assuan protocol
@item 12 (4096)
bypass all certificate validation
@end table
@item --debug-all
@opindex debug-all
Same as @code{--debug=0xffffffff}
@item --debug-wait @var{n}
@opindex debug-wait
When running in server mode, wait @var{n} seconds before entering the
actual processing loop and print the pid. This gives time to attach a
debugger.
@item --no-detach
@opindex no-detach
Don't detach the process from the console. This is manly usefule for
debugging.
@item -s
@itemx --sh
@itemx -c
@itemx --csh
@opindex s
@opindex sh
@opindex c
@opindex csh
Format the info output in daemon mode for use with the standard Bourne
shell respective the C-shell . The default ist to guess it based on the
environment variable @code{SHELL} which is in almost all cases
sufficient.
@item --write-env-file @var{file}
@opindex write-env-file
Often it is required to connect to the agent from a process not being an
inferior of @command{gpg-agent} and thus the environment variable with
the socket name is not available. To help setting up those variables in
other sessions, this option may be used to write the information into
@var{file}. If @var{file} is not specified the default name
@file{$@{HOME@}/.gpg-agent-info} will be used. The format is suitable
to be evaluated by a Bourne shell like in this simple example:
@example
eval `cat @var{file}`
eval `cut -d= -f 1 < @var{file} | xargs echo export`
@end example
@item --no-grab
@opindex no-grab
Tell the pinentryo not to grab the keyboard and mouse. This option
should in general not be used to avaoid X-sniffing attacks.
@item --log-file @var{file}
@opindex log-file
Append all logging output to @var{file}. This is very helpful in
seeing what the agent actually does.
@anchor{option --allow-mark-trusted}
@item --allow-mark-trusted
@opindex allow-mark-trusted
Allow clients to mark keys as trusted, i.e. put them into the
@file{trustlist.txt} file. This is by default not allowed to make it
harder for users to inadvertly accept Root-CA keys.
@item --ignore-cache-for-signing
@opindex ignore-cache-for-signing
This option will let @command{gpg-agent} bypass the passphrase cache for all
signing operation. Note that there is also a per-session option to
control this behaviour but this command line option takes precedence.
@item --default-cache-ttl @var{n}
@opindex default-cache-ttl
Set the time a cache entry is valid to @var{n} seconds. The default are
600 seconds.
@item --default-cache-ttl-ssh @var{n}
@opindex default-cache-ttl
Set the time a cache entry used for SSH keys is valid to @var{n}
seconds. The default are 1800 seconds.
@item --max-cache-ttl @var{n}
@opindex max-cache-ttl
Set the maximum time a cache entry is valid to @var{n} seconds. After
this time a cache entry will get expired even if it has been accessed
recently. The default are 2 hours (7200 seconds).
@item --max-cache-ttl-ssh @var{n}
@opindex max-cache-ttl-ssh
Set the maximum time a cache entry used for SSH keys is valid to @var{n}
seconds. After this time a cache entry will get expired even if it has
been accessed recently. The default are 2 hours (7200 seconds).
@item --min-passphrase-len @var{n}
@opindex min-passphrase-len
Set the minimal length of a passphrase. When entereing a new passphrase
shorter than this value a warning will be displayed. Defaults to 8.
@item --pinentry-program @var{filename}
@opindex pinentry-program
Use program @var{filename} as the PIN entry. The default is installation
dependend and can be shown with the @code{--version} command.
+@item --pinentry-touch-file @var{filename}
+@opindex pinentry-touch-file
+By default the file name of the socket gpg-agent is listening for
+requests is passed to Pinentry, so that it can touch that file before
+exiting (it does this only in curses mode). This option changes the
+file passed to Pinentry to @var{filename}. The special name
+@code{/dev/null} may be used to completely disable this feature. Note
+that Pinentry will not create that file, it will only change the
+modification and access time.
+
+
@item --scdaemon-program @var{filename}
@opindex scdaemon-program
Use program @var{filename} as the Smartcard daemon. The default is
installation dependend and can be shown with the @code{--version}
command.
@item --disable-scdaemon
@opindex disable-scdaemon
Do not make use of the scdaemon tool. This option has the effect of
disabling the ability to do smartcard operations. Note, that enabling
this option at runtime does not kill an already forked scdaemon.
@item --use-standard-socket
@itemx --no-use-standard-socket
@opindex use-standard-socket
@opindex no-use-standard-socket
By enabling this option @command{gpg-agent} will listen on the socket
named @file{S.gpg-agent}, located in the home directory, and not create
a random socket below a temporary directory. Tools connecting to
@command{gpg-agent} should first try to connect to the socket given in
environment variable @var{GPG_AGENT_INFO} and the fall back to this
socket. This option may not be used if the home directory is mounted as
a remote file system.
@noindent
Note, that as of now, W32 systems default to this option.
@item --display @var{string}
@itemx --ttyname @var{string}
@itemx --ttytype @var{string}
@itemx --lc-type @var{string}
@itemx --lc-messages @var{string}
@opindex display
@opindex ttyname
@opindex ttytype
@opindex lc-type
@opindex lc-messages
These options are used with the server mode to pass localization
information.
@item --keep-tty
@itemx --keep-display
@opindex keep-tty
@opindex keep-display
Ignore requests to change change the current @code{tty} respective the X
window system's @code{DISPLAY} variable. This is useful to lock the
pinentry to pop up at the @code{tty} or display you started the agent.
@anchor{option --enable-ssh-support}
@item --enable-ssh-support
@opindex enable-ssh-support
Enable emulation of the OpenSSH Agent protocol.
In this mode of operation, the agent does not only implement the
gpg-agent protocol, but also the agent protocol used by OpenSSH
(through a seperate socket). Consequently, it should possible to use
the gpg-agent as a drop-in replacement for the well known ssh-agent.
SSH Keys, which are to be used through the agent, need to be added to
the gpg-agent initially through the ssh-add utility. When a key is
added, ssh-add will ask for the password of the provided key file and
send the unprotected key material to the agent; this causes the
gpg-agent to ask for a passphrase, which is to be used for encrypting
the newly received key and storing it in a gpg-agent specific
directory.
Once, a key has been added to the gpg-agent this way, the gpg-agent
will be ready to use the key.
Note: in case the gpg-agent receives a signature request, the user might
need to be prompted for a passphrase, which is necessary for decrypting
the stored key. Since the ssh-agent protocol does not contain a
mechanism for telling the agent on which display/terminal it is running,
gpg-agent's ssh-support will use the TTY or X display where gpg-agent
has been started. To switch this display to the current one, the
follwing command may be used:
@smallexample
echo UPDATESTARTUPTTY | gpg-connect-agent
@end smallexample
@end table
All the long options may also be given in the configuration file after
stripping off the two leading dashes.
@mansect files
@node Agent Configuration
@section Configuration
There are a few configuration files needed for the operation of the
agent. By default they may all be found in the current home directory
(@pxref{option --homedir}).
@table @file
@item gpg-agent.conf
@cindex gpg-agent.conf
This is the standard configuration file read by @command{gpg-agent} on
startup. It may contain any valid long option; the leading
two dashes may not be entered and the option may not be abbreviated.
This file is also read after a @code{SIGHUP} however only a few
options will actually have an effect. This default name may be
changed on the command line (@pxref{option --options}).
@item trustlist.txt
This is the list of trusted keys. Comment lines, indicated by a leading
hash mark, as well as empty lines are ignored. To mark a key as trusted
you need to enter its fingerprint followed by a space and a capital
letter @code{S}. Colons may optionally be used to separate the bytes of
a fingerprint; this allows to cut and paste the fingerprint from a key
listing output.
Here is an example where two keys are marked as ultimately trusted:
@example
# CN=Wurzel ZS 3,O=Intevation GmbH,C=DE
A6935DD34EF3087973C706FC311AA2CCF733765B S
# CN=PCA-1-Verwaltung-02/O=PKI-1-Verwaltung/C=DE
DC:BD:69:25:48:BD:BB:7E:31:6E:BB:80:D3:00:80:35:D4:F8:A6:CD S
@end example
Before entering a key into this file, you need to ensure its
authenticity. How to do this depends on your organisation; your
administrator might have already entered those keys which are deemed
trustworthy enough into this file. Places where to look for the
fingerprint of a root certificate are letters received from the CA or
the website of the CA (after making 100% sure that this is indeed the
website of that CA). You may want to consider allowing interactive
updates of this file by using the @xref{option --allow-mark-trusted}.
This is however not as secure as maintaining this file manually. It is
even advisable to change the permissions to read-only so that this file
can't be changed inadvertently.
It is possible to add further flags after the @code{S} for use by the
caller. The only flag currently defined is @code{relax} to relax
checking of some root certificate requirements.
As a special feature a line @code{include-default} will include a global
list of trusted certificates (e.g. @file{/etc/gnupg/trustlist.txt}).
This global list is also used if the local list ios not available.
@item sshcontrol
This file is used when support for the secure shell agent protocol has
been enabled (@pxref{option --enable-ssh-support}). Only keys present in
this file are used in the SSH protocol. The @command{ssh-add} tool y be
used to add new entries to this file; you may also add them manually.
Comment lines, indicated by a leading hash mark, as well as empty lines
are ignored. An entry starts with optional white spaces, followed by
the keygrip of the key given as 40 hex digits, optionally followed by
the caching TTL in seconds and another optional field for arbitrary
flags. A @code{!} may be prepended to the keygrip to disable this
entry.
The follwoing example lists exactly one key. Note that keys available
through a OpenPGP smartcard in the active smartcard reader are implictly
added to this list; i.e. there is no need to list them.
@example
# Key added on 2005-02-25 15:08:29
5A6592BF45DC73BD876874A28FD4639282E29B52 0
@end example
@item private-keys-v1.d/
This is the directory where gpg-agent stores the private keys. Each
key is stored in a file with the name made up of the keygrip and the
suffix @file{key}.
@end table
Note that on larger installations, it is useful to put predefined
files into the directory @file{/etc/skel/.gnupg/} so that newly created
users start up with a working configuration. For existing users the
a small helper script is provied to create these files (@pxref{addgnupghome}).
@c
@c Agent Signals
@c
@mansect signals
@node Agent Signals
@section Use of some signals.
A running @command{gpg-agent} may be controlled by signals, i.e. using
the @command{kill} command to send a signal to the process.
Here is a list of supported signals:
@table @gnupgtabopt
@item SIGHUP
@cpindex SIGHUP
This signal flushes all chached passphrases and if the program has been
started with a configuration file, the configuration file is read again.
Only certain options are honored: @code{quiet}, @code{verbose},
@code{debug}, @code{debug-all}, @code{debug-level}, @code{no-grab},
@code{pinentry-program}, @code{default-cache-ttl}, @code{max-cache-ttl},
@code{ignore-cache-for-signing}, @code{allow-mark-trusted} and
@code{disable-scdaemon}. @code{scdaemon-program} is also supported but
due to the current implementation, which calls the scdaemon only once,
it is not of much use unless you manually kill the scdaemon.
@item SIGTERM
@cpindex SIGTERM
Shuts down the process but waits until all current requests are
fulfilled. If the process has received 3 of these signals and requests
are still pending, a shutdown is forced.
@item SIGINT
@cpindex SIGINT
Shuts down the process immediately.
@item SIGUSR1
@cpindex SIGUSR1
Dump internal information to the log file.
@item SIGUSR2
@cpindex SIGUSR2
This signal is used for internal purposes.
@end table
@c
@c Examples
@c
@mansect examples
@node Agent Examples
@section Examples
The usual way to invoke @command{gpg-agent} is
@example
$ eval `gpg-agent --daemon`
@end example
An alternative way is by replacing @command{ssh-agent} with
@command{gpg-agent}. If for example @command{ssh-agent} is started as
part of the Xsession intialization you may simply replace
@command{ssh-agent} by a script like:
@cartouche
@example
#!/bin/sh
exec /usr/local/bin/gpg-agent --enable-ssh-support --daemon \
--write-env-file $@{HOME@}/.gpg-agent-info "$@@"
@end example
@end cartouche
@noindent
and add something like (for Bourne shells)
@cartouche
@example
if [ -f "$@{HOME@}/.gpg-agent-info" ]; then
. "$@{HOME@}/.gpg-agent-info"
export GPG_AGENT_INFO
export SSH_AUTH_SOCK
export SSH_AGENT_PID
fi
@end example
@end cartouche
@noindent
to your shell initialization file (e.g. @file{~/.bashrc}).
@c
@c Assuan Protocol
@c
@manpause
@node Agent Protocol
@section Agent's Assuan Protocol
Note: this section does only document the protocol, which is used by
GnuPG components; it does not deal with the ssh-agent protocol.
The @command{gpg-agent} should be started by the login shell and set an
environment variable to tell clients about the socket to be used.
Clients should deny to access an agent with a socket name which does
not match its own configuration. An application may choose to start
an instance of the gpgagent if it does not figure that any has been
started; it should not do this if a gpgagent is running but not
usable. Because @command{gpg-agent} can only be used in background mode, no
special command line option is required to activate the use of the
protocol.
To identify a key we use a thing called keygrip which is the SHA-1 hash
of an canoncical encoded S-Expression of the the public key as used in
Libgcrypt. For the purpose of this interface the keygrip is given as a
hex string. The advantage of using this and not the hash of a
certificate is that it will be possible to use the same keypair for
different protocols, thereby saving space on the token used to keep the
secret keys.
@menu
* Agent PKDECRYPT:: Decrypting a session key
* Agent PKSIGN:: Signing a Hash
* Agent GENKEY:: Generating a Key
* Agent IMPORT:: Importing a Secret Key
* Agent EXPORT:: Exporting a Secret Key
* Agent ISTRUSTED:: Importing a Root Certificate
* Agent GET_PASSPHRASE:: Ask for a passphrase
* Agent GET_CONFIRMATION:: Ask for confirmation
* Agent HAVEKEY:: Check whether a key is available
* Agent LEARN:: Register a smartcard
* Agent PASSWD:: Change a Passphrase
* Agent UPDATESTARTUPTTY:: Change the Standard Display
* Agent GETEVENTCOUNTER:: Get the Event Counters
@end menu
@node Agent PKDECRYPT
@subsection Decrypting a session key
The client asks the server to decrypt a session key. The encrypted
session key should have all information needed to select the
appropriate secret key or to delegate it to a smartcard.
@example
SETKEY <keyGrip>
@end example
Tell the server about the key to be used for decryption. If this is
not used, @command{gpg-agent} may try to figure out the key by trying to
decrypt the message with each key available.
@example
PKDECRYPT
@end example
The agent checks whether this command is allowed and then does an
INQUIRY to get the ciphertext the client should then send the cipher
text.
@example
S: INQUIRE CIPHERTEXT
C: D (xxxxxx
C: D xxxx)
C: END
@end example
Please note that the server may send status info lines while reading the
data lines from the client. The data send is a SPKI like S-Exp with
this structure:
@example
(enc-val
(<algo>
(<param_name1> <mpi>)
...
(<param_namen> <mpi>)))
@end example
Where algo is a string with the name of the algorithm; see the libgcrypt
documentation for a list of valid algorithms. The number and names of
the parameters depend on the algorithm. The agent does return an error
if there is an inconsistency.
If the decryption was successful the decrypted data is returned by
means of "D" lines.
Here is an example session:
@example
C: PKDECRYPT
S: INQUIRE CIPHERTEXT
C: D (enc-val elg (a 349324324)
C: D (b 3F444677CA)))
C: END
S: # session key follows
S: D (value 1234567890ABCDEF0)
S: OK descryption successful
@end example
@node Agent PKSIGN
@subsection Signing a Hash
The client ask the agent to sign a given hash value. A default key
will be chosen if no key has been set. To set a key a client first
uses:
@example
SIGKEY <keyGrip>
@end example
This can be used multiple times to create multiple signature, the list
of keys is reset with the next PKSIGN command or a RESET. The server
test whether the key is a valid key to sign something and responds with
okay.
@example
SETHASH --hash=<name>|<algo> <hexstring>
@end example
The client can use this command to tell the server about the data <hexstring>
(which usually is a hash) to be signed. <algo> is the decimal encoded hash
algorithm number as used by Libgcrypt. Either <algo> or --hash=<name>
must be given. Valid names for <name> are:
@table @code
@item sha1
@item sha256
@item rmd160
@item md5
@item tls-md5sha1
@end table
@noindent
The actual signing is done using
@example
PKSIGN <options>
@end example
Options are not yet defined, but my later be used to choosen among
different algorithms. The agent does then some checks, asks for the
passphrase and as a result the server returns the signature as an SPKI
like S-expression in "D" lines:
@example
(sig-val
(<algo>
(<param_name1> <mpi>)
...
(<param_namen> <mpi>)))
@end example
The operation is affected by the option
@example
OPTION use-cache-for-signing=0|1
@end example
The default of @code{1} uses the cache. Setting this option to @code{0}
will lead @command{gpg-agent} to ignore the passphrase cache. Note, that there is
also a global command line option for @command{gpg-agent} to globally disable the
caching.
Here is an example session:
@example
C: SIGKEY <keyGrip>
S: OK key available
C: SIGKEY <keyGrip>
S: OK key available
C: PKSIGN
S: # I did ask the user whether he really wants to sign
S: # I did ask the user for the passphrase
S: INQUIRE HASHVAL
C: D ABCDEF012345678901234
C: END
S: # signature follows
S: D (sig-val rsa (s 45435453654612121212))
S: OK
@end example
@node Agent GENKEY
@subsection Generating a Key
This is used to create a new keypair and store the secret key inside the
active PSE -w which is in most cases a Soft-PSE. An not yet defined
option allows to choose the storage location. To get the secret key out
of the PSE, a special export tool has to be used.
@example
GENKEY
@end example
Invokes the key generation process and the server will then inquire
on the generation parameters, like:
@example
S: INQUIRE KEYPARM
C: D (genkey (rsa (nbits 1024)))
C: END
@end example
The format of the key parameters which depends on the algorithm is of
the form:
@example
(genkey
(algo
(parameter_name_1 ....)
....
(parameter_name_n ....)))
@end example
If everything succeeds, the server returns the *public key* in a SPKI
like S-Expression like this:
@example
(public-key
(rsa
(n <mpi>)
(e <mpi>)))
@end example
Here is an example session:
@example
C: GENKEY
S: INQUIRE KEYPARM
C: D (genkey (rsa (nbits 1024)))
C: END
S: D (public-key
S: D (rsa (n 326487324683264) (e 10001)))
S OK key created
@end example
@node Agent IMPORT
@subsection Importing a Secret Key
This operation is not yet supportted by GpgAgent. Specialized tools
are to be used for this.
There is no actual need because we can expect that secret keys
created by a 3rd party are stored on a smartcard. If we have
generated the key ourself, we do not need to import it.
@node Agent EXPORT
@subsection Export a Secret Key
Not implemented.
Should be done by an extra tool.
@node Agent ISTRUSTED
@subsection Importing a Root Certificate
Actually we do not import a Root Cert but provide a way to validate
any piece of data by storing its Hash along with a description and
an identifier in the PSE. Here is the interface desription:
@example
ISTRUSTED <fingerprint>
@end example
Check whether the OpenPGP primary key or the X.509 certificate with the
given fingerprint is an ultimately trusted key or a trusted Root CA
certificate. The fingerprint should be given as a hexstring (without
any blanks or colons or whatever in between) and may be left padded with
00 in case of an MD5 fingerprint. GPGAgent will answer with:
@example
OK
@end example
The key is in the table of trusted keys.
@example
ERR 304 (Not Trusted)
@end example
The key is not in this table.
Gpg needs the entire list of trusted keys to maintain the web of
trust; the following command is therefore quite helpful:
@example
LISTTRUSTED
@end example
GpgAgent returns a list of trusted keys line by line:
@example
S: D 000000001234454556565656677878AF2F1ECCFF P
S: D 340387563485634856435645634856438576457A P
S: D FEDC6532453745367FD83474357495743757435D S
S: OK
@end example
The first item on a line is the hexified fingerprint where MD5
ingerprints are @code{00} padded to the left and the second item is a
flag to indicate the type of key (so that gpg is able to only take care
of PGP keys). P = OpenPGP, S = S/MIME. A client should ignore the rest
of the line, so that we can extend the format in the future.
Finally a client should be able to mark a key as trusted:
@example
MARKTRUSTED @var{fingerprint} "P"|"S"
@end example
The server will then pop up a window to ask the user whether she
really trusts this key. For this it will probably ask for a text to
be displayed like this:
@example
S: INQUIRE TRUSTDESC
C: D Do you trust the key with the fingerprint @@FPR@@
C: D bla fasel blurb.
C: END
S: OK
@end example
Known sequences with the pattern @@foo@@ are replaced according to this
table:
@table @code
@item @@FPR16@@
Format the fingerprint according to gpg rules for a v3 keys.
@item @@FPR20@@
Format the fingerprint according to gpg rules for a v4 keys.
@item @@FPR@@
Choose an appropriate format to format the fingerprint.
@item @@@@
Replaced by a single @code{@@}
@end table
@node Agent GET_PASSPHRASE
@subsection Ask for a passphrase
This function is usually used to ask for a passphrase to be used for
conventional encryption, but may also be used by programs which need
special handling of passphrases. This command uses a syntax which helps
clients to use the agent with minimum effort.
@example
GET_PASSPHRASE [--data] [--check] @var{cache_id} [@var{error_message} @var{prompt} @var{description}]
@end example
@var{cache_id} is expected to be a string used to identify a cached
passphrase. Use a @code{X} to bypass the cache. With no other
arguments the agent returns a cached passphrase or an error. By
convention either the hexified fingerprint of the key shall be used for
@var{cache_id} or an arbitrary string prefixed with the name of the
calling application and a colon: Like @code{gpg:somestring}.
@var{error_message} is either a single @code{X} for no error message or
a string to be shown as an error message like (e.g. "invalid
passphrase"). Blanks must be percent escaped or replaced by @code{+}'.
@var{prompt} is either a single @code{X} for a default prompt or the
text to be shown as the prompt. Blanks must be percent escaped or
replaced by @code{+}.
@var{description} is a text shown above the entry field. Blanks must be
percent escaped or replaced by @code{+}.
The agent either returns with an error or with a OK followed by the hex
encoded passphrase. Note that the length of the strings is implicitly
limited by the maximum length of a command. If the option
@option{--data} is used, the passphrase is not returned on the OK line
but by regular data lines; this is the preferred method.
If the option @option{--check} is used, the standard passphrase
constraints checks are applied. A check is not done if the passphrase
has been found in the cache.
@example
CLEAR_PASSPHRASE @var{cache_id}
@end example
may be used to invalidate the cache entry for a passphrase. The
function returns with OK even when there is no cached passphrase.
@node Agent GET_CONFIRMATION
@subsection Ask for confirmation
This command may be used to ask for a simple confirmation by
presenting a text and 2 bottonts: Okay and Cancel.
@example
GET_CONFIRMATION @var{description}
@end example
@var{description}is displayed along with a Okay and Cancel
button. Blanks must be percent escaped or replaced by @code{+}. A
@code{X} may be used to display confirmation dialog with a default
text.
The agent either returns with an error or with a OK. Note, that the
length of @var{description} is implicitly limited by the maximum
length of a command.
@node Agent HAVEKEY
@subsection Check whether a key is available
This can be used to see whether a secret key is available. It does
not return any information on whether the key is somehow protected.
@example
HAVEKEY @var{keygrip}
@end example
The Agent answers either with OK or @code{No_Secret_Key} (208). The
caller may want to check for other error codes as well.
@node Agent LEARN
@subsection Register a smartcard
@example
LEARN [--send]
@end example
This command is used to register a smartcard. With the --send
option given the certificates are send back.
@node Agent PASSWD
@subsection Change a Passphrase
@example
PASSWD @var{keygrip}
@end example
This command is used to interactively change the passphrase of the key
indentified by the hex string @var{keygrip}.
@node Agent UPDATESTARTUPTTY
@subsection Change the standard display
@example
UPDATESTARTUPTTY
@end example
Set the startup TTY and X-DISPLAY variables to the values of this
session. This command is useful to direct future pinentry invocations
to another screen. It is only required because there is no way in the
ssh-agent protocol to convey this information.
@node Agent GETEVENTCOUNTER
@subsection Get the Event Counters
@example
GETEVENTCOUNTER
@end example
This function return one status line with the current values of the
event counters. The event counters are useful to avoid polling by
delaying a poll until something has changed. The values are decimal
numbers in the range @code{0} to @code{UINT_MAX} and wrapping around to
0. The actual values should not be relied upon; they shall only be used
to detect a change.
The currently defined counters are are:
@table @code
@item ANY
Incremented with any change of any of the other counters.
@item KEY
Incremented for added or removed private keys.
@item CARD
Incremented for changes of the card readers stati.
@end table
@mansect see also
@ifset isman
@command{gpg2}(1),
@command{gpgsm}(1),
@command{gpg-connect-agent}(1),
@command{scdaemon}(1)
@end ifset
@include see-also-note.texi
diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi
index 91b056aeb..6eb2f1656 100644
--- a/doc/scdaemon.texi
+++ b/doc/scdaemon.texi
@@ -1,667 +1,667 @@
@c Copyright (C) 2002 Free Software Foundation, Inc.
@c This is part of the GnuPG manual.
@c For copying conditions, see the file gnupg.texi.
@node Invoking SCDAEMON
@chapter Invoking the SCDAEMON
@cindex SCDAEMON command options
@cindex command options
@cindex options, SCDAEMON command
@manpage scdaemon.1
@ifset manverb
.B scdaemon
\- Smartcard daemon for the GnuPG system
@end ifset
@mansect synopsis
@ifset manverb
.B scdaemon
.RB [ \-\-homedir
.IR dir ]
.RB [ \-\-options
.IR file ]
.RI [ options ]
.B \-\-server
.br
.B scdaemon
.RB [ \-\-homedir
.IR dir ]
.RB [ \-\-options
.IR file ]
.RI [ options ]
.B \-\-daemon
.RI [ command_line ]
@end ifset
@mansect description
The @command{scdaemon} is a daemon to manage smartcards. It is usually
invoked by @command{gpg-agent} and in general not used directly.
@manpause
@xref{Option Index}, for an index to @command{scdaemon}'s commands and
options.
@mancont
@menu
* Scdaemon Commands:: List of all commands.
* Scdaemon Options:: List of all options.
* Card applications:: Description of card applications.
* Scdaemon Configuration:: Configuration files.
* Scdaemon Examples:: Some usage examples.
* Scdaemon Protocol:: The protocol the daemon uses.
@end menu
@mansect commands
@node Scdaemon Commands
@section Commands
Commands are not distinguished from options execpt for the fact that
only one one command is allowed.
@table @gnupgtabopt
@item --version
@opindex version
Print the program version and licensing information. Not that you can
abbreviate this command.
@item --help, -h
@opindex help
Print a usage message summarizing the most usefule command-line options.
Not that you can abbreviate this command.
@item --dump-options
@opindex dump-options
Print a list of all available options and commands. Not that you can
abbreviate this command.
@item --server
@opindex server
Run in server mode and wait for commands on the @code{stdin}. This is
default mode is to create a socket and listen for commands there.
@item --multi-server
@opindex multi-server
Run in server mode and wait for commands on the @code{stdin} as well as
on an additional Unix Domain socket. The server command @code{GETINFO}
may be used to get the name of that extra socket.
@item --daemon
@opindex daemon
Run the program in the background. This option is required to prevent
it from being accidently running in the background.
@item --print-atr
@opindex print-atr
This is mainly a debugging command, used to print the ATR
(Answer-To-Reset) of a card and exit immediately.
@end table
@mansect options
@node Scdaemon Options
@section Option Summary
@table @gnupgtabopt
@item --options @var{file}
@opindex options
Reads configuration from @var{file} instead of from the default
per-user configuration file. The default configuration file is named
@file{scdaemon.conf} and expected in the @file{.gnupg} directory directly
below the home directory of the user.
@include opt-homedir.texi
@item -v
@item --verbose
@opindex v
@opindex verbose
Outputs additional information while running.
You can increase the verbosity by giving several
verbose commands to @command{gpgsm}, such as @samp{-vv}.
@item --debug-level @var{level}
@opindex debug-level
Select the debug level for investigating problems. @var{level} may be
one of:
@table @code
@item none
no debugging at all.
@item basic
some basic debug messages
@item advanced
more verbose debug messages
@item expert
even more detailed messages
@item guru
all of the debug messages you can get
@end table
How these messages are mapped to the actual debugging flags is not
specified and may change with newer releaes of this program. They are
however carefully selected to best aid in debugging.
@quotation Note
All debugging options are subject to change and thus should not be used
by any application program. As the name says, they are only used as
helpers to debug problems.
@end quotation
@item --debug @var{flags}
@opindex debug
This option is only useful for debugging and the behaviour may change at
any time without notice. FLAGS are bit encoded and may be given in
usual C-Syntax. The currently defined bits are:
@table @code
@item 0 (1)
command I/O
@item 1 (2)
values of big number integers
@item 2 (4)
low level crypto operations
@item 5 (32)
memory allocation
@item 6 (64)
caching
@item 7 (128)
show memory statistics.
@item 9 (512)
write hashed data to files named @code{dbgmd-000*}
@item 10 (1024)
trace Assuan protocol
@item 11 (2048)
trace APDU I/O to the card. This may reveal sensitive data.
@end table
@item --debug-all
@opindex debug-all
Same as @code{--debug=0xffffffff}
@item --debug-wait @var{n}
@opindex debug-wait
When running in server mode, wait @var{n} seconds before entering the
actual processing loop and print the pid. This gives time to attach a
debugger.
@item --debug-ccid-driver
@opindex debug-wait
Enable debug output from the included CCID driver for smartcards.
Using this option twice will also enable some tracing of the T=1
protocol. Note that this option may reveal sensitive data.
@item --debug-disable-ticker
@opindex debug-disable-ticker
This option disables all ticker functions like checking for card
insertions.
@item --debug-allow-core-dump
@opindex debug-allow-core-dump
For security reasons we won't create a core dump when the process
aborts. For debugging purposes it is sometimes better to allow core
dump. This options enables it and also changes the working directory to
@file{/tmp} when running in @option{--server} mode.
@item --no-detach
@opindex no-detach
Don't detach the process from the console. This is manly usefule for
debugging.
@item --log-file @var{file}
@opindex log-file
Append all logging output to @var{file}. This is very helpful in
seeing what the agent actually does.
@item --pcsc-driver @var{library}
@opindex pcsc-driver
Use @var{library} to access the smartcard reader. The current default
is @file{libpcsclite.so}. Instead of using this option you might also
want to install a symbolic link to the default file name
(e.g. from @file{libpcsclite.so.1}).
@item --ctapi-driver @var{library}
@opindex ctapi-driver
Use @var{library} to access the smartcard reader. The current default
is @file{libtowitoko.so}. Note that the use of this interface is
deprecated; it may be removed in future releases.
@item --disable-ccid
@opindex disable-ccid
Disable the integrated support for CCID compliant readers. This
allows to fall back to one of the other drivers even if the internal
CCID driver can handle the reader. Note, that CCID support is only
available if libusb was available at build time.
@item --reader-port @var{number_or_string}
@opindex reader-port
This option may be used to specify the port of the card terminal. A
value of 0 refers to the first serial device; add 32768 to access USB
devices. The default is 32768 (first USB device). PC/SC or CCID
readers might need a string here; run the program in verbose mode to get
a list of available readers. The default is then the first reader
found.
@item --disable-keypad
@opindex disable-keypad
Even if a card reader features a keypad, do not try to use it.
@item --allow-admin
@itemx --deny-admin
@opindex allow-admin
@opindex deny-admin
This enables the use of Admin class commands for card applications
where this is supported. Currently we support it for the OpenPGP
card. Deny is the default. This commands is useful to inhibit
accidental access to admin class command which could ultimately lock
the card through worng PIN numbers.
@item --disable-application @var{name}
@opindex disable-application
This option disables the use of the card application named
@var{name}. This is mainly useful for debugging or if a application
with lower priority should be used by default.
@end table
All the long options may also be given in the configuration file after
stripping off the two leading dashes.
@mansect card applications
@node Card applications
@section Description of card applications
@command{scdaemon} supports the card applications as described below.
@menu
* OpenPGP Card:: The OpenPGP card application
* NKS Card:: The Telesec NetKey card application
* DINSIG Card:: The DINSIG card application
* PKCS#15 Card:: The PKCS#15 card application
@end menu
@node OpenPGP Card
@subsection The OpenPGP card application ``openpgp''
This application is currently only used by @command{gpg} but may in
future also be useful with @command{gpgsm}.
The specification for such a card is available at
@uref{http://g10code.com/docs/openpgp-card-1.0.pdf}.
@node NKS Card
@subsection The Telesec NetKey card ``nks''
This is the main application of the Telesec cards as available in
Germany. It is a superset of the German DINSIG card. The card is
used by @command{gpgsm}.
@node DINSIG Card
@subsection The DINSIG card application ``dinsig''
This is an application as described in the German draft standard
-@emph{DIN V 66291-1}. It is intended to be used by cards supporteing
+@emph{DIN V 66291-1}. It is intended to be used by cards supporting
the German signature law and its bylaws (SigG and SigV).
@node PKCS#15 Card
@subsection The PKCS#15 card application ``p15''
This is common fraqmework for smart card applications. It is used by
@command{gpgsm}.
@c *******************************************
@c *************** ****************
@c *************** FILES ****************
@c *************** ****************
@c *******************************************
@mansect files
@node Scdaemon Configuration
@section Configuration files
There are a few configuration files to control certain aspects of
@command{scdaemons}'s operation. Unless noted, they are expected in the
current home directory (@pxref{option --homedir}).
@table @file
@item scdaemon.conf
@cindex scdaemon.conf
This is the standard configuration file read by @command{scdaemon} on
startup. It may contain any valid long option; the leading two dashes
may not be entered and the option may not be abbreviated. This default
name may be changed on the command line (@pxref{option --options}).
@item scd-event
@cindex scd-event
If this file is present and executable, it will be called on veyer card
reader's status changed. An example of this script is provided with the
distribution
@item reader_@var{n}.status
This file is created by @command{sdaemon} to let other applications now
about reader status changes. Its use is now deprecated in favor of
@file{scd-event}.
@end table
@c
@c Examples
@c
@mansect examples
@node Scdaemon Examples
@section Examples
@c man begin EXAMPLES
@example
$ scdaemon --server -v
@end example
@c man end
@c
@c Assuan Protocol
@c
@manpause
@node Scdaemon Protocol
@section Scdaemon's Assuan Protocol
The SC-Daemon should be started by the system to provide access to
external tokens. Using Smartcards on a multi-user system does not
make much sense expcet for system services, but in this case no
regular user accounts are hosted on the machine.
A client connects to the SC-Daemon by connecting to the socket named
@file{/var/run/scdaemon/socket}, configuration information is read from
@var{/etc/scdaemon.conf}
Each connection acts as one session, SC-Daemon takes care of
syncronizing access to a token between sessions.
@menu
* Scdaemon SERIALNO:: Return the serial number.
* Scdaemon LEARN:: Read all useful information from the card.
* Scdaemon READCERT:: Return a certificate.
* Scdaemon READKEY:: Return a public key.
* Scdaemon PKSIGN:: Signing data with a Smartcard.
* Scdaemon PKDECRYPT:: Decrypting data with a Smartcard.
* Scdaemon GETATTR:: Read an attribute's value.
* Scdaemon SETATTR:: Update an attribute's value.
* Scdaemon WRITEKEY:: Write a key to a card.
* Scdaemon GENKEY:: Generate a new key on-card.
* Scdaemon RANDOM:: Return random bytes generate on-card.
* Scdaemon PASSWD:: Change PINs.
* Scdaemon CHECKPIN:: Perform a VERIFY operation.
* Scdaemon RESTART:: Restart connection
* Scdaemon APDU:: Send a verbatim APDU to the card
@end menu
@node Scdaemon SERIALNO
@subsection Return the serial number
This command should be used to check for the presence of a card. It is
special in that it can be used to reset the card. Most other commands
will return an error when a card change has been detected and the use of
this function is therefore required.
Background: We want to keep the client clear of handling card changes
between operations; i.e. the client can assume that all operations are
done on the same card unless he call this function.
@example
SERIALNO
@end example
Return the serial number of the card using a status reponse like:
@example
S SERIALNO D27600000000000000000000 0
@end example
The trailing 0 should be ignored for now, it is reserved for a future
extension. The serial number is the hex encoded value identified by
the @code{0x5A} tag in the GDO file (FIX=0x2F02).
@node Scdaemon LEARN
@subsection Read all useful information from the card
@example
LEARN [--force]
@end example
Learn all useful information of the currently inserted card. When
used without the force options, the command might do an INQUIRE
like this:
@example
INQUIRE KNOWNCARDP <hexstring_with_serialNumber> <timestamp>
@end example
The client should just send an @code{END} if the processing should go on
or a @code{CANCEL} to force the function to terminate with a cancel
error message. The response of this command is a list of status lines
formatted as this:
@example
S KEYPAIRINFO @var{hexstring_with_keygrip} @var{hexstring_with_id}
@end example
If there is no certificate yet stored on the card a single "X" is
returned in @var{hexstring_with_keygrip}.
@node Scdaemon READCERT
@subsection Return a certificate
@example
READCERT @var{hexified_certid}
@end example
This function is used to read a certificate identified by
@var{hexified_certid} from the card.
@node Scdaemon READKEY
@subsection Return a public key
@example
READKEY @var{hexified_certid}
@end example
Return the public key for the given cert or key ID as an standard
S-Expression.
@node Scdaemon PKSIGN
@subsection Signing data with a Smartcard
To sign some data the caller should use the command
@example
SETDATA @var{hexstring}
@end example
to tell @command{scdaemon} about the data to be signed. The data must be given in
hex notation. The actual signing is done using the command
@example
PKSIGN @var{keyid}
@end example
where @var{keyid} is the hexified ID of the key to be used. The key id
may have been retrieved using the command @code{LEARN}. If another
hash algorithm than SHA-1 is used, that algorithm may be given like:
@example
PKSIGN --hash=@var{algoname} @var{keyid}
@end example
With @var{algoname} are one of @code{sha1}, @code{rmd160} or @code{md5}.
@node Scdaemon PKDECRYPT
@subsection Decrypting data with a Smartcard
To decrypt some data the caller should use the command
@example
SETDATA @var{hexstring}
@end example
to tell @command{scdaemon} about the data to be decrypted. The data
must be given in hex notation. The actual decryption is then done
using the command
@example
PKDECRYPT @var{keyid}
@end example
where @var{keyid} is the hexified ID of the key to be used.
@node Scdaemon GETATTR
@subsection Read an attribute's value.
TO BE WRITTEN.
@node Scdaemon SETATTR
@subsection Update an attribute's value.
TO BE WRITTEN.
@node Scdaemon WRITEKEY
@subsection Write a key to a card.
@example
WRITEKEY [--force] @var{keyid}
@end example
This command is used to store a secret key on a a smartcard. The
allowed keyids depend on the currently selected smartcard
application. The actual keydata is requested using the inquiry
@code{KEYDATA} and need to be provided without any protection. With
@option{--force} set an existing key under this @var{keyid} will get
overwritten. The key data is expected to be the usual canonical encoded
S-expression.
A PIN will be requested in most saes. This however depends on the
actual card application.
@node Scdaemon GENKEY
@subsection Generate a new key on-card.
TO BE WRITTEN.
@node Scdaemon RANDOM
@subsection Return random bytes generate on-card.
TO BE WRITTEN.
@node Scdaemon PASSWD
@subsection Change PINs.
@example
PASSWD [--reset] @var{chvno}
@end example
Change the PIN or reset the retry counter of the card holder
verification vector number @var{chvno}.
@node Scdaemon CHECKPIN
@subsection Perform a VERIFY operation.
@example
CHECKPIN @var{idstr}
@end example
Perform a VERIFY operation without doing anything else. This may be
used to initialize a the PIN cache earlier to long lasting
operations. Its use is highly application dependent:
@table @strong
@item OpenPGP
Perform a simple verify operation for CHV1 and CHV2, so that further
operations won't ask for CHV2 and it is possible to do a cheap check on
the PIN: If there is something wrong with the PIN entry system, only the
regular CHV will get blocked and not the dangerous CHV3. @var{idstr} is
the usual card's serial number in hex notation; an optional fingerprint
part will get ignored.
There is however a special mode if @var{idstr} is suffixed with the
literal string @code{[CHV3]}: In this case the Admin PIN is checked if
and only if the retry counter is still at 3.
@end table
@node Scdaemon RESTART
@subsection Perform a RESTART operation.
@example
RESTART
@end example
Restart the current connection; this is a kind of warm reset. It
deletes the context used by this connection but does not actually
reset the card.
This is used by gpg-agent to reuse a primary pipe connection and
may be used by clients to backup from a conflict in the serial
command; i.e. to select another application.
@node Scdaemon APDU
@subsection Send a verbatim APDU to the card.
@example
APDU [--atr] [--more] [@var{hexstring}]
@end example
Send an APDU to the current reader. This command bypasses the high
level functions and sends the data directly to the card.
@var{hexstring} is expected to be a proper APDU. If @var{hexstring} is
not given no commands are send to the card; However the command will
implictly check whether the card is ready for use.
Using the option @code{--atr} returns the ATR of the card as a status
message before any data like this:
@example
S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1
@end example
Using the option @code{--more} handles the card status word MORE_DATA
(61xx) and concatenate all reponses to one block.
@mansect see also
@ifset isman
@command{gpg-agent}(1),
@command{gpgsm}(1),
@command{gpg2}(1)
@end ifset
@include see-also-note.texi
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Feb 26, 6:26 PM (10 h, 32 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
a3/f8/3ab6f84342d600e927fd541b0730
Attached To
rG GnuPG
Event Timeline
Log In to Comment