* call-scd.c (unescape_status_string): New. Actual a copy of
[gnupg.git] / scd / command.c
1 /* command.c - SCdaemon command handler
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
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
30 #include <assuan.h>
31
32 #include "scdaemon.h"
33 #include <ksba.h>
34 #include "app-common.h"
35 #include "apdu.h" /* Required for apdu_*_reader (). */
36
37 /* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */
38 #define MAXLEN_PIN 100
39
40
41 /* We keep track of the primary client using scdaemon.  This one will
42    for example receive signal on card change. */
43 static ctrl_t primary_connection;
44
45
46 #define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
47
48
49 /* Macro to flag a a removed card.  */
50 #define TEST_CARD_REMOVAL(c,r)                              \
51        do {                                                 \
52           int _r = (r);                                     \
53           if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \
54               || gpg_err_code (_r) == GPG_ERR_CARD_REMOVED) \
55             (c)->server_local->card_removed = 1;            \
56        } while (0)
57
58
59 /* Data used to associate an Assuan context with local server data */
60 struct server_local_s {
61   assuan_context_t assuan_ctx;
62   int event_signal;        /* Or 0 if not used. */
63   int card_removed;        /* True if the card has been removed and a
64                               reset is required to continue
65                               operation. */
66 };
67
68
69 /* Check whether the option NAME appears in LINE */
70 static int
71 has_option (const char *line, const char *name)
72 {
73   const char *s;
74   int n = strlen (name);
75
76   s = strstr (line, name);
77   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
78 }
79
80
81 /* Reset the card and free the application context.  With DO_CLOSE set
82    to true, close the reader and don't do just a reset. */
83 static void
84 do_reset (ctrl_t ctrl, int do_close)
85 {
86   if (ctrl->card_ctx)
87     {
88       card_close (ctrl->card_ctx);
89       ctrl->card_ctx = NULL;
90       xfree (ctrl->in_data.value);
91       ctrl->in_data.value = NULL;
92     }
93   if (ctrl->app_ctx)
94     {
95       release_application (ctrl->app_ctx);
96       ctrl->app_ctx = NULL;
97     }
98   if (ctrl->reader_slot != -1)
99     {
100       if (do_close || apdu_reset (ctrl->reader_slot))
101         {
102           apdu_close_reader (ctrl->reader_slot);
103           ctrl->reader_slot = -1;
104         }
105     }
106   ctrl->server_local->card_removed = 0;
107 }
108
109 \f
110 static void
111 reset_notify (ASSUAN_CONTEXT ctx)
112 {
113   CTRL ctrl = assuan_get_pointer (ctx); 
114
115   do_reset (ctrl, 0);
116 }
117
118
119 static int
120 option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
121 {
122   ctrl_t ctrl = assuan_get_pointer (ctx);
123
124   if (!strcmp (key, "event-signal"))
125     {
126       /* A value of 0 is allowed to reset the event signal. */
127       int i = *value? atoi (value) : -1;
128       if (i < 0)
129         return ASSUAN_Parameter_Error;
130       ctrl->server_local->event_signal = i;
131     }
132
133  return 0;
134 }
135
136
137 /* If the card has not yet been opened, do it.  Note that this
138    function returns an Assuan error, so don't map the error a second
139    time */
140 static assuan_error_t
141 open_card (ctrl_t ctrl, const char *apptype)
142 {
143   gpg_error_t err;
144   int slot;
145
146   /* If we ever got a card not present error code, return that.  Only
147      the SERIALNO command and a reset are able to clear from that
148      state. */
149   if (ctrl->server_local->card_removed)
150     return map_to_assuan_status (gpg_error (GPG_ERR_CARD_REMOVED));
151
152   if (ctrl->app_ctx)
153     return 0; /* Already initialized for one specific application. */
154   if (ctrl->card_ctx)
155     return 0; /* Already initialized using a card context. */
156
157   if (ctrl->reader_slot != -1)
158     slot = ctrl->reader_slot;
159   else
160     slot = apdu_open_reader (opt.reader_port);
161   ctrl->reader_slot = slot;
162   if (slot == -1)
163     err = gpg_error (GPG_ERR_CARD);
164   else
165     err = select_application (ctrl, slot, apptype, &ctrl->app_ctx);
166   if (!ctrl->app_ctx
167       && gpg_err_code (err) != GPG_ERR_CARD_NOT_PRESENT)
168     { 
169       /* No application found - fall back to old mode. */
170       /* Note that we should rework the old code to use the
171          application paradigma too. */
172       /* If an APPTYPE was requested and it is not pkcs#15, we return
173          an error here. */
174       if (apptype && !(!strcmp (apptype, "P15") || !strcmp (apptype, "p15")))
175         err = gpg_error (GPG_ERR_NOT_SUPPORTED);
176       else 
177         err = card_open (&ctrl->card_ctx);
178     }
179
180   if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)
181     ctrl->server_local->card_removed = 1;
182
183   return map_to_assuan_status (err);
184 }
185
186
187 /* Do the percent and plus/space unescaping in place and return the
188    length of the valid buffer. */
189 static size_t
190 percent_plus_unescape (unsigned char *string)
191 {
192   unsigned char *p = string;
193   size_t n = 0;
194
195   while (*string)
196     {
197       if (*string == '%' && string[1] && string[2])
198         { 
199           string++;
200           *p++ = xtoi_2 (string);
201           n++;
202           string+= 2;
203         }
204       else if (*string == '+')
205         {
206           *p++ = ' ';
207           n++;
208           string++;
209         }
210       else
211         {
212           *p++ = *string++;
213           n++;
214         }
215     }
216
217   return n;
218 }
219
220
221
222 /* SERIALNO [APPTYPE] 
223
224    Return the serial number of the card using a status reponse.  This
225    functon should be used to check for the presence of a card.
226
227    If APPTYPE is given, an application of that type is selected and an
228    error is returned if the application is not supported or available.
229    The default is to auto-select the application using a hardwired
230    preference system.  Note, that a future extension to this function
231    may allow to specify a list and order of applications to try.
232
233    This function is special in that it can be used to reset the card.
234    Most other functions will return an error when a card change has
235    been detected and the use of this function is therefore required.
236
237    Background: We want to keep the client clear of handling card
238    changes between operations; i.e. the client can assume that all
239    operations are done on the same card unless he calls this function.
240  */
241 static int
242 cmd_serialno (assuan_context_t ctx, char *line)
243 {
244   ctrl_t ctrl = assuan_get_pointer (ctx);
245   int rc = 0;
246   char *serial_and_stamp;
247   char *serial;
248   time_t stamp;
249
250   /* Clear the remove flag so that the open_card is able to reread it.  */
251   if (ctrl->server_local->card_removed)
252     do_reset (ctrl, 0);
253
254   if ((rc = open_card (ctrl, *line? line:NULL)))
255     return rc;
256
257   if (ctrl->app_ctx)
258     rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
259   else
260     rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp);
261   if (rc)
262     return map_to_assuan_status (rc);
263   rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp);
264   xfree (serial);
265   if (rc < 0)
266     return ASSUAN_Out_Of_Core;
267   rc = 0;
268   assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
269   free (serial_and_stamp);
270   return 0;
271 }
272
273
274
275
276 /* LEARN [--force]
277
278    Learn all useful information of the currently inserted card.  When
279    used without the force options, the command might do an INQUIRE
280    like this:
281
282       INQUIRE KNOWNCARDP <hexstring_with_serialNumber> <timestamp>
283
284    The client should just send an "END" if the processing should go on
285    or a "CANCEL" to force the function to terminate with a Cancel
286    error message.  The response of this command is a list of status
287    lines formatted as this:
288
289      S APPTYPE <apptype>
290
291    This returns the type of the application, currently the strings:
292
293        P15     = PKCS-15 structure used
294        DINSIG  = DIN SIG
295        OPENPGP = OpenPGP card
296  
297    are implemented.  These strings are aliases for the AID
298
299      S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id>
300
301    If there is no certificate yet stored on the card a single "X" is
302    returned as the keygrip.  In addition to the keypair info, information
303    about all certificates stored on the card is also returned:
304
305      S CERTINFO <certtype> <hexstring_with_id>
306
307    Where CERTTYPE is a number indicating the type of certificate:
308       0   := Unknown
309       100 := Regular X.509 cert
310       101 := Trusted X.509 cert
311       102 := Useful X.509 cert
312       110 := Root CA cert (DINSIG)
313
314    For certain cards, more information will be returned:
315
316      S KEY-FPR <no> <hexstring>
317
318    For OpenPGP cards this returns the stored fingerprints of the
319    keys. This can be used check whether a key is available on the
320    card.  NO may be 1, 2 or 3.
321
322      S CA-FPR <no> <hexstring>
323
324    Similar to above, these are the fingerprints of keys assumed to be
325    ultimately trusted.
326
327      S DISP-NAME <name_of_card_holder>
328
329    The name of the card holder as stored on the card; percent
330    escaping takes place, spaces are encoded as '+'
331
332      S PUBKEY-URL <url>
333
334    The URL to be used for locating the entire public key.
335      
336 */
337 static int
338 cmd_learn (ASSUAN_CONTEXT ctx, char *line)
339 {
340   CTRL ctrl = assuan_get_pointer (ctx);
341   int rc = 0;
342   int idx;
343
344   if ((rc = open_card (ctrl, NULL)))
345     return rc;
346
347   /* Unless the force option is used we try a shortcut by identifying
348      the card using a serial number and inquiring the client with
349      that. The client may choose to cancel the operation if he already
350      knows about this card */
351   {
352     char *serial_and_stamp;
353     char *serial;
354     time_t stamp;
355
356     if (ctrl->app_ctx)
357       rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
358     else
359       rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp);
360     if (rc)
361       return map_to_assuan_status (rc);
362     rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp);
363     xfree (serial);
364     if (rc < 0)
365       return ASSUAN_Out_Of_Core;
366     rc = 0;
367     assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
368
369     if (!has_option (line, "--force"))
370       {
371         char *command;
372
373         rc = asprintf (&command, "KNOWNCARDP %s", serial_and_stamp);
374         if (rc < 0)
375           {
376             free (serial_and_stamp);
377             return ASSUAN_Out_Of_Core;
378           }
379         rc = 0;
380         rc = assuan_inquire (ctx, command, NULL, NULL, 0); 
381         free (command);  /* (must use standard free here) */
382         if (rc)
383           {
384             if (rc != ASSUAN_Canceled)
385               log_error ("inquire KNOWNCARDP failed: %s\n",
386                          assuan_strerror (rc));
387             free (serial_and_stamp);
388             return rc; 
389           }
390         /* not canceled, so we have to proceeed */
391       }
392     free (serial_and_stamp);
393   }
394
395   /* If we are using the modern application paradigma, let the
396      application print out its collection of useful status
397      information. */
398   if (!rc && ctrl->app_ctx)
399     rc = app_write_learn_status (ctrl->app_ctx, ctrl);
400
401   /* Return information about the certificates.  FIXME: Move this into
402      an app-p15.c*/
403   for (idx=0; !rc && !ctrl->app_ctx; idx++)
404     {
405       char *certid;
406       int certtype;
407
408       rc = card_enum_certs (ctrl->card_ctx, idx, &certid, &certtype);
409       if (!rc)
410         {
411           char *buf;
412
413           buf = xtrymalloc (40 + 1 + strlen (certid) + 1);
414           if (!buf)
415             rc = gpg_error (gpg_err_code_from_errno (errno));
416           else
417             {
418               sprintf (buf, "%d %s", certtype, certid);
419               assuan_write_status (ctx, "CERTINFO", buf);
420               xfree (buf);
421             }
422         }
423       xfree (certid);
424     }
425   if (rc == -1)
426     rc = 0;
427
428   /* Return information about the keys. FIXME: Move this into an
429      app-p15.c */
430   for (idx=0; !rc && !ctrl->app_ctx; idx++)
431     {
432       unsigned char keygrip[20];
433       char *keyid;
434       int no_cert = 0;
435
436       rc = card_enum_keypairs (ctrl->card_ctx, idx, keygrip, &keyid);
437       if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT && keyid)
438         {
439           /* This does happen with an incomplete personalized
440              card; i.e. during the time we have stored the key on the
441              card but not stored the certificate; probably becuase it
442              has not yet been received back from the CA.  Note that we
443              must release KEYID in this case. */
444           rc = 0; 
445           no_cert = 1;
446         }
447       if (!rc)
448         {
449           char *buf, *p;
450
451           buf = p = xtrymalloc (40 + 1 + strlen (keyid) + 1);
452           if (!buf)
453             rc = gpg_error (gpg_err_code_from_errno (errno));
454           else
455             {
456               int i;
457               
458               if (no_cert)
459                 *p++ = 'X';
460               else
461                 {
462                   for (i=0; i < 20; i++, p += 2)
463                     sprintf (p, "%02X", keygrip[i]);
464                 }
465               *p++ = ' ';
466               strcpy (p, keyid);
467               assuan_write_status (ctx, "KEYPAIRINFO", buf);
468               xfree (buf);
469             }
470         }
471       xfree (keyid);
472     }
473   if (rc == -1)
474     rc = 0;
475
476   TEST_CARD_REMOVAL (ctrl, rc);
477   return map_to_assuan_status (rc);
478 }
479
480
481 \f
482 /* READCERT <hexified_certid>
483
484  */
485 static int
486 cmd_readcert (ASSUAN_CONTEXT ctx, char *line)
487 {
488   CTRL ctrl = assuan_get_pointer (ctx);
489   int rc;
490   unsigned char *cert;
491   size_t ncert;
492
493   if ((rc = open_card (ctrl, NULL)))
494     return rc;
495
496   line = xstrdup (line); /* Need a copy of the line. */
497   if (ctrl->app_ctx)
498     {
499       rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
500       if (rc)
501         log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
502     }
503   else
504     {
505       rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert);
506       if (rc)
507         log_error ("card_read_cert failed: %s\n", gpg_strerror (rc));
508     }
509   xfree (line);
510   line = NULL;
511   if (!rc)
512     {
513       rc = assuan_send_data (ctx, cert, ncert);
514       xfree (cert);
515       if (rc)
516         return rc;
517     }
518
519   TEST_CARD_REMOVAL (ctrl, rc);
520   return map_to_assuan_status (rc);
521 }
522
523
524 /* READKEY <hexified_certid>
525
526    Return the public key for the given cert or key ID as an standard
527    S-Expression.  */
528 static int
529 cmd_readkey (assuan_context_t ctx, char *line)
530 {
531   ctrl_t ctrl = assuan_get_pointer (ctx);
532   int rc;
533   unsigned char *cert = NULL;
534   size_t ncert, n;
535   ksba_cert_t kc = NULL;
536   ksba_sexp_t p;
537
538   if ((rc = open_card (ctrl, NULL)))
539     return rc;
540
541   line = xstrdup (line); /* Need a copy of the line. */
542   if (ctrl->app_ctx)
543     {
544       unsigned char *pk;
545       size_t pklen;
546
547       /* If the application supports the READKEY function we use that.
548          Otherwise we use the old way by extracting it from the
549          certificate.  */
550       rc = app_readkey (ctrl->app_ctx, line, &pk, &pklen);
551       if (!rc)
552         { /* Yeah, got that key - send it back.  */
553           rc = assuan_send_data (ctx, pk, pklen);
554           xfree (pk);
555           rc = map_assuan_err (rc);
556           xfree (line);
557           line = NULL;
558           goto leave;
559         }
560
561       if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION)
562         log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
563       else  
564         {
565           rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
566           if (rc)
567             log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
568         }
569     }
570   else
571     {
572       rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert);
573       if (rc)
574         log_error ("card_read_cert failed: %s\n", gpg_strerror (rc));
575     }
576   xfree (line);
577   line = NULL;
578   if (rc)
579     goto leave;
580       
581   rc = ksba_cert_new (&kc);
582   if (rc)
583     {
584       xfree (cert);
585       goto leave;
586     }
587   rc = ksba_cert_init_from_mem (kc, cert, ncert);
588   if (rc)
589     {
590       log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
591       goto leave;
592     }
593
594   p = ksba_cert_get_public_key (kc);
595   if (!p)
596     {
597       rc = gpg_error (GPG_ERR_NO_PUBKEY);
598       goto leave;
599     }
600
601   n = gcry_sexp_canon_len (p, 0, NULL, NULL);
602   rc = assuan_send_data (ctx, p, n);
603   rc = map_assuan_err (rc);
604   xfree (p);
605
606
607  leave:
608   ksba_cert_release (kc);
609   xfree (cert);
610   TEST_CARD_REMOVAL (ctrl, rc);
611   return map_to_assuan_status (rc);
612 }
613
614
615 \f
616
617 /* SETDATA <hexstring> 
618
619    The client should use this command to tell us the data he want to
620    sign.  */
621 static int
622 cmd_setdata (ASSUAN_CONTEXT ctx, char *line)
623 {
624   CTRL ctrl = assuan_get_pointer (ctx);
625   int n;
626   char *p;
627   unsigned char *buf;
628
629   /* parse the hexstring */
630   for (p=line,n=0; hexdigitp (p); p++, n++)
631     ;
632   if (*p)
633     return set_error (Parameter_Error, "invalid hexstring");
634   if (!n)
635     return set_error (Parameter_Error, "no data given");
636   if ((n&1))
637     return set_error (Parameter_Error, "odd number of digits");
638   n /= 2;
639   buf = xtrymalloc (n);
640   if (!buf)
641     return ASSUAN_Out_Of_Core;
642
643   ctrl->in_data.value = buf;
644   ctrl->in_data.valuelen = n;
645   for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++)
646     buf[n] = xtoi_2 (p);
647   return 0;
648 }
649
650
651
652 static int 
653 pin_cb (void *opaque, const char *info, char **retstr)
654 {
655   ASSUAN_CONTEXT ctx = opaque;
656   char *command;
657   int rc;
658   unsigned char *value;
659   size_t valuelen;
660
661   *retstr = NULL;
662   log_debug ("asking for PIN '%s'\n", info);
663
664   rc = asprintf (&command, "NEEDPIN %s", info);
665   if (rc < 0)
666     return gpg_error (gpg_err_code_from_errno (errno));
667
668   /* FIXME: Write an inquire function which returns the result in
669      secure memory */
670   rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); 
671   free (command);  
672   if (rc)
673     return map_assuan_err (rc);
674
675   if (!valuelen || value[valuelen-1])
676     {
677       /* We require that the returned value is an UTF-8 string */
678       xfree (value);
679       return gpg_error (GPG_ERR_INV_RESPONSE);
680     }
681   *retstr = value;
682   return 0;
683 }
684
685
686 /* PKSIGN <hexified_id>
687
688  */
689 static int
690 cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
691 {
692   CTRL ctrl = assuan_get_pointer (ctx);
693   int rc;
694   unsigned char *outdata;
695   size_t outdatalen;
696   char *keyidstr;
697
698   if ((rc = open_card (ctrl, NULL)))
699     return rc;
700
701   /* We have to use a copy of the key ID because the function may use
702      the pin_cb which in turn uses the assuan line buffer and thus
703      overwriting the original line with the keyid */
704   keyidstr = xtrystrdup (line);
705   if (!keyidstr)
706     return ASSUAN_Out_Of_Core;
707   
708   if (ctrl->app_ctx)
709     rc = app_sign (ctrl->app_ctx,
710                     keyidstr, GCRY_MD_SHA1,
711                     pin_cb, ctx,
712                     ctrl->in_data.value, ctrl->in_data.valuelen,
713                     &outdata, &outdatalen);
714   else  
715     rc = card_sign (ctrl->card_ctx,
716                     keyidstr, GCRY_MD_SHA1,
717                     pin_cb, ctx,
718                     ctrl->in_data.value, ctrl->in_data.valuelen,
719                     &outdata, &outdatalen);
720   xfree (keyidstr);
721   if (rc)
722     {
723       log_error ("card_sign failed: %s\n", gpg_strerror (rc));
724     }
725   else
726     {
727       rc = assuan_send_data (ctx, outdata, outdatalen);
728       xfree (outdata);
729       if (rc)
730         return rc; /* that is already an assuan error code */
731     }
732
733   TEST_CARD_REMOVAL (ctrl, rc);
734   return map_to_assuan_status (rc);
735 }
736
737 /* PKAUTH <hexified_id>
738
739  */
740 static int
741 cmd_pkauth (ASSUAN_CONTEXT ctx, char *line)
742 {
743   CTRL ctrl = assuan_get_pointer (ctx);
744   int rc;
745   unsigned char *outdata;
746   size_t outdatalen;
747   char *keyidstr;
748
749   if ((rc = open_card (ctrl, NULL)))
750     return rc;
751
752   if (!ctrl->app_ctx)
753     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
754
755   /* We have to use a copy of the key ID because the function may use
756      the pin_cb which in turn uses the assuan line buffer and thus
757      overwriting the original line with the keyid */
758   keyidstr = xtrystrdup (line);
759   if (!keyidstr)
760     return ASSUAN_Out_Of_Core;
761   
762   rc = app_auth (ctrl->app_ctx,
763                  keyidstr,
764                  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_sign 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   TEST_CARD_REMOVAL (ctrl, rc);
781   return map_to_assuan_status (rc);
782 }
783
784 /* PKDECRYPT <hexified_id>
785
786  */
787 static int
788 cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
789 {
790   CTRL ctrl = assuan_get_pointer (ctx);
791   int rc;
792   unsigned char *outdata;
793   size_t outdatalen;
794   char *keyidstr;
795
796   if ((rc = open_card (ctrl, NULL)))
797     return rc;
798
799   keyidstr = xtrystrdup (line);
800   if (!keyidstr)
801     return ASSUAN_Out_Of_Core;
802   if (ctrl->app_ctx)
803     rc = app_decipher (ctrl->app_ctx,
804                         keyidstr, 
805                         pin_cb, ctx,
806                         ctrl->in_data.value, ctrl->in_data.valuelen,
807                         &outdata, &outdatalen);
808   else
809     rc = card_decipher (ctrl->card_ctx,
810                         keyidstr, 
811                         pin_cb, ctx,
812                         ctrl->in_data.value, ctrl->in_data.valuelen,
813                         &outdata, &outdatalen);
814   xfree (keyidstr);
815   if (rc)
816     {
817       log_error ("card_create_signature failed: %s\n", gpg_strerror (rc));
818     }
819   else
820     {
821       rc = assuan_send_data (ctx, outdata, outdatalen);
822       xfree (outdata);
823       if (rc)
824         return rc; /* that is already an assuan error code */
825     }
826
827   TEST_CARD_REMOVAL (ctrl, rc);
828   return map_to_assuan_status (rc);
829 }
830
831
832 /* GETATTR <name>
833
834    This command is used to retrieve data from a smartcard.  The
835    allowed names depend on the currently selected smartcard
836    application.  NAME must be percent and '+' escaped.  The value is
837    returned through status message, see the LESRN command for details.
838
839    However, the current implementation assumes that Name is not escaped;
840    this works as long as noone uses arbitrary escaping. 
841  
842 */
843 static int
844 cmd_getattr (ASSUAN_CONTEXT ctx, char *line)
845 {
846   CTRL ctrl = assuan_get_pointer (ctx);
847   int rc;
848   char *keyword;
849
850   if ((rc = open_card (ctrl, NULL)))
851     return rc;
852
853   keyword = line;
854   for (; *line && !spacep (line); line++)
855     ;
856   if (*line)
857       *line++ = 0;
858
859   /* (We ignore any garbage for now.) */
860
861   rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
862
863   TEST_CARD_REMOVAL (ctrl, rc);
864   return map_to_assuan_status (rc);
865 }
866
867
868 /* SETATTR <name> <value> 
869
870    This command is used to store data on a a smartcard.  The allowed
871    names and values are depend on the currently selected smartcard
872    application.  NAME and VALUE must be percent and '+' escaped.
873
874    However, the curent implementation assumes that Name is not escaped;
875    this works as long as noone uses arbitrary escaping. 
876  
877    A PIN will be requested for most NAMEs.  See the corresponding
878    setattr function of the actually used application (app-*.c) for
879    details.  */
880 static int
881 cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line)
882 {
883   CTRL ctrl = assuan_get_pointer (ctx);
884   int rc;
885   char *keyword;
886   int keywordlen;
887   size_t nbytes;
888   char *line, *linebuf;
889
890   if ((rc = open_card (ctrl, NULL)))
891     return rc;
892
893   /* We need to use a copy of LINE, because PIN_CB uses the same
894      context and thus reuses the Assuan provided LINE. */
895   line = linebuf = xtrystrdup (orig_line);
896   if (!line)
897     return ASSUAN_Out_Of_Core;
898
899   keyword = line;
900   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
901     ;
902   if (*line)
903       *line++ = 0;
904   while (spacep (line))
905     line++;
906   nbytes = percent_plus_unescape (line);
907
908   rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx, line, nbytes);
909   xfree (linebuf);
910
911   TEST_CARD_REMOVAL (ctrl, rc);
912   return map_to_assuan_status (rc);
913 }
914
915 /* GENKEY [--force] <no>
916
917    Generate a key on-card identified by NO, which is application
918    specific.  Return values are application specific.  For OpenPGP
919    cards 2 status lines are returned:
920
921      S KEY-FPR  <hexstring>
922      S KEY-CREATED-AT <seconds_since_epoch>
923      S KEY-DATA [p|n] <hexdata>
924      
925
926    --force is required to overwriet an already existing key.  The
927    KEY-CREATED-AT is required for further processing because it is
928    part of the hashed key material for the fingerprint.
929
930    The public part of the key can also later be retrieved using the
931    READKEY command.
932
933  */
934 static int
935 cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
936 {
937   CTRL ctrl = assuan_get_pointer (ctx);
938   int rc;
939   char *keyno;
940   int force = has_option (line, "--force");
941
942   /* Skip over options. */
943   while ( *line == '-' && line[1] == '-' )
944     {
945       while (*line && !spacep (line))
946         line++;
947       while (spacep (line))
948         line++;
949     }
950   if (!*line)
951     return set_error (Parameter_Error, "no key number given");
952   keyno = line;
953   while (*line && !spacep (line))
954     line++;
955   *line = 0;
956
957   if ((rc = open_card (ctrl, NULL)))
958     return rc;
959
960   if (!ctrl->app_ctx)
961     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
962
963   keyno = xtrystrdup (keyno);
964   if (!keyno)
965     return ASSUAN_Out_Of_Core;
966   rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0, pin_cb, ctx);
967   xfree (keyno);
968
969   TEST_CARD_REMOVAL (ctrl, rc);
970   return map_to_assuan_status (rc);
971 }
972
973
974 /* RANDOM <nbytes>
975
976    Get NBYTES of random from the card and send them back as data. 
977 */
978 static int
979 cmd_random (ASSUAN_CONTEXT ctx, char *line)
980 {
981   CTRL ctrl = assuan_get_pointer (ctx);
982   int rc;
983   size_t nbytes;
984   unsigned char *buffer;
985
986   if (!*line)
987     return set_error (Parameter_Error, "number of requested bytes missing");
988   nbytes = strtoul (line, NULL, 0);
989
990   if ((rc = open_card (ctrl, NULL)))
991     return rc;
992
993   if (!ctrl->app_ctx)
994     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
995
996   buffer = xtrymalloc (nbytes);
997   if (!buffer)
998     return ASSUAN_Out_Of_Core;
999
1000   rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
1001   if (!rc)
1002     {
1003       rc = assuan_send_data (ctx, buffer, nbytes);
1004       xfree (buffer);
1005       return rc; /* that is already an assuan error code */
1006     }
1007   xfree (buffer);
1008
1009   TEST_CARD_REMOVAL (ctrl, rc);
1010   return map_to_assuan_status (rc);
1011 }
1012
1013 \f
1014 /* PASSWD [--reset] <chvno>
1015   
1016    Change the PIN or reset thye retry counter of the card holder
1017    verfication vector CHVNO. */
1018 static int
1019 cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
1020 {
1021   CTRL ctrl = assuan_get_pointer (ctx);
1022   int rc;
1023   char *chvnostr;
1024   int reset_mode = has_option (line, "--reset");
1025
1026   /* Skip over options. */
1027   while (*line == '-' && line[1] == '-')
1028     {
1029       while (*line && !spacep (line))
1030         line++;
1031       while (spacep (line))
1032         line++;
1033     }
1034   if (!*line)
1035     return set_error (Parameter_Error, "no CHV number given");
1036   chvnostr = line;
1037   while (*line && !spacep (line))
1038     line++;
1039   *line = 0;
1040
1041   if ((rc = open_card (ctrl, NULL)))
1042     return rc;
1043
1044   if (!ctrl->app_ctx)
1045     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1046   
1047   chvnostr = xtrystrdup (chvnostr);
1048   if (!chvnostr)
1049     return ASSUAN_Out_Of_Core;
1050   rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, reset_mode, pin_cb, ctx);
1051   if (rc)
1052     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1053   xfree (chvnostr);
1054
1055   TEST_CARD_REMOVAL (ctrl, rc);
1056   return map_to_assuan_status (rc);
1057 }
1058
1059
1060 /* CHECKPIN <hexified_id>
1061
1062  */
1063 static int
1064 cmd_checkpin (ASSUAN_CONTEXT ctx, char *line)
1065 {
1066   CTRL ctrl = assuan_get_pointer (ctx);
1067   int rc;
1068   char *keyidstr;
1069
1070   if ((rc = open_card (ctrl, NULL)))
1071     return rc;
1072
1073   if (!ctrl->app_ctx)
1074     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1075
1076   /* We have to use a copy of the key ID because the function may use
1077      the pin_cb which in turn uses the assuan line buffer and thus
1078      overwriting the original line with the keyid. */
1079   keyidstr = xtrystrdup (line);
1080   if (!keyidstr)
1081     return ASSUAN_Out_Of_Core;
1082   
1083   rc = app_check_pin (ctrl->app_ctx,
1084                       keyidstr,
1085                       pin_cb, ctx);
1086   xfree (keyidstr);
1087   if (rc)
1088     log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
1089
1090   TEST_CARD_REMOVAL (ctrl, rc);
1091   return map_to_assuan_status (rc);
1092 }
1093
1094
1095
1096 \f
1097 /* Tell the assuan library about our commands */
1098 static int
1099 register_commands (ASSUAN_CONTEXT ctx)
1100 {
1101   static struct {
1102     const char *name;
1103     int (*handler)(ASSUAN_CONTEXT, char *line);
1104   } table[] = {
1105     { "SERIALNO",     cmd_serialno },
1106     { "LEARN",        cmd_learn },
1107     { "READCERT",     cmd_readcert },
1108     { "READKEY",      cmd_readkey },
1109     { "SETDATA",      cmd_setdata },
1110     { "PKSIGN",       cmd_pksign },
1111     { "PKAUTH",       cmd_pkauth },
1112     { "PKDECRYPT",    cmd_pkdecrypt },
1113     { "INPUT",        NULL }, 
1114     { "OUTPUT",       NULL }, 
1115     { "GETATTR",      cmd_getattr },
1116     { "SETATTR",      cmd_setattr },
1117     { "GENKEY",       cmd_genkey },
1118     { "RANDOM",       cmd_random },
1119     { "PASSWD",       cmd_passwd },
1120     { "CHECKPIN",     cmd_checkpin },
1121     { NULL }
1122   };
1123   int i, rc;
1124
1125   for (i=0; table[i].name; i++)
1126     {
1127       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
1128       if (rc)
1129         return rc;
1130     } 
1131   assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
1132
1133   assuan_register_reset_notify (ctx, reset_notify);
1134   assuan_register_option_handler (ctx, option_handler);
1135   return 0;
1136 }
1137
1138
1139 /* Startup the server.  If LISTEN_FD is given as -1, this is simple
1140    piper server, otherwise it is a regular server */
1141 void
1142 scd_command_handler (int listen_fd)
1143 {
1144   int rc;
1145   ASSUAN_CONTEXT ctx;
1146   struct server_control_s ctrl;
1147
1148   memset (&ctrl, 0, sizeof ctrl);
1149   scd_init_default_ctrl (&ctrl);
1150   
1151   if (listen_fd == -1)
1152     {
1153       int filedes[2];
1154
1155       filedes[0] = 0;
1156       filedes[1] = 1;
1157       rc = assuan_init_pipe_server (&ctx, filedes);
1158     }
1159   else
1160     {
1161       rc = assuan_init_socket_server (&ctx, listen_fd);
1162     }
1163   if (rc)
1164     {
1165       log_error ("failed to initialize the server: %s\n",
1166                  assuan_strerror(rc));
1167       scd_exit (2);
1168     }
1169   rc = register_commands (ctx);
1170   if (rc)
1171     {
1172       log_error ("failed to register commands with Assuan: %s\n",
1173                  assuan_strerror(rc));
1174       scd_exit (2);
1175     }
1176   assuan_set_pointer (ctx, &ctrl);
1177   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
1178   ctrl.server_local->assuan_ctx = ctx;
1179
1180   if (DBG_ASSUAN)
1181     assuan_set_log_stream (ctx, log_get_stream ());
1182
1183   /* Store the primary connection's assuan context. */
1184   if (!primary_connection)
1185     primary_connection = &ctrl;
1186
1187   /* We open the reader right at startup so that the ticker is able to
1188      update the status file. */
1189   if (ctrl.reader_slot == -1)
1190     ctrl.reader_slot = apdu_open_reader (opt.reader_port);
1191
1192   /* Command processing loop. */
1193   for (;;)
1194     {
1195       rc = assuan_accept (ctx);
1196       if (rc == -1)
1197         {
1198           break;
1199         }
1200       else if (rc)
1201         {
1202           log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
1203           break;
1204         }
1205       
1206       rc = assuan_process (ctx);
1207       if (rc)
1208         {
1209           log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
1210           continue;
1211         }
1212     }
1213
1214   /* The next client will be the primary conenction if this one
1215      terminates. */
1216   if (primary_connection == &ctrl)
1217     primary_connection = NULL;
1218
1219   do_reset (&ctrl, 1); /* Cleanup. */
1220
1221   assuan_deinit_server (ctx);
1222 }
1223
1224
1225 /* Send a line with status information via assuan and escape all given
1226    buffers. The variable elements are pairs of (char *, size_t),
1227    terminated with a (NULL, 0). */
1228 void
1229 send_status_info (CTRL ctrl, const char *keyword, ...)
1230 {
1231   va_list arg_ptr;
1232   const unsigned char *value;
1233   size_t valuelen;
1234   char buf[950], *p;
1235   size_t n;
1236   ASSUAN_CONTEXT ctx = ctrl->server_local->assuan_ctx;
1237   
1238   va_start (arg_ptr, keyword);
1239
1240   p = buf; 
1241   n = 0;
1242   while ( (value = va_arg (arg_ptr, const unsigned char *)) )
1243     {
1244       valuelen = va_arg (arg_ptr, size_t);
1245       if (!valuelen)
1246         continue; /* empty buffer */
1247       if (n)
1248         {
1249           *p++ = ' ';
1250           n++;
1251         }
1252       for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
1253         {
1254           if (*value < ' ' || *value == '+')
1255             {
1256               sprintf (p, "%%%02X", *value);
1257               p += 3;
1258             }
1259           else if (*value == ' ')
1260             *p++ = '+';
1261           else
1262             *p++ = *value;
1263         }
1264     }
1265   *p = 0;
1266   assuan_write_status (ctx, keyword, buf);
1267
1268   va_end (arg_ptr);
1269 }
1270
1271
1272 /* This fucntion is called by the ticker thread to check for changes
1273    of the reader stati.  It updates the reader status files and if
1274    requested by the caller also send a signal to the caller.  */
1275 void
1276 scd_update_reader_status_file (void)
1277 {
1278   static struct {
1279     int any;
1280     unsigned int status;
1281     unsigned int changed;
1282   } last[10];
1283   int slot;
1284   int used;
1285   unsigned int status, changed;
1286
1287   /* Note, that we only try to get the status, because it does not
1288      make sense to wait here for a operation to complete.  If we are
1289      busy working with a card, delays in the status file update should
1290      be acceptable. */
1291   for (slot=0; (slot < DIM(last)
1292                 &&!apdu_enum_reader (slot, &used)); slot++)
1293     if (used && !apdu_get_status (slot, 0, &status, &changed))
1294       {
1295         if (!last[slot].any || last[slot].status != status
1296             || last[slot].changed != changed )
1297           {
1298             char *fname;
1299             char templ[50];
1300             FILE *fp;
1301
1302             log_info ("updating status of slot %d to 0x%04X\n", slot, status);
1303             
1304             sprintf (templ, "reader_%d.status", slot);
1305             fname = make_filename (opt.homedir, templ, NULL );
1306             fp = fopen (fname, "w");
1307             if (fp)
1308               {
1309                 fprintf (fp, "%s\n",
1310                          (status & 1)? "USABLE":
1311                          (status & 4)? "ACTIVE":
1312                          (status & 2)? "PRESENT": "NOCARD");
1313                 fclose (fp);
1314               }
1315             xfree (fname);
1316
1317             /* Set the card removed flag.  We will set this on any
1318                card change because a reset or SERIALNO request must be
1319                done in any case.  */
1320             if (primary_connection && primary_connection->server_local
1321                 && last[slot].any )
1322               primary_connection->server_local->card_removed = 1;
1323
1324             last[slot].any = 1;
1325             last[slot].status = status;
1326             last[slot].changed = changed;
1327
1328
1329             /* Send a signal to the primary client, if any.  */
1330             if (primary_connection && primary_connection->server_local
1331                 && primary_connection->server_local->assuan_ctx)
1332               {
1333                 pid_t pid = assuan_get_pid (primary_connection
1334                                             ->server_local->assuan_ctx);
1335                 int signo = primary_connection->server_local->event_signal;
1336
1337                 log_info ("client pid is %d, sending signal %d\n", pid, signo);
1338
1339 #ifndef HAVE_W32_SYSTEM
1340                 if (pid != (pid_t)(-1) && pid && signo > 0)
1341                   kill (pid, signo);
1342 #endif
1343               }
1344           }
1345       }
1346 }