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