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);
784 rc = ksba_cert_init_from_mem (kc, cert, ncert);
787 log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
791 p = ksba_cert_get_public_key (kc);
794 rc = gpg_error (GPG_ERR_NO_PUBKEY);
798 n = gcry_sexp_canon_len (p, 0, NULL, NULL);
799 rc = assuan_send_data (ctx, p, n);
804 ksba_cert_release (kc);
806 TEST_CARD_REMOVAL (ctrl, rc);
812 static const char hlp_setdata[] =
813 "SETDATA [--append] <hexstring>\n"
815 "The client should use this command to tell us the data he want to sign.\n"
816 "With the option --append, the data is appended to the data set by a\n"
817 "previous SETDATA command.";
819 cmd_setdata (assuan_context_t ctx, char *line)
821 ctrl_t ctrl = assuan_get_pointer (ctx);
827 append = (ctrl->in_data.value && has_option (line, "--append"));
829 line = skip_options (line);
831 if (locked_session && locked_session != ctrl->server_local)
832 return gpg_error (GPG_ERR_LOCKED);
834 /* Parse the hexstring. */
835 for (p=line,n=0; hexdigitp (p); p++, n++)
838 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
840 return set_error (GPG_ERR_ASS_PARAMETER, "no data given");
842 return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
846 if (ctrl->in_data.valuelen + n > MAXLEN_SETDATA)
847 return set_error (GPG_ERR_TOO_LARGE,
848 "limit on total size of data reached");
849 buf = xtrymalloc (ctrl->in_data.valuelen + n);
852 buf = xtrymalloc (n);
854 return out_of_core ();
858 memcpy (buf, ctrl->in_data.value, ctrl->in_data.valuelen);
859 off = ctrl->in_data.valuelen;
863 for (p=line, i=0; i < n; p += 2, i++)
864 buf[off+i] = xtoi_2 (p);
866 ctrl->in_data.value = buf;
867 ctrl->in_data.valuelen = off + n;
874 pin_cb (void *opaque, const char *info, char **retstr)
876 assuan_context_t ctx = opaque;
879 unsigned char *value;
884 /* We prompt for pinpad entry. To make sure that the popup has
885 been show we use an inquire and not just a status message.
886 We ignore any value returned. */
889 log_debug ("prompting for pinpad entry '%s'\n", info);
890 rc = estream_asprintf (&command, "POPUPPINPADPROMPT %s", info);
892 return gpg_error (gpg_err_code_from_errno (errno));
893 rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
898 log_debug ("dismiss pinpad entry prompt\n");
899 rc = assuan_inquire (ctx, "DISMISSPINPADPROMPT",
900 &value, &valuelen, MAXLEN_PIN);
908 log_debug ("asking for PIN '%s'\n", info);
910 rc = estream_asprintf (&command, "NEEDPIN %s", info);
912 return gpg_error (gpg_err_code_from_errno (errno));
914 /* Fixme: Write an inquire function which returns the result in
915 secure memory and check all further handling of the PIN. */
916 rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
921 if (!valuelen || value[valuelen-1])
923 /* We require that the returned value is an UTF-8 string */
925 return gpg_error (GPG_ERR_INV_RESPONSE);
927 *retstr = (char*)value;
932 static const char hlp_pksign[] =
933 "PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5]] <hexified_id>\n"
935 "The --hash option is optional; the default is SHA1.";
937 cmd_pksign (assuan_context_t ctx, char *line)
939 ctrl_t ctrl = assuan_get_pointer (ctx);
941 unsigned char *outdata;
946 if (has_option (line, "--hash=rmd160"))
947 hash_algo = GCRY_MD_RMD160;
948 else if (has_option (line, "--hash=sha1"))
949 hash_algo = GCRY_MD_SHA1;
950 else if (has_option (line, "--hash=sha224"))
951 hash_algo = GCRY_MD_SHA224;
952 else if (has_option (line, "--hash=sha256"))
953 hash_algo = GCRY_MD_SHA256;
954 else if (has_option (line, "--hash=sha384"))
955 hash_algo = GCRY_MD_SHA384;
956 else if (has_option (line, "--hash=sha512"))
957 hash_algo = GCRY_MD_SHA512;
958 else if (has_option (line, "--hash=md5"))
959 hash_algo = GCRY_MD_MD5;
960 else if (!strstr (line, "--"))
961 hash_algo = GCRY_MD_SHA1;
963 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
965 line = skip_options (line);
967 if ( IS_LOCKED (ctrl) )
968 return gpg_error (GPG_ERR_LOCKED);
970 if ((rc = open_card (ctrl, NULL)))
973 /* We have to use a copy of the key ID because the function may use
974 the pin_cb which in turn uses the assuan line buffer and thus
975 overwriting the original line with the keyid */
976 keyidstr = xtrystrdup (line);
978 return out_of_core ();
980 rc = app_sign (ctrl->app_ctx,
983 ctrl->in_data.value, ctrl->in_data.valuelen,
984 &outdata, &outdatalen);
989 log_error ("app_sign failed: %s\n", gpg_strerror (rc));
993 rc = assuan_send_data (ctx, outdata, outdatalen);
996 return rc; /* that is already an assuan error code */
999 TEST_CARD_REMOVAL (ctrl, rc);
1004 static const char hlp_pkauth[] =
1005 "PKAUTH <hexified_id>";
1007 cmd_pkauth (assuan_context_t ctx, char *line)
1009 ctrl_t ctrl = assuan_get_pointer (ctx);
1011 unsigned char *outdata;
1015 if ( IS_LOCKED (ctrl) )
1016 return gpg_error (GPG_ERR_LOCKED);
1018 if ((rc = open_card (ctrl, NULL)))
1022 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1024 /* We have to use a copy of the key ID because the function may use
1025 the pin_cb which in turn uses the assuan line buffer and thus
1026 overwriting the original line with the keyid */
1027 keyidstr = xtrystrdup (line);
1029 return out_of_core ();
1031 rc = app_auth (ctrl->app_ctx,
1034 ctrl->in_data.value, ctrl->in_data.valuelen,
1035 &outdata, &outdatalen);
1039 log_error ("app_auth failed: %s\n", gpg_strerror (rc));
1043 rc = assuan_send_data (ctx, outdata, outdatalen);
1046 return rc; /* that is already an assuan error code */
1049 TEST_CARD_REMOVAL (ctrl, rc);
1054 static const char hlp_pkdecrypt[] =
1055 "PKDECRYPT <hexified_id>";
1057 cmd_pkdecrypt (assuan_context_t ctx, char *line)
1059 ctrl_t ctrl = assuan_get_pointer (ctx);
1061 unsigned char *outdata;
1065 if ( IS_LOCKED (ctrl) )
1066 return gpg_error (GPG_ERR_LOCKED);
1068 if ((rc = open_card (ctrl, NULL)))
1071 keyidstr = xtrystrdup (line);
1073 return out_of_core ();
1074 rc = app_decipher (ctrl->app_ctx,
1077 ctrl->in_data.value, ctrl->in_data.valuelen,
1078 &outdata, &outdatalen);
1083 log_error ("app_decipher failed: %s\n", gpg_strerror (rc));
1087 rc = assuan_send_data (ctx, outdata, outdatalen);
1090 return rc; /* that is already an assuan error code */
1093 TEST_CARD_REMOVAL (ctrl, rc);
1098 static const char hlp_getattr[] =
1101 "This command is used to retrieve data from a smartcard. The\n"
1102 "allowed names depend on the currently selected smartcard\n"
1103 "application. NAME must be percent and '+' escaped. The value is\n"
1104 "returned through status message, see the LEARN command for details.\n"
1106 "However, the current implementation assumes that Name is not escaped;\n"
1107 "this works as long as noone uses arbitrary escaping. \n"
1109 "Note, that this function may even be used on a locked card.";
1111 cmd_getattr (assuan_context_t ctx, char *line)
1113 ctrl_t ctrl = assuan_get_pointer (ctx);
1115 const char *keyword;
1117 if ((rc = open_card (ctrl, NULL)))
1121 for (; *line && !spacep (line); line++)
1126 /* (We ignore any garbage for now.) */
1128 /* FIXME: Applications should not return sensitive data if the card
1130 rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
1132 TEST_CARD_REMOVAL (ctrl, rc);
1137 static const char hlp_setattr[] =
1138 "SETATTR <name> <value> \n"
1140 "This command is used to store data on a a smartcard. The allowed\n"
1141 "names and values are depend on the currently selected smartcard\n"
1142 "application. NAME and VALUE must be percent and '+' escaped.\n"
1144 "However, the current implementation assumes that NAME is not\n"
1145 "escaped; this works as long as noone uses arbitrary escaping.\n"
1147 "A PIN will be requested for most NAMEs. See the corresponding\n"
1148 "setattr function of the actually used application (app-*.c) for\n"
1151 cmd_setattr (assuan_context_t ctx, char *orig_line)
1153 ctrl_t ctrl = assuan_get_pointer (ctx);
1158 char *line, *linebuf;
1160 if ( IS_LOCKED (ctrl) )
1161 return gpg_error (GPG_ERR_LOCKED);
1163 if ((rc = open_card (ctrl, NULL)))
1166 /* We need to use a copy of LINE, because PIN_CB uses the same
1167 context and thus reuses the Assuan provided LINE. */
1168 line = linebuf = xtrystrdup (orig_line);
1170 return out_of_core ();
1173 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
1177 while (spacep (line))
1179 nbytes = percent_plus_unescape_inplace (line, 0);
1181 rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx,
1182 (const unsigned char*)line, nbytes);
1185 TEST_CARD_REMOVAL (ctrl, rc);
1190 static const char hlp_writecert[] =
1191 "WRITECERT <hexified_certid>\n"
1193 "This command is used to store a certifciate on a smartcard. The\n"
1194 "allowed certids depend on the currently selected smartcard\n"
1195 "application. The actual certifciate is requested using the inquiry\n"
1196 "\"CERTDATA\" and needs to be provided in its raw (e.g. DER) form.\n"
1198 "In almost all cases a a PIN will be requested. See the related\n"
1199 "writecert function of the actually used application (app-*.c) for\n"
1202 cmd_writecert (assuan_context_t ctx, char *line)
1204 ctrl_t ctrl = assuan_get_pointer (ctx);
1207 unsigned char *certdata;
1210 if ( IS_LOCKED (ctrl) )
1211 return gpg_error (GPG_ERR_LOCKED);
1213 line = skip_options (line);
1216 return set_error (GPG_ERR_ASS_PARAMETER, "no certid given");
1218 while (*line && !spacep (line))
1222 if ((rc = open_card (ctrl, NULL)))
1226 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1228 certid = xtrystrdup (certid);
1230 return out_of_core ();
1232 /* Now get the actual keydata. */
1233 rc = assuan_inquire (ctx, "CERTDATA",
1234 &certdata, &certdatalen, MAXLEN_CERTDATA);
1241 /* Write the certificate to the card. */
1242 rc = app_writecert (ctrl->app_ctx, ctrl, certid,
1243 pin_cb, ctx, certdata, certdatalen);
1247 TEST_CARD_REMOVAL (ctrl, rc);
1252 static const char hlp_writekey[] =
1253 "WRITEKEY [--force] <keyid> \n"
1255 "This command is used to store a secret key on a a smartcard. The\n"
1256 "allowed keyids depend on the currently selected smartcard\n"
1257 "application. The actual keydata is requested using the inquiry\n"
1258 "\"KEYDATA\" and need to be provided without any protection. With\n"
1259 "--force set an existing key under this KEYID will get overwritten.\n"
1260 "The keydata is expected to be the usual canonical encoded\n"
1263 "A PIN will be requested for most NAMEs. See the corresponding\n"
1264 "writekey function of the actually used application (app-*.c) for\n"
1267 cmd_writekey (assuan_context_t ctx, char *line)
1269 ctrl_t ctrl = assuan_get_pointer (ctx);
1272 int force = has_option (line, "--force");
1273 unsigned char *keydata;
1276 if ( IS_LOCKED (ctrl) )
1277 return gpg_error (GPG_ERR_LOCKED);
1279 line = skip_options (line);
1282 return set_error (GPG_ERR_ASS_PARAMETER, "no keyid given");
1284 while (*line && !spacep (line))
1288 if ((rc = open_card (ctrl, NULL)))
1292 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1294 keyid = xtrystrdup (keyid);
1296 return out_of_core ();
1298 /* Now get the actual keydata. */
1299 assuan_begin_confidential (ctx);
1300 rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA);
1301 assuan_end_confidential (ctx);
1308 /* Write the key to the card. */
1309 rc = app_writekey (ctrl->app_ctx, ctrl, keyid, force? 1:0,
1310 pin_cb, ctx, keydata, keydatalen);
1314 TEST_CARD_REMOVAL (ctrl, rc);
1319 static const char hlp_genkey[] =
1320 "GENKEY [--force] [--timestamp=<isodate>] <no>\n"
1322 "Generate a key on-card identified by NO, which is application\n"
1323 "specific. Return values are application specific. For OpenPGP\n"
1324 "cards 3 status lines are returned:\n"
1326 " S KEY-FPR <hexstring>\n"
1327 " S KEY-CREATED-AT <seconds_since_epoch>\n"
1328 " S KEY-DATA [-|p|n] <hexdata>\n"
1330 " 'p' and 'n' are the names of the RSA parameters; '-' is used to\n"
1331 " indicate that HEXDATA is the first chunk of a parameter given\n"
1332 " by the next KEY-DATA.\n"
1334 "--force is required to overwrite an already existing key. The\n"
1335 "KEY-CREATED-AT is required for further processing because it is\n"
1336 "part of the hashed key material for the fingerprint.\n"
1338 "If --timestamp is given an OpenPGP key will be created using this\n"
1339 "value. The value needs to be in ISO Format; e.g.\n"
1340 "\"--timestamp=20030316T120000\" and after 1970-01-01 00:00:00.\n"
1342 "The public part of the key can also later be retrieved using the\n"
1345 cmd_genkey (assuan_context_t ctx, char *line)
1347 ctrl_t ctrl = assuan_get_pointer (ctx);
1354 if ( IS_LOCKED (ctrl) )
1355 return gpg_error (GPG_ERR_LOCKED);
1357 force = has_option (line, "--force");
1359 if ((s=has_option_name (line, "--timestamp")))
1362 return set_error (GPG_ERR_ASS_PARAMETER, "missing value for option");
1363 timestamp = isotime2epoch (s+1);
1365 return set_error (GPG_ERR_ASS_PARAMETER, "invalid time value");
1371 line = skip_options (line);
1373 return set_error (GPG_ERR_ASS_PARAMETER, "no key number given");
1375 while (*line && !spacep (line))
1379 if ((rc = open_card (ctrl, NULL)))
1383 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1385 keyno = xtrystrdup (keyno);
1387 return out_of_core ();
1388 rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0,
1389 timestamp, pin_cb, ctx);
1392 TEST_CARD_REMOVAL (ctrl, rc);
1397 static const char hlp_random[] =
1400 "Get NBYTES of random from the card and send them back as data.\n"
1401 "This usually involves EEPROM write on the card and thus excessive\n"
1402 "use of this command may destroy the card.\n"
1404 "Note, that this function may be even be used on a locked card.";
1406 cmd_random (assuan_context_t ctx, char *line)
1408 ctrl_t ctrl = assuan_get_pointer (ctx);
1411 unsigned char *buffer;
1414 return set_error (GPG_ERR_ASS_PARAMETER,
1415 "number of requested bytes missing");
1416 nbytes = strtoul (line, NULL, 0);
1418 if ((rc = open_card (ctrl, NULL)))
1422 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1424 buffer = xtrymalloc (nbytes);
1426 return out_of_core ();
1428 rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
1431 rc = assuan_send_data (ctx, buffer, nbytes);
1433 return rc; /* that is already an assuan error code */
1437 TEST_CARD_REMOVAL (ctrl, rc);
1443 static const char hlp_passwd[] =
1444 "PASSWD [--reset] [--nullpin] <chvno>\n"
1446 "Change the PIN or, if --reset is given, reset the retry counter of\n"
1447 "the card holder verfication vector CHVNO. The option --nullpin is\n"
1448 "used for TCOS cards to set the initial PIN. The format of CHVNO\n"
1449 "depends on the card application.";
1451 cmd_passwd (assuan_context_t ctx, char *line)
1453 ctrl_t ctrl = assuan_get_pointer (ctx);
1456 unsigned int flags = 0;
1458 if (has_option (line, "--reset"))
1459 flags |= APP_CHANGE_FLAG_RESET;
1460 if (has_option (line, "--nullpin"))
1461 flags |= APP_CHANGE_FLAG_NULLPIN;
1463 if ( IS_LOCKED (ctrl) )
1464 return gpg_error (GPG_ERR_LOCKED);
1466 line = skip_options (line);
1469 return set_error (GPG_ERR_ASS_PARAMETER, "no CHV number given");
1471 while (*line && !spacep (line))
1475 if ((rc = open_card (ctrl, NULL)))
1479 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1481 chvnostr = xtrystrdup (chvnostr);
1483 return out_of_core ();
1484 rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, flags, pin_cb, ctx);
1486 log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1489 TEST_CARD_REMOVAL (ctrl, rc);
1494 static const char hlp_checkpin[] =
1495 "CHECKPIN <idstr>\n"
1497 "Perform a VERIFY operation without doing anything else. This may\n"
1498 "be used to initialize a the PIN cache earlier to long lasting\n"
1499 "operations. Its use is highly application dependent.\n"
1503 " Perform a simple verify operation for CHV1 and CHV2, so that\n"
1504 " further operations won't ask for CHV2 and it is possible to do a\n"
1505 " cheap check on the PIN: If there is something wrong with the PIN\n"
1506 " entry system, only the regular CHV will get blocked and not the\n"
1507 " dangerous CHV3. IDSTR is the usual card's serial number in hex\n"
1508 " notation; an optional fingerprint part will get ignored. There\n"
1509 " is however a special mode if the IDSTR is sffixed with the\n"
1510 " literal string \"[CHV3]\": In this case the Admin PIN is checked\n"
1511 " if and only if the retry counter is still at 3.\n"
1515 " Any of the valid PIN Ids may be used. These are the strings:\n"
1517 " PW1.CH - Global password 1\n"
1518 " PW2.CH - Global password 2\n"
1519 " PW1.CH.SIG - SigG password 1\n"
1520 " PW2.CH.SIG - SigG password 2\n"
1522 " For a definitive list, see the implementation in app-nks.c.\n"
1523 " Note that we call a PW2.* PIN a \"PUK\" despite that since TCOS\n"
1524 " 3.0 they are technically alternative PINs used to mutally\n"
1525 " unblock each other.";
1527 cmd_checkpin (assuan_context_t ctx, char *line)
1529 ctrl_t ctrl = assuan_get_pointer (ctx);
1533 if ( IS_LOCKED (ctrl) )
1534 return gpg_error (GPG_ERR_LOCKED);
1536 if ((rc = open_card (ctrl, NULL)))
1540 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1542 /* We have to use a copy of the key ID because the function may use
1543 the pin_cb which in turn uses the assuan line buffer and thus
1544 overwriting the original line with the keyid. */
1545 idstr = xtrystrdup (line);
1547 return out_of_core ();
1549 rc = app_check_pin (ctrl->app_ctx, idstr, pin_cb, ctx);
1552 log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
1554 TEST_CARD_REMOVAL (ctrl, rc);
1559 static const char hlp_lock[] =
1562 "Grant exclusive card access to this session. Note that there is\n"
1563 "no lock counter used and a second lock from the same session will\n"
1564 "be ignored. A single unlock (or RESET) unlocks the session.\n"
1565 "Return GPG_ERR_LOCKED if another session has locked the reader.\n"
1567 "If the option --wait is given the command will wait until a\n"
1568 "lock has been released.";
1570 cmd_lock (assuan_context_t ctx, char *line)
1572 ctrl_t ctrl = assuan_get_pointer (ctx);
1578 if (locked_session != ctrl->server_local)
1579 rc = gpg_error (GPG_ERR_LOCKED);
1582 locked_session = ctrl->server_local;
1585 if (rc && has_option (line, "--wait"))
1588 pth_sleep (1); /* Better implement an event mechanism. However,
1589 for card operations this should be
1591 /* FIXME: Need to check that the connection is still alive.
1592 This can be done by issuing status messages. */
1595 #endif /*USE_GNU_PTH*/
1598 log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
1603 static const char hlp_unlock[] =
1606 "Release exclusive card access.";
1608 cmd_unlock (assuan_context_t ctx, char *line)
1610 ctrl_t ctrl = assuan_get_pointer (ctx);
1617 if (locked_session != ctrl->server_local)
1618 rc = gpg_error (GPG_ERR_LOCKED);
1620 locked_session = NULL;
1623 rc = gpg_error (GPG_ERR_NOT_LOCKED);
1626 log_error ("cmd_unlock failed: %s\n", gpg_strerror (rc));
1631 static const char hlp_getinfo[] =
1634 "Multi purpose command to return certain information. \n"
1635 "Supported values of WHAT are:\n"
1637 "version - Return the version of the program.\n"
1638 "pid - Return the process id of the server.\n"
1640 "socket_name - Return the name of the socket.\n"
1642 "status - Return the status of the current slot (in the future, may\n"
1643 "also return the status of all slots). The status is a list of\n"
1644 "one-character flags. The following flags are currently defined:\n"
1645 " 'u' Usable card present. This is the normal state during operation.\n"
1646 " 'r' Card removed. A reset is necessary.\n"
1647 "These flags are exclusive.\n"
1649 "reader_list - Return a list of detected card readers. Does\n"
1650 " currently only work with the internal CCID driver.\n"
1652 "deny_admin - Returns OK if admin commands are not allowed or\n"
1653 " GPG_ERR_GENERAL if admin commands are allowed.\n"
1655 "app_list - Return a list of supported applications. One\n"
1656 " application per line, fields delimited by colons,\n"
1657 " first field is the name.";
1659 cmd_getinfo (assuan_context_t ctx, char *line)
1663 if (!strcmp (line, "version"))
1665 const char *s = VERSION;
1666 rc = assuan_send_data (ctx, s, strlen (s));
1668 else if (!strcmp (line, "pid"))
1672 snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1673 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1675 else if (!strcmp (line, "socket_name"))
1677 const char *s = scd_get_socket_name ();
1680 rc = assuan_send_data (ctx, s, strlen (s));
1682 rc = gpg_error (GPG_ERR_NO_DATA);
1684 else if (!strcmp (line, "status"))
1686 ctrl_t ctrl = assuan_get_pointer (ctx);
1687 int slot = ctrl->reader_slot;
1690 if (!ctrl->server_local->card_removed && slot != -1)
1692 struct slot_status_s *ss;
1694 if (!(slot >= 0 && slot < DIM(slot_table)))
1697 ss = &slot_table[slot];
1699 if (ss->valid && ss->any && (ss->status & 1))
1702 rc = assuan_send_data (ctx, &flag, 1);
1704 else if (!strcmp (line, "reader_list"))
1707 char *s = ccid_get_reader_list ();
1713 rc = assuan_send_data (ctx, s, strlen (s));
1715 rc = gpg_error (GPG_ERR_NO_DATA);
1718 else if (!strcmp (line, "deny_admin"))
1719 rc = opt.allow_admin? gpg_error (GPG_ERR_GENERAL) : 0;
1720 else if (!strcmp (line, "app_list"))
1722 char *s = get_supported_applications ();
1724 rc = assuan_send_data (ctx, s, strlen (s));
1730 rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1735 static const char hlp_restart[] =
1738 "Restart the current connection; this is a kind of warm reset. It\n"
1739 "deletes the context used by this connection but does not send a\n"
1740 "RESET to the card. Thus the card itself won't get reset. \n"
1742 "This is used by gpg-agent to reuse a primary pipe connection and\n"
1743 "may be used by clients to backup from a conflict in the serial\n"
1744 "command; i.e. to select another application.";
1746 cmd_restart (assuan_context_t ctx, char *line)
1748 ctrl_t ctrl = assuan_get_pointer (ctx);
1754 release_application (ctrl->app_ctx);
1755 ctrl->app_ctx = NULL;
1757 if (locked_session && ctrl->server_local == locked_session)
1759 locked_session = NULL;
1760 log_info ("implicitly unlocking due to RESTART\n");
1766 static const char hlp_disconnect[] =
1769 "Disconnect the card if it is not any longer used by other\n"
1770 "connections and the backend supports a disconnect operation.";
1772 cmd_disconnect (assuan_context_t ctx, char *line)
1774 ctrl_t ctrl = assuan_get_pointer (ctx);
1778 ctrl->server_local->disconnect_allowed = 1;
1784 static const char hlp_apdu[] =
1785 "APDU [--atr] [--more] [--exlen[=N]] [hexstring]\n"
1787 "Send an APDU to the current reader. This command bypasses the high\n"
1788 "level functions and sends the data directly to the card. HEXSTRING\n"
1789 "is expected to be a proper APDU. If HEXSTRING is not given no\n"
1790 "commands are set to the card but the command will implictly check\n"
1791 "whether the card is ready for use. \n"
1793 "Using the option \"--atr\" returns the ATR of the card as a status\n"
1794 "message before any data like this:\n"
1795 " S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1\n"
1797 "Using the option --more handles the card status word MORE_DATA\n"
1798 "(61xx) and concatenates all reponses to one block.\n"
1800 "Using the option \"--exlen\" the returned APDU may use extended\n"
1801 "length up to N bytes. If N is not given a default value is used\n"
1802 "(currently 4096).";
1804 cmd_apdu (assuan_context_t ctx, char *line)
1806 ctrl_t ctrl = assuan_get_pointer (ctx);
1808 unsigned char *apdu;
1815 with_atr = has_option (line, "--atr");
1816 handle_more = has_option (line, "--more");
1818 if ((s=has_option_name (line, "--exlen")))
1821 exlen = strtoul (s+1, NULL, 0);
1828 line = skip_options (line);
1830 if ( IS_LOCKED (ctrl) )
1831 return gpg_error (GPG_ERR_LOCKED);
1833 if ((rc = open_card (ctrl, NULL)))
1842 atr = apdu_get_atr (ctrl->reader_slot, &atrlen);
1843 if (!atr || atrlen > sizeof hexbuf - 2 )
1845 rc = gpg_error (GPG_ERR_INV_CARD);
1848 bin2hex (atr, atrlen, hexbuf);
1850 send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
1853 apdu = hex_to_buffer (line, &apdulen);
1856 rc = gpg_error_from_syserror ();
1861 unsigned char *result = NULL;
1864 rc = apdu_send_direct (ctrl->reader_slot, exlen,
1865 apdu, apdulen, handle_more,
1866 &result, &resultlen);
1868 log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
1871 rc = assuan_send_data (ctx, result, resultlen);
1878 TEST_CARD_REMOVAL (ctrl, rc);
1883 static const char hlp_killscd[] =
1888 cmd_killscd (assuan_context_t ctx, char *line)
1890 ctrl_t ctrl = assuan_get_pointer (ctx);
1894 ctrl->server_local->stopme = 1;
1895 return gpg_error (GPG_ERR_EOF);
1900 /* Tell the assuan library about our commands */
1902 register_commands (assuan_context_t ctx)
1906 assuan_handler_t handler;
1907 const char * const help;
1909 { "SERIALNO", cmd_serialno, hlp_serialno },
1910 { "LEARN", cmd_learn, hlp_learn },
1911 { "READCERT", cmd_readcert, hlp_readcert },
1912 { "READKEY", cmd_readkey, hlp_readkey },
1913 { "SETDATA", cmd_setdata, hlp_setdata },
1914 { "PKSIGN", cmd_pksign, hlp_pksign },
1915 { "PKAUTH", cmd_pkauth, hlp_pkauth },
1916 { "PKDECRYPT", cmd_pkdecrypt,hlp_pkdecrypt },
1919 { "GETATTR", cmd_getattr, hlp_getattr },
1920 { "SETATTR", cmd_setattr, hlp_setattr },
1921 { "WRITECERT", cmd_writecert,hlp_writecert },
1922 { "WRITEKEY", cmd_writekey, hlp_writekey },
1923 { "GENKEY", cmd_genkey, hlp_genkey },
1924 { "RANDOM", cmd_random, hlp_random },
1925 { "PASSWD", cmd_passwd, hlp_passwd },
1926 { "CHECKPIN", cmd_checkpin, hlp_checkpin },
1927 { "LOCK", cmd_lock, hlp_lock },
1928 { "UNLOCK", cmd_unlock, hlp_unlock },
1929 { "GETINFO", cmd_getinfo, hlp_getinfo },
1930 { "RESTART", cmd_restart, hlp_restart },
1931 { "DISCONNECT", cmd_disconnect,hlp_disconnect },
1932 { "APDU", cmd_apdu, hlp_apdu },
1933 { "KILLSCD", cmd_killscd, hlp_killscd },
1938 for (i=0; table[i].name; i++)
1940 rc = assuan_register_command (ctx, table[i].name, table[i].handler,
1945 assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
1947 assuan_register_reset_notify (ctx, reset_notify);
1948 assuan_register_option_handler (ctx, option_handler);
1953 /* Startup the server. If FD is given as -1 this is simple pipe
1954 server, otherwise it is a regular server. Returns true if there
1955 are no more active asessions. */
1957 scd_command_handler (ctrl_t ctrl, int fd)
1960 assuan_context_t ctx = NULL;
1963 rc = assuan_new (&ctx);
1966 log_error ("failed to allocate assuan context: %s\n",
1973 assuan_fd_t filedes[2];
1975 filedes[0] = assuan_fdopen (0);
1976 filedes[1] = assuan_fdopen (1);
1977 rc = assuan_init_pipe_server (ctx, filedes);
1981 rc = assuan_init_socket_server (ctx, INT2FD(fd),
1982 ASSUAN_SOCKET_SERVER_ACCEPTED);
1986 log_error ("failed to initialize the server: %s\n",
1990 rc = register_commands (ctx);
1993 log_error ("failed to register commands with Assuan: %s\n",
1997 assuan_set_pointer (ctx, ctrl);
1999 /* Allocate and initialize the server object. Put it into the list
2000 of active sessions. */
2001 ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
2002 ctrl->server_local->next_session = session_list;
2003 session_list = ctrl->server_local;
2004 ctrl->server_local->ctrl_backlink = ctrl;
2005 ctrl->server_local->assuan_ctx = ctx;
2008 assuan_set_log_stream (ctx, log_get_stream ());
2010 /* We open the reader right at startup so that the ticker is able to
2011 update the status file. */
2012 if (ctrl->reader_slot == -1)
2014 ctrl->reader_slot = get_reader_slot ();
2017 /* Command processing loop. */
2020 rc = assuan_accept (ctx);
2027 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
2031 rc = assuan_process (ctx);
2034 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
2039 /* Cleanup. We don't send an explicit reset to the card. */
2042 /* Release the server object. */
2043 if (session_list == ctrl->server_local)
2044 session_list = ctrl->server_local->next_session;
2047 struct server_local_s *sl;
2049 for (sl=session_list; sl->next_session; sl = sl->next_session)
2050 if (sl->next_session == ctrl->server_local)
2052 if (!sl->next_session)
2054 sl->next_session = ctrl->server_local->next_session;
2056 stopme = ctrl->server_local->stopme;
2057 xfree (ctrl->server_local);
2058 ctrl->server_local = NULL;
2060 /* Release the Assuan context. */
2061 assuan_release (ctx);
2066 /* If there are no more sessions return true. */
2067 return !session_list;
2071 /* Send a line with status information via assuan and escape all given
2072 buffers. The variable elements are pairs of (char *, size_t),
2073 terminated with a (NULL, 0). */
2075 send_status_info (ctrl_t ctrl, const char *keyword, ...)
2078 const unsigned char *value;
2082 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2084 va_start (arg_ptr, keyword);
2088 while ( (value = va_arg (arg_ptr, const unsigned char *)) )
2090 valuelen = va_arg (arg_ptr, size_t);
2092 continue; /* empty buffer */
2098 for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
2100 if (*value < ' ' || *value == '+')
2102 sprintf (p, "%%%02X", *value);
2105 else if (*value == ' ')
2112 assuan_write_status (ctx, keyword, buf);
2118 /* Send a ready formatted status line via assuan. */
2120 send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
2122 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2124 if (strchr (args, '\n'))
2125 log_error ("error: LF detected in status line - not sending\n");
2127 assuan_write_status (ctx, keyword, args);
2131 /* Helper to send the clients a status change notification. */
2133 send_client_notifications (void)
2137 #ifdef HAVE_W32_SYSTEM
2145 struct server_local_s *sl;
2147 for (sl=session_list; sl; sl = sl->next_session)
2149 if (sl->event_signal && sl->assuan_ctx)
2151 pid_t pid = assuan_get_pid (sl->assuan_ctx);
2152 #ifdef HAVE_W32_SYSTEM
2153 HANDLE handle = (void *)sl->event_signal;
2155 for (kidx=0; kidx < killidx; kidx++)
2156 if (killed[kidx].pid == pid
2157 && killed[kidx].handle == handle)
2160 log_info ("event %lx (%p) already triggered for client %d\n",
2161 sl->event_signal, handle, (int)pid);
2164 log_info ("triggering event %lx (%p) for client %d\n",
2165 sl->event_signal, handle, (int)pid);
2166 if (!SetEvent (handle))
2167 log_error ("SetEvent(%lx) failed: %s\n",
2168 sl->event_signal, w32_strerror (-1));
2169 if (killidx < DIM (killed))
2171 killed[killidx].pid = pid;
2172 killed[killidx].handle = handle;
2176 #else /*!HAVE_W32_SYSTEM*/
2177 int signo = sl->event_signal;
2179 if (pid != (pid_t)(-1) && pid && signo > 0)
2181 for (kidx=0; kidx < killidx; kidx++)
2182 if (killed[kidx].pid == pid
2183 && killed[kidx].signo == signo)
2186 log_info ("signal %d already sent to client %d\n",
2190 log_info ("sending signal %d to client %d\n",
2193 if (killidx < DIM (killed))
2195 killed[killidx].pid = pid;
2196 killed[killidx].signo = signo;
2201 #endif /*!HAVE_W32_SYSTEM*/
2208 /* This is the core of scd_update_reader_status_file but the caller
2209 needs to take care of the locking. */
2211 update_reader_status_file (int set_card_removed_flag)
2214 unsigned int status, changed;
2216 /* Note, that we only try to get the status, because it does not
2217 make sense to wait here for a operation to complete. If we are
2218 busy working with a card, delays in the status file update should
2220 for (idx=0; idx < DIM(slot_table); idx++)
2222 struct slot_status_s *ss = slot_table + idx;
2223 struct server_local_s *sl;
2226 if (!ss->valid || ss->slot == -1)
2227 continue; /* Not valid or reader not yet open. */
2229 sw_apdu = apdu_get_status (ss->slot, 0, &status, &changed);
2230 if (sw_apdu == SW_HOST_NO_READER)
2232 /* Most likely the _reader_ has been unplugged. */
2233 application_notify_card_reset (ss->slot);
2234 apdu_close_reader (ss->slot);
2237 changed = ss->changed;
2241 /* Get status failed. Ignore that. */
2245 if (!ss->any || ss->status != status || ss->changed != changed )
2251 log_info ("updating slot %d status: 0x%04X->0x%04X (%u->%u)\n",
2252 ss->slot, ss->status, status, ss->changed, changed);
2253 ss->status = status;
2254 ss->changed = changed;
2256 /* FIXME: Should this be IDX instead of ss->slot? This
2257 depends on how client sessions will associate the reader
2258 status with their session. */
2259 snprintf (templ, sizeof templ, "reader_%d.status", ss->slot);
2260 fname = make_filename (opt.homedir, templ, NULL );
2261 fp = fopen (fname, "w");
2264 fprintf (fp, "%s\n",
2265 (status & 1)? "USABLE":
2266 (status & 4)? "ACTIVE":
2267 (status & 2)? "PRESENT": "NOCARD");
2272 /* If a status script is executable, run it. */
2274 const char *args[9], *envs[2];
2275 char numbuf1[30], numbuf2[30], numbuf3[30];
2276 char *homestr, *envstr;
2279 homestr = make_filename (opt.homedir, NULL);
2280 if (estream_asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
2281 log_error ("out of core while building environment\n");
2287 sprintf (numbuf1, "%d", ss->slot);
2288 sprintf (numbuf2, "0x%04X", ss->status);
2289 sprintf (numbuf3, "0x%04X", status);
2290 args[0] = "--reader-port";
2292 args[2] = "--old-code";
2294 args[4] = "--new-code";
2296 args[6] = "--status";
2297 args[7] = ((status & 1)? "USABLE":
2298 (status & 4)? "ACTIVE":
2299 (status & 2)? "PRESENT": "NOCARD");
2302 fname = make_filename (opt.homedir, "scd-event", NULL);
2303 err = gnupg_spawn_process_detached (fname, args, envs);
2304 if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
2305 log_error ("failed to run event handler `%s': %s\n",
2306 fname, gpg_strerror (err));
2313 /* Set the card removed flag for all current sessions. */
2314 if (ss->any && ss->status == 0 && set_card_removed_flag)
2315 update_card_removed (idx, 1);
2319 /* Send a signal to all clients who applied for it. */
2320 send_client_notifications ();
2323 /* Check whether a disconnect is pending. */
2324 if (opt.card_timeout)
2326 for (sl=session_list; sl; sl = sl->next_session)
2327 if (!sl->disconnect_allowed)
2329 if (session_list && !sl)
2331 /* FIXME: Use a real timeout. */
2332 /* At least one connection and all allow a disconnect. */
2333 log_info ("disconnecting card in slot %d\n", ss->slot);
2334 apdu_disconnect (ss->slot);
2341 /* This function is called by the ticker thread to check for changes
2342 of the reader stati. It updates the reader status files and if
2343 requested by the caller also send a signal to the caller. */
2345 scd_update_reader_status_file (void)
2347 if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL))
2348 return; /* locked - give up. */
2349 update_reader_status_file (1);
2350 if (!pth_mutex_release (&status_file_update_lock))
2351 log_error ("failed to release status_file_update lock\n");