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/>.
37 #include "apdu.h" /* Required for apdu_*_reader (). */
40 #include "ccid-driver.h"
42 #include "../common/asshelp.h"
43 #include "../common/server-help.h"
44 #include "../common/ssh-utils.h"
46 /* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN. That
47 * length needs to small compared to the maximum Assuan line length. */
48 #define MAXLEN_PIN 100
50 /* Maximum allowed size of key data as used in inquiries. */
51 #define MAXLEN_KEYDATA 4096
53 /* Maximum allowed total data size for SETDATA. */
54 #define MAXLEN_SETDATA 4096
56 /* Maximum allowed size of certificate data as used in inquiries. */
57 #define MAXLEN_CERTDATA 16384
59 /* Maximum allowed size for "SETATTR --inquire". */
60 #define MAXLEN_SETATTRDATA 16384
63 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
65 #define IS_LOCKED(c) (locked_session && locked_session != (c)->server_local)
68 /* Data used to associate an Assuan context with local server data.
69 This object describes the local properties of one session. */
72 /* We keep a list of all active sessions with the anchor at
73 SESSION_LIST (see below). This field is used for linking. */
74 struct server_local_s *next_session;
76 /* This object is usually assigned to a CTRL object (which is
77 globally visible). While enumerating all sessions we sometimes
78 need to access data of the CTRL object; thus we keep a
82 /* The Assuan context used by this session/server. */
83 assuan_context_t assuan_ctx;
85 #ifdef HAVE_W32_SYSTEM
86 void *event_signal; /* Or NULL if not used. */
88 int event_signal; /* Or 0 if not used. */
91 /* True if the card has been removed and a reset is required to
92 continue operation. */
93 unsigned int card_removed:1;
95 /* If set to true we will be terminate ourself at the end of the
97 unsigned int stopme:1;
99 /* If set to true, status change will be reported. */
100 unsigned int watching_status:1;
104 /* To keep track of all running sessions, we link all active server
105 contexts and the anchor in this variable. */
106 static struct server_local_s *session_list;
108 /* If a session has been locked we store a link to its server object
110 static struct server_local_s *locked_session;
114 /* Local prototypes. */
115 static int command_has_option (const char *cmd, const char *cmdopt);
119 /* Convert the STRING into a newly allocated buffer while translating
120 the hex numbers. Stops at the first invalid character. Blanks and
121 colons are allowed to separate the hex digits. Returns NULL on
122 error or a newly malloced buffer and its length in LENGTH. */
123 static unsigned char *
124 hex_to_buffer (const char *string, size_t *r_length)
126 unsigned char *buffer;
130 buffer = xtrymalloc (strlen (string)+1);
133 for (s=string, n=0; *s; s++)
135 if (spacep (s) || *s == ':')
137 if (hexdigitp (s) && hexdigitp (s+1))
139 buffer[n++] = xtoi_2 (s);
151 /* Reset the card and free the application context. With SEND_RESET
152 set to true actually send a RESET to the reader; this is the normal
153 way of calling the function. If KEEP_LOCK is set and the session
154 is locked that lock wil not be released. */
156 do_reset (ctrl_t ctrl, int send_reset, int keep_lock)
158 card_t card = card_get (ctrl, NULL);
162 if (!IS_LOCKED (ctrl) && send_reset)
166 ctrl->card_ctx = NULL;
167 ctrl->current_apptype = APPTYPE_NONE;
168 card_unref_locked (card);
173 /* If we hold a lock, unlock now. */
174 if (!keep_lock && locked_session && ctrl->server_local == locked_session)
176 locked_session = NULL;
177 log_info ("implicitly unlocking due to RESET\n");
184 reset_notify (assuan_context_t ctx, char *line)
186 ctrl_t ctrl = assuan_get_pointer (ctx);
188 do_reset (ctrl, 1, has_option (line, "--keep-lock"));
194 option_handler (assuan_context_t ctx, const char *key, const char *value)
196 ctrl_t ctrl = assuan_get_pointer (ctx);
198 if (!strcmp (key, "event-signal"))
200 /* A value of 0 is allowed to reset the event signal. */
201 #ifdef HAVE_W32_SYSTEM
203 return gpg_error (GPG_ERR_ASS_PARAMETER);
205 ctrl->server_local->event_signal = (void *)strtoull (value, NULL, 16);
207 ctrl->server_local->event_signal = (void *)strtoul (value, NULL, 16);
210 int i = *value? atoi (value) : -1;
212 return gpg_error (GPG_ERR_ASS_PARAMETER);
213 ctrl->server_local->event_signal = i;
221 /* If the card has not yet been opened, do it. */
223 open_card (ctrl_t ctrl)
225 /* If we ever got a card not present error code, return that. Only
226 the SERIALNO command and a reset are able to clear from that
228 if (ctrl->server_local->card_removed)
229 return gpg_error (GPG_ERR_CARD_REMOVED);
231 if ( IS_LOCKED (ctrl) )
232 return gpg_error (GPG_ERR_LOCKED);
237 return select_application (ctrl, NULL, 0, NULL, 0);
240 /* Explicitly open a card for a specific use of APPTYPE or SERIALNO.
241 * If OPT_ALL is set also add all possible additional apps. */
243 open_card_with_request (card_t *card_p, ctrl_t ctrl,
244 const char *apptypestr, const char *serialno,
248 unsigned char *serialno_bin = NULL;
249 size_t serialno_bin_len = 0;
250 card_t card = card_get (ctrl, NULL);
253 serialno_bin = hex_to_buffer (serialno, &serialno_bin_len);
255 /* If we are already initialized for one specific application we
256 need to check that the client didn't requested a specific
257 application different from the one in use before we continue. */
258 if (apptypestr && card)
260 err = check_application_conflict (card, apptypestr,
261 serialno_bin, serialno_bin_len);
262 if (gpg_err_code (err) == GPG_ERR_FALSE)
264 /* Different application but switching is supported. */
265 err = select_additional_application (card, ctrl, apptypestr);
272 /* Re-scan USB devices. Release CARD, before the scan. */
275 ctrl->card_ctx = NULL;
276 ctrl->current_apptype = APPTYPE_NONE;
277 card_unref_locked (card);
281 err = select_application (ctrl, apptypestr, 1,
282 serialno_bin, serialno_bin_len);
283 card = card_get (ctrl, NULL);
288 err = select_additional_application (card, ctrl, NULL);
297 xfree (serialno_bin);
302 static const char hlp_serialno[] =
303 "SERIALNO [--demand=<serialno>] [--all] [<apptype>]\n"
305 "Return the serial number of the card using a status response. This\n"
306 "function should be used to check for the presence of a card.\n"
308 "If --demand is given, an application on the card with SERIALNO is\n"
309 "selected and an error is returned if no such card available.\n"
311 "If --all is given, all possible other applications of the card are\n"
312 "also selected to prepare for things like \"LEARN --force --multi\".\n"
314 "If APPTYPE is given, an application of that type is selected and an\n"
315 "error is returned if the application is not supported or available.\n"
316 "The default is to auto-select the application using a hardwired\n"
317 "preference system.\n"
319 "This function is special in that it can be used to reset the card.\n"
320 "Most other functions will return an error when a card change has\n"
321 "been detected and the use of this function is therefore required.\n"
323 "Background: We want to keep the client clear of handling card\n"
324 "changes between operations; i.e. the client can assume that all\n"
325 "operations are done on the same card unless he calls this function.";
327 cmd_serialno (assuan_context_t ctx, char *line)
329 ctrl_t ctrl = assuan_get_pointer (ctx);
330 struct server_local_s *sl;
334 int opt_all = has_option (line, "--all");
338 if ( IS_LOCKED (ctrl) )
339 return gpg_error (GPG_ERR_LOCKED);
341 if ((demand = has_option_name (line, "--demand")))
344 return set_error (GPG_ERR_ASS_PARAMETER, "missing value for option");
345 line = (char *)++demand;
346 while (*line && !spacep (line))
354 line = skip_options (line);
356 /* Clear the remove flag so that the open_card is able to reread it. */
357 ctrl->server_local->card_removed = 0;
358 err = open_card_with_request (&card, ctrl, *line? line:NULL, demand, opt_all);
359 /* Now clear or set the card_removed flag for all sessions using the
360 * current slot. In the error case make sure that the flag is set
361 * for the current session. */
362 thisslot = card? card->slot : -1;
363 for (sl=session_list; sl; sl = sl->next_session)
365 ctrl_t c = sl->ctrl_backlink;
366 if (c && c->card_ctx && c->card_ctx->slot == thisslot)
367 c->server_local->card_removed = err? 1 : 0;
371 ctrl->server_local->card_removed = 1;
375 serial = card_get_serialno (card);
378 return gpg_error (GPG_ERR_INV_VALUE);
380 err = assuan_write_status (ctx, "SERIALNO", serial);
387 static const char hlp_switchcard[] =
388 "SWITCHCARD [<serialno>]\n"
390 "Make the card with SERIALNO the current card.\n"
391 "The command \"getinfo card_list\" can be used to list\n"
392 "the serial numbers of inserted and known cards. Note\n"
393 "that the command \"SERIALNO\" can be used to refresh\n"
394 "the list of known cards. A simple SERIALNO status\n"
395 "is printed on success.";
397 cmd_switchcard (assuan_context_t ctx, char *line)
399 ctrl_t ctrl = assuan_get_pointer (ctx);
401 unsigned char *sn_bin = NULL;
402 size_t sn_bin_len = 0;
404 if ((err = open_card (ctrl)))
407 line = skip_options (line);
411 sn_bin = hex_to_buffer (line, &sn_bin_len);
414 err = gpg_error_from_syserror ();
419 /* Note that an SN_BIN of NULL will only print the status. */
420 err = app_switch_current_card (ctrl, sn_bin, sn_bin_len);
428 static const char hlp_switchapp[] =
429 "SWITCHAPP [<appname>]\n"
431 "Make APPNAME the active application for the current card.\n"
432 "Only some cards support switching between application; the\n"
433 "command \"getinfo active_app\" can be used to get a list of\n"
434 "applications which can be switched to. A SERIALNO status\n"
435 "including the active appname is printed on success.";
437 cmd_switchapp (assuan_context_t ctx, char *line)
439 ctrl_t ctrl = assuan_get_pointer (ctx);
443 if ((err = open_card (ctrl)))
446 line = skip_options (line);
447 card = card_get (ctrl, NULL);
450 err = app_switch_active_app (card, ctrl, line);
454 err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
460 static const char hlp_learn[] =
461 "LEARN [--force] [--keypairinfo] [--reread] [--multi]\n"
463 "Learn all useful information of the currently inserted card. When\n"
464 "used without the force options, the command might do an INQUIRE\n"
467 " INQUIRE KNOWNCARDP <hexstring_with_serialNumber>\n"
469 "The client should just send an \"END\" if the processing should go on\n"
470 "or a \"CANCEL\" to force the function to terminate with a Cancel\n"
473 "With the option --keypairinfo only KEYPAIRINFO status lines are\n"
474 "returned. With the option --reread information from the card are\n"
475 "read again without the need for a reset (sone some cards).\n"
477 "The response of this command is a list of status lines formatted as\n"
480 " S APPTYPE <apptype>\n"
482 "This returns the type of the application, currently the strings:\n"
484 " P15 = PKCS-15 structure used\n"
485 " DINSIG = DIN SIG\n"
486 " OPENPGP = OpenPGP card\n"
488 " NKS = NetKey card\n"
490 "are implemented. These strings are aliases for the AID. With option\n"
491 "--multi information for all switchable apps are returned.\n"
493 " S KEYPAIRINFO <hexgrip> <keyref> [<usage>] [<keytime>] [<algo>]\n"
495 "If there is no certificate yet stored on the card a single 'X' is\n"
496 "returned as the keygrip. For more info see doc/DETAILS. In addition\n"
497 "to the keypair info, information about all certificates stored on the\n"
498 "card is also returned:\n"
500 " S CERTINFO <certtype> <keyref> [<label>]\n"
502 "Where CERTTYPE is a number indicating the type of certificate:\n"
504 " 100 := Regular X.509 cert\n"
505 " 101 := Trusted X.509 cert\n"
506 " 102 := Useful X.509 cert\n"
507 " 110 := Root CA cert in a special format (e.g. DINSIG)\n"
508 " 111 := Root CA cert as standard X509 cert.\n"
510 "For certain cards, more information will be returned:\n"
512 " S KEY-FPR <keyref> <hexstring>\n"
514 "For some cards this returns the stored fingerprints of the\n"
515 "keys. This can be used check whether a key is available on the\n"
516 "card. KEYREF may be 1, 2 or 3 for OpenPGP or a standard keyref.\n"
518 " S CA-FPR <no> <hexstring>\n"
520 "Similar to above, these are the fingerprints of keys assumed to be\n"
521 "ultimately trusted.\n"
523 " S DISP-NAME <name_of_card_holder>\n"
525 "The name of the card holder as stored on the card; percent\n"
526 "escaping takes place, spaces are encoded as '+'\n"
528 " S PUBKEY-URL <url>\n"
530 "The URL to be used for locating the entire public key.\n"
532 "Note, that this function may even be used on a locked card.";
534 cmd_learn (assuan_context_t ctx, char *line)
536 ctrl_t ctrl = assuan_get_pointer (ctx);
538 int only_keypairinfo = has_option (line, "--keypairinfo");
539 int opt_multi = has_option (line, "--multi");
540 int opt_reread = has_option (line, "--reread");
541 int opt_force = has_option (line, "--force");
544 const char *keygrip = NULL;
546 if ((rc = open_card (ctrl)))
549 line = skip_options (line);
550 if (strlen (line) == 40)
553 card = card_get (ctrl, keygrip);
555 return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
557 /* Unless the force option is used we try a shortcut by identifying
558 the card using a serial number and inquiring the client with
559 that. The client may choose to cancel the operation if he already
560 knows about this card */
561 if (!only_keypairinfo)
566 reader = apdu_get_reader_name (card->slot);
570 return out_of_core ();
572 send_status_direct (ctrl, "READER", reader);
573 /* No need to free the string of READER. */
575 serial = card_get_serialno (card);
579 return gpg_error (GPG_ERR_INV_VALUE);
582 rc = assuan_write_status (ctx, "SERIALNO", serial);
587 return out_of_core ();
594 rc = gpgrt_asprintf (&command, "KNOWNCARDP %s", serial);
599 return out_of_core ();
601 rc = assuan_inquire (ctx, command, NULL, NULL, 0);
605 if (gpg_err_code (rc) != GPG_ERR_ASS_CANCELED)
606 log_error ("inquire KNOWNCARDP failed: %s\n",
612 /* Not canceled, so we have to proceed. */
617 /* Let the application print out its collection of useful status
620 if (only_keypairinfo)
621 flags |= APP_LEARN_FLAG_KEYPAIRINFO;
623 flags |= APP_LEARN_FLAG_MULTI;
625 flags |= APP_LEARN_FLAG_REREAD;
628 rc = app_write_learn_status (card, ctrl, flags);
636 static const char hlp_readcert[] =
637 "READCERT <hexified_certid>|<keyid>|<oid>\n"
639 "Note, that this function may even be used on a locked card.";
641 cmd_readcert (assuan_context_t ctx, char *line)
643 ctrl_t ctrl = assuan_get_pointer (ctx);
648 const char *keygrip = NULL;
650 if ((rc = open_card (ctrl)))
653 line = xtrystrdup (line); /* Need a copy of the line. */
655 return gpg_error_from_syserror ();
657 if (strlen (line) == 40)
660 card = card_get (ctrl, keygrip);
664 return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
667 rc = app_readcert (card, ctrl, line, &cert, &ncert);
669 log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
675 rc = assuan_send_data (ctx, cert, ncert);
686 do_readkey (card_t card, ctrl_t ctrl, const char *line,
687 int opt_info, unsigned char **pk_p, size_t *pklen_p)
690 int direct_readkey = 0;
692 /* If the application supports the READKEY function we use that.
693 Otherwise we use the old way by extracting it from the
695 rc = app_readkey (card, ctrl, line,
696 opt_info? APP_READKEY_FLAG_INFO : 0,
699 direct_readkey = 1; /* Got the key. */
700 else if (gpg_err_code (rc) == GPG_ERR_UNSUPPORTED_OPERATION
701 || gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
703 /* Fall back to certificate reading. */
704 unsigned char *cert = NULL;
707 rc = app_readcert (card, ctrl, line, &cert, &ncert);
709 log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
712 rc = app_help_pubkey_from_cert (cert, ncert, pk_p, pklen_p);
715 log_error ("failed to parse the certificate: %s\n",
720 log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
722 if (!rc && opt_info && !direct_readkey)
724 char keygripstr[KEYGRIP_LEN*2+1];
727 rc = app_help_get_keygrip_string_pk (*pk_p, *pklen_p,
728 keygripstr, NULL, NULL,
732 log_error ("app_help_get_keygrip_string failed: %s\n",
737 /* FIXME: Using LINE is not correct because it might be an
738 * OID and has not been canonicalized (i.e. uppercased). */
739 send_status_info (ctrl, "KEYPAIRINFO",
740 keygripstr, strlen (keygripstr),
744 algostr, strlen (algostr),
752 static const char hlp_readkey[] =
753 "READKEY [--format=advanced|ssh] [--info[-only]] <keyid>|<oid>|<keygrip>\n"
755 "Return the public key for the given cert or key ID as a standard\n"
756 "S-expression. With --format option, it may be returned in advanced\n"
757 "S-expression format, or SSH format. With --info a KEYPAIRINFO\n"
758 "status line is also emitted; with --info-only the regular output is\n"
761 cmd_readkey (assuan_context_t ctx, char *line)
763 ctrl_t ctrl = assuan_get_pointer (ctx);
769 unsigned char *pk = NULL;
772 const char *keygrip = NULL;
774 if ((err = open_card (ctrl)))
777 if (has_option (line, "--advanced"))
779 if (has_option (line, "--format=advanced"))
781 if (has_option (line, "--format=ssh"))
783 if (has_option (line, "--info"))
785 if (has_option (line, "--info-only"))
786 opt_info = opt_nokey = 1;
788 line = skip_options (line);
790 line = xtrystrdup (line); /* Need a copy of the line. */
792 return gpg_error_from_syserror ();
794 if (strlen (line) == 40)
797 card = card_get (ctrl, keygrip);
800 err = do_readkey (card, ctrl, line, opt_info, &pk, &pklen);
804 err = gpg_error (GPG_ERR_NO_SECKEY);
813 estream_t stream = NULL;
818 stream = es_fopenmem (0, "r+b");
821 err = gpg_error_from_syserror ();
825 err = gcry_sexp_new (&s_key, pk, pklen, 0);
832 err = ssh_public_key_in_base64 (s_key, stream, "(none)");
835 gcry_sexp_release (s_key);
840 err = es_fclose_snatch (stream, &buf, &buflen);
841 gcry_sexp_release (s_key);
843 err = assuan_send_data (ctx, buf, buflen);
848 unsigned char *pkadv;
851 err = gcry_sexp_new (&s_key, pk, pklen, 0);
855 pkadvlen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_ADVANCED, NULL, 0);
856 pkadv = xtrymalloc (pkadvlen);
859 err = gpg_error_from_syserror ();
860 gcry_sexp_release (s_key);
863 log_assert (pkadvlen);
865 gcry_sexp_sprint (s_key, GCRYSEXP_FMT_ADVANCED, pkadv, pkadvlen);
866 gcry_sexp_release (s_key);
867 /* (One less to adjust for the trailing '\0') */
868 err = assuan_send_data (ctx, pkadv, pkadvlen-1);
872 err = assuan_send_data (ctx, pk, pklen);
882 static const char hlp_setdata[] =
883 "SETDATA [--append] <hexstring>\n"
885 "The client should use this command to tell us the data he want to sign.\n"
886 "With the option --append, the data is appended to the data set by a\n"
887 "previous SETDATA command.";
889 cmd_setdata (assuan_context_t ctx, char *line)
891 ctrl_t ctrl = assuan_get_pointer (ctx);
897 append = (ctrl->in_data.value && has_option (line, "--append"));
899 line = skip_options (line);
901 if (locked_session && locked_session != ctrl->server_local)
902 return gpg_error (GPG_ERR_LOCKED);
904 /* Parse the hexstring. */
905 for (p=line,n=0; hexdigitp (p); p++, n++)
908 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
910 return set_error (GPG_ERR_ASS_PARAMETER, "no data given");
912 return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
916 if (ctrl->in_data.valuelen + n > MAXLEN_SETDATA)
917 return set_error (GPG_ERR_TOO_LARGE,
918 "limit on total size of data reached");
919 buf = xtrymalloc (ctrl->in_data.valuelen + n);
922 buf = xtrymalloc (n);
924 return out_of_core ();
928 memcpy (buf, ctrl->in_data.value, ctrl->in_data.valuelen);
929 off = ctrl->in_data.valuelen;
933 for (p=line, i=0; i < n; p += 2, i++)
934 buf[off+i] = xtoi_2 (p);
936 xfree (ctrl->in_data.value);
937 ctrl->in_data.value = buf;
938 ctrl->in_data.valuelen = off+n;
945 pin_cb (void *opaque, const char *info, char **retstr)
947 assuan_context_t ctx = opaque;
950 unsigned char *value;
955 /* We prompt for pinpad entry. To make sure that the popup has
956 been show we use an inquire and not just a status message.
957 We ignore any value returned. */
960 log_debug ("prompting for pinpad entry '%s'\n", info);
961 rc = gpgrt_asprintf (&command, "POPUPPINPADPROMPT %s", info);
963 return gpg_error (gpg_err_code_from_errno (errno));
964 rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
969 log_debug ("dismiss pinpad entry prompt\n");
970 rc = assuan_inquire (ctx, "DISMISSPINPADPROMPT",
971 &value, &valuelen, MAXLEN_PIN);
979 log_debug ("asking for PIN '%s'\n", info);
981 rc = gpgrt_asprintf (&command, "NEEDPIN %s", info);
983 return gpg_error (gpg_err_code_from_errno (errno));
985 /* Fixme: Write an inquire function which returns the result in
986 secure memory and check all further handling of the PIN. */
987 assuan_begin_confidential (ctx);
988 rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
989 assuan_end_confidential (ctx);
994 if (!valuelen || value[valuelen-1])
996 /* We require that the returned value is an UTF-8 string */
998 return gpg_error (GPG_ERR_INV_RESPONSE);
1000 *retstr = (char*)value;
1005 static const char hlp_pksign[] =
1006 "PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5|none]] <hexified_id>\n"
1008 "The --hash option is optional; the default is SHA1.";
1010 cmd_pksign (assuan_context_t ctx, char *line)
1012 ctrl_t ctrl = assuan_get_pointer (ctx);
1014 unsigned char *outdata;
1019 const char *keygrip = NULL;
1021 if (has_option (line, "--hash=rmd160"))
1022 hash_algo = GCRY_MD_RMD160;
1023 else if (has_option (line, "--hash=sha1"))
1024 hash_algo = GCRY_MD_SHA1;
1025 else if (has_option (line, "--hash=sha224"))
1026 hash_algo = GCRY_MD_SHA224;
1027 else if (has_option (line, "--hash=sha256"))
1028 hash_algo = GCRY_MD_SHA256;
1029 else if (has_option (line, "--hash=sha384"))
1030 hash_algo = GCRY_MD_SHA384;
1031 else if (has_option (line, "--hash=sha512"))
1032 hash_algo = GCRY_MD_SHA512;
1033 else if (has_option (line, "--hash=md5"))
1034 hash_algo = GCRY_MD_MD5;
1035 else if (has_option (line, "--hash=none")) /* For raw RSA. */
1037 else if (!strstr (line, "--"))
1038 hash_algo = GCRY_MD_SHA1;
1040 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
1042 line = skip_options (line);
1044 if ((rc = open_card (ctrl)))
1047 /* We have to use a copy of the key ID because the function may use
1048 the pin_cb which in turn uses the assuan line buffer and thus
1049 overwriting the original line with the keyid */
1050 keyidstr = xtrystrdup (line);
1052 return out_of_core ();
1054 /* When it's a keygrip, we directly use the card, with no change of
1056 if (strlen (keyidstr) == 40)
1059 card = card_get (ctrl, keygrip);
1062 rc = app_sign (card, ctrl,
1063 keyidstr, hash_algo,
1065 ctrl->in_data.value, ctrl->in_data.valuelen,
1066 &outdata, &outdatalen);
1070 rc = gpg_error (GPG_ERR_NO_SECKEY);
1075 log_error ("app_sign failed: %s\n", gpg_strerror (rc));
1079 rc = assuan_send_data (ctx, outdata, outdatalen);
1082 return rc; /* that is already an assuan error code */
1089 static const char hlp_pkauth[] =
1090 "PKAUTH [--challenge-response] <hexified_id>";
1092 cmd_pkauth (assuan_context_t ctx, char *line)
1094 ctrl_t ctrl = assuan_get_pointer (ctx);
1096 unsigned char *outdata;
1100 const char *keygrip = NULL;
1101 int challenge_response = 0;
1103 if ((rc = open_card (ctrl)))
1106 if (has_option (line, "--challenge-response"))
1107 challenge_response = 1;
1109 line = skip_options (line);
1111 /* We have to use a copy of the key ID because the function may use
1112 the pin_cb which in turn uses the assuan line buffer and thus
1113 overwriting the original line with the keyid */
1114 keyidstr = xtrystrdup (line);
1116 return out_of_core ();
1118 /* When it's a keygrip, we directly use CARD, with no change of
1120 if (strlen (keyidstr) == 40)
1123 if (challenge_response)
1125 xfree (ctrl->in_data.value);
1126 ctrl->in_data.value = NULL;
1127 ctrl->in_data.valuelen = 0;
1130 card = card_get (ctrl, keygrip);
1133 rc = app_auth (card, ctrl, keyidstr, pin_cb, ctx,
1134 ctrl->in_data.value, ctrl->in_data.valuelen,
1135 &outdata, &outdatalen);
1139 rc = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1144 log_error ("app_auth failed: %s\n", gpg_strerror (rc));
1148 if (!challenge_response)
1149 rc = assuan_send_data (ctx, outdata, outdatalen);
1157 static const char hlp_pkdecrypt[] =
1158 "PKDECRYPT <hexified_id>";
1160 cmd_pkdecrypt (assuan_context_t ctx, char *line)
1162 ctrl_t ctrl = assuan_get_pointer (ctx);
1164 unsigned char *outdata;
1167 unsigned int infoflags;
1169 const char *keygrip = NULL;
1171 if ((rc = open_card (ctrl)))
1174 keyidstr = xtrystrdup (line);
1176 return out_of_core ();
1178 /* When it's a keygrip, we directly use CARD, with no change of
1180 if (strlen (keyidstr) == 40)
1183 card = card_get (ctrl, keygrip);
1186 rc = app_decipher (card, ctrl, keyidstr, pin_cb, ctx,
1187 ctrl->in_data.value, ctrl->in_data.valuelen,
1188 &outdata, &outdatalen, &infoflags);
1192 rc = gpg_error (GPG_ERR_NO_SECKEY);
1197 log_error ("app_decipher failed: %s\n", gpg_strerror (rc));
1201 /* If the card driver told us that there is no padding, send a
1202 status line. If there is a padding it is assumed that the
1203 caller knows what padding is used. It would have been better
1204 to always send that information but for backward
1205 compatibility we can't do that. */
1206 if ((infoflags & APP_DECIPHER_INFO_NOPAD))
1207 send_status_direct (ctrl, "PADDING", "0");
1208 rc = assuan_send_data (ctx, outdata, outdatalen);
1211 return rc; /* that is already an assuan error code */
1218 static const char hlp_getattr[] =
1219 "GETATTR <name> [<keygrip>]\n"
1221 "This command is used to retrieve data from a smartcard. The\n"
1222 "allowed names depend on the currently selected smartcard\n"
1223 "application. NAME must be percent and '+' escaped. The value is\n"
1224 "returned through status message, see the LEARN command for details.\n"
1226 "However, the current implementation assumes that Name is not escaped;\n"
1227 "this works as long as no one uses arbitrary escaping. \n"
1229 "Note, that this function may even be used on a locked card.\n"
1230 "When KEYGRIP is specified, it accesses directly with the KEYGRIP.";
1232 cmd_getattr (assuan_context_t ctx, char *line)
1234 ctrl_t ctrl = assuan_get_pointer (ctx);
1236 const char *keyword;
1238 const char *keygrip = NULL;
1240 if ((rc = open_card (ctrl)))
1244 while (*line && !spacep (line))
1249 if (strlen (line) == 40)
1252 card = card_get (ctrl, keygrip);
1255 /* FIXME: Applications should not return sensitive data if the card
1257 rc = app_getattr (card, ctrl, keyword);
1261 rc = gpg_error (GPG_ERR_NO_SECKEY);
1267 static const char hlp_setattr[] =
1268 "SETATTR [--inquire] <name> <value> \n"
1270 "This command is used to store data on a smartcard. The allowed\n"
1271 "names and values are depend on the currently selected smartcard\n"
1272 "application. NAME and VALUE must be percent and '+' escaped.\n"
1274 "However, the current implementation assumes that NAME is not\n"
1275 "escaped; this works as long as no one uses arbitrary escaping.\n"
1277 "If the option --inquire is used, VALUE shall not be given; instead\n"
1278 "an inquiry using the keyword \"VALUE\" is used to retrieve it. The\n"
1279 "value is in this case considered to be confidential and not logged.\n"
1281 "A PIN will be requested for most NAMEs. See the corresponding\n"
1282 "setattr function of the actually used application (app-*.c) for\n"
1285 cmd_setattr (assuan_context_t ctx, char *orig_line)
1287 ctrl_t ctrl = assuan_get_pointer (ctx);
1292 char *line, *linebuf;
1296 opt_inquire = has_option (orig_line, "--inquire");
1297 orig_line = skip_options (orig_line);
1299 if ((err = open_card (ctrl)))
1302 /* We need to use a copy of LINE, because PIN_CB uses the same
1303 context and thus reuses the Assuan provided LINE. */
1304 line = linebuf = xtrystrdup (orig_line);
1306 return out_of_core ();
1308 card = card_get (ctrl, NULL);
1312 return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
1316 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
1320 while (spacep (line))
1324 unsigned char *value;
1326 assuan_begin_confidential (ctx);
1327 err = assuan_inquire (ctx, "VALUE", &value, &nbytes, MAXLEN_SETATTRDATA);
1328 assuan_end_confidential (ctx);
1331 err = app_setattr (card, ctrl, keyword, pin_cb, ctx,
1333 wipememory (value, nbytes);
1340 nbytes = percent_plus_unescape_inplace (line, 0);
1341 err = app_setattr (card, ctrl, keyword, pin_cb, ctx,
1342 (const unsigned char*)line, nbytes);
1351 static const char hlp_writecert[] =
1352 "WRITECERT <hexified_certid>\n"
1354 "This command is used to store a certificate on a smartcard. The\n"
1355 "allowed certids depend on the currently selected smartcard\n"
1356 "application. The actual certifciate is requested using the inquiry\n"
1357 "\"CERTDATA\" and needs to be provided in its raw (e.g. DER) form.\n"
1359 "In almost all cases a PIN will be requested. See the related\n"
1360 "writecert function of the actually used application (app-*.c) for\n"
1363 cmd_writecert (assuan_context_t ctx, char *line)
1365 ctrl_t ctrl = assuan_get_pointer (ctx);
1368 unsigned char *certdata;
1372 line = skip_options (line);
1375 return set_error (GPG_ERR_ASS_PARAMETER, "no certid given");
1377 while (*line && !spacep (line))
1381 if ((rc = open_card (ctrl)))
1384 card = card_get (ctrl, NULL);
1386 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1388 certid = xtrystrdup (certid);
1392 return out_of_core ();
1395 /* Now get the actual keydata. */
1396 rc = assuan_inquire (ctx, "CERTDATA",
1397 &certdata, &certdatalen, MAXLEN_CERTDATA);
1405 /* Write the certificate to the card. */
1406 rc = app_writecert (card, ctrl, certid,
1407 pin_cb, ctx, certdata, certdatalen);
1416 static const char hlp_writekey[] =
1417 "WRITEKEY [--force] <keyid> \n"
1419 "This command is used to store a secret key on a smartcard. The\n"
1420 "allowed keyids depend on the currently selected smartcard\n"
1421 "application. The actual keydata is requested using the inquiry\n"
1422 "\"KEYDATA\" and need to be provided without any protection. With\n"
1423 "--force set an existing key under this KEYID will get overwritten.\n"
1424 "The keydata is expected to be the usual canonical encoded\n"
1427 "A PIN will be requested for most NAMEs. See the corresponding\n"
1428 "writekey function of the actually used application (app-*.c) for\n"
1431 cmd_writekey (assuan_context_t ctx, char *line)
1433 ctrl_t ctrl = assuan_get_pointer (ctx);
1436 int force = has_option (line, "--force");
1437 unsigned char *keydata;
1441 line = skip_options (line);
1444 return set_error (GPG_ERR_ASS_PARAMETER, "no keyid given");
1446 while (*line && !spacep (line))
1450 if ((rc = open_card (ctrl)))
1453 card = card_get (ctrl, NULL);
1455 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1457 keyid = xtrystrdup (keyid);
1461 return out_of_core ();
1464 /* Now get the actual keydata. */
1465 assuan_begin_confidential (ctx);
1466 rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA);
1467 assuan_end_confidential (ctx);
1474 /* Write the key to the card. */
1475 rc = app_writekey (card, ctrl, keyid, force? 1:0,
1476 pin_cb, ctx, keydata, keydatalen);
1485 static const char hlp_genkey[] =
1486 "GENKEY [--force] [--timestamp=<isodate>] [--algo=ALGO] <keyref>\n"
1488 "Generate a key on-card identified by <keyref>, which is application\n"
1489 "specific. Return values are also application specific. For OpenPGP\n"
1490 "cards 3 status lines are returned:\n"
1492 " S KEY-FPR <hexstring>\n"
1493 " S KEY-CREATED-AT <seconds_since_epoch>\n"
1494 " S KEY-DATA [-|p|n] <hexdata>\n"
1496 " 'p' and 'n' are the names of the RSA parameters; '-' is used to\n"
1497 " indicate that HEXDATA is the first chunk of a parameter given\n"
1498 " by the next KEY-DATA. Only used by GnuPG version < 2.1.\n"
1500 "--force is required to overwrite an already existing key. The\n"
1501 "KEY-CREATED-AT is required for further processing because it is\n"
1502 "part of the hashed key material for the fingerprint.\n"
1504 "If --timestamp is given an OpenPGP key will be created using this\n"
1505 "value. The value needs to be in ISO Format; e.g.\n"
1506 "\"--timestamp=20030316T120000\" and after 1970-01-01 00:00:00.\n"
1508 "The option --algo can be used to request creation using a specific\n"
1509 "algorithm. The possible algorithms are card dependent.\n"
1511 "The public part of the key can also later be retrieved using the\n"
1514 cmd_genkey (assuan_context_t ctx, char *line)
1516 ctrl_t ctrl = assuan_get_pointer (ctx);
1518 char *keyref_buffer = NULL;
1522 char *opt_algo = NULL;
1526 force = has_option (line, "--force");
1528 if ((s=has_option_name (line, "--timestamp")))
1531 return set_error (GPG_ERR_ASS_PARAMETER, "missing value for option");
1532 timestamp = isotime2epoch (s+1);
1534 return set_error (GPG_ERR_ASS_PARAMETER, "invalid time value");
1539 err = get_option_value (line, "--algo", &opt_algo);
1543 line = skip_options (line);
1546 err = set_error (GPG_ERR_ASS_PARAMETER, "no key number given");
1550 while (*line && !spacep (line))
1554 if ((err = open_card (ctrl)))
1557 card = card_get (ctrl, NULL);
1560 err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1564 keyref = keyref_buffer = xtrystrdup (keyref);
1567 err = gpg_error_from_syserror ();
1571 err = app_genkey (card, ctrl, keyref, opt_algo,
1572 force? APP_GENKEY_FLAG_FORCE : 0,
1573 timestamp, pin_cb, ctx);
1577 xfree (keyref_buffer);
1583 static const char hlp_random[] =
1586 "Get NBYTES of random from the card and send them back as data.\n"
1587 "This usually involves EEPROM write on the card and thus excessive\n"
1588 "use of this command may destroy the card.\n"
1590 "Note, that this function may be even be used on a locked card.";
1592 cmd_random (assuan_context_t ctx, char *line)
1594 ctrl_t ctrl = assuan_get_pointer (ctx);
1597 unsigned char *buffer;
1601 return set_error (GPG_ERR_ASS_PARAMETER,
1602 "number of requested bytes missing");
1603 nbytes = strtoul (line, NULL, 0);
1605 if ((rc = open_card (ctrl)))
1608 card = card_get (ctrl, NULL);
1610 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1612 buffer = xtrymalloc (nbytes);
1616 return out_of_core ();
1619 rc = app_get_challenge (card, ctrl, nbytes, buffer);
1623 rc = assuan_send_data (ctx, buffer, nbytes);
1625 return rc; /* that is already an assuan error code */
1634 static const char hlp_passwd[] =
1635 "PASSWD [--reset] [--nullpin] [--clear] <chvno> [<keygrip>]\n"
1637 "Change the PIN or, if --reset is given, reset the retry counter of\n"
1638 "the card holder verification vector CHVNO. The option --nullpin is\n"
1639 "used for TCOS cards to set the initial PIN. The option --clear clears\n"
1640 "the security status associated with the PIN so that the PIN needs to\n"
1641 "be presented again. The format of CHVNO depends on the card application.\n"
1643 "The target card is the currently selected smartcard, when KEYPGIP is not\n"
1644 "specified. When it is specified, it accesses directly with the KEYGRIP.";
1646 cmd_passwd (assuan_context_t ctx, char *line)
1648 ctrl_t ctrl = assuan_get_pointer (ctx);
1651 unsigned int flags = 0;
1653 const char *keygrip = NULL;
1655 if (has_option (line, "--reset"))
1656 flags |= APP_CHANGE_FLAG_RESET;
1657 if (has_option (line, "--nullpin"))
1658 flags |= APP_CHANGE_FLAG_NULLPIN;
1659 if (has_option (line, "--clear"))
1660 flags |= APP_CHANGE_FLAG_CLEAR;
1662 line = skip_options (line);
1665 return set_error (GPG_ERR_ASS_PARAMETER, "no CHV number given");
1667 while (*line && !spacep (line))
1672 if (strlen (line) == 40)
1675 /* Do not allow other flags aside of --clear. */
1676 if ((flags & APP_CHANGE_FLAG_CLEAR) && (flags & ~APP_CHANGE_FLAG_CLEAR))
1677 return set_error (GPG_ERR_UNSUPPORTED_OPERATION,
1678 "--clear used with other options");
1680 if ((rc = open_card (ctrl)))
1683 card = card_get (ctrl, keygrip);
1685 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1687 chvnostr = xtrystrdup (chvnostr);
1691 return out_of_core ();
1693 rc = app_change_pin (card, ctrl, chvnostr, flags, pin_cb, ctx);
1696 log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1703 static const char hlp_checkpin[] =
1704 "CHECKPIN <idstr>\n"
1706 "Perform a VERIFY operation without doing anything else. This may\n"
1707 "be used to initialize a the PIN cache earlier to long lasting\n"
1708 "operations. Its use is highly application dependent.\n"
1712 " Perform a simple verify operation for CHV1 and CHV2, so that\n"
1713 " further operations won't ask for CHV2 and it is possible to do a\n"
1714 " cheap check on the PIN: If there is something wrong with the PIN\n"
1715 " entry system, only the regular CHV will get blocked and not the\n"
1716 " dangerous CHV3. IDSTR is the usual card's serial number in hex\n"
1717 " notation; an optional fingerprint part will get ignored. There\n"
1718 " is however a special mode if the IDSTR is suffixed with the\n"
1719 " literal string \"[CHV3]\": In this case the Admin PIN is checked\n"
1720 " if and only if the retry counter is still at 3.\n"
1724 " Any of the valid PIN Ids may be used. These are the strings:\n"
1726 " PW1.CH - Global password 1\n"
1727 " PW2.CH - Global password 2\n"
1728 " PW1.CH.SIG - SigG password 1\n"
1729 " PW2.CH.SIG - SigG password 2\n"
1731 " For a definitive list, see the implementation in app-nks.c.\n"
1732 " Note that we call a PW2.* PIN a \"PUK\" despite that since TCOS\n"
1733 " 3.0 they are technically alternative PINs used to mutally\n"
1734 " unblock each other.\n"
1738 " The key's ID string or the PIN's label may be used.";
1740 cmd_checkpin (assuan_context_t ctx, char *line)
1742 ctrl_t ctrl = assuan_get_pointer (ctx);
1747 if ((err = open_card (ctrl)))
1750 card = card_get (ctrl, NULL);
1752 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1754 /* We have to use a copy of the key ID because the function may use
1755 the pin_cb which in turn uses the assuan line buffer and thus
1756 overwriting the original line with the keyid. */
1757 idstr = xtrystrdup (line);
1761 return out_of_core ();
1764 err = app_check_pin (card, ctrl, idstr, pin_cb, ctx);
1768 log_error ("app_check_pin failed: %s\n", gpg_strerror (err));
1774 static const char hlp_lock[] =
1777 "Grant exclusive card access to this session. Note that there is\n"
1778 "no lock counter used and a second lock from the same session will\n"
1779 "be ignored. A single unlock (or RESET) unlocks the session.\n"
1780 "Return GPG_ERR_LOCKED if another session has locked the reader.\n"
1782 "If the option --wait is given the command will wait until a\n"
1783 "lock has been released.";
1785 cmd_lock (assuan_context_t ctx, char *line)
1787 ctrl_t ctrl = assuan_get_pointer (ctx);
1793 if (locked_session != ctrl->server_local)
1794 rc = gpg_error (GPG_ERR_LOCKED);
1797 locked_session = ctrl->server_local;
1800 if (rc && has_option (line, "--wait"))
1803 gnupg_sleep (1); /* Better implement an event mechanism. However,
1804 for card operations this should be
1806 /* Send a progress so that we can detect a connection loss. */
1807 rc = send_status_printf (ctrl, "PROGRESS", "scd_locked . 0 0");
1814 log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
1819 static const char hlp_unlock[] =
1822 "Release exclusive card access.";
1824 cmd_unlock (assuan_context_t ctx, char *line)
1826 ctrl_t ctrl = assuan_get_pointer (ctx);
1833 if (locked_session != ctrl->server_local)
1834 rc = gpg_error (GPG_ERR_LOCKED);
1836 locked_session = NULL;
1839 rc = gpg_error (GPG_ERR_NOT_LOCKED);
1842 log_error ("cmd_unlock failed: %s\n", gpg_strerror (rc));
1847 static const char hlp_getinfo[] =
1850 "Multi purpose command to return certain information. \n"
1851 "Supported values of WHAT are:\n"
1853 " version - Return the version of the program.\n"
1854 " pid - Return the process id of the server.\n"
1855 " socket_name - Return the name of the socket.\n"
1856 " connections - Return number of active connections.\n"
1857 " status - Return the status of the current reader (in the future,\n"
1858 " may also return the status of all readers). The status\n"
1859 " is a list of one-character flags. The following flags\n"
1860 " are currently defined:\n"
1861 " 'u' Usable card present.\n"
1862 " 'r' Card removed. A reset is necessary.\n"
1863 " These flags are exclusive.\n"
1864 " reader_list - Return a list of detected card readers. Does\n"
1865 " currently only work with the internal CCID driver.\n"
1866 " deny_admin - Returns OK if admin commands are not allowed or\n"
1867 " GPG_ERR_GENERAL if admin commands are allowed.\n"
1868 " app_list - Return a list of supported applications. One\n"
1869 " application per line, fields delimited by colons,\n"
1870 " first field is the name.\n"
1871 " card_list - Return a list of serial numbers of all inserted cards.\n"
1872 " active_apps - Return a list of active apps on the current card.\n"
1873 " all_active_apps\n"
1874 " - Return a list of active apps on all inserted cards.\n"
1875 " cmd_has_option CMD OPT\n"
1876 " - Returns OK if command CMD has option OPT.\n"
1877 " apdu_strerror NUMBER\n"
1878 " - Return a string for a status word.\n";
1880 cmd_getinfo (assuan_context_t ctx, char *line)
1885 if (!strcmp (line, "version"))
1888 rc = assuan_send_data (ctx, s, strlen (s));
1890 else if (!strcmp (line, "pid"))
1894 snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1895 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1897 else if (!strncmp (line, "cmd_has_option", 14)
1898 && (line[14] == ' ' || line[14] == '\t' || !line[14]))
1902 while (*line == ' ' || *line == '\t')
1905 rc = gpg_error (GPG_ERR_MISSING_VALUE);
1909 while (*line && (*line != ' ' && *line != '\t'))
1912 rc = gpg_error (GPG_ERR_MISSING_VALUE);
1916 while (*line == ' ' || *line == '\t')
1919 rc = gpg_error (GPG_ERR_MISSING_VALUE);
1923 if (!command_has_option (cmd, cmdopt))
1924 rc = gpg_error (GPG_ERR_FALSE);
1929 else if (!strcmp (line, "socket_name"))
1931 s = scd_get_socket_name ();
1933 rc = assuan_send_data (ctx, s, strlen (s));
1935 rc = gpg_error (GPG_ERR_NO_DATA);
1937 else if (!strcmp (line, "connections"))
1941 snprintf (numbuf, sizeof numbuf, "%d", get_active_connection_count ());
1942 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1944 else if (!strcmp (line, "status"))
1946 ctrl_t ctrl = assuan_get_pointer (ctx);
1949 if (open_card (ctrl))
1954 rc = assuan_send_data (ctx, &flag, 1);
1956 else if (!strcmp (line, "reader_list"))
1959 char *p = ccid_get_reader_list ();
1965 rc = assuan_send_data (ctx, p, strlen (p));
1967 rc = gpg_error (GPG_ERR_NO_DATA);
1970 else if (!strcmp (line, "deny_admin"))
1971 rc = opt.allow_admin? gpg_error (GPG_ERR_GENERAL) : 0;
1972 else if (!strcmp (line, "app_list"))
1974 char *p = get_supported_applications ();
1976 rc = assuan_send_data (ctx, p, strlen (p));
1981 else if (!strcmp (line, "card_list"))
1983 ctrl_t ctrl = assuan_get_pointer (ctx);
1985 rc = app_send_card_list (ctrl);
1987 else if (!strcmp (line, "active_apps"))
1989 ctrl_t ctrl = assuan_get_pointer (ctx);
1990 card_t card = card_get (ctrl, NULL);
1993 rc = 0; /* No current card - no active apps. */
1996 rc = app_send_active_apps (card, ctrl);
2000 else if (!strcmp (line, "all_active_apps"))
2002 ctrl_t ctrl = assuan_get_pointer (ctx);
2003 rc = app_send_active_apps (NULL, ctrl);
2005 else if ((s=has_leading_keyword (line, "apdu_strerror")))
2007 unsigned long ul = strtoul (s, NULL, 0);
2008 s = apdu_strerror (ul);
2009 rc = assuan_send_data (ctx, s, strlen (s));
2012 rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
2017 static const char hlp_restart[] =
2020 "Restart the current connection; this is a kind of warm reset. It\n"
2021 "deletes the context used by this connection but does not send a\n"
2022 "RESET to the card. Thus the card itself won't get reset. \n"
2024 "This is used by gpg-agent to reuse a primary pipe connection and\n"
2025 "may be used by clients to backup from a conflict in the serial\n"
2026 "command; i.e. to select another application.";
2028 cmd_restart (assuan_context_t ctx, char *line)
2030 ctrl_t ctrl = assuan_get_pointer (ctx);
2031 card_t card = card_get (ctrl, NULL);
2037 ctrl->card_ctx = NULL;
2038 ctrl->current_apptype = APPTYPE_NONE;
2039 card_unref_locked (card);
2042 if (locked_session && ctrl->server_local == locked_session)
2044 locked_session = NULL;
2045 log_info ("implicitly unlocking due to RESTART\n");
2051 static const char hlp_disconnect[] =
2054 "Disconnect the card if the backend supports a disconnect operation.";
2056 cmd_disconnect (assuan_context_t ctx, char *line)
2058 ctrl_t ctrl = assuan_get_pointer (ctx);
2063 card = card_get (ctrl, NULL);
2066 apdu_disconnect (card->slot);
2071 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
2076 static const char hlp_apdu[] =
2077 "APDU [--[dump-]atr] [--more] [--exlen[=N]] [hexstring]\n"
2079 "Send an APDU to the current reader. This command bypasses the high\n"
2080 "level functions and sends the data directly to the card. HEXSTRING\n"
2081 "is expected to be a proper APDU. If HEXSTRING is not given no\n"
2082 "commands are set to the card but the command will implicitly check\n"
2083 "whether the card is ready for use. \n"
2085 "Using the option \"--atr\" returns the ATR of the card as a status\n"
2086 "message before any data like this:\n"
2087 " S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1\n"
2089 "Using the option --more handles the card status word MORE_DATA\n"
2090 "(61xx) and concatenates all responses to one block.\n"
2092 "Using the option \"--exlen\" the returned APDU may use extended\n"
2093 "length up to N bytes. If N is not given a default value is used\n"
2094 "(currently 4096).";
2096 cmd_apdu (assuan_context_t ctx, char *line)
2098 ctrl_t ctrl = assuan_get_pointer (ctx);
2101 unsigned char *apdu;
2108 if (has_option (line, "--dump-atr"))
2110 else if (has_option (line, "--data-atr"))
2113 with_atr = has_option (line, "--atr");
2114 handle_more = has_option (line, "--more");
2116 if ((s=has_option_name (line, "--exlen")))
2119 exlen = strtoul (s+1, NULL, 0);
2126 line = skip_options (line);
2128 if ((rc = open_card (ctrl)))
2131 card = card_get (ctrl, NULL);
2133 return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
2141 atr = apdu_get_atr (card->slot, &atrlen);
2142 if (!atr || atrlen > sizeof hexbuf - 2 )
2144 rc = gpg_error (GPG_ERR_INV_CARD);
2149 char *string, *p, *pend;
2151 string = atr_dump (atr, atrlen);
2154 for (rc=0, p=string; !rc && (pend = strchr (p, '\n')); p = pend+1)
2156 rc = assuan_send_data (ctx, p, pend - p + 1);
2158 rc = assuan_send_data (ctx, NULL, 0);
2161 rc = assuan_send_data (ctx, p, strlen (p));
2170 else if (with_atr == 2)
2172 rc = assuan_send_data (ctx, atr, atrlen);
2181 bin2hex (atr, atrlen, hexbuf);
2182 send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
2187 apdu = hex_to_buffer (line, &apdulen);
2190 rc = gpg_error_from_syserror ();
2195 unsigned char *result = NULL;
2198 card->maybe_check_aid = 1;
2199 rc = apdu_send_direct (card->slot, exlen,
2200 apdu, apdulen, handle_more,
2201 NULL, &result, &resultlen);
2204 log_error ("apdu_send_direct failed: %s\n", apdu_strerror (rc));
2205 rc = iso7816_map_sw (rc);
2209 rc = assuan_send_data (ctx, result, resultlen);
2221 static const char hlp_killscd[] =
2226 cmd_killscd (assuan_context_t ctx, char *line)
2228 ctrl_t ctrl = assuan_get_pointer (ctx);
2232 ctrl->server_local->stopme = 1;
2233 assuan_set_flag (ctx, ASSUAN_FORCE_CLOSE, 1);
2238 static const char hlp_keyinfo[] =
2239 "KEYINFO [--list[=auth|encr|sign]] [--data] <keygrip>\n"
2241 "Return information about the key specified by the KEYGRIP. If the\n"
2242 "key is not available GPG_ERR_NOT_FOUND is returned. If the option\n"
2243 "--list is given the keygrip is ignored and information about all\n"
2244 "available keys are returned. Capability may limit the listing.\n"
2245 "Unless --data is given, the\n"
2246 "information is returned as a status line using the format:\n"
2248 " KEYINFO <keygrip> T <serialno> <idstr> <usage>\n"
2250 "KEYGRIP is the keygrip.\n"
2252 "SERIALNO is an ASCII string with the serial number of the\n"
2253 " smartcard. If the serial number is not known a single\n"
2254 " dash '-' is used instead.\n"
2256 "IDSTR is a string used to distinguish keys on a smartcard. If it\n"
2257 " is not known a dash is used instead.\n"
2259 "USAGE is a string of capabilities of the key, 's' for sign, \n"
2260 "'e' for encryption, 'a' for auth, and 'c' for cert. If it is not\n"
2261 "known a dash is used instead.\n"
2263 "More information may be added in the future.";
2265 cmd_keyinfo (assuan_context_t ctx, char *line)
2271 ctrl_t ctrl = assuan_get_pointer (ctx);
2274 opt_data = has_option (line, "--data");
2278 if (has_option (line, "--list"))
2280 else if (has_option (line, "--list=sign"))
2281 cap = GCRY_PK_USAGE_SIGN;
2282 else if (has_option (line, "--list=encr"))
2283 cap = GCRY_PK_USAGE_ENCR;
2284 else if (has_option (line, "--list=auth"))
2285 cap = GCRY_PK_USAGE_AUTH;
2287 keygrip_str = skip_options (line);
2290 action = KEYGRIP_ACTION_SEND_DATA;
2292 action = KEYGRIP_ACTION_WRITE_STATUS;
2294 card = app_do_with_keygrip (ctrl, action, keygrip_str, cap);
2296 if (keygrip_str && !card)
2297 return gpg_error (GPG_ERR_NOT_FOUND);
2302 /* Send a keyinfo string as used by the KEYGRIP_ACTION_SEND_DATA. If
2303 * DATA is true the string is emitted as a data line, else as a status
2306 send_keyinfo (ctrl_t ctrl, int data, const char *keygrip_str,
2307 const char *serialno, const char *idstr, const char *usage)
2310 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2312 string = xtryasprintf ("%s T %s %s %s%s", keygrip_str,
2313 serialno? serialno : "-",
2322 assuan_write_status (ctx, "KEYINFO", string);
2324 assuan_send_data (ctx, string, strlen (string));
2331 static const char hlp_devinfo[] =
2332 "DEVINFO [--watch]\n"
2334 "Return information about devices. If the option --watch is given,\n"
2335 "it keeps reporting status change until it detects no device is\n"
2337 "The information is returned as a status line using the format:\n"
2339 " DEVICE <card_type> <serialno> <app_type>\n"
2341 "CARD_TYPE is the type of the card.\n"
2343 "SERIALNO is an ASCII string with the serial number of the\n"
2344 " smartcard. If the serial number is not known a single\n"
2345 " dash '-' is used instead.\n"
2347 "APP_TYPE is the type of the application.\n"
2349 "More information may be added in the future.";
2351 cmd_devinfo (assuan_context_t ctx, char *line)
2353 ctrl_t ctrl = assuan_get_pointer (ctx);
2354 gpg_error_t err = 0;
2358 if (has_option (line, "--watch"))
2361 ctrl->server_local->watching_status = 1;
2364 /* Firstly, send information of available devices. */
2365 err = app_send_devinfo (ctrl, 0);
2367 /* If not watching, that's all. */
2371 if (err && gpg_err_code (err) != GPG_ERR_NOT_FOUND)
2374 /* Secondly, try to open device(s) available. */
2376 /* Clear the remove flag so that the open_card is able to reread it. */
2377 if (ctrl->server_local->card_removed)
2378 ctrl->server_local->card_removed = 0;
2380 if ((err = open_card (ctrl))
2381 && gpg_err_code (err) != GPG_ERR_ENODEV)
2386 card = card_get (ctrl, NULL);
2389 /* If any, remove reference to the card in CTRL. */
2390 ctrl->card_ctx = NULL;
2391 ctrl->current_apptype = APPTYPE_NONE;
2392 card_unref_locked (card);
2396 /* Then, keep watching the status change. */
2397 err = app_send_devinfo (ctrl, 1);
2399 ctrl->server_local->watching_status = 0;
2403 /* Return true if the command CMD implements the option OPT. */
2405 command_has_option (const char *cmd, const char *cmdopt)
2407 if (!strcmp (cmd, "SERIALNO"))
2409 if (!strcmp (cmdopt, "all"))
2417 /* Tell the assuan library about our commands */
2419 register_commands (assuan_context_t ctx)
2423 assuan_handler_t handler;
2424 const char * const help;
2426 { "SERIALNO", cmd_serialno, hlp_serialno },
2427 { "SWITCHCARD", cmd_switchcard,hlp_switchcard },
2428 { "SWITCHAPP", cmd_switchapp,hlp_switchapp },
2429 { "LEARN", cmd_learn, hlp_learn },
2430 { "READCERT", cmd_readcert, hlp_readcert },
2431 { "READKEY", cmd_readkey, hlp_readkey },
2432 { "SETDATA", cmd_setdata, hlp_setdata },
2433 { "PKSIGN", cmd_pksign, hlp_pksign },
2434 { "PKAUTH", cmd_pkauth, hlp_pkauth },
2435 { "PKDECRYPT", cmd_pkdecrypt,hlp_pkdecrypt },
2438 { "GETATTR", cmd_getattr, hlp_getattr },
2439 { "SETATTR", cmd_setattr, hlp_setattr },
2440 { "WRITECERT", cmd_writecert,hlp_writecert },
2441 { "WRITEKEY", cmd_writekey, hlp_writekey },
2442 { "GENKEY", cmd_genkey, hlp_genkey },
2443 { "RANDOM", cmd_random, hlp_random },
2444 { "PASSWD", cmd_passwd, hlp_passwd },
2445 { "CHECKPIN", cmd_checkpin, hlp_checkpin },
2446 { "LOCK", cmd_lock, hlp_lock },
2447 { "UNLOCK", cmd_unlock, hlp_unlock },
2448 { "GETINFO", cmd_getinfo, hlp_getinfo },
2449 { "RESTART", cmd_restart, hlp_restart },
2450 { "DISCONNECT", cmd_disconnect,hlp_disconnect },
2451 { "APDU", cmd_apdu, hlp_apdu },
2452 { "KILLSCD", cmd_killscd, hlp_killscd },
2453 { "KEYINFO", cmd_keyinfo, hlp_keyinfo },
2454 { "DEVINFO", cmd_devinfo, hlp_devinfo },
2459 for (i=0; table[i].name; i++)
2461 rc = assuan_register_command (ctx, table[i].name, table[i].handler,
2466 assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
2468 assuan_register_reset_notify (ctx, reset_notify);
2469 assuan_register_option_handler (ctx, option_handler);
2474 /* Startup the server. If FD is given as -1 this is simple pipe
2475 server, otherwise it is a regular server. Returns true if there
2476 are no more active asessions. */
2478 scd_command_handler (ctrl_t ctrl, gnupg_fd_t fd)
2481 assuan_context_t ctx = NULL;
2484 rc = assuan_new (&ctx);
2487 log_error ("failed to allocate assuan context: %s\n",
2492 if (fd == GNUPG_INVALID_FD)
2494 assuan_fd_t filedes[2];
2496 filedes[0] = assuan_fdopen (0);
2497 filedes[1] = assuan_fdopen (1);
2498 rc = assuan_init_pipe_server (ctx, filedes);
2502 rc = assuan_init_socket_server (ctx, fd,
2503 ASSUAN_SOCKET_SERVER_ACCEPTED);
2507 log_error ("failed to initialize the server: %s\n",
2511 rc = register_commands (ctx);
2514 log_error ("failed to register commands with Assuan: %s\n",
2518 assuan_set_pointer (ctx, ctrl);
2520 /* Allocate and initialize the server object. Put it into the list
2521 of active sessions. */
2522 ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
2523 ctrl->server_local->next_session = session_list;
2524 session_list = ctrl->server_local;
2525 ctrl->server_local->ctrl_backlink = ctrl;
2526 ctrl->server_local->assuan_ctx = ctx;
2528 /* Command processing loop. */
2531 rc = assuan_accept (ctx);
2538 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
2542 rc = assuan_process (ctx);
2545 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
2550 /* Cleanup. We don't send an explicit reset to the card. */
2551 do_reset (ctrl, 0, 0);
2553 /* Release the server object. */
2554 if (session_list == ctrl->server_local)
2555 session_list = ctrl->server_local->next_session;
2558 struct server_local_s *sl;
2560 for (sl=session_list; sl->next_session; sl = sl->next_session)
2561 if (sl->next_session == ctrl->server_local)
2563 if (!sl->next_session)
2565 sl->next_session = ctrl->server_local->next_session;
2567 stopme = ctrl->server_local->stopme;
2568 xfree (ctrl->server_local);
2569 ctrl->server_local = NULL;
2571 /* Release the Assuan context. */
2572 assuan_release (ctx);
2577 /* If there are no more sessions return true. */
2578 return !session_list;
2582 /* Send a line with status information via assuan and escape all given
2583 buffers. The variable elements are pairs of (char *, size_t),
2584 terminated with a (NULL, 0). */
2586 send_status_info (ctrl_t ctrl, const char *keyword, ...)
2589 const unsigned char *value;
2593 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2595 va_start (arg_ptr, keyword);
2599 while ( (value = va_arg (arg_ptr, const unsigned char *))
2600 && n < DIM (buf)-2 )
2602 valuelen = va_arg (arg_ptr, size_t);
2604 continue; /* empty buffer */
2610 for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
2612 if (*value == '+' || *value == '\"' || *value == '%'
2615 sprintf (p, "%%%02X", *value);
2619 else if (*value == ' ')
2626 assuan_write_status (ctx, keyword, buf);
2632 /* Send a ready formatted status line via assuan. */
2634 send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
2636 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2638 if (strchr (args, '\n'))
2640 log_error ("error: LF detected in status line - not sending\n");
2641 return gpg_error (GPG_ERR_INTERNAL);
2643 return assuan_write_status (ctx, keyword, args);
2647 /* This status functions expects a printf style format string. No
2648 * filtering of the data is done instead the printf formatted data is
2649 * send using assuan_send_status. */
2651 send_status_printf (ctrl_t ctrl, const char *keyword, const char *format, ...)
2655 assuan_context_t ctx;
2657 if (!ctrl || !ctrl->server_local || !(ctx = ctrl->server_local->assuan_ctx))
2660 va_start (arg_ptr, format);
2661 err = vprint_assuan_status (ctx, keyword, format, arg_ptr);
2667 /* Set a gcrypt key for use with the pincache. The key is a random
2668 * key unique for this process and is useless after this process has
2669 * terminated. This way the cached PINs stored in the gpg-agent are
2670 * bound to this specific process. The main purpose of this
2671 * encryption is to hide the PIN in logs of the IPC. */
2673 set_key_for_pincache (gcry_cipher_hd_t hd)
2675 static int initialized;
2676 static unsigned char keybuf[16];
2680 gcry_randomize (keybuf, sizeof keybuf, GCRY_STRONG_RANDOM);
2684 return gcry_cipher_setkey (hd, keybuf, sizeof keybuf);
2688 /* Store the PIN in the PIN cache. The key to identify the PIN
2689 * consists of (SLOT,APPNAME,PINREF). If PIN is NULL the PIN stored
2690 * under the given key is cleared. If APPNAME and PINREF are NULL the
2691 * entire PIN cache for SLOT is cleared. If SLOT is -1 the entire PIN
2692 * cache is cleared. We do no use an scdaemon internal cache but let
2693 * gpg-agent cache it because it is better suited for this. */
2695 pincache_put (ctrl_t ctrl, int slot, const char *appname, const char *pinref,
2696 const char *pin, unsigned int pinlen)
2698 gpg_error_t err = 0;
2699 assuan_context_t ctx;
2701 gcry_cipher_hd_t cipherhd = NULL;
2702 char *pinbuf = NULL;
2703 unsigned char *wrappedkey = NULL;
2704 size_t pinbuflen, wrappedkeylen;
2708 /* No CTRL object provided. We could pick an arbitrary
2709 * connection and send the status to that one. However, such a
2710 * connection is inlikley to wait for a respinse from use and
2711 * thus it would at best be read as a response to the next
2712 * command send to us. That is not good because it may clog up
2713 * our connection. Thus we better don't do that. A better will
2714 * be to queue this up and let the agent poll for general status
2716 /* struct server_local_s *sl; */
2717 /* for (sl=session_list; sl; sl = sl->next_session) */
2718 /* if (sl->ctrl_backlink && sl->ctrl_backlink->server_local */
2719 /* && sl->ctrl_backlink->server_local->assuan_ctx) */
2721 /* ctrl = sl->ctrl_backlink; */
2726 if (!ctrl || !ctrl->server_local || !(ctx=ctrl->server_local->assuan_ctx))
2729 return; /* Ignore an empty PIN. */
2731 snprintf (line, sizeof line, "%d/%s/%s ",
2732 slot, appname? appname:"", pinref? pinref:"");
2734 /* Without an APPNAME etc or without a PIN we clear the cache and
2735 * thus there is no need to send the pin - even if the caller
2736 * accidentally passed a pin. */
2737 if (pin && slot != -1 && appname && pinref)
2739 /* FIXME: Replace this by OCB mode and use the cache key as
2740 * additional data. */
2741 /* Pad with zeroes (AESWRAP requires multiples of 64 bit but
2742 * at least 128 bit data). */
2743 pinbuflen = pinlen + 8 - (pinlen % 8);
2746 pinbuf = xtrycalloc_secure (1, pinbuflen);
2749 err = gpg_error_from_syserror ();
2752 memcpy (pinbuf, pin, pinlen);
2756 err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
2757 GCRY_CIPHER_MODE_AESWRAP, 0);
2759 err = set_key_for_pincache (cipherhd);
2763 wrappedkeylen = pinlen + 8;
2764 wrappedkey = xtrymalloc (wrappedkeylen);
2767 err = gpg_error_from_syserror ();
2771 err = gcry_cipher_encrypt (cipherhd, wrappedkey, wrappedkeylen,
2775 gcry_cipher_close (cipherhd);
2777 if (strlen (line) + 2*wrappedkeylen + 1 >= sizeof line)
2779 log_error ("%s: PIN or pinref string too long - ignored", __func__);
2782 bin2hex (wrappedkey, wrappedkeylen, line + strlen (line));
2785 send_status_direct (ctrl, "PINCACHE_PUT", line);
2790 gcry_cipher_close (cipherhd);
2792 log_error ("%s: error caching PIN: %s\n", __func__, gpg_strerror (err));
2796 /* Ask the agent for a cached PIN for the tuple (SLOT,APPNAME,PINREF).
2797 * Returns on success and stores the PIN at R_PIN; the caller needs to
2798 * wipe(!) and then free that value. On error NULL is stored at
2799 * R_PIN and an error code returned. Common error codes are:
2800 * GPG_ERR_NOT_SUPPORTED - Client does not support the PIN cache
2801 * GPG_ERR_NO_DATA - No PIN cached for the given key tuple
2804 pincache_get (ctrl_t ctrl, int slot, const char *appname, const char *pinref,
2808 assuan_context_t ctx;
2810 unsigned char *value = NULL;
2812 unsigned char *wrappedkey = NULL;
2813 size_t wrappedkeylen;
2814 gcry_cipher_hd_t cipherhd = NULL;
2816 if (slot == -1 || !appname || !pinref || !r_pin)
2818 err = gpg_error (GPG_ERR_INV_ARG);
2821 if (!ctrl || !ctrl->server_local || !(ctx = ctrl->server_local->assuan_ctx))
2823 err = gpg_error (GPG_ERR_USE_CONDITIONS);
2824 log_error ("%s: called w/o assuan context\n", __func__);
2828 snprintf (command, sizeof command, "PINCACHE_GET %d/%s/%s",
2829 slot, appname? appname:"", pinref? pinref:"");
2831 /* Limit the inquire to something reasonable. The 32 extra bytes
2832 * are a guessed size for padding etc. */
2833 err = assuan_inquire (ctx, command, &wrappedkey, &wrappedkeylen,
2835 if (gpg_err_code (err) == GPG_ERR_ASS_CANCELED)
2837 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
2838 log_info ("caller does not feature a PIN cache");
2843 log_error ("%s: sending PINCACHE_GET to caller failed: %s\n",
2844 __func__, gpg_strerror (err));
2847 if (!wrappedkey || !wrappedkeylen)
2849 err = gpg_error (GPG_ERR_NOT_FOUND);
2853 /* Convert to hex to binary and store it in (wrappedkey, wrappedkeylen). */
2854 if (!hex2str (wrappedkey, wrappedkey, wrappedkeylen, &wrappedkeylen))
2856 err = gpg_error_from_syserror ();
2857 log_error ("%s: caller returned invalid hex string: %s\n",
2858 __func__, gpg_strerror (err));
2862 if (!wrappedkey || wrappedkeylen < 24)
2864 err = gpg_error (GPG_ERR_INV_LENGTH); /* too short cryptogram */
2868 valuelen = wrappedkeylen - 8;
2869 value = xtrymalloc_secure (valuelen);
2872 err = gpg_error_from_syserror ();
2876 err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
2877 GCRY_CIPHER_MODE_AESWRAP, 0);
2879 err = set_key_for_pincache (cipherhd);
2883 err = gcry_cipher_decrypt (cipherhd, value, valuelen,
2884 wrappedkey, wrappedkeylen);
2887 log_error ("%s: cached value could not be decrypted: %s\n",
2888 __func__, gpg_strerror (err));
2896 gcry_cipher_close (cipherhd);
2904 popup_prompt (void *opaque, int on)
2906 ctrl_t ctrl = opaque;
2910 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2916 unsigned char *value;
2920 cmd = "POPUPPINPADPROMPT --ack";
2922 cmd = "DISMISSPINPADPROMPT";
2923 err = assuan_inquire (ctx, cmd, &value, &valuelen, 100);
2932 * Helper to send the clients a status change notification.
2934 * When it's removal of card, this function also clean up all
2935 * references by ctrl->card_ctx of all sessions.
2937 * Note that this function assumes that all accesses to cards and
2938 * applications are locked. By the mrsw-lock, it is guaranteed that
2939 * no card/app is accessed, when this function is called..
2942 send_client_notifications (card_t card, int removal)
2946 #ifdef HAVE_W32_SYSTEM
2954 struct server_local_s *sl;
2956 for (sl=session_list; sl; sl = sl->next_session)
2958 if (sl->watching_status)
2961 assuan_write_status (sl->assuan_ctx, "DEVINFO_STATUS", "removal");
2963 assuan_write_status (sl->assuan_ctx, "DEVINFO_STATUS", "new");
2966 if (sl->ctrl_backlink && sl->ctrl_backlink->card_ctx == card)
2969 #ifdef HAVE_W32_SYSTEM
2977 sl->ctrl_backlink->card_ctx = NULL;
2978 sl->ctrl_backlink->current_apptype = APPTYPE_NONE;
2979 sl->card_removed = 1;
2980 card_unref_locked (card);
2983 if (!sl->event_signal || !sl->assuan_ctx)
2986 pid = assuan_get_pid (sl->assuan_ctx);
2988 #ifdef HAVE_W32_SYSTEM
2989 handle = sl->event_signal;
2990 for (kidx=0; kidx < killidx; kidx++)
2991 if (killed[kidx].pid == pid
2992 && killed[kidx].handle == handle)
2995 log_info ("event %p (%p) already triggered for client %d\n",
2996 sl->event_signal, handle, (int)pid);
2999 log_info ("triggering event %p (%p) for client %d\n",
3000 sl->event_signal, handle, (int)pid);
3001 if (!SetEvent (handle))
3002 log_error ("SetEvent(%p) failed: %s\n",
3003 sl->event_signal, w32_strerror (-1));
3004 if (killidx < DIM (killed))
3006 killed[killidx].pid = pid;
3007 killed[killidx].handle = handle;
3011 #else /*!HAVE_W32_SYSTEM*/
3012 signo = sl->event_signal;
3014 if (pid != (pid_t)(-1) && pid && signo > 0)
3016 for (kidx=0; kidx < killidx; kidx++)
3017 if (killed[kidx].pid == pid
3018 && killed[kidx].signo == signo)
3021 log_info ("signal %d already sent to client %d\n",
3025 log_info ("sending signal %d to client %d\n",
3028 if (killidx < DIM (killed))
3030 killed[killidx].pid = pid;
3031 killed[killidx].signo = signo;
3036 #endif /*!HAVE_W32_SYSTEM*/