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