1 /* command.c - SCdaemon command handler
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005,
3 * 2007, 2008, 2009 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 <http://www.gnu.org/licenses/>.
36 #include "app-common.h"
37 #include "apdu.h" /* Required for apdu_*_reader (). */
40 #include "ccid-driver.h"
43 /* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */
44 #define MAXLEN_PIN 100
46 /* Maximum allowed size of key data as used in inquiries. */
47 #define MAXLEN_KEYDATA 4096
49 /* Maximum allowed size of certificate data as used in inquiries. */
50 #define MAXLEN_CERTDATA 16384
53 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
56 /* Macro to flag a removed card. ENODEV is also tested to catch teh
57 case of a removed reader. */
58 #define TEST_CARD_REMOVAL(c,r) \
61 if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \
62 || gpg_err_code (_r) == GPG_ERR_CARD_REMOVED \
63 || gpg_err_code (_r) == GPG_ERR_ENODEV ) \
64 update_card_removed ((c)->reader_slot, 1); \
67 #define IS_LOCKED(c) \
68 (locked_session && locked_session != (c)->server_local \
69 && (c)->reader_slot != -1 && locked_session->ctrl_backlink \
70 && (c)->reader_slot == locked_session->ctrl_backlink->reader_slot)
73 /* Flag indicating that the reader has been disabled. */
74 static int reader_disabled;
77 /* This structure is used to keep track of open readers (slots). */
80 int valid; /* True if the other objects are valid. */
81 int slot; /* Slot number of the reader or -1 if not open. */
83 int reset_failed; /* A reset failed. */
85 int any; /* Flag indicating whether any status check has been
86 done. This is set once to indicate that the status
87 tracking for the slot has been initialized. */
88 unsigned int status; /* Last status of the slot. */
89 unsigned int changed; /* Last change counter of the slot. */
93 /* Data used to associate an Assuan context with local server data.
94 This object describes the local properties of one session. */
97 /* We keep a list of all active sessions with the anchor at
98 SESSION_LIST (see below). This field is used for linking. */
99 struct server_local_s *next_session;
101 /* This object is usually assigned to a CTRL object (which is
102 globally visible). While enumerating all sessions we sometimes
103 need to access data of the CTRL object; thus we keep a
105 ctrl_t ctrl_backlink;
107 /* The Assuan context used by this session/server. */
108 assuan_context_t assuan_ctx;
110 #ifdef HAVE_W32_SYSTEM
111 unsigned long event_signal; /* Or 0 if not used. */
113 int event_signal; /* Or 0 if not used. */
116 /* True if the card has been removed and a reset is required to
117 continue operation. */
120 /* Flag indicating that the application context needs to be released
121 at the next opportunity. */
122 int app_ctx_marked_for_release;
124 /* A disconnect command has been sent. */
125 int disconnect_allowed;
127 /* If set to true we will be terminate ourself at the end of the
134 /* The table with information on all used slots. FIXME: This is a
135 different slot number than the one used by the APDU layer, and
136 should be renamed. */
137 static struct slot_status_s slot_table[10];
140 /* To keep track of all running sessions, we link all active server
141 contexts and the anchor in this variable. */
142 static struct server_local_s *session_list;
144 /* If a session has been locked we store a link to its server object
146 static struct server_local_s *locked_session;
148 /* While doing a reset we need to make sure that the ticker does not
149 call scd_update_reader_status_file while we are using it. */
150 static pth_mutex_t status_file_update_lock;
153 /*-- Local prototypes --*/
154 static void update_reader_status_file (int set_card_removed_flag);
159 /* This function must be called once to initialize this module. This
160 has to be done before a second thread is spawned. We can't do the
161 static initialization because Pth emulation code might not be able
162 to do a static init; in particular, it is not possible for W32. */
164 initialize_module_command (void)
166 static int initialized;
170 if (pth_mutex_init (&status_file_update_lock))
176 /* Update the CARD_REMOVED element of all sessions using the reader
177 given by SLOT to VALUE. */
179 update_card_removed (int slot, int value)
181 struct server_local_s *sl;
183 for (sl=session_list; sl; sl = sl->next_session)
184 if (sl->ctrl_backlink
185 && sl->ctrl_backlink->reader_slot == slot)
187 sl->card_removed = value;
189 /* Let the card application layer know about the removal. */
191 application_notify_card_reset (slot);
196 /* Check whether the option NAME appears in LINE. Returns 1 or 0. */
198 has_option (const char *line, const char *name)
201 int n = strlen (name);
203 s = strstr (line, name);
204 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
207 /* Same as has_option but does only test for the name of the option
208 and ignores an argument, i.e. with NAME being "--hash" it would
209 return a pointer for "--hash" as well as for "--hash=foo". If
210 there is no such option NULL is returned. The pointer returned
211 points right behind the option name, this may be an equal sign, Nul
214 has_option_name (const char *line, const char *name)
217 int n = strlen (name);
219 s = strstr (line, name);
220 return (s && (s == line || spacep (s-1))
221 && (!s[n] || spacep (s+n) || s[n] == '=')) ? (s+n) : NULL;
225 /* Skip over options. It is assumed that leading spaces have been
226 removed (this is the case for lines passed to a handler from
227 assuan). Blanks after the options are also removed. */
229 skip_options (char *line)
231 while ( *line == '-' && line[1] == '-' )
233 while (*line && !spacep (line))
235 while (spacep (line))
243 /* Convert the STRING into a newly allocated buffer while translating
244 the hex numbers. Stops at the first invalid character. Blanks and
245 colons are allowed to separate the hex digits. Returns NULL on
246 error or a newly malloced buffer and its length in LENGTH. */
247 static unsigned char *
248 hex_to_buffer (const char *string, size_t *r_length)
250 unsigned char *buffer;
254 buffer = xtrymalloc (strlen (string)+1);
257 for (s=string, n=0; *s; s++)
259 if (spacep (s) || *s == ':')
261 if (hexdigitp (s) && hexdigitp (s+1))
263 buffer[n++] = xtoi_2 (s);
275 /* Reset the card and free the application context. With SEND_RESET
276 set to true actually send a RESET to the reader; this is the normal
277 way of calling the function. */
279 do_reset (ctrl_t ctrl, int send_reset)
281 int slot = ctrl->reader_slot;
283 if (!(slot == -1 || (slot >= 0 && slot < DIM(slot_table))))
286 /* If there is an active application, release it. Tell all other
287 sessions using the same application to release the
291 release_application (ctrl->app_ctx);
292 ctrl->app_ctx = NULL;
295 struct server_local_s *sl;
297 for (sl=session_list; sl; sl = sl->next_session)
298 if (sl->ctrl_backlink
299 && sl->ctrl_backlink->reader_slot == slot)
301 sl->app_ctx_marked_for_release = 1;
306 /* If we want a real reset for the card, send the reset APDU and
307 tell the application layer about it. */
308 if (slot != -1 && send_reset && !IS_LOCKED (ctrl) )
310 if (apdu_reset (slot))
312 slot_table[slot].valid = 0;
314 application_notify_card_reset (slot);
317 /* If we hold a lock, unlock now. */
318 if (locked_session && ctrl->server_local == locked_session)
320 locked_session = NULL;
321 log_info ("implicitly unlocking due to RESET\n");
324 /* Reset the card removed flag for the current reader. We need to
325 take the lock here so that the ticker thread won't concurrently
326 try to update the file. Calling update_reader_status_file is
327 required to get hold of the new status of the card in the slot
329 if (!pth_mutex_acquire (&status_file_update_lock, 0, NULL))
331 log_error ("failed to acquire status_fle_update lock\n");
332 ctrl->reader_slot = -1;
335 update_reader_status_file (0); /* Update slot status table. */
336 update_card_removed (slot, 0); /* Clear card_removed flag. */
337 if (!pth_mutex_release (&status_file_update_lock))
338 log_error ("failed to release status_file_update lock\n");
340 /* Do this last, so that the update_card_removed above does its job. */
341 ctrl->reader_slot = -1;
346 reset_notify (assuan_context_t ctx, char *line)
348 ctrl_t ctrl = assuan_get_pointer (ctx);
358 option_handler (assuan_context_t ctx, const char *key, const char *value)
360 ctrl_t ctrl = assuan_get_pointer (ctx);
362 if (!strcmp (key, "event-signal"))
364 /* A value of 0 is allowed to reset the event signal. */
365 #ifdef HAVE_W32_SYSTEM
367 return gpg_error (GPG_ERR_ASS_PARAMETER);
368 ctrl->server_local->event_signal = strtoul (value, NULL, 16);
370 int i = *value? atoi (value) : -1;
372 return gpg_error (GPG_ERR_ASS_PARAMETER);
373 ctrl->server_local->event_signal = i;
381 /* Return the slot of the current reader or open the reader if no
382 other sessions are using a reader. Note, that we currently support
383 only one reader but most of the code (except for this function)
384 should be able to cope with several readers. */
386 get_reader_slot (void)
388 struct slot_status_s *ss;
390 ss = &slot_table[0]; /* One reader for now. */
392 /* Initialize the item if needed. */
399 /* Try to open the reader. */
403 ss->slot = apdu_open_reader (opt.reader_port, &no_service_flag);
405 /* If we still don't have a slot, we have no readers.
406 Invalidate for now until a reader is attached. */
414 log_info ("no card services - disabling scdaemon\n");
419 /* Return the slot_table index. */
423 /* If the card has not yet been opened, do it. Note that this
424 function returns an Assuan error, so don't map the error a second
427 open_card (ctrl_t ctrl, const char *apptype)
433 return gpg_error (GPG_ERR_NOT_OPERATIONAL);
435 /* If we ever got a card not present error code, return that. Only
436 the SERIALNO command and a reset are able to clear from that
438 if (ctrl->server_local->card_removed)
439 return gpg_error (GPG_ERR_CARD_REMOVED);
441 if ( IS_LOCKED (ctrl) )
442 return gpg_error (GPG_ERR_LOCKED);
444 /* If the application has been marked for release do it now. We
445 can't do it immediately in do_reset because the application may
447 if (ctrl->server_local->app_ctx_marked_for_release)
449 ctrl->server_local->app_ctx_marked_for_release = 0;
450 release_application (ctrl->app_ctx);
451 ctrl->app_ctx = NULL;
454 /* If we are already initialized for one specific application we
455 need to check that the client didn't requested a specific
456 application different from the one in use before we continue. */
458 return check_application_conflict (ctrl, apptype);
460 /* Setup the slot and select the application. */
461 if (ctrl->reader_slot != -1)
462 slot = ctrl->reader_slot;
464 slot = get_reader_slot ();
465 ctrl->reader_slot = slot;
467 err = gpg_error (reader_disabled? GPG_ERR_NOT_OPERATIONAL: GPG_ERR_CARD);
470 /* Fixme: We should move the apdu_connect call to
471 select_application. */
474 ctrl->server_local->disconnect_allowed = 0;
475 sw = apdu_connect (slot);
476 if (sw && sw != SW_HOST_ALREADY_CONNECTED)
478 if (sw == SW_HOST_NO_CARD)
479 err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
481 err = gpg_error (GPG_ERR_CARD);
484 err = select_application (ctrl, slot, apptype, &ctrl->app_ctx);
487 TEST_CARD_REMOVAL (ctrl, err);
492 static const char hlp_serialno[] =
493 "SERIALNO [<apptype>]\n"
495 "Return the serial number of the card using a status reponse. This\n"
496 "function should be used to check for the presence of a card.\n"
498 "If APPTYPE is given, an application of that type is selected and an\n"
499 "error is returned if the application is not supported or available.\n"
500 "The default is to auto-select the application using a hardwired\n"
501 "preference system. Note, that a future extension to this function\n"
502 "may allow to specify a list and order of applications to try.\n"
504 "This function is special in that it can be used to reset the card.\n"
505 "Most other functions will return an error when a card change has\n"
506 "been detected and the use of this function is therefore required.\n"
508 "Background: We want to keep the client clear of handling card\n"
509 "changes between operations; i.e. the client can assume that all\n"
510 "operations are done on the same card unless he calls this function.";
512 cmd_serialno (assuan_context_t ctx, char *line)
514 ctrl_t ctrl = assuan_get_pointer (ctx);
516 char *serial_and_stamp;
520 /* Clear the remove flag so that the open_card is able to reread it. */
521 if (!reader_disabled && ctrl->server_local->card_removed)
523 if ( IS_LOCKED (ctrl) )
524 return gpg_error (GPG_ERR_LOCKED);
528 if ((rc = open_card (ctrl, *line? line:NULL)))
531 rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
535 rc = estream_asprintf (&serial_and_stamp, "%s %lu",
536 serial, (unsigned long)stamp);
539 return out_of_core ();
541 assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
542 xfree (serial_and_stamp);
547 static const char hlp_learn[] =
548 "LEARN [--force] [--keypairinfo]\n"
550 "Learn all useful information of the currently inserted card. When\n"
551 "used without the force options, the command might do an INQUIRE\n"
554 " INQUIRE KNOWNCARDP <hexstring_with_serialNumber> <timestamp>\n"
556 "The client should just send an \"END\" if the processing should go on\n"
557 "or a \"CANCEL\" to force the function to terminate with a Cancel\n"
560 "With the option --keypairinfo only KEYPARIINFO lstatus lines are\n"
563 "The response of this command is a list of status lines formatted as\n"
566 " S APPTYPE <apptype>\n"
568 "This returns the type of the application, currently the strings:\n"
570 " P15 = PKCS-15 structure used\n"
571 " DINSIG = DIN SIG\n"
572 " OPENPGP = OpenPGP card\n"
573 " NKS = NetKey card\n"
575 "are implemented. These strings are aliases for the AID\n"
577 " S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id>\n"
579 "If there is no certificate yet stored on the card a single 'X' is\n"
580 "returned as the keygrip. In addition to the keypair info, information\n"
581 "about all certificates stored on the card is also returned:\n"
583 " S CERTINFO <certtype> <hexstring_with_id>\n"
585 "Where CERTTYPE is a number indicating the type of certificate:\n"
587 " 100 := Regular X.509 cert\n"
588 " 101 := Trusted X.509 cert\n"
589 " 102 := Useful X.509 cert\n"
590 " 110 := Root CA cert in a special format (e.g. DINSIG)\n"
591 " 111 := Root CA cert as standard X509 cert.\n"
593 "For certain cards, more information will be returned:\n"
595 " S KEY-FPR <no> <hexstring>\n"
597 "For OpenPGP cards this returns the stored fingerprints of the\n"
598 "keys. This can be used check whether a key is available on the\n"
599 "card. NO may be 1, 2 or 3.\n"
601 " S CA-FPR <no> <hexstring>\n"
603 "Similar to above, these are the fingerprints of keys assumed to be\n"
604 "ultimately trusted.\n"
606 " S DISP-NAME <name_of_card_holder>\n"
608 "The name of the card holder as stored on the card; percent\n"
609 "escaping takes place, spaces are encoded as '+'\n"
611 " S PUBKEY-URL <url>\n"
613 "The URL to be used for locating the entire public key.\n"
615 "Note, that this function may even be used on a locked card.";
617 cmd_learn (assuan_context_t ctx, char *line)
619 ctrl_t ctrl = assuan_get_pointer (ctx);
621 int only_keypairinfo = has_option (line, "--keypairinfo");
623 if ((rc = open_card (ctrl, NULL)))
626 /* Unless the force option is used we try a shortcut by identifying
627 the card using a serial number and inquiring the client with
628 that. The client may choose to cancel the operation if he already
629 knows about this card */
630 if (!only_keypairinfo)
632 char *serial_and_stamp;
636 rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
639 rc = estream_asprintf (&serial_and_stamp, "%s %lu",
640 serial, (unsigned long)stamp);
643 return out_of_core ();
645 assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
647 if (!has_option (line, "--force"))
651 rc = estream_asprintf (&command, "KNOWNCARDP %s", serial_and_stamp);
654 xfree (serial_and_stamp);
655 return out_of_core ();
658 rc = assuan_inquire (ctx, command, NULL, NULL, 0);
662 if (gpg_err_code (rc) != GPG_ERR_ASS_CANCELED)
663 log_error ("inquire KNOWNCARDP failed: %s\n",
665 xfree (serial_and_stamp);
668 /* Not canceled, so we have to proceeed. */
670 xfree (serial_and_stamp);
673 /* Let the application print out its collection of useful status
676 rc = app_write_learn_status (ctrl->app_ctx, ctrl, only_keypairinfo);
678 TEST_CARD_REMOVAL (ctrl, rc);
684 static const char hlp_readcert[] =
685 "READCERT <hexified_certid>|<keyid>\n"
687 "Note, that this function may even be used on a locked card.";
689 cmd_readcert (assuan_context_t ctx, char *line)
691 ctrl_t ctrl = assuan_get_pointer (ctx);
696 if ((rc = open_card (ctrl, NULL)))
699 line = xstrdup (line); /* Need a copy of the line. */
700 rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
702 log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
707 rc = assuan_send_data (ctx, cert, ncert);
713 TEST_CARD_REMOVAL (ctrl, rc);
718 static const char hlp_readkey[] =
721 "Return the public key for the given cert or key ID as a standard\n"
724 "Note, that this function may even be used on a locked card.";
726 cmd_readkey (assuan_context_t ctx, char *line)
728 ctrl_t ctrl = assuan_get_pointer (ctx);
730 unsigned char *cert = NULL;
732 ksba_cert_t kc = NULL;
737 if ((rc = open_card (ctrl, NULL)))
740 line = xstrdup (line); /* Need a copy of the line. */
741 /* If the application supports the READKEY function we use that.
742 Otherwise we use the old way by extracting it from the
744 rc = app_readkey (ctrl->app_ctx, line, &pk, &pklen);
746 { /* Yeah, got that key - send it back. */
747 rc = assuan_send_data (ctx, pk, pklen);
754 if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION)
755 log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
758 rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
760 log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
767 rc = ksba_cert_new (&kc);
773 rc = ksba_cert_init_from_mem (kc, cert, ncert);
776 log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
780 p = ksba_cert_get_public_key (kc);
783 rc = gpg_error (GPG_ERR_NO_PUBKEY);
787 n = gcry_sexp_canon_len (p, 0, NULL, NULL);
788 rc = assuan_send_data (ctx, p, n);
793 ksba_cert_release (kc);
795 TEST_CARD_REMOVAL (ctrl, rc);
801 static const char hlp_setdata[] =
802 "SETDATA <hexstring> \n"
804 "The client should use this command to tell us the data he want to sign.";
806 cmd_setdata (assuan_context_t ctx, char *line)
808 ctrl_t ctrl = assuan_get_pointer (ctx);
813 if (locked_session && locked_session != ctrl->server_local)
814 return gpg_error (GPG_ERR_LOCKED);
816 /* Parse the hexstring. */
817 for (p=line,n=0; hexdigitp (p); p++, n++)
820 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
822 return set_error (GPG_ERR_ASS_PARAMETER, "no data given");
824 return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
826 buf = xtrymalloc (n);
828 return out_of_core ();
830 ctrl->in_data.value = buf;
831 ctrl->in_data.valuelen = n;
832 for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++)
840 pin_cb (void *opaque, const char *info, char **retstr)
842 assuan_context_t ctx = opaque;
845 unsigned char *value;
850 /* We prompt for keypad entry. To make sure that the popup has
851 been show we use an inquire and not just a status message.
852 We ignore any value returned. */
855 log_debug ("prompting for keypad entry '%s'\n", info);
856 rc = estream_asprintf (&command, "POPUPKEYPADPROMPT %s", info);
858 return gpg_error (gpg_err_code_from_errno (errno));
859 rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
864 log_debug ("dismiss keypad entry prompt\n");
865 rc = assuan_inquire (ctx, "DISMISSKEYPADPROMPT",
866 &value, &valuelen, MAXLEN_PIN);
874 log_debug ("asking for PIN '%s'\n", info);
876 rc = estream_asprintf (&command, "NEEDPIN %s", info);
878 return gpg_error (gpg_err_code_from_errno (errno));
880 /* Fixme: Write an inquire function which returns the result in
881 secure memory and check all further handling of the PIN. */
882 rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
887 if (!valuelen || value[valuelen-1])
889 /* We require that the returned value is an UTF-8 string */
891 return gpg_error (GPG_ERR_INV_RESPONSE);
893 *retstr = (char*)value;
898 static const char hlp_pksign[] =
899 "PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5]] <hexified_id>\n"
901 "The --hash option is optional; the default is SHA1.";
903 cmd_pksign (assuan_context_t ctx, char *line)
905 ctrl_t ctrl = assuan_get_pointer (ctx);
907 unsigned char *outdata;
912 if (has_option (line, "--hash=rmd160"))
913 hash_algo = GCRY_MD_RMD160;
914 else if (has_option (line, "--hash=sha1"))
915 hash_algo = GCRY_MD_SHA1;
916 else if (has_option (line, "--hash=sha224"))
917 hash_algo = GCRY_MD_SHA224;
918 else if (has_option (line, "--hash=sha256"))
919 hash_algo = GCRY_MD_SHA256;
920 else if (has_option (line, "--hash=sha384"))
921 hash_algo = GCRY_MD_SHA384;
922 else if (has_option (line, "--hash=sha512"))
923 hash_algo = GCRY_MD_SHA512;
924 else if (has_option (line, "--hash=md5"))
925 hash_algo = GCRY_MD_MD5;
926 else if (!strstr (line, "--"))
927 hash_algo = GCRY_MD_SHA1;
929 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
931 line = skip_options (line);
933 if ( IS_LOCKED (ctrl) )
934 return gpg_error (GPG_ERR_LOCKED);
936 if ((rc = open_card (ctrl, NULL)))
939 /* We have to use a copy of the key ID because the function may use
940 the pin_cb which in turn uses the assuan line buffer and thus
941 overwriting the original line with the keyid */
942 keyidstr = xtrystrdup (line);
944 return out_of_core ();
946 rc = app_sign (ctrl->app_ctx,
949 ctrl->in_data.value, ctrl->in_data.valuelen,
950 &outdata, &outdatalen);
955 log_error ("app_sign failed: %s\n", gpg_strerror (rc));
959 rc = assuan_send_data (ctx, outdata, outdatalen);
962 return rc; /* that is already an assuan error code */
965 TEST_CARD_REMOVAL (ctrl, rc);
970 static const char hlp_pkauth[] =
971 "PKAUTH <hexified_id>";
973 cmd_pkauth (assuan_context_t ctx, char *line)
975 ctrl_t ctrl = assuan_get_pointer (ctx);
977 unsigned char *outdata;
981 if ( IS_LOCKED (ctrl) )
982 return gpg_error (GPG_ERR_LOCKED);
984 if ((rc = open_card (ctrl, NULL)))
988 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
990 /* We have to use a copy of the key ID because the function may use
991 the pin_cb which in turn uses the assuan line buffer and thus
992 overwriting the original line with the keyid */
993 keyidstr = xtrystrdup (line);
995 return out_of_core ();
997 rc = app_auth (ctrl->app_ctx,
1000 ctrl->in_data.value, ctrl->in_data.valuelen,
1001 &outdata, &outdatalen);
1005 log_error ("app_auth failed: %s\n", gpg_strerror (rc));
1009 rc = assuan_send_data (ctx, outdata, outdatalen);
1012 return rc; /* that is already an assuan error code */
1015 TEST_CARD_REMOVAL (ctrl, rc);
1020 static const char hlp_pkdecrypt[] =
1021 "PKDECRYPT <hexified_id>";
1023 cmd_pkdecrypt (assuan_context_t ctx, char *line)
1025 ctrl_t ctrl = assuan_get_pointer (ctx);
1027 unsigned char *outdata;
1031 if ( IS_LOCKED (ctrl) )
1032 return gpg_error (GPG_ERR_LOCKED);
1034 if ((rc = open_card (ctrl, NULL)))
1037 keyidstr = xtrystrdup (line);
1039 return out_of_core ();
1040 rc = app_decipher (ctrl->app_ctx,
1043 ctrl->in_data.value, ctrl->in_data.valuelen,
1044 &outdata, &outdatalen);
1049 log_error ("app_decipher failed: %s\n", gpg_strerror (rc));
1053 rc = assuan_send_data (ctx, outdata, outdatalen);
1056 return rc; /* that is already an assuan error code */
1059 TEST_CARD_REMOVAL (ctrl, rc);
1064 static const char hlp_getattr[] =
1067 "This command is used to retrieve data from a smartcard. The\n"
1068 "allowed names depend on the currently selected smartcard\n"
1069 "application. NAME must be percent and '+' escaped. The value is\n"
1070 "returned through status message, see the LEARN command for details.\n"
1072 "However, the current implementation assumes that Name is not escaped;\n"
1073 "this works as long as noone uses arbitrary escaping. \n"
1075 "Note, that this function may even be used on a locked card.";
1077 cmd_getattr (assuan_context_t ctx, char *line)
1079 ctrl_t ctrl = assuan_get_pointer (ctx);
1081 const char *keyword;
1083 if ((rc = open_card (ctrl, NULL)))
1087 for (; *line && !spacep (line); line++)
1092 /* (We ignore any garbage for now.) */
1094 /* FIXME: Applications should not return sensitive data if the card
1096 rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
1098 TEST_CARD_REMOVAL (ctrl, rc);
1103 static const char hlp_setattr[] =
1104 "SETATTR <name> <value> \n"
1106 "This command is used to store data on a a smartcard. The allowed\n"
1107 "names and values are depend on the currently selected smartcard\n"
1108 "application. NAME and VALUE must be percent and '+' escaped.\n"
1110 "However, the current implementation assumes that NAME is not\n"
1111 "escaped; this works as long as noone uses arbitrary escaping.\n"
1113 "A PIN will be requested for most NAMEs. See the corresponding\n"
1114 "setattr function of the actually used application (app-*.c) for\n"
1117 cmd_setattr (assuan_context_t ctx, char *orig_line)
1119 ctrl_t ctrl = assuan_get_pointer (ctx);
1124 char *line, *linebuf;
1126 if ( IS_LOCKED (ctrl) )
1127 return gpg_error (GPG_ERR_LOCKED);
1129 if ((rc = open_card (ctrl, NULL)))
1132 /* We need to use a copy of LINE, because PIN_CB uses the same
1133 context and thus reuses the Assuan provided LINE. */
1134 line = linebuf = xtrystrdup (orig_line);
1136 return out_of_core ();
1139 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
1143 while (spacep (line))
1145 nbytes = percent_plus_unescape_inplace (line, 0);
1147 rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx,
1148 (const unsigned char*)line, nbytes);
1151 TEST_CARD_REMOVAL (ctrl, rc);
1156 static const char hlp_writecert[] =
1157 "WRITECERT <hexified_certid>\n"
1159 "This command is used to store a certifciate on a smartcard. The\n"
1160 "allowed certids depend on the currently selected smartcard\n"
1161 "application. The actual certifciate is requested using the inquiry\n"
1162 "\"CERTDATA\" and needs to be provided in its raw (e.g. DER) form.\n"
1164 "In almost all cases a a PIN will be requested. See the related\n"
1165 "writecert function of the actually used application (app-*.c) for\n"
1168 cmd_writecert (assuan_context_t ctx, char *line)
1170 ctrl_t ctrl = assuan_get_pointer (ctx);
1173 unsigned char *certdata;
1176 if ( IS_LOCKED (ctrl) )
1177 return gpg_error (GPG_ERR_LOCKED);
1179 line = skip_options (line);
1182 return set_error (GPG_ERR_ASS_PARAMETER, "no certid given");
1184 while (*line && !spacep (line))
1188 if ((rc = open_card (ctrl, NULL)))
1192 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1194 certid = xtrystrdup (certid);
1196 return out_of_core ();
1198 /* Now get the actual keydata. */
1199 rc = assuan_inquire (ctx, "CERTDATA",
1200 &certdata, &certdatalen, MAXLEN_CERTDATA);
1207 /* Write the certificate to the card. */
1208 rc = app_writecert (ctrl->app_ctx, ctrl, certid,
1209 pin_cb, ctx, certdata, certdatalen);
1213 TEST_CARD_REMOVAL (ctrl, rc);
1218 static const char hlp_writekey[] =
1219 "WRITEKEY [--force] <keyid> \n"
1221 "This command is used to store a secret key on a a smartcard. The\n"
1222 "allowed keyids depend on the currently selected smartcard\n"
1223 "application. The actual keydata is requested using the inquiry\n"
1224 "\"KEYDATA\" and need to be provided without any protection. With\n"
1225 "--force set an existing key under this KEYID will get overwritten.\n"
1226 "The keydata is expected to be the usual canonical encoded\n"
1229 "A PIN will be requested for most NAMEs. See the corresponding\n"
1230 "writekey function of the actually used application (app-*.c) for\n"
1233 cmd_writekey (assuan_context_t ctx, char *line)
1235 ctrl_t ctrl = assuan_get_pointer (ctx);
1238 int force = has_option (line, "--force");
1239 unsigned char *keydata;
1242 if ( IS_LOCKED (ctrl) )
1243 return gpg_error (GPG_ERR_LOCKED);
1245 line = skip_options (line);
1248 return set_error (GPG_ERR_ASS_PARAMETER, "no keyid given");
1250 while (*line && !spacep (line))
1254 if ((rc = open_card (ctrl, NULL)))
1258 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1260 keyid = xtrystrdup (keyid);
1262 return out_of_core ();
1264 /* Now get the actual keydata. */
1265 assuan_begin_confidential (ctx);
1266 rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA);
1267 assuan_end_confidential (ctx);
1274 /* Write the key to the card. */
1275 rc = app_writekey (ctrl->app_ctx, ctrl, keyid, force? 1:0,
1276 pin_cb, ctx, keydata, keydatalen);
1280 TEST_CARD_REMOVAL (ctrl, rc);
1285 static const char hlp_genkey[] =
1286 "GENKEY [--force] [--timestamp=<isodate>] <no>\n"
1288 "Generate a key on-card identified by NO, which is application\n"
1289 "specific. Return values are application specific. For OpenPGP\n"
1290 "cards 3 status lines are returned:\n"
1292 " S KEY-FPR <hexstring>\n"
1293 " S KEY-CREATED-AT <seconds_since_epoch>\n"
1294 " S KEY-DATA [-|p|n] <hexdata>\n"
1296 " 'p' and 'n' are the names of the RSA parameters; '-' is used to\n"
1297 " indicate that HEXDATA is the first chunk of a parameter given\n"
1298 " by the next KEY-DATA.\n"
1300 "--force is required to overwrite an already existing key. The\n"
1301 "KEY-CREATED-AT is required for further processing because it is\n"
1302 "part of the hashed key material for the fingerprint.\n"
1304 "If --timestamp is given an OpenPGP key will be created using this\n"
1305 "value. The value needs to be in ISO Format; e.g.\n"
1306 "\"--timestamp=20030316T120000\" and after 1970-01-01 00:00:00.\n"
1308 "The public part of the key can also later be retrieved using the\n"
1311 cmd_genkey (assuan_context_t ctx, char *line)
1313 ctrl_t ctrl = assuan_get_pointer (ctx);
1320 if ( IS_LOCKED (ctrl) )
1321 return gpg_error (GPG_ERR_LOCKED);
1323 force = has_option (line, "--force");
1325 if ((s=has_option_name (line, "--timestamp")))
1328 return set_error (GPG_ERR_ASS_PARAMETER, "missing value for option");
1329 timestamp = isotime2epoch (s+1);
1331 return set_error (GPG_ERR_ASS_PARAMETER, "invalid time value");
1337 line = skip_options (line);
1339 return set_error (GPG_ERR_ASS_PARAMETER, "no key number given");
1341 while (*line && !spacep (line))
1345 if ((rc = open_card (ctrl, NULL)))
1349 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1351 keyno = xtrystrdup (keyno);
1353 return out_of_core ();
1354 rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0,
1355 timestamp, pin_cb, ctx);
1358 TEST_CARD_REMOVAL (ctrl, rc);
1363 static const char hlp_random[] =
1366 "Get NBYTES of random from the card and send them back as data.\n"
1367 "This usually involves EEPROM write on the card and thus excessive\n"
1368 "use of this command may destroy the card.\n"
1370 "Note, that this function may be even be used on a locked card.";
1372 cmd_random (assuan_context_t ctx, char *line)
1374 ctrl_t ctrl = assuan_get_pointer (ctx);
1377 unsigned char *buffer;
1380 return set_error (GPG_ERR_ASS_PARAMETER,
1381 "number of requested bytes missing");
1382 nbytes = strtoul (line, NULL, 0);
1384 if ((rc = open_card (ctrl, NULL)))
1388 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1390 buffer = xtrymalloc (nbytes);
1392 return out_of_core ();
1394 rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
1397 rc = assuan_send_data (ctx, buffer, nbytes);
1399 return rc; /* that is already an assuan error code */
1403 TEST_CARD_REMOVAL (ctrl, rc);
1409 static const char hlp_passwd[] =
1410 "PASSWD [--reset] [--nullpin] <chvno>\n"
1412 "Change the PIN or, if --reset is given, reset the retry counter of\n"
1413 "the card holder verfication vector CHVNO. The option --nullpin is\n"
1414 "used for TCOS cards to set the initial PIN. The format of CHVNO\n"
1415 "depends on the card application.";
1417 cmd_passwd (assuan_context_t ctx, char *line)
1419 ctrl_t ctrl = assuan_get_pointer (ctx);
1422 unsigned int flags = 0;
1424 if (has_option (line, "--reset"))
1425 flags |= APP_CHANGE_FLAG_RESET;
1426 if (has_option (line, "--nullpin"))
1427 flags |= APP_CHANGE_FLAG_NULLPIN;
1429 if ( IS_LOCKED (ctrl) )
1430 return gpg_error (GPG_ERR_LOCKED);
1432 line = skip_options (line);
1435 return set_error (GPG_ERR_ASS_PARAMETER, "no CHV number given");
1437 while (*line && !spacep (line))
1441 if ((rc = open_card (ctrl, NULL)))
1445 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1447 chvnostr = xtrystrdup (chvnostr);
1449 return out_of_core ();
1450 rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, flags, pin_cb, ctx);
1452 log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1455 TEST_CARD_REMOVAL (ctrl, rc);
1460 static const char hlp_checkpin[] =
1461 "CHECKPIN <idstr>\n"
1463 "Perform a VERIFY operation without doing anything else. This may\n"
1464 "be used to initialize a the PIN cache earlier to long lasting\n"
1465 "operations. Its use is highly application dependent.\n"
1469 " Perform a simple verify operation for CHV1 and CHV2, so that\n"
1470 " further operations won't ask for CHV2 and it is possible to do a\n"
1471 " cheap check on the PIN: If there is something wrong with the PIN\n"
1472 " entry system, only the regular CHV will get blocked and not the\n"
1473 " dangerous CHV3. IDSTR is the usual card's serial number in hex\n"
1474 " notation; an optional fingerprint part will get ignored. There\n"
1475 " is however a special mode if the IDSTR is sffixed with the\n"
1476 " literal string \"[CHV3]\": In this case the Admin PIN is checked\n"
1477 " if and only if the retry counter is still at 3.\n"
1481 " Any of the valid PIN Ids may be used. These are the strings:\n"
1483 " PW1.CH - Global password 1\n"
1484 " PW2.CH - Global password 2\n"
1485 " PW1.CH.SIG - SigG password 1\n"
1486 " PW2.CH.SIG - SigG password 2\n"
1488 " For a definitive list, see the implementation in app-nks.c.\n"
1489 " Note that we call a PW2.* PIN a \"PUK\" despite that since TCOS\n"
1490 " 3.0 they are technically alternative PINs used to mutally\n"
1491 " unblock each other.";
1493 cmd_checkpin (assuan_context_t ctx, char *line)
1495 ctrl_t ctrl = assuan_get_pointer (ctx);
1499 if ( IS_LOCKED (ctrl) )
1500 return gpg_error (GPG_ERR_LOCKED);
1502 if ((rc = open_card (ctrl, NULL)))
1506 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1508 /* We have to use a copy of the key ID because the function may use
1509 the pin_cb which in turn uses the assuan line buffer and thus
1510 overwriting the original line with the keyid. */
1511 idstr = xtrystrdup (line);
1513 return out_of_core ();
1515 rc = app_check_pin (ctrl->app_ctx, idstr, pin_cb, ctx);
1518 log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
1520 TEST_CARD_REMOVAL (ctrl, rc);
1525 static const char hlp_lock[] =
1528 "Grant exclusive card access to this session. Note that there is\n"
1529 "no lock counter used and a second lock from the same session will\n"
1530 "be ignored. A single unlock (or RESET) unlocks the session.\n"
1531 "Return GPG_ERR_LOCKED if another session has locked the reader.\n"
1533 "If the option --wait is given the command will wait until a\n"
1534 "lock has been released.";
1536 cmd_lock (assuan_context_t ctx, char *line)
1538 ctrl_t ctrl = assuan_get_pointer (ctx);
1544 if (locked_session != ctrl->server_local)
1545 rc = gpg_error (GPG_ERR_LOCKED);
1548 locked_session = ctrl->server_local;
1551 if (rc && has_option (line, "--wait"))
1554 pth_sleep (1); /* Better implement an event mechanism. However,
1555 for card operations this should be
1557 /* FIXME: Need to check that the connection is still alive.
1558 This can be done by issuing status messages. */
1561 #endif /*USE_GNU_PTH*/
1564 log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
1569 static const char hlp_unlock[] =
1572 "Release exclusive card access.";
1574 cmd_unlock (assuan_context_t ctx, char *line)
1576 ctrl_t ctrl = assuan_get_pointer (ctx);
1583 if (locked_session != ctrl->server_local)
1584 rc = gpg_error (GPG_ERR_LOCKED);
1586 locked_session = NULL;
1589 rc = gpg_error (GPG_ERR_NOT_LOCKED);
1592 log_error ("cmd_unlock failed: %s\n", gpg_strerror (rc));
1597 static const char hlp_getinfo[] =
1600 "Multi purpose command to return certain information. \n"
1601 "Supported values of WHAT are:\n"
1603 "version - Return the version of the program.\n"
1604 "pid - Return the process id of the server.\n"
1606 "socket_name - Return the name of the socket.\n"
1608 "status - Return the status of the current slot (in the future, may\n"
1609 "also return the status of all slots). The status is a list of\n"
1610 "one-character flags. The following flags are currently defined:\n"
1611 " 'u' Usable card present. This is the normal state during operation.\n"
1612 " 'r' Card removed. A reset is necessary.\n"
1613 "These flags are exclusive.\n"
1615 "reader_list - Return a list of detected card readers. Does\n"
1616 " currently only work with the internal CCID driver.\n"
1618 "deny_admin - Returns OK if admin commands are not allowed or\n"
1619 " GPG_ERR_GENERAL if admin commands are allowed.\n"
1621 "app_list - Return a list of supported applications. One\n"
1622 " application per line, fields delimited by colons,\n"
1623 " first field is the name.";
1625 cmd_getinfo (assuan_context_t ctx, char *line)
1629 if (!strcmp (line, "version"))
1631 const char *s = VERSION;
1632 rc = assuan_send_data (ctx, s, strlen (s));
1634 else if (!strcmp (line, "pid"))
1638 snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1639 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1641 else if (!strcmp (line, "socket_name"))
1643 const char *s = scd_get_socket_name ();
1646 rc = assuan_send_data (ctx, s, strlen (s));
1648 rc = gpg_error (GPG_ERR_NO_DATA);
1650 else if (!strcmp (line, "status"))
1652 ctrl_t ctrl = assuan_get_pointer (ctx);
1653 int slot = ctrl->reader_slot;
1656 if (!ctrl->server_local->card_removed && slot != -1)
1658 struct slot_status_s *ss;
1660 if (!(slot >= 0 && slot < DIM(slot_table)))
1663 ss = &slot_table[slot];
1668 if (ss->any && (ss->status & 1))
1671 rc = assuan_send_data (ctx, &flag, 1);
1673 else if (!strcmp (line, "reader_list"))
1676 char *s = ccid_get_reader_list ();
1682 rc = assuan_send_data (ctx, s, strlen (s));
1684 rc = gpg_error (GPG_ERR_NO_DATA);
1687 else if (!strcmp (line, "deny_admin"))
1688 rc = opt.allow_admin? gpg_error (GPG_ERR_GENERAL) : 0;
1689 else if (!strcmp (line, "app_list"))
1691 char *s = get_supported_applications ();
1693 rc = assuan_send_data (ctx, s, strlen (s));
1699 rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1704 static const char hlp_restart[] =
1707 "Restart the current connection; this is a kind of warm reset. It\n"
1708 "deletes the context used by this connection but does not send a\n"
1709 "RESET to the card. Thus the card itself won't get reset. \n"
1711 "This is used by gpg-agent to reuse a primary pipe connection and\n"
1712 "may be used by clients to backup from a conflict in the serial\n"
1713 "command; i.e. to select another application.";
1715 cmd_restart (assuan_context_t ctx, char *line)
1717 ctrl_t ctrl = assuan_get_pointer (ctx);
1723 release_application (ctrl->app_ctx);
1724 ctrl->app_ctx = NULL;
1726 if (locked_session && ctrl->server_local == locked_session)
1728 locked_session = NULL;
1729 log_info ("implicitly unlocking due to RESTART\n");
1735 static const char hlp_disconnect[] =
1738 "Disconnect the card if it is not any longer used by other\n"
1739 "connections and the backend supports a disconnect operation.";
1741 cmd_disconnect (assuan_context_t ctx, char *line)
1743 ctrl_t ctrl = assuan_get_pointer (ctx);
1747 ctrl->server_local->disconnect_allowed = 1;
1753 static const char hlp_apdu[] =
1754 "APDU [--atr] [--more] [--exlen[=N]] [hexstring]\n"
1756 "Send an APDU to the current reader. This command bypasses the high\n"
1757 "level functions and sends the data directly to the card. HEXSTRING\n"
1758 "is expected to be a proper APDU. If HEXSTRING is not given no\n"
1759 "commands are set to the card but the command will implictly check\n"
1760 "whether the card is ready for use. \n"
1762 "Using the option \"--atr\" returns the ATR of the card as a status\n"
1763 "message before any data like this:\n"
1764 " S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1\n"
1766 "Using the option --more handles the card status word MORE_DATA\n"
1767 "(61xx) and concatenates all reponses to one block.\n"
1769 "Using the option \"--exlen\" the returned APDU may use extended\n"
1770 "length up to N bytes. If N is not given a default value is used\n"
1771 "(currently 4096).";
1773 cmd_apdu (assuan_context_t ctx, char *line)
1775 ctrl_t ctrl = assuan_get_pointer (ctx);
1777 unsigned char *apdu;
1784 with_atr = has_option (line, "--atr");
1785 handle_more = has_option (line, "--more");
1787 if ((s=has_option_name (line, "--exlen")))
1790 exlen = strtoul (s+1, NULL, 0);
1797 line = skip_options (line);
1799 if ( IS_LOCKED (ctrl) )
1800 return gpg_error (GPG_ERR_LOCKED);
1802 if ((rc = open_card (ctrl, NULL)))
1811 atr = apdu_get_atr (ctrl->reader_slot, &atrlen);
1812 if (!atr || atrlen > sizeof hexbuf - 2 )
1814 rc = gpg_error (GPG_ERR_INV_CARD);
1817 bin2hex (atr, atrlen, hexbuf);
1819 send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
1822 apdu = hex_to_buffer (line, &apdulen);
1825 rc = gpg_error_from_syserror ();
1830 unsigned char *result = NULL;
1833 rc = apdu_send_direct (ctrl->reader_slot, exlen,
1834 apdu, apdulen, handle_more,
1835 &result, &resultlen);
1837 log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
1840 rc = assuan_send_data (ctx, result, resultlen);
1847 TEST_CARD_REMOVAL (ctrl, rc);
1852 static const char hlp_killscd[] =
1857 cmd_killscd (assuan_context_t ctx, char *line)
1859 ctrl_t ctrl = assuan_get_pointer (ctx);
1863 ctrl->server_local->stopme = 1;
1864 return gpg_error (GPG_ERR_EOF);
1869 /* Tell the assuan library about our commands */
1871 register_commands (assuan_context_t ctx)
1875 assuan_handler_t handler;
1876 const char * const help;
1878 { "SERIALNO", cmd_serialno, hlp_serialno },
1879 { "LEARN", cmd_learn, hlp_learn },
1880 { "READCERT", cmd_readcert, hlp_readcert },
1881 { "READKEY", cmd_readkey, hlp_readkey },
1882 { "SETDATA", cmd_setdata, hlp_setdata },
1883 { "PKSIGN", cmd_pksign, hlp_pksign },
1884 { "PKAUTH", cmd_pkauth, hlp_pkauth },
1885 { "PKDECRYPT", cmd_pkdecrypt,hlp_pkdecrypt },
1888 { "GETATTR", cmd_getattr, hlp_getattr },
1889 { "SETATTR", cmd_setattr, hlp_setattr },
1890 { "WRITECERT", cmd_writecert,hlp_writecert },
1891 { "WRITEKEY", cmd_writekey, hlp_writekey },
1892 { "GENKEY", cmd_genkey, hlp_genkey },
1893 { "RANDOM", cmd_random, hlp_random },
1894 { "PASSWD", cmd_passwd, hlp_passwd },
1895 { "CHECKPIN", cmd_checkpin, hlp_checkpin },
1896 { "LOCK", cmd_lock, hlp_lock },
1897 { "UNLOCK", cmd_unlock, hlp_unlock },
1898 { "GETINFO", cmd_getinfo, hlp_getinfo },
1899 { "RESTART", cmd_restart, hlp_restart },
1900 { "DISCONNECT", cmd_disconnect,hlp_disconnect },
1901 { "APDU", cmd_apdu, hlp_apdu },
1902 { "KILLSCD", cmd_killscd, hlp_killscd },
1907 for (i=0; table[i].name; i++)
1909 rc = assuan_register_command (ctx, table[i].name, table[i].handler,
1914 assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
1916 assuan_register_reset_notify (ctx, reset_notify);
1917 assuan_register_option_handler (ctx, option_handler);
1922 /* Startup the server. If FD is given as -1 this is simple pipe
1923 server, otherwise it is a regular server. Returns true if there
1924 are no more active asessions. */
1926 scd_command_handler (ctrl_t ctrl, int fd)
1929 assuan_context_t ctx = NULL;
1932 rc = assuan_new (&ctx);
1935 log_error ("failed to allocate assuan context: %s\n",
1942 assuan_fd_t filedes[2];
1944 filedes[0] = assuan_fdopen (0);
1945 filedes[1] = assuan_fdopen (1);
1946 rc = assuan_init_pipe_server (ctx, filedes);
1950 rc = assuan_init_socket_server (ctx, INT2FD(fd),
1951 ASSUAN_SOCKET_SERVER_ACCEPTED);
1955 log_error ("failed to initialize the server: %s\n",
1959 rc = register_commands (ctx);
1962 log_error ("failed to register commands with Assuan: %s\n",
1966 assuan_set_pointer (ctx, ctrl);
1968 /* Allocate and initialize the server object. Put it into the list
1969 of active sessions. */
1970 ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
1971 ctrl->server_local->next_session = session_list;
1972 session_list = ctrl->server_local;
1973 ctrl->server_local->ctrl_backlink = ctrl;
1974 ctrl->server_local->assuan_ctx = ctx;
1977 assuan_set_log_stream (ctx, log_get_stream ());
1979 /* We open the reader right at startup so that the ticker is able to
1980 update the status file. */
1981 if (ctrl->reader_slot == -1)
1983 ctrl->reader_slot = get_reader_slot ();
1986 /* Command processing loop. */
1989 rc = assuan_accept (ctx);
1996 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
2000 rc = assuan_process (ctx);
2003 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
2008 /* Cleanup. We don't send an explicit reset to the card. */
2011 /* Release the server object. */
2012 if (session_list == ctrl->server_local)
2013 session_list = ctrl->server_local->next_session;
2016 struct server_local_s *sl;
2018 for (sl=session_list; sl->next_session; sl = sl->next_session)
2019 if (sl->next_session == ctrl->server_local)
2021 if (!sl->next_session)
2023 sl->next_session = ctrl->server_local->next_session;
2025 stopme = ctrl->server_local->stopme || reader_disabled;
2026 xfree (ctrl->server_local);
2027 ctrl->server_local = NULL;
2029 /* Release the Assuan context. */
2030 assuan_release (ctx);
2035 /* If there are no more sessions return true. */
2036 return !session_list;
2040 /* Send a line with status information via assuan and escape all given
2041 buffers. The variable elements are pairs of (char *, size_t),
2042 terminated with a (NULL, 0). */
2044 send_status_info (ctrl_t ctrl, const char *keyword, ...)
2047 const unsigned char *value;
2051 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2053 va_start (arg_ptr, keyword);
2057 while ( (value = va_arg (arg_ptr, const unsigned char *)) )
2059 valuelen = va_arg (arg_ptr, size_t);
2061 continue; /* empty buffer */
2067 for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
2069 if (*value < ' ' || *value == '+')
2071 sprintf (p, "%%%02X", *value);
2074 else if (*value == ' ')
2081 assuan_write_status (ctx, keyword, buf);
2087 /* Send a ready formatted status line via assuan. */
2089 send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
2091 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2093 if (strchr (args, '\n'))
2094 log_error ("error: LF detected in status line - not sending\n");
2096 assuan_write_status (ctx, keyword, args);
2100 /* Helper to send the clients a status change notification. */
2102 send_client_notifications (void)
2106 #ifdef HAVE_W32_SYSTEM
2114 struct server_local_s *sl;
2116 for (sl=session_list; sl; sl = sl->next_session)
2118 if (sl->event_signal && sl->assuan_ctx)
2120 pid_t pid = assuan_get_pid (sl->assuan_ctx);
2121 #ifdef HAVE_W32_SYSTEM
2122 HANDLE handle = (void *)sl->event_signal;
2124 for (kidx=0; kidx < killidx; kidx++)
2125 if (killed[kidx].pid == pid
2126 && killed[kidx].handle == handle)
2129 log_info ("event %lx (%p) already triggered for client %d\n",
2130 sl->event_signal, handle, (int)pid);
2133 log_info ("triggering event %lx (%p) for client %d\n",
2134 sl->event_signal, handle, (int)pid);
2135 if (!SetEvent (handle))
2136 log_error ("SetEvent(%lx) failed: %s\n",
2137 sl->event_signal, w32_strerror (-1));
2138 if (killidx < DIM (killed))
2140 killed[killidx].pid = pid;
2141 killed[killidx].handle = handle;
2145 #else /*!HAVE_W32_SYSTEM*/
2146 int signo = sl->event_signal;
2148 if (pid != (pid_t)(-1) && pid && signo > 0)
2150 for (kidx=0; kidx < killidx; kidx++)
2151 if (killed[kidx].pid == pid
2152 && killed[kidx].signo == signo)
2155 log_info ("signal %d already sent to client %d\n",
2159 log_info ("sending signal %d to client %d\n",
2162 if (killidx < DIM (killed))
2164 killed[killidx].pid = pid;
2165 killed[killidx].signo = signo;
2170 #endif /*!HAVE_W32_SYSTEM*/
2177 /* This is the core of scd_update_reader_status_file but the caller
2178 needs to take care of the locking. */
2180 update_reader_status_file (int set_card_removed_flag)
2183 unsigned int status, changed;
2185 /* Make sure that the reader has been opened. Like get_reader_slot,
2186 this part of the code assumes that there is only one reader. */
2187 if (!slot_table[0].valid)
2188 (void)get_reader_slot ();
2190 /* Note, that we only try to get the status, because it does not
2191 make sense to wait here for a operation to complete. If we are
2192 busy working with a card, delays in the status file update should
2194 for (idx=0; idx < DIM(slot_table); idx++)
2196 struct slot_status_s *ss = slot_table + idx;
2197 struct server_local_s *sl;
2200 if (!ss->valid || ss->slot == -1)
2201 continue; /* Not valid or reader not yet open. */
2203 sw_apdu = apdu_get_status (ss->slot, 0, &status, &changed);
2204 if (sw_apdu == SW_HOST_NO_READER)
2206 /* Most likely the _reader_ has been unplugged. */
2207 apdu_close_reader (ss->slot);
2210 changed = ss->changed;
2214 /* Get status failed. Ignore that. */
2218 if (!ss->any || ss->status != status || ss->changed != changed )
2224 log_info ("updating slot %d status: 0x%04X->0x%04X (%u->%u)\n",
2225 ss->slot, ss->status, status, ss->changed, changed);
2226 ss->status = status;
2227 ss->changed = changed;
2229 /* FIXME: Should this be IDX instead of ss->slot? This
2230 depends on how client sessions will associate the reader
2231 status with their session. */
2232 snprintf (templ, sizeof templ, "reader_%d.status", ss->slot);
2233 fname = make_filename (opt.homedir, templ, NULL );
2234 fp = fopen (fname, "w");
2237 fprintf (fp, "%s\n",
2238 (status & 1)? "USABLE":
2239 (status & 4)? "ACTIVE":
2240 (status & 2)? "PRESENT": "NOCARD");
2245 /* If a status script is executable, run it. */
2247 const char *args[9], *envs[2];
2248 char numbuf1[30], numbuf2[30], numbuf3[30];
2249 char *homestr, *envstr;
2252 homestr = make_filename (opt.homedir, NULL);
2253 if (estream_asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
2254 log_error ("out of core while building environment\n");
2260 sprintf (numbuf1, "%d", ss->slot);
2261 sprintf (numbuf2, "0x%04X", ss->status);
2262 sprintf (numbuf3, "0x%04X", status);
2263 args[0] = "--reader-port";
2265 args[2] = "--old-code";
2267 args[4] = "--new-code";
2269 args[6] = "--status";
2270 args[7] = ((status & 1)? "USABLE":
2271 (status & 4)? "ACTIVE":
2272 (status & 2)? "PRESENT": "NOCARD");
2275 fname = make_filename (opt.homedir, "scd-event", NULL);
2276 err = gnupg_spawn_process_detached (fname, args, envs);
2277 if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
2278 log_error ("failed to run event handler `%s': %s\n",
2279 fname, gpg_strerror (err));
2286 /* Set the card removed flag for all current sessions. We
2287 will set this on any card change because a reset or
2288 SERIALNO request must be done in any case. */
2289 if (ss->any && set_card_removed_flag)
2290 update_card_removed (idx, 1);
2294 /* Send a signal to all clients who applied for it. */
2295 send_client_notifications ();
2298 /* Check whether a disconnect is pending. */
2299 if (opt.card_timeout)
2301 for (sl=session_list; sl; sl = sl->next_session)
2302 if (!sl->disconnect_allowed)
2304 if (session_list && !sl)
2306 /* FIXME: Use a real timeout. */
2307 /* At least one connection and all allow a disconnect. */
2308 log_info ("disconnecting card in slot %d\n", ss->slot);
2309 apdu_disconnect (ss->slot);
2316 /* This function is called by the ticker thread to check for changes
2317 of the reader stati. It updates the reader status files and if
2318 requested by the caller also send a signal to the caller. */
2320 scd_update_reader_status_file (void)
2322 if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL))
2323 return; /* locked - give up. */
2324 update_reader_status_file (1);
2325 if (!pth_mutex_release (&status_file_update_lock))
2326 log_error ("failed to release status_file_update lock\n");