From 5885142c83823b153689acd272103403127a3cd3 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 20 Nov 2006 16:49:41 +0000 Subject: [PATCH] Made some PIN pads work. Some cleanups for 64 bit CPUs. --- ChangeLog | 4 ++ Makefile.am | 2 +- NEWS | 5 +++ THANKS | 1 + agent/ChangeLog | 24 +++++++++++ agent/agent.h | 11 +++-- agent/call-pinentry.c | 7 +-- agent/call-scd.c | 16 ++++--- agent/command-ssh.c | 40 +++++++----------- agent/command.c | 44 ++++++++----------- agent/gpg-agent.c | 89 ++++++++++++++++++++++++++++++++------- agent/minip12.c | 7 +-- agent/protect.c | 2 +- autogen.sh | 48 +++++++++++++++++++++ common/ChangeLog | 8 ++++ common/estream.c | 13 +++++- common/iobuf.c | 2 +- jnlib/ChangeLog | 7 ++- jnlib/logging.c | 9 +++- kbx/ChangeLog | 4 ++ kbx/kbxutil.c | 2 +- m4/ChangeLog | 5 +++ m4/gnupg-pth.m4 | 1 + scd/ChangeLog | 34 +++++++++++++++ scd/apdu.c | 22 +++++++--- scd/app-openpgp.c | 53 +++++++++++++++++------ scd/app-p15.c | 3 +- scd/ccid-driver.c | 73 +++++++++++++++++++++----------- scd/command.c | 58 +++++++++++++++++-------- scd/iso7816.c | 2 +- scd/scdaemon.c | 55 ++++++++++++++++++------ scd/scdaemon.h | 9 +++- tests/openpgp/ChangeLog | 5 +++ tests/openpgp/Makefile.am | 2 +- tools/ChangeLog | 4 ++ tools/gpgconf-comp.c | 2 +- 36 files changed, 502 insertions(+), 171 deletions(-) diff --git a/ChangeLog b/ChangeLog index db8df3ea2..5a2d98b61 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2006-11-15 Werner Koch + + * autogen.sh: Add convenience option --build-amd64. + 2006-11-14 Werner Koch * configure.ac (HAVE_ASSUAN_SET_IO_MONITOR): Test for it. diff --git a/Makefile.am b/Makefile.am index 996ed02e9..c5dec1426 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,7 +22,7 @@ ACLOCAL_AMFLAGS = -I m4 -I gl/m4 AUTOMAKE_OPTIONS = dist-bzip2 -DISTCHECK_CONFIGURE_FLAGS = --enable-gpg +DISTCHECK_CONFIGURE_FLAGS = --enable-symcryptrun EXTRA_DIST = scripts/config.rpath autogen.sh README.SVN DISTCLEANFILES = g10defs.h diff --git a/NEWS b/NEWS index 3e2232f1f..0f589c9a0 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,11 @@ Noteworthy changes in version 2.0.1 ------------------------------------------------- + * Experimental support for the PIN pads of the SPR 532 and the Kaan + Advanced card readers. Add "disable-keypad" scdaemon.conf if you + don't want it. Does currently only work for the OpenPGP card and + the authentication and decrypt keys. + Noteworthy changes in version 2.0.0 (2006-11-11) ------------------------------------------------- diff --git a/THANKS b/THANKS index 40d1a344e..868e75578 100644 --- a/THANKS +++ b/THANKS @@ -90,6 +90,7 @@ Greg Troxel gdt at ir.bbn.com Gregory Steuck steuck at iname.com Harald Denker harry at hal.westfalen.de Holger Baust Holger.Baust at freenet-ag.de +Henrik Nordstrom henrik at henriknordstrom.net Hendrik Buschkamp buschkamp at rheumanet.org Holger Schurig holger at d.om.org Holger Smolinski smolinsk at de.ibm.com diff --git a/agent/ChangeLog b/agent/ChangeLog index 761b7b013..ddee4e5c6 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,27 @@ +2006-11-20 Werner Koch + + * call-pinentry.c (agent_popup_message_stop): Use SIGKILL. + * call-scd.c (inq_needpin): Implement POPUPKEYPADPROMPT and + DISMISSKEYPADPROMPT. + +2006-11-15 Werner Koch + + * protect.c (make_shadow_info): Cast printf arg to unsigned int. + * minip12.c (parse_bag_encrypted_data): Ditto. + (parse_bag_data, p12_parse): Ditto. + * command-ssh.c (ssh_identity_register): Changed buffer_n to + size_t. + + * agent.h (struct server_control_s): New field thread_startup. + * command.c (start_command_handler): Moved CTRL init code to .. + * gpg-agent.c (start_connection_thread): .. here. + (agent_deinit_default_ctrl): New. + (agent_init_default_ctrl): Made static. + (handle_connections): Allocate CTRL and pass it pth_spawn. + * command-ssh.c (start_command_handler_ssh): Moved CTRL init code + to .. + * gpg-agent.c (start_connection_thread_ssh): .. here. + 2006-11-14 Werner Koch * command.c (bump_key_eventcounter): New. diff --git a/agent/agent.h b/agent/agent.h index 2b7f36741..883924cd9 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -112,6 +112,12 @@ 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; @@ -178,16 +184,15 @@ cache_mode_t; /*-- gpg-agent.c --*/ void agent_exit (int rc) JNLIB_GCC_A_NR; /* Also implemented in other tools */ -void agent_init_default_ctrl (struct server_control_s *ctrl); /*-- 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 (int, int); +void start_command_handler (ctrl_t, int, int); /*-- command-ssh.c --*/ -void start_command_handler_ssh (int); +void start_command_handler_ssh (ctrl_t, int); /*-- findkey.c --*/ int agent_write_private_key (const unsigned char *grip, diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c index 7193db799..f22136fd4 100644 --- a/agent/call-pinentry.c +++ b/agent/call-pinentry.c @@ -636,7 +636,7 @@ popup_message_thread (void *arg) /* 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 becuase the message is + 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 @@ -723,8 +723,9 @@ agent_popup_message_stop (ctrl_t ctrl) if (rc == pid) assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1); } - else - kill (pid, SIGINT); + 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); diff --git a/agent/call-scd.c b/agent/call-scd.c index 2f91e1e84..53e4ced4d 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -711,17 +711,19 @@ inq_needpin (void *opaque, const char *line) rc = assuan_send_data (parm->ctx, pin, pinlen); xfree (pin); } - else if (!strncmp (line, "KEYPADINFO", 10) && (line[10] == ' ' || !line[10])) + else if (!strncmp (line, "POPUPKEYPADPROMPT", 17) + && (line[17] == ' ' || !line[17])) { - size_t code; - char *endp; - - code = strtoul (line+10, &endp, 10); - line = endp; + line += 17; while (*line == ' ') line++; - rc = parm->getpin_cb (parm->getpin_cb_arg, line, NULL, code); + rc = parm->getpin_cb (parm->getpin_cb_arg, line, NULL, 1); + } + else if (!strncmp (line, "DISMISSKEYPADPROMPT", 19) + && (line[19] == ' ' || !line[19])) + { + rc = parm->getpin_cb (parm->getpin_cb_arg, "", NULL, 0); } else { diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 1adf8ba94..b44dc2140 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -2329,7 +2329,7 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) unsigned char key_grip_raw[20]; char key_grip[41]; unsigned char *buffer = NULL; - unsigned int buffer_n; + size_t buffer_n; char *description = NULL; char *comment = NULL; unsigned int i; @@ -2821,32 +2821,28 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) /* Start serving client on SOCK_CLIENT. */ void -start_command_handler_ssh (int sock_client) +start_command_handler_ssh (ctrl_t ctrl, int sock_client) { - struct server_control_s ctrl; estream_t stream_sock; gpg_error_t err; int ret; /* Setup control structure. */ - - memset (&ctrl, 0, sizeof (ctrl)); - agent_init_default_ctrl (&ctrl); - ctrl.connection_fd = sock_client; + ctrl->connection_fd = sock_client; /* Because the ssh protocol does not send us information about the the current TTY setting, we resort here to use those from startup or those explictly set. */ - if (!ctrl.display && opt.startup_display) - ctrl.display = strdup (opt.startup_display); - if (!ctrl.ttyname && opt.startup_ttyname) - ctrl.ttyname = strdup (opt.startup_ttyname); - if (!ctrl.ttytype && opt.startup_ttytype) - ctrl.ttytype = strdup (opt.startup_ttytype); - if (!ctrl.lc_ctype && opt.startup_lc_ctype) - ctrl.lc_ctype = strdup (opt.startup_lc_ctype); - if (!ctrl.lc_messages && opt.startup_lc_messages) - ctrl.lc_messages = strdup (opt.startup_lc_messages); + if (!ctrl->display && opt.startup_display) + ctrl->display = strdup (opt.startup_display); + if (!ctrl->ttyname && opt.startup_ttyname) + ctrl->ttyname = strdup (opt.startup_ttyname); + if (!ctrl->ttytype && opt.startup_ttytype) + ctrl->ttytype = strdup (opt.startup_ttytype); + if (!ctrl->lc_ctype && opt.startup_lc_ctype) + ctrl->lc_ctype = strdup (opt.startup_lc_ctype); + if (!ctrl->lc_messages && opt.startup_lc_messages) + ctrl->lc_messages = strdup (opt.startup_lc_messages); /* Create stream from socket. */ @@ -2870,20 +2866,14 @@ start_command_handler_ssh (int sock_client) } /* Main processing loop. */ - while ( !ssh_request_process (&ctrl, stream_sock) ) + while ( !ssh_request_process (ctrl, stream_sock) ) ; /* Reset the SCD in case it has been used. */ - agent_reset_scd (&ctrl); + agent_reset_scd (ctrl); out: if (stream_sock) es_fclose (stream_sock); - - free (ctrl.display); - free (ctrl.ttyname); - free (ctrl.ttytype); - free (ctrl.lc_ctype); - free (ctrl.lc_messages); } diff --git a/agent/command.c b/agent/command.c index d28dd7cb6..63f41c369 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1441,18 +1441,16 @@ register_commands (assuan_context_t ctx) } -/* Startup the server. If LISTEN_FD and FD is given as -1, this is a simple - piper server, otherwise it is a regular server */ +/* Startup the server. If LISTEN_FD and FD is given as -1, this is a + simple piper server, otherwise it is a regular server. CTRL is the + control structure for this connection; it has only the basic + intialization. */ void -start_command_handler (int listen_fd, int fd) +start_command_handler (ctrl_t ctrl, int listen_fd, int fd) { int rc; assuan_context_t ctx; - struct server_control_s ctrl; - memset (&ctrl, 0, sizeof ctrl); - agent_init_default_ctrl (&ctrl); - if (listen_fd == -1 && fd == -1) { int filedes[2]; @@ -1468,7 +1466,7 @@ start_command_handler (int listen_fd, int fd) else { rc = assuan_init_socket_server_ext (&ctx, fd, 2); - ctrl.connection_fd = fd; + ctrl->connection_fd = fd; } if (rc) { @@ -1484,12 +1482,12 @@ start_command_handler (int listen_fd, int fd) agent_exit (2); } - assuan_set_pointer (ctx, &ctrl); - ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local); - ctrl.server_local->assuan_ctx = ctx; - ctrl.server_local->message_fd = -1; - ctrl.server_local->use_cache_for_signing = 1; - ctrl.digest.raw_value = 0; + assuan_set_pointer (ctx, ctrl); + ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local); + ctrl->server_local->assuan_ctx = ctx; + ctrl->server_local->message_fd = -1; + ctrl->server_local->use_cache_for_signing = 1; + ctrl->digest.raw_value = 0; if (DBG_ASSUAN) assuan_set_log_stream (ctx, log_get_stream ()); @@ -1520,22 +1518,14 @@ start_command_handler (int listen_fd, int fd) } /* Reset the SCD if needed. */ - agent_reset_scd (&ctrl); + agent_reset_scd (ctrl); /* Reset the pinentry (in case of popup messages). */ - agent_reset_query (&ctrl); + agent_reset_query (ctrl); + /* Cleanup. */ assuan_deinit_server (ctx); - 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); - xfree (ctrl.server_local); + xfree (ctrl->server_local); + ctrl->server_local = NULL; } diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 793bc91bf..75ffb70da 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -211,6 +211,9 @@ static char *create_socket_name (int use_standard_socket, 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); @@ -813,8 +816,21 @@ main (int argc, char **argv ) if (pipe_server) - { /* this is the simple pipe based server */ - start_command_handler (-1, -1); + { + /* 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 */ @@ -1073,8 +1089,8 @@ agent_exit (int rc) } -void -agent_init_default_ctrl (struct server_control_s *ctrl) +static void +agent_init_default_ctrl (ctrl_t ctrl) { ctrl->connection_fd = -1; @@ -1103,6 +1119,21 @@ agent_init_default_ctrl (struct server_control_s *ctrl) } +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. @@ -1437,17 +1468,20 @@ handle_signal (int signo) static void * start_connection_thread (void *arg) { - int fd = (int)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 (), fd); + (long)pth_self (), ctrl->thread_startup.fd); - start_command_handler (-1, 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 (), fd); + (long)pth_self (), ctrl->thread_startup.fd); + agent_deinit_default_ctrl (ctrl); + xfree (ctrl); return NULL; } @@ -1456,17 +1490,20 @@ start_connection_thread (void *arg) static void * start_connection_thread_ssh (void *arg) { - int fd = (int)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 (), fd); + (long)pth_self (), ctrl->thread_startup.fd); - start_command_handler_ssh (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 (), fd); + (long)pth_self (), ctrl->thread_startup.fd); + agent_deinit_default_ctrl (ctrl); + xfree (ctrl); return NULL; } @@ -1584,24 +1621,35 @@ handle_connections (int listen_fd, int listen_fd_ssh) 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); - if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) + 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; @@ -1609,25 +1657,36 @@ handle_connections (int listen_fd, int listen_fd_ssh) 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); - - if (!pth_spawn (tattr, start_connection_thread_ssh, (void*)fd)) + 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; diff --git a/agent/minip12.c b/agent/minip12.c index 2da118022..25a38b9c8 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -888,7 +888,7 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, gcry_free (plain); gcry_free (cram_buffer); log_error ("encryptedData error at \"%s\", offset %u\n", - where, (p - p_start)+startoffset); + where, (unsigned int)((p - p_start)+startoffset)); if (bad_pass) { /* Note, that the following string might be used by other programs @@ -1133,7 +1133,7 @@ parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, } gcry_free (cram_buffer); log_error ( "data error at \"%s\", offset %u\n", - where, (p - buffer) + startoffset); + where, (unsigned int)((p - buffer) + startoffset)); if (r_consumed) *r_consumed = consumed; return NULL; @@ -1309,7 +1309,8 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw, gcry_free (cram_buffer); return result; bailout: - log_error ("error at \"%s\", offset %u\n", where, (p - p_start)); + log_error ("error at \"%s\", offset %u\n", + where, (unsigned int)(p - p_start)); if (result) { int i; diff --git a/agent/protect.c b/agent/protect.c index 19f6ccbc6..2bb38f316 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -861,7 +861,7 @@ make_shadow_info (const char *serialno, const char *idstring) p = stpcpy (p, numbuf); for (s=serialno; *s && s[1]; s += 2) *(unsigned char *)p++ = xtoi_2 (s); - sprintf (numbuf, "%d:", strlen (idstring)); + sprintf (numbuf, "%u:", (unsigned int)strlen (idstring)); p = stpcpy (p, numbuf); p = stpcpy (p, idstring); *p++ = ')'; diff --git a/autogen.sh b/autogen.sh index 2636c0888..8a20b1a38 100755 --- a/autogen.sh +++ b/autogen.sh @@ -93,7 +93,55 @@ if test "$1" = "--build-w32"; then fi # ***** end W32 build script ******* +# ***** AMD64 cross build script ******* +# Used to cross-compile for AMD64 (for testing) +if test "$1" = "--build-amd64"; then + tmp=`dirname $0` + tsdir=`cd "$tmp"; pwd` + shift + if [ ! -f $tsdir/scripts/config.guess ]; then + echo "$tsdir/scripts/config.guess not found" >&2 + exit 1 + fi + build=`$tsdir/scripts/config.guess` + [ -z "$amd64root" ] && amd64root="$HOME/amd64root" + echo "Using $amd64root as standard install directory" >&2 + + # Locate the cross compiler + crossbindir= + for host in x86_64-linux-gnu amd64-linux-gnu; do + if ${host}-gcc --version >/dev/null 2>&1 ; then + crossbindir=/usr/${host}/bin + conf_CC="CC=${host}-gcc" + break; + fi + done + if [ -z "$crossbindir" ]; then + echo "Cross compiler kit not installed" >&2 + echo "Stop." >&2 + exit 1 + fi + + if [ -f "$tsdir/config.log" ]; then + if ! head $tsdir/config.log | grep "$host" >/dev/null; then + echo "Please run a 'make distclean' first" >&2 + exit 1 + fi + fi + + $tsdir/configure --enable-maintainer-mode --prefix=${amd64root} \ + --host=${host} --build=${build} \ + --with-gpg-error-prefix=${amd64root} \ + --with-ksba-prefix=${amd64root} \ + --with-libgcrypt-prefix=${amd64root} \ + --with-libassuan-prefix=${amd64root} \ + --with-zlib=/usr/x86_64-linux-gnu/usr \ + --with-pth-prefix=/usr/x86_64-linux-gnu/usr + rc=$? + exit $rc +fi +# ***** end AMD64 cross build script ******* # Grep the required versions from configure.ac diff --git a/common/ChangeLog b/common/ChangeLog index 25af94867..5ff12da97 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,11 @@ +2006-11-15 Werner Koch + + * estream.c: Disabled Pth soft mapping. + (my_funopen_hook_ret_t): New. + (print_fun_writer): Use it here. + + * iobuf.c (fd_cache_close): Use %d instead of %p for debug output. + 2006-11-03 Werner Koch * Makefile.am (t_convert_DEPENDENCIES): Add libcommon. From diff --git a/common/estream.c b/common/estream.c index e056cb7b4..e00191e53 100644 --- a/common/estream.c +++ b/common/estream.c @@ -46,6 +46,9 @@ #endif #ifdef HAVE_PTH + /* We explicitly need to disable soft mapping as Debian currently + enables it for no reason. */ +# define PTH_SYSCALL_SOFT 0 # include #endif @@ -59,6 +62,7 @@ void *memrchr (const void *block, int c, size_t size); #include + /* Generally used types. */ @@ -66,6 +70,13 @@ void *memrchr (const void *block, int c, size_t size); typedef void *(*func_realloc_t) (void *mem, size_t size); typedef void (*func_free_t) (void *mem); +#ifdef HAVE_FOPENCOOKIE +typedef ssize_t my_funopen_hook_ret_t; +#else +typedef int my_funopen_hook_ret_t; +#endif + + /* Buffer management layer. */ @@ -1651,7 +1662,7 @@ doreadline (estream_t ES__RESTRICT stream, size_t max_length, /* Helper for esprint. */ #if defined(HAVE_FOPENCOOKIE) || defined(HAVE_FUNOPEN) -static int +static my_funopen_hook_ret_t print_fun_writer (void *cookie_arg, const char *buffer, size_t size) { estream_t stream = cookie_arg; diff --git a/common/iobuf.c b/common/iobuf.c index 113d35bb4..c01702696 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -271,7 +271,7 @@ fd_cache_close (const char *fname, FILEP_OR_FD fp) close (fp); #endif if (DBG_IOBUF) - log_debug ("fd_cache_close (%p) real\n", (void *) fp); + log_debug ("fd_cache_close (%d) real\n", fp); return; } /* try to reuse a slot */ diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 65e7d4786..68340896c 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,8 @@ +2006-11-15 Werner Koch + + * logging.c (my_funopen_hook_ret_t): New. + (fun_writer): Use it. + 2006-10-19 Werner Koch * stringhelp.c (memrchr) [!HAVE_MEMRCHR]: Provide a replacement. @@ -5,7 +10,7 @@ 2006-09-27 Werner Koch * mischelp.c: New. - (timegm): Copied from gnupg 1.4, Changed from LGPL to GPL. Fixed + (timegm): Copied from gnupg 1.4, changed from GPL to LGPL. Fixed a memory leak. * stringhelp.h (isascii): New. diff --git a/jnlib/logging.c b/jnlib/logging.c index dce5ab2ea..0df4422b0 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -48,6 +48,13 @@ #define USE_FUNWRITER 1 #endif +#ifdef HAVE_FOPENCOOKIE +typedef ssize_t my_funopen_hook_ret_t; +#else +typedef int my_funopen_hook_ret_t; +#endif + + static FILE *logstream; static int log_socket = -1; static char prefix_buffer[80]; @@ -111,7 +118,7 @@ writen (int fd, const void *buffer, size_t nbytes) } -static int +static my_funopen_hook_ret_t fun_writer (void *cookie_arg, const char *buffer, size_t size) { struct fun_cookie_s *cookie = cookie_arg; diff --git a/kbx/ChangeLog b/kbx/ChangeLog index 52962eae0..bb1a38aa3 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,7 @@ +2006-11-15 Werner Koch + + * kbxutil.c (dump_openpgp_key): Cast printf argument. + 2006-10-20 Werner Koch * keybox-search.c (blob_x509_has_grip, has_keygrip): New. diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c index 19d356007..73d10e348 100644 --- a/kbx/kbxutil.c +++ b/kbx/kbxutil.c @@ -367,7 +367,7 @@ dump_openpgp_key (keybox_openpgp_info_t info, const unsigned char *image) u = &info->uids; do { - printf ("uid\t\t%.*s\n", u->len, image + u->off); + printf ("uid\t\t%.*s\n", (int)u->len, image + u->off); u = u->next; } while (u); diff --git a/m4/ChangeLog b/m4/ChangeLog index 4b034d7d9..20bb2c81f 100644 --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,3 +1,8 @@ +2006-11-17 Werner Koch + + * gnupg-pth.m4: Make sure that have_w32_system is set to no by + default. + 2006-11-14 Werner Koch * libassuan.m4: Updated from libassuan SVN. diff --git a/m4/gnupg-pth.m4 b/m4/gnupg-pth.m4 index 00db177e9..4afdcc402 100644 --- a/m4/gnupg-pth.m4 +++ b/m4/gnupg-pth.m4 @@ -91,6 +91,7 @@ AC_DEFUN([GNUPG_PATH_PTH], fi AC_PATH_PROG(PTH_CONFIG, pth-config, no) tmp=ifelse([$1], ,1.3.7,$1) + test -z "$have_w32_system" && have_w32_system="no" if test "$have_w32_system" = no; then if test "$PTH_CONFIG" != "no"; then GNUPG_PTH_VERSION_CHECK($tmp) diff --git a/scd/ChangeLog b/scd/ChangeLog index f637e5ad8..3c1c373a6 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,37 @@ +2006-11-20 Werner Koch + + * app-openpgp.c (verify_chv2): Support for keypads (only CHV2). + + * ccid-driver.c (ccid_transceive_secure): Made it work for Kaan + and SCM. + +2006-11-17 Werner Koch + + * ccid-driver.c (scan_or_find_devices): Use DEBUGOUT_2 instead of + log_debug. Removed few other log_debug. + + * iso7816.c (iso7816_check_keypad): Allow for a SW of 0. + + * command.c (pin_cb): New mode to prompt for a keypad entry. + + * scdaemon.c (main) : Add disable-keypad. + +2006-11-15 Werner Koch + + * app-p15.c (read_ef_odf): Cast one printf arg. + + * scdaemon.h (struct server_control_s): Add field THREAD_STARTUP. + * command.c (scd_command_handler): Add new arg CTRL. + * scdaemon.c (scd_init_default_ctrl): Made static. + (scd_deinit_default_ctrl): New. + (start_connection_thread): Call init/deinit of ctrl. + (handle_connections): Allocate CTRL. + + * apdu.c (PCSC_ERR_MASK): New. + (reset_pcsc_reader, pcsc_get_status, pcsc_send_apdu) + (close_pcsc_reader, open_pcsc_reader): Use it after shifting error + values. Reported by Henrik Nordstrom. Fixes bug #724. + 2006-10-24 Werner Koch * scdaemon.h (GCRY_MD_USER_TLS_MD5SHA1): New. diff --git a/scd/apdu.c b/scd/apdu.c index 242849adb..e83ce3c3e 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -222,6 +222,11 @@ static char (* DLSTDCALL CT_close) (unsigned short ctn); #define PCSC_E_READER_UNAVAILABLE 0x80100017 #define PCSC_W_REMOVED_CARD 0x80100069 +/* The PC/SC error is defined as a long as per specs. Due to left + shifts bit 31 will get sign extended. We use this mask to fix + it. */ +#define PCSC_ERR_MASK(a) ((a) & 0xffffffff) + struct pcsc_io_request_s { @@ -739,7 +744,7 @@ pcsc_error_to_sw (long ec) { int rc; - switch (ec) + switch ( PCSC_ERR_MASK (ec) ) { case 0: rc = 0; break; @@ -834,7 +839,8 @@ reset_pcsc_reader (int slot) sw = SW_HOST_GENERAL_ERROR; goto command_failed; } - err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; + err = PCSC_ERR_MASK ((msgbuf[5] << 24) | (msgbuf[6] << 16) + | (msgbuf[7] << 8 ) | msgbuf[8]); if (err) { log_error ("PC/SC RESET failed: %s (0x%lx)\n", @@ -981,7 +987,8 @@ pcsc_get_status (int slot, unsigned int *status) goto command_failed; } len -= 4; /* Already read the error code. */ - err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; + err = PCSC_ERR_MASK ((msgbuf[5] << 24) | (msgbuf[6] << 16) + | (msgbuf[7] << 8 ) | msgbuf[8]); if (err) { log_error ("pcsc_status failed: %s (0x%lx)\n", @@ -1151,7 +1158,8 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, goto command_failed; } len -= 4; /* Already read the error code. */ - err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; + err = PCSC_ERR_MASK ((msgbuf[5] << 24) | (msgbuf[6] << 16) + | (msgbuf[7] << 8 ) | msgbuf[8]); if (err) { log_error ("pcsc_transmit failed: %s (0x%lx)\n", @@ -1283,7 +1291,8 @@ close_pcsc_reader (int slot) goto command_failed; } len -= 4; /* Already read the error code. */ - err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; + err = PCSC_ERR_MASK ((msgbuf[5] << 24) | (msgbuf[6] << 16) + | (msgbuf[7] << 8 ) | msgbuf[8]); if (err) log_error ("pcsc_close failed: %s (0x%lx)\n", pcsc_error_string (err), err); @@ -1470,7 +1479,8 @@ open_pcsc_reader (const char *portstr) (unsigned long)len); goto command_failed; } - err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; + err = PCSC_ERR_MASK ((msgbuf[5] << 24) | (msgbuf[6] << 16) + | (msgbuf[7] << 8 ) | msgbuf[8]); if (err) { log_error ("PC/SC OPEN failed: %s\n", pcsc_error_string (err)); diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 466f37c57..6c2eb82fb 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1291,27 +1291,52 @@ verify_chv2 (app_t app, { char *pinvalue; iso7816_pininfo_t pininfo; + int did_keypad = 0; memset (&pininfo, 0, sizeof pininfo); pininfo.mode = 1; pininfo.minlen = 6; - rc = pincb (pincb_arg, "PIN", &pinvalue); - if (rc) + if (!opt.disable_keypad + && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) ) { - log_info (_("PIN callback returned error: %s\n"), gpg_strerror (rc)); - return rc; + /* The reader supports the verify command through the keypad. */ + did_keypad = 1; + rc = pincb (pincb_arg, + _("||Please enter your PIN at the reader's keypad"), + NULL); + if (rc) + { + log_info (_("PIN callback returned error: %s\n"), + gpg_strerror (rc)); + return rc; + } + rc = iso7816_verify_kp (app->slot, 0x82, "", 0, &pininfo); + /* Dismiss the prompt. */ + pincb (pincb_arg, NULL, NULL); + } + else + { + /* The reader has no keypad or we don't want to use it. */ + rc = pincb (pincb_arg, "PIN", &pinvalue); + if (rc) + { + log_info (_("PIN callback returned error: %s\n"), + gpg_strerror (rc)); + return rc; + } + + if (strlen (pinvalue) < 6) + { + log_error (_("PIN for CHV%d is too short;" + " minimum length is %d\n"), 2, 6); + xfree (pinvalue); + return gpg_error (GPG_ERR_BAD_PIN); + } + + rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); } - if (strlen (pinvalue) < 6) - { - log_error (_("PIN for CHV%d is too short;" - " minimum length is %d\n"), 2, 6); - xfree (pinvalue); - return gpg_error (GPG_ERR_BAD_PIN); - } - - rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); if (rc) { log_error (_("verify CHV%d failed: %s\n"), 2, gpg_strerror (rc)); @@ -1321,7 +1346,7 @@ verify_chv2 (app_t app, } app->did_chv2 = 1; - if (!app->did_chv1 && !app->force_chv1) + if (!app->did_chv1 && !app->force_chv1 && !did_keypad) { rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue)); if (gpg_err_code (rc) == GPG_ERR_BAD_PIN) diff --git a/scd/app-p15.c b/scd/app-p15.c index f11de5902..475226270 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -692,7 +692,8 @@ read_ef_odf (app_t app, unsigned short odf_fid) } if (buflen) - log_info ("warning: %u bytes of garbage detected at end of ODF\n", buflen); + log_info ("warning: %u bytes of garbage detected at end of ODF\n", + (unsigned int)buflen); xfree (buffer); return 0; diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index e990f757a..35fedfd55 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -200,7 +200,8 @@ enum { VENDOR_CHERRY = 0x046a, VENDOR_SCM = 0x04e6, VENDOR_OMNIKEY= 0x076b, - VENDOR_GEMPC = 0x08e6 + VENDOR_GEMPC = 0x08e6, + VENDOR_KAAN = 0x0d46 }; /* A list and a table with special transport descriptions. */ @@ -990,11 +991,10 @@ scan_or_find_devices (int readerno, const char *readerid, fd = open (transports[i].name, O_RDWR); if (fd == -1) { - log_debug ("failed to open `%s': %s\n", + DEBUGOUT_2 ("failed to open `%s': %s\n", transports[i].name, strerror (errno)); continue; } - log_debug ("opened `%s': fd=%d\n", transports[i].name, fd); rid = malloc (strlen (transports[i].name) + 30 + 10); if (!rid) @@ -1047,7 +1047,6 @@ scan_or_find_devices (int readerno, const char *readerid, } free (rid); close (fd); - log_debug ("closed fd %d\n", fd); } if (scan_mode) @@ -1208,10 +1207,7 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid) if (idev) usb_close (idev); if (dev_fd != -1) - { - close (dev_fd); - log_debug ("closed fd %d\n", dev_fd); - } + close (dev_fd); free (*handle); *handle = NULL; } @@ -1254,7 +1250,6 @@ do_close_reader (ccid_driver_t handle) if (handle->dev_fd != -1) { close (handle->dev_fd); - log_debug ("closed fd %d\n", handle->dev_fd); handle->dev_fd = -1; } } @@ -1324,10 +1319,7 @@ ccid_shutdown_reader (ccid_driver_t handle) usb_close (handle->idev); handle->idev = NULL; if (handle->dev_fd != -1) - { - close (handle->dev_fd); - log_debug ("closed fd %d\n", handle->dev_fd); - } + close (handle->dev_fd); handle->dev_fd = -1; } @@ -2369,10 +2361,24 @@ ccid_transceive_secure (ccid_driver_t handle, || pinlen_min > pinlen_max) return CCID_DRIVER_ERR_INV_VALUE; - /* We have only tested this with an SCM reader so better don't risk - anything and do not allow the use with other readers. */ - if (handle->id_vendor != VENDOR_SCM) - return CCID_DRIVER_ERR_NOT_SUPPORTED; + /* We have only tested a few readers so better don't risk anything + and do not allow the use with other readers. */ + switch (handle->id_vendor) + { + case VENDOR_SCM: /* Tested with SPR 532. */ + case VENDOR_KAAN: /* Tested with KAAN Advanced (1.02). */ + break; + /* The CHERRY XX44 does not yet work. I have not investigated it + closer because there is another problem: It echos a "*" for + each entered character and we somehow need to arrange that it + doesn't get to the tty at all. Given thate are running + without a control terminal there is not much we can do about. + A weird hack using pinentry comes in mind but I doubnt that + this is a clean solution. Need to contact Cherry. + */ + default: + return CCID_DRIVER_ERR_NOT_SUPPORTED; + } if (testmode) return 0; /* Success */ @@ -2390,7 +2396,7 @@ ccid_transceive_secure (ccid_driver_t handle, msg[0] = PC_to_RDR_Secure; msg[5] = 0; /* slot */ msg[6] = seqno = handle->seqno++; - msg[7] = 4; /* bBWI */ + msg[7] = 0; /* bBWI */ msg[8] = 0; /* RFU */ msg[9] = 0; /* RFU */ msg[10] = 0; /* Perform PIN verification. */ @@ -2411,8 +2417,8 @@ ccid_transceive_secure (ccid_driver_t handle, msg[14] = 0x00; /* bmPINLengthFormat: Units are bytes, position is 0. */ } - msg[15] = pinlen_min; /* wPINMaxExtraDigit-Minimum. */ - msg[16] = pinlen_max; /* wPINMaxExtraDigit-Maximum. */ + msg[15] = pinlen_max; /* wPINMaxExtraDigit-Maximum. */ + msg[16] = pinlen_min; /* wPINMaxExtraDigit-Minimum. */ msg[17] = 0x02; /* bEntryValidationCondition: Validation key pressed */ if (pinlen_min && pinlen_max && pinlen_min == pinlen_max) @@ -2424,13 +2430,14 @@ ccid_transceive_secure (ccid_driver_t handle, /* bTeoProlog follows: */ msg[22] = handle->nonnull_nad? ((1 << 4) | 0): 0; msg[23] = ((handle->t1_ns & 1) << 6); /* I-block */ - msg[24] = 4; /* apdulen. */ + msg[24] = 0; /* The apdulen will be filled in by the reader. */ /* APDU follows: */ msg[25] = apdu_buf[0]; /* CLA */ msg[26] = apdu_buf[1]; /* INS */ msg[27] = apdu_buf[2]; /* P1 */ msg[28] = apdu_buf[3]; /* P2 */ msglen = 29; + /* An EDC is not required. */ set_msg_len (msg, msglen - 10); DEBUGOUT ("sending"); @@ -2444,12 +2451,30 @@ ccid_transceive_secure (ccid_driver_t handle, msg = recv_buffer; rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen, - RDR_to_PC_DataBlock, seqno, 5000, 0); + RDR_to_PC_DataBlock, seqno, 30000, 0); if (rc) return rc; tpdu = msg + 10; tpdulen = msglen - 10; + + if (handle->apdu_level) + { + if (resp) + { + if (tpdulen > maxresplen) + { + DEBUGOUT_2 ("provided buffer too short for received data " + "(%u/%u)\n", + (unsigned int)tpdulen, (unsigned int)maxresplen); + return CCID_DRIVER_ERR_INV_VALUE; + } + + memcpy (resp, tpdu, tpdulen); + *nresp = tpdulen; + } + return 0; + } if (tpdulen < 4) { @@ -2595,7 +2620,7 @@ main (int argc, char **argv) { int rc; ccid_driver_t ccid; - unsigned int slotstat; + int slotstat; unsigned char result[512]; size_t resultlen; int no_pinpad = 0; @@ -2623,7 +2648,7 @@ main (int argc, char **argv) } else if ( !strcmp (*argv, "--debug")) { - ccid_set_debug_level (1); + ccid_set_debug_level (ccid_set_debug_level (-1)+1); argc--; argv++; } else if ( !strcmp (*argv, "--no-poll")) diff --git a/scd/command.c b/scd/command.c index 5116461d4..0dbd32df8 100644 --- a/scd/command.c +++ b/scd/command.c @@ -721,6 +721,31 @@ pin_cb (void *opaque, const char *info, char **retstr) unsigned char *value; size_t valuelen; + if (!retstr) + { + /* We prompt for keypad entry. To make sure that the popup has + been show we use an inquire and not just a status message. + We ignore any value returned. */ + if (info) + { + log_debug ("prompting for keypad entry '%s'\n", info); + rc = asprintf (&command, "POPUPKEYPADPROMPT %s", info); + if (rc < 0) + return gpg_error (gpg_err_code_from_errno (errno)); + rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); + free (command); + } + else + { + log_debug ("dismiss keypad entry prompt\n"); + rc = assuan_inquire (ctx, "DISMISSKEYPADPROMPT", + &value, &valuelen, MAXLEN_PIN); + } + if (!rc) + xfree (value); + return rc; + } + *retstr = NULL; log_debug ("asking for PIN '%s'\n", info); @@ -1584,14 +1609,10 @@ register_commands (assuan_context_t ctx) /* Startup the server. If FD is given as -1 this is simple pipe server, otherwise it is a regular server. */ void -scd_command_handler (int fd) +scd_command_handler (ctrl_t ctrl, int fd) { int rc; assuan_context_t ctx; - struct server_control_s ctrl; - - memset (&ctrl, 0, sizeof ctrl); - scd_init_default_ctrl (&ctrl); if (fd == -1) { @@ -1622,20 +1643,20 @@ scd_command_handler (int fd) /* Allocate and initialize the server object. Put it into the list of active sessions. */ - ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local); - ctrl.server_local->next_session = session_list; - session_list = ctrl.server_local; - ctrl.server_local->ctrl_backlink = &ctrl; - ctrl.server_local->assuan_ctx = ctx; + ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local); + ctrl->server_local->next_session = session_list; + session_list = ctrl->server_local; + ctrl->server_local->ctrl_backlink = ctrl; + ctrl->server_local->assuan_ctx = ctx; if (DBG_ASSUAN) assuan_set_log_stream (ctx, log_get_stream ()); /* We open the reader right at startup so that the ticker is able to update the status file. */ - if (ctrl.reader_slot == -1) + if (ctrl->reader_slot == -1) { - ctrl.reader_slot = get_reader_slot (); + ctrl->reader_slot = get_reader_slot (); } /* Command processing loop. */ @@ -1661,23 +1682,24 @@ scd_command_handler (int fd) } /* Cleanup. */ - do_reset (&ctrl, 0); + do_reset (ctrl, 0); /* Release the server object. */ - if (session_list == ctrl.server_local) - session_list = ctrl.server_local->next_session; + if (session_list == ctrl->server_local) + session_list = ctrl->server_local->next_session; else { struct server_local_s *sl; for (sl=session_list; sl->next_session; sl = sl->next_session) - if (sl->next_session == ctrl.server_local) + if (sl->next_session == ctrl->server_local) break; if (!sl->next_session) BUG (); - sl->next_session = ctrl.server_local->next_session; + sl->next_session = ctrl->server_local->next_session; } - xfree (ctrl.server_local); + xfree (ctrl->server_local); + ctrl->server_local = NULL; /* Release the Assuan context. */ assuan_deinit_server (ctx); diff --git a/scd/iso7816.c b/scd/iso7816.c index 250ee40d5..943961da7 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -235,7 +235,7 @@ iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo) sw = apdu_check_keypad (slot, command, pininfo->mode, pininfo->minlen, pininfo->maxlen, pininfo->padlen); - return map_sw (sw); + return iso7816_map_sw (sw); } diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 0ee3f4bc6..6993b75e6 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -600,7 +600,7 @@ main (int argc, char **argv ) printf ("disable-ccid:%lu:\n", GC_OPT_FLAG_NONE ); #endif printf ("allow-admin:%lu:\n", GC_OPT_FLAG_NONE ); - + printf ("disable-keypad:%lu:\n", GC_OPT_FLAG_NONE ); scd_exit (0); } @@ -615,6 +615,7 @@ main (int argc, char **argv ) if (pipe_server) { /* This is the simple pipe based server */ + ctrl_t ctrl; pth_attr_t tattr; int fd = -1; @@ -656,10 +657,19 @@ main (int argc, char **argv ) pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 512*1024); pth_attr_set (tattr, PTH_ATTR_NAME, "pipe-connection"); - if (!pth_spawn (tattr, start_connection_thread, (void*)(-1))) + ctrl = xtrycalloc (1, sizeof *ctrl); + if ( !ctrl ) + { + log_error ("error allocating connection control data: %s\n", + strerror (errno) ); + scd_exit (2); + } + ctrl->thread_startup.fd = -1; + if ( !pth_spawn (tattr, start_connection_thread, ctrl) ) { log_error ("error spawning pipe connection handler: %s\n", strerror (errno) ); + xfree (ctrl); scd_exit (2); } @@ -810,12 +820,18 @@ scd_exit (int rc) } -void +static void scd_init_default_ctrl (ctrl_t ctrl) { ctrl->reader_slot = -1; } +static void +scd_deinit_default_ctrl (ctrl_t ctrl) +{ + +} + /* Return the name of the socket to be used to connect to this process. If no socket is available, return NULL. */ @@ -1007,23 +1023,26 @@ create_server_socket (int is_standard_name, const char *name) static void * start_connection_thread (void *arg) { - int fd = (int)arg; + ctrl_t ctrl = arg; + + scd_init_default_ctrl (ctrl); + if (opt.verbose) + log_info (_("handler for fd %d started\n"), ctrl->thread_startup.fd); + + scd_command_handler (ctrl, ctrl->thread_startup.fd); if (opt.verbose) - log_info (_("handler for fd %d started\n"), fd); - - scd_command_handler (fd); - - if (opt.verbose) - log_info (_("handler for fd %d terminated\n"), fd); + log_info (_("handler for fd %d terminated\n"), ctrl->thread_startup.fd); /* If this thread is the pipe connection thread, flag that a shutdown is required. With the next ticker event and given that no other connections are running the shutdown will then happen. */ - if (fd == -1) + if (ctrl->thread_startup.fd == -1) shutdown_pending = 1; + scd_deinit_default_ctrl (ctrl); + xfree (ctrl); return NULL; } @@ -1137,23 +1156,33 @@ handle_connections (int listen_fd) if (listen_fd != -1 && 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", fd); threadname[sizeof threadname -1] = 0; pth_attr_set (tattr, PTH_ATTR_NAME, threadname); - - if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) + ctrl->thread_startup.fd = fd; + if (!pth_spawn (tattr, start_connection_thread, ctrl)) { log_error ("error spawning connection handler: %s\n", strerror (errno) ); + xfree (ctrl); close (fd); } } diff --git a/scd/scdaemon.h b/scd/scdaemon.h index 2d20b0231..7e5b9fb9b 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -90,6 +90,12 @@ struct app_ctx_s; 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; + /* Local data of the server; used only in command.c. */ struct server_local_s *server_local; @@ -115,11 +121,10 @@ typedef struct app_ctx_s *app_t; /*-- scdaemon.c --*/ void scd_exit (int rc); -void scd_init_default_ctrl (ctrl_t ctrl); const char *scd_get_socket_name (void); /*-- command.c --*/ -void scd_command_handler (int); +void scd_command_handler (ctrl_t, int); void send_status_info (ctrl_t ctrl, const char *keyword, ...) GNUPG_GCC_A_SENTINEL(1); void scd_update_reader_status_file (void); diff --git a/tests/openpgp/ChangeLog b/tests/openpgp/ChangeLog index 0688bf1bf..5518b6cd1 100644 --- a/tests/openpgp/ChangeLog +++ b/tests/openpgp/ChangeLog @@ -1,3 +1,8 @@ +2006-11-16 Werner Koch + + * Makefile.am (plain-large): Use gpg.texi instead of FAQ which + won't be found as it is not a source file. Pointed out by Moritz. + 2006-10-04 Werner Koch * signencrypt.test: Need to prepend srcdir to the file name diff --git a/tests/openpgp/Makefile.am b/tests/openpgp/Makefile.am index dac3df5f7..070a0835a 100644 --- a/tests/openpgp/Makefile.am +++ b/tests/openpgp/Makefile.am @@ -100,7 +100,7 @@ data-80000: plain-large: cat $(srcdir)/../../doc/HACKING \ $(srcdir)/../../doc/DETAILS \ - $(srcdir)/../../doc/FAQ >plain-large + $(srcdir)/../../doc/gpg.texi >plain-large # To speed up key generation we create a dummy random seed file random_seed: diff --git a/tools/ChangeLog b/tools/ChangeLog index 435c39799..34bba91a9 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2006-11-17 Werner Koch + + * gpgconf-comp.c: Made disable-keypad a basic option. + 2006-11-03 Werner Koch * symcryptrun.c: Include signal.h and include pth.h only if test diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 65cdc0a82..d88c96751 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -530,7 +530,7 @@ static gc_option_t gc_options_scdaemon[] = { "disable-ccid", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "do not use the internal CCID driver", GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, - { "disable-keypad", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + { "disable-keypad", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", "do not use a reader's keypad", GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },