Typo fixes
[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 "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 the
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     goto leave;
808
809   rc = ksba_cert_init_from_mem (kc, cert, ncert);
810   if (rc)
811     {
812       log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
813       goto leave;
814     }
815
816   p = ksba_cert_get_public_key (kc);
817   if (!p)
818     {
819       rc = gpg_error (GPG_ERR_NO_PUBKEY);
820       goto leave;
821     }
822
823   n = gcry_sexp_canon_len (p, 0, NULL, NULL);
824   rc = assuan_send_data (ctx, p, n);
825   xfree (p);
826
827
828  leave:
829   ksba_cert_release (kc);
830   xfree (cert);
831   TEST_CARD_REMOVAL (ctrl, rc);
832   return rc;
833 }
834
835
836 \f
837 static const char hlp_setdata[] =
838   "SETDATA [--append] <hexstring>\n"
839   "\n"
840   "The client should use this command to tell us the data he want to sign.\n"
841   "With the option --append, the data is appended to the data set by a\n"
842   "previous SETDATA command.";
843 static gpg_error_t
844 cmd_setdata (assuan_context_t ctx, char *line)
845 {
846   ctrl_t ctrl = assuan_get_pointer (ctx);
847   int append;
848   int n, i, off;
849   char *p;
850   unsigned char *buf;
851
852   append = (ctrl->in_data.value && has_option (line, "--append"));
853
854   line = skip_options (line);
855
856   if (locked_session && locked_session != ctrl->server_local)
857     return gpg_error (GPG_ERR_LOCKED);
858
859   /* Parse the hexstring. */
860   for (p=line,n=0; hexdigitp (p); p++, n++)
861     ;
862   if (*p)
863     return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
864   if (!n)
865     return set_error (GPG_ERR_ASS_PARAMETER, "no data given");
866   if ((n&1))
867     return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
868   n /= 2;
869   if (append)
870     {
871       if (ctrl->in_data.valuelen + n > MAXLEN_SETDATA)
872         return set_error (GPG_ERR_TOO_LARGE,
873                           "limit on total size of data reached");
874       buf = xtrymalloc (ctrl->in_data.valuelen + n);
875     }
876   else
877     buf = xtrymalloc (n);
878   if (!buf)
879     return out_of_core ();
880
881   if (append)
882     {
883       memcpy (buf, ctrl->in_data.value, ctrl->in_data.valuelen);
884       off = ctrl->in_data.valuelen;
885     }
886   else
887     off = 0;
888   for (p=line, i=0; i < n; p += 2, i++)
889     buf[off+i] = xtoi_2 (p);
890
891   xfree (ctrl->in_data.value);
892   ctrl->in_data.value = buf;
893   ctrl->in_data.valuelen = off+n;
894   return 0;
895 }
896
897
898
899 static gpg_error_t
900 pin_cb (void *opaque, const char *info, char **retstr)
901 {
902   assuan_context_t ctx = opaque;
903   char *command;
904   int rc;
905   unsigned char *value;
906   size_t valuelen;
907
908   if (!retstr)
909     {
910       /* We prompt for pinpad entry.  To make sure that the popup has
911          been show we use an inquire and not just a status message.
912          We ignore any value returned.  */
913       if (info)
914         {
915           log_debug ("prompting for pinpad entry '%s'\n", info);
916           rc = gpgrt_asprintf (&command, "POPUPPINPADPROMPT %s", info);
917           if (rc < 0)
918             return gpg_error (gpg_err_code_from_errno (errno));
919           rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
920           xfree (command);
921         }
922       else
923         {
924           log_debug ("dismiss pinpad entry prompt\n");
925           rc = assuan_inquire (ctx, "DISMISSPINPADPROMPT",
926                                &value, &valuelen, MAXLEN_PIN);
927         }
928       if (!rc)
929         xfree (value);
930       return rc;
931     }
932
933   *retstr = NULL;
934   log_debug ("asking for PIN '%s'\n", info);
935
936   rc = gpgrt_asprintf (&command, "NEEDPIN %s", info);
937   if (rc < 0)
938     return gpg_error (gpg_err_code_from_errno (errno));
939
940   /* Fixme: Write an inquire function which returns the result in
941      secure memory and check all further handling of the PIN. */
942   rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
943   xfree (command);
944   if (rc)
945     return rc;
946
947   if (!valuelen || value[valuelen-1])
948     {
949       /* We require that the returned value is an UTF-8 string */
950       xfree (value);
951       return gpg_error (GPG_ERR_INV_RESPONSE);
952     }
953   *retstr = (char*)value;
954   return 0;
955 }
956
957
958 static const char hlp_pksign[] =
959   "PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5]] <hexified_id>\n"
960   "\n"
961   "The --hash option is optional; the default is SHA1.";
962 static gpg_error_t
963 cmd_pksign (assuan_context_t ctx, char *line)
964 {
965   ctrl_t ctrl = assuan_get_pointer (ctx);
966   int rc;
967   unsigned char *outdata;
968   size_t outdatalen;
969   char *keyidstr;
970   int hash_algo;
971
972   if (has_option (line, "--hash=rmd160"))
973     hash_algo = GCRY_MD_RMD160;
974   else if (has_option (line, "--hash=sha1"))
975     hash_algo = GCRY_MD_SHA1;
976   else if (has_option (line, "--hash=sha224"))
977     hash_algo = GCRY_MD_SHA224;
978   else if (has_option (line, "--hash=sha256"))
979     hash_algo = GCRY_MD_SHA256;
980   else if (has_option (line, "--hash=sha384"))
981     hash_algo = GCRY_MD_SHA384;
982   else if (has_option (line, "--hash=sha512"))
983     hash_algo = GCRY_MD_SHA512;
984   else if (has_option (line, "--hash=md5"))
985     hash_algo = GCRY_MD_MD5;
986   else if (!strstr (line, "--"))
987     hash_algo = GCRY_MD_SHA1;
988   else
989     return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
990
991   line = skip_options (line);
992
993   if ( IS_LOCKED (ctrl) )
994     return gpg_error (GPG_ERR_LOCKED);
995
996   if ((rc = open_card (ctrl, NULL)))
997     return rc;
998
999   /* We have to use a copy of the key ID because the function may use
1000      the pin_cb which in turn uses the assuan line buffer and thus
1001      overwriting the original line with the keyid */
1002   keyidstr = xtrystrdup (line);
1003   if (!keyidstr)
1004     return out_of_core ();
1005
1006   rc = app_sign (ctrl->app_ctx,
1007                  keyidstr, hash_algo,
1008                  pin_cb, ctx,
1009                  ctrl->in_data.value, ctrl->in_data.valuelen,
1010                  &outdata, &outdatalen);
1011
1012   xfree (keyidstr);
1013   if (rc)
1014     {
1015       log_error ("app_sign failed: %s\n", gpg_strerror (rc));
1016     }
1017   else
1018     {
1019       rc = assuan_send_data (ctx, outdata, outdatalen);
1020       xfree (outdata);
1021       if (rc)
1022         return rc; /* that is already an assuan error code */
1023     }
1024
1025   TEST_CARD_REMOVAL (ctrl, rc);
1026   return rc;
1027 }
1028
1029
1030 static const char hlp_pkauth[] =
1031   "PKAUTH <hexified_id>";
1032 static gpg_error_t
1033 cmd_pkauth (assuan_context_t ctx, char *line)
1034 {
1035   ctrl_t ctrl = assuan_get_pointer (ctx);
1036   int rc;
1037   unsigned char *outdata;
1038   size_t outdatalen;
1039   char *keyidstr;
1040
1041   if ( IS_LOCKED (ctrl) )
1042     return gpg_error (GPG_ERR_LOCKED);
1043
1044   if ((rc = open_card (ctrl, NULL)))
1045     return rc;
1046
1047   if (!ctrl->app_ctx)
1048     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1049
1050  /* We have to use a copy of the key ID because the function may use
1051      the pin_cb which in turn uses the assuan line buffer and thus
1052      overwriting the original line with the keyid */
1053   keyidstr = xtrystrdup (line);
1054   if (!keyidstr)
1055     return out_of_core ();
1056
1057   rc = app_auth (ctrl->app_ctx,
1058                  keyidstr,
1059                  pin_cb, ctx,
1060                  ctrl->in_data.value, ctrl->in_data.valuelen,
1061                  &outdata, &outdatalen);
1062   xfree (keyidstr);
1063   if (rc)
1064     {
1065       log_error ("app_auth failed: %s\n", gpg_strerror (rc));
1066     }
1067   else
1068     {
1069       rc = assuan_send_data (ctx, outdata, outdatalen);
1070       xfree (outdata);
1071       if (rc)
1072         return rc; /* that is already an assuan error code */
1073     }
1074
1075   TEST_CARD_REMOVAL (ctrl, rc);
1076   return rc;
1077 }
1078
1079
1080 static const char hlp_pkdecrypt[] =
1081   "PKDECRYPT <hexified_id>";
1082 static gpg_error_t
1083 cmd_pkdecrypt (assuan_context_t ctx, char *line)
1084 {
1085   ctrl_t ctrl = assuan_get_pointer (ctx);
1086   int rc;
1087   unsigned char *outdata;
1088   size_t outdatalen;
1089   char *keyidstr;
1090   unsigned int infoflags;
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, &infoflags);
1106
1107   xfree (keyidstr);
1108   if (rc)
1109     {
1110       log_error ("app_decipher failed: %s\n", gpg_strerror (rc));
1111     }
1112   else
1113     {
1114       /* If the card driver told us that there is no padding, send a
1115          status line.  If there is a padding it is assumed that the
1116          caller knows what padding is used.  It would have been better
1117          to always send that information but for backward
1118          compatibility we can't do that.  */
1119       if ((infoflags & APP_DECIPHER_INFO_NOPAD))
1120         send_status_direct (ctrl, "PADDING", "0");
1121       rc = assuan_send_data (ctx, outdata, outdatalen);
1122       xfree (outdata);
1123       if (rc)
1124         return rc; /* that is already an assuan error code */
1125     }
1126
1127   TEST_CARD_REMOVAL (ctrl, rc);
1128   return rc;
1129 }
1130
1131
1132 static const char hlp_getattr[] =
1133   "GETATTR <name>\n"
1134   "\n"
1135   "This command is used to retrieve data from a smartcard.  The\n"
1136   "allowed names depend on the currently selected smartcard\n"
1137   "application.  NAME must be percent and '+' escaped.  The value is\n"
1138   "returned through status message, see the LEARN command for details.\n"
1139   "\n"
1140   "However, the current implementation assumes that Name is not escaped;\n"
1141   "this works as long as noone uses arbitrary escaping. \n"
1142   "\n"
1143   "Note, that this function may even be used on a locked card.";
1144 static gpg_error_t
1145 cmd_getattr (assuan_context_t ctx, char *line)
1146 {
1147   ctrl_t ctrl = assuan_get_pointer (ctx);
1148   int rc;
1149   const char *keyword;
1150
1151   if ((rc = open_card (ctrl, NULL)))
1152     return rc;
1153
1154   keyword = line;
1155   for (; *line && !spacep (line); line++)
1156     ;
1157   if (*line)
1158       *line++ = 0;
1159
1160   /* (We ignore any garbage for now.) */
1161
1162   /* FIXME: Applications should not return sensitive data if the card
1163      is locked.  */
1164   rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
1165
1166   TEST_CARD_REMOVAL (ctrl, rc);
1167   return rc;
1168 }
1169
1170
1171 static const char hlp_setattr[] =
1172   "SETATTR <name> <value> \n"
1173   "\n"
1174   "This command is used to store data on a a smartcard.  The allowed\n"
1175   "names and values are depend on the currently selected smartcard\n"
1176   "application.  NAME and VALUE must be percent and '+' escaped.\n"
1177   "\n"
1178   "However, the current implementation assumes that NAME is not\n"
1179   "escaped; this works as long as noone uses arbitrary escaping.\n"
1180   "\n"
1181   "A PIN will be requested for most NAMEs.  See the corresponding\n"
1182   "setattr function of the actually used application (app-*.c) for\n"
1183   "details.";
1184 static gpg_error_t
1185 cmd_setattr (assuan_context_t ctx, char *orig_line)
1186 {
1187   ctrl_t ctrl = assuan_get_pointer (ctx);
1188   int rc;
1189   char *keyword;
1190   int keywordlen;
1191   size_t nbytes;
1192   char *line, *linebuf;
1193
1194   if ( IS_LOCKED (ctrl) )
1195     return gpg_error (GPG_ERR_LOCKED);
1196
1197   if ((rc = open_card (ctrl, NULL)))
1198     return rc;
1199
1200   /* We need to use a copy of LINE, because PIN_CB uses the same
1201      context and thus reuses the Assuan provided LINE. */
1202   line = linebuf = xtrystrdup (orig_line);
1203   if (!line)
1204     return out_of_core ();
1205
1206   keyword = line;
1207   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
1208     ;
1209   if (*line)
1210       *line++ = 0;
1211   while (spacep (line))
1212     line++;
1213   nbytes = percent_plus_unescape_inplace (line, 0);
1214
1215   rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx,
1216                     (const unsigned char*)line, nbytes);
1217   xfree (linebuf);
1218
1219   TEST_CARD_REMOVAL (ctrl, rc);
1220   return rc;
1221 }
1222
1223
1224 static const char hlp_writecert[] =
1225   "WRITECERT <hexified_certid>\n"
1226   "\n"
1227   "This command is used to store a certifciate on a smartcard.  The\n"
1228   "allowed certids depend on the currently selected smartcard\n"
1229   "application. The actual certifciate is requested using the inquiry\n"
1230   "\"CERTDATA\" and needs to be provided in its raw (e.g. DER) form.\n"
1231   "\n"
1232   "In almost all cases a a PIN will be requested.  See the related\n"
1233   "writecert function of the actually used application (app-*.c) for\n"
1234   "details.";
1235 static gpg_error_t
1236 cmd_writecert (assuan_context_t ctx, char *line)
1237 {
1238   ctrl_t ctrl = assuan_get_pointer (ctx);
1239   int rc;
1240   char *certid;
1241   unsigned char *certdata;
1242   size_t certdatalen;
1243
1244   if ( IS_LOCKED (ctrl) )
1245     return gpg_error (GPG_ERR_LOCKED);
1246
1247   line = skip_options (line);
1248
1249   if (!*line)
1250     return set_error (GPG_ERR_ASS_PARAMETER, "no certid given");
1251   certid = line;
1252   while (*line && !spacep (line))
1253     line++;
1254   *line = 0;
1255
1256   if ((rc = open_card (ctrl, NULL)))
1257     return rc;
1258
1259   if (!ctrl->app_ctx)
1260     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1261
1262   certid = xtrystrdup (certid);
1263   if (!certid)
1264     return out_of_core ();
1265
1266   /* Now get the actual keydata. */
1267   rc = assuan_inquire (ctx, "CERTDATA",
1268                        &certdata, &certdatalen, MAXLEN_CERTDATA);
1269   if (rc)
1270     {
1271       xfree (certid);
1272       return rc;
1273     }
1274
1275   /* Write the certificate to the card. */
1276   rc = app_writecert (ctrl->app_ctx, ctrl, certid,
1277                       pin_cb, ctx, certdata, certdatalen);
1278   xfree (certid);
1279   xfree (certdata);
1280
1281   TEST_CARD_REMOVAL (ctrl, rc);
1282   return rc;
1283 }
1284
1285
1286 static const char hlp_writekey[] =
1287   "WRITEKEY [--force] <keyid> \n"
1288   "\n"
1289   "This command is used to store a secret key on a a smartcard.  The\n"
1290   "allowed keyids depend on the currently selected smartcard\n"
1291   "application. The actual keydata is requested using the inquiry\n"
1292   "\"KEYDATA\" and need to be provided without any protection.  With\n"
1293   "--force set an existing key under this KEYID will get overwritten.\n"
1294   "The keydata is expected to be the usual canonical encoded\n"
1295   "S-expression.\n"
1296   "\n"
1297   "A PIN will be requested for most NAMEs.  See the corresponding\n"
1298   "writekey function of the actually used application (app-*.c) for\n"
1299   "details.";
1300 static gpg_error_t
1301 cmd_writekey (assuan_context_t ctx, char *line)
1302 {
1303   ctrl_t ctrl = assuan_get_pointer (ctx);
1304   int rc;
1305   char *keyid;
1306   int force = has_option (line, "--force");
1307   unsigned char *keydata;
1308   size_t keydatalen;
1309
1310   if ( IS_LOCKED (ctrl) )
1311     return gpg_error (GPG_ERR_LOCKED);
1312
1313   line = skip_options (line);
1314
1315   if (!*line)
1316     return set_error (GPG_ERR_ASS_PARAMETER, "no keyid given");
1317   keyid = line;
1318   while (*line && !spacep (line))
1319     line++;
1320   *line = 0;
1321
1322   if ((rc = open_card (ctrl, NULL)))
1323     return rc;
1324
1325   if (!ctrl->app_ctx)
1326     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1327
1328   keyid = xtrystrdup (keyid);
1329   if (!keyid)
1330     return out_of_core ();
1331
1332   /* Now get the actual keydata. */
1333   assuan_begin_confidential (ctx);
1334   rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA);
1335   assuan_end_confidential (ctx);
1336   if (rc)
1337     {
1338       xfree (keyid);
1339       return rc;
1340     }
1341
1342   /* Write the key to the card. */
1343   rc = app_writekey (ctrl->app_ctx, ctrl, keyid, force? 1:0,
1344                      pin_cb, ctx, keydata, keydatalen);
1345   xfree (keyid);
1346   xfree (keydata);
1347
1348   TEST_CARD_REMOVAL (ctrl, rc);
1349   return rc;
1350 }
1351
1352
1353 static const char hlp_genkey[] =
1354   "GENKEY [--force] [--timestamp=<isodate>] <no>\n"
1355   "\n"
1356   "Generate a key on-card identified by NO, which is application\n"
1357   "specific.  Return values are application specific.  For OpenPGP\n"
1358   "cards 3 status lines are returned:\n"
1359   "\n"
1360   "  S KEY-FPR  <hexstring>\n"
1361   "  S KEY-CREATED-AT <seconds_since_epoch>\n"
1362   "  S KEY-DATA [-|p|n] <hexdata>\n"
1363   "\n"
1364   "  'p' and 'n' are the names of the RSA parameters; '-' is used to\n"
1365   "  indicate that HEXDATA is the first chunk of a parameter given\n"
1366   "  by the next KEY-DATA.\n"
1367   "\n"
1368   "--force is required to overwrite an already existing key.  The\n"
1369   "KEY-CREATED-AT is required for further processing because it is\n"
1370   "part of the hashed key material for the fingerprint.\n"
1371   "\n"
1372   "If --timestamp is given an OpenPGP key will be created using this\n"
1373   "value.  The value needs to be in ISO Format; e.g.\n"
1374   "\"--timestamp=20030316T120000\" and after 1970-01-01 00:00:00.\n"
1375   "\n"
1376   "The public part of the key can also later be retrieved using the\n"
1377   "READKEY command.";
1378 static gpg_error_t
1379 cmd_genkey (assuan_context_t ctx, char *line)
1380 {
1381   ctrl_t ctrl = assuan_get_pointer (ctx);
1382   int rc;
1383   char *keyno;
1384   int force;
1385   const char *s;
1386   time_t timestamp;
1387
1388   if ( IS_LOCKED (ctrl) )
1389     return gpg_error (GPG_ERR_LOCKED);
1390
1391   force = has_option (line, "--force");
1392
1393   if ((s=has_option_name (line, "--timestamp")))
1394     {
1395       if (*s != '=')
1396         return set_error (GPG_ERR_ASS_PARAMETER, "missing value for option");
1397       timestamp = isotime2epoch (s+1);
1398       if (timestamp < 1)
1399         return set_error (GPG_ERR_ASS_PARAMETER, "invalid time value");
1400     }
1401   else
1402     timestamp = 0;
1403
1404
1405   line = skip_options (line);
1406   if (!*line)
1407     return set_error (GPG_ERR_ASS_PARAMETER, "no key number given");
1408   keyno = line;
1409   while (*line && !spacep (line))
1410     line++;
1411   *line = 0;
1412
1413   if ((rc = open_card (ctrl, NULL)))
1414     return rc;
1415
1416   if (!ctrl->app_ctx)
1417     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1418
1419   keyno = xtrystrdup (keyno);
1420   if (!keyno)
1421     return out_of_core ();
1422   rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0,
1423                    timestamp, pin_cb, ctx);
1424   xfree (keyno);
1425
1426   TEST_CARD_REMOVAL (ctrl, rc);
1427   return rc;
1428 }
1429
1430
1431 static const char hlp_random[] =
1432   "RANDOM <nbytes>\n"
1433   "\n"
1434   "Get NBYTES of random from the card and send them back as data.\n"
1435   "This usually involves EEPROM write on the card and thus excessive\n"
1436   "use of this command may destroy the card.\n"
1437   "\n"
1438   "Note, that this function may be even be used on a locked card.";
1439 static gpg_error_t
1440 cmd_random (assuan_context_t ctx, char *line)
1441 {
1442   ctrl_t ctrl = assuan_get_pointer (ctx);
1443   int rc;
1444   size_t nbytes;
1445   unsigned char *buffer;
1446
1447   if (!*line)
1448     return set_error (GPG_ERR_ASS_PARAMETER,
1449                       "number of requested bytes missing");
1450   nbytes = strtoul (line, NULL, 0);
1451
1452   if ((rc = open_card (ctrl, NULL)))
1453     return rc;
1454
1455   if (!ctrl->app_ctx)
1456     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1457
1458   buffer = xtrymalloc (nbytes);
1459   if (!buffer)
1460     return out_of_core ();
1461
1462   rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
1463   if (!rc)
1464     {
1465       rc = assuan_send_data (ctx, buffer, nbytes);
1466       xfree (buffer);
1467       return rc; /* that is already an assuan error code */
1468     }
1469   xfree (buffer);
1470
1471   TEST_CARD_REMOVAL (ctrl, rc);
1472   return rc;
1473 }
1474
1475
1476 \f
1477 static const char hlp_passwd[] =
1478   "PASSWD [--reset] [--nullpin] <chvno>\n"
1479   "\n"
1480   "Change the PIN or, if --reset is given, reset the retry counter of\n"
1481   "the card holder verfication vector CHVNO.  The option --nullpin is\n"
1482   "used for TCOS cards to set the initial PIN.  The format of CHVNO\n"
1483   "depends on the card application.";
1484 static gpg_error_t
1485 cmd_passwd (assuan_context_t ctx, char *line)
1486 {
1487   ctrl_t ctrl = assuan_get_pointer (ctx);
1488   int rc;
1489   char *chvnostr;
1490   unsigned int flags = 0;
1491
1492   if (has_option (line, "--reset"))
1493     flags |= APP_CHANGE_FLAG_RESET;
1494   if (has_option (line, "--nullpin"))
1495     flags |= APP_CHANGE_FLAG_NULLPIN;
1496
1497   if ( IS_LOCKED (ctrl) )
1498     return gpg_error (GPG_ERR_LOCKED);
1499
1500   line = skip_options (line);
1501
1502   if (!*line)
1503     return set_error (GPG_ERR_ASS_PARAMETER, "no CHV number given");
1504   chvnostr = line;
1505   while (*line && !spacep (line))
1506     line++;
1507   *line = 0;
1508
1509   if ((rc = open_card (ctrl, NULL)))
1510     return rc;
1511
1512   if (!ctrl->app_ctx)
1513     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1514
1515   chvnostr = xtrystrdup (chvnostr);
1516   if (!chvnostr)
1517     return out_of_core ();
1518   rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, flags, pin_cb, ctx);
1519   if (rc)
1520     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1521   xfree (chvnostr);
1522
1523   TEST_CARD_REMOVAL (ctrl, rc);
1524   return rc;
1525 }
1526
1527
1528 static const char hlp_checkpin[] =
1529   "CHECKPIN <idstr>\n"
1530   "\n"
1531   "Perform a VERIFY operation without doing anything else.  This may\n"
1532   "be used to initialize a the PIN cache earlier to long lasting\n"
1533   "operations.  Its use is highly application dependent.\n"
1534   "\n"
1535   "For OpenPGP:\n"
1536   "\n"
1537   "   Perform a simple verify operation for CHV1 and CHV2, so that\n"
1538   "   further operations won't ask for CHV2 and it is possible to do a\n"
1539   "   cheap check on the PIN: If there is something wrong with the PIN\n"
1540   "   entry system, only the regular CHV will get blocked and not the\n"
1541   "   dangerous CHV3.  IDSTR is the usual card's serial number in hex\n"
1542   "   notation; an optional fingerprint part will get ignored.  There\n"
1543   "   is however a special mode if the IDSTR is sffixed with the\n"
1544   "   literal string \"[CHV3]\": In this case the Admin PIN is checked\n"
1545   "   if and only if the retry counter is still at 3.\n"
1546   "\n"
1547   "For Netkey:\n"
1548   "\n"
1549   "   Any of the valid PIN Ids may be used.  These are the strings:\n"
1550   "\n"
1551   "     PW1.CH       - Global password 1\n"
1552   "     PW2.CH       - Global password 2\n"
1553   "     PW1.CH.SIG   - SigG password 1\n"
1554   "     PW2.CH.SIG   - SigG password 2\n"
1555   "\n"
1556   "   For a definitive list, see the implementation in app-nks.c.\n"
1557   "   Note that we call a PW2.* PIN a \"PUK\" despite that since TCOS\n"
1558   "   3.0 they are technically alternative PINs used to mutally\n"
1559   "   unblock each other.";
1560 static gpg_error_t
1561 cmd_checkpin (assuan_context_t ctx, char *line)
1562 {
1563   ctrl_t ctrl = assuan_get_pointer (ctx);
1564   int rc;
1565   char *idstr;
1566
1567   if ( IS_LOCKED (ctrl) )
1568     return gpg_error (GPG_ERR_LOCKED);
1569
1570   if ((rc = open_card (ctrl, NULL)))
1571     return rc;
1572
1573   if (!ctrl->app_ctx)
1574     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1575
1576   /* We have to use a copy of the key ID because the function may use
1577      the pin_cb which in turn uses the assuan line buffer and thus
1578      overwriting the original line with the keyid. */
1579   idstr = xtrystrdup (line);
1580   if (!idstr)
1581     return out_of_core ();
1582
1583   rc = app_check_pin (ctrl->app_ctx, idstr, pin_cb, ctx);
1584   xfree (idstr);
1585   if (rc)
1586     log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
1587
1588   TEST_CARD_REMOVAL (ctrl, rc);
1589   return rc;
1590 }
1591
1592
1593 static const char hlp_lock[] =
1594   "LOCK [--wait]\n"
1595   "\n"
1596   "Grant exclusive card access to this session.  Note that there is\n"
1597   "no lock counter used and a second lock from the same session will\n"
1598   "be ignored.  A single unlock (or RESET) unlocks the session.\n"
1599   "Return GPG_ERR_LOCKED if another session has locked the reader.\n"
1600   "\n"
1601   "If the option --wait is given the command will wait until a\n"
1602   "lock has been released.";
1603 static gpg_error_t
1604 cmd_lock (assuan_context_t ctx, char *line)
1605 {
1606   ctrl_t ctrl = assuan_get_pointer (ctx);
1607   int rc = 0;
1608
1609  retry:
1610   if (locked_session)
1611     {
1612       if (locked_session != ctrl->server_local)
1613         rc = gpg_error (GPG_ERR_LOCKED);
1614     }
1615   else
1616     locked_session = ctrl->server_local;
1617
1618 #ifdef USE_NPTH
1619   if (rc && has_option (line, "--wait"))
1620     {
1621       rc = 0;
1622       npth_sleep (1); /* Better implement an event mechanism. However,
1623                          for card operations this should be
1624                          sufficient. */
1625       /* FIXME: Need to check that the connection is still alive.
1626          This can be done by issuing status messages. */
1627       goto retry;
1628     }
1629 #endif /*USE_NPTH*/
1630
1631   if (rc)
1632     log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
1633   return rc;
1634 }
1635
1636
1637 static const char hlp_unlock[] =
1638   "UNLOCK\n"
1639   "\n"
1640   "Release exclusive card access.";
1641 static gpg_error_t
1642 cmd_unlock (assuan_context_t ctx, char *line)
1643 {
1644   ctrl_t ctrl = assuan_get_pointer (ctx);
1645   int rc = 0;
1646
1647   (void)line;
1648
1649   if (locked_session)
1650     {
1651       if (locked_session != ctrl->server_local)
1652         rc = gpg_error (GPG_ERR_LOCKED);
1653       else
1654         locked_session = NULL;
1655     }
1656   else
1657     rc = gpg_error (GPG_ERR_NOT_LOCKED);
1658
1659   if (rc)
1660     log_error ("cmd_unlock failed: %s\n", gpg_strerror (rc));
1661   return rc;
1662 }
1663
1664
1665 static const char hlp_getinfo[] =
1666   "GETINFO <what>\n"
1667   "\n"
1668   "Multi purpose command to return certain information.  \n"
1669   "Supported values of WHAT are:\n"
1670   "\n"
1671   "version     - Return the version of the program.\n"
1672   "pid         - Return the process id of the server.\n"
1673   "\n"
1674   "socket_name - Return the name of the socket.\n"
1675   "\n"
1676   "status - Return the status of the current reader (in the future, may\n"
1677   "also return the status of all readers).  The status is a list of\n"
1678   "one-character flags.  The following flags are currently defined:\n"
1679   "  'u'  Usable card present.  This is the normal state during operation.\n"
1680   "  'r'  Card removed.  A reset is necessary.\n"
1681   "These flags are exclusive.\n"
1682   "\n"
1683   "reader_list - Return a list of detected card readers.  Does\n"
1684   "              currently only work with the internal CCID driver.\n"
1685   "\n"
1686   "deny_admin  - Returns OK if admin commands are not allowed or\n"
1687   "              GPG_ERR_GENERAL if admin commands are allowed.\n"
1688   "\n"
1689   "app_list    - Return a list of supported applications.  One\n"
1690   "              application per line, fields delimited by colons,\n"
1691   "              first field is the name.";
1692 static gpg_error_t
1693 cmd_getinfo (assuan_context_t ctx, char *line)
1694 {
1695   int rc = 0;
1696
1697   if (!strcmp (line, "version"))
1698     {
1699       const char *s = VERSION;
1700       rc = assuan_send_data (ctx, s, strlen (s));
1701     }
1702   else if (!strcmp (line, "pid"))
1703     {
1704       char numbuf[50];
1705
1706       snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1707       rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1708     }
1709   else if (!strcmp (line, "socket_name"))
1710     {
1711       const char *s = scd_get_socket_name ();
1712
1713       if (s)
1714         rc = assuan_send_data (ctx, s, strlen (s));
1715       else
1716         rc = gpg_error (GPG_ERR_NO_DATA);
1717     }
1718   else if (!strcmp (line, "status"))
1719     {
1720       ctrl_t ctrl = assuan_get_pointer (ctx);
1721       int vrdr = ctrl->server_local->vreader_idx;
1722       char flag = 'r';
1723
1724       if (!ctrl->server_local->card_removed && vrdr != -1)
1725         {
1726           struct vreader_s *vr;
1727
1728           if (!(vrdr >= 0 && vrdr < DIM(vreader_table)))
1729             BUG ();
1730
1731           vr = &vreader_table[vrdr];
1732           if (vr->valid && vr->any && (vr->status & 1))
1733             flag = 'u';
1734         }
1735       rc = assuan_send_data (ctx, &flag, 1);
1736     }
1737   else if (!strcmp (line, "reader_list"))
1738     {
1739 #ifdef HAVE_LIBUSB
1740       char *s = ccid_get_reader_list ();
1741 #else
1742       char *s = NULL;
1743 #endif
1744
1745       if (s)
1746         rc = assuan_send_data (ctx, s, strlen (s));
1747       else
1748         rc = gpg_error (GPG_ERR_NO_DATA);
1749       xfree (s);
1750     }
1751   else if (!strcmp (line, "deny_admin"))
1752     rc = opt.allow_admin? gpg_error (GPG_ERR_GENERAL) : 0;
1753   else if (!strcmp (line, "app_list"))
1754     {
1755       char *s = get_supported_applications ();
1756       if (s)
1757         rc = assuan_send_data (ctx, s, strlen (s));
1758       else
1759         rc = 0;
1760       xfree (s);
1761     }
1762   else
1763     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1764   return rc;
1765 }
1766
1767
1768 static const char hlp_restart[] =
1769   "RESTART\n"
1770   "\n"
1771   "Restart the current connection; this is a kind of warm reset.  It\n"
1772   "deletes the context used by this connection but does not send a\n"
1773   "RESET to the card.  Thus the card itself won't get reset. \n"
1774   "\n"
1775   "This is used by gpg-agent to reuse a primary pipe connection and\n"
1776   "may be used by clients to backup from a conflict in the serial\n"
1777   "command; i.e. to select another application.";
1778 static gpg_error_t
1779 cmd_restart (assuan_context_t ctx, char *line)
1780 {
1781   ctrl_t ctrl = assuan_get_pointer (ctx);
1782
1783   (void)line;
1784
1785   if (ctrl->app_ctx)
1786     {
1787       release_application (ctrl->app_ctx);
1788       ctrl->app_ctx = NULL;
1789     }
1790   if (locked_session && ctrl->server_local == locked_session)
1791     {
1792       locked_session = NULL;
1793       log_info ("implicitly unlocking due to RESTART\n");
1794     }
1795   return 0;
1796 }
1797
1798
1799 static const char hlp_disconnect[] =
1800   "DISCONNECT\n"
1801   "\n"
1802   "Disconnect the card if it is not any longer used by other\n"
1803   "connections and the backend supports a disconnect operation.";
1804 static gpg_error_t
1805 cmd_disconnect (assuan_context_t ctx, char *line)
1806 {
1807   ctrl_t ctrl = assuan_get_pointer (ctx);
1808
1809   (void)line;
1810
1811   ctrl->server_local->disconnect_allowed = 1;
1812   return 0;
1813 }
1814
1815
1816
1817 static const char hlp_apdu[] =
1818   "APDU [--[dump-]atr] [--more] [--exlen[=N]] [hexstring]\n"
1819   "\n"
1820   "Send an APDU to the current reader.  This command bypasses the high\n"
1821   "level functions and sends the data directly to the card.  HEXSTRING\n"
1822   "is expected to be a proper APDU.  If HEXSTRING is not given no\n"
1823   "commands are set to the card but the command will implictly check\n"
1824   "whether the card is ready for use. \n"
1825   "\n"
1826   "Using the option \"--atr\" returns the ATR of the card as a status\n"
1827   "message before any data like this:\n"
1828   "  S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1\n"
1829   "\n"
1830   "Using the option --more handles the card status word MORE_DATA\n"
1831   "(61xx) and concatenates all reponses to one block.\n"
1832   "\n"
1833   "Using the option \"--exlen\" the returned APDU may use extended\n"
1834   "length up to N bytes.  If N is not given a default value is used\n"
1835   "(currently 4096).";
1836 static gpg_error_t
1837 cmd_apdu (assuan_context_t ctx, char *line)
1838 {
1839   ctrl_t ctrl = assuan_get_pointer (ctx);
1840   int rc;
1841   unsigned char *apdu;
1842   size_t apdulen;
1843   int with_atr;
1844   int handle_more;
1845   const char *s;
1846   size_t exlen;
1847   int slot;
1848
1849   if (has_option (line, "--dump-atr"))
1850     with_atr = 2;
1851   else
1852     with_atr = has_option (line, "--atr");
1853   handle_more = has_option (line, "--more");
1854
1855   if ((s=has_option_name (line, "--exlen")))
1856     {
1857       if (*s == '=')
1858         exlen = strtoul (s+1, NULL, 0);
1859       else
1860         exlen = 4096;
1861     }
1862   else
1863     exlen = 0;
1864
1865   line = skip_options (line);
1866
1867   if ( IS_LOCKED (ctrl) )
1868     return gpg_error (GPG_ERR_LOCKED);
1869
1870   if ((rc = open_card (ctrl, NULL)))
1871     return rc;
1872
1873   slot = vreader_slot (ctrl->server_local->vreader_idx);
1874
1875   if (with_atr)
1876     {
1877       unsigned char *atr;
1878       size_t atrlen;
1879       char hexbuf[400];
1880
1881       atr = apdu_get_atr (slot, &atrlen);
1882       if (!atr || atrlen > sizeof hexbuf - 2 )
1883         {
1884           rc = gpg_error (GPG_ERR_INV_CARD);
1885           goto leave;
1886         }
1887       if (with_atr == 2)
1888         {
1889           char *string, *p, *pend;
1890
1891           string = atr_dump (atr, atrlen);
1892           if (string)
1893             {
1894               for (rc=0, p=string; !rc && (pend = strchr (p, '\n')); p = pend+1)
1895                 {
1896                   rc = assuan_send_data (ctx, p, pend - p + 1);
1897                   if (!rc)
1898                     rc = assuan_send_data (ctx, NULL, 0);
1899                 }
1900               if (!rc && *p)
1901                 rc = assuan_send_data (ctx, p, strlen (p));
1902               es_free (string);
1903               if (rc)
1904                 goto leave;
1905             }
1906         }
1907       else
1908         {
1909           bin2hex (atr, atrlen, hexbuf);
1910           send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
1911         }
1912       xfree (atr);
1913     }
1914
1915   apdu = hex_to_buffer (line, &apdulen);
1916   if (!apdu)
1917     {
1918       rc = gpg_error_from_syserror ();
1919       goto leave;
1920     }
1921   if (apdulen)
1922     {
1923       unsigned char *result = NULL;
1924       size_t resultlen;
1925
1926       rc = apdu_send_direct (slot, exlen,
1927                              apdu, apdulen, handle_more,
1928                              &result, &resultlen);
1929       if (rc)
1930         log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
1931       else
1932         {
1933           rc = assuan_send_data (ctx, result, resultlen);
1934           xfree (result);
1935         }
1936     }
1937   xfree (apdu);
1938
1939  leave:
1940   TEST_CARD_REMOVAL (ctrl, rc);
1941   return rc;
1942 }
1943
1944
1945 static const char hlp_killscd[] =
1946   "KILLSCD\n"
1947   "\n"
1948   "Commit suicide.";
1949 static gpg_error_t
1950 cmd_killscd (assuan_context_t ctx, char *line)
1951 {
1952   ctrl_t ctrl = assuan_get_pointer (ctx);
1953
1954   (void)line;
1955
1956   ctrl->server_local->stopme = 1;
1957   assuan_set_flag (ctx, ASSUAN_FORCE_CLOSE, 1);
1958   return 0;
1959 }
1960
1961
1962 \f
1963 /* Tell the assuan library about our commands */
1964 static int
1965 register_commands (assuan_context_t ctx)
1966 {
1967   static struct {
1968     const char *name;
1969     assuan_handler_t handler;
1970     const char * const help;
1971   } table[] = {
1972     { "SERIALNO",     cmd_serialno, hlp_serialno },
1973     { "LEARN",        cmd_learn,    hlp_learn },
1974     { "READCERT",     cmd_readcert, hlp_readcert },
1975     { "READKEY",      cmd_readkey,  hlp_readkey },
1976     { "SETDATA",      cmd_setdata,  hlp_setdata },
1977     { "PKSIGN",       cmd_pksign,   hlp_pksign },
1978     { "PKAUTH",       cmd_pkauth,   hlp_pkauth },
1979     { "PKDECRYPT",    cmd_pkdecrypt,hlp_pkdecrypt },
1980     { "INPUT",        NULL },
1981     { "OUTPUT",       NULL },
1982     { "GETATTR",      cmd_getattr,  hlp_getattr },
1983     { "SETATTR",      cmd_setattr,  hlp_setattr },
1984     { "WRITECERT",    cmd_writecert,hlp_writecert },
1985     { "WRITEKEY",     cmd_writekey, hlp_writekey },
1986     { "GENKEY",       cmd_genkey,   hlp_genkey },
1987     { "RANDOM",       cmd_random,   hlp_random },
1988     { "PASSWD",       cmd_passwd,   hlp_passwd },
1989     { "CHECKPIN",     cmd_checkpin, hlp_checkpin },
1990     { "LOCK",         cmd_lock,     hlp_lock },
1991     { "UNLOCK",       cmd_unlock,   hlp_unlock },
1992     { "GETINFO",      cmd_getinfo,  hlp_getinfo },
1993     { "RESTART",      cmd_restart,  hlp_restart },
1994     { "DISCONNECT",   cmd_disconnect,hlp_disconnect },
1995     { "APDU",         cmd_apdu,     hlp_apdu },
1996     { "KILLSCD",      cmd_killscd,  hlp_killscd },
1997     { NULL }
1998   };
1999   int i, rc;
2000
2001   for (i=0; table[i].name; i++)
2002     {
2003       rc = assuan_register_command (ctx, table[i].name, table[i].handler,
2004                                     table[i].help);
2005       if (rc)
2006         return rc;
2007     }
2008   assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
2009
2010   assuan_register_reset_notify (ctx, reset_notify);
2011   assuan_register_option_handler (ctx, option_handler);
2012   return 0;
2013 }
2014
2015
2016 /* Startup the server.  If FD is given as -1 this is simple pipe
2017    server, otherwise it is a regular server.  Returns true if there
2018    are no more active asessions.  */
2019 int
2020 scd_command_handler (ctrl_t ctrl, int fd)
2021 {
2022   int rc;
2023   assuan_context_t ctx = NULL;
2024   int stopme;
2025
2026   rc = assuan_new (&ctx);
2027   if (rc)
2028     {
2029       log_error ("failed to allocate assuan context: %s\n",
2030                  gpg_strerror (rc));
2031       scd_exit (2);
2032     }
2033
2034   if (fd == -1)
2035     {
2036       assuan_fd_t filedes[2];
2037
2038       filedes[0] = assuan_fdopen (0);
2039       filedes[1] = assuan_fdopen (1);
2040       rc = assuan_init_pipe_server (ctx, filedes);
2041     }
2042   else
2043     {
2044       rc = assuan_init_socket_server (ctx, INT2FD(fd),
2045                                       ASSUAN_SOCKET_SERVER_ACCEPTED);
2046     }
2047   if (rc)
2048     {
2049       log_error ("failed to initialize the server: %s\n",
2050                  gpg_strerror(rc));
2051       scd_exit (2);
2052     }
2053   rc = register_commands (ctx);
2054   if (rc)
2055     {
2056       log_error ("failed to register commands with Assuan: %s\n",
2057                  gpg_strerror(rc));
2058       scd_exit (2);
2059     }
2060   assuan_set_pointer (ctx, ctrl);
2061
2062   /* Allocate and initialize the server object.  Put it into the list
2063      of active sessions. */
2064   ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
2065   ctrl->server_local->next_session = session_list;
2066   session_list = ctrl->server_local;
2067   ctrl->server_local->ctrl_backlink = ctrl;
2068   ctrl->server_local->assuan_ctx = ctx;
2069   ctrl->server_local->vreader_idx = -1;
2070
2071   /* We open the reader right at startup so that the ticker is able to
2072      update the status file. */
2073   if (ctrl->server_local->vreader_idx == -1)
2074     {
2075       ctrl->server_local->vreader_idx = get_current_reader ();
2076     }
2077
2078   /* Command processing loop. */
2079   for (;;)
2080     {
2081       rc = assuan_accept (ctx);
2082       if (rc == -1)
2083         {
2084           break;
2085         }
2086       else if (rc)
2087         {
2088           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
2089           break;
2090         }
2091
2092       rc = assuan_process (ctx);
2093       if (rc)
2094         {
2095           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
2096           continue;
2097         }
2098     }
2099
2100   /* Cleanup.  We don't send an explicit reset to the card.  */
2101   do_reset (ctrl, 0);
2102
2103   /* Release the server object.  */
2104   if (session_list == ctrl->server_local)
2105     session_list = ctrl->server_local->next_session;
2106   else
2107     {
2108       struct server_local_s *sl;
2109
2110       for (sl=session_list; sl->next_session; sl = sl->next_session)
2111         if (sl->next_session == ctrl->server_local)
2112           break;
2113       if (!sl->next_session)
2114           BUG ();
2115       sl->next_session = ctrl->server_local->next_session;
2116     }
2117   stopme = ctrl->server_local->stopme;
2118   xfree (ctrl->server_local);
2119   ctrl->server_local = NULL;
2120
2121   /* Release the Assuan context.  */
2122   assuan_release (ctx);
2123
2124   if (stopme)
2125     scd_exit (0);
2126
2127   /* If there are no more sessions return true.  */
2128   return !session_list;
2129 }
2130
2131
2132 /* Send a line with status information via assuan and escape all given
2133    buffers. The variable elements are pairs of (char *, size_t),
2134    terminated with a (NULL, 0). */
2135 void
2136 send_status_info (ctrl_t ctrl, const char *keyword, ...)
2137 {
2138   va_list arg_ptr;
2139   const unsigned char *value;
2140   size_t valuelen;
2141   char buf[950], *p;
2142   size_t n;
2143   assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2144
2145   va_start (arg_ptr, keyword);
2146
2147   p = buf;
2148   n = 0;
2149   while ( (value = va_arg (arg_ptr, const unsigned char *)) )
2150     {
2151       valuelen = va_arg (arg_ptr, size_t);
2152       if (!valuelen)
2153         continue; /* empty buffer */
2154       if (n)
2155         {
2156           *p++ = ' ';
2157           n++;
2158         }
2159       for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
2160         {
2161           if (*value < ' ' || *value == '+')
2162             {
2163               sprintf (p, "%%%02X", *value);
2164               p += 3;
2165             }
2166           else if (*value == ' ')
2167             *p++ = '+';
2168           else
2169             *p++ = *value;
2170         }
2171     }
2172   *p = 0;
2173   assuan_write_status (ctx, keyword, buf);
2174
2175   va_end (arg_ptr);
2176 }
2177
2178
2179 /* Send a ready formatted status line via assuan.  */
2180 void
2181 send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
2182 {
2183   assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2184
2185   if (strchr (args, '\n'))
2186     log_error ("error: LF detected in status line - not sending\n");
2187   else
2188     assuan_write_status (ctx, keyword, args);
2189 }
2190
2191
2192 /* Helper to send the clients a status change notification.  */
2193 static void
2194 send_client_notifications (void)
2195 {
2196   struct {
2197     pid_t pid;
2198 #ifdef HAVE_W32_SYSTEM
2199     HANDLE handle;
2200 #else
2201     int signo;
2202 #endif
2203   } killed[50];
2204   int killidx = 0;
2205   int kidx;
2206   struct server_local_s *sl;
2207
2208   for (sl=session_list; sl; sl = sl->next_session)
2209     {
2210       if (sl->event_signal && sl->assuan_ctx)
2211         {
2212           pid_t pid = assuan_get_pid (sl->assuan_ctx);
2213 #ifdef HAVE_W32_SYSTEM
2214           HANDLE handle = (void *)sl->event_signal;
2215
2216           for (kidx=0; kidx < killidx; kidx++)
2217             if (killed[kidx].pid == pid
2218                 && killed[kidx].handle == handle)
2219               break;
2220           if (kidx < killidx)
2221             log_info ("event %lx (%p) already triggered for client %d\n",
2222                       sl->event_signal, handle, (int)pid);
2223           else
2224             {
2225               log_info ("triggering event %lx (%p) for client %d\n",
2226                         sl->event_signal, handle, (int)pid);
2227               if (!SetEvent (handle))
2228                 log_error ("SetEvent(%lx) failed: %s\n",
2229                            sl->event_signal, w32_strerror (-1));
2230               if (killidx < DIM (killed))
2231                 {
2232                   killed[killidx].pid = pid;
2233                   killed[killidx].handle = handle;
2234                   killidx++;
2235                 }
2236             }
2237 #else /*!HAVE_W32_SYSTEM*/
2238           int signo = sl->event_signal;
2239
2240           if (pid != (pid_t)(-1) && pid && signo > 0)
2241             {
2242               for (kidx=0; kidx < killidx; kidx++)
2243                 if (killed[kidx].pid == pid
2244                     && killed[kidx].signo == signo)
2245                   break;
2246               if (kidx < killidx)
2247                 log_info ("signal %d already sent to client %d\n",
2248                           signo, (int)pid);
2249               else
2250                 {
2251                   log_info ("sending signal %d to client %d\n",
2252                             signo, (int)pid);
2253                   kill (pid, signo);
2254                   if (killidx < DIM (killed))
2255                     {
2256                       killed[killidx].pid = pid;
2257                       killed[killidx].signo = signo;
2258                       killidx++;
2259                     }
2260                 }
2261             }
2262 #endif /*!HAVE_W32_SYSTEM*/
2263         }
2264     }
2265 }
2266
2267
2268
2269 /* This is the core of scd_update_reader_status_file but the caller
2270    needs to take care of the locking.  */
2271 static void
2272 update_reader_status_file (int set_card_removed_flag)
2273 {
2274   int idx;
2275   unsigned int status, changed;
2276
2277   /* Note, that we only try to get the status, because it does not
2278      make sense to wait here for a operation to complete.  If we are
2279      busy working with a card, delays in the status file update should
2280      be acceptable. */
2281   for (idx=0; idx < DIM(vreader_table); idx++)
2282     {
2283       struct vreader_s *vr = vreader_table + idx;
2284       struct server_local_s *sl;
2285       int sw_apdu;
2286
2287       if (!vr->valid || vr->slot == -1)
2288         continue; /* Not valid or reader not yet open. */
2289
2290       sw_apdu = apdu_get_status (vr->slot, 0, &status, &changed);
2291       if (sw_apdu == SW_HOST_NO_READER)
2292         {
2293           /* Most likely the _reader_ has been unplugged.  */
2294           application_notify_card_reset (vr->slot);
2295           apdu_close_reader (vr->slot);
2296           vr->slot = -1;
2297           status = 0;
2298           changed = vr->changed;
2299         }
2300       else if (sw_apdu)
2301         {
2302           /* Get status failed.  Ignore that.  */
2303           continue;
2304         }
2305
2306       if (!vr->any || vr->status != status || vr->changed != changed )
2307         {
2308           char *fname;
2309           char templ[50];
2310           FILE *fp;
2311
2312           log_info ("updating reader %d (%d) status: 0x%04X->0x%04X (%u->%u)\n",
2313                     idx, vr->slot, vr->status, status, vr->changed, changed);
2314           vr->status = status;
2315           vr->changed = changed;
2316
2317           /* FIXME: Should this be IDX instead of vr->slot?  This
2318              depends on how client sessions will associate the reader
2319              status with their session.  */
2320           snprintf (templ, sizeof templ, "reader_%d.status", vr->slot);
2321           fname = make_filename (opt.homedir, templ, NULL );
2322           fp = fopen (fname, "w");
2323           if (fp)
2324             {
2325               fprintf (fp, "%s\n",
2326                        (status & 1)? "USABLE":
2327                        (status & 4)? "ACTIVE":
2328                        (status & 2)? "PRESENT": "NOCARD");
2329               fclose (fp);
2330             }
2331           xfree (fname);
2332
2333           /* If a status script is executable, run it. */
2334           {
2335             const char *args[9], *envs[2];
2336             char numbuf1[30], numbuf2[30], numbuf3[30];
2337             char *homestr, *envstr;
2338             gpg_error_t err;
2339
2340             homestr = make_filename (opt.homedir, NULL);
2341             if (gpgrt_asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
2342               log_error ("out of core while building environment\n");
2343             else
2344               {
2345                 envs[0] = envstr;
2346                 envs[1] = NULL;
2347
2348                 sprintf (numbuf1, "%d", vr->slot);
2349                 sprintf (numbuf2, "0x%04X", vr->status);
2350                 sprintf (numbuf3, "0x%04X", status);
2351                 args[0] = "--reader-port";
2352                 args[1] = numbuf1;
2353                 args[2] = "--old-code";
2354                 args[3] = numbuf2;
2355                 args[4] = "--new-code";
2356                 args[5] = numbuf3;
2357                 args[6] = "--status";
2358                 args[7] = ((status & 1)? "USABLE":
2359                            (status & 4)? "ACTIVE":
2360                            (status & 2)? "PRESENT": "NOCARD");
2361                 args[8] = NULL;
2362
2363                 fname = make_filename (opt.homedir, "scd-event", NULL);
2364                 err = gnupg_spawn_process_detached (fname, args, envs);
2365                 if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
2366                   log_error ("failed to run event handler '%s': %s\n",
2367                              fname, gpg_strerror (err));
2368                 xfree (fname);
2369                 xfree (envstr);
2370               }
2371             xfree (homestr);
2372           }
2373
2374           /* Set the card removed flag for all current sessions.  */
2375           if (vr->any && vr->status == 0 && set_card_removed_flag)
2376             update_card_removed (idx, 1);
2377
2378           vr->any = 1;
2379
2380           /* Send a signal to all clients who applied for it.  */
2381           send_client_notifications ();
2382         }
2383
2384       /* Check whether a disconnect is pending.  */
2385       if (opt.card_timeout)
2386         {
2387           for (sl=session_list; sl; sl = sl->next_session)
2388             if (!sl->disconnect_allowed)
2389               break;
2390           if (session_list && !sl)
2391             {
2392               /* FIXME: Use a real timeout.  */
2393               /* At least one connection and all allow a disconnect.  */
2394               log_info ("disconnecting card in reader %d (%d)\n",
2395                         idx, vr->slot);
2396               apdu_disconnect (vr->slot);
2397             }
2398         }
2399
2400     }
2401 }
2402
2403 /* This function is called by the ticker thread to check for changes
2404    of the reader stati.  It updates the reader status files and if
2405    requested by the caller also send a signal to the caller.  */
2406 void
2407 scd_update_reader_status_file (void)
2408 {
2409   int err;
2410   err = npth_mutex_lock (&status_file_update_lock);
2411   if (err)
2412     return; /* locked - give up. */
2413   update_reader_status_file (1);
2414   err = npth_mutex_unlock (&status_file_update_lock);
2415   if (err)
2416     log_error ("failed to release status_file_update lock: %s\n",
2417                strerror (err));
2418 }