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