summaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2024-06-27 08:29:01 +0200
committerNIIBE Yutaka <gniibe@fsij.org>2024-06-27 08:29:01 +0200
commitb3f1f2cd192b71f2c19ec6f871ece0c175d46db0 (patch)
treeb2267863e4f38e217f51593aa2298369f9139274 /agent
parentagent:daemon: Add an argument to specify requiring socket connection. (diff)
downloadgnupg2-b3f1f2cd192b71f2c19ec6f871ece0c175d46db0.tar.xz
gnupg2-b3f1f2cd192b71f2c19ec6f871ece0c175d46db0.zip
agent: Handle SCD DEVINFO --watch command in a special way.
* agent/call-scd.c (devinfo_watch_thread): New. (agent_card_devinfo): New. (agent_card_scd): Call agent_card_devinfo when it's DEVINFO_WATCH_COMMAND. -- GnuPG-bug-id: 7151 Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Diffstat (limited to 'agent')
-rw-r--r--agent/call-scd.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/agent/call-scd.c b/agent/call-scd.c
index 048c5d306..70bd78e94 100644
--- a/agent/call-scd.c
+++ b/agent/call-scd.c
@@ -1155,6 +1155,97 @@ pass_data_thru (void *opaque, const void *buffer, size_t length)
return 0;
}
+#define DEVINFO_WATCH_COMMAND "DEVINFO --watch"
+
+struct devinfo_watch_thread {
+ ctrl_t ctrl;
+ void *assuan_context;
+};
+
+static void *
+devinfo_watch_thread (void *arg)
+{
+ struct devinfo_watch_thread *d = arg;
+
+ assuan_set_flag (daemon_ctx (d->ctrl), ASSUAN_CONVEY_COMMENTS, 1);
+ assuan_transact (daemon_ctx (d->ctrl), DEVINFO_WATCH_COMMAND,
+ pass_data_thru, d->assuan_context,
+ NULL, NULL,
+ pass_status_thru, d->assuan_context);
+ return NULL;
+}
+
+static int
+agent_card_devinfo (ctrl_t ctrl, void *assuan_context)
+{
+ npth_t thread;
+ struct devinfo_watch_thread dwt;
+ gpg_error_t err = 0;
+ npth_attr_t tattr;
+ assuan_context_t scd_ctx;
+ gnupg_fd_t scd_fds[2];
+ gnupg_fd_t client_input;
+ gnupg_fd_t scd_sock;
+ int rc;
+ gnupg_fd_t client_fds[2];
+
+ rc = daemon_start (DAEMON_SCD, ctrl, 1);
+ if (rc)
+ return rc;
+
+ dwt.ctrl = ctrl;
+ dwt.assuan_context = assuan_context;
+ scd_ctx = daemon_ctx (ctrl);
+
+ err = npth_attr_init (&tattr);
+ if (err)
+ return err;
+
+ npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
+ err = npth_create (&thread, &tattr, devinfo_watch_thread, &dwt);
+ npth_attr_destroy (&tattr);
+ if (err)
+ {
+ log_error ("error spawning devinfo_watch_thread: %s\n", strerror (err));
+ return err;
+ }
+
+ assuan_get_active_fds (assuan_context, 0, client_fds, 2);
+ client_input = client_fds[0];
+
+ assuan_get_active_fds (scd_ctx, 0, scd_fds, 2);
+ scd_sock = scd_fds[0];
+
+ while (1)
+ {
+ fd_set fdset;
+ int nfd;
+ int ret;
+
+ FD_ZERO (&fdset);
+ FD_SET (FD2INT (client_input), &fdset);
+ nfd = FD2NUM (client_input);
+
+ ret = npth_select (nfd+1, &fdset, NULL, NULL, NULL);
+ if (ret == 1)
+ break;
+ }
+
+ /* Forcibly close the socket connection to scdaemon. */
+#ifdef HAVE_W32_SYSTEM
+# if _WIN64
+ shutdown ((uintptr_t)scd_sock, SD_BOTH);
+# else
+ shutdown ((unsigned int)scd_sock, SD_BOTH);
+# endif
+#else
+ shutdown (scd_sock, SHUT_RDWR);
+#endif
+ /* Then, join the thread. */
+ npth_join (thread, NULL);
+
+ return unlock_scd (ctrl, rc);
+}
/* Send the line CMDLINE with command for the SCDdaemon to it and send
all status messages back. This command is used as a general quoting
@@ -1170,6 +1261,11 @@ agent_card_scd (ctrl_t ctrl, const char *cmdline,
struct inq_needpin_parm_s inqparm;
int saveflag;
+ /* This is a layer violation, but it's needed that because DEVINFO
+ --watch is so special. */
+ if (!strcmp (cmdline, DEVINFO_WATCH_COMMAND))
+ return agent_card_devinfo (ctrl, assuan_context);
+
rc = start_scd (ctrl);
if (rc)
return rc;