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 /* Flag indicating that the application context needs to be released
122 at the next opportunity. */
123 int app_ctx_marked_for_release;
125 /* A disconnect command has been sent. */
126 int disconnect_allowed;
128 /* If set to true we will be terminate ourself at the end of the
135 /* The table with information on all used slots. FIXME: This is a
136 different slot number than the one used by the APDU layer, and
137 should be renamed. */
138 static struct slot_status_s slot_table[10];
141 /* To keep track of all running sessions, we link all active server
142 contexts and the anchor in this variable. */
143 static struct server_local_s *session_list;
145 /* If a session has been locked we store a link to its server object
147 static struct server_local_s *locked_session;
149 /* While doing a reset we need to make sure that the ticker does not
150 call scd_update_reader_status_file while we are using it. */
151 static pth_mutex_t status_file_update_lock;
154 /*-- Local prototypes --*/
155 static void update_reader_status_file (int set_card_removed_flag);
160 /* This function must be called once to initialize this module. This
161 has to be done before a second thread is spawned. We can't do the
162 static initialization because Pth emulation code might not be able
163 to do a static init; in particular, it is not possible for W32. */
165 initialize_module_command (void)
167 static int initialized;
171 if (pth_mutex_init (&status_file_update_lock))
177 /* Update the CARD_REMOVED element of all sessions using the reader
178 given by SLOT to VALUE. */
180 update_card_removed (int slot, int value)
182 struct server_local_s *sl;
187 for (sl=session_list; sl; sl = sl->next_session)
188 if (sl->ctrl_backlink
189 && sl->ctrl_backlink->reader_slot == slot)
191 sl->card_removed = value;
193 /* Let the card application layer know about the removal. */
195 application_notify_card_reset (slot);
200 /* Check whether the option NAME appears in LINE. Returns 1 or 0. */
202 has_option (const char *line, const char *name)
205 int n = strlen (name);
207 s = strstr (line, name);
208 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
211 /* Same as has_option but does only test for the name of the option
212 and ignores an argument, i.e. with NAME being "--hash" it would
213 return a pointer for "--hash" as well as for "--hash=foo". If
214 there is no such option NULL is returned. The pointer returned
215 points right behind the option name, this may be an equal sign, Nul
218 has_option_name (const char *line, const char *name)
221 int n = strlen (name);
223 s = strstr (line, name);
224 return (s && (s == line || spacep (s-1))
225 && (!s[n] || spacep (s+n) || s[n] == '=')) ? (s+n) : NULL;
229 /* Skip over options. It is assumed that leading spaces have been
230 removed (this is the case for lines passed to a handler from
231 assuan). Blanks after the options are also removed. */
233 skip_options (char *line)
235 while ( *line == '-' && line[1] == '-' )
237 while (*line && !spacep (line))
239 while (spacep (line))
247 /* Convert the STRING into a newly allocated buffer while translating
248 the hex numbers. Stops at the first invalid character. Blanks and
249 colons are allowed to separate the hex digits. Returns NULL on
250 error or a newly malloced buffer and its length in LENGTH. */
251 static unsigned char *
252 hex_to_buffer (const char *string, size_t *r_length)
254 unsigned char *buffer;
258 buffer = xtrymalloc (strlen (string)+1);
261 for (s=string, n=0; *s; s++)
263 if (spacep (s) || *s == ':')
265 if (hexdigitp (s) && hexdigitp (s+1))
267 buffer[n++] = xtoi_2 (s);
279 /* Reset the card and free the application context. With SEND_RESET
280 set to true actually send a RESET to the reader; this is the normal
281 way of calling the function. */
283 do_reset (ctrl_t ctrl, int send_reset)
285 int slot = ctrl->reader_slot;
287 if (!(slot == -1 || (slot >= 0 && slot < DIM(slot_table))))
290 /* If there is an active application, release it. Tell all other
291 sessions using the same application to release the
295 release_application (ctrl->app_ctx);
296 ctrl->app_ctx = NULL;
299 struct server_local_s *sl;
301 for (sl=session_list; sl; sl = sl->next_session)
302 if (sl->ctrl_backlink
303 && sl->ctrl_backlink->reader_slot == slot)
305 sl->app_ctx_marked_for_release = 1;
310 /* If we want a real reset for the card, send the reset APDU and
311 tell the application layer about it. */
312 if (slot != -1 && send_reset && !IS_LOCKED (ctrl) )
314 application_notify_card_reset (slot);
315 switch (apdu_reset (slot))
319 case SW_HOST_NO_CARD:
320 case SW_HOST_CARD_INACTIVE:
323 apdu_close_reader (slot);
324 slot_table[slot].slot = -1;
329 /* If we hold a lock, unlock now. */
330 if (locked_session && ctrl->server_local == locked_session)
332 locked_session = NULL;
333 log_info ("implicitly unlocking due to RESET\n");
336 /* Reset the card removed flag for the current reader. We need to
337 take the lock here so that the ticker thread won't concurrently
338 try to update the file. Calling update_reader_status_file is
339 required to get hold of the new status of the card in the slot
341 if (!pth_mutex_acquire (&status_file_update_lock, 0, NULL))
343 log_error ("failed to acquire status_fle_update lock\n");
344 ctrl->reader_slot = -1;
347 update_reader_status_file (0); /* Update slot status table. */
348 update_card_removed (slot, 0); /* Clear card_removed flag. */
349 if (!pth_mutex_release (&status_file_update_lock))
350 log_error ("failed to release status_file_update lock\n");
352 /* Do this last, so that the update_card_removed above does its job. */
353 ctrl->reader_slot = -1;
358 reset_notify (assuan_context_t ctx, char *line)
360 ctrl_t ctrl = assuan_get_pointer (ctx);
370 option_handler (assuan_context_t ctx, const char *key, const char *value)
372 ctrl_t ctrl = assuan_get_pointer (ctx);
374 if (!strcmp (key, "event-signal"))
376 /* A value of 0 is allowed to reset the event signal. */
377 #ifdef HAVE_W32_SYSTEM
379 return gpg_error (GPG_ERR_ASS_PARAMETER);
380 ctrl->server_local->event_signal = strtoul (value, NULL, 16);
382 int i = *value? atoi (value) : -1;
384 return gpg_error (GPG_ERR_ASS_PARAMETER);
385 ctrl->server_local->event_signal = i;
393 /* Return the slot of the current reader or open the reader if no
394 other sessions are using a reader. Note, that we currently support
395 only one reader but most of the code (except for this function)
396 should be able to cope with several readers. */
398 get_reader_slot (void)
400 struct slot_status_s *ss;
402 ss = &slot_table[0]; /* One reader for now. */
404 /* Initialize the item if needed. */
411 /* Try to open the reader. */
414 ss->slot = apdu_open_reader (opt.reader_port);
416 /* If we still don't have a slot, we have no readers.
417 Invalidate for now until a reader is attached. */
425 /* Return the slot_table index. */
430 /* If the card has not yet been opened, do it. */
432 open_card (ctrl_t ctrl, const char *apptype)
437 /* If we ever got a card not present error code, return that. Only
438 the SERIALNO command and a reset are able to clear from that
440 if (ctrl->server_local->card_removed)
441 return gpg_error (GPG_ERR_CARD_REMOVED);
443 if ( IS_LOCKED (ctrl) )
444 return gpg_error (GPG_ERR_LOCKED);
446 /* If the application has been marked for release do it now. We
447 can't do it immediately in do_reset because the application may
449 if (ctrl->server_local->app_ctx_marked_for_release)
451 ctrl->server_local->app_ctx_marked_for_release = 0;
452 release_application (ctrl->app_ctx);
453 ctrl->app_ctx = NULL;
456 /* If we are already initialized for one specific application we
457 need to check that the client didn't requested a specific
458 application different from the one in use before we continue. */
460 return check_application_conflict (ctrl, apptype);
462 /* Setup the slot and select the application. */
463 if (ctrl->reader_slot != -1)
464 slot = ctrl->reader_slot;
466 slot = get_reader_slot ();
467 ctrl->reader_slot = slot;
469 err = gpg_error (GPG_ERR_CARD);
472 /* Fixme: We should move the apdu_connect call to
473 select_application. */
476 ctrl->server_local->disconnect_allowed = 0;
477 sw = apdu_connect (slot);
478 if (sw && sw != SW_HOST_ALREADY_CONNECTED)
480 if (sw == SW_HOST_NO_CARD)
481 err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
482 else if (sw == SW_HOST_CARD_INACTIVE)
483 err = gpg_error (GPG_ERR_CARD_RESET);
485 err = gpg_error (GPG_ERR_CARD);
488 err = select_application (ctrl, slot, apptype, &ctrl->app_ctx);
491 TEST_CARD_REMOVAL (ctrl, err);
496 static const char hlp_serialno[] =
497 "SERIALNO [<apptype>]\n"
499 "Return the serial number of the card using a status reponse. This\n"
500 "function should be used to check for the presence of a card.\n"
502 "If APPTYPE is given, an application of that type is selected and an\n"
503 "error is returned if the application is not supported or available.\n"
504 "The default is to auto-select the application using a hardwired\n"
505 "preference system. Note, that a future extension to this function\n"
506 "may allow to specify a list and order of applications to try.\n"
508 "This function is special in that it can be used to reset the card.\n"
509 "Most other functions will return an error when a card change has\n"
510 "been detected and the use of this function is therefore required.\n"
512 "Background: We want to keep the client clear of handling card\n"
513 "changes between operations; i.e. the client can assume that all\n"
514 "operations are done on the same card unless he calls this function.";
516 cmd_serialno (assuan_context_t ctx, char *line)
518 ctrl_t ctrl = assuan_get_pointer (ctx);
520 char *serial_and_stamp;
525 /* Clear the remove flag so that the open_card is able to reread it. */
527 if (ctrl->server_local->card_removed)
529 if ( IS_LOCKED (ctrl) )
530 return gpg_error (GPG_ERR_LOCKED);
534 if ((rc = open_card (ctrl, *line? line:NULL)))
536 /* In case of an inactive card, retry once. */
537 if (gpg_err_code (rc) == GPG_ERR_CARD_RESET && retries++ < 1)
542 rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
546 rc = estream_asprintf (&serial_and_stamp, "%s %lu",
547 serial, (unsigned long)stamp);
550 return out_of_core ();
552 assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
553 xfree (serial_and_stamp);
558 static const char hlp_learn[] =
559 "LEARN [--force] [--keypairinfo]\n"
561 "Learn all useful information of the currently inserted card. When\n"
562 "used without the force options, the command might do an INQUIRE\n"
565 " INQUIRE KNOWNCARDP <hexstring_with_serialNumber> <timestamp>\n"
567 "The client should just send an \"END\" if the processing should go on\n"
568 "or a \"CANCEL\" to force the function to terminate with a Cancel\n"
571 "With the option --keypairinfo only KEYPARIINFO lstatus lines are\n"
574 "The response of this command is a list of status lines formatted as\n"
577 " S APPTYPE <apptype>\n"
579 "This returns the type of the application, currently the strings:\n"
581 " P15 = PKCS-15 structure used\n"
582 " DINSIG = DIN SIG\n"
583 " OPENPGP = OpenPGP card\n"
584 " NKS = NetKey card\n"
586 "are implemented. These strings are aliases for the AID\n"
588 " S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id>\n"
590 "If there is no certificate yet stored on the card a single 'X' is\n"
591 "returned as the keygrip. In addition to the keypair info, information\n"
592 "about all certificates stored on the card is also returned:\n"
594 " S CERTINFO <certtype> <hexstring_with_id>\n"
596 "Where CERTTYPE is a number indicating the type of certificate:\n"
598 " 100 := Regular X.509 cert\n"
599 " 101 := Trusted X.509 cert\n"
600 " 102 := Useful X.509 cert\n"
601 " 110 := Root CA cert in a special format (e.g. DINSIG)\n"
602 " 111 := Root CA cert as standard X509 cert.\n"
604 "For certain cards, more information will be returned:\n"
606 " S KEY-FPR <no> <hexstring>\n"
608 "For OpenPGP cards this returns the stored fingerprints of the\n"
609 "keys. This can be used check whether a key is available on the\n"
610 "card. NO may be 1, 2 or 3.\n"
612 " S CA-FPR <no> <hexstring>\n"
614 "Similar to above, these are the fingerprints of keys assumed to be\n"
615 "ultimately trusted.\n"
617 " S DISP-NAME <name_of_card_holder>\n"
619 "The name of the card holder as stored on the card; percent\n"
620 "escaping takes place, spaces are encoded as '+'\n"
622 " S PUBKEY-URL <url>\n"
624 "The URL to be used for locating the entire public key.\n"
626 "Note, that this function may even be used on a locked card.";
628 cmd_learn (assuan_context_t ctx, char *line)
630 ctrl_t ctrl = assuan_get_pointer (ctx);
632 int only_keypairinfo = has_option (line, "--keypairinfo");
634 if ((rc = open_card (ctrl, NULL)))
637 /* Unless the force option is used we try a shortcut by identifying
638 the card using a serial number and inquiring the client with
639 that. The client may choose to cancel the operation if he already
640 knows about this card */
641 if (!only_keypairinfo)
643 char *serial_and_stamp;
647 rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
650 rc = estream_asprintf (&serial_and_stamp, "%s %lu",
651 serial, (unsigned long)stamp);
654 return out_of_core ();
656 assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
658 if (!has_option (line, "--force"))
662 rc = estream_asprintf (&command, "KNOWNCARDP %s", serial_and_stamp);
665 xfree (serial_and_stamp);
666 return out_of_core ();
669 rc = assuan_inquire (ctx, command, NULL, NULL, 0);
673 if (gpg_err_code (rc) != GPG_ERR_ASS_CANCELED)
674 log_error ("inquire KNOWNCARDP failed: %s\n",
676 xfree (serial_and_stamp);
679 /* Not canceled, so we have to proceeed. */
681 xfree (serial_and_stamp);
684 /* Let the application print out its collection of useful status
687 rc = app_write_learn_status (ctrl->app_ctx, ctrl, only_keypairinfo);
689 TEST_CARD_REMOVAL (ctrl, rc);
695 static const char hlp_readcert[] =
696 "READCERT <hexified_certid>|<keyid>\n"
698 "Note, that this function may even be used on a locked card.";
700 cmd_readcert (assuan_context_t ctx, char *line)
702 ctrl_t ctrl = assuan_get_pointer (ctx);
707 if ((rc = open_card (ctrl, NULL)))
710 line = xstrdup (line); /* Need a copy of the line. */
711 rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
713 log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
718 rc = assuan_send_data (ctx, cert, ncert);
724 TEST_CARD_REMOVAL (ctrl, rc);
729 static const char hlp_readkey[] =
732 "Return the public key for the given cert or key ID as a standard\n"
735 "Note, that this function may even be used on a locked card.";
737 cmd_readkey (assuan_context_t ctx, char *line)
739 ctrl_t ctrl = assuan_get_pointer (ctx);
741 unsigned char *cert = NULL;
743 ksba_cert_t kc = NULL;
748 if ((rc = open_card (ctrl, NULL)))
751 line = xstrdup (line); /* Need a copy of the line. */
752 /* If the application supports the READKEY function we use that.
753 Otherwise we use the old way by extracting it from the
755 rc = app_readkey (ctrl->app_ctx, line, &pk, &pklen);
757 { /* Yeah, got that key - send it back. */
758 rc = assuan_send_data (ctx, pk, pklen);
765 if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION)
766 log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
769 rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
771 log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
778 rc = ksba_cert_new (&kc);
782 rc = ksba_cert_init_from_mem (kc, cert, ncert);
785 log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
789 p = ksba_cert_get_public_key (kc);
792 rc = gpg_error (GPG_ERR_NO_PUBKEY);
796 n = gcry_sexp_canon_len (p, 0, NULL, NULL);
797 rc = assuan_send_data (ctx, p, n);
802 ksba_cert_release (kc);
804 TEST_CARD_REMOVAL (ctrl, rc);
810 static const char hlp_setdata[] =
811 "SETDATA [--append] <hexstring>\n"
813 "The client should use this command to tell us the data he want to sign.\n"
814 "With the option --append, the data is appended to the data set by a\n"
815 "previous SETDATA command.";
817 cmd_setdata (assuan_context_t ctx, char *line)
819 ctrl_t ctrl = assuan_get_pointer (ctx);
825 append = (ctrl->in_data.value && has_option (line, "--append"));
827 line = skip_options (line);
829 if (locked_session && locked_session != ctrl->server_local)
830 return gpg_error (GPG_ERR_LOCKED);
832 /* Parse the hexstring. */
833 for (p=line,n=0; hexdigitp (p); p++, n++)
836 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
838 return set_error (GPG_ERR_ASS_PARAMETER, "no data given");
840 return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
844 if (ctrl->in_data.valuelen + n > MAXLEN_SETDATA)
845 return set_error (GPG_ERR_TOO_LARGE,
846 "limit on total size of data reached");
847 buf = xtrymalloc (ctrl->in_data.valuelen + n);
850 buf = xtrymalloc (n);
852 return out_of_core ();
856 memcpy (buf, ctrl->in_data.value, ctrl->in_data.valuelen);
857 off = ctrl->in_data.valuelen;
861 for (p=line, i=0; i < n; p += 2, i++)
862 buf[off+i] = xtoi_2 (p);
864 ctrl->in_data.value = buf;
865 ctrl->in_data.valuelen = off + n;
872 pin_cb (void *opaque, const char *info, char **retstr)
874 assuan_context_t ctx = opaque;
877 unsigned char *value;
882 /* We prompt for pinpad entry. To make sure that the popup has
883 been show we use an inquire and not just a status message.
884 We ignore any value returned. */
887 log_debug ("prompting for pinpad entry '%s'\n", info);
888 rc = estream_asprintf (&command, "POPUPPINPADPROMPT %s", info);
890 return gpg_error (gpg_err_code_from_errno (errno));
891 rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
896 log_debug ("dismiss pinpad entry prompt\n");
897 rc = assuan_inquire (ctx, "DISMISSPINPADPROMPT",
898 &value, &valuelen, MAXLEN_PIN);
906 log_debug ("asking for PIN '%s'\n", info);
908 rc = estream_asprintf (&command, "NEEDPIN %s", info);
910 return gpg_error (gpg_err_code_from_errno (errno));
912 /* Fixme: Write an inquire function which returns the result in
913 secure memory and check all further handling of the PIN. */
914 rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
919 if (!valuelen || value[valuelen-1])
921 /* We require that the returned value is an UTF-8 string */
923 return gpg_error (GPG_ERR_INV_RESPONSE);
925 *retstr = (char*)value;
930 static const char hlp_pksign[] =
931 "PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5]] <hexified_id>\n"
933 "The --hash option is optional; the default is SHA1.";
935 cmd_pksign (assuan_context_t ctx, char *line)
937 ctrl_t ctrl = assuan_get_pointer (ctx);
939 unsigned char *outdata;
944 if (has_option (line, "--hash=rmd160"))
945 hash_algo = GCRY_MD_RMD160;
946 else if (has_option (line, "--hash=sha1"))
947 hash_algo = GCRY_MD_SHA1;
948 else if (has_option (line, "--hash=sha224"))
949 hash_algo = GCRY_MD_SHA224;
950 else if (has_option (line, "--hash=sha256"))
951 hash_algo = GCRY_MD_SHA256;
952 else if (has_option (line, "--hash=sha384"))
953 hash_algo = GCRY_MD_SHA384;
954 else if (has_option (line, "--hash=sha512"))
955 hash_algo = GCRY_MD_SHA512;
956 else if (has_option (line, "--hash=md5"))
957 hash_algo = GCRY_MD_MD5;
958 else if (!strstr (line, "--"))
959 hash_algo = GCRY_MD_SHA1;
961 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
963 line = skip_options (line);
965 if ( IS_LOCKED (ctrl) )
966 return gpg_error (GPG_ERR_LOCKED);
968 if ((rc = open_card (ctrl, NULL)))
971 /* We have to use a copy of the key ID because the function may use
972 the pin_cb which in turn uses the assuan line buffer and thus
973 overwriting the original line with the keyid */
974 keyidstr = xtrystrdup (line);
976 return out_of_core ();
978 rc = app_sign (ctrl->app_ctx,
981 ctrl->in_data.value, ctrl->in_data.valuelen,
982 &outdata, &outdatalen);
987 log_error ("app_sign failed: %s\n", gpg_strerror (rc));
991 rc = assuan_send_data (ctx, outdata, outdatalen);
994 return rc; /* that is already an assuan error code */
997 TEST_CARD_REMOVAL (ctrl, rc);
1002 static const char hlp_pkauth[] =
1003 "PKAUTH <hexified_id>";
1005 cmd_pkauth (assuan_context_t ctx, char *line)
1007 ctrl_t ctrl = assuan_get_pointer (ctx);
1009 unsigned char *outdata;
1013 if ( IS_LOCKED (ctrl) )
1014 return gpg_error (GPG_ERR_LOCKED);
1016 if ((rc = open_card (ctrl, NULL)))
1020 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1022 /* We have to use a copy of the key ID because the function may use
1023 the pin_cb which in turn uses the assuan line buffer and thus
1024 overwriting the original line with the keyid */
1025 keyidstr = xtrystrdup (line);
1027 return out_of_core ();
1029 rc = app_auth (ctrl->app_ctx,
1032 ctrl->in_data.value, ctrl->in_data.valuelen,
1033 &outdata, &outdatalen);
1037 log_error ("app_auth failed: %s\n", gpg_strerror (rc));
1041 rc = assuan_send_data (ctx, outdata, outdatalen);
1044 return rc; /* that is already an assuan error code */
1047 TEST_CARD_REMOVAL (ctrl, rc);
1052 static const char hlp_pkdecrypt[] =
1053 "PKDECRYPT <hexified_id>";
1055 cmd_pkdecrypt (assuan_context_t ctx, char *line)
1057 ctrl_t ctrl = assuan_get_pointer (ctx);
1059 unsigned char *outdata;
1063 if ( IS_LOCKED (ctrl) )
1064 return gpg_error (GPG_ERR_LOCKED);
1066 if ((rc = open_card (ctrl, NULL)))
1069 keyidstr = xtrystrdup (line);
1071 return out_of_core ();
1072 rc = app_decipher (ctrl->app_ctx,
1075 ctrl->in_data.value, ctrl->in_data.valuelen,
1076 &outdata, &outdatalen);
1081 log_error ("app_decipher failed: %s\n", gpg_strerror (rc));
1085 rc = assuan_send_data (ctx, outdata, outdatalen);
1088 return rc; /* that is already an assuan error code */
1091 TEST_CARD_REMOVAL (ctrl, rc);
1096 static const char hlp_getattr[] =
1099 "This command is used to retrieve data from a smartcard. The\n"
1100 "allowed names depend on the currently selected smartcard\n"
1101 "application. NAME must be percent and '+' escaped. The value is\n"
1102 "returned through status message, see the LEARN command for details.\n"
1104 "However, the current implementation assumes that Name is not escaped;\n"
1105 "this works as long as noone uses arbitrary escaping. \n"
1107 "Note, that this function may even be used on a locked card.";
1109 cmd_getattr (assuan_context_t ctx, char *line)
1111 ctrl_t ctrl = assuan_get_pointer (ctx);
1113 const char *keyword;
1115 if ((rc = open_card (ctrl, NULL)))
1119 for (; *line && !spacep (line); line++)
1124 /* (We ignore any garbage for now.) */
1126 /* FIXME: Applications should not return sensitive data if the card
1128 rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
1130 TEST_CARD_REMOVAL (ctrl, rc);
1135 static const char hlp_setattr[] =
1136 "SETATTR <name> <value> \n"
1138 "This command is used to store data on a a smartcard. The allowed\n"
1139 "names and values are depend on the currently selected smartcard\n"
1140 "application. NAME and VALUE must be percent and '+' escaped.\n"
1142 "However, the current implementation assumes that NAME is not\n"
1143 "escaped; this works as long as noone uses arbitrary escaping.\n"
1145 "A PIN will be requested for most NAMEs. See the corresponding\n"
1146 "setattr function of the actually used application (app-*.c) for\n"
1149 cmd_setattr (assuan_context_t ctx, char *orig_line)
1151 ctrl_t ctrl = assuan_get_pointer (ctx);
1156 char *line, *linebuf;
1158 if ( IS_LOCKED (ctrl) )
1159 return gpg_error (GPG_ERR_LOCKED);
1161 if ((rc = open_card (ctrl, NULL)))
1164 /* We need to use a copy of LINE, because PIN_CB uses the same
1165 context and thus reuses the Assuan provided LINE. */
1166 line = linebuf = xtrystrdup (orig_line);
1168 return out_of_core ();
1171 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
1175 while (spacep (line))
1177 nbytes = percent_plus_unescape_inplace (line, 0);
1179 rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx,
1180 (const unsigned char*)line, nbytes);
1183 TEST_CARD_REMOVAL (ctrl, rc);
1188 static const char hlp_writecert[] =
1189 "WRITECERT <hexified_certid>\n"
1191 "This command is used to store a certifciate on a smartcard. The\n"
1192 "allowed certids depend on the currently selected smartcard\n"
1193 "application. The actual certifciate is requested using the inquiry\n"
1194 "\"CERTDATA\" and needs to be provided in its raw (e.g. DER) form.\n"
1196 "In almost all cases a a PIN will be requested. See the related\n"
1197 "writecert function of the actually used application (app-*.c) for\n"
1200 cmd_writecert (assuan_context_t ctx, char *line)
1202 ctrl_t ctrl = assuan_get_pointer (ctx);
1205 unsigned char *certdata;
1208 if ( IS_LOCKED (ctrl) )
1209 return gpg_error (GPG_ERR_LOCKED);
1211 line = skip_options (line);
1214 return set_error (GPG_ERR_ASS_PARAMETER, "no certid given");
1216 while (*line && !spacep (line))
1220 if ((rc = open_card (ctrl, NULL)))
1224 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1226 certid = xtrystrdup (certid);
1228 return out_of_core ();
1230 /* Now get the actual keydata. */
1231 rc = assuan_inquire (ctx, "CERTDATA",
1232 &certdata, &certdatalen, MAXLEN_CERTDATA);
1239 /* Write the certificate to the card. */
1240 rc = app_writecert (ctrl->app_ctx, ctrl, certid,
1241 pin_cb, ctx, certdata, certdatalen);
1245 TEST_CARD_REMOVAL (ctrl, rc);
1250 static const char hlp_writekey[] =
1251 "WRITEKEY [--force] <keyid> \n"
1253 "This command is used to store a secret key on a a smartcard. The\n"
1254 "allowed keyids depend on the currently selected smartcard\n"
1255 "application. The actual keydata is requested using the inquiry\n"
1256 "\"KEYDATA\" and need to be provided without any protection. With\n"
1257 "--force set an existing key under this KEYID will get overwritten.\n"
1258 "The keydata is expected to be the usual canonical encoded\n"
1261 "A PIN will be requested for most NAMEs. See the corresponding\n"
1262 "writekey function of the actually used application (app-*.c) for\n"
1265 cmd_writekey (assuan_context_t ctx, char *line)
1267 ctrl_t ctrl = assuan_get_pointer (ctx);
1270 int force = has_option (line, "--force");
1271 unsigned char *keydata;
1274 if ( IS_LOCKED (ctrl) )
1275 return gpg_error (GPG_ERR_LOCKED);
1277 line = skip_options (line);
1280 return set_error (GPG_ERR_ASS_PARAMETER, "no keyid given");
1282 while (*line && !spacep (line))
1286 if ((rc = open_card (ctrl, NULL)))
1290 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1292 keyid = xtrystrdup (keyid);
1294 return out_of_core ();
1296 /* Now get the actual keydata. */
1297 assuan_begin_confidential (ctx);
1298 rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA);
1299 assuan_end_confidential (ctx);
1306 /* Write the key to the card. */
1307 rc = app_writekey (ctrl->app_ctx, ctrl, keyid, force? 1:0,
1308 pin_cb, ctx, keydata, keydatalen);
1312 TEST_CARD_REMOVAL (ctrl, rc);
1317 static const char hlp_genkey[] =
1318 "GENKEY [--force] [--timestamp=<isodate>] <no>\n"
1320 "Generate a key on-card identified by NO, which is application\n"
1321 "specific. Return values are application specific. For OpenPGP\n"
1322 "cards 3 status lines are returned:\n"
1324 " S KEY-FPR <hexstring>\n"
1325 " S KEY-CREATED-AT <seconds_since_epoch>\n"
1326 " S KEY-DATA [-|p|n] <hexdata>\n"
1328 " 'p' and 'n' are the names of the RSA parameters; '-' is used to\n"
1329 " indicate that HEXDATA is the first chunk of a parameter given\n"
1330 " by the next KEY-DATA.\n"
1332 "--force is required to overwrite an already existing key. The\n"
1333 "KEY-CREATED-AT is required for further processing because it is\n"
1334 "part of the hashed key material for the fingerprint.\n"
1336 "If --timestamp is given an OpenPGP key will be created using this\n"
1337 "value. The value needs to be in ISO Format; e.g.\n"
1338 "\"--timestamp=20030316T120000\" and after 1970-01-01 00:00:00.\n"
1340 "The public part of the key can also later be retrieved using the\n"
1343 cmd_genkey (assuan_context_t ctx, char *line)
1345 ctrl_t ctrl = assuan_get_pointer (ctx);
1352 if ( IS_LOCKED (ctrl) )
1353 return gpg_error (GPG_ERR_LOCKED);
1355 force = has_option (line, "--force");
1357 if ((s=has_option_name (line, "--timestamp")))
1360 return set_error (GPG_ERR_ASS_PARAMETER, "missing value for option");
1361 timestamp = isotime2epoch (s+1);
1363 return set_error (GPG_ERR_ASS_PARAMETER, "invalid time value");
1369 line = skip_options (line);
1371 return set_error (GPG_ERR_ASS_PARAMETER, "no key number given");
1373 while (*line && !spacep (line))
1377 if ((rc = open_card (ctrl, NULL)))
1381 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1383 keyno = xtrystrdup (keyno);
1385 return out_of_core ();
1386 rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0,
1387 timestamp, pin_cb, ctx);
1390 TEST_CARD_REMOVAL (ctrl, rc);
1395 static const char hlp_random[] =
1398 "Get NBYTES of random from the card and send them back as data.\n"
1399 "This usually involves EEPROM write on the card and thus excessive\n"
1400 "use of this command may destroy the card.\n"
1402 "Note, that this function may be even be used on a locked card.";
1404 cmd_random (assuan_context_t ctx, char *line)
1406 ctrl_t ctrl = assuan_get_pointer (ctx);
1409 unsigned char *buffer;
1412 return set_error (GPG_ERR_ASS_PARAMETER,
1413 "number of requested bytes missing");
1414 nbytes = strtoul (line, NULL, 0);
1416 if ((rc = open_card (ctrl, NULL)))
1420 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1422 buffer = xtrymalloc (nbytes);
1424 return out_of_core ();
1426 rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
1429 rc = assuan_send_data (ctx, buffer, nbytes);
1431 return rc; /* that is already an assuan error code */
1435 TEST_CARD_REMOVAL (ctrl, rc);
1441 static const char hlp_passwd[] =
1442 "PASSWD [--reset] [--nullpin] <chvno>\n"
1444 "Change the PIN or, if --reset is given, reset the retry counter of\n"
1445 "the card holder verfication vector CHVNO. The option --nullpin is\n"
1446 "used for TCOS cards to set the initial PIN. The format of CHVNO\n"
1447 "depends on the card application.";
1449 cmd_passwd (assuan_context_t ctx, char *line)
1451 ctrl_t ctrl = assuan_get_pointer (ctx);
1454 unsigned int flags = 0;
1456 if (has_option (line, "--reset"))
1457 flags |= APP_CHANGE_FLAG_RESET;
1458 if (has_option (line, "--nullpin"))
1459 flags |= APP_CHANGE_FLAG_NULLPIN;
1461 if ( IS_LOCKED (ctrl) )
1462 return gpg_error (GPG_ERR_LOCKED);
1464 line = skip_options (line);
1467 return set_error (GPG_ERR_ASS_PARAMETER, "no CHV number given");
1469 while (*line && !spacep (line))
1473 if ((rc = open_card (ctrl, NULL)))
1477 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1479 chvnostr = xtrystrdup (chvnostr);
1481 return out_of_core ();
1482 rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, flags, pin_cb, ctx);
1484 log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1487 TEST_CARD_REMOVAL (ctrl, rc);
1492 static const char hlp_checkpin[] =
1493 "CHECKPIN <idstr>\n"
1495 "Perform a VERIFY operation without doing anything else. This may\n"
1496 "be used to initialize a the PIN cache earlier to long lasting\n"
1497 "operations. Its use is highly application dependent.\n"
1501 " Perform a simple verify operation for CHV1 and CHV2, so that\n"
1502 " further operations won't ask for CHV2 and it is possible to do a\n"
1503 " cheap check on the PIN: If there is something wrong with the PIN\n"
1504 " entry system, only the regular CHV will get blocked and not the\n"
1505 " dangerous CHV3. IDSTR is the usual card's serial number in hex\n"
1506 " notation; an optional fingerprint part will get ignored. There\n"
1507 " is however a special mode if the IDSTR is sffixed with the\n"
1508 " literal string \"[CHV3]\": In this case the Admin PIN is checked\n"
1509 " if and only if the retry counter is still at 3.\n"
1513 " Any of the valid PIN Ids may be used. These are the strings:\n"
1515 " PW1.CH - Global password 1\n"
1516 " PW2.CH - Global password 2\n"
1517 " PW1.CH.SIG - SigG password 1\n"
1518 " PW2.CH.SIG - SigG password 2\n"
1520 " For a definitive list, see the implementation in app-nks.c.\n"
1521 " Note that we call a PW2.* PIN a \"PUK\" despite that since TCOS\n"
1522 " 3.0 they are technically alternative PINs used to mutally\n"
1523 " unblock each other.";
1525 cmd_checkpin (assuan_context_t ctx, char *line)
1527 ctrl_t ctrl = assuan_get_pointer (ctx);
1531 if ( IS_LOCKED (ctrl) )
1532 return gpg_error (GPG_ERR_LOCKED);
1534 if ((rc = open_card (ctrl, NULL)))
1538 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1540 /* We have to use a copy of the key ID because the function may use
1541 the pin_cb which in turn uses the assuan line buffer and thus
1542 overwriting the original line with the keyid. */
1543 idstr = xtrystrdup (line);
1545 return out_of_core ();
1547 rc = app_check_pin (ctrl->app_ctx, idstr, pin_cb, ctx);
1550 log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
1552 TEST_CARD_REMOVAL (ctrl, rc);
1557 static const char hlp_lock[] =
1560 "Grant exclusive card access to this session. Note that there is\n"
1561 "no lock counter used and a second lock from the same session will\n"
1562 "be ignored. A single unlock (or RESET) unlocks the session.\n"
1563 "Return GPG_ERR_LOCKED if another session has locked the reader.\n"
1565 "If the option --wait is given the command will wait until a\n"
1566 "lock has been released.";
1568 cmd_lock (assuan_context_t ctx, char *line)
1570 ctrl_t ctrl = assuan_get_pointer (ctx);
1576 if (locked_session != ctrl->server_local)
1577 rc = gpg_error (GPG_ERR_LOCKED);
1580 locked_session = ctrl->server_local;
1583 if (rc && has_option (line, "--wait"))
1586 pth_sleep (1); /* Better implement an event mechanism. However,
1587 for card operations this should be
1589 /* FIXME: Need to check that the connection is still alive.
1590 This can be done by issuing status messages. */
1593 #endif /*USE_GNU_PTH*/
1596 log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
1601 static const char hlp_unlock[] =
1604 "Release exclusive card access.";
1606 cmd_unlock (assuan_context_t ctx, char *line)
1608 ctrl_t ctrl = assuan_get_pointer (ctx);
1615 if (locked_session != ctrl->server_local)
1616 rc = gpg_error (GPG_ERR_LOCKED);
1618 locked_session = NULL;
1621 rc = gpg_error (GPG_ERR_NOT_LOCKED);
1624 log_error ("cmd_unlock failed: %s\n", gpg_strerror (rc));
1629 static const char hlp_getinfo[] =
1632 "Multi purpose command to return certain information. \n"
1633 "Supported values of WHAT are:\n"
1635 "version - Return the version of the program.\n"
1636 "pid - Return the process id of the server.\n"
1638 "socket_name - Return the name of the socket.\n"
1640 "status - Return the status of the current slot (in the future, may\n"
1641 "also return the status of all slots). The status is a list of\n"
1642 "one-character flags. The following flags are currently defined:\n"
1643 " 'u' Usable card present. This is the normal state during operation.\n"
1644 " 'r' Card removed. A reset is necessary.\n"
1645 "These flags are exclusive.\n"
1647 "reader_list - Return a list of detected card readers. Does\n"
1648 " currently only work with the internal CCID driver.\n"
1650 "deny_admin - Returns OK if admin commands are not allowed or\n"
1651 " GPG_ERR_GENERAL if admin commands are allowed.\n"
1653 "app_list - Return a list of supported applications. One\n"
1654 " application per line, fields delimited by colons,\n"
1655 " first field is the name.";
1657 cmd_getinfo (assuan_context_t ctx, char *line)
1661 if (!strcmp (line, "version"))
1663 const char *s = VERSION;
1664 rc = assuan_send_data (ctx, s, strlen (s));
1666 else if (!strcmp (line, "pid"))
1670 snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1671 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1673 else if (!strcmp (line, "socket_name"))
1675 const char *s = scd_get_socket_name ();
1678 rc = assuan_send_data (ctx, s, strlen (s));
1680 rc = gpg_error (GPG_ERR_NO_DATA);
1682 else if (!strcmp (line, "status"))
1684 ctrl_t ctrl = assuan_get_pointer (ctx);
1685 int slot = ctrl->reader_slot;
1688 if (!ctrl->server_local->card_removed && slot != -1)
1690 struct slot_status_s *ss;
1692 if (!(slot >= 0 && slot < DIM(slot_table)))
1695 ss = &slot_table[slot];
1697 if (ss->valid && ss->any && (ss->status & 1))
1700 rc = assuan_send_data (ctx, &flag, 1);
1702 else if (!strcmp (line, "reader_list"))
1705 char *s = ccid_get_reader_list ();
1711 rc = assuan_send_data (ctx, s, strlen (s));
1713 rc = gpg_error (GPG_ERR_NO_DATA);
1716 else if (!strcmp (line, "deny_admin"))
1717 rc = opt.allow_admin? gpg_error (GPG_ERR_GENERAL) : 0;
1718 else if (!strcmp (line, "app_list"))
1720 char *s = get_supported_applications ();
1722 rc = assuan_send_data (ctx, s, strlen (s));
1728 rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1733 static const char hlp_restart[] =
1736 "Restart the current connection; this is a kind of warm reset. It\n"
1737 "deletes the context used by this connection but does not send a\n"
1738 "RESET to the card. Thus the card itself won't get reset. \n"
1740 "This is used by gpg-agent to reuse a primary pipe connection and\n"
1741 "may be used by clients to backup from a conflict in the serial\n"
1742 "command; i.e. to select another application.";
1744 cmd_restart (assuan_context_t ctx, char *line)
1746 ctrl_t ctrl = assuan_get_pointer (ctx);
1752 release_application (ctrl->app_ctx);
1753 ctrl->app_ctx = NULL;
1755 if (locked_session && ctrl->server_local == locked_session)
1757 locked_session = NULL;
1758 log_info ("implicitly unlocking due to RESTART\n");
1764 static const char hlp_disconnect[] =
1767 "Disconnect the card if it is not any longer used by other\n"
1768 "connections and the backend supports a disconnect operation.";
1770 cmd_disconnect (assuan_context_t ctx, char *line)
1772 ctrl_t ctrl = assuan_get_pointer (ctx);
1776 ctrl->server_local->disconnect_allowed = 1;
1782 static const char hlp_apdu[] =
1783 "APDU [--atr] [--more] [--exlen[=N]] [hexstring]\n"
1785 "Send an APDU to the current reader. This command bypasses the high\n"
1786 "level functions and sends the data directly to the card. HEXSTRING\n"
1787 "is expected to be a proper APDU. If HEXSTRING is not given no\n"
1788 "commands are set to the card but the command will implictly check\n"
1789 "whether the card is ready for use. \n"
1791 "Using the option \"--atr\" returns the ATR of the card as a status\n"
1792 "message before any data like this:\n"
1793 " S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1\n"
1795 "Using the option --more handles the card status word MORE_DATA\n"
1796 "(61xx) and concatenates all reponses to one block.\n"
1798 "Using the option \"--exlen\" the returned APDU may use extended\n"
1799 "length up to N bytes. If N is not given a default value is used\n"
1800 "(currently 4096).";
1802 cmd_apdu (assuan_context_t ctx, char *line)
1804 ctrl_t ctrl = assuan_get_pointer (ctx);
1806 unsigned char *apdu;
1813 with_atr = has_option (line, "--atr");
1814 handle_more = has_option (line, "--more");
1816 if ((s=has_option_name (line, "--exlen")))
1819 exlen = strtoul (s+1, NULL, 0);
1826 line = skip_options (line);
1828 if ( IS_LOCKED (ctrl) )
1829 return gpg_error (GPG_ERR_LOCKED);
1831 if ((rc = open_card (ctrl, NULL)))
1840 atr = apdu_get_atr (ctrl->reader_slot, &atrlen);
1841 if (!atr || atrlen > sizeof hexbuf - 2 )
1843 rc = gpg_error (GPG_ERR_INV_CARD);
1846 bin2hex (atr, atrlen, hexbuf);
1848 send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
1851 apdu = hex_to_buffer (line, &apdulen);
1854 rc = gpg_error_from_syserror ();
1859 unsigned char *result = NULL;
1862 rc = apdu_send_direct (ctrl->reader_slot, exlen,
1863 apdu, apdulen, handle_more,
1864 &result, &resultlen);
1866 log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
1869 rc = assuan_send_data (ctx, result, resultlen);
1876 TEST_CARD_REMOVAL (ctrl, rc);
1881 static const char hlp_killscd[] =
1886 cmd_killscd (assuan_context_t ctx, char *line)
1888 ctrl_t ctrl = assuan_get_pointer (ctx);
1892 ctrl->server_local->stopme = 1;
1893 return gpg_error (GPG_ERR_EOF);
1898 /* Tell the assuan library about our commands */
1900 register_commands (assuan_context_t ctx)
1904 assuan_handler_t handler;
1905 const char * const help;
1907 { "SERIALNO", cmd_serialno, hlp_serialno },
1908 { "LEARN", cmd_learn, hlp_learn },
1909 { "READCERT", cmd_readcert, hlp_readcert },
1910 { "READKEY", cmd_readkey, hlp_readkey },
1911 { "SETDATA", cmd_setdata, hlp_setdata },
1912 { "PKSIGN", cmd_pksign, hlp_pksign },
1913 { "PKAUTH", cmd_pkauth, hlp_pkauth },
1914 { "PKDECRYPT", cmd_pkdecrypt,hlp_pkdecrypt },
1917 { "GETATTR", cmd_getattr, hlp_getattr },
1918 { "SETATTR", cmd_setattr, hlp_setattr },
1919 { "WRITECERT", cmd_writecert,hlp_writecert },
1920 { "WRITEKEY", cmd_writekey, hlp_writekey },
1921 { "GENKEY", cmd_genkey, hlp_genkey },
1922 { "RANDOM", cmd_random, hlp_random },
1923 { "PASSWD", cmd_passwd, hlp_passwd },
1924 { "CHECKPIN", cmd_checkpin, hlp_checkpin },
1925 { "LOCK", cmd_lock, hlp_lock },
1926 { "UNLOCK", cmd_unlock, hlp_unlock },
1927 { "GETINFO", cmd_getinfo, hlp_getinfo },
1928 { "RESTART", cmd_restart, hlp_restart },
1929 { "DISCONNECT", cmd_disconnect,hlp_disconnect },
1930 { "APDU", cmd_apdu, hlp_apdu },
1931 { "KILLSCD", cmd_killscd, hlp_killscd },
1936 for (i=0; table[i].name; i++)
1938 rc = assuan_register_command (ctx, table[i].name, table[i].handler,
1943 assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
1945 assuan_register_reset_notify (ctx, reset_notify);
1946 assuan_register_option_handler (ctx, option_handler);
1951 /* Startup the server. If FD is given as -1 this is simple pipe
1952 server, otherwise it is a regular server. Returns true if there
1953 are no more active asessions. */
1955 scd_command_handler (ctrl_t ctrl, int fd)
1958 assuan_context_t ctx = NULL;
1961 rc = assuan_new (&ctx);
1964 log_error ("failed to allocate assuan context: %s\n",
1971 assuan_fd_t filedes[2];
1973 filedes[0] = assuan_fdopen (0);
1974 filedes[1] = assuan_fdopen (1);
1975 rc = assuan_init_pipe_server (ctx, filedes);
1979 rc = assuan_init_socket_server (ctx, INT2FD(fd),
1980 ASSUAN_SOCKET_SERVER_ACCEPTED);
1984 log_error ("failed to initialize the server: %s\n",
1988 rc = register_commands (ctx);
1991 log_error ("failed to register commands with Assuan: %s\n",
1995 assuan_set_pointer (ctx, ctrl);
1997 /* Allocate and initialize the server object. Put it into the list
1998 of active sessions. */
1999 ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
2000 ctrl->server_local->next_session = session_list;
2001 session_list = ctrl->server_local;
2002 ctrl->server_local->ctrl_backlink = ctrl;
2003 ctrl->server_local->assuan_ctx = ctx;
2006 assuan_set_log_stream (ctx, log_get_stream ());
2008 /* We open the reader right at startup so that the ticker is able to
2009 update the status file. */
2010 if (ctrl->reader_slot == -1)
2012 ctrl->reader_slot = get_reader_slot ();
2015 /* Command processing loop. */
2018 rc = assuan_accept (ctx);
2025 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
2029 rc = assuan_process (ctx);
2032 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
2037 /* Cleanup. We don't send an explicit reset to the card. */
2040 /* Release the server object. */
2041 if (session_list == ctrl->server_local)
2042 session_list = ctrl->server_local->next_session;
2045 struct server_local_s *sl;
2047 for (sl=session_list; sl->next_session; sl = sl->next_session)
2048 if (sl->next_session == ctrl->server_local)
2050 if (!sl->next_session)
2052 sl->next_session = ctrl->server_local->next_session;
2054 stopme = ctrl->server_local->stopme;
2055 xfree (ctrl->server_local);
2056 ctrl->server_local = NULL;
2058 /* Release the Assuan context. */
2059 assuan_release (ctx);
2064 /* If there are no more sessions return true. */
2065 return !session_list;
2069 /* Send a line with status information via assuan and escape all given
2070 buffers. The variable elements are pairs of (char *, size_t),
2071 terminated with a (NULL, 0). */
2073 send_status_info (ctrl_t ctrl, const char *keyword, ...)
2076 const unsigned char *value;
2080 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2082 va_start (arg_ptr, keyword);
2086 while ( (value = va_arg (arg_ptr, const unsigned char *)) )
2088 valuelen = va_arg (arg_ptr, size_t);
2090 continue; /* empty buffer */
2096 for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
2098 if (*value < ' ' || *value == '+')
2100 sprintf (p, "%%%02X", *value);
2103 else if (*value == ' ')
2110 assuan_write_status (ctx, keyword, buf);
2116 /* Send a ready formatted status line via assuan. */
2118 send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
2120 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2122 if (strchr (args, '\n'))
2123 log_error ("error: LF detected in status line - not sending\n");
2125 assuan_write_status (ctx, keyword, args);
2129 /* Helper to send the clients a status change notification. */
2131 send_client_notifications (void)
2135 #ifdef HAVE_W32_SYSTEM
2143 struct server_local_s *sl;
2145 for (sl=session_list; sl; sl = sl->next_session)
2147 if (sl->event_signal && sl->assuan_ctx)
2149 pid_t pid = assuan_get_pid (sl->assuan_ctx);
2150 #ifdef HAVE_W32_SYSTEM
2151 HANDLE handle = (void *)sl->event_signal;
2153 for (kidx=0; kidx < killidx; kidx++)
2154 if (killed[kidx].pid == pid
2155 && killed[kidx].handle == handle)
2158 log_info ("event %lx (%p) already triggered for client %d\n",
2159 sl->event_signal, handle, (int)pid);
2162 log_info ("triggering event %lx (%p) for client %d\n",
2163 sl->event_signal, handle, (int)pid);
2164 if (!SetEvent (handle))
2165 log_error ("SetEvent(%lx) failed: %s\n",
2166 sl->event_signal, w32_strerror (-1));
2167 if (killidx < DIM (killed))
2169 killed[killidx].pid = pid;
2170 killed[killidx].handle = handle;
2174 #else /*!HAVE_W32_SYSTEM*/
2175 int signo = sl->event_signal;
2177 if (pid != (pid_t)(-1) && pid && signo > 0)
2179 for (kidx=0; kidx < killidx; kidx++)
2180 if (killed[kidx].pid == pid
2181 && killed[kidx].signo == signo)
2184 log_info ("signal %d already sent to client %d\n",
2188 log_info ("sending signal %d to client %d\n",
2191 if (killidx < DIM (killed))
2193 killed[killidx].pid = pid;
2194 killed[killidx].signo = signo;
2199 #endif /*!HAVE_W32_SYSTEM*/
2206 /* This is the core of scd_update_reader_status_file but the caller
2207 needs to take care of the locking. */
2209 update_reader_status_file (int set_card_removed_flag)
2212 unsigned int status, changed;
2214 /* Note, that we only try to get the status, because it does not
2215 make sense to wait here for a operation to complete. If we are
2216 busy working with a card, delays in the status file update should
2218 for (idx=0; idx < DIM(slot_table); idx++)
2220 struct slot_status_s *ss = slot_table + idx;
2221 struct server_local_s *sl;
2224 if (!ss->valid || ss->slot == -1)
2225 continue; /* Not valid or reader not yet open. */
2227 sw_apdu = apdu_get_status (ss->slot, 0, &status, &changed);
2228 if (sw_apdu == SW_HOST_NO_READER)
2230 /* Most likely the _reader_ has been unplugged. */
2231 application_notify_card_reset (ss->slot);
2232 apdu_close_reader (ss->slot);
2235 changed = ss->changed;
2239 /* Get status failed. Ignore that. */
2243 if (!ss->any || ss->status != status || ss->changed != changed )
2249 log_info ("updating slot %d status: 0x%04X->0x%04X (%u->%u)\n",
2250 ss->slot, ss->status, status, ss->changed, changed);
2251 ss->status = status;
2252 ss->changed = changed;
2254 /* FIXME: Should this be IDX instead of ss->slot? This
2255 depends on how client sessions will associate the reader
2256 status with their session. */
2257 snprintf (templ, sizeof templ, "reader_%d.status", ss->slot);
2258 fname = make_filename (opt.homedir, templ, NULL );
2259 fp = fopen (fname, "w");
2262 fprintf (fp, "%s\n",
2263 (status & 1)? "USABLE":
2264 (status & 4)? "ACTIVE":
2265 (status & 2)? "PRESENT": "NOCARD");
2270 /* If a status script is executable, run it. */
2272 const char *args[9], *envs[2];
2273 char numbuf1[30], numbuf2[30], numbuf3[30];
2274 char *homestr, *envstr;
2277 homestr = make_filename (opt.homedir, NULL);
2278 if (estream_asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
2279 log_error ("out of core while building environment\n");
2285 sprintf (numbuf1, "%d", ss->slot);
2286 sprintf (numbuf2, "0x%04X", ss->status);
2287 sprintf (numbuf3, "0x%04X", status);
2288 args[0] = "--reader-port";
2290 args[2] = "--old-code";
2292 args[4] = "--new-code";
2294 args[6] = "--status";
2295 args[7] = ((status & 1)? "USABLE":
2296 (status & 4)? "ACTIVE":
2297 (status & 2)? "PRESENT": "NOCARD");
2300 fname = make_filename (opt.homedir, "scd-event", NULL);
2301 err = gnupg_spawn_process_detached (fname, args, envs);
2302 if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
2303 log_error ("failed to run event handler `%s': %s\n",
2304 fname, gpg_strerror (err));
2311 /* Set the card removed flag for all current sessions. */
2312 if (ss->any && ss->status == 0 && set_card_removed_flag)
2313 update_card_removed (idx, 1);
2317 /* Send a signal to all clients who applied for it. */
2318 send_client_notifications ();
2321 /* Check whether a disconnect is pending. */
2322 if (opt.card_timeout)
2324 for (sl=session_list; sl; sl = sl->next_session)
2325 if (!sl->disconnect_allowed)
2327 if (session_list && !sl)
2329 /* FIXME: Use a real timeout. */
2330 /* At least one connection and all allow a disconnect. */
2331 log_info ("disconnecting card in slot %d\n", ss->slot);
2332 apdu_disconnect (ss->slot);
2339 /* This function is called by the ticker thread to check for changes
2340 of the reader stati. It updates the reader status files and if
2341 requested by the caller also send a signal to the caller. */
2343 scd_update_reader_status_file (void)
2345 if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL))
2346 return; /* locked - give up. */
2347 update_reader_status_file (1);
2348 if (!pth_mutex_release (&status_file_update_lock))
2349 log_error ("failed to release status_file_update lock\n");