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