scd: Support "acknowledge button" feature.
authorNIIBE Yutaka <gniibe@fsij.org>
Thu, 11 Oct 2018 06:41:49 +0000 (15:41 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Thu, 11 Oct 2018 06:41:49 +0000 (15:41 +0900)
* scd/apdu.c (set_prompt_cb): New member function.
(set_prompt_cb_ccid_reader): New function.
(open_ccid_reader): Initialize with set_prompt_cb_ccid_reader.
(apdu_set_prompt_cb): New.
* scd/app.c (lock_app, unlock_app): Add call to apdu_set_prompt_cb.
* ccid-driver.c (ccid_set_prompt_cb): New.
(bulk_in): Call ->prompt_cb when timer extension.
* scd/command.c (popup_prompt): New.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
scd/apdu.c
scd/apdu.h
scd/app.c
scd/ccid-driver.c
scd/ccid-driver.h
scd/command.c
scd/scdaemon.h

index ce7f41f..c0b1bbe 100644 (file)
@@ -105,6 +105,7 @@ struct reader_table_s {
   int (*check_pinpad)(int, int, pininfo_t *);
   void (*dump_status_reader)(int);
   int (*set_progress_cb)(int, gcry_handler_progress_t, void*);
+  int (*set_prompt_cb)(int, void (*) (void *, int), void*);
   int (*pinpad_verify)(int, int, int, int, int, pininfo_t *);
   int (*pinpad_modify)(int, int, int, int, int, pininfo_t *);
 
@@ -444,6 +445,7 @@ new_reader_slot (void)
   reader_table[reader].check_pinpad = check_pcsc_pinpad;
   reader_table[reader].dump_status_reader = NULL;
   reader_table[reader].set_progress_cb = NULL;
+  reader_table[reader].set_prompt_cb = NULL;
   reader_table[reader].pinpad_verify = pcsc_pinpad_verify;
   reader_table[reader].pinpad_modify = pcsc_pinpad_modify;
 
@@ -1404,6 +1406,14 @@ set_progress_cb_ccid_reader (int slot, gcry_handler_progress_t cb, void *cb_arg)
   return ccid_set_progress_cb (slotp->ccid.handle, cb, cb_arg);
 }
 
+static int
+set_prompt_cb_ccid_reader (int slot, void (*cb) (void *, int ), void *cb_arg)
+{
+  reader_table_t slotp = reader_table + slot;
+
+  return ccid_set_prompt_cb (slotp->ccid.handle, cb, cb_arg);
+}
+
 
 static int
 get_status_ccid (int slot, unsigned int *status, int on_wire)
@@ -1543,6 +1553,7 @@ open_ccid_reader (struct dev_list *dl)
   reader_table[slot].check_pinpad = check_ccid_pinpad;
   reader_table[slot].dump_status_reader = dump_ccid_reader_status;
   reader_table[slot].set_progress_cb = set_progress_cb_ccid_reader;
+  reader_table[slot].set_prompt_cb = set_prompt_cb_ccid_reader;
   reader_table[slot].pinpad_verify = ccid_pinpad_operation;
   reader_table[slot].pinpad_modify = ccid_pinpad_operation;
   /* Our CCID reader code does not support T=0 at all, thus reset the
@@ -2382,6 +2393,29 @@ apdu_set_progress_cb (int slot, gcry_handler_progress_t cb, void *cb_arg)
 }
 
 
+int
+apdu_set_prompt_cb (int slot, void (*cb) (void *, int), void *cb_arg)
+{
+  int sw;
+
+  if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
+    return SW_HOST_NO_DRIVER;
+
+  if (reader_table[slot].set_prompt_cb)
+    {
+      sw = lock_slot (slot);
+      if (!sw)
+        {
+          sw = reader_table[slot].set_prompt_cb (slot, cb, cb_arg);
+          unlock_slot (slot);
+        }
+    }
+  else
+    sw = 0;
+  return sw;
+}
+
+
 /* Do a reset for the card in reader at SLOT. */
 int
 apdu_reset (int slot)
index 8a0d4bd..8621ddc 100644 (file)
@@ -117,6 +117,7 @@ int apdu_connect (int slot);
 int apdu_disconnect (int slot);
 
 int apdu_set_progress_cb (int slot, gcry_handler_progress_t cb, void *cb_arg);
+int apdu_set_prompt_cb (int slot, void (*cb) (void *, int), void *cb_arg);
 
 int apdu_reset (int slot);
 int apdu_get_status (int slot, int hang, unsigned int *status);
index f3f1205..a82db26 100644 (file)
--- a/scd/app.c
+++ b/scd/app.c
@@ -67,6 +67,7 @@ lock_app (app_t app, ctrl_t ctrl)
     }
 
   apdu_set_progress_cb (app->slot, print_progress_line, ctrl);
