scd: Retry command SERIALNO for an inactive card.
[gnupg.git] / scd / command.c
1 /* command.c - SCdaemon command handler
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005,
3  *               2007, 2008, 2009  Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
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.
11  *
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.
16  *
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/>.
19  */
20
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <unistd.h>
28 #include <signal.h>
29 #ifdef USE_GNU_PTH
30 # include <pth.h>
31 #endif
32
33 #include "scdaemon.h"
34 #include <assuan.h>
35 #include <ksba.h>
36 #include "app-common.h"
37 #include "apdu.h" /* Required for apdu_*_reader (). */
38 #include "exechelp.h"
39 #ifdef HAVE_LIBUSB
40 #include "ccid-driver.h"
41 #endif
42
43 /* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */
44 #define MAXLEN_PIN 100
45
46 /* Maximum allowed size of key data as used in inquiries. */
47 #define MAXLEN_KEYDATA 4096
48
49 /* Maximum allowed size of certificate data as used in inquiries. */
50 #define MAXLEN_CERTDATA 16384
51
52
53 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
54
55
56 /* Macro to flag a removed card.  ENODEV is also tested to catch teh
57    case of a removed reader.  */
58 #define TEST_CARD_REMOVAL(c,r)                              \
59        do {                                                 \
60           int _r = (r);                                     \
61           if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \
62               || gpg_err_code (_r) == GPG_ERR_CARD_REMOVED  \
63               || gpg_err_code (_r) == GPG_ERR_CARD_RESET    \
64               || gpg_err_code (_r) == GPG_ERR_ENODEV )      \
65             update_card_removed ((c)->reader_slot, 1);      \
66        } while (0)
67
68 #define IS_LOCKED(c)                                                     \
69      (locked_session && locked_session != (c)->server_local              \
70       && (c)->reader_slot != -1 && locked_session->ctrl_backlink         \
71       && (c)->reader_slot == locked_session->ctrl_backlink->reader_slot)
72
73
74 /* Flag indicating that the reader has been disabled.  */
75 static int reader_disabled;
76
77
78 /* This structure is used to keep track of open readers (slots). */
79 struct slot_status_s
80 {
81   int valid;  /* True if the other objects are valid. */
82   int slot;   /* Slot number of the reader or -1 if not open. */
83
84   int reset_failed; /* A reset failed. */
85
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. */
91 };
92
93
94 /* Data used to associate an Assuan context with local server data.
95    This object describes the local properties of one session.  */
96 struct server_local_s
97 {
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;
101
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
105      backpointer here. */
106   ctrl_t ctrl_backlink;
107
108   /* The Assuan context used by this session/server. */
109   assuan_context_t assuan_ctx;
110
111 #ifdef HAVE_W32_SYSTEM
112   unsigned long event_signal;   /* Or 0 if not used. */
113 #else
114   int event_signal;             /* Or 0 if not used. */
115 #endif
116
117   /* True if the card has been removed and a reset is required to
118      continue operation. */
119   int card_removed;
120
121   /* Flag indicating that the application context needs to be released
122      at the next opportunity.  */
123   int app_ctx_marked_for_release;
124
125   /* A disconnect command has been sent.  */
126   int disconnect_allowed;
127
128   /* If set to true we will be terminate ourself at the end of the
129      this session.  */
130   int stopme;
131
132 };
133
134
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];
139
140
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;
144
145 /* If a session has been locked we store a link to its server object
146    in this variable. */
147 static struct server_local_s *locked_session;
148
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;
152
153 \f
154 /*-- Local prototypes --*/
155 static void update_reader_status_file (int set_card_removed_flag);
156
157
158 \f
159
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. */
164 void
165 initialize_module_command (void)
166 {
167   static int initialized;
168
169   if (!initialized)
170     {
171       if (pth_mutex_init (&status_file_update_lock))
172         initialized = 1;
173     }
174 }
175
176
177 /* Update the CARD_REMOVED element of all sessions using the reader
178    given by SLOT to VALUE.  */
179 static void
180 update_card_removed (int slot, int value)
181 {
182   struct server_local_s *sl;
183
184   for (sl=session_list; sl; sl = sl->next_session)
185     if (sl->ctrl_backlink
186         && sl->ctrl_backlink->reader_slot == slot)
187       {
188         sl->card_removed = value;
189       }
190   /* Let the card application layer know about the removal.  */
191   if (value)
192     application_notify_card_reset (slot);
193 }
194
195
196
197 /* Check whether the option NAME appears in LINE.  Returns 1 or 0. */
198 static int
199 has_option (const char *line, const char *name)
200 {
201   const char *s;
202   int n = strlen (name);
203
204   s = strstr (line, name);
205   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
206 }
207
208 /* Same as has_option but does only test for the name of the option
209    and ignores an argument, i.e. with NAME being "--hash" it would
210    return a pointer for "--hash" as well as for "--hash=foo".  If
211    there is no such option NULL is returned.  The pointer returned
212    points right behind the option name, this may be an equal sign, Nul
213    or a space.  */
214 static const char *
215 has_option_name (const char *line, const char *name)
216 {
217   const char *s;
218   int n = strlen (name);
219
220   s = strstr (line, name);
221   return (s && (s == line || spacep (s-1))
222           && (!s[n] || spacep (s+n) || s[n] == '=')) ? (s+n) : NULL;
223 }
224
225
226 /* Skip over options.  It is assumed that leading spaces have been
227    removed (this is the case for lines passed to a handler from
228    assuan).  Blanks after the options are also removed. */
229 static char *
230 skip_options (char *line)
231 {
232   while ( *line == '-' && line[1] == '-' )
233     {
234       while (*line && !spacep (line))
235         line++;
236       while (spacep (line))
237         line++;
238     }
239   return line;
240 }
241
242
243
244 /* Convert the STRING into a newly allocated buffer while translating
245    the hex numbers.  Stops at the first invalid character.  Blanks and
246    colons are allowed to separate the hex digits.  Returns NULL on
247    error or a newly malloced buffer and its length in LENGTH.  */
248 static unsigned char *
249 hex_to_buffer (const char *string, size_t *r_length)
250 {
251   unsigned char *buffer;
252   const char *s;
253   size_t n;
254
255   buffer = xtrymalloc (strlen (string)+1);
256   if (!buffer)
257     return NULL;
258   for (s=string, n=0; *s; s++)
259     {
260       if (spacep (s) || *s == ':')
261         continue;
262       if (hexdigitp (s) && hexdigitp (s+1))
263         {
264           buffer[n++] = xtoi_2 (s);
265           s++;
266         }
267       else
268         break;
269     }
270   *r_length = n;
271   return buffer;
272 }
273
274
275
276 /* Reset the card and free the application context.  With SEND_RESET
277    set to true actually send a RESET to the reader; this is the normal
278    way of calling the function.  */
279 static void
280 do_reset (ctrl_t ctrl, int send_reset)
281 {
282   int slot = ctrl->reader_slot;
283
284   if (!(slot == -1 || (slot >= 0 && slot < DIM(slot_table))))
285     BUG ();
286
287   /* If there is an active application, release it.  Tell all other
288      sessions using the same application to release the
289      application.  */
290   if (ctrl->app_ctx)
291     {
292       release_application (ctrl->app_ctx);
293       ctrl->app_ctx = NULL;
294       if (send_reset)
295         {
296           struct server_local_s *sl;
297
298           for (sl=session_list; sl; sl = sl->next_session)
299             if (sl->ctrl_backlink
300                 && sl->ctrl_backlink->reader_slot == slot)
301               {
302                 sl->app_ctx_marked_for_release = 1;
303               }
304         }
305     }
306
307   /* If we want a real reset for the card, send the reset APDU and
308      tell the application layer about it.  */
309   if (slot != -1 && send_reset && !IS_LOCKED (ctrl) )
310     {
311       if (apdu_reset (slot))
312         {
313           slot_table[slot].valid = 0;
314         }
315       application_notify_card_reset (slot);
316     }
317
318   /* If we hold a lock, unlock now. */
319   if (locked_session && ctrl->server_local == locked_session)
320     {
321       locked_session = NULL;
322       log_info ("implicitly unlocking due to RESET\n");
323     }
324
325   /* Reset the card removed flag for the current reader.  We need to
326      take the lock here so that the ticker thread won't concurrently
327      try to update the file.  Calling update_reader_status_file is
328      required to get hold of the new status of the card in the slot
329      table.  */
330   if (!pth_mutex_acquire (&status_file_update_lock, 0, NULL))
331     {
332       log_error ("failed to acquire status_fle_update lock\n");
333       ctrl->reader_slot = -1;
334       return;
335     }
336   update_reader_status_file (0);  /* Update slot status table.  */
337   update_card_removed (slot, 0);  /* Clear card_removed flag.  */
338   if (!pth_mutex_release (&status_file_update_lock))
339     log_error ("failed to release status_file_update lock\n");
340
341   /* Do this last, so that the update_card_removed above does its job.  */
342   ctrl->reader_slot = -1;
343 }
344
345 \f
346 static gpg_error_t
347 reset_notify (assuan_context_t ctx, char *line)
348 {
349   ctrl_t ctrl = assuan_get_pointer (ctx);
350
351   (void) line;
352
353   do_reset (ctrl, 1);
354   return 0;
355 }
356
357
358 static gpg_error_t
359 option_handler (assuan_context_t ctx, const char *key, const char *value)
360 {
361   ctrl_t ctrl = assuan_get_pointer (ctx);
362
363   if (!strcmp (key, "event-signal"))
364     {
365       /* A value of 0 is allowed to reset the event signal. */
366 #ifdef HAVE_W32_SYSTEM
367       if (!*value)
368         return gpg_error (GPG_ERR_ASS_PARAMETER);
369       ctrl->server_local->event_signal = strtoul (value, NULL, 16);
370 #else
371       int i = *value? atoi (value) : -1;
372       if (i < 0)
373         return gpg_error (GPG_ERR_ASS_PARAMETER);
374       ctrl->server_local->event_signal = i;
375 #endif
376     }
377
378  return 0;
379 }
380
381
382 /* Return the slot of the current reader or open the reader if no
383    other sessions are using a reader.  Note, that we currently support
384    only one reader but most of the code (except for this function)
385    should be able to cope with several readers.  */
386 static int
387 get_reader_slot (void)
388 {
389   struct slot_status_s *ss;
390
391   ss = &slot_table[0]; /* One reader for now. */
392
393   /* Initialize the item if needed. */
394   if (!ss->valid)
395     {
396       ss->slot = -1;
397       ss->valid = 1;
398     }
399
400   /* Try to open the reader. */
401   if (ss->slot == -1)
402     {
403       int no_service_flag;
404       ss->slot = apdu_open_reader (opt.reader_port, &no_service_flag);
405
406       /* If we still don't have a slot, we have no readers.
407          Invalidate for now until a reader is attached. */
408       if(ss->slot == -1)
409         {
410           ss->valid = 0;
411         }
412
413       if (no_service_flag)
414         {
415           log_info ("no card services - disabling scdaemon\n");
416           reader_disabled = 1;
417         }
418     }
419
420   /* Return the slot_table index.  */
421   return 0;
422 }
423
424
425 /* If the card has not yet been opened, do it.  */
426 static gpg_error_t
427 open_card (ctrl_t ctrl, const char *apptype)
428 {
429   gpg_error_t err;
430   int slot;
431
432   if (reader_disabled)
433     return gpg_error (GPG_ERR_NOT_OPERATIONAL);
434
435   /* If we ever got a card not present error code, return that.  Only
436      the SERIALNO command and a reset are able to clear from that
437      state. */
438   if (ctrl->server_local->card_removed)
439     return gpg_error (GPG_ERR_CARD_REMOVED);
440
441   if ( IS_LOCKED (ctrl) )
442     return gpg_error (GPG_ERR_LOCKED);
443
444   /* If the application has been marked for release do it now.  We
445      can't do it immediately in do_reset because the application may
446      still be in use.  */
447   if (ctrl->server_local->app_ctx_marked_for_release)
448     {
449       ctrl->server_local->app_ctx_marked_for_release = 0;
450       release_application (ctrl->app_ctx);
451       ctrl->app_ctx = NULL;
452     }
453
454   /* If we are already initialized for one specific application we
455      need to check that the client didn't requested a specific
456      application different from the one in use before we continue. */
457   if (ctrl->app_ctx)
458     return check_application_conflict (ctrl, apptype);
459
460   /* Setup the slot and select the application.  */
461   if (ctrl->reader_slot != -1)
462     slot = ctrl->reader_slot;
463   else
464     slot = get_reader_slot ();
465   ctrl->reader_slot = slot;
466   if (slot == -1)
467     err = gpg_error (reader_disabled? GPG_ERR_NOT_OPERATIONAL: GPG_ERR_CARD);
468   else
469     {
470       /* Fixme: We should move the apdu_connect call to
471          select_application.  */
472       int sw;
473
474       ctrl->server_local->disconnect_allowed = 0;
475       sw = apdu_connect (slot);
476       if (sw && sw != SW_HOST_ALREADY_CONNECTED)
477         {
478           if (sw == SW_HOST_NO_CARD)
479             err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
480           else if (sw == SW_HOST_CARD_INACTIVE)
481             err = gpg_error (GPG_ERR_CARD_RESET);
482           else
483             err = gpg_error (GPG_ERR_CARD);
484         }
485       else
486         err = select_application (ctrl, slot, apptype, &ctrl->app_ctx);
487     }
488
489   TEST_CARD_REMOVAL (ctrl, err);
490   return err;
491 }
492
493
494 static const char hlp_serialno[] =
495   "SERIALNO [<apptype>]\n"
496   "\n"
497   "Return the serial number of the card using a status reponse.  This\n"
498   "function should be used to check for the presence of a card.\n"
499   "\n"
500   "If APPTYPE is given, an application of that type is selected and an\n"
501   "error is returned if the application is not supported or available.\n"
502   "The default is to auto-select the application using a hardwired\n"
503   "preference system.  Note, that a future extension to this function\n"
504   "may allow to specify a list and order of applications to try.\n"
505   "\n"
506   "This function is special in that it can be used to reset the card.\n"
507   "Most other functions will return an error when a card change has\n"
508   "been detected and the use of this function is therefore required.\n"
509   "\n"
510   "Background: We want to keep the client clear of handling card\n"
511   "changes between operations; i.e. the client can assume that all\n"
512   "operations are done on the same card unless he calls this function.";
513 static gpg_error_t
514 cmd_serialno (assuan_context_t ctx, char *line)
515 {
516   ctrl_t ctrl = assuan_get_pointer (ctx);
517   int rc = 0;
518   char *serial_and_stamp;
519   char *serial;
520   time_t stamp;
521   int retries = 0;
522
523   /* Clear the remove flag so that the open_card is able to reread it.  */
524  retry:
525   if (!reader_disabled && ctrl->server_local->card_removed)
526     {
527       if ( IS_LOCKED (ctrl) )
528         return gpg_error (GPG_ERR_LOCKED);
529       do_reset (ctrl, 1);
530     }
531
532   if ((rc = open_card (ctrl, *line? line:NULL)))
533     {
534       /* In case of an inactive card, retry once.  */
535       if (gpg_err_code (rc) == GPG_ERR_CARD_RESET && retries++ < 1)
536         goto retry;
537       return rc;
538     }
539
540   rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
541   if (rc)
542     return rc;
543
544   rc = estream_asprintf (&serial_and_stamp, "%s %lu",
545                          serial, (unsigned long)stamp);
546   xfree (serial);
547   if (rc < 0)
548     return out_of_core ();
549   rc = 0;
550   assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
551   xfree (serial_and_stamp);
552   return 0;
553 }
554
555
556 static const char hlp_learn[] =
557   "LEARN [--force] [--keypairinfo]\n"
558   "\n"
559   "Learn all useful information of the currently inserted card.  When\n"
560   "used without the force options, the command might do an INQUIRE\n"
561   "like this:\n"
562   "\n"
563   "   INQUIRE KNOWNCARDP <hexstring_with_serialNumber> <timestamp>\n"
564   "\n"
565   "The client should just send an \"END\" if the processing should go on\n"
566   "or a \"CANCEL\" to force the function to terminate with a Cancel\n"
567   "error message.\n"
568   "\n"
569   "With the option --keypairinfo only KEYPARIINFO lstatus lines are\n"
570   "returned.\n"
571   "\n"
572   "The response of this command is a list of status lines formatted as\n"
573   "this:\n"
574   "\n"
575   "  S APPTYPE <apptype>\n"
576   "\n"
577   "This returns the type of the application, currently the strings:\n"
578   "\n"
579   "    P15     = PKCS-15 structure used\n"
580   "    DINSIG  = DIN SIG\n"
581   "    OPENPGP = OpenPGP card\n"
582   "    NKS     = NetKey card\n"
583   "\n"
584   "are implemented.  These strings are aliases for the AID\n"
585   "\n"
586   "  S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id>\n"
587   "\n"
588   "If there is no certificate yet stored on the card a single 'X' is\n"
589   "returned as the keygrip.  In addition to the keypair info, information\n"
590   "about all certificates stored on the card is also returned:\n"
591   "\n"
592   "  S CERTINFO <certtype> <hexstring_with_id>\n"
593   "\n"
594   "Where CERTTYPE is a number indicating the type of certificate:\n"
595   "   0   := Unknown\n"
596   "   100 := Regular X.509 cert\n"
597   "   101 := Trusted X.509 cert\n"
598   "   102 := Useful X.509 cert\n"
599   "   110 := Root CA cert in a special format (e.g. DINSIG)\n"
600   "   111 := Root CA cert as standard X509 cert.\n"
601   "\n"
602   "For certain cards, more information will be returned:\n"
603   "\n"
604   "  S KEY-FPR <no> <hexstring>\n"
605   "\n"
606   "For OpenPGP cards this returns the stored fingerprints of the\n"
607   "keys. This can be used check whether a key is available on the\n"
608   "card.  NO may be 1, 2 or 3.\n"
609   "\n"
610   "  S CA-FPR <no> <hexstring>\n"
611   "\n"
612   "Similar to above, these are the fingerprints of keys assumed to be\n"
613   "ultimately trusted.\n"
614   "\n"
615   "  S DISP-NAME <name_of_card_holder>\n"
616   "\n"
617   "The name of the card holder as stored on the card; percent\n"
618   "escaping takes place, spaces are encoded as '+'\n"
619   "\n"
620   "  S PUBKEY-URL <url>\n"
621   "\n"
622   "The URL to be used for locating the entire public key.\n"
623   "  \n"
624   "Note, that this function may even be used on a locked card.";
625 static gpg_error_t
626 cmd_learn (assuan_context_t ctx, char *line)
627 {
628   ctrl_t ctrl = assuan_get_pointer (ctx);
629   int rc = 0;
630   int only_keypairinfo = has_option (line, "--keypairinfo");
631
632   if ((rc = open_card (ctrl, NULL)))
633     return rc;
634
635   /* Unless the force option is used we try a shortcut by identifying
636      the card using a serial number and inquiring the client with
637      that. The client may choose to cancel the operation if he already
638      knows about this card */
639   if (!only_keypairinfo)
640     {
641       char *serial_and_stamp;
642       char *serial;
643       time_t stamp;
644
645       rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
646       if (rc)
647         return rc;
648       rc = estream_asprintf (&serial_and_stamp, "%s %lu",
649                              serial, (unsigned long)stamp);
650       xfree (serial);
651       if (rc < 0)
652         return out_of_core ();
653       rc = 0;
654       assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
655
656       if (!has_option (line, "--force"))
657         {
658           char *command;
659
660           rc = estream_asprintf (&command, "KNOWNCARDP %s", serial_and_stamp);
661           if (rc < 0)
662             {
663               xfree (serial_and_stamp);
664               return out_of_core ();
665             }
666           rc = 0;
667           rc = assuan_inquire (ctx, command, NULL, NULL, 0);
668           xfree (command);
669           if (rc)
670             {
671               if (gpg_err_code (rc) != GPG_ERR_ASS_CANCELED)
672                 log_error ("inquire KNOWNCARDP failed: %s\n",
673                            gpg_strerror (rc));
674               xfree (serial_and_stamp);
675               return rc;
676             }
677           /* Not canceled, so we have to proceeed.  */
678         }
679       xfree (serial_and_stamp);
680     }
681
682   /* Let the application print out its collection of useful status
683      information. */
684   if (!rc)
685     rc = app_write_learn_status (ctrl->app_ctx, ctrl, only_keypairinfo);
686
687   TEST_CARD_REMOVAL (ctrl, rc);
688   return rc;
689 }
690
691
692 \f
693 static const char hlp_readcert[] =
694   "READCERT <hexified_certid>|<keyid>\n"
695   "\n"
696   "Note, that this function may even be used on a locked card.";
697 static gpg_error_t
698 cmd_readcert (assuan_context_t ctx, char *line)
699 {
700   ctrl_t ctrl = assuan_get_pointer (ctx);
701   int rc;
702   unsigned char *cert;
703   size_t ncert;
704
705   if ((rc = open_card (ctrl, NULL)))
706     return rc;
707
708   line = xstrdup (line); /* Need a copy of the line. */
709   rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
710   if (rc)
711     log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
712   xfree (line);
713   line = NULL;
714   if (!rc)
715     {
716       rc = assuan_send_data (ctx, cert, ncert);
717       xfree (cert);
718       if (rc)
719         return rc;
720     }
721
722   TEST_CARD_REMOVAL (ctrl, rc);
723   return rc;
724 }
725
726
727 static const char hlp_readkey[] =
728   "READKEY <keyid>\n"
729   "\n"
730   "Return the public key for the given cert or key ID as a standard\n"
731   "S-expression.\n"
732   "\n"
733   "Note, that this function may even be used on a locked card.";
734 static gpg_error_t
735 cmd_readkey (assuan_context_t ctx, char *line)
736 {
737   ctrl_t ctrl = assuan_get_pointer (ctx);
738   int rc;
739   unsigned char *cert = NULL;
740   size_t ncert, n;
741   ksba_cert_t kc = NULL;
742   ksba_sexp_t p;
743   unsigned char *pk;
744   size_t pklen;
745
746   if ((rc = open_card (ctrl, NULL)))
747     return rc;
748
749   line = xstrdup (line); /* Need a copy of the line. */
750   /* If the application supports the READKEY function we use that.
751      Otherwise we use the old way by extracting it from the
752      certificate.  */
753   rc = app_readkey (ctrl->app_ctx, line, &pk, &pklen);
754   if (!rc)
755     { /* Yeah, got that key - send it back.  */
756       rc = assuan_send_data (ctx, pk, pklen);
757       xfree (pk);
758       xfree (line);
759       line = NULL;
760       goto leave;
761     }
762
763   if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION)
764     log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
765   else
766     {
767       rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
768       if (rc)
769         log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
770     }
771   xfree (line);
772   line = NULL;
773   if (rc)
774     goto leave;
775
776   rc = ksba_cert_new (&kc);
777   if (rc)
778     {
779       xfree (cert);
780       goto leave;
781     }
782   rc = ksba_cert_init_from_mem (kc, cert, ncert);
783   if (rc)
784     {
785       log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
786       goto leave;
787     }
788
789   p = ksba_cert_get_public_key (kc);
790   if (!p)
791     {
792       rc = gpg_error (GPG_ERR_NO_PUBKEY);
793       goto leave;
794     }
795
796   n = gcry_sexp_canon_len (p, 0, NULL, NULL);
797   rc = assuan_send_data (ctx, p, n);
798   xfree (p);
799
800
801  leave:
802   ksba_cert_release (kc);
803   xfree (cert);
804   TEST_CARD_REMOVAL (ctrl, rc);
805   return rc;
806 }
807
808
809 \f
810 static const char hlp_setdata[] =
811   "SETDATA <hexstring> \n"
812   "\n"
813   "The client should use this command to tell us the data he want to sign.";
814 static gpg_error_t
815 cmd_setdata (assuan_context_t ctx, char *line)
816 {
817   ctrl_t ctrl = assuan_get_pointer (ctx);
818   int n;
819   char *p;
820   unsigned char *buf;
821
822   if (locked_session && locked_session != ctrl->server_local)
823     return gpg_error (GPG_ERR_LOCKED);
824
825   /* Parse the hexstring. */
826   for (p=line,n=0; hexdigitp (p); p++, n++)
827     ;
828   if (*p)
829     return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
830   if (!n)
831     return set_error (GPG_ERR_ASS_PARAMETER, "no data given");
832   if ((n&1))
833     return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
834   n /= 2;
835   buf = xtrymalloc (n);
836   if (!buf)
837     return out_of_core ();
838
839   xfree (ctrl->in_data.value);
840   ctrl->in_data.value = buf;
841   ctrl->in_data.valuelen = n;
842   for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++)
843     buf[n] = xtoi_2 (p);
844   return 0;
845 }
846
847
848
849 static gpg_error_t
850 pin_cb (void *opaque, const char *info, char **retstr)
851 {
852   assuan_context_t ctx = opaque;
853   char *command;
854   int rc;
855   unsigned char *value;
856   size_t valuelen;
857
858   if (!retstr)
859     {
860       /* We prompt for keypad entry.  To make sure that the popup has
861          been show we use an inquire and not just a status message.
862          We ignore any value returned.  */
863       if (info)
864         {
865           log_debug ("prompting for keypad entry '%s'\n", info);
866           rc = estream_asprintf (&command, "POPUPKEYPADPROMPT %s", info);
867           if (rc < 0)
868             return gpg_error (gpg_err_code_from_errno (errno));
869           rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
870           xfree (command);
871         }
872       else
873         {
874           log_debug ("dismiss keypad entry prompt\n");
875           rc = assuan_inquire (ctx, "DISMISSKEYPADPROMPT",
876                                &value, &valuelen, MAXLEN_PIN);
877         }
878       if (!rc)
879         xfree (value);
880       return rc;
881     }
882
883   *retstr = NULL;
884   log_debug ("asking for PIN '%s'\n", info);
885
886   rc = estream_asprintf (&command, "NEEDPIN %s", info);
887   if (rc < 0)
888     return gpg_error (gpg_err_code_from_errno (errno));
889
890   /* Fixme: Write an inquire function which returns the result in
891      secure memory and check all further handling of the PIN. */
892   rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
893   xfree (command);
894   if (rc)
895     return rc;
896
897   if (!valuelen || value[valuelen-1])
898     {
899       /* We require that the returned value is an UTF-8 string */
900       xfree (value);
901       return gpg_error (GPG_ERR_INV_RESPONSE);
902     }
903   *retstr = (char*)value;
904   return 0;
905 }
906
907
908 static const char hlp_pksign[] =
909   "PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5]] <hexified_id>\n"
910   "\n"
911   "The --hash option is optional; the default is SHA1.";
912 static gpg_error_t
913 cmd_pksign (assuan_context_t ctx, char *line)
914 {
915   ctrl_t ctrl = assuan_get_pointer (ctx);
916   int rc;
917   unsigned char *outdata;
918   size_t outdatalen;
919   char *keyidstr;
920   int hash_algo;
921
922   if (has_option (line, "--hash=rmd160"))
923     hash_algo = GCRY_MD_RMD160;
924   else if (has_option (line, "--hash=sha1"))
925     hash_algo = GCRY_MD_SHA1;
926   else if (has_option (line, "--hash=sha224"))
927     hash_algo = GCRY_MD_SHA224;
928   else if (has_option (line, "--hash=sha256"))
929     hash_algo = GCRY_MD_SHA256;
930   else if (has_option (line, "--hash=sha384"))
931     hash_algo = GCRY_MD_SHA384;
932   else if (has_option (line, "--hash=sha512"))
933     hash_algo = GCRY_MD_SHA512;
934   else if (has_option (line, "--hash=md5"))
935     hash_algo = GCRY_MD_MD5;
936   else if (!strstr (line, "--"))
937     hash_algo = GCRY_MD_SHA1;
938   else
939     return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
940
941   line = skip_options (line);
942
943   if ( IS_LOCKED (ctrl) )
944     return gpg_error (GPG_ERR_LOCKED);
945
946   if ((rc = open_card (ctrl, NULL)))
947     return rc;
948
949   /* We have to use a copy of the key ID because the function may use
950      the pin_cb which in turn uses the assuan line buffer and thus
951      overwriting the original line with the keyid */
952   keyidstr = xtrystrdup (line);
953   if (!keyidstr)
954     return out_of_core ();
955
956   rc = app_sign (ctrl->app_ctx,
957                  keyidstr, hash_algo,
958                  pin_cb, ctx,
959                  ctrl->in_data.value, ctrl->in_data.valuelen,
960                  &outdata, &outdatalen);
961
962   xfree (keyidstr);
963   if (rc)
964     {
965       log_error ("app_sign failed: %s\n", gpg_strerror (rc));
966     }
967   else
968     {
969       rc = assuan_send_data (ctx, outdata, outdatalen);
970       xfree (outdata);
971       if (rc)
972         return rc; /* that is already an assuan error code */
973     }
974
975   TEST_CARD_REMOVAL (ctrl, rc);
976   return rc;
977 }
978
979
980 static const char hlp_pkauth[] =
981   "PKAUTH <hexified_id>";
982 static gpg_error_t
983 cmd_pkauth (assuan_context_t ctx, char *line)
984 {
985   ctrl_t ctrl = assuan_get_pointer (ctx);
986   int rc;
987   unsigned char *outdata;
988   size_t outdatalen;
989   char *keyidstr;
990
991   if ( IS_LOCKED (ctrl) )
992     return gpg_error (GPG_ERR_LOCKED);
993
994   if ((rc = open_card (ctrl, NULL)))
995     return rc;
996
997   if (!ctrl->app_ctx)
998     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
999
1000  /* We have to use a copy of the key ID because the function may use
1001      the pin_cb which in turn uses the assuan line buffer and thus
1002      overwriting the original line with the keyid */
1003   keyidstr = xtrystrdup (line);
1004   if (!keyidstr)
1005     return out_of_core ();
1006
1007   rc = app_auth (ctrl->app_ctx,
1008                  keyidstr,
1009                  pin_cb, ctx,
1010                  ctrl->in_data.value, ctrl->in_data.valuelen,
1011                  &outdata, &outdatalen);
1012   xfree (keyidstr);
1013   if (rc)
1014     {
1015       log_error ("app_auth failed: %s\n", gpg_strerror (rc));
1016     }
1017   else
1018     {
1019       rc = assuan_send_data (ctx, outdata, outdatalen);
1020       xfree (outdata);
1021       if (rc)
1022         return rc; /* that is already an assuan error code */
1023     }
1024
1025   TEST_CARD_REMOVAL (ctrl, rc);
1026   return rc;
1027 }
1028
1029
1030 static const char hlp_pkdecrypt[] =
1031   "PKDECRYPT <hexified_id>";
1032 static gpg_error_t
1033 cmd_pkdecrypt (assuan_context_t ctx, char *line)
1034 {
1035   ctrl_t ctrl = assuan_get_pointer (ctx);
1036   int rc;
1037   unsigned char *outdata;
1038   size_t outdatalen;
1039   char *keyidstr;
1040
1041   if ( IS_LOCKED (ctrl) )
1042     return gpg_error (GPG_ERR_LOCKED);
1043
1044   if ((rc = open_card (ctrl, NULL)))
1045     return rc;
1046
1047   keyidstr = xtrystrdup (line);
1048   if (!keyidstr)
1049     return out_of_core ();
1050   rc = app_decipher (ctrl->app_ctx,
1051                      keyidstr,
1052                      pin_cb, ctx,
1053                      ctrl->in_data.value, ctrl->in_data.valuelen,
1054                      &outdata, &outdatalen);
1055
1056   xfree (keyidstr);
1057   if (rc)
1058     {
1059       log_error ("app_decipher failed: %s\n", gpg_strerror (rc));
1060     }
1061   else
1062     {
1063       rc = assuan_send_data (ctx, outdata, outdatalen);
1064       xfree (outdata);
1065       if (rc)
1066         return rc; /* that is already an assuan error code */
1067     }
1068
1069   TEST_CARD_REMOVAL (ctrl, rc);
1070   return rc;
1071 }
1072
1073
1074 static const char hlp_getattr[] =
1075   "GETATTR <name>\n"
1076   "\n"
1077   "This command is used to retrieve data from a smartcard.  The\n"
1078   "allowed names depend on the currently selected smartcard\n"
1079   "application.  NAME must be percent and '+' escaped.  The value is\n"
1080   "returned through status message, see the LEARN command for details.\n"
1081   "\n"
1082   "However, the current implementation assumes that Name is not escaped;\n"
1083   "this works as long as noone uses arbitrary escaping. \n"
1084   "\n"
1085   "Note, that this function may even be used on a locked card.";
1086 static gpg_error_t
1087 cmd_getattr (assuan_context_t ctx, char *line)
1088 {
1089   ctrl_t ctrl = assuan_get_pointer (ctx);
1090   int rc;
1091   const char *keyword;
1092
1093   if ((rc = open_card (ctrl, NULL)))
1094     return rc;
1095
1096   keyword = line;
1097   for (; *line && !spacep (line); line++)
1098     ;
1099   if (*line)
1100       *line++ = 0;
1101
1102   /* (We ignore any garbage for now.) */
1103
1104   /* FIXME: Applications should not return sensitive data if the card
1105      is locked.  */
1106   rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
1107
1108   TEST_CARD_REMOVAL (ctrl, rc);
1109   return rc;
1110 }
1111
1112
1113 static const char hlp_setattr[] =
1114   "SETATTR <name> <value> \n"
1115   "\n"
1116   "This command is used to store data on a a smartcard.  The allowed\n"
1117   "names and values are depend on the currently selected smartcard\n"
1118   "application.  NAME and VALUE must be percent and '+' escaped.\n"
1119   "\n"
1120   "However, the current implementation assumes that NAME is not\n"
1121   "escaped; this works as long as noone uses arbitrary escaping.\n"
1122   "\n"
1123   "A PIN will be requested for most NAMEs.  See the corresponding\n"
1124   "setattr function of the actually used application (app-*.c) for\n"
1125   "details.";
1126 static gpg_error_t
1127 cmd_setattr (assuan_context_t ctx, char *orig_line)
1128 {
1129   ctrl_t ctrl = assuan_get_pointer (ctx);
1130   int rc;
1131   char *keyword;
1132   int keywordlen;
1133   size_t nbytes;
1134   char *line, *linebuf;
1135
1136   if ( IS_LOCKED (ctrl) )
1137     return gpg_error (GPG_ERR_LOCKED);
1138
1139   if ((rc = open_card (ctrl, NULL)))
1140     return rc;
1141
1142   /* We need to use a copy of LINE, because PIN_CB uses the same
1143      context and thus reuses the Assuan provided LINE. */
1144   line = linebuf = xtrystrdup (orig_line);
1145   if (!line)
1146     return out_of_core ();
1147
1148   keyword = line;
1149   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
1150     ;
1151   if (*line)
1152       *line++ = 0;
1153   while (spacep (line))
1154     line++;
1155   nbytes = percent_plus_unescape_inplace (line, 0);
1156
1157   rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx,
1158                     (const unsigned char*)line, nbytes);
1159   xfree (linebuf);
1160
1161   TEST_CARD_REMOVAL (ctrl, rc);
1162   return rc;
1163 }
1164
1165
1166 static const char hlp_writecert[] =
1167   "WRITECERT <hexified_certid>\n"
1168   "\n"
1169   "This command is used to store a certifciate on a smartcard.  The\n"
1170   "allowed certids depend on the currently selected smartcard\n"
1171   "application. The actual certifciate is requested using the inquiry\n"
1172   "\"CERTDATA\" and needs to be provided in its raw (e.g. DER) form.\n"
1173   "\n"
1174   "In almost all cases a a PIN will be requested.  See the related\n"
1175   "writecert function of the actually used application (app-*.c) for\n"
1176   "details.";
1177 static gpg_error_t
1178 cmd_writecert (assuan_context_t ctx, char *line)
1179 {
1180   ctrl_t ctrl = assuan_get_pointer (ctx);
1181   int rc;
1182   char *certid;
1183   unsigned char *certdata;
1184   size_t certdatalen;
1185
1186   if ( IS_LOCKED (ctrl) )
1187     return gpg_error (GPG_ERR_LOCKED);
1188
1189   line = skip_options (line);
1190
1191   if (!*line)
1192     return set_error (GPG_ERR_ASS_PARAMETER, "no certid given");
1193   certid = line;
1194   while (*line && !spacep (line))
1195     line++;
1196   *line = 0;
1197
1198   if ((rc = open_card (ctrl, NULL)))
1199     return rc;
1200
1201   if (!ctrl->app_ctx)
1202     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1203
1204   certid = xtrystrdup (certid);
1205   if (!certid)
1206     return out_of_core ();
1207
1208   /* Now get the actual keydata. */
1209   rc = assuan_inquire (ctx, "CERTDATA",
1210                        &certdata, &certdatalen, MAXLEN_CERTDATA);
1211   if (rc)
1212     {
1213       xfree (certid);
1214       return rc;
1215     }
1216
1217   /* Write the certificate to the card. */
1218   rc = app_writecert (ctrl->app_ctx, ctrl, certid,
1219                       pin_cb, ctx, certdata, certdatalen);
1220   xfree (certid);
1221   xfree (certdata);
1222
1223   TEST_CARD_REMOVAL (ctrl, rc);
1224   return rc;
1225 }
1226
1227
1228 static const char hlp_writekey[] =
1229   "WRITEKEY [--force] <keyid> \n"
1230   "\n"
1231   "This command is used to store a secret key on a a smartcard.  The\n"
1232   "allowed keyids depend on the currently selected smartcard\n"
1233   "application. The actual keydata is requested using the inquiry\n"
1234   "\"KEYDATA\" and need to be provided without any protection.  With\n"
1235   "--force set an existing key under this KEYID will get overwritten.\n"
1236   "The keydata is expected to be the usual canonical encoded\n"
1237   "S-expression.\n"
1238   "\n"
1239   "A PIN will be requested for most NAMEs.  See the corresponding\n"
1240   "writekey function of the actually used application (app-*.c) for\n"
1241   "details.";
1242 static gpg_error_t
1243 cmd_writekey (assuan_context_t ctx, char *line)
1244 {
1245   ctrl_t ctrl = assuan_get_pointer (ctx);
1246   int rc;
1247   char *keyid;
1248   int force = has_option (line, "--force");
1249   unsigned char *keydata;
1250   size_t keydatalen;
1251
1252   if ( IS_LOCKED (ctrl) )
1253     return gpg_error (GPG_ERR_LOCKED);
1254
1255   line = skip_options (line);
1256
1257   if (!*line)
1258     return set_error (GPG_ERR_ASS_PARAMETER, "no keyid given");
1259   keyid = line;
1260   while (*line && !spacep (line))
1261     line++;
1262   *line = 0;
1263
1264   if ((rc = open_card (ctrl, NULL)))
1265     return rc;
1266
1267   if (!ctrl->app_ctx)
1268     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1269
1270   keyid = xtrystrdup (keyid);
1271   if (!keyid)
1272     return out_of_core ();
1273
1274   /* Now get the actual keydata. */
1275   assuan_begin_confidential (ctx);
1276   rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA);
1277   assuan_end_confidential (ctx);
1278   if (rc)
1279     {
1280       xfree (keyid);
1281       return rc;
1282     }
1283
1284   /* Write the key to the card. */
1285   rc = app_writekey (ctrl->app_ctx, ctrl, keyid, force? 1:0,
1286                      pin_cb, ctx, keydata, keydatalen);
1287   xfree (keyid);
1288   xfree (keydata);
1289
1290   TEST_CARD_REMOVAL (ctrl, rc);
1291   return rc;
1292 }
1293
1294
1295 static const char hlp_genkey[] =
1296   "GENKEY [--force] [--timestamp=<isodate>] <no>\n"
1297   "\n"
1298   "Generate a key on-card identified by NO, which is application\n"
1299   "specific.  Return values are application specific.  For OpenPGP\n"
1300   "cards 3 status lines are returned:\n"
1301   "\n"
1302   "  S KEY-FPR  <hexstring>\n"
1303   "  S KEY-CREATED-AT <seconds_since_epoch>\n"
1304   "  S KEY-DATA [-|p|n] <hexdata>\n"
1305   "\n"
1306   "  'p' and 'n' are the names of the RSA parameters; '-' is used to\n"
1307   "  indicate that HEXDATA is the first chunk of a parameter given\n"
1308   "  by the next KEY-DATA.\n"
1309   "\n"
1310   "--force is required to overwrite an already existing key.  The\n"
1311   "KEY-CREATED-AT is required for further processing because it is\n"
1312   "part of the hashed key material for the fingerprint.\n"
1313   "\n"
1314   "If --timestamp is given an OpenPGP key will be created using this\n"
1315   "value.  The value needs to be in ISO Format; e.g.\n"
1316   "\"--timestamp=20030316T120000\" and after 1970-01-01 00:00:00.\n"
1317   "\n"
1318   "The public part of the key can also later be retrieved using the\n"
1319   "READKEY command.";
1320 static gpg_error_t
1321 cmd_genkey (assuan_context_t ctx, char *line)
1322 {
1323   ctrl_t ctrl = assuan_get_pointer (ctx);
1324   int rc;
1325   char *keyno;
1326   int force;
1327   const char *s;
1328   time_t timestamp;
1329
1330   if ( IS_LOCKED (ctrl) )
1331     return gpg_error (GPG_ERR_LOCKED);
1332
1333   force = has_option (line, "--force");
1334
1335   if ((s=has_option_name (line, "--timestamp")))
1336     {
1337       if (*s != '=')
1338         return set_error (GPG_ERR_ASS_PARAMETER, "missing value for option");
1339       timestamp = isotime2epoch (s+1);
1340       if (timestamp < 1)
1341         return set_error (GPG_ERR_ASS_PARAMETER, "invalid time value");
1342     }
1343   else
1344     timestamp = 0;
1345
1346
1347   line = skip_options (line);
1348   if (!*line)
1349     return set_error (GPG_ERR_ASS_PARAMETER, "no key number given");
1350   keyno = line;
1351   while (*line && !spacep (line))
1352     line++;
1353   *line = 0;
1354
1355   if ((rc = open_card (ctrl, NULL)))
1356     return rc;
1357
1358   if (!ctrl->app_ctx)
1359     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1360
1361   keyno = xtrystrdup (keyno);
1362   if (!keyno)
1363     return out_of_core ();
1364   rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0,
1365                    timestamp, pin_cb, ctx);
1366   xfree (keyno);
1367
1368   TEST_CARD_REMOVAL (ctrl, rc);
1369   return rc;
1370 }
1371
1372
1373 static const char hlp_random[] =
1374   "RANDOM <nbytes>\n"
1375   "\n"
1376   "Get NBYTES of random from the card and send them back as data.\n"
1377   "This usually involves EEPROM write on the card and thus excessive\n"
1378   "use of this command may destroy the card.\n"
1379   "\n"
1380   "Note, that this function may be even be used on a locked card.";
1381 static gpg_error_t
1382 cmd_random (assuan_context_t ctx, char *line)
1383 {
1384   ctrl_t ctrl = assuan_get_pointer (ctx);
1385   int rc;
1386   size_t nbytes;
1387   unsigned char *buffer;
1388
1389   if (!*line)
1390     return set_error (GPG_ERR_ASS_PARAMETER,
1391                       "number of requested bytes missing");
1392   nbytes = strtoul (line, NULL, 0);
1393
1394   if ((rc = open_card (ctrl, NULL)))
1395     return rc;
1396
1397   if (!ctrl->app_ctx)
1398     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1399
1400   buffer = xtrymalloc (nbytes);
1401   if (!buffer)
1402     return out_of_core ();
1403
1404   rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
1405   if (!rc)
1406     {
1407       rc = assuan_send_data (ctx, buffer, nbytes);
1408       xfree (buffer);
1409       return rc; /* that is already an assuan error code */
1410     }
1411   xfree (buffer);
1412
1413   TEST_CARD_REMOVAL (ctrl, rc);
1414   return rc;
1415 }
1416
1417
1418 \f
1419 static const char hlp_passwd[] =
1420   "PASSWD [--reset] [--nullpin] <chvno>\n"
1421   "\n"
1422   "Change the PIN or, if --reset is given, reset the retry counter of\n"
1423   "the card holder verfication vector CHVNO.  The option --nullpin is\n"
1424   "used for TCOS cards to set the initial PIN.  The format of CHVNO\n"
1425   "depends on the card application.";
1426 static gpg_error_t
1427 cmd_passwd (assuan_context_t ctx, char *line)
1428 {
1429   ctrl_t ctrl = assuan_get_pointer (ctx);
1430   int rc;
1431   char *chvnostr;
1432   unsigned int flags = 0;
1433
1434   if (has_option (line, "--reset"))
1435     flags |= APP_CHANGE_FLAG_RESET;
1436   if (has_option (line, "--nullpin"))
1437     flags |= APP_CHANGE_FLAG_NULLPIN;
1438
1439   if ( IS_LOCKED (ctrl) )
1440     return gpg_error (GPG_ERR_LOCKED);
1441
1442   line = skip_options (line);
1443
1444   if (!*line)
1445     return set_error (GPG_ERR_ASS_PARAMETER, "no CHV number given");
1446   chvnostr = line;
1447   while (*line && !spacep (line))
1448     line++;
1449   *line = 0;
1450
1451   if ((rc = open_card (ctrl, NULL)))
1452     return rc;
1453
1454   if (!ctrl->app_ctx)
1455     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1456
1457   chvnostr = xtrystrdup (chvnostr);
1458   if (!chvnostr)
1459     return out_of_core ();
1460   rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, flags, pin_cb, ctx);
1461   if (rc)
1462     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1463   xfree (chvnostr);
1464
1465   TEST_CARD_REMOVAL (ctrl, rc);
1466   return rc;
1467 }
1468
1469
1470 static const char hlp_checkpin[] =
1471   "CHECKPIN <idstr>\n"
1472   "\n"
1473   "Perform a VERIFY operation without doing anything else.  This may\n"
1474   "be used to initialize a the PIN cache earlier to long lasting\n"
1475   "operations.  Its use is highly application dependent.\n"
1476   "\n"
1477   "For OpenPGP:\n"
1478   "\n"
1479   "   Perform a simple verify operation for CHV1 and CHV2, so that\n"
1480   "   further operations won't ask for CHV2 and it is possible to do a\n"
1481   "   cheap check on the PIN: If there is something wrong with the PIN\n"
1482   "   entry system, only the regular CHV will get blocked and not the\n"
1483   "   dangerous CHV3.  IDSTR is the usual card's serial number in hex\n"
1484   "   notation; an optional fingerprint part will get ignored.  There\n"
1485   "   is however a special mode if the IDSTR is sffixed with the\n"
1486   "   literal string \"[CHV3]\": In this case the Admin PIN is checked\n"
1487   "   if and only if the retry counter is still at 3.\n"
1488   "\n"
1489   "For Netkey:\n"
1490   "\n"
1491   "   Any of the valid PIN Ids may be used.  These are the strings:\n"
1492   "\n"
1493   "     PW1.CH       - Global password 1\n"
1494   "     PW2.CH       - Global password 2\n"
1495   "     PW1.CH.SIG   - SigG password 1\n"
1496   "     PW2.CH.SIG   - SigG password 2\n"
1497   "\n"
1498   "   For a definitive list, see the implementation in app-nks.c.\n"
1499   "   Note that we call a PW2.* PIN a \"PUK\" despite that since TCOS\n"
1500   "   3.0 they are technically alternative PINs used to mutally\n"
1501   "   unblock each other.";
1502 static gpg_error_t
1503 cmd_checkpin (assuan_context_t ctx, char *line)
1504 {
1505   ctrl_t ctrl = assuan_get_pointer (ctx);
1506   int rc;
1507   char *idstr;
1508
1509   if ( IS_LOCKED (ctrl) )
1510     return gpg_error (GPG_ERR_LOCKED);
1511
1512   if ((rc = open_card (ctrl, NULL)))
1513     return rc;
1514
1515   if (!ctrl->app_ctx)
1516     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1517
1518   /* We have to use a copy of the key ID because the function may use
1519      the pin_cb which in turn uses the assuan line buffer and thus
1520      overwriting the original line with the keyid. */
1521   idstr = xtrystrdup (line);
1522   if (!idstr)
1523     return out_of_core ();
1524
1525   rc = app_check_pin (ctrl->app_ctx, idstr, pin_cb, ctx);
1526   xfree (idstr);
1527   if (rc)
1528     log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
1529
1530   TEST_CARD_REMOVAL (ctrl, rc);
1531   return rc;
1532 }
1533
1534
1535 static const char hlp_lock[] =
1536   "LOCK [--wait]\n"
1537   "\n"
1538   "Grant exclusive card access to this session.  Note that there is\n"
1539   "no lock counter used and a second lock from the same session will\n"
1540   "be ignored.  A single unlock (or RESET) unlocks the session.\n"
1541   "Return GPG_ERR_LOCKED if another session has locked the reader.\n"
1542   "\n"
1543   "If the option --wait is given the command will wait until a\n"
1544   "lock has been released.";
1545 static gpg_error_t
1546 cmd_lock (assuan_context_t ctx, char *line)
1547 {
1548   ctrl_t ctrl = assuan_get_pointer (ctx);
1549   int rc = 0;
1550
1551  retry:
1552   if (locked_session)
1553     {
1554       if (locked_session != ctrl->server_local)
1555         rc = gpg_error (GPG_ERR_LOCKED);
1556     }
1557   else
1558     locked_session = ctrl->server_local;
1559
1560 #ifdef USE_GNU_PTH
1561   if (rc && has_option (line, "--wait"))
1562     {
1563       rc = 0;
1564       pth_sleep (1); /* Better implement an event mechanism. However,
1565                         for card operations this should be
1566                         sufficient. */
1567       /* FIXME: Need to check that the connection is still alive.
1568          This can be done by issuing status messages. */
1569       goto retry;
1570     }
1571 #endif /*USE_GNU_PTH*/
1572
1573   if (rc)
1574     log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
1575   return rc;
1576 }
1577
1578
1579 static const char hlp_unlock[] =
1580   "UNLOCK\n"
1581   "\n"
1582   "Release exclusive card access.";
1583 static gpg_error_t
1584 cmd_unlock (assuan_context_t ctx, char *line)
1585 {
1586   ctrl_t ctrl = assuan_get_pointer (ctx);
1587   int rc = 0;
1588
1589   (void)line;
1590
1591   if (locked_session)
1592     {
1593       if (locked_session != ctrl->server_local)
1594         rc = gpg_error (GPG_ERR_LOCKED);
1595       else
1596         locked_session = NULL;
1597     }
1598   else
1599     rc = gpg_error (GPG_ERR_NOT_LOCKED);
1600
1601   if (rc)
1602     log_error ("cmd_unlock failed: %s\n", gpg_strerror (rc));
1603   return rc;
1604 }
1605
1606
1607 static const char hlp_getinfo[] =
1608   "GETINFO <what>\n"
1609   "\n"
1610   "Multi purpose command to return certain information.  \n"
1611   "Supported values of WHAT are:\n"
1612   "\n"
1613   "version     - Return the version of the program.\n"
1614   "pid         - Return the process id of the server.\n"
1615   "\n"
1616   "socket_name - Return the name of the socket.\n"
1617   "\n"
1618   "status - Return the status of the current slot (in the future, may\n"
1619   "also return the status of all slots).  The status is a list of\n"
1620   "one-character flags.  The following flags are currently defined:\n"
1621   "  'u'  Usable card present.  This is the normal state during operation.\n"
1622   "  'r'  Card removed.  A reset is necessary.\n"
1623   "These flags are exclusive.\n"
1624   "\n"
1625   "reader_list - Return a list of detected card readers.  Does\n"
1626   "              currently only work with the internal CCID driver.\n"
1627   "\n"
1628   "deny_admin  - Returns OK if admin commands are not allowed or\n"
1629   "              GPG_ERR_GENERAL if admin commands are allowed.\n"
1630   "\n"
1631   "app_list    - Return a list of supported applications.  One\n"
1632   "              application per line, fields delimited by colons,\n"
1633   "              first field is the name.";
1634 static gpg_error_t
1635 cmd_getinfo (assuan_context_t ctx, char *line)
1636 {
1637   int rc = 0;
1638
1639   if (!strcmp (line, "version"))
1640     {
1641       const char *s = VERSION;
1642       rc = assuan_send_data (ctx, s, strlen (s));
1643     }
1644   else if (!strcmp (line, "pid"))
1645     {
1646       char numbuf[50];
1647
1648       snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1649       rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1650     }
1651   else if (!strcmp (line, "socket_name"))
1652     {
1653       const char *s = scd_get_socket_name ();
1654
1655       if (s)
1656         rc = assuan_send_data (ctx, s, strlen (s));
1657       else
1658         rc = gpg_error (GPG_ERR_NO_DATA);
1659     }
1660   else if (!strcmp (line, "status"))
1661     {
1662       ctrl_t ctrl = assuan_get_pointer (ctx);
1663       int slot = ctrl->reader_slot;
1664       char flag = 'r';
1665
1666       if (!ctrl->server_local->card_removed && slot != -1)
1667         {
1668           struct slot_status_s *ss;
1669
1670           if (!(slot >= 0 && slot < DIM(slot_table)))
1671             BUG ();
1672
1673           ss = &slot_table[slot];
1674
1675           if (!ss->valid)
1676             BUG ();
1677
1678           if (ss->any && (ss->status & 1))
1679             flag = 'u';
1680         }
1681       rc = assuan_send_data (ctx, &flag, 1);
1682     }
1683   else if (!strcmp (line, "reader_list"))
1684     {
1685 #ifdef HAVE_LIBUSB
1686       char *s = ccid_get_reader_list ();
1687 #else
1688       char *s = NULL;
1689 #endif
1690
1691       if (s)
1692         rc = assuan_send_data (ctx, s, strlen (s));
1693       else
1694         rc = gpg_error (GPG_ERR_NO_DATA);
1695       xfree (s);
1696     }
1697   else if (!strcmp (line, "deny_admin"))
1698     rc = opt.allow_admin? gpg_error (GPG_ERR_GENERAL) : 0;
1699   else if (!strcmp (line, "app_list"))
1700     {
1701       char *s = get_supported_applications ();
1702       if (s)
1703         rc = assuan_send_data (ctx, s, strlen (s));
1704       else
1705         rc = 0;
1706       xfree (s);
1707     }
1708   else
1709     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1710   return rc;
1711 }
1712
1713
1714 static const char hlp_restart[] =
1715   "RESTART\n"
1716   "\n"
1717   "Restart the current connection; this is a kind of warm reset.  It\n"
1718   "deletes the context used by this connection but does not send a\n"
1719   "RESET to the card.  Thus the card itself won't get reset. \n"
1720   "\n"
1721   "This is used by gpg-agent to reuse a primary pipe connection and\n"
1722   "may be used by clients to backup from a conflict in the serial\n"
1723   "command; i.e. to select another application.";
1724 static gpg_error_t
1725 cmd_restart (assuan_context_t ctx, char *line)
1726 {
1727   ctrl_t ctrl = assuan_get_pointer (ctx);
1728
1729   (void)line;
1730
1731   if (ctrl->app_ctx)
1732     {
1733       release_application (ctrl->app_ctx);
1734       ctrl->app_ctx = NULL;
1735     }
1736   if (locked_session && ctrl->server_local == locked_session)
1737     {
1738       locked_session = NULL;
1739       log_info ("implicitly unlocking due to RESTART\n");
1740     }
1741   return 0;
1742 }
1743
1744
1745 static const char hlp_disconnect[] =
1746   "DISCONNECT\n"
1747   "\n"
1748   "Disconnect the card if it is not any longer used by other\n"
1749   "connections and the backend supports a disconnect operation.";
1750 static gpg_error_t
1751 cmd_disconnect (assuan_context_t ctx, char *line)
1752 {
1753   ctrl_t ctrl = assuan_get_pointer (ctx);
1754
1755   (void)line;
1756
1757   ctrl->server_local->disconnect_allowed = 1;
1758   return 0;
1759 }
1760
1761
1762
1763 static const char hlp_apdu[] =
1764   "APDU [--atr] [--more] [--exlen[=N]] [hexstring]\n"
1765   "\n"
1766   "Send an APDU to the current reader.  This command bypasses the high\n"
1767   "level functions and sends the data directly to the card.  HEXSTRING\n"
1768   "is expected to be a proper APDU.  If HEXSTRING is not given no\n"
1769   "commands are set to the card but the command will implictly check\n"
1770   "whether the card is ready for use. \n"
1771   "\n"
1772   "Using the option \"--atr\" returns the ATR of the card as a status\n"
1773   "message before any data like this:\n"
1774   "  S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1\n"
1775   "\n"
1776   "Using the option --more handles the card status word MORE_DATA\n"
1777   "(61xx) and concatenates all reponses to one block.\n"
1778   "\n"
1779   "Using the option \"--exlen\" the returned APDU may use extended\n"
1780   "length up to N bytes.  If N is not given a default value is used\n"
1781   "(currently 4096).";
1782 static gpg_error_t
1783 cmd_apdu (assuan_context_t ctx, char *line)
1784 {
1785   ctrl_t ctrl = assuan_get_pointer (ctx);
1786   int rc;
1787   unsigned char *apdu;
1788   size_t apdulen;
1789   int with_atr;
1790   int handle_more;
1791   const char *s;
1792   size_t exlen;
1793
1794   with_atr = has_option (line, "--atr");
1795   handle_more = has_option (line, "--more");
1796
1797   if ((s=has_option_name (line, "--exlen")))
1798     {
1799       if (*s == '=')
1800         exlen = strtoul (s+1, NULL, 0);
1801       else
1802         exlen = 4096;
1803     }
1804   else
1805     exlen = 0;
1806
1807   line = skip_options (line);
1808
1809   if ( IS_LOCKED (ctrl) )
1810     return gpg_error (GPG_ERR_LOCKED);
1811
1812   if ((rc = open_card (ctrl, NULL)))
1813     return rc;
1814
1815   if (with_atr)
1816     {
1817       unsigned char *atr;
1818       size_t atrlen;
1819       char hexbuf[400];
1820
1821       atr = apdu_get_atr (ctrl->reader_slot, &atrlen);
1822       if (!atr || atrlen > sizeof hexbuf - 2 )
1823         {
1824           rc = gpg_error (GPG_ERR_INV_CARD);
1825           goto leave;
1826         }
1827       bin2hex (atr, atrlen, hexbuf);
1828       xfree (atr);
1829       send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
1830     }
1831
1832   apdu = hex_to_buffer (line, &apdulen);
1833   if (!apdu)
1834     {
1835       rc = gpg_error_from_syserror ();
1836       goto leave;
1837     }
1838   if (apdulen)
1839     {
1840       unsigned char *result = NULL;
1841       size_t resultlen;
1842
1843       rc = apdu_send_direct (ctrl->reader_slot, exlen,
1844                              apdu, apdulen, handle_more,
1845                              &result, &resultlen);
1846       if (rc)
1847         log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
1848       else
1849         {
1850           rc = assuan_send_data (ctx, result, resultlen);
1851           xfree (result);
1852         }
1853     }
1854   xfree (apdu);
1855
1856  leave:
1857   TEST_CARD_REMOVAL (ctrl, rc);
1858   return rc;
1859 }
1860
1861
1862 static const char hlp_killscd[] =
1863   "KILLSCD\n"
1864   "\n"
1865   "Commit suicide.";
1866 static gpg_error_t
1867 cmd_killscd (assuan_context_t ctx, char *line)
1868 {
1869   ctrl_t ctrl = assuan_get_pointer (ctx);
1870
1871   (void)line;
1872
1873   ctrl->server_local->stopme = 1;
1874 #ifdef ASSUAN_FORCE_CLOSE
1875   assuan_set_flag (ctx, ASSUAN_FORCE_CLOSE, 1);
1876   return 0;
1877 #else
1878   /* Actually returning an EOF does not anymore work with modern
1879      Libassuan versions.  However we keep that non working code until
1880      we make a Libassuan with the force close flag a requirement.  */
1881   return gpg_error (GPG_ERR_EOF);
1882 #endif
1883 }
1884
1885
1886 \f
1887 /* Tell the assuan library about our commands */
1888 static int
1889 register_commands (assuan_context_t ctx)
1890 {
1891   static struct {
1892     const char *name;
1893     assuan_handler_t handler;
1894     const char * const help;
1895   } table[] = {
1896     { "SERIALNO",     cmd_serialno, hlp_serialno },
1897     { "LEARN",        cmd_learn,    hlp_learn },
1898     { "READCERT",     cmd_readcert, hlp_readcert },
1899     { "READKEY",      cmd_readkey,  hlp_readkey },
1900     { "SETDATA",      cmd_setdata,  hlp_setdata },
1901     { "PKSIGN",       cmd_pksign,   hlp_pksign },
1902     { "PKAUTH",       cmd_pkauth,   hlp_pkauth },
1903     { "PKDECRYPT",    cmd_pkdecrypt,hlp_pkdecrypt },
1904     { "INPUT",        NULL },
1905     { "OUTPUT",       NULL },
1906     { "GETATTR",      cmd_getattr,  hlp_getattr },
1907     { "SETATTR",      cmd_setattr,  hlp_setattr },
1908     { "WRITECERT",    cmd_writecert,hlp_writecert },
1909     { "WRITEKEY",     cmd_writekey, hlp_writekey },
1910     { "GENKEY",       cmd_genkey,   hlp_genkey },
1911     { "RANDOM",       cmd_random,   hlp_random },
1912     { "PASSWD",       cmd_passwd,   hlp_passwd },
1913     { "CHECKPIN",     cmd_checkpin, hlp_checkpin },
1914     { "LOCK",         cmd_lock,     hlp_lock },
1915     { "UNLOCK",       cmd_unlock,   hlp_unlock },
1916     { "GETINFO",      cmd_getinfo,  hlp_getinfo },
1917     { "RESTART",      cmd_restart,  hlp_restart },
1918     { "DISCONNECT",   cmd_disconnect,hlp_disconnect },
1919     { "APDU",         cmd_apdu,     hlp_apdu },
1920     { "KILLSCD",      cmd_killscd,  hlp_killscd },
1921     { NULL }
1922   };
1923   int i, rc;
1924
1925   for (i=0; table[i].name; i++)
1926     {
1927       rc = assuan_register_command (ctx, table[i].name, table[i].handler,
1928                                     table[i].help);
1929       if (rc)
1930         return rc;
1931     }
1932   assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
1933
1934   assuan_register_reset_notify (ctx, reset_notify);
1935   assuan_register_option_handler (ctx, option_handler);
1936   return 0;
1937 }
1938
1939
1940 /* Startup the server.  If FD is given as -1 this is simple pipe
1941    server, otherwise it is a regular server.  Returns true if there
1942    are no more active asessions.  */
1943 int
1944 scd_command_handler (ctrl_t ctrl, int fd)
1945 {
1946   int rc;
1947   assuan_context_t ctx = NULL;
1948   int stopme;
1949
1950   rc = assuan_new (&ctx);
1951   if (rc)
1952     {
1953       log_error ("failed to allocate assuan context: %s\n",
1954                  gpg_strerror (rc));
1955       scd_exit (2);
1956     }
1957
1958   if (fd == -1)
1959     {
1960       assuan_fd_t filedes[2];
1961
1962       filedes[0] = assuan_fdopen (0);
1963       filedes[1] = assuan_fdopen (1);
1964       rc = assuan_init_pipe_server (ctx, filedes);
1965     }
1966   else
1967     {
1968       rc = assuan_init_socket_server (ctx, INT2FD(fd),
1969                                       ASSUAN_SOCKET_SERVER_ACCEPTED);
1970     }
1971   if (rc)
1972     {
1973       log_error ("failed to initialize the server: %s\n",
1974                  gpg_strerror(rc));
1975       scd_exit (2);
1976     }
1977   rc = register_commands (ctx);
1978   if (rc)
1979     {
1980       log_error ("failed to register commands with Assuan: %s\n",
1981                  gpg_strerror(rc));
1982       scd_exit (2);
1983     }
1984   assuan_set_pointer (ctx, ctrl);
1985
1986   /* Allocate and initialize the server object.  Put it into the list
1987      of active sessions. */
1988   ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
1989   ctrl->server_local->next_session = session_list;
1990   session_list = ctrl->server_local;
1991   ctrl->server_local->ctrl_backlink = ctrl;
1992   ctrl->server_local->assuan_ctx = ctx;
1993
1994   /* We open the reader right at startup so that the ticker is able to
1995      update the status file. */
1996   if (ctrl->reader_slot == -1)
1997     {
1998       ctrl->reader_slot = get_reader_slot ();
1999     }
2000
2001   /* Command processing loop. */
2002   for (;;)
2003     {
2004       rc = assuan_accept (ctx);
2005       if (rc == -1)
2006         {
2007           break;
2008         }
2009       else if (rc)
2010         {
2011           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
2012           break;
2013         }
2014
2015       rc = assuan_process (ctx);
2016       if (rc)
2017         {
2018           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
2019           continue;
2020         }
2021     }
2022
2023   /* Cleanup.  We don't send an explicit reset to the card.  */
2024   do_reset (ctrl, 0);
2025
2026   /* Release the server object.  */
2027   if (session_list == ctrl->server_local)
2028     session_list = ctrl->server_local->next_session;
2029   else
2030     {
2031       struct server_local_s *sl;
2032
2033       for (sl=session_list; sl->next_session; sl = sl->next_session)
2034         if (sl->next_session == ctrl->server_local)
2035           break;
2036       if (!sl->next_session)
2037           BUG ();
2038       sl->next_session = ctrl->server_local->next_session;
2039     }
2040   stopme = ctrl->server_local->stopme || reader_disabled;
2041   xfree (ctrl->server_local);
2042   ctrl->server_local = NULL;
2043
2044   /* Release the Assuan context.  */
2045   assuan_release (ctx);
2046
2047   if (stopme)
2048     scd_exit (0);
2049
2050   /* If there are no more sessions return true.  */
2051   return !session_list;
2052 }
2053
2054
2055 /* Send a line with status information via assuan and escape all given
2056    buffers. The variable elements are pairs of (char *, size_t),
2057    terminated with a (NULL, 0). */
2058 void
2059 send_status_info (ctrl_t ctrl, const char *keyword, ...)
2060 {
2061   va_list arg_ptr;
2062   const unsigned char *value;
2063   size_t valuelen;
2064   char buf[950], *p;
2065   size_t n;
2066   assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2067
2068   va_start (arg_ptr, keyword);
2069
2070   p = buf;
2071   n = 0;
2072   while ( (value = va_arg (arg_ptr, const unsigned char *)) )
2073     {
2074       valuelen = va_arg (arg_ptr, size_t);
2075       if (!valuelen)
2076         continue; /* empty buffer */
2077       if (n)
2078         {
2079           *p++ = ' ';
2080           n++;
2081         }
2082       for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
2083         {
2084           if (*value < ' ' || *value == '+')
2085             {
2086               sprintf (p, "%%%02X", *value);
2087               p += 3;
2088             }
2089           else if (*value == ' ')
2090             *p++ = '+';
2091           else
2092             *p++ = *value;
2093         }
2094     }
2095   *p = 0;
2096   assuan_write_status (ctx, keyword, buf);
2097
2098   va_end (arg_ptr);
2099 }
2100
2101
2102 /* Send a ready formatted status line via assuan.  */
2103 void
2104 send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
2105 {
2106   assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2107
2108   if (strchr (args, '\n'))
2109     log_error ("error: LF detected in status line - not sending\n");
2110   else
2111     assuan_write_status (ctx, keyword, args);
2112 }
2113
2114
2115 /* Helper to send the clients a status change notification.  */
2116 static void
2117 send_client_notifications (void)
2118 {
2119   struct {
2120     pid_t pid;
2121 #ifdef HAVE_W32_SYSTEM
2122     HANDLE handle;
2123 #else
2124     int signo;
2125 #endif
2126   } killed[50];
2127   int killidx = 0;
2128   int kidx;
2129   struct server_local_s *sl;
2130
2131   for (sl=session_list; sl; sl = sl->next_session)
2132     {
2133       if (sl->event_signal && sl->assuan_ctx)
2134         {
2135           pid_t pid = assuan_get_pid (sl->assuan_ctx);
2136 #ifdef HAVE_W32_SYSTEM
2137           HANDLE handle = (void *)sl->event_signal;
2138
2139           for (kidx=0; kidx < killidx; kidx++)
2140             if (killed[kidx].pid == pid
2141                 && killed[kidx].handle == handle)
2142               break;
2143           if (kidx < killidx)
2144             log_info ("event %lx (%p) already triggered for client %d\n",
2145                       sl->event_signal, handle, (int)pid);
2146           else
2147             {
2148               log_info ("triggering event %lx (%p) for client %d\n",
2149                         sl->event_signal, handle, (int)pid);
2150               if (!SetEvent (handle))
2151                 log_error ("SetEvent(%lx) failed: %s\n",
2152                            sl->event_signal, w32_strerror (-1));
2153               if (killidx < DIM (killed))
2154                 {
2155                   killed[killidx].pid = pid;
2156                   killed[killidx].handle = handle;
2157                   killidx++;
2158                 }
2159             }
2160 #else /*!HAVE_W32_SYSTEM*/
2161           int signo = sl->event_signal;
2162
2163           if (pid != (pid_t)(-1) && pid && signo > 0)
2164             {
2165               for (kidx=0; kidx < killidx; kidx++)
2166                 if (killed[kidx].pid == pid
2167                     && killed[kidx].signo == signo)
2168                   break;
2169               if (kidx < killidx)
2170                 log_info ("signal %d already sent to client %d\n",
2171                           signo, (int)pid);
2172               else
2173                 {
2174                   log_info ("sending signal %d to client %d\n",
2175                             signo, (int)pid);
2176                   kill (pid, signo);
2177                   if (killidx < DIM (killed))
2178                     {
2179                       killed[killidx].pid = pid;
2180                       killed[killidx].signo = signo;
2181                       killidx++;
2182                     }
2183                 }
2184             }
2185 #endif /*!HAVE_W32_SYSTEM*/
2186         }
2187     }
2188 }
2189
2190
2191
2192 /* This is the core of scd_update_reader_status_file but the caller
2193    needs to take care of the locking.  */
2194 static void
2195 update_reader_status_file (int set_card_removed_flag)
2196 {
2197   int idx;
2198   unsigned int status, changed;
2199
2200   /* Make sure that the reader has been opened.  Like get_reader_slot,
2201      this part of the code assumes that there is only one reader.  */
2202   if (!slot_table[0].valid)
2203     (void)get_reader_slot ();
2204
2205   /* Note, that we only try to get the status, because it does not
2206      make sense to wait here for a operation to complete.  If we are
2207      busy working with a card, delays in the status file update should
2208      be acceptable. */
2209   for (idx=0; idx < DIM(slot_table); idx++)
2210     {
2211       struct slot_status_s *ss = slot_table + idx;
2212       struct server_local_s *sl;
2213       int sw_apdu;
2214
2215       if (!ss->valid || ss->slot == -1)
2216         continue; /* Not valid or reader not yet open. */
2217
2218       sw_apdu = apdu_get_status (ss->slot, 0, &status, &changed);
2219       if (sw_apdu == SW_HOST_NO_READER)
2220         {
2221           /* Most likely the _reader_ has been unplugged.  */
2222           apdu_close_reader(ss->slot);
2223           ss->valid = 0;
2224           status = 0;
2225           changed = ss->changed;
2226         }
2227       else if (sw_apdu)
2228         {
2229           /* Get status failed.  Ignore that.  */
2230           continue;
2231         }
2232
2233       if (!ss->any || ss->status != status || ss->changed != changed )
2234         {
2235           char *fname;
2236           char templ[50];
2237           FILE *fp;
2238
2239           log_info ("updating slot %d status: 0x%04X->0x%04X (%u->%u)\n",
2240                     ss->slot, ss->status, status, ss->changed, changed);
2241           ss->status = status;
2242           ss->changed = changed;
2243
2244           /* FIXME: Should this be IDX instead of ss->slot?  This
2245              depends on how client sessions will associate the reader
2246              status with their session.  */
2247           snprintf (templ, sizeof templ, "reader_%d.status", ss->slot);
2248           fname = make_filename (opt.homedir, templ, NULL );
2249           fp = fopen (fname, "w");
2250           if (fp)
2251             {
2252               fprintf (fp, "%s\n",
2253                        (status & 1)? "USABLE":
2254                        (status & 4)? "ACTIVE":
2255                        (status & 2)? "PRESENT": "NOCARD");
2256               fclose (fp);
2257             }
2258           xfree (fname);
2259
2260           /* If a status script is executable, run it. */
2261           {
2262             const char *args[9], *envs[2];
2263             char numbuf1[30], numbuf2[30], numbuf3[30];
2264             char *homestr, *envstr;
2265             gpg_error_t err;
2266
2267             homestr = make_filename (opt.homedir, NULL);
2268             if (estream_asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
2269               log_error ("out of core while building environment\n");
2270             else
2271               {
2272                 envs[0] = envstr;
2273                 envs[1] = NULL;
2274
2275                 sprintf (numbuf1, "%d", ss->slot);
2276                 sprintf (numbuf2, "0x%04X", ss->status);
2277                 sprintf (numbuf3, "0x%04X", status);
2278                 args[0] = "--reader-port";
2279                 args[1] = numbuf1;
2280                 args[2] = "--old-code";
2281                 args[3] = numbuf2;
2282                 args[4] = "--new-code";
2283                 args[5] = numbuf3;
2284                 args[6] = "--status";
2285                 args[7] = ((status & 1)? "USABLE":
2286                            (status & 4)? "ACTIVE":
2287                            (status & 2)? "PRESENT": "NOCARD");
2288                 args[8] = NULL;
2289
2290                 fname = make_filename (opt.homedir, "scd-event", NULL);
2291                 err = gnupg_spawn_process_detached (fname, args, envs);
2292                 if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
2293                   log_error ("failed to run event handler `%s': %s\n",
2294                              fname, gpg_strerror (err));
2295                 xfree (fname);
2296                 xfree (envstr);
2297               }
2298             xfree (homestr);
2299           }
2300
2301           /* Set the card removed flag for all current sessions.  We
2302              will set this on any card change because a reset or
2303              SERIALNO request must be done in any case.  */
2304           if (ss->any && set_card_removed_flag)
2305             update_card_removed (idx, 1);
2306
2307           ss->any = 1;
2308
2309           /* Send a signal to all clients who applied for it.  */
2310           send_client_notifications ();
2311         }
2312
2313       /* Check whether a disconnect is pending.  */
2314       if (opt.card_timeout)
2315         {
2316           for (sl=session_list; sl; sl = sl->next_session)
2317             if (!sl->disconnect_allowed)
2318               break;
2319           if (session_list && !sl)
2320             {
2321               /* FIXME: Use a real timeout.  */
2322               /* At least one connection and all allow a disconnect.  */
2323               log_info ("disconnecting card in slot %d\n", ss->slot);
2324               apdu_disconnect (ss->slot);
2325             }
2326         }
2327
2328     }
2329 }
2330
2331 /* This function is called by the ticker thread to check for changes
2332    of the reader stati.  It updates the reader status files and if
2333    requested by the caller also send a signal to the caller.  */
2334 void
2335 scd_update_reader_status_file (void)
2336 {
2337   if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL))
2338     return; /* locked - give up. */
2339   update_reader_status_file (1);
2340   if (!pth_mutex_release (&status_file_update_lock))
2341     log_error ("failed to release status_file_update lock\n");
2342 }