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"
38 #include "apdu.h" /* Required for apdu_*_reader (). */
41 #include "ccid-driver.h"
44 /* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */
45 #define MAXLEN_PIN 100
47 /* Maximum allowed size of key data as used in inquiries. */
48 #define MAXLEN_KEYDATA 4096
50 /* Maximum allowed total data size for SETDATA. */
51 #define MAXLEN_SETDATA 4096
53 /* Maximum allowed size of certificate data as used in inquiries. */
54 #define MAXLEN_CERTDATA 16384
57 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
60 /* Macro to flag a removed card. ENODEV is also tested to catch teh
61 case of a removed reader. */
62 #define TEST_CARD_REMOVAL(c,r) \
65 if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \
66 || gpg_err_code (_r) == GPG_ERR_CARD_REMOVED \
67 || gpg_err_code (_r) == GPG_ERR_CARD_RESET \
68 || gpg_err_code (_r) == GPG_ERR_ENODEV ) \
69 update_card_removed ((c)->reader_slot, 1); \
72 #define IS_LOCKED(c) \
73 (locked_session && locked_session != (c)->server_local \
74 && (c)->reader_slot != -1 && locked_session->ctrl_backlink \
75 && (c)->reader_slot == locked_session->ctrl_backlink->reader_slot)
78 /* This structure is used to keep track of open readers (slots). */
81 int valid; /* True if the other objects are valid. */
82 int slot; /* Slot number of the reader or -1 if not open. */
84 int reset_failed; /* A reset failed. */
86 int any; /* Flag indicating whether any status check has been
87 done. This is set once to indicate that the status
88 tracking for the slot has been initialized. */
89 unsigned int status; /* Last status of the slot. */
90 unsigned int changed; /* Last change counter of the slot. */
94 /* Data used to associate an Assuan context with local server data.
95 This object describes the local properties of one session. */
98 /* We keep a list of all active sessions with the anchor at
99 SESSION_LIST (see below). This field is used for linking. */
100 struct server_local_s *next_session;
102 /* This object is usually assigned to a CTRL object (which is
103 globally visible). While enumerating all sessions we sometimes
104 need to access data of the CTRL object; thus we keep a
106 ctrl_t ctrl_backlink;
108 /* The Assuan context used by this session/server. */
109 assuan_context_t assuan_ctx;
111 #ifdef HAVE_W32_SYSTEM
112 unsigned long event_signal; /* Or 0 if not used. */
114 int event_signal; /* Or 0 if not used. */
117 /* True if the card has been removed and a reset is required to
118 continue operation. */
121 /* A disconnect command has been sent. */
122 int disconnect_allowed;
124 /* If set to true we will be terminate ourself at the end of the
131 /* The table with information on all used slots. FIXME: This is a
132 different slot number than the one used by the APDU layer, and
133 should be renamed. */
134 static struct slot_status_s slot_table[10];
137 /* To keep track of all running sessions, we link all active server
138 contexts and the anchor in this variable. */
139 static struct server_local_s *session_list;
141 /* If a session has been locked we store a link to its server object
143 static struct server_local_s *locked_session;
145 /* While doing a reset we need to make sure that the ticker does not
146 call scd_update_reader_status_file while we are using it. */
147 static pth_mutex_t status_file_update_lock;
150 /*-- Local prototypes --*/
151 static void update_reader_status_file (int set_card_removed_flag);
156 /* This function must be called once to initialize this module. This
157 has to be done before a second thread is spawned. We can't do the
158 static initialization because Pth emulation code might not be able
159 to do a static init; in particular, it is not possible for W32. */
161 initialize_module_command (void)
163 static int initialized;
167 if (pth_mutex_init (&status_file_update_lock))
173 /* Update the CARD_REMOVED element of all sessions using the reader
174 given by SLOT to VALUE. */
176 update_card_removed (int slot, int value)
178 struct server_local_s *sl;
183 for (sl=session_list; sl; sl = sl->next_session)
185 ctrl_t ctrl = sl->ctrl_backlink;
187 if (ctrl && ctrl->reader_slot == slot)
189 sl->card_removed = value;
192 struct app_ctx_s *app = ctrl->app_ctx;
193 ctrl->app_ctx = NULL;
194 release_application (app);
199 /* Let the card application layer know about the removal. */
202 log_debug ("Removal of a card: %d\n", slot);
203 apdu_close_reader (slot);
204 application_notify_card_reset (slot);
205 slot_table[slot].slot = -1;
211 /* Check whether the option NAME appears in LINE. Returns 1 or 0. */
213 has_option (const char *line, const char *name)
216 int n = strlen (name);
218 s = strstr (line, name);
219 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
222 /* Same as has_option but does only test for the name of the option
223 and ignores an argument, i.e. with NAME being "--hash" it would
224 return a pointer for "--hash" as well as for "--hash=foo". If
225 there is no such option NULL is returned. The pointer returned
226 points right behind the option name, this may be an equal sign, Nul
229 has_option_name (const char *line, const char *name)
232 int n = strlen (name);
234 s = strstr (line, name);
235 return (s && (s == line || spacep (s-1))
236 && (!s[n] || spacep (s+n) || s[n] == '=')) ? (s+n) : NULL;
240 /* Skip over options. It is assumed that leading spaces have been
241 removed (this is the case for lines passed to a handler from
242 assuan). Blanks after the options are also removed. */
244 skip_options (char *line)
246 while ( *line == '-' && line[1] == '-' )
248 while (*line && !spacep (line))
250 while (spacep (line))
258 /* Convert the STRING into a newly allocated buffer while translating
259 the hex numbers. Stops at the first invalid character. Blanks and
260 colons are allowed to separate the hex digits. Returns NULL on
261 error or a newly malloced buffer and its length in LENGTH. */
262 static unsigned char *
263 hex_to_buffer (const char *string, size_t *r_length)
265 unsigned char *buffer;
269 buffer = xtrymalloc (strlen (string)+1);
272 for (s=string, n=0; *s; s++)
274 if (spacep (s) || *s == ':')
276 if (hexdigitp (s) && hexdigitp (s+1))
278 buffer[n++] = xtoi_2 (s);
290 /* Reset the card and free the application context. With SEND_RESET
291 set to true actually send a RESET to the reader; this is the normal
292 way of calling the function. */
294 do_reset (ctrl_t ctrl, int send_reset)
296 int slot = ctrl->reader_slot;
297 struct app_ctx_s *app = ctrl->app_ctx;
299 if (!(slot == -1 || (slot >= 0 && slot < DIM(slot_table))))
302 /* If there is an active application, release it. */
305 ctrl->app_ctx = NULL;
306 release_application (app);
309 /* Release the same application which is used by other sessions. */
312 struct server_local_s *sl;
314 for (sl=session_list; sl; sl = sl->next_session)
316 ctrl_t c = sl->ctrl_backlink;
318 if (c && c != ctrl && c->reader_slot == slot)
320 struct app_ctx_s *app0 = c->app_ctx;
324 release_application (app0);
330 /* If we want a real reset for the card, send the reset APDU and
331 tell the application layer about it. */
332 if (slot != -1 && send_reset && !IS_LOCKED (ctrl) )
334 application_notify_card_reset (slot);
335 switch (apdu_reset (slot))
339 case SW_HOST_NO_CARD:
340 case SW_HOST_CARD_INACTIVE:
343 apdu_close_reader (slot);
344 slot_table[slot].slot = -1;
349 /* If we hold a lock, unlock now. */
350 if (locked_session && ctrl->server_local == locked_session)
352 locked_session = NULL;
353 log_info ("implicitly unlocking due to RESET\n");
356 /* Reset the card removed flag for the current reader. We need to
357 take the lock here so that the ticker thread won't concurrently
358 try to update the file. Calling update_reader_status_file is
359 required to get hold of the new status of the card in the slot
361 if (!pth_mutex_acquire (&status_file_update_lock, 0, NULL))
363 log_error ("failed to acquire status_fle_update lock\n");
364 ctrl->reader_slot = -1;
367 update_reader_status_file (0); /* Update slot status table. */
368 update_card_removed (slot, 0); /* Clear card_removed flag. */
369 if (!pth_mutex_release (&status_file_update_lock))
370 log_error ("failed to release status_file_update lock\n");
372 /* Do this last, so that the update_card_removed above does its job. */
373 ctrl->reader_slot = -1;
378 reset_notify (assuan_context_t ctx, char *line)
380 ctrl_t ctrl = assuan_get_pointer (ctx);
390 option_handler (assuan_context_t ctx, const char *key, const char *value)
392 ctrl_t ctrl = assuan_get_pointer (ctx);
394 if (!strcmp (key, "event-signal"))
396 /* A value of 0 is allowed to reset the event signal. */
397 #ifdef HAVE_W32_SYSTEM
399 return gpg_error (GPG_ERR_ASS_PARAMETER);
400 ctrl->server_local->event_signal = strtoul (value, NULL, 16);
402 int i = *value? atoi (value) : -1;
404 return gpg_error (GPG_ERR_ASS_PARAMETER);
405 ctrl->server_local->event_signal = i;
413 /* Return the slot of the current reader or open the reader if no
414 other sessions are using a reader. Note, that we currently support
415 only one reader but most of the code (except for this function)
416 should be able to cope with several readers. */
418 get_reader_slot (void)
420 struct slot_status_s *ss;
422 ss = &slot_table[0]; /* One reader for now. */
424 /* Initialize the item if needed. */
431 /* Try to open the reader. */
434 ss->slot = apdu_open_reader (opt.reader_port);
436 /* If we still don't have a slot, we have no readers.
437 Invalidate for now until a reader is attached. */
445 /* Return the slot_table index. */
450 /* If the card has not yet been opened, do it. */
452 open_card (ctrl_t ctrl, const char *apptype)
457 /* If we ever got a card not present error code, return that. Only
458 the SERIALNO command and a reset are able to clear from that
460 if (ctrl->server_local->card_removed)
461 return gpg_error (GPG_ERR_CARD_REMOVED);
463 if ( IS_LOCKED (ctrl) )
464 return gpg_error (GPG_ERR_LOCKED);
466 /* If we are already initialized for one specific application we
467 need to check that the client didn't requested a specific
468 application different from the one in use before we continue. */
470 return check_application_conflict (ctrl, apptype);
472 /* Setup the slot and select the application. */
473 if (ctrl->reader_slot != -1)
474 slot = ctrl->reader_slot;
476 slot = get_reader_slot ();
477 ctrl->reader_slot = slot;
479 err = gpg_error (GPG_ERR_CARD);
482 /* Fixme: We should move the apdu_connect call to
483 select_application. */
486 ctrl->server_local->disconnect_allowed = 0;
487 sw = apdu_connect (slot);
488 if (sw && sw != SW_HOST_ALREADY_CONNECTED)
490 if (sw == SW_HOST_NO_CARD)
491 err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
492 else if (sw == SW_HOST_CARD_INACTIVE)
493 err = gpg_error (GPG_ERR_CARD_RESET);
495 err = gpg_error (GPG_ERR_ENODEV);
498 err = select_application (ctrl, slot, apptype, &ctrl->app_ctx);
501 TEST_CARD_REMOVAL (ctrl, err);
506 static const char hlp_serialno[] =
507 "SERIALNO [<apptype>]\n"
509 "Return the serial number of the card using a status reponse. This\n"
510 "function should be used to check for the presence of a card.\n"
512 "If APPTYPE is given, an application of that type is selected and an\n"
513 "error is returned if the application is not supported or available.\n"
514 "The default is to auto-select the application using a hardwired\n"
515 "preference system. Note, that a future extension to this function\n"
516 "may allow to specify a list and order of applications to try.\n"
518 "This function is special in that it can be used to reset the card.\n"
519 "Most other functions will return an error when a card change has\n"
520 "been detected and the use of this function is therefore required.\n"
522 "Background: We want to keep the client clear of handling card\n"
523 "changes between operations; i.e. the client can assume that all\n"
524 "operations are done on the same card unless he calls this function.";
526 cmd_serialno (assuan_context_t ctx, char *line)
528 ctrl_t ctrl = assuan_get_pointer (ctx);
530 char *serial_and_stamp;
535 /* Clear the remove flag so that the open_card is able to reread it. */
537 if (ctrl->server_local->card_removed)
539 if ( IS_LOCKED (ctrl) )
540 return gpg_error (GPG_ERR_LOCKED);
544 if ((rc = open_card (ctrl, *line? line:NULL)))
546 /* In case of an inactive card, retry once. */
547 if (gpg_err_code (rc) == GPG_ERR_CARD_RESET && retries++ < 1)
552 rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
556 rc = estream_asprintf (&serial_and_stamp, "%s %lu",
557 serial, (unsigned long)stamp);
560 return out_of_core ();
562 assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
563 xfree (serial_and_stamp);
568 static const char hlp_learn[] =
569 "LEARN [--force] [--keypairinfo]\n"
571 "Learn all useful information of the currently inserted card. When\n"
572 "used without the force options, the command might do an INQUIRE\n"
575 " INQUIRE KNOWNCARDP <hexstring_with_serialNumber> <timestamp>\n"
577 "The client should just send an \"END\" if the processing should go on\n"
578 "or a \"CANCEL\" to force the function to terminate with a Cancel\n"
581 "With the option --keypairinfo only KEYPARIINFO lstatus lines are\n"
584 "The response of this command is a list of status lines formatted as\n"
587 " S APPTYPE <apptype>\n"
589 "This returns the type of the application, currently the strings:\n"
591 " P15 = PKCS-15 structure used\n"
592 " DINSIG = DIN SIG\n"
593 " OPENPGP = OpenPGP card\n"
594 " NKS = NetKey card\n"
596 "are implemented. These strings are aliases for the AID\n"
598 " S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id>\n"
600 "If there is no certificate yet stored on the card a single 'X' is\n"
601 "returned as the keygrip. In addition to the keypair info, information\n"
602 "about all certificates stored on the card is also returned:\n"
604 " S CERTINFO <certtype> <hexstring_with_id>\n"
606 "Where CERTTYPE is a number indicating the type of certificate:\n"
608 " 100 := Regular X.509 cert\n"
609 " 101 := Trusted X.509 cert\n"
610 " 102 := Useful X.509 cert\n"
611 " 110 := Root CA cert in a special format (e.g. DINSIG)\n"
612 " 111 := Root CA cert as standard X509 cert.\n"
614 "For certain cards, more information will be returned:\n"
616 " S KEY-FPR <no> <hexstring>\n"
618 "For OpenPGP cards this returns the stored fingerprints of the\n"
619 "keys. This can be used check whether a key is available on the\n"
620 "card. NO may be 1, 2 or 3.\n"
622 " S CA-FPR <no> <hexstring>\n"
624 "Similar to above, these are the fingerprints of keys assumed to be\n"
625 "ultimately trusted.\n"
627 " S DISP-NAME <name_of_card_holder>\n"
629 "The name of the card holder as stored on the card; percent\n"
630 "escaping takes place, spaces are encoded as '+'\n"
632 " S PUBKEY-URL <url>\n"
634 "The URL to be used for locating the entire public key.\n"
636 "Note, that this function may even be used on a locked card.";
638 cmd_learn (assuan_context_t ctx, char *line)
640 ctrl_t ctrl = assuan_get_pointer (ctx);
642 int only_keypairinfo = has_option (line, "--keypairinfo");
644 if ((rc = open_card (ctrl, NULL)))
647 /* Unless the force option is used we try a shortcut by identifying
648 the card using a serial number and inquiring the client with
649 that. The client may choose to cancel the operation if he already
650 knows about this card */
651 if (!only_keypairinfo)
653 char *serial_and_stamp;
657 rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
660 rc = estream_asprintf (&serial_and_stamp, "%s %lu",
661 serial, (unsigned long)stamp);
664 return out_of_core ();
666 assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
668 if (!has_option (line, "--force"))
672 rc = estream_asprintf (&command, "KNOWNCARDP %s", serial_and_stamp);
675 xfree (serial_and_stamp);
676 return out_of_core ();
679 rc = assuan_inquire (ctx, command, NULL, NULL, 0);
683 if (gpg_err_code (rc) != GPG_ERR_ASS_CANCELED)
684 log_error ("inquire KNOWNCARDP failed: %s\n",
686 xfree (serial_and_stamp);
689 /* Not canceled, so we have to proceeed. */
691 xfree (serial_and_stamp);
694 /* Let the application print out its collection of useful status
697 rc = app_write_learn_status (ctrl->app_ctx, ctrl, only_keypairinfo);
699 TEST_CARD_REMOVAL (ctrl, rc);
705 static const char hlp_readcert[] =
706 "READCERT <hexified_certid>|<keyid>\n"
708 "Note, that this function may even be used on a locked card.";
710 cmd_readcert (assuan_context_t ctx, char *line)
712 ctrl_t ctrl = assuan_get_pointer (ctx);
717 if ((rc = open_card (ctrl, NULL)))
720 line = xstrdup (line); /* Need a copy of the line. */
721 rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
723 log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
728 rc = assuan_send_data (ctx, cert, ncert);
734 TEST_CARD_REMOVAL (ctrl, rc);
739 static const char hlp_readkey[] =
742 "Return the public key for the given cert or key ID as a standard\n"
745 "Note, that this function may even be used on a locked card.";
747 cmd_readkey (assuan_context_t ctx, char *line)
749 ctrl_t ctrl = assuan_get_pointer (ctx);
751 unsigned char *cert = NULL;
753 ksba_cert_t kc = NULL;
758 if ((rc = open_card (ctrl, NULL)))
761 line = xstrdup (line); /* Need a copy of the line. */
762 /* If the application supports the READKEY function we use that.
763 Otherwise we use the old way by extracting it from the
765 rc = app_readkey (ctrl->app_ctx, line, &pk, &pklen);
767 { /* Yeah, got that key - send it back. */
768 rc = assuan_send_data (ctx, pk, pklen);
775 if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION)
776 log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
779 rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
781 log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
788 rc = ksba_cert_new (&kc);
792 rc = ksba_cert_init_from_mem (kc, cert, ncert);
795 log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
799 p = ksba_cert_get_public_key (kc);
802 rc = gpg_error (GPG_ERR_NO_PUBKEY);
806 n = gcry_sexp_canon_len (p, 0, NULL, NULL);
807 rc = assuan_send_data (ctx, p, n);
812 ksba_cert_release (kc);
814 TEST_CARD_REMOVAL (ctrl, rc);
820 static const char hlp_setdata[] =
821 "SETDATA [--append] <hexstring>\n"
823 "The client should use this command to tell us the data he want to sign.\n"
824 "With the option --append, the data is appended to the data set by a\n"
825 "previous SETDATA command.";
827 cmd_setdata (assuan_context_t ctx, char *line)
829 ctrl_t ctrl = assuan_get_pointer (ctx);
835 append = (ctrl->in_data.value && has_option (line, "--append"));
837 line = skip_options (line);
839 if (locked_session && locked_session != ctrl->server_local)
840 return gpg_error (GPG_ERR_LOCKED);
842 /* Parse the hexstring. */
843 for (p=line,n=0; hexdigitp (p); p++, n++)
846 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
848 return set_error (GPG_ERR_ASS_PARAMETER, "no data given");
850 return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
854 if (ctrl->in_data.valuelen + n > MAXLEN_SETDATA)
855 return set_error (GPG_ERR_TOO_LARGE,
856 "limit on total size of data reached");
857 buf = xtrymalloc (ctrl->in_data.valuelen + n);
860 buf = xtrymalloc (n);
862 return out_of_core ();
866 memcpy (buf, ctrl->in_data.value, ctrl->in_data.valuelen);
867 off = ctrl->in_data.valuelen;
871 for (p=line, i=0; i < n; p += 2, i++)
872 buf[off+i] = xtoi_2 (p);
874 ctrl->in_data.value = buf;
875 ctrl->in_data.valuelen = off + n;
882 pin_cb (void *opaque, const char *info, char **retstr)
884 assuan_context_t ctx = opaque;
887 unsigned char *value;
892 /* We prompt for pinpad entry. To make sure that the popup has
893 been show we use an inquire and not just a status message.
894 We ignore any value returned. */
897 log_debug ("prompting for pinpad entry '%s'\n", info);
898 rc = estream_asprintf (&command, "POPUPPINPADPROMPT %s", info);
900 return gpg_error (gpg_err_code_from_errno (errno));
901 rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
906 log_debug ("dismiss pinpad entry prompt\n");
907 rc = assuan_inquire (ctx, "DISMISSPINPADPROMPT",
908 &value, &valuelen, MAXLEN_PIN);
916 log_debug ("asking for PIN '%s'\n", info);
918 rc = estream_asprintf (&command, "NEEDPIN %s", info);
920 return gpg_error (gpg_err_code_from_errno (errno));
922 /* Fixme: Write an inquire function which returns the result in
923 secure memory and check all further handling of the PIN. */
924 rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
929 if (!valuelen || value[valuelen-1])
931 /* We require that the returned value is an UTF-8 string */
933 return gpg_error (GPG_ERR_INV_RESPONSE);
935 *retstr = (char*)value;
940 static const char hlp_pksign[] =
941 "PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5]] <hexified_id>\n"
943 "The --hash option is optional; the default is SHA1.";
945 cmd_pksign (assuan_context_t ctx, char *line)
947 ctrl_t ctrl = assuan_get_pointer (ctx);
949 unsigned char *outdata;
954 if (has_option (line, "--hash=rmd160"))
955 hash_algo = GCRY_MD_RMD160;
956 else if (has_option (line, "--hash=sha1"))
957 hash_algo = GCRY_MD_SHA1;
958 else if (has_option (line, "--hash=sha224"))
959 hash_algo = GCRY_MD_SHA224;
960 else if (has_option (line, "--hash=sha256"))
961 hash_algo = GCRY_MD_SHA256;
962 else if (has_option (line, "--hash=sha384"))
963 hash_algo = GCRY_MD_SHA384;
964 else if (has_option (line, "--hash=sha512"))
965 hash_algo = GCRY_MD_SHA512;
966 else if (has_option (line, "--hash=md5"))
967 hash_algo = GCRY_MD_MD5;
968 else if (!strstr (line, "--"))
969 hash_algo = GCRY_MD_SHA1;
971 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
973 line = skip_options (line);
975 if ( IS_LOCKED (ctrl) )
976 return gpg_error (GPG_ERR_LOCKED);
978 if ((rc = open_card (ctrl, NULL)))
981 /* We have to use a copy of the key ID because the function may use
982 the pin_cb which in turn uses the assuan line buffer and thus
983 overwriting the original line with the keyid */
984 keyidstr = xtrystrdup (line);
986 return out_of_core ();
988 rc = app_sign (ctrl->app_ctx,
991 ctrl->in_data.value, ctrl->in_data.valuelen,
992 &outdata, &outdatalen);
997 log_error ("app_sign failed: %s\n", gpg_strerror (rc));
1001 rc = assuan_send_data (ctx, outdata, outdatalen);
1004 return rc; /* that is already an assuan error code */
1007 TEST_CARD_REMOVAL (ctrl, rc);
1012 static const char hlp_pkauth[] =
1013 "PKAUTH <hexified_id>";
1015 cmd_pkauth (assuan_context_t ctx, char *line)
1017 ctrl_t ctrl = assuan_get_pointer (ctx);
1019 unsigned char *outdata;
1023 if ( IS_LOCKED (ctrl) )
1024 return gpg_error (GPG_ERR_LOCKED);
1026 if ((rc = open_card (ctrl, NULL)))
1030 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1032 /* We have to use a copy of the key ID because the function may use
1033 the pin_cb which in turn uses the assuan line buffer and thus
1034 overwriting the original line with the keyid */
1035 keyidstr = xtrystrdup (line);
1037 return out_of_core ();
1039 rc = app_auth (ctrl->app_ctx,
1042 ctrl->in_data.value, ctrl->in_data.valuelen,
1043 &outdata, &outdatalen);
1047 log_error ("app_auth failed: %s\n", gpg_strerror (rc));
1051 rc = assuan_send_data (ctx, outdata, outdatalen);
1054 return rc; /* that is already an assuan error code */
1057 TEST_CARD_REMOVAL (ctrl, rc);
1062 static const char hlp_pkdecrypt[] =
1063 "PKDECRYPT <hexified_id>";
1065 cmd_pkdecrypt (assuan_context_t ctx, char *line)
1067 ctrl_t ctrl = assuan_get_pointer (ctx);
1069 unsigned char *outdata;
1073 if ( IS_LOCKED (ctrl) )
1074 return gpg_error (GPG_ERR_LOCKED);
1076 if ((rc = open_card (ctrl, NULL)))
1079 keyidstr = xtrystrdup (line);
1081 return out_of_core ();
1082 rc = app_decipher (ctrl->app_ctx,
1085 ctrl->in_data.value, ctrl->in_data.valuelen,
1086 &outdata, &outdatalen);
1091 log_error ("app_decipher failed: %s\n", gpg_strerror (rc));
1095 rc = assuan_send_data (ctx, outdata, outdatalen);
1098 return rc; /* that is already an assuan error code */
1101 TEST_CARD_REMOVAL (ctrl, rc);
1106 static const char hlp_getattr[] =
1109 "This command is used to retrieve data from a smartcard. The\n"
1110 "allowed names depend on the currently selected smartcard\n"
1111 "application. NAME must be percent and '+' escaped. The value is\n"
1112 "returned through status message, see the LEARN command for details.\n"
1114 "However, the current implementation assumes that Name is not escaped;\n"
1115 "this works as long as noone uses arbitrary escaping. \n"
1117 "Note, that this function may even be used on a locked card.";
1119 cmd_getattr (assuan_context_t ctx, char *line)
1121 ctrl_t ctrl = assuan_get_pointer (ctx);
1123 const char *keyword;
1125 if ((rc = open_card (ctrl, NULL)))
1129 for (; *line && !spacep (line); line++)
1134 /* (We ignore any garbage for now.) */
1136 /* FIXME: Applications should not return sensitive data if the card
1138 rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
1140 TEST_CARD_REMOVAL (ctrl, rc);
1145 static const char hlp_setattr[] =
1146 "SETATTR <name> <value> \n"
1148 "This command is used to store data on a a smartcard. The allowed\n"
1149 "names and values are depend on the currently selected smartcard\n"
1150 "application. NAME and VALUE must be percent and '+' escaped.\n"
1152 "However, the current implementation assumes that NAME is not\n"
1153 "escaped; this works as long as noone uses arbitrary escaping.\n"
1155 "A PIN will be requested for most NAMEs. See the corresponding\n"
1156 "setattr function of the actually used application (app-*.c) for\n"
1159 cmd_setattr (assuan_context_t ctx, char *orig_line)
1161 ctrl_t ctrl = assuan_get_pointer (ctx);
1166 char *line, *linebuf;
1168 if ( IS_LOCKED (ctrl) )
1169 return gpg_error (GPG_ERR_LOCKED);
1171 if ((rc = open_card (ctrl, NULL)))
1174 /* We need to use a copy of LINE, because PIN_CB uses the same
1175 context and thus reuses the Assuan provided LINE. */
1176 line = linebuf = xtrystrdup (orig_line);
1178 return out_of_core ();
1181 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
1185 while (spacep (line))
1187 nbytes = percent_plus_unescape_inplace (line, 0);
1189 rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx,
1190 (const unsigned char*)line, nbytes);
1193 TEST_CARD_REMOVAL (ctrl, rc);
1198 static const char hlp_writecert[] =
1199 "WRITECERT <hexified_certid>\n"
1201 "This command is used to store a certifciate on a smartcard. The\n"
1202 "allowed certids depend on the currently selected smartcard\n"
1203 "application. The actual certifciate is requested using the inquiry\n"
1204 "\"CERTDATA\" and needs to be provided in its raw (e.g. DER) form.\n"
1206 "In almost all cases a a PIN will be requested. See the related\n"
1207 "writecert function of the actually used application (app-*.c) for\n"
1210 cmd_writecert (assuan_context_t ctx, char *line)
1212 ctrl_t ctrl = assuan_get_pointer (ctx);
1215 unsigned char *certdata;
1218 if ( IS_LOCKED (ctrl) )
1219 return gpg_error (GPG_ERR_LOCKED);
1221 line = skip_options (line);
1224 return set_error (GPG_ERR_ASS_PARAMETER, "no certid given");
1226 while (*line && !spacep (line))
1230 if ((rc = open_card (ctrl, NULL)))
1234 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1236 certid = xtrystrdup (certid);
1238 return out_of_core ();
1240 /* Now get the actual keydata. */
1241 rc = assuan_inquire (ctx, "CERTDATA",
1242 &certdata, &certdatalen, MAXLEN_CERTDATA);
1249 /* Write the certificate to the card. */
1250 rc = app_writecert (ctrl->app_ctx, ctrl, certid,
1251 pin_cb, ctx, certdata, certdatalen);
1255 TEST_CARD_REMOVAL (ctrl, rc);
1260 static const char hlp_writekey[] =
1261 "WRITEKEY [--force] <keyid> \n"
1263 "This command is used to store a secret key on a a smartcard. The\n"
1264 "allowed keyids depend on the currently selected smartcard\n"
1265 "application. The actual keydata is requested using the inquiry\n"
1266 "\"KEYDATA\" and need to be provided without any protection. With\n"
1267 "--force set an existing key under this KEYID will get overwritten.\n"
1268 "The keydata is expected to be the usual canonical encoded\n"
1271 "A PIN will be requested for most NAMEs. See the corresponding\n"
1272 "writekey function of the actually used application (app-*.c) for\n"
1275 cmd_writekey (assuan_context_t ctx, char *line)
1277 ctrl_t ctrl = assuan_get_pointer (ctx);
1280 int force = has_option (line, "--force");
1281 unsigned char *keydata;
1284 if ( IS_LOCKED (ctrl) )
1285 return gpg_error (GPG_ERR_LOCKED);
1287 line = skip_options (line);
1290 return set_error (GPG_ERR_ASS_PARAMETER, "no keyid given");
1292 while (*line && !spacep (line))
1296 if ((rc = open_card (ctrl, NULL)))
1300 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1302 keyid = xtrystrdup (keyid);
1304 return out_of_core ();
1306 /* Now get the actual keydata. */
1307 assuan_begin_confidential (ctx);
1308 rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA);
1309 assuan_end_confidential (ctx);
1316 /* Write the key to the card. */
1317 rc = app_writekey (ctrl->app_ctx, ctrl, keyid, force? 1:0,
1318 pin_cb, ctx, keydata, keydatalen);
1322 TEST_CARD_REMOVAL (ctrl, rc);
1327 static const char hlp_genkey[] =
1328 "GENKEY [--force] [--timestamp=<isodate>] <no>\n"
1330 "Generate a key on-card identified by NO, which is application\n"
1331 "specific. Return values are application specific. For OpenPGP\n"
1332 "cards 3 status lines are returned:\n"
1334 " S KEY-FPR <hexstring>\n"
1335 " S KEY-CREATED-AT <seconds_since_epoch>\n"
1336 " S KEY-DATA [-|p|n] <hexdata>\n"
1338 " 'p' and 'n' are the names of the RSA parameters; '-' is used to\n"
1339 " indicate that HEXDATA is the first chunk of a parameter given\n"
1340 " by the next KEY-DATA.\n"
1342 "--force is required to overwrite an already existing key. The\n"
1343 "KEY-CREATED-AT is required for further processing because it is\n"
1344 "part of the hashed key material for the fingerprint.\n"
1346 "If --timestamp is given an OpenPGP key will be created using this\n"
1347 "value. The value needs to be in ISO Format; e.g.\n"
1348 "\"--timestamp=20030316T120000\" and after 1970-01-01 00:00:00.\n"
1350 "The public part of the key can also later be retrieved using the\n"
1353 cmd_genkey (assuan_context_t ctx, char *line)
1355 ctrl_t ctrl = assuan_get_pointer (ctx);
1362 if ( IS_LOCKED (ctrl) )
1363 return gpg_error (GPG_ERR_LOCKED);
1365 force = has_option (line, "--force");
1367 if ((s=has_option_name (line, "--timestamp")))
1370 return set_error (GPG_ERR_ASS_PARAMETER, "missing value for option");
1371 timestamp = isotime2epoch (s+1);
1373 return set_error (GPG_ERR_ASS_PARAMETER, "invalid time value");
1379 line = skip_options (line);
1381 return set_error (GPG_ERR_ASS_PARAMETER, "no key number given");
1383 while (*line && !spacep (line))
1387 if ((rc = open_card (ctrl, NULL)))
1391 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1393 keyno = xtrystrdup (keyno);
1395 return out_of_core ();
1396 rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0,
1397 timestamp, pin_cb, ctx);
1400 TEST_CARD_REMOVAL (ctrl, rc);
1405 static const char hlp_random[] =
1408 "Get NBYTES of random from the card and send them back as data.\n"
1409 "This usually involves EEPROM write on the card and thus excessive\n"
1410 "use of this command may destroy the card.\n"
1412 "Note, that this function may be even be used on a locked card.";
1414 cmd_random (assuan_context_t ctx, char *line)
1416 ctrl_t ctrl = assuan_get_pointer (ctx);
1419 unsigned char *buffer;
1422 return set_error (GPG_ERR_ASS_PARAMETER,
1423 "number of requested bytes missing");
1424 nbytes = strtoul (line, NULL, 0);
1426 if ((rc = open_card (ctrl, NULL)))
1430 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1432 buffer = xtrymalloc (nbytes);
1434 return out_of_core ();
1436 rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
1439 rc = assuan_send_data (ctx, buffer, nbytes);
1441 return rc; /* that is already an assuan error code */
1445 TEST_CARD_REMOVAL (ctrl, rc);
1451 static const char hlp_passwd[] =
1452 "PASSWD [--reset] [--nullpin] <chvno>\n"
1454 "Change the PIN or, if --reset is given, reset the retry counter of\n"
1455 "the card holder verfication vector CHVNO. The option --nullpin is\n"
1456 "used for TCOS cards to set the initial PIN. The format of CHVNO\n"
1457 "depends on the card application.";
1459 cmd_passwd (assuan_context_t ctx, char *line)
1461 ctrl_t ctrl = assuan_get_pointer (ctx);
1464 unsigned int flags = 0;
1466 if (has_option (line, "--reset"))
1467 flags |= APP_CHANGE_FLAG_RESET;
1468 if (has_option (line, "--nullpin"))
1469 flags |= APP_CHANGE_FLAG_NULLPIN;
1471 if ( IS_LOCKED (ctrl) )
1472 return gpg_error (GPG_ERR_LOCKED);
1474 line = skip_options (line);
1477 return set_error (GPG_ERR_ASS_PARAMETER, "no CHV number given");
1479 while (*line && !spacep (line))
1483 if ((rc = open_card (ctrl, NULL)))
1487 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1489 chvnostr = xtrystrdup (chvnostr);
1491 return out_of_core ();
1492 rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, flags, pin_cb, ctx);
1494 log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1497 TEST_CARD_REMOVAL (ctrl, rc);
1502 static const char hlp_checkpin[] =
1503 "CHECKPIN <idstr>\n"
1505 "Perform a VERIFY operation without doing anything else. This may\n"
1506 "be used to initialize a the PIN cache earlier to long lasting\n"
1507 "operations. Its use is highly application dependent.\n"
1511 " Perform a simple verify operation for CHV1 and CHV2, so that\n"
1512 " further operations won't ask for CHV2 and it is possible to do a\n"
1513 " cheap check on the PIN: If there is something wrong with the PIN\n"
1514 " entry system, only the regular CHV will get blocked and not the\n"
1515 " dangerous CHV3. IDSTR is the usual card's serial number in hex\n"
1516 " notation; an optional fingerprint part will get ignored. There\n"
1517 " is however a special mode if the IDSTR is sffixed with the\n"
1518 " literal string \"[CHV3]\": In this case the Admin PIN is checked\n"
1519 " if and only if the retry counter is still at 3.\n"
1523 " Any of the valid PIN Ids may be used. These are the strings:\n"
1525 " PW1.CH - Global password 1\n"
1526 " PW2.CH - Global password 2\n"
1527 " PW1.CH.SIG - SigG password 1\n"
1528 " PW2.CH.SIG - SigG password 2\n"
1530 " For a definitive list, see the implementation in app-nks.c.\n"
1531 " Note that we call a PW2.* PIN a \"PUK\" despite that since TCOS\n"
1532 " 3.0 they are technically alternative PINs used to mutally\n"
1533 " unblock each other.";
1535 cmd_checkpin (assuan_context_t ctx, char *line)
1537 ctrl_t ctrl = assuan_get_pointer (ctx);
1541 if ( IS_LOCKED (ctrl) )
1542 return gpg_error (GPG_ERR_LOCKED);
1544 if ((rc = open_card (ctrl, NULL)))
1548 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1550 /* We have to use a copy of the key ID because the function may use
1551 the pin_cb which in turn uses the assuan line buffer and thus
1552 overwriting the original line with the keyid. */
1553 idstr = xtrystrdup (line);
1555 return out_of_core ();
1557 rc = app_check_pin (ctrl->app_ctx, idstr, pin_cb, ctx);
1560 log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
1562 TEST_CARD_REMOVAL (ctrl, rc);
1567 static const char hlp_lock[] =
1570 "Grant exclusive card access to this session. Note that there is\n"
1571 "no lock counter used and a second lock from the same session will\n"
1572 "be ignored. A single unlock (or RESET) unlocks the session.\n"
1573 "Return GPG_ERR_LOCKED if another session has locked the reader.\n"
1575 "If the option --wait is given the command will wait until a\n"
1576 "lock has been released.";
1578 cmd_lock (assuan_context_t ctx, char *line)
1580 ctrl_t ctrl = assuan_get_pointer (ctx);
1586 if (locked_session != ctrl->server_local)
1587 rc = gpg_error (GPG_ERR_LOCKED);
1590 locked_session = ctrl->server_local;
1593 if (rc && has_option (line, "--wait"))
1596 pth_sleep (1); /* Better implement an event mechanism. However,
1597 for card operations this should be
1599 /* FIXME: Need to check that the connection is still alive.
1600 This can be done by issuing status messages. */
1603 #endif /*USE_GNU_PTH*/
1606 log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
1611 static const char hlp_unlock[] =
1614 "Release exclusive card access.";
1616 cmd_unlock (assuan_context_t ctx, char *line)
1618 ctrl_t ctrl = assuan_get_pointer (ctx);
1625 if (locked_session != ctrl->server_local)
1626 rc = gpg_error (GPG_ERR_LOCKED);
1628 locked_session = NULL;
1631 rc = gpg_error (GPG_ERR_NOT_LOCKED);
1634 log_error ("cmd_unlock failed: %s\n", gpg_strerror (rc));
1639 static const char hlp_getinfo[] =
1642 "Multi purpose command to return certain information. \n"
1643 "Supported values of WHAT are:\n"
1645 "version - Return the version of the program.\n"
1646 "pid - Return the process id of the server.\n"
1648 "socket_name - Return the name of the socket.\n"
1650 "status - Return the status of the current slot (in the future, may\n"
1651 "also return the status of all slots). The status is a list of\n"
1652 "one-character flags. The following flags are currently defined:\n"
1653 " 'u' Usable card present. This is the normal state during operation.\n"
1654 " 'r' Card removed. A reset is necessary.\n"
1655 "These flags are exclusive.\n"
1657 "reader_list - Return a list of detected card readers. Does\n"
1658 " currently only work with the internal CCID driver.\n"
1660 "deny_admin - Returns OK if admin commands are not allowed or\n"
1661 " GPG_ERR_GENERAL if admin commands are allowed.\n"
1663 "app_list - Return a list of supported applications. One\n"
1664 " application per line, fields delimited by colons,\n"
1665 " first field is the name.";
1667 cmd_getinfo (assuan_context_t ctx, char *line)
1671 if (!strcmp (line, "version"))
1673 const char *s = VERSION;
1674 rc = assuan_send_data (ctx, s, strlen (s));
1676 else if (!strcmp (line, "pid"))
1680 snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1681 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1683 else if (!strcmp (line, "socket_name"))
1685 const char *s = scd_get_socket_name ();
1688 rc = assuan_send_data (ctx, s, strlen (s));
1690 rc = gpg_error (GPG_ERR_NO_DATA);
1692 else if (!strcmp (line, "status"))
1694 ctrl_t ctrl = assuan_get_pointer (ctx);
1695 int slot = ctrl->reader_slot;
1698 if (!ctrl->server_local->card_removed && slot != -1)
1700 struct slot_status_s *ss;
1702 if (!(slot >= 0 && slot < DIM(slot_table)))
1705 ss = &slot_table[slot];
1707 if (ss->valid && ss->any && (ss->status & 1))
1710 rc = assuan_send_data (ctx, &flag, 1);
1712 else if (!strcmp (line, "reader_list"))
1715 char *s = ccid_get_reader_list ();
1721 rc = assuan_send_data (ctx, s, strlen (s));
1723 rc = gpg_error (GPG_ERR_NO_DATA);
1726 else if (!strcmp (line, "deny_admin"))
1727 rc = opt.allow_admin? gpg_error (GPG_ERR_GENERAL) : 0;
1728 else if (!strcmp (line, "app_list"))
1730 char *s = get_supported_applications ();
1732 rc = assuan_send_data (ctx, s, strlen (s));
1738 rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1743 static const char hlp_restart[] =
1746 "Restart the current connection; this is a kind of warm reset. It\n"
1747 "deletes the context used by this connection but does not send a\n"
1748 "RESET to the card. Thus the card itself won't get reset. \n"
1750 "This is used by gpg-agent to reuse a primary pipe connection and\n"
1751 "may be used by clients to backup from a conflict in the serial\n"
1752 "command; i.e. to select another application.";
1754 cmd_restart (assuan_context_t ctx, char *line)
1756 ctrl_t ctrl = assuan_get_pointer (ctx);
1757 struct app_ctx_s *app = ctrl->app_ctx;
1763 ctrl->app_ctx = NULL;
1764 release_application (app);
1766 if (locked_session && ctrl->server_local == locked_session)
1768 locked_session = NULL;
1769 log_info ("implicitly unlocking due to RESTART\n");
1775 static const char hlp_disconnect[] =
1778 "Disconnect the card if it is not any longer used by other\n"
1779 "connections and the backend supports a disconnect operation.";
1781 cmd_disconnect (assuan_context_t ctx, char *line)
1783 ctrl_t ctrl = assuan_get_pointer (ctx);
1787 ctrl->server_local->disconnect_allowed = 1;
1793 static const char hlp_apdu[] =
1794 "APDU [--atr] [--more] [--exlen[=N]] [hexstring]\n"
1796 "Send an APDU to the current reader. This command bypasses the high\n"
1797 "level functions and sends the data directly to the card. HEXSTRING\n"
1798 "is expected to be a proper APDU. If HEXSTRING is not given no\n"
1799 "commands are set to the card but the command will implictly check\n"
1800 "whether the card is ready for use. \n"
1802 "Using the option \"--atr\" returns the ATR of the card as a status\n"
1803 "message before any data like this:\n"
1804 " S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1\n"
1806 "Using the option --more handles the card status word MORE_DATA\n"
1807 "(61xx) and concatenates all reponses to one block.\n"
1809 "Using the option \"--exlen\" the returned APDU may use extended\n"
1810 "length up to N bytes. If N is not given a default value is used\n"
1811 "(currently 4096).";
1813 cmd_apdu (assuan_context_t ctx, char *line)
1815 ctrl_t ctrl = assuan_get_pointer (ctx);
1817 unsigned char *apdu;
1824 with_atr = has_option (line, "--atr");
1825 handle_more = has_option (line, "--more");
1827 if ((s=has_option_name (line, "--exlen")))
1830 exlen = strtoul (s+1, NULL, 0);
1837 line = skip_options (line);
1839 if ( IS_LOCKED (ctrl) )
1840 return gpg_error (GPG_ERR_LOCKED);
1842 if ((rc = open_card (ctrl, NULL)))
1851 atr = apdu_get_atr (ctrl->reader_slot, &atrlen);
1852 if (!atr || atrlen > sizeof hexbuf - 2 )
1854 rc = gpg_error (GPG_ERR_INV_CARD);
1857 bin2hex (atr, atrlen, hexbuf);
1859 send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
1862 apdu = hex_to_buffer (line, &apdulen);
1865 rc = gpg_error_from_syserror ();
1870 unsigned char *result = NULL;
1873 rc = apdu_send_direct (ctrl->reader_slot, exlen,
1874 apdu, apdulen, handle_more,
1875 &result, &resultlen);
1877 log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
1880 rc = assuan_send_data (ctx, result, resultlen);
1887 TEST_CARD_REMOVAL (ctrl, rc);
1892 static const char hlp_killscd[] =
1897 cmd_killscd (assuan_context_t ctx, char *line)
1899 ctrl_t ctrl = assuan_get_pointer (ctx);
1903 ctrl->server_local->stopme = 1;
1904 return gpg_error (GPG_ERR_EOF);
1909 /* Tell the assuan library about our commands */
1911 register_commands (assuan_context_t ctx)
1915 assuan_handler_t handler;
1916 const char * const help;
1918 { "SERIALNO", cmd_serialno, hlp_serialno },
1919 { "LEARN", cmd_learn, hlp_learn },
1920 { "READCERT", cmd_readcert, hlp_readcert },
1921 { "READKEY", cmd_readkey, hlp_readkey },
1922 { "SETDATA", cmd_setdata, hlp_setdata },
1923 { "PKSIGN", cmd_pksign, hlp_pksign },
1924 { "PKAUTH", cmd_pkauth, hlp_pkauth },
1925 { "PKDECRYPT", cmd_pkdecrypt,hlp_pkdecrypt },
1928 { "GETATTR", cmd_getattr, hlp_getattr },
1929 { "SETATTR", cmd_setattr, hlp_setattr },
1930 { "WRITECERT", cmd_writecert,hlp_writecert },
1931 { "WRITEKEY", cmd_writekey, hlp_writekey },
1932 { "GENKEY", cmd_genkey, hlp_genkey },
1933 { "RANDOM", cmd_random, hlp_random },
1934 { "PASSWD", cmd_passwd, hlp_passwd },
1935 { "CHECKPIN", cmd_checkpin, hlp_checkpin },
1936 { "LOCK", cmd_lock, hlp_lock },
1937 { "UNLOCK", cmd_unlock, hlp_unlock },
1938 { "GETINFO", cmd_getinfo, hlp_getinfo },
1939 { "RESTART", cmd_restart, hlp_restart },
1940 { "DISCONNECT", cmd_disconnect,hlp_disconnect },
1941 { "APDU", cmd_apdu, hlp_apdu },
1942 { "KILLSCD", cmd_killscd, hlp_killscd },
1947 for (i=0; table[i].name; i++)
1949 rc = assuan_register_command (ctx, table[i].name, table[i].handler,
1954 assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
1956 assuan_register_reset_notify (ctx, reset_notify);
1957 assuan_register_option_handler (ctx, option_handler);
1962 /* Startup the server. If FD is given as -1 this is simple pipe
1963 server, otherwise it is a regular server. Returns true if there
1964 are no more active asessions. */
1966 scd_command_handler (ctrl_t ctrl, int fd)
1969 assuan_context_t ctx = NULL;
1972 rc = assuan_new (&ctx);
1975 log_error ("failed to allocate assuan context: %s\n",
1982 assuan_fd_t filedes[2];
1984 filedes[0] = assuan_fdopen (0);
1985 filedes[1] = assuan_fdopen (1);
1986 rc = assuan_init_pipe_server (ctx, filedes);
1990 rc = assuan_init_socket_server (ctx, INT2FD(fd),
1991 ASSUAN_SOCKET_SERVER_ACCEPTED);
1995 log_error ("failed to initialize the server: %s\n",
1999 rc = register_commands (ctx);
2002 log_error ("failed to register commands with Assuan: %s\n",
2006 assuan_set_pointer (ctx, ctrl);
2008 /* Allocate and initialize the server object. Put it into the list
2009 of active sessions. */
2010 ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
2011 ctrl->server_local->next_session = session_list;
2012 session_list = ctrl->server_local;
2013 ctrl->server_local->ctrl_backlink = ctrl;
2014 ctrl->server_local->assuan_ctx = ctx;
2017 assuan_set_log_stream (ctx, log_get_stream ());
2019 /* We open the reader right at startup so that the ticker is able to
2020 update the status file. */
2021 ctrl->reader_slot = get_reader_slot ();
2023 /* Command processing loop. */
2026 rc = assuan_accept (ctx);
2033 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
2037 rc = assuan_process (ctx);
2040 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
2045 /* Cleanup. We don't send an explicit reset to the card. */
2048 /* Release the server object. */
2049 if (session_list == ctrl->server_local)
2050 session_list = ctrl->server_local->next_session;
2053 struct server_local_s *sl;
2055 for (sl=session_list; sl->next_session; sl = sl->next_session)
2056 if (sl->next_session == ctrl->server_local)
2058 if (!sl->next_session)
2060 sl->next_session = ctrl->server_local->next_session;
2062 stopme = ctrl->server_local->stopme;
2063 xfree (ctrl->server_local);
2064 ctrl->server_local = NULL;
2066 /* Release the Assuan context. */
2067 assuan_release (ctx);
2072 /* If there are no more sessions return true. */
2073 return !session_list;
2077 /* Send a line with status information via assuan and escape all given
2078 buffers. The variable elements are pairs of (char *, size_t),
2079 terminated with a (NULL, 0). */
2081 send_status_info (ctrl_t ctrl, const char *keyword, ...)
2084 const unsigned char *value;
2088 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2090 va_start (arg_ptr, keyword);
2094 while ( (value = va_arg (arg_ptr, const unsigned char *)) )
2096 valuelen = va_arg (arg_ptr, size_t);
2098 continue; /* empty buffer */
2104 for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
2106 if (*value == '+' || *value == '\"' || *value == '%'
2109 sprintf (p, "%%%02X", *value);
2112 else if (*value == ' ')
2119 assuan_write_status (ctx, keyword, buf);
2125 /* Send a ready formatted status line via assuan. */
2127 send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
2129 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2131 if (strchr (args, '\n'))
2132 log_error ("error: LF detected in status line - not sending\n");
2134 assuan_write_status (ctx, keyword, args);
2138 /* Helper to send the clients a status change notification. */
2140 send_client_notifications (void)
2144 #ifdef HAVE_W32_SYSTEM
2152 struct server_local_s *sl;
2154 for (sl=session_list; sl; sl = sl->next_session)
2156 if (sl->event_signal && sl->assuan_ctx)
2158 pid_t pid = assuan_get_pid (sl->assuan_ctx);
2159 #ifdef HAVE_W32_SYSTEM
2160 HANDLE handle = (void *)sl->event_signal;
2162 for (kidx=0; kidx < killidx; kidx++)
2163 if (killed[kidx].pid == pid
2164 && killed[kidx].handle == handle)
2167 log_info ("event %lx (%p) already triggered for client %d\n",
2168 sl->event_signal, handle, (int)pid);
2171 log_info ("triggering event %lx (%p) for client %d\n",
2172 sl->event_signal, handle, (int)pid);
2173 if (!SetEvent (handle))
2174 log_error ("SetEvent(%lx) failed: %s\n",
2175 sl->event_signal, w32_strerror (-1));
2176 if (killidx < DIM (killed))
2178 killed[killidx].pid = pid;
2179 killed[killidx].handle = handle;
2183 #else /*!HAVE_W32_SYSTEM*/
2184 int signo = sl->event_signal;
2186 if (pid != (pid_t)(-1) && pid && signo > 0)
2188 for (kidx=0; kidx < killidx; kidx++)
2189 if (killed[kidx].pid == pid
2190 && killed[kidx].signo == signo)
2193 log_info ("signal %d already sent to client %d\n",
2197 log_info ("sending signal %d to client %d\n",
2200 if (killidx < DIM (killed))
2202 killed[killidx].pid = pid;
2203 killed[killidx].signo = signo;
2208 #endif /*!HAVE_W32_SYSTEM*/
2215 /* This is the core of scd_update_reader_status_file but the caller
2216 needs to take care of the locking. */
2218 update_reader_status_file (int set_card_removed_flag)
2221 unsigned int status, changed;
2223 /* Note, that we only try to get the status, because it does not
2224 make sense to wait here for a operation to complete. If we are
2225 busy working with a card, delays in the status file update should
2227 for (idx=0; idx < DIM(slot_table); idx++)
2229 struct slot_status_s *ss = slot_table + idx;
2230 struct server_local_s *sl;
2233 if (!ss->valid || ss->slot == -1)
2234 continue; /* Not valid or reader not yet open. */
2236 sw_apdu = apdu_get_status (ss->slot, 0, &status, &changed);
2237 if (sw_apdu == SW_HOST_NO_READER)
2239 /* Most likely the _reader_ has been unplugged. */
2240 apdu_close_reader (ss->slot);
2242 changed = ss->changed;
2246 /* Get status failed. Ignore that. */
2250 if (!ss->any || ss->status != status || ss->changed != changed )
2256 log_info ("updating slot %d status: 0x%04X->0x%04X (%u->%u)\n",
2257 ss->slot, ss->status, status, ss->changed, changed);
2258 ss->status = status;
2259 ss->changed = changed;
2261 /* FIXME: Should this be IDX instead of ss->slot? This
2262 depends on how client sessions will associate the reader
2263 status with their session. */
2264 snprintf (templ, sizeof templ, "reader_%d.status", ss->slot);
2265 fname = make_filename (opt.homedir, templ, NULL );
2266 fp = fopen (fname, "w");
2269 fprintf (fp, "%s\n",
2270 (status & 1)? "USABLE":
2271 (status & 4)? "ACTIVE":
2272 (status & 2)? "PRESENT": "NOCARD");
2277 /* If a status script is executable, run it. */
2279 const char *args[9], *envs[2];
2280 char numbuf1[30], numbuf2[30], numbuf3[30];
2281 char *homestr, *envstr;
2284 homestr = make_filename (opt.homedir, NULL);
2285 if (estream_asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
2286 log_error ("out of core while building environment\n");
2292 sprintf (numbuf1, "%d", ss->slot);
2293 sprintf (numbuf2, "0x%04X", ss->status);
2294 sprintf (numbuf3, "0x%04X", status);
2295 args[0] = "--reader-port";
2297 args[2] = "--old-code";
2299 args[4] = "--new-code";
2301 args[6] = "--status";
2302 args[7] = ((status & 1)? "USABLE":
2303 (status & 4)? "ACTIVE":
2304 (status & 2)? "PRESENT": "NOCARD");
2307 fname = make_filename (opt.homedir, "scd-event", NULL);
2308 err = gnupg_spawn_process_detached (fname, args, envs);
2309 if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
2310 log_error ("failed to run event handler `%s': %s\n",
2311 fname, gpg_strerror (err));
2318 /* Set the card removed flag for all current sessions. */
2319 if (ss->any && ss->status == 0 && set_card_removed_flag)
2320 update_card_removed (ss->slot, 1);
2324 /* Send a signal to all clients who applied for it. */
2325 send_client_notifications ();
2328 /* Check whether a disconnect is pending. */
2329 if (opt.card_timeout)
2331 for (sl=session_list; sl; sl = sl->next_session)
2332 if (!sl->disconnect_allowed)
2334 if (session_list && !sl)
2336 /* FIXME: Use a real timeout. */
2337 /* At least one connection and all allow a disconnect. */
2338 log_info ("disconnecting card in slot %d\n", ss->slot);
2339 apdu_disconnect (ss->slot);
2346 /* This function is called by the ticker thread to check for changes
2347 of the reader stati. It updates the reader status files and if
2348 requested by the caller also send a signal to the caller. */
2350 scd_update_reader_status_file (void)
2352 if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL))
2353 return; /* locked - give up. */
2354 update_reader_status_file (1);
2355 if (!pth_mutex_release (&status_file_update_lock))
2356 log_error ("failed to release status_file_update lock\n");