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