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