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