Require Libassuan 2.0.3
[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   assuan_set_flag (ctx, ASSUAN_FORCE_CLOSE, 1);
1940   return 0;
1941 }
1942
1943
1944 \f
1945 /* Tell the assuan library about our commands */
1946 static int
1947 register_commands (assuan_context_t ctx)
1948 {
1949   static struct {
1950     const char *name;
1951     assuan_handler_t handler;
1952     const char * const help;
1953   } table[] = {
1954     { "SERIALNO",     cmd_serialno, hlp_serialno },
1955     { "LEARN",        cmd_learn,    hlp_learn },
1956     { "READCERT",     cmd_readcert, hlp_readcert },
1957     { "READKEY",      cmd_readkey,  hlp_readkey },
1958     { "SETDATA",      cmd_setdata,  hlp_setdata },
1959     { "PKSIGN",       cmd_pksign,   hlp_pksign },
1960     { "PKAUTH",       cmd_pkauth,   hlp_pkauth },
1961     { "PKDECRYPT",    cmd_pkdecrypt,hlp_pkdecrypt },
1962     { "INPUT",        NULL },
1963     { "OUTPUT",       NULL },
1964     { "GETATTR",      cmd_getattr,  hlp_getattr },
1965     { "SETATTR",      cmd_setattr,  hlp_setattr },
1966     { "WRITECERT",    cmd_writecert,hlp_writecert },
1967     { "WRITEKEY",     cmd_writekey, hlp_writekey },
1968     { "GENKEY",       cmd_genkey,   hlp_genkey },
1969     { "RANDOM",       cmd_random,   hlp_random },
1970     { "PASSWD",       cmd_passwd,   hlp_passwd },
1971     { "CHECKPIN",     cmd_checkpin, hlp_checkpin },
1972     { "LOCK",         cmd_lock,     hlp_lock },
1973     { "UNLOCK",       cmd_unlock,   hlp_unlock },
1974     { "GETINFO",      cmd_getinfo,  hlp_getinfo },
1975     { "RESTART",      cmd_restart,  hlp_restart },
1976     { "DISCONNECT",   cmd_disconnect,hlp_disconnect },
1977     { "APDU",         cmd_apdu,     hlp_apdu },
1978     { "KILLSCD",      cmd_killscd,  hlp_killscd },
1979     { NULL }
1980   };
1981   int i, rc;
1982
1983   for (i=0; table[i].name; i++)
1984     {
1985       rc = assuan_register_command (ctx, table[i].name, table[i].handler,
1986                                     table[i].help);
1987       if (rc)
1988         return rc;
1989     }
1990   assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
1991
1992   assuan_register_reset_notify (ctx, reset_notify);
1993   assuan_register_option_handler (ctx, option_handler);
1994   return 0;
1995 }
1996
1997
1998 /* Startup the server.  If FD is given as -1 this is simple pipe
1999    server, otherwise it is a regular server.  Returns true if there
2000    are no more active asessions.  */
2001 int
2002 scd_command_handler (ctrl_t ctrl, int fd)
2003 {
2004   int rc;
2005   assuan_context_t ctx = NULL;
2006   int stopme;
2007
2008   rc = assuan_new (&ctx);
2009   if (rc)
2010     {
2011       log_error ("failed to allocate assuan context: %s\n",
2012                  gpg_strerror (rc));
2013       scd_exit (2);
2014     }
2015
2016   if (fd == -1)
2017     {
2018       assuan_fd_t filedes[2];
2019
2020       filedes[0] = assuan_fdopen (0);
2021       filedes[1] = assuan_fdopen (1);
2022       rc = assuan_init_pipe_server (ctx, filedes);
2023     }
2024   else
2025     {
2026       rc = assuan_init_socket_server (ctx, INT2FD(fd),
2027                                       ASSUAN_SOCKET_SERVER_ACCEPTED);
2028     }
2029   if (rc)
2030     {
2031       log_error ("failed to initialize the server: %s\n",
2032                  gpg_strerror(rc));
2033       scd_exit (2);
2034     }
2035   rc = register_commands (ctx);
2036   if (rc)
2037     {
2038       log_error ("failed to register commands with Assuan: %s\n",
2039                  gpg_strerror(rc));
2040       scd_exit (2);
2041     }
2042   assuan_set_pointer (ctx, ctrl);
2043
2044   /* Allocate and initialize the server object.  Put it into the list
2045      of active sessions. */
2046   ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
2047   ctrl->server_local->next_session = session_list;
2048   session_list = ctrl->server_local;
2049   ctrl->server_local->ctrl_backlink = ctrl;
2050   ctrl->server_local->assuan_ctx = ctx;
2051   ctrl->server_local->vreader_idx = -1;
2052
2053   /* We open the reader right at startup so that the ticker is able to
2054      update the status file. */
2055   if (ctrl->server_local->vreader_idx == -1)
2056     {
2057       ctrl->server_local->vreader_idx = get_current_reader ();
2058     }
2059
2060   /* Command processing loop. */
2061   for (;;)
2062     {
2063       rc = assuan_accept (ctx);
2064       if (rc == -1)
2065         {
2066           break;
2067         }
2068       else if (rc)
2069         {
2070           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
2071           break;
2072         }
2073
2074       rc = assuan_process (ctx);
2075       if (rc)
2076         {
2077           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
2078           continue;
2079         }
2080     }
2081
2082   /* Cleanup.  We don't send an explicit reset to the card.  */
2083   do_reset (ctrl, 0);
2084
2085   /* Release the server object.  */
2086   if (session_list == ctrl->server_local)
2087     session_list = ctrl->server_local->next_session;
2088   else
2089     {
2090       struct server_local_s *sl;
2091
2092       for (sl=session_list; sl->next_session; sl = sl->next_session)
2093         if (sl->next_session == ctrl->server_local)
2094           break;
2095       if (!sl->next_session)
2096           BUG ();
2097       sl->next_session = ctrl->server_local->next_session;
2098     }
2099   stopme = ctrl->server_local->stopme || reader_disabled;
2100   xfree (ctrl->server_local);
2101   ctrl->server_local = NULL;
2102
2103   /* Release the Assuan context.  */
2104   assuan_release (ctx);
2105
2106   if (stopme)
2107     scd_exit (0);
2108
2109   /* If there are no more sessions return true.  */
2110   return !session_list;
2111 }
2112
2113
2114 /* Send a line with status information via assuan and escape all given
2115    buffers. The variable elements are pairs of (char *, size_t),
2116    terminated with a (NULL, 0). */
2117 void
2118 send_status_info (ctrl_t ctrl, const char *keyword, ...)
2119 {
2120   va_list arg_ptr;
2121   const unsigned char *value;
2122   size_t valuelen;
2123   char buf[950], *p;
2124   size_t n;
2125   assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2126
2127   va_start (arg_ptr, keyword);
2128
2129   p = buf;
2130   n = 0;
2131   while ( (value = va_arg (arg_ptr, const unsigned char *)) )
2132     {
2133       valuelen = va_arg (arg_ptr, size_t);
2134       if (!valuelen)
2135         continue; /* empty buffer */
2136       if (n)
2137         {
2138           *p++ = ' ';
2139           n++;
2140         }
2141       for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
2142         {
2143           if (*value < ' ' || *value == '+')
2144             {
2145               sprintf (p, "%%%02X", *value);
2146               p += 3;
2147             }
2148           else if (*value == ' ')
2149             *p++ = '+';
2150           else
2151             *p++ = *value;
2152         }
2153     }
2154   *p = 0;
2155   assuan_write_status (ctx, keyword, buf);
2156
2157   va_end (arg_ptr);
2158 }
2159
2160
2161 /* Send a ready formatted status line via assuan.  */
2162 void
2163 send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
2164 {
2165   assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2166
2167   if (strchr (args, '\n'))
2168     log_error ("error: LF detected in status line - not sending\n");
2169   else
2170     assuan_write_status (ctx, keyword, args);
2171 }
2172
2173
2174 /* Helper to send the clients a status change notification.  */
2175 static void
2176 send_client_notifications (void)
2177 {
2178   struct {
2179     pid_t pid;
2180 #ifdef HAVE_W32_SYSTEM
2181     HANDLE handle;
2182 #else
2183     int signo;
2184 #endif
2185   } killed[50];
2186   int killidx = 0;
2187   int kidx;
2188   struct server_local_s *sl;
2189
2190   for (sl=session_list; sl; sl = sl->next_session)
2191     {
2192       if (sl->event_signal && sl->assuan_ctx)
2193         {
2194           pid_t pid = assuan_get_pid (sl->assuan_ctx);
2195 #ifdef HAVE_W32_SYSTEM
2196           HANDLE handle = (void *)sl->event_signal;
2197
2198           for (kidx=0; kidx < killidx; kidx++)
2199             if (killed[kidx].pid == pid
2200                 && killed[kidx].handle == handle)
2201               break;
2202           if (kidx < killidx)
2203             log_info ("event %lx (%p) already triggered for client %d\n",
2204                       sl->event_signal, handle, (int)pid);
2205           else
2206             {
2207               log_info ("triggering event %lx (%p) for client %d\n",
2208                         sl->event_signal, handle, (int)pid);
2209               if (!SetEvent (handle))
2210                 log_error ("SetEvent(%lx) failed: %s\n",
2211                            sl->event_signal, w32_strerror (-1));
2212               if (killidx < DIM (killed))
2213                 {
2214                   killed[killidx].pid = pid;
2215                   killed[killidx].handle = handle;
2216                   killidx++;
2217                 }
2218             }
2219 #else /*!HAVE_W32_SYSTEM*/
2220           int signo = sl->event_signal;
2221
2222           if (pid != (pid_t)(-1) && pid && signo > 0)
2223             {
2224               for (kidx=0; kidx < killidx; kidx++)
2225                 if (killed[kidx].pid == pid
2226                     && killed[kidx].signo == signo)
2227                   break;
2228               if (kidx < killidx)
2229                 log_info ("signal %d already sent to client %d\n",
2230                           signo, (int)pid);
2231               else
2232                 {
2233                   log_info ("sending signal %d to client %d\n",
2234                             signo, (int)pid);
2235                   kill (pid, signo);
2236                   if (killidx < DIM (killed))
2237                     {
2238                       killed[killidx].pid = pid;
2239                       killed[killidx].signo = signo;
2240                       killidx++;
2241                     }
2242                 }
2243             }
2244 #endif /*!HAVE_W32_SYSTEM*/
2245         }
2246     }
2247 }
2248
2249
2250
2251 /* This is the core of scd_update_reader_status_file but the caller
2252    needs to take care of the locking.  */
2253 static void
2254 update_reader_status_file (int set_card_removed_flag)
2255 {
2256   int idx;
2257   unsigned int status, changed;
2258
2259   /* Make sure that a reader has been opened.  Like get_current_reader,
2260      this part of the code assumes that there is only one reader.  */
2261   if (!vreader_table[0].valid)
2262     (void)get_current_reader ();
2263
2264   /* Note, that we only try to get the status, because it does not
2265      make sense to wait here for a operation to complete.  If we are
2266      busy working with a card, delays in the status file update should
2267      be acceptable. */
2268   for (idx=0; idx < DIM(vreader_table); idx++)
2269     {
2270       struct vreader_s *vr = vreader_table + idx;
2271       struct server_local_s *sl;
2272       int sw_apdu;
2273
2274       if (!vr->valid || vr->slot == -1)
2275         continue; /* Not valid or reader not yet open. */
2276
2277       sw_apdu = apdu_get_status (vr->slot, 0, &status, &changed);
2278       if (sw_apdu == SW_HOST_NO_READER)
2279         {
2280           /* Most likely the _reader_ has been unplugged.  */
2281           application_notify_card_reset (vr->slot);
2282           apdu_close_reader (vr->slot);
2283           vr->slot = -1;
2284           status = 0;
2285           changed = vr->changed;
2286         }
2287       else if (sw_apdu)
2288         {
2289           /* Get status failed.  Ignore that.  */
2290           continue;
2291         }
2292
2293       if (!vr->any || vr->status != status || vr->changed != changed )
2294         {
2295           char *fname;
2296           char templ[50];
2297           FILE *fp;
2298
2299           log_info ("updating reader %d (%d) status: 0x%04X->0x%04X (%u->%u)\n",
2300                     idx, vr->slot, vr->status, status, vr->changed, changed);
2301           vr->status = status;
2302           vr->changed = changed;
2303
2304           /* FIXME: Should this be IDX instead of vr->slot?  This
2305              depends on how client sessions will associate the reader
2306              status with their session.  */
2307           snprintf (templ, sizeof templ, "reader_%d.status", vr->slot);
2308           fname = make_filename (opt.homedir, templ, NULL );
2309           fp = fopen (fname, "w");
2310           if (fp)
2311             {
2312               fprintf (fp, "%s\n",
2313                        (status & 1)? "USABLE":
2314                        (status & 4)? "ACTIVE":
2315                        (status & 2)? "PRESENT": "NOCARD");
2316               fclose (fp);
2317             }
2318           xfree (fname);
2319
2320           /* If a status script is executable, run it. */
2321           {
2322             const char *args[9], *envs[2];
2323             char numbuf1[30], numbuf2[30], numbuf3[30];
2324             char *homestr, *envstr;
2325             gpg_error_t err;
2326
2327             homestr = make_filename (opt.homedir, NULL);
2328             if (estream_asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
2329               log_error ("out of core while building environment\n");
2330             else
2331               {
2332                 envs[0] = envstr;
2333                 envs[1] = NULL;
2334
2335                 sprintf (numbuf1, "%d", vr->slot);
2336                 sprintf (numbuf2, "0x%04X", vr->status);
2337                 sprintf (numbuf3, "0x%04X", status);
2338                 args[0] = "--reader-port";
2339                 args[1] = numbuf1;
2340                 args[2] = "--old-code";
2341                 args[3] = numbuf2;
2342                 args[4] = "--new-code";
2343                 args[5] = numbuf3;
2344                 args[6] = "--status";
2345                 args[7] = ((status & 1)? "USABLE":
2346                            (status & 4)? "ACTIVE":
2347                            (status & 2)? "PRESENT": "NOCARD");
2348                 args[8] = NULL;
2349
2350                 fname = make_filename (opt.homedir, "scd-event", NULL);
2351                 err = gnupg_spawn_process_detached (fname, args, envs);
2352                 if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
2353                   log_error ("failed to run event handler `%s': %s\n",
2354                              fname, gpg_strerror (err));
2355                 xfree (fname);
2356                 xfree (envstr);
2357               }
2358             xfree (homestr);
2359           }
2360
2361           /* Set the card removed flag for all current sessions.  We
2362              will set this on any card change because a reset or
2363              SERIALNO request must be done in any case.  */
2364           if (vr->any && set_card_removed_flag)
2365             update_card_removed (idx, 1);
2366
2367           vr->any = 1;
2368
2369           /* Send a signal to all clients who applied for it.  */
2370           send_client_notifications ();
2371         }
2372
2373       /* Check whether a disconnect is pending.  */
2374       if (opt.card_timeout)
2375         {
2376           for (sl=session_list; sl; sl = sl->next_session)
2377             if (!sl->disconnect_allowed)
2378               break;
2379           if (session_list && !sl)
2380             {
2381               /* FIXME: Use a real timeout.  */
2382               /* At least one connection and all allow a disconnect.  */
2383               log_info ("disconnecting card in reader %d (%d)\n",
2384                         idx, vr->slot);
2385               apdu_disconnect (vr->slot);
2386             }
2387         }
2388
2389     }
2390 }
2391
2392 /* This function is called by the ticker thread to check for changes
2393    of the reader stati.  It updates the reader status files and if
2394    requested by the caller also send a signal to the caller.  */
2395 void
2396 scd_update_reader_status_file (void)
2397 {
2398   if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL))
2399     return; /* locked - give up. */
2400   update_reader_status_file (1);
2401   if (!pth_mutex_release (&status_file_update_lock))
2402     log_error ("failed to release status_file_update lock\n");
2403 }