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