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