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