+  apdu_set_prompt_cb (app->slot, popup_prompt, ctrl);
 
   return 0;
 }
@@ -76,6 +77,7 @@ static void
 unlock_app (app_t app)
 {
   apdu_set_progress_cb (app->slot, NULL, NULL);
+  apdu_set_prompt_cb (app->slot, NULL, NULL);
 
   if (npth_mutex_unlock (&app->lock))
     {
index ae40f01..6b0833b 100644 (file)
@@ -255,6 +255,9 @@ struct ccid_driver_s
   void (*progress_cb)(void *, const char *, int, int, int);
   void *progress_cb_arg;
 
+  void (*prompt_cb)(void *, int);
+  void *prompt_cb_arg;
+
   unsigned char intr_buf[64];
   struct libusb_transfer *transfer;
 };
@@ -1802,6 +1805,19 @@ ccid_set_progress_cb (ccid_driver_t handle,
 }
 
 
+int
+ccid_set_prompt_cb (ccid_driver_t handle,
+                   void (*cb)(void *, int), void *cb_arg)
+{
+  if (!handle)
+    return CCID_DRIVER_ERR_INV_VALUE;
+
+  handle->prompt_cb = cb;
+  handle->prompt_cb_arg = cb_arg;
+  return 0;
+}
+
+
 /* Close the reader HANDLE. */
 int
 ccid_close_reader (ccid_driver_t handle)
@@ -1930,6 +1946,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
 {
   int rc;
   int msglen;
+  int notified = 0;
 
   /* Fixme: The next line for the current Valgrind without support
      for USB IOCTLs. */
@@ -1982,14 +1999,25 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
      we got the expected message type.  This is in particular required
      for the Cherry keyboard which sends a time extension request for
      each key hit.  */
-  if ( !(buffer[7] & 0x03) && (buffer[7] & 0xC0) == 0x80)
+  if (!(buffer[7] & 0x03) && (buffer[7] & 0xC0) == 0x80)
     {
       /* Card present and active, time extension requested. */
       DEBUGOUT_2 ("time extension requested (%02X,%02X)\n",
                   buffer[7], buffer[8]);
+
+      /* Gnuk enhancement to prompt user input by ack button */
+      if (buffer[8] == 0xff && !notified)
+        {
+          notified = 1;
+         handle->prompt_cb (handle->prompt_cb_arg, 1);
+        }
+
       goto retry;
     }
 
+  if (notified)
+    handle->prompt_cb (handle->prompt_cb_arg, 0);
+
   if (buffer[0] != expected_type && buffer[0] != RDR_to_PC_SlotStatus)
     {
       DEBUGOUT_1 ("unexpected bulk-in msg type (%02x)\n", buffer[0]);
index c31c25f..1550b3e 100644 (file)
@@ -126,6 +126,8 @@ int ccid_open_reader (const char *spec_reader_name,
 int ccid_set_progress_cb (ccid_driver_t handle,
                           void (*cb)(void *, const char *, int, int, int),
                           void *cb_arg);
+int ccid_set_prompt_cb (ccid_driver_t handle, void (*cb)(void *, int),
+                        void *cb_arg);
 int ccid_shutdown_reader (ccid_driver_t handle);
 int ccid_close_reader (ccid_driver_t handle);
 int ccid_get_atr (ccid_driver_t handle,
index 66d9fb9..0a96546 100644 (file)
@@ -1898,6 +1898,34 @@ send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
 }
 
 
+void
+popup_prompt (void *opaque, int on)
+{
+  ctrl_t ctrl = opaque;
+
+  if (ctrl)
+    {
+      assuan_context_t ctx = ctrl->server_local->assuan_ctx;
+
+      if (ctx)
+        {
+          const char *cmd;
+          gpg_error_t err;
+          unsigned char *value;
+          size_t valuelen;
+
+          if (on)
+            cmd = "POPUPPINPADPROMPT --ack";
+          else
+            cmd = "DISMISSPINPADPROMPT";
+          err = assuan_inquire (ctx, cmd, &value, &valuelen, 100);
+          if (!err)
+            xfree (value);
+        }
+    }
+}
+
+
 /* Helper to send the clients a status change notification.  */
 void
 send_client_notifications (app_t app, int removal)
index 4797f3d..238e6a8 100644 (file)
@@ -123,6 +123,7 @@ int  scd_command_handler (ctrl_t, int);
 void send_status_info (ctrl_t ctrl, const char *keyword, ...)
      GPGRT_ATTR_SENTINEL(1);
 void send_status_direct (ctrl_t ctrl, const char *keyword, const char *args);
+void popup_prompt (void *opaque, int on);
 void send_client_notifications (app_t app, int removal);
 void scd_kick_the_loop (void);
 int get_active_connection_count (void);