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