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