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