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