1 /* command.c - SCdaemon command handler
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005,
3 * 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <https://www.gnu.org/licenses/>.
36 #include "app-common.h"
38 #include "apdu.h" /* Required for apdu_*_reader (). */
41 #include "ccid-driver.h"
43 #include "../common/asshelp.h"
44 #include "../common/server-help.h"
46 /* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */
47 #define MAXLEN_PIN 100
49 /* Maximum allowed size of key data as used in inquiries. */
50 #define MAXLEN_KEYDATA 4096
52 /* Maximum allowed total data size for SETDATA. */
53 #define MAXLEN_SETDATA 4096
55 /* Maximum allowed size of certificate data as used in inquiries. */
56 #define MAXLEN_CERTDATA 16384
59 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
61 #define IS_LOCKED(c) (locked_session && locked_session != (c)->server_local)
64 /* Data used to associate an Assuan context with local server data.
65 This object describes the local properties of one session. */
68 /* We keep a list of all active sessions with the anchor at
69 SESSION_LIST (see below). This field is used for linking. */
70 struct server_local_s *next_session;
72 /* This object is usually assigned to a CTRL object (which is
73 globally visible). While enumerating all sessions we sometimes
74 need to access data of the CTRL object; thus we keep a
78 /* The Assuan context used by this session/server. */
79 assuan_context_t assuan_ctx;
81 #ifdef HAVE_W32_SYSTEM
82 void *event_signal; /* Or NULL if not used. */
84 int event_signal; /* Or 0 if not used. */
87 /* True if the card has been removed and a reset is required to
88 continue operation. */
91 /* If set to true we will be terminate ourself at the end of the
98 /* To keep track of all running sessions, we link all active server
99 contexts and the anchor in this variable. */
100 static struct server_local_s *session_list;
102 /* If a session has been locked we store a link to its server object
104 static struct server_local_s *locked_session;
107 /* Convert the STRING into a newly allocated buffer while translating
108 the hex numbers. Stops at the first invalid character. Blanks and
109 colons are allowed to separate the hex digits. Returns NULL on
110 error or a newly malloced buffer and its length in LENGTH. */
111 static unsigned char *
112 hex_to_buffer (const char *string, size_t *r_length)
114 unsigned char *buffer;
118 buffer = xtrymalloc (strlen (string)+1);
121 for (s=string, n=0; *s; s++)
123 if (spacep (s) || *s == ':')
125 if (hexdigitp (s) && hexdigitp (s+1))
127 buffer[n++] = xtoi_2 (s);
139 /* Reset the card and free the application context. With SEND_RESET
140 set to true actually send a RESET to the reader; this is the normal
141 way of calling the function. If KEEP_LOCK is set and the session
142 is locked that lock wil not be released. */
144 do_reset (ctrl_t ctrl, int send_reset, int keep_lock)
146 app_t app = ctrl->app_ctx;
149 app_reset (app, ctrl, IS_LOCKED (ctrl)? 0: send_reset);
151 /* If we hold a lock, unlock now. */
152 if (!keep_lock && locked_session && ctrl->server_local == locked_session)
154 locked_session = NULL;
155 log_info ("implicitly unlocking due to RESET\n");
160 reset_notify (assuan_context_t ctx, char *line)
162 ctrl_t ctrl = assuan_get_pointer (ctx);
164 do_reset (ctrl, 1, has_option (line, "--keep-lock"));
170 option_handler (assuan_context_t ctx, const char *key, const char *value)
172 ctrl_t ctrl = assuan_get_pointer (ctx);
174 if (!strcmp (key, "event-signal"))
176 /* A value of 0 is allowed to reset the event signal. */
177 #ifdef HAVE_W32_SYSTEM
179 return gpg_error (GPG_ERR_ASS_PARAMETER);
181 ctrl->server_local->event_signal = (void *)strtoull (value, NULL, 16);
183 ctrl->server_local->event_signal = (void *)strtoul (value, NULL, 16);
186 int i = *value? atoi (value) : -1;
188 return gpg_error (GPG_ERR_ASS_PARAMETER);
189 ctrl->server_local->event_signal = i;
197 /* If the card has not yet been opened, do it. */
199 open_card (ctrl_t ctrl)
201 /* If we ever got a card not present error code, return that. Only
202 the SERIALNO command and a reset are able to clear from that
204 if (ctrl->server_local->card_removed)
205 return gpg_error (GPG_ERR_CARD_REMOVED);
207 if ( IS_LOCKED (ctrl) )
208 return gpg_error (GPG_ERR_LOCKED);
213 return select_application (ctrl, NULL, &ctrl->app_ctx, 0, NULL, 0);
216 /* Explicitly open a card for a specific use of APPTYPE or SERIALNO. */
218 open_card_with_request (ctrl_t ctrl, const char *apptype, const char *serialno)
221 unsigned char *serialno_bin = NULL;
222 size_t serialno_bin_len = 0;
223 app_t app = ctrl->app_ctx;
225 /* If we are already initialized for one specific application we
226 need to check that the client didn't requested a specific
227 application different from the one in use before we continue. */
228 if (apptype && ctrl->app_ctx)
229 return check_application_conflict (apptype, ctrl->app_ctx);
231 /* Re-scan USB devices. Release APP, before the scan. */
232 ctrl->app_ctx = NULL;
233 release_application (app, 0);
236 serialno_bin = hex_to_buffer (serialno, &serialno_bin_len);
238 err = select_application (ctrl, apptype, &ctrl->app_ctx, 1,
239 serialno_bin, serialno_bin_len);
240 xfree (serialno_bin);
246 static const char hlp_serialno[] =
247 "SERIALNO [--demand=<serialno>] [<apptype>]\n"
249 "Return the serial number of the card using a status response. This\n"
250 "function should be used to check for the presence of a card.\n"
252 "If --demand is given, an application on the card with SERIALNO is\n"
253 "selected and an error is returned if no such card available.\n"
255 "If APPTYPE is given, an application of that type is selected and an\n"
256 "error is returned if the application is not supported or available.\n"
257 "The default is to auto-select the application using a hardwired\n"
258 "preference system. Note, that a future extension to this function\n"
259 "may enable specifying a list and order of applications to try.\n"
261 "This function is special in that it can be used to reset the card.\n"
262 "Most other functions will return an error when a card change has\n"
263 "been detected and the use of this function is therefore required.\n"
265 "Background: We want to keep the client clear of handling card\n"
266 "changes between operations; i.e. the client can assume that all\n"
267 "operations are done on the same card unless he calls this function.";
269 cmd_serialno (assuan_context_t ctx, char *line)
271 ctrl_t ctrl = assuan_get_pointer (ctx);
272 struct server_local_s *sl;
277 if ( IS_LOCKED (ctrl) )
278 return gpg_error (GPG_ERR_LOCKED);
280 if ((demand = has_option_name (line, "--demand")))
283 return set_error (GPG_ERR_ASS_PARAMETER, "missing value for option");
284 line = (char *)++demand;
285 for (; *line && !spacep (line); line++)
293 line = skip_options (line);
295 /* Clear the remove flag so that the open_card is able to reread it. */
296 if (ctrl->server_local->card_removed)
297 ctrl->server_local->card_removed = 0;
299 if ((rc = open_card_with_request (ctrl, *line? line:NULL, demand)))
301 ctrl->server_local->card_removed = 1;
305 /* Success, clear the card_removed flag for all sessions. */
306 for (sl=session_list; sl; sl = sl->next_session)
308 ctrl_t c = sl->ctrl_backlink;
311 c->server_local->card_removed = 0;
314 serial = app_get_serialno (ctrl->app_ctx);
316 return gpg_error (GPG_ERR_INV_VALUE);
318 rc = assuan_write_status (ctx, "SERIALNO", serial);
324 static const char hlp_learn[] =
325 "LEARN [--force] [--keypairinfo]\n"
327 "Learn all useful information of the currently inserted card. When\n"
328 "used without the force options, the command might do an INQUIRE\n"
331 " INQUIRE KNOWNCARDP <hexstring_with_serialNumber>\n"
333 "The client should just send an \"END\" if the processing should go on\n"
334 "or a \"CANCEL\" to force the function to terminate with a Cancel\n"
337 "With the option --keypairinfo only KEYPARIINFO status lines are\n"
340 "The response of this command is a list of status lines formatted as\n"
343 " S APPTYPE <apptype>\n"
345 "This returns the type of the application, currently the strings:\n"
347 " P15 = PKCS-15 structure used\n"
348 " DINSIG = DIN SIG\n"
349 " OPENPGP = OpenPGP card\n"
351 " NKS = NetKey card\n"
353 "are implemented. These strings are aliases for the AID\n"
355 " S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id>\n"
357 "If there is no certificate yet stored on the card a single 'X' is\n"
358 "returned as the keygrip. In addition to the keypair info, information\n"
359 "about all certificates stored on the card is also returned:\n"
361 " S CERTINFO <certtype> <hexstring_with_id>\n"
363 "Where CERTTYPE is a number indicating the type of certificate:\n"
365 " 100 := Regular X.509 cert\n"
366 " 101 := Trusted X.509 cert\n"
367 " 102 := Useful X.509 cert\n"
368 " 110 := Root CA cert in a special format (e.g. DINSIG)\n"
369 " 111 := Root CA cert as standard X509 cert.\n"
371 "For certain cards, more information will be returned:\n"
373 " S KEY-FPR <no> <hexstring>\n"
375 "For OpenPGP cards this returns the stored fingerprints of the\n"
376 "keys. This can be used check whether a key is available on the\n"
377 "card. NO may be 1, 2 or 3.\n"
379 " S CA-FPR <no> <hexstring>\n"
381 "Similar to above, these are the fingerprints of keys assumed to be\n"
382 "ultimately trusted.\n"
384 " S DISP-NAME <name_of_card_holder>\n"
386 "The name of the card holder as stored on the card; percent\n"
387 "escaping takes place, spaces are encoded as '+'\n"
389 " S PUBKEY-URL <url>\n"
391 "The URL to be used for locating the entire public key.\n"
393 "Note, that this function may even be used on a locked card.";
395 cmd_learn (assuan_context_t ctx, char *line)
397 ctrl_t ctrl = assuan_get_pointer (ctx);
399 int only_keypairinfo = has_option (line, "--keypairinfo");
401 if ((rc = open_card (ctrl)))
404 /* Unless the force option is used we try a shortcut by identifying
405 the card using a serial number and inquiring the client with
406 that. The client may choose to cancel the operation if he already
407 knows about this card */
408 if (!only_keypairinfo)
412 app_t app = ctrl->app_ctx;
415 return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
417 reader = apdu_get_reader_name (app->slot);
419 return out_of_core ();
420 send_status_direct (ctrl, "READER", reader);
421 /* No need to free the string of READER. */
423 serial = app_get_serialno (ctrl->app_ctx);
425 return gpg_error (GPG_ERR_INV_VALUE);
427 rc = assuan_write_status (ctx, "SERIALNO", serial);
431 return out_of_core ();
434 if (!has_option (line, "--force"))
438 rc = gpgrt_asprintf (&command, "KNOWNCARDP %s", serial);
442 return out_of_core ();
444 rc = assuan_inquire (ctx, command, NULL, NULL, 0);
448 if (gpg_err_code (rc) != GPG_ERR_ASS_CANCELED)
449 log_error ("inquire KNOWNCARDP failed: %s\n",
454 /* Not canceled, so we have to proceed. */
459 /* Let the application print out its collection of useful status
462 rc = app_write_learn_status (ctrl->app_ctx, ctrl, only_keypairinfo);
469 static const char hlp_readcert[] =
470 "READCERT <hexified_certid>|<keyid>\n"
472 "Note, that this function may even be used on a locked card.";
474 cmd_readcert (assuan_context_t ctx, char *line)
476 ctrl_t ctrl = assuan_get_pointer (ctx);
481 if ((rc = open_card (ctrl)))
484 line = xstrdup (line); /* Need a copy of the line. */
485 rc = app_readcert (ctrl->app_ctx, ctrl, line, &cert, &ncert);
487 log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
492 rc = assuan_send_data (ctx, cert, ncert);
502 static const char hlp_readkey[] =
503 "READKEY [--advanced] <keyid>\n"
505 "Return the public key for the given cert or key ID as a standard\n"
507 "In --advanced mode it returns the S-expression in advanced format.\n"
509 "Note that this function may even be used on a locked card.";
511 cmd_readkey (assuan_context_t ctx, char *line)
513 ctrl_t ctrl = assuan_get_pointer (ctx);
516 unsigned char *cert = NULL;
518 ksba_cert_t kc = NULL;
523 if ((rc = open_card (ctrl)))
526 if (has_option (line, "--advanced"))
529 line = skip_options (line);
531 line = xstrdup (line); /* Need a copy of the line. */
532 /* If the application supports the READKEY function we use that.
533 Otherwise we use the old way by extracting it from the
535 rc = app_readkey (ctrl->app_ctx, ctrl, advanced, line, &pk, &pklen);
537 { /* Yeah, got that key - send it back. */
538 rc = assuan_send_data (ctx, pk, pklen);
545 if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION)
546 log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
549 rc = app_readcert (ctrl->app_ctx, ctrl, line, &cert, &ncert);
551 log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
558 rc = ksba_cert_new (&kc);
562 rc = ksba_cert_init_from_mem (kc, cert, ncert);
565 log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
569 p = ksba_cert_get_public_key (kc);
572 rc = gpg_error (GPG_ERR_NO_PUBKEY);
576 n = gcry_sexp_canon_len (p, 0, NULL, NULL);
577 rc = assuan_send_data (ctx, p, n);
582 ksba_cert_release (kc);
589 static const char hlp_setdata[] =
590 "SETDATA [--append] <hexstring>\n"
592 "The client should use this command to tell us the data he want to sign.\n"
593 "With the option --append, the data is appended to the data set by a\n"
594 "previous SETDATA command.";
596 cmd_setdata (assuan_context_t ctx, char *line)
598 ctrl_t ctrl = assuan_get_pointer (ctx);
604 append = (ctrl->in_data.value && has_option (line, "--append"));
606 line = skip_options (line);
608 if (locked_session && locked_session != ctrl->server_local)
609 return gpg_error (GPG_ERR_LOCKED);
611 /* Parse the hexstring. */
612 for (p=line,n=0; hexdigitp (p); p++, n++)
615 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
617 return set_error (GPG_ERR_ASS_PARAMETER, "no data given");
619 return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
623 if (ctrl->in_data.valuelen + n > MAXLEN_SETDATA)
624 return set_error (GPG_ERR_TOO_LARGE,
625 "limit on total size of data reached");
626 buf = xtrymalloc (ctrl->in_data.valuelen + n);
629 buf = xtrymalloc (n);
631 return out_of_core ();
635 memcpy (buf, ctrl->in_data.value, ctrl->in_data.valuelen);
636 off = ctrl->in_data.valuelen;
640 for (p=line, i=0; i < n; p += 2, i++)
641 buf[off+i] = xtoi_2 (p);
643 xfree (ctrl->in_data.value);
644 ctrl->in_data.value = buf;
645 ctrl->in_data.valuelen = off+n;
652 pin_cb (void *opaque, const char *info, char **retstr)
654 assuan_context_t ctx = opaque;
657 unsigned char *value;
662 /* We prompt for pinpad entry. To make sure that the popup has
663 been show we use an inquire and not just a status message.
664 We ignore any value returned. */
667 log_debug ("prompting for pinpad entry '%s'\n", info);
668 rc = gpgrt_asprintf (&command, "POPUPPINPADPROMPT %s", info);
670 return gpg_error (gpg_err_code_from_errno (errno));
671 rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
676 log_debug ("dismiss pinpad entry prompt\n");
677 rc = assuan_inquire (ctx, "DISMISSPINPADPROMPT",
678 &value, &valuelen, MAXLEN_PIN);
686 log_debug ("asking for PIN '%s'\n", info);
688 rc = gpgrt_asprintf (&command, "NEEDPIN %s", info);
690 return gpg_error (gpg_err_code_from_errno (errno));
692 /* Fixme: Write an inquire function which returns the result in
693 secure memory and check all further handling of the PIN. */
694 rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
699 if (!valuelen || value[valuelen-1])
701 /* We require that the returned value is an UTF-8 string */
703 return gpg_error (GPG_ERR_INV_RESPONSE);
705 *retstr = (char*)value;
710 static const char hlp_pksign[] =
711 "PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5]] <hexified_id>\n"
713 "The --hash option is optional; the default is SHA1.";
715 cmd_pksign (assuan_context_t ctx, char *line)
717 ctrl_t ctrl = assuan_get_pointer (ctx);
719 unsigned char *outdata;
724 if (has_option (line, "--hash=rmd160"))
725 hash_algo = GCRY_MD_RMD160;
726 else if (has_option (line, "--hash=sha1"))
727 hash_algo = GCRY_MD_SHA1;
728 else if (has_option (line, "--hash=sha224"))
729 hash_algo = GCRY_MD_SHA224;
730 else if (has_option (line, "--hash=sha256"))
731 hash_algo = GCRY_MD_SHA256;
732 else if (has_option (line, "--hash=sha384"))
733 hash_algo = GCRY_MD_SHA384;
734 else if (has_option (line, "--hash=sha512"))
735 hash_algo = GCRY_MD_SHA512;
736 else if (has_option (line, "--hash=md5"))
737 hash_algo = GCRY_MD_MD5;
738 else if (!strstr (line, "--"))
739 hash_algo = GCRY_MD_SHA1;
741 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
743 line = skip_options (line);
745 if ((rc = open_card (ctrl)))
748 /* We have to use a copy of the key ID because the function may use
749 the pin_cb which in turn uses the assuan line buffer and thus
750 overwriting the original line with the keyid */
751 keyidstr = xtrystrdup (line);
753 return out_of_core ();
755 rc = app_sign (ctrl->app_ctx, ctrl,
758 ctrl->in_data.value, ctrl->in_data.valuelen,
759 &outdata, &outdatalen);
764 log_error ("app_sign failed: %s\n", gpg_strerror (rc));
768 rc = assuan_send_data (ctx, outdata, outdatalen);
771 return rc; /* that is already an assuan error code */
778 static const char hlp_pkauth[] =
779 "PKAUTH <hexified_id>";
781 cmd_pkauth (assuan_context_t ctx, char *line)
783 ctrl_t ctrl = assuan_get_pointer (ctx);
785 unsigned char *outdata;
789 if ((rc = open_card (ctrl)))
793 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
795 /* We have to use a copy of the key ID because the function may use
796 the pin_cb which in turn uses the assuan line buffer and thus
797 overwriting the original line with the keyid */
798 keyidstr = xtrystrdup (line);
800 return out_of_core ();
802 rc = app_auth (ctrl->app_ctx, ctrl, keyidstr, pin_cb, ctx,
803 ctrl->in_data.value, ctrl->in_data.valuelen,
804 &outdata, &outdatalen);
808 log_error ("app_auth failed: %s\n", gpg_strerror (rc));
812 rc = assuan_send_data (ctx, outdata, outdatalen);
815 return rc; /* that is already an assuan error code */
822 static const char hlp_pkdecrypt[] =
823 "PKDECRYPT <hexified_id>";
825 cmd_pkdecrypt (assuan_context_t ctx, char *line)
827 ctrl_t ctrl = assuan_get_pointer (ctx);
829 unsigned char *outdata;
832 unsigned int infoflags;
834 if ((rc = open_card (ctrl)))
837 keyidstr = xtrystrdup (line);
839 return out_of_core ();
840 rc = app_decipher (ctrl->app_ctx, ctrl, keyidstr, pin_cb, ctx,
841 ctrl->in_data.value, ctrl->in_data.valuelen,
842 &outdata, &outdatalen, &infoflags);
847 log_error ("app_decipher failed: %s\n", gpg_strerror (rc));
851 /* If the card driver told us that there is no padding, send a
852 status line. If there is a padding it is assumed that the
853 caller knows what padding is used. It would have been better
854 to always send that information but for backward
855 compatibility we can't do that. */
856 if ((infoflags & APP_DECIPHER_INFO_NOPAD))
857 send_status_direct (ctrl, "PADDING", "0");
858 rc = assuan_send_data (ctx, outdata, outdatalen);
861 return rc; /* that is already an assuan error code */
868 static const char hlp_getattr[] =
871 "This command is used to retrieve data from a smartcard. The\n"
872 "allowed names depend on the currently selected smartcard\n"
873 "application. NAME must be percent and '+' escaped. The value is\n"
874 "returned through status message, see the LEARN command for details.\n"
876 "However, the current implementation assumes that Name is not escaped;\n"
877 "this works as long as no one uses arbitrary escaping. \n"
879 "Note, that this function may even be used on a locked card.";
881 cmd_getattr (assuan_context_t ctx, char *line)
883 ctrl_t ctrl = assuan_get_pointer (ctx);
887 if ((rc = open_card (ctrl)))
891 for (; *line && !spacep (line); line++)
896 /* (We ignore any garbage for now.) */
898 /* FIXME: Applications should not return sensitive data if the card
900 rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
906 static const char hlp_setattr[] =
907 "SETATTR <name> <value> \n"
909 "This command is used to store data on a smartcard. The allowed\n"
910 "names and values are depend on the currently selected smartcard\n"
911 "application. NAME and VALUE must be percent and '+' escaped.\n"
913 "However, the current implementation assumes that NAME is not\n"
914 "escaped; this works as long as no one uses arbitrary escaping.\n"
916 "A PIN will be requested for most NAMEs. See the corresponding\n"
917 "setattr function of the actually used application (app-*.c) for\n"
920 cmd_setattr (assuan_context_t ctx, char *orig_line)
922 ctrl_t ctrl = assuan_get_pointer (ctx);
927 char *line, *linebuf;
929 if ((rc = open_card (ctrl)))
932 /* We need to use a copy of LINE, because PIN_CB uses the same
933 context and thus reuses the Assuan provided LINE. */
934 line = linebuf = xtrystrdup (orig_line);
936 return out_of_core ();
939 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
943 while (spacep (line))
945 nbytes = percent_plus_unescape_inplace (line, 0);
947 rc = app_setattr (ctrl->app_ctx, ctrl, keyword, pin_cb, ctx,
948 (const unsigned char*)line, nbytes);
955 static const char hlp_writecert[] =
956 "WRITECERT <hexified_certid>\n"
958 "This command is used to store a certifciate on a smartcard. The\n"
959 "allowed certids depend on the currently selected smartcard\n"
960 "application. The actual certifciate is requested using the inquiry\n"
961 "\"CERTDATA\" and needs to be provided in its raw (e.g. DER) form.\n"
963 "In almost all cases a PIN will be requested. See the related\n"
964 "writecert function of the actually used application (app-*.c) for\n"
967 cmd_writecert (assuan_context_t ctx, char *line)
969 ctrl_t ctrl = assuan_get_pointer (ctx);
972 unsigned char *certdata;
975 line = skip_options (line);
978 return set_error (GPG_ERR_ASS_PARAMETER, "no certid given");
980 while (*line && !spacep (line))
984 if ((rc = open_card (ctrl)))
988 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
990 certid = xtrystrdup (certid);
992 return out_of_core ();
994 /* Now get the actual keydata. */
995 rc = assuan_inquire (ctx, "CERTDATA",
996 &certdata, &certdatalen, MAXLEN_CERTDATA);
1003 /* Write the certificate to the card. */
1004 rc = app_writecert (ctrl->app_ctx, ctrl, certid,
1005 pin_cb, ctx, certdata, certdatalen);
1013 static const char hlp_writekey[] =
1014 "WRITEKEY [--force] <keyid> \n"
1016 "This command is used to store a secret key on a smartcard. The\n"
1017 "allowed keyids depend on the currently selected smartcard\n"
1018 "application. The actual keydata is requested using the inquiry\n"
1019 "\"KEYDATA\" and need to be provided without any protection. With\n"
1020 "--force set an existing key under this KEYID will get overwritten.\n"
1021 "The keydata is expected to be the usual canonical encoded\n"
1024 "A PIN will be requested for most NAMEs. See the corresponding\n"
1025 "writekey function of the actually used application (app-*.c) for\n"
1028 cmd_writekey (assuan_context_t ctx, char *line)
1030 ctrl_t ctrl = assuan_get_pointer (ctx);
1033 int force = has_option (line, "--force");
1034 unsigned char *keydata;
1037 line = skip_options (line);
1040 return set_error (GPG_ERR_ASS_PARAMETER, "no keyid given");
1042 while (*line && !spacep (line))
1046 if ((rc = open_card (ctrl)))
1050 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1052 keyid = xtrystrdup (keyid);
1054 return out_of_core ();
1056 /* Now get the actual keydata. */
1057 assuan_begin_confidential (ctx);
1058 rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA);
1059 assuan_end_confidential (ctx);
1066 /* Write the key to the card. */
1067 rc = app_writekey (ctrl->app_ctx, ctrl, keyid, force? 1:0,
1068 pin_cb, ctx, keydata, keydatalen);
1076 static const char hlp_genkey[] =
1077 "GENKEY [--force] [--timestamp=<isodate>] <no>\n"
1079 "Generate a key on-card identified by NO, which is application\n"
1080 "specific. Return values are application specific. For OpenPGP\n"
1081 "cards 3 status lines are returned:\n"
1083 " S KEY-FPR <hexstring>\n"
1084 " S KEY-CREATED-AT <seconds_since_epoch>\n"
1085 " S KEY-DATA [-|p|n] <hexdata>\n"
1087 " 'p' and 'n' are the names of the RSA parameters; '-' is used to\n"
1088 " indicate that HEXDATA is the first chunk of a parameter given\n"
1089 " by the next KEY-DATA.\n"
1091 "--force is required to overwrite an already existing key. The\n"
1092 "KEY-CREATED-AT is required for further processing because it is\n"
1093 "part of the hashed key material for the fingerprint.\n"
1095 "If --timestamp is given an OpenPGP key will be created using this\n"
1096 "value. The value needs to be in ISO Format; e.g.\n"
1097 "\"--timestamp=20030316T120000\" and after 1970-01-01 00:00:00.\n"
1099 "The public part of the key can also later be retrieved using the\n"
1102 cmd_genkey (assuan_context_t ctx, char *line)
1104 ctrl_t ctrl = assuan_get_pointer (ctx);
1111 force = has_option (line, "--force");
1113 if ((s=has_option_name (line, "--timestamp")))
1116 return set_error (GPG_ERR_ASS_PARAMETER, "missing value for option");
1117 timestamp = isotime2epoch (s+1);
1119 return set_error (GPG_ERR_ASS_PARAMETER, "invalid time value");
1125 line = skip_options (line);
1127 return set_error (GPG_ERR_ASS_PARAMETER, "no key number given");
1129 while (*line && !spacep (line))
1133 if ((rc = open_card (ctrl)))
1137 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1139 keyno = xtrystrdup (keyno);
1141 return out_of_core ();
1142 rc = app_genkey (ctrl->app_ctx, ctrl, keyno, NULL,
1143 force? APP_GENKEY_FLAG_FORCE : 0,
1144 timestamp, pin_cb, ctx);
1151 static const char hlp_random[] =
1154 "Get NBYTES of random from the card and send them back as data.\n"
1155 "This usually involves EEPROM write on the card and thus excessive\n"
1156 "use of this command may destroy the card.\n"
1158 "Note, that this function may be even be used on a locked card.";
1160 cmd_random (assuan_context_t ctx, char *line)
1162 ctrl_t ctrl = assuan_get_pointer (ctx);
1165 unsigned char *buffer;
1168 return set_error (GPG_ERR_ASS_PARAMETER,
1169 "number of requested bytes missing");
1170 nbytes = strtoul (line, NULL, 0);
1172 if ((rc = open_card (ctrl)))
1176 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1178 buffer = xtrymalloc (nbytes);
1180 return out_of_core ();
1182 rc = app_get_challenge (ctrl->app_ctx, ctrl, nbytes, buffer);
1185 rc = assuan_send_data (ctx, buffer, nbytes);
1187 return rc; /* that is already an assuan error code */
1196 static const char hlp_passwd[] =
1197 "PASSWD [--reset] [--nullpin] [--clear] <chvno>\n"
1199 "Change the PIN or, if --reset is given, reset the retry counter of\n"
1200 "the card holder verification vector CHVNO. The option --nullpin is\n"
1201 "used for TCOS cards to set the initial PIN. The option --clear clears\n"
1202 "the security status associated with the PIN so that the PIN needs to\n"
1203 "be presented again. The format of CHVNO depends on the card application.";
1205 cmd_passwd (assuan_context_t ctx, char *line)
1207 ctrl_t ctrl = assuan_get_pointer (ctx);
1210 unsigned int flags = 0;
1212 if (has_option (line, "--reset"))
1213 flags |= APP_CHANGE_FLAG_RESET;
1214 if (has_option (line, "--nullpin"))
1215 flags |= APP_CHANGE_FLAG_NULLPIN;
1216 if (has_option (line, "--clear"))
1217 flags |= APP_CHANGE_FLAG_CLEAR;
1219 line = skip_options (line);
1222 return set_error (GPG_ERR_ASS_PARAMETER, "no CHV number given");
1224 while (*line && !spacep (line))
1228 /* Do not allow other flags aside of --clear. */
1229 if ((flags & APP_CHANGE_FLAG_CLEAR) && (flags & ~APP_CHANGE_FLAG_CLEAR))
1230 return set_error (GPG_ERR_UNSUPPORTED_OPERATION,
1231 "--clear used with other options");
1233 if ((rc = open_card (ctrl)))
1237 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1239 chvnostr = xtrystrdup (chvnostr);
1241 return out_of_core ();
1242 rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, flags, pin_cb, ctx);
1244 log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1251 static const char hlp_checkpin[] =
1252 "CHECKPIN <idstr>\n"
1254 "Perform a VERIFY operation without doing anything else. This may\n"
1255 "be used to initialize a the PIN cache earlier to long lasting\n"
1256 "operations. Its use is highly application dependent.\n"
1260 " Perform a simple verify operation for CHV1 and CHV2, so that\n"
1261 " further operations won't ask for CHV2 and it is possible to do a\n"
1262 " cheap check on the PIN: If there is something wrong with the PIN\n"
1263 " entry system, only the regular CHV will get blocked and not the\n"
1264 " dangerous CHV3. IDSTR is the usual card's serial number in hex\n"
1265 " notation; an optional fingerprint part will get ignored. There\n"
1266 " is however a special mode if the IDSTR is suffixed with the\n"
1267 " literal string \"[CHV3]\": In this case the Admin PIN is checked\n"
1268 " if and only if the retry counter is still at 3.\n"
1272 " Any of the valid PIN Ids may be used. These are the strings:\n"
1274 " PW1.CH - Global password 1\n"
1275 " PW2.CH - Global password 2\n"
1276 " PW1.CH.SIG - SigG password 1\n"
1277 " PW2.CH.SIG - SigG password 2\n"
1279 " For a definitive list, see the implementation in app-nks.c.\n"
1280 " Note that we call a PW2.* PIN a \"PUK\" despite that since TCOS\n"
1281 " 3.0 they are technically alternative PINs used to mutally\n"
1282 " unblock each other.";
1284 cmd_checkpin (assuan_context_t ctx, char *line)
1286 ctrl_t ctrl = assuan_get_pointer (ctx);
1290 if ((rc = open_card (ctrl)))
1294 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1296 /* We have to use a copy of the key ID because the function may use
1297 the pin_cb which in turn uses the assuan line buffer and thus
1298 overwriting the original line with the keyid. */
1299 idstr = xtrystrdup (line);
1301 return out_of_core ();
1303 rc = app_check_pin (ctrl->app_ctx, ctrl, idstr, pin_cb, ctx);
1306 log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
1312 static const char hlp_lock[] =
1315 "Grant exclusive card access to this session. Note that there is\n"
1316 "no lock counter used and a second lock from the same session will\n"
1317 "be ignored. A single unlock (or RESET) unlocks the session.\n"
1318 "Return GPG_ERR_LOCKED if another session has locked the reader.\n"
1320 "If the option --wait is given the command will wait until a\n"
1321 "lock has been released.";
1323 cmd_lock (assuan_context_t ctx, char *line)
1325 ctrl_t ctrl = assuan_get_pointer (ctx);
1331 if (locked_session != ctrl->server_local)
1332 rc = gpg_error (GPG_ERR_LOCKED);
1335 locked_session = ctrl->server_local;
1338 if (rc && has_option (line, "--wait"))
1341 npth_sleep (1); /* Better implement an event mechanism. However,
1342 for card operations this should be
1344 /* Send a progress so that we can detect a connection loss. */
1345 rc = send_status_printf (ctrl, "PROGRESS", "scd_locked . 0 0");
1352 log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
1357 static const char hlp_unlock[] =
1360 "Release exclusive card access.";
1362 cmd_unlock (assuan_context_t ctx, char *line)
1364 ctrl_t ctrl = assuan_get_pointer (ctx);
1371 if (locked_session != ctrl->server_local)
1372 rc = gpg_error (GPG_ERR_LOCKED);
1374 locked_session = NULL;
1377 rc = gpg_error (GPG_ERR_NOT_LOCKED);
1380 log_error ("cmd_unlock failed: %s\n", gpg_strerror (rc));
1385 static const char hlp_getinfo[] =
1388 "Multi purpose command to return certain information. \n"
1389 "Supported values of WHAT are:\n"
1391 " version - Return the version of the program.\n"
1392 " pid - Return the process id of the server.\n"
1393 " socket_name - Return the name of the socket.\n"
1394 " connections - Return number of active connections.\n"
1395 " status - Return the status of the current reader (in the future,\n"
1396 " may also return the status of all readers). The status\n"
1397 " is a list of one-character flags. The following flags\n"
1398 " are currently defined:\n"
1399 " 'u' Usable card present.\n"
1400 " 'r' Card removed. A reset is necessary.\n"
1401 " These flags are exclusive.\n"
1402 " reader_list - Return a list of detected card readers. Does\n"
1403 " currently only work with the internal CCID driver.\n"
1404 " deny_admin - Returns OK if admin commands are not allowed or\n"
1405 " GPG_ERR_GENERAL if admin commands are allowed.\n"
1406 " app_list - Return a list of supported applications. One\n"
1407 " application per line, fields delimited by colons,\n"
1408 " first field is the name.\n"
1409 " card_list - Return a list of serial numbers of active cards,\n"
1410 " using a status response.";
1412 cmd_getinfo (assuan_context_t ctx, char *line)
1416 if (!strcmp (line, "version"))
1418 const char *s = VERSION;
1419 rc = assuan_send_data (ctx, s, strlen (s));
1421 else if (!strcmp (line, "pid"))
1425 snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1426 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1428 else if (!strcmp (line, "socket_name"))
1430 const char *s = scd_get_socket_name ();
1433 rc = assuan_send_data (ctx, s, strlen (s));
1435 rc = gpg_error (GPG_ERR_NO_DATA);
1437 else if (!strcmp (line, "connections"))
1441 snprintf (numbuf, sizeof numbuf, "%d", get_active_connection_count ());
1442 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1444 else if (!strcmp (line, "status"))
1446 ctrl_t ctrl = assuan_get_pointer (ctx);
1449 if (open_card (ctrl))
1454 rc = assuan_send_data (ctx, &flag, 1);
1456 else if (!strcmp (line, "reader_list"))
1459 char *s = ccid_get_reader_list ();
1465 rc = assuan_send_data (ctx, s, strlen (s));
1467 rc = gpg_error (GPG_ERR_NO_DATA);
1470 else if (!strcmp (line, "deny_admin"))
1471 rc = opt.allow_admin? gpg_error (GPG_ERR_GENERAL) : 0;
1472 else if (!strcmp (line, "app_list"))
1474 char *s = get_supported_applications ();
1476 rc = assuan_send_data (ctx, s, strlen (s));
1481 else if (!strcmp (line, "card_list"))
1483 ctrl_t ctrl = assuan_get_pointer (ctx);
1485 app_send_card_list (ctrl);
1488 rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1493 static const char hlp_restart[] =
1496 "Restart the current connection; this is a kind of warm reset. It\n"
1497 "deletes the context used by this connection but does not send a\n"
1498 "RESET to the card. Thus the card itself won't get reset. \n"
1500 "This is used by gpg-agent to reuse a primary pipe connection and\n"
1501 "may be used by clients to backup from a conflict in the serial\n"
1502 "command; i.e. to select another application.";
1504 cmd_restart (assuan_context_t ctx, char *line)
1506 ctrl_t ctrl = assuan_get_pointer (ctx);
1507 app_t app = ctrl->app_ctx;
1513 ctrl->app_ctx = NULL;
1514 release_application (app, 0);
1516 if (locked_session && ctrl->server_local == locked_session)
1518 locked_session = NULL;
1519 log_info ("implicitly unlocking due to RESTART\n");
1525 static const char hlp_disconnect[] =
1528 "Disconnect the card if the backend supports a disconnect operation.";
1530 cmd_disconnect (assuan_context_t ctx, char *line)
1532 ctrl_t ctrl = assuan_get_pointer (ctx);
1537 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1539 apdu_disconnect (ctrl->app_ctx->slot);
1545 static const char hlp_apdu[] =
1546 "APDU [--[dump-]atr] [--more] [--exlen[=N]] [hexstring]\n"
1548 "Send an APDU to the current reader. This command bypasses the high\n"
1549 "level functions and sends the data directly to the card. HEXSTRING\n"
1550 "is expected to be a proper APDU. If HEXSTRING is not given no\n"
1551 "commands are set to the card but the command will implictly check\n"
1552 "whether the card is ready for use. \n"
1554 "Using the option \"--atr\" returns the ATR of the card as a status\n"
1555 "message before any data like this:\n"
1556 " S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1\n"
1558 "Using the option --more handles the card status word MORE_DATA\n"
1559 "(61xx) and concatenates all responses to one block.\n"
1561 "Using the option \"--exlen\" the returned APDU may use extended\n"
1562 "length up to N bytes. If N is not given a default value is used\n"
1563 "(currently 4096).";
1565 cmd_apdu (assuan_context_t ctx, char *line)
1567 ctrl_t ctrl = assuan_get_pointer (ctx);
1570 unsigned char *apdu;
1577 if (has_option (line, "--dump-atr"))
1580 with_atr = has_option (line, "--atr");
1581 handle_more = has_option (line, "--more");
1583 if ((s=has_option_name (line, "--exlen")))
1586 exlen = strtoul (s+1, NULL, 0);
1593 line = skip_options (line);
1595 if ((rc = open_card (ctrl)))
1598 app = ctrl->app_ctx;
1600 return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
1608 atr = apdu_get_atr (app->slot, &atrlen);
1609 if (!atr || atrlen > sizeof hexbuf - 2 )
1611 rc = gpg_error (GPG_ERR_INV_CARD);
1616 char *string, *p, *pend;
1618 string = atr_dump (atr, atrlen);
1621 for (rc=0, p=string; !rc && (pend = strchr (p, '\n')); p = pend+1)
1623 rc = assuan_send_data (ctx, p, pend - p + 1);
1625 rc = assuan_send_data (ctx, NULL, 0);
1628 rc = assuan_send_data (ctx, p, strlen (p));
1636 bin2hex (atr, atrlen, hexbuf);
1637 send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
1642 apdu = hex_to_buffer (line, &apdulen);
1645 rc = gpg_error_from_syserror ();
1650 unsigned char *result = NULL;
1653 rc = apdu_send_direct (app->slot, exlen,
1654 apdu, apdulen, handle_more,
1655 NULL, &result, &resultlen);
1657 log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
1660 rc = assuan_send_data (ctx, result, resultlen);
1671 static const char hlp_killscd[] =
1676 cmd_killscd (assuan_context_t ctx, char *line)
1678 ctrl_t ctrl = assuan_get_pointer (ctx);
1682 ctrl->server_local->stopme = 1;
1683 assuan_set_flag (ctx, ASSUAN_FORCE_CLOSE, 1);
1689 /* Tell the assuan library about our commands */
1691 register_commands (assuan_context_t ctx)
1695 assuan_handler_t handler;
1696 const char * const help;
1698 { "SERIALNO", cmd_serialno, hlp_serialno },
1699 { "LEARN", cmd_learn, hlp_learn },
1700 { "READCERT", cmd_readcert, hlp_readcert },
1701 { "READKEY", cmd_readkey, hlp_readkey },
1702 { "SETDATA", cmd_setdata, hlp_setdata },
1703 { "PKSIGN", cmd_pksign, hlp_pksign },
1704 { "PKAUTH", cmd_pkauth, hlp_pkauth },
1705 { "PKDECRYPT", cmd_pkdecrypt,hlp_pkdecrypt },
1708 { "GETATTR", cmd_getattr, hlp_getattr },
1709 { "SETATTR", cmd_setattr, hlp_setattr },
1710 { "WRITECERT", cmd_writecert,hlp_writecert },
1711 { "WRITEKEY", cmd_writekey, hlp_writekey },
1712 { "GENKEY", cmd_genkey, hlp_genkey },
1713 { "RANDOM", cmd_random, hlp_random },
1714 { "PASSWD", cmd_passwd, hlp_passwd },
1715 { "CHECKPIN", cmd_checkpin, hlp_checkpin },
1716 { "LOCK", cmd_lock, hlp_lock },
1717 { "UNLOCK", cmd_unlock, hlp_unlock },
1718 { "GETINFO", cmd_getinfo, hlp_getinfo },
1719 { "RESTART", cmd_restart, hlp_restart },
1720 { "DISCONNECT", cmd_disconnect,hlp_disconnect },
1721 { "APDU", cmd_apdu, hlp_apdu },
1722 { "KILLSCD", cmd_killscd, hlp_killscd },
1727 for (i=0; table[i].name; i++)
1729 rc = assuan_register_command (ctx, table[i].name, table[i].handler,
1734 assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
1736 assuan_register_reset_notify (ctx, reset_notify);
1737 assuan_register_option_handler (ctx, option_handler);
1742 /* Startup the server. If FD is given as -1 this is simple pipe
1743 server, otherwise it is a regular server. Returns true if there
1744 are no more active asessions. */
1746 scd_command_handler (ctrl_t ctrl, int fd)
1749 assuan_context_t ctx = NULL;
1752 rc = assuan_new (&ctx);
1755 log_error ("failed to allocate assuan context: %s\n",
1762 assuan_fd_t filedes[2];
1764 filedes[0] = assuan_fdopen (0);
1765 filedes[1] = assuan_fdopen (1);
1766 rc = assuan_init_pipe_server (ctx, filedes);
1770 rc = assuan_init_socket_server (ctx, INT2FD(fd),
1771 ASSUAN_SOCKET_SERVER_ACCEPTED);
1775 log_error ("failed to initialize the server: %s\n",
1779 rc = register_commands (ctx);
1782 log_error ("failed to register commands with Assuan: %s\n",
1786 assuan_set_pointer (ctx, ctrl);
1788 /* Allocate and initialize the server object. Put it into the list
1789 of active sessions. */
1790 ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
1791 ctrl->server_local->next_session = session_list;
1792 session_list = ctrl->server_local;
1793 ctrl->server_local->ctrl_backlink = ctrl;
1794 ctrl->server_local->assuan_ctx = ctx;
1796 /* Command processing loop. */
1799 rc = assuan_accept (ctx);
1806 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
1810 rc = assuan_process (ctx);
1813 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
1818 /* Cleanup. We don't send an explicit reset to the card. */
1819 do_reset (ctrl, 0, 0);
1821 /* Release the server object. */
1822 if (session_list == ctrl->server_local)
1823 session_list = ctrl->server_local->next_session;
1826 struct server_local_s *sl;
1828 for (sl=session_list; sl->next_session; sl = sl->next_session)
1829 if (sl->next_session == ctrl->server_local)
1831 if (!sl->next_session)
1833 sl->next_session = ctrl->server_local->next_session;
1835 stopme = ctrl->server_local->stopme;
1836 xfree (ctrl->server_local);
1837 ctrl->server_local = NULL;
1839 /* Release the Assuan context. */
1840 assuan_release (ctx);
1845 /* If there are no more sessions return true. */
1846 return !session_list;
1850 /* Send a line with status information via assuan and escape all given
1851 buffers. The variable elements are pairs of (char *, size_t),
1852 terminated with a (NULL, 0). */
1854 send_status_info (ctrl_t ctrl, const char *keyword, ...)
1857 const unsigned char *value;
1861 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
1863 va_start (arg_ptr, keyword);
1867 while ( (value = va_arg (arg_ptr, const unsigned char *))
1868 && n < DIM (buf)-2 )
1870 valuelen = va_arg (arg_ptr, size_t);
1872 continue; /* empty buffer */
1878 for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
1880 if (*value == '+' || *value == '\"' || *value == '%'
1883 sprintf (p, "%%%02X", *value);
1887 else if (*value == ' ')
1894 assuan_write_status (ctx, keyword, buf);
1900 /* Send a ready formatted status line via assuan. */
1902 send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
1904 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
1906 if (strchr (args, '\n'))
1907 log_error ("error: LF detected in status line - not sending\n");
1909 assuan_write_status (ctx, keyword, args);
1913 /* This status functions expects a printf style format string. No
1914 * filtering of the data is done instead the orintf formatted data is
1915 * send using assuan_send_status. */
1917 send_status_printf (ctrl_t ctrl, const char *keyword, const char *format, ...)
1921 assuan_context_t ctx;
1923 if (!ctrl || !ctrl->server_local || !(ctx = ctrl->server_local->assuan_ctx))
1926 va_start (arg_ptr, format);
1927 err = vprint_assuan_status (ctx, keyword, format, arg_ptr);
1934 popup_prompt (void *opaque, int on)
1936 ctrl_t ctrl = opaque;
1940 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
1946 unsigned char *value;
1950 cmd = "POPUPPINPADPROMPT --ack";
1952 cmd = "DISMISSPINPADPROMPT";
1953 err = assuan_inquire (ctx, cmd, &value, &valuelen, 100);
1961 /* Helper to send the clients a status change notification. */
1963 send_client_notifications (app_t app, int removal)
1967 #ifdef HAVE_W32_SYSTEM
1975 struct server_local_s *sl;
1977 for (sl=session_list; sl; sl = sl->next_session)
1978 if (sl->ctrl_backlink && sl->ctrl_backlink->app_ctx == app)
1981 #ifdef HAVE_W32_SYSTEM
1989 sl->ctrl_backlink->app_ctx = NULL;
1990 sl->card_removed = 1;
1991 release_application (app, 1);
1994 if (!sl->event_signal || !sl->assuan_ctx)
1997 pid = assuan_get_pid (sl->assuan_ctx);
1999 #ifdef HAVE_W32_SYSTEM
2000 handle = sl->event_signal;
2001 for (kidx=0; kidx < killidx; kidx++)
2002 if (killed[kidx].pid == pid
2003 && killed[kidx].handle == handle)
2006 log_info ("event %p (%p) already triggered for client %d\n",
2007 sl->event_signal, handle, (int)pid);
2010 log_info ("triggering event %p (%p) for client %d\n",
2011 sl->event_signal, handle, (int)pid);
2012 if (!SetEvent (handle))
2013 log_error ("SetEvent(%p) failed: %s\n",
2014 sl->event_signal, w32_strerror (-1));
2015 if (killidx < DIM (killed))
2017 killed[killidx].pid = pid;
2018 killed[killidx].handle = handle;
2022 #else /*!HAVE_W32_SYSTEM*/
2023 signo = sl->event_signal;
2025 if (pid != (pid_t)(-1) && pid && signo > 0)
2027 for (kidx=0; kidx < killidx; kidx++)
2028 if (killed[kidx].pid == pid
2029 && killed[kidx].signo == signo)
2032 log_info ("signal %d already sent to client %d\n",
2036 log_info ("sending signal %d to client %d\n",
2039 if (killidx < DIM (killed))
2041 killed[killidx].pid = pid;
2042 killed[killidx].signo = signo;
2047 #endif /*!HAVE_W32_SYSTEM*/