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