Mainly changes to adjust for the changed KSBA API.
[gnupg.git] / scd / command.c
1 /* command.c - SCdaemon command handler
2  *      Copyright (C) 2001, 2002, 2003 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
29 #include <assuan.h>
30
31 #include "scdaemon.h"
32 #include <ksba.h>
33 #include "app-common.h"
34
35 /* maximum length aloowed as a PIN; used for INQUIRE NEEDPIN */
36 #define MAXLEN_PIN 100
37
38 #define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
39
40 /* Data used to associate an Assuan context with local server data */
41 struct server_local_s {
42   ASSUAN_CONTEXT assuan_ctx;
43 };
44
45
46 /* Check whether the option NAME appears in LINE */
47 static int
48 has_option (const char *line, const char *name)
49 {
50   const char *s;
51   int n = strlen (name);
52
53   s = strstr (line, name);
54   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
55 }
56
57
58
59 \f
60 /* Note, that this reset_notify is also used for cleanup purposes. */
61 static void
62 reset_notify (ASSUAN_CONTEXT ctx)
63 {
64   CTRL ctrl = assuan_get_pointer (ctx); 
65
66   if (ctrl->card_ctx)
67     {
68       card_close (ctrl->card_ctx);
69       ctrl->card_ctx = NULL;
70       xfree (ctrl->in_data.value);
71       ctrl->in_data.value = NULL;
72     }
73   if (ctrl->app_ctx)
74     {
75       /* FIXME: close the application. */
76       xfree (ctrl->app_ctx);
77       ctrl->app_ctx = NULL;
78     }
79 }
80
81
82 static int
83 option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
84 {
85   return 0;
86 }
87
88
89 /* If the card has not yet been opened, do it.  Note that this
90    function returns an Assuan error, so don't map the error a second
91    time */
92 static AssuanError
93 open_card (CTRL ctrl)
94 {
95   if (ctrl->app_ctx)
96     return 0; /* Already initialized for one specific application. */
97   if (ctrl->card_ctx)
98     return 0; /* Already initialized using a card context. */
99
100   ctrl->app_ctx = select_application ();
101   if (!ctrl->app_ctx)
102     { /* No application found - fall back to old mode. */
103       int rc = card_open (&ctrl->card_ctx);
104       if (rc)
105         return map_to_assuan_status (rc);
106     }
107   return 0;
108 }
109
110
111 /* Do the percent and plus/space unescaping in place and return tghe
112    length of the valid buffer. */
113 static size_t
114 percent_plus_unescape (unsigned char *string)
115 {
116   unsigned char *p = string;
117   size_t n = 0;
118
119   while (*string)
120     {
121       if (*string == '%' && string[1] && string[2])
122         { 
123           string++;
124           *p++ = xtoi_2 (string);
125           n++;
126           string+= 2;
127         }
128       else if (*string == '+')
129         {
130           *p++ = ' ';
131           n++;
132           string++;
133         }
134       else
135         {
136           *p++ = *string++;
137           n++;
138         }
139     }
140
141   return n;
142 }
143
144
145
146 /* SERIALNO 
147
148    Return the serial number of the card using a status reponse.  This
149    functon should be used to check for the presence of a card.
150
151    This function is special in that it can be used to reset the card.
152    Most other functions will return an error when a card change has
153    been detected and the use of this function is therefore required.
154
155    Background: We want to keep the client clear of handling card
156    changes between operations; i.e. the client can assume that all
157    operations are done on the same card unless he calls this function.
158  */
159 static int
160 cmd_serialno (ASSUAN_CONTEXT ctx, char *line)
161 {
162   CTRL ctrl = assuan_get_pointer (ctx);
163   int rc = 0;
164   char *serial_and_stamp;
165   char *serial;
166   time_t stamp;
167
168   if ((rc = open_card (ctrl)))
169     return rc;
170
171   if (ctrl->app_ctx)
172     rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
173   else
174     rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp);
175   if (rc)
176     return map_to_assuan_status (rc);
177   rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp);
178   xfree (serial);
179   if (rc < 0)
180     return ASSUAN_Out_Of_Core;
181   rc = 0;
182   assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
183   free (serial_and_stamp);
184   return 0;
185 }
186
187
188
189
190 /* LEARN [--force]
191
192    Learn all useful information of the currently inserted card.  When
193    used without the force options, the command might do an INQUIRE
194    like this:
195
196       INQUIRE KNOWNCARDP <hexstring_with_serialNumber> <timestamp>
197
198    The client should just send an "END" if the processing should go on
199    or a "CANCEL" to force the function to terminate with a Cancel
200    error message.  The response of this command is a list of status
201    lines formatted as this:
202
203      S APPTYPE <apptype>
204
205    This returns the type of the application, currently the strings:
206
207        P15     = PKCS-15 structure used
208        DINSIG  = DIN SIG
209        OPENPGP = OpenPGP card
210  
211    are implemented.  These strings are aliases for the AID
212
213      S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id>
214
215    If there is no certificate yet stored on the card a single "X" is
216    returned as the keygrip.  In addition to the keypair info, information
217    about all certificates stored on the card is also returned:
218
219      S CERTINFO <certtype> <hexstring_with_id>
220
221    Where CERTTYPE is a number indicating the type of certificate:
222       0   := Unknown
223       100 := Regular X.509 cert
224       101 := Trusted X.509 cert
225       102 := Useful X.509 cert
226
227    For certain cards, more information will be returned:
228
229      S KEY-FPR <no> <hexstring>
230
231    For OpenPGP cards this returns the stored fingerprints of the
232    keys. This can be used check whether a key is available on the
233    card.  NO may be 1, 2 or 3.
234
235      S CA-FPR <no> <hexstring>
236
237    Similar to above, these are the fingerprints of keys assumed to be
238    ultimately trusted.
239
240      S DISP-NAME <name_of_card_holder>
241
242    The name of the card holder as stored on the card; percent
243    aescaping takes place, spaces are encoded as '+'
244
245      S PUBKEY-URL <url>
246
247    The URL to be used for locating the entire public key.
248      
249 */
250 static int
251 cmd_learn (ASSUAN_CONTEXT ctx, char *line)
252 {
253   CTRL ctrl = assuan_get_pointer (ctx);
254   int rc = 0;
255   int idx;
256
257   if ((rc = open_card (ctrl)))
258     return rc;
259
260   /* Unless the force option is used we try a shortcut by identifying
261      the card using a serial number and inquiring the client with
262      that. The client may choose to cancel the operation if he already
263      knows about this card */
264   {
265     char *serial_and_stamp;
266     char *serial;
267     time_t stamp;
268
269     if (ctrl->app_ctx)
270       rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
271     else
272       rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp);
273     if (rc)
274       return map_to_assuan_status (rc);
275     rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp);
276     xfree (serial);
277     if (rc < 0)
278       return ASSUAN_Out_Of_Core;
279     rc = 0;
280     assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
281
282     if (!has_option (line, "--force"))
283       {
284         char *command;
285
286         rc = asprintf (&command, "KNOWNCARDP %s", serial_and_stamp);
287         if (rc < 0)
288           {
289             free (serial_and_stamp);
290             return ASSUAN_Out_Of_Core;
291           }
292         rc = 0;
293         rc = assuan_inquire (ctx, command, NULL, NULL, 0); 
294         free (command);  /* (must use standard free here) */
295         if (rc)
296           {
297             if (rc != ASSUAN_Canceled)
298               log_error ("inquire KNOWNCARDP failed: %s\n",
299                          assuan_strerror (rc));
300             free (serial_and_stamp);
301             return rc; 
302           }
303         /* not canceled, so we have to proceeed */
304       }
305     free (serial_and_stamp);
306   }
307
308   /* Return information about the certificates. */
309   if (ctrl->app_ctx)
310     rc = -1; /* This information is not yet available for applications. */
311   for (idx=0; !rc; idx++)
312     {
313       char *certid;
314       int certtype;
315
316       rc = card_enum_certs (ctrl->card_ctx, idx, &certid, &certtype);
317       if (!rc)
318         {
319           char *buf;
320
321           buf = xtrymalloc (40 + 1 + strlen (certid) + 1);
322           if (!buf)
323             rc = out_of_core ();
324           else
325             {
326               sprintf (buf, "%d %s", certtype, certid);
327               assuan_write_status (ctx, "CERTINFO", buf);
328               xfree (buf);
329             }
330         }
331       xfree (certid);
332     }
333   if (rc == -1)
334     rc = 0;
335
336
337   /* Return information about the keys. */
338   if (ctrl->app_ctx)
339     rc = -1; /* This information is not yet available for applications. */
340   for (idx=0; !rc; idx++)
341     {
342       unsigned char keygrip[20];
343       char *keyid;
344       int no_cert = 0;
345
346       rc = card_enum_keypairs (ctrl->card_ctx, idx, keygrip, &keyid);
347       if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT && keyid)
348         {
349           /* this does happen with an incomplete personalized
350              card; i.e. during the time we have stored the key on the
351              card but not stored the certificate; probably becuase it
352              has not yet been received back from the CA.  Note that we
353              must release KEYID in this case. */
354           rc = 0; 
355           no_cert = 1;
356         }
357       if (!rc)
358         {
359           char *buf, *p;
360
361           buf = p = xtrymalloc (40 + 1 + strlen (keyid) + 1);
362           if (!buf)
363             rc = out_of_core ();
364           else
365             {
366               int i;
367               
368               if (no_cert)
369                 *p++ = 'X';
370               else
371                 {
372                   for (i=0; i < 20; i++, p += 2)
373                     sprintf (p, "%02X", keygrip[i]);
374                 }
375               *p++ = ' ';
376               strcpy (p, keyid);
377               assuan_write_status (ctx, "KEYPAIRINFO", buf);
378               xfree (buf);
379             }
380         }
381       xfree (keyid);
382     }
383   if (rc == -1)
384     rc = 0;
385
386   if (!rc && ctrl->app_ctx)
387     rc = app_write_learn_status (ctrl->app_ctx, ctrl);
388
389
390   return map_to_assuan_status (rc);
391 }
392
393
394 \f
395 /* READCERT <hexified_certid>
396
397  */
398 static int
399 cmd_readcert (ASSUAN_CONTEXT ctx, char *line)
400 {
401   CTRL ctrl = assuan_get_pointer (ctx);
402   int rc;
403   unsigned char *cert;
404   size_t ncert;
405
406   if ((rc = open_card (ctrl)))
407     return rc;
408
409   if (ctrl->app_ctx)
410     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
411
412   rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert);
413   if (rc)
414     {
415       log_error ("card_read_cert failed: %s\n", gpg_strerror (rc));
416     }
417   if (!rc)
418     {
419       rc = assuan_send_data (ctx, cert, ncert);
420       xfree (cert);
421       if (rc)
422         return rc;
423     }
424
425   return map_to_assuan_status (rc);
426 }
427
428
429 /* READKEY <hexified_certid>
430
431    Return the public key for the given cert or key ID as an standard
432    S-Expression.  */
433 static int
434 cmd_readkey (ASSUAN_CONTEXT ctx, char *line)
435 {
436   CTRL ctrl = assuan_get_pointer (ctx);
437   int rc;
438   unsigned char *cert = NULL;
439   size_t ncert, n;
440   KsbaCert kc = NULL;
441   KsbaSexp p;
442
443   if ((rc = open_card (ctrl)))
444     return rc;
445
446   if (ctrl->app_ctx)
447     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
448
449   rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert);
450   if (rc)
451     {
452       log_error ("card_read_cert failed: %s\n", gpg_strerror (rc));
453       goto leave;
454     }
455       
456   rc = ksba_cert_new (&kc);
457   if (rc)
458     {
459       xfree (cert);
460       goto leave;
461     }
462   rc = ksba_cert_init_from_mem (kc, cert, ncert);
463   if (rc)
464     {
465       log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
466       goto leave;
467     }
468
469   p = ksba_cert_get_public_key (kc);
470   if (!p)
471     {
472       rc = gpg_error (GPG_ERR_NO_PUBKEY);
473       goto leave;
474     }
475
476   n = gcry_sexp_canon_len (p, 0, NULL, NULL);
477   rc = assuan_send_data (ctx, p, n);
478   rc = map_assuan_err (rc);
479   xfree (p);
480
481
482  leave:
483   ksba_cert_release (kc);
484   xfree (cert);
485   return map_to_assuan_status (rc);
486 }
487
488
489 \f
490
491 /* SETDATA <hexstring> 
492
493    The client should use this command to tell us the data he want to
494    sign.  */
495 static int
496 cmd_setdata (ASSUAN_CONTEXT ctx, char *line)
497 {
498   CTRL ctrl = assuan_get_pointer (ctx);
499   int n;
500   char *p;
501   unsigned char *buf;
502
503   /* parse the hexstring */
504   for (p=line,n=0; hexdigitp (p); p++, n++)
505     ;
506   if (*p)
507     return set_error (Parameter_Error, "invalid hexstring");
508   if (!n)
509     return set_error (Parameter_Error, "no data given");
510   if ((n&1))
511     return set_error (Parameter_Error, "odd number of digits");
512   n /= 2;
513   buf = xtrymalloc (n);
514   if (!buf)
515     return ASSUAN_Out_Of_Core;
516
517   ctrl->in_data.value = buf;
518   ctrl->in_data.valuelen = n;
519   for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++)
520     buf[n] = xtoi_2 (p);
521   return 0;
522 }
523
524
525
526 static int 
527 pin_cb (void *opaque, const char *info, char **retstr)
528 {
529   ASSUAN_CONTEXT ctx = opaque;
530   char *command;
531   int rc;
532   unsigned char *value;
533   size_t valuelen;
534
535   *retstr = NULL;
536   log_debug ("asking for PIN '%s'\n", info);
537
538   rc = asprintf (&command, "NEEDPIN %s", info);
539   if (rc < 0)
540     return out_of_core ();
541
542   /* FIXME: Write an inquire function which returns the result in
543      secure memory */
544   rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); 
545   free (command);  
546   if (rc)
547     return map_assuan_err (rc);
548
549   if (!valuelen || value[valuelen-1])
550     {
551       /* We require that the returned value is an UTF-8 string */
552       xfree (value);
553       return gpg_error (GPG_ERR_INV_RESPONSE);
554     }
555   *retstr = value;
556   return 0;
557 }
558
559
560 /* PKSIGN <hexified_id>
561
562  */
563 static int
564 cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
565 {
566   CTRL ctrl = assuan_get_pointer (ctx);
567   int rc;
568   unsigned char *outdata;
569   size_t outdatalen;
570   char *keyidstr;
571
572   if ((rc = open_card (ctrl)))
573     return rc;
574
575   /* We have to use a copy of the key ID because the function may use
576      the pin_cb which in turn uses the assuan line buffer and thus
577      overwriting the original line with the keyid */
578   keyidstr = xtrystrdup (line);
579   if (!keyidstr)
580     return ASSUAN_Out_Of_Core;
581   
582   if (ctrl->app_ctx)
583     rc = app_sign (ctrl->app_ctx,
584                     keyidstr, GCRY_MD_SHA1,
585                     pin_cb, ctx,
586                     ctrl->in_data.value, ctrl->in_data.valuelen,
587                     &outdata, &outdatalen);
588   else  
589     rc = card_sign (ctrl->card_ctx,
590                     keyidstr, GCRY_MD_SHA1,
591                     pin_cb, ctx,
592                     ctrl->in_data.value, ctrl->in_data.valuelen,
593                     &outdata, &outdatalen);
594   xfree (keyidstr);
595   if (rc)
596     {
597       log_error ("card_sign failed: %s\n", gpg_strerror (rc));
598     }
599   else
600     {
601       rc = assuan_send_data (ctx, outdata, outdatalen);
602       xfree (outdata);
603       if (rc)
604         return rc; /* that is already an assuan error code */
605     }
606
607   return map_to_assuan_status (rc);
608 }
609
610 /* PKAUTH <hexified_id>
611
612  */
613 static int
614 cmd_pkauth (ASSUAN_CONTEXT ctx, char *line)
615 {
616   CTRL ctrl = assuan_get_pointer (ctx);
617   int rc;
618   unsigned char *outdata;
619   size_t outdatalen;
620   char *keyidstr;
621
622   if ((rc = open_card (ctrl)))
623     return rc;
624
625   if (!ctrl->app_ctx)
626     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
627
628   /* We have to use a copy of the key ID because the function may use
629      the pin_cb which in turn uses the assuan line buffer and thus
630      overwriting the original line with the keyid */
631   keyidstr = xtrystrdup (line);
632   if (!keyidstr)
633     return ASSUAN_Out_Of_Core;
634   
635   rc = app_auth (ctrl->app_ctx,
636                  keyidstr,
637                  pin_cb, ctx,
638                  ctrl->in_data.value, ctrl->in_data.valuelen,
639                  &outdata, &outdatalen);
640   xfree (keyidstr);
641   if (rc)
642     {
643       log_error ("app_auth_sign failed: %s\n", gpg_strerror (rc));
644     }
645   else
646     {
647       rc = assuan_send_data (ctx, outdata, outdatalen);
648       xfree (outdata);
649       if (rc)
650         return rc; /* that is already an assuan error code */
651     }
652
653   return map_to_assuan_status (rc);
654 }
655
656 /* PKDECRYPT <hexified_id>
657
658  */
659 static int
660 cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
661 {
662   CTRL ctrl = assuan_get_pointer (ctx);
663   int rc;
664   unsigned char *outdata;
665   size_t outdatalen;
666   char *keyidstr;
667
668   if ((rc = open_card (ctrl)))
669     return rc;
670
671   keyidstr = xtrystrdup (line);
672   if (!keyidstr)
673     return ASSUAN_Out_Of_Core;
674   if (ctrl->app_ctx)
675     rc = app_decipher (ctrl->app_ctx,
676                         keyidstr, 
677                         pin_cb, ctx,
678                         ctrl->in_data.value, ctrl->in_data.valuelen,
679                         &outdata, &outdatalen);
680   else
681     rc = card_decipher (ctrl->card_ctx,
682                         keyidstr, 
683                         pin_cb, ctx,
684                         ctrl->in_data.value, ctrl->in_data.valuelen,
685                         &outdata, &outdatalen);
686   xfree (keyidstr);
687   if (rc)
688     {
689       log_error ("card_create_signature failed: %s\n", gpg_strerror (rc));
690     }
691   else
692     {
693       rc = assuan_send_data (ctx, outdata, outdatalen);
694       xfree (outdata);
695       if (rc)
696         return rc; /* that is already an assuan error code */
697     }
698
699   return map_to_assuan_status (rc);
700 }
701
702
703 /* GETATTR <name>
704
705    This command is used to retrieve data from a smartcard.  The
706    allowed names depend on the currently selected smartcard
707    application.  NAME must be percent and '+' escaped.  The value is
708    returned through status message, see the LESRN command for details.
709
710    However, the current implementation assumes that Name is not escaped;
711    this works as long as noone uses arbitrary escaping. 
712  
713 */
714 static int
715 cmd_getattr (ASSUAN_CONTEXT ctx, char *line)
716 {
717   CTRL ctrl = assuan_get_pointer (ctx);
718   int rc;
719   char *keyword;
720
721   if ((rc = open_card (ctrl)))
722     return rc;
723
724   keyword = line;
725   for (; *line && !spacep (line); line++)
726     ;
727   if (*line)
728       *line++ = 0;
729
730   /* (We ignore any garbage for now.) */
731
732   rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
733
734   return map_to_assuan_status (rc);
735 }
736
737
738 /* SETATTR <name> <value> 
739
740    This command is used to store data on a a smartcard.  The allowed
741    names and values are depend on the currently selected smartcard
742    application.  NAME and VALUE must be percent and '+' escaped.
743
744    However, the curent implementation assumes that Name is not escaped;
745    this works as long as noone uses arbitrary escaping. 
746  
747    A PIN will be requested for most NAMEs.  See the corresponding
748    setattr function of the actually used application (app-*.c) for
749    details.  */
750 static int
751 cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line)
752 {
753   CTRL ctrl = assuan_get_pointer (ctx);
754   int rc;
755   char *keyword;
756   int keywordlen;
757   size_t nbytes;
758   char *line, *linebuf;
759
760   if ((rc = open_card (ctrl)))
761     return rc;
762
763   /* We need to use a copy of LINE, because PIN_CB uses the same
764      context and thus reuses the Assuan provided LINE. */
765   line = linebuf = xtrystrdup (orig_line);
766   if (!line)
767     return ASSUAN_Out_Of_Core;
768
769   keyword = line;
770   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
771     ;
772   if (*line)
773       *line++ = 0;
774   while (spacep (line))
775     line++;
776   nbytes = percent_plus_unescape (line);
777
778   rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx, line, nbytes);
779   xfree (linebuf);
780
781   return map_to_assuan_status (rc);
782 }
783
784 /* GENKEY [--force] <no>
785
786    Generate a key on-card identified by NO, which is application
787    specific.  Return values are application specific.  For OpenPGP
788    cards 2 status lines are returned:
789
790      S KEY-FPR  <hexstring>
791      S KEY-CREATED-AT <seconds_since_epoch>
792      S KEY-DATA [p|n] <hexdata>
793      
794
795    --force is required to overwriet an already existing key.  The
796    KEY-CREATED-AT is required for further processing because it is
797    part of the hashed key material for the fingerprint.
798
799    The public part of the key can also later be retrieved using the
800    READKEY command.
801
802  */
803 static int
804 cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
805 {
806   CTRL ctrl = assuan_get_pointer (ctx);
807   int rc;
808   char *keyno;
809   int force = has_option (line, "--force");
810
811   /* Skip over options. */
812   while ( *line == '-' && line[1] == '-' )
813     {
814       while (*line && !spacep (line))
815         line++;
816       while (spacep (line))
817         line++;
818     }
819   if (!*line)
820     return set_error (Parameter_Error, "no key number given");
821   keyno = line;
822   while (*line && !spacep (line))
823     line++;
824   *line = 0;
825
826   if ((rc = open_card (ctrl)))
827     return rc;
828
829   if (!ctrl->app_ctx)
830     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
831
832   keyno = xtrystrdup (keyno);
833   if (!keyno)
834     return ASSUAN_Out_Of_Core;
835   rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0, pin_cb, ctx);
836   xfree (keyno);
837   return map_to_assuan_status (rc);
838 }
839
840
841 /* RANDOM <nbytes>
842
843    Get NBYTES of random from the card and send them back as data. 
844 */
845 static int
846 cmd_random (ASSUAN_CONTEXT ctx, char *line)
847 {
848   CTRL ctrl = assuan_get_pointer (ctx);
849   int rc;
850   size_t nbytes;
851   unsigned char *buffer;
852
853   if (!*line)
854     return set_error (Parameter_Error, "number of requested bytes missing");
855   nbytes = strtoul (line, NULL, 0);
856
857   if ((rc = open_card (ctrl)))
858     return rc;
859
860   if (!ctrl->app_ctx)
861     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
862
863   buffer = xtrymalloc (nbytes);
864   if (!buffer)
865     return ASSUAN_Out_Of_Core;
866
867   rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
868   if (!rc)
869     {
870       rc = assuan_send_data (ctx, buffer, nbytes);
871       xfree (buffer);
872       return rc; /* that is already an assuan error code */
873     }
874   xfree (buffer);
875
876   return map_to_assuan_status (rc);
877 }
878
879 \f
880 /* PASSWD [--reset] <chvno>
881   
882    Change the PIN or reset thye retry counter of the card holder
883    verfication vector CHVNO. */
884 static int
885 cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
886 {
887   CTRL ctrl = assuan_get_pointer (ctx);
888   int rc;
889   char *chvnostr;
890   int reset_mode = has_option (line, "--reset");
891
892   /* Skip over options. */
893   while (*line == '-' && line[1] == '-')
894     {
895       while (*line && !spacep (line))
896         line++;
897       while (spacep (line))
898         line++;
899     }
900   if (!*line)
901     return set_error (Parameter_Error, "no CHV number given");
902   chvnostr = line;
903   while (*line && !spacep (line))
904     line++;
905   *line = 0;
906
907   if ((rc = open_card (ctrl)))
908     return rc;
909
910   if (!ctrl->app_ctx)
911     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
912   
913   chvnostr = xtrystrdup (chvnostr);
914   if (!chvnostr)
915     return ASSUAN_Out_Of_Core;
916   rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, reset_mode, pin_cb, ctx);
917   if (rc)
918     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
919   xfree (chvnostr);
920   return map_to_assuan_status (rc);
921 }
922
923
924 /* CHECKPIN <hexified_id>
925
926  */
927 static int
928 cmd_checkpin (ASSUAN_CONTEXT ctx, char *line)
929 {
930   CTRL ctrl = assuan_get_pointer (ctx);
931   int rc;
932   char *keyidstr;
933
934   if ((rc = open_card (ctrl)))
935     return rc;
936
937   if (!ctrl->app_ctx)
938     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
939
940   /* We have to use a copy of the key ID because the function may use
941      the pin_cb which in turn uses the assuan line buffer and thus
942      overwriting the original line with the keyid. */
943   keyidstr = xtrystrdup (line);
944   if (!keyidstr)
945     return ASSUAN_Out_Of_Core;
946   
947   rc = app_check_pin (ctrl->app_ctx,
948                       keyidstr,
949                       pin_cb, ctx);
950   xfree (keyidstr);
951   if (rc)
952     log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
953
954   return map_to_assuan_status (rc);
955 }
956
957
958
959
960 \f
961 /* Tell the assuan library about our commands */
962 static int
963 register_commands (ASSUAN_CONTEXT ctx)
964 {
965   static struct {
966     const char *name;
967     int (*handler)(ASSUAN_CONTEXT, char *line);
968   } table[] = {
969     { "SERIALNO",     cmd_serialno },
970     { "LEARN",        cmd_learn },
971     { "READCERT",     cmd_readcert },
972     { "READKEY",      cmd_readkey },
973     { "SETDATA",      cmd_setdata },
974     { "PKSIGN",       cmd_pksign },
975     { "PKAUTH",       cmd_pkauth },
976     { "PKDECRYPT",    cmd_pkdecrypt },
977     { "INPUT",        NULL }, 
978     { "OUTPUT",       NULL }, 
979     { "GETATTR",      cmd_getattr },
980     { "SETATTR",      cmd_setattr },
981     { "GENKEY",       cmd_genkey },
982     { "RANDOM",       cmd_random },
983     { "PASSWD",       cmd_passwd },
984     { "CHECKPIN",     cmd_checkpin },
985     { NULL }
986   };
987   int i, rc;
988
989   for (i=0; table[i].name; i++)
990     {
991       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
992       if (rc)
993         return rc;
994     } 
995   assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
996
997   assuan_register_reset_notify (ctx, reset_notify);
998   assuan_register_option_handler (ctx, option_handler);
999   return 0;
1000 }
1001
1002
1003 /* Startup the server.  If LISTEN_FD is given as -1, this is simple
1004    piper server, otherwise it is a regular server */
1005 void
1006 scd_command_handler (int listen_fd)
1007 {
1008   int rc;
1009   ASSUAN_CONTEXT ctx;
1010   struct server_control_s ctrl;
1011
1012   memset (&ctrl, 0, sizeof ctrl);
1013   scd_init_default_ctrl (&ctrl);
1014   
1015   if (listen_fd == -1)
1016     {
1017       int filedes[2];
1018
1019       filedes[0] = 0;
1020       filedes[1] = 1;
1021       rc = assuan_init_pipe_server (&ctx, filedes);
1022     }
1023   else
1024     {
1025       rc = assuan_init_socket_server (&ctx, listen_fd);
1026     }
1027   if (rc)
1028     {
1029       log_error ("failed to initialize the server: %s\n",
1030                  assuan_strerror(rc));
1031       scd_exit (2);
1032     }
1033   rc = register_commands (ctx);
1034   if (rc)
1035     {
1036       log_error ("failed to register commands with Assuan: %s\n",
1037                  assuan_strerror(rc));
1038       scd_exit (2);
1039     }
1040   assuan_set_pointer (ctx, &ctrl);
1041   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
1042   ctrl.server_local->assuan_ctx = ctx;
1043
1044   if (DBG_ASSUAN)
1045     assuan_set_log_stream (ctx, log_get_stream ());
1046
1047   for (;;)
1048     {
1049       rc = assuan_accept (ctx);
1050       if (rc == -1)
1051         {
1052           break;
1053         }
1054       else if (rc)
1055         {
1056           log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
1057           break;
1058         }
1059       
1060       rc = assuan_process (ctx);
1061       if (rc)
1062         {
1063           log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
1064           continue;
1065         }
1066     }
1067   reset_notify (ctx); /* used for cleanup */
1068
1069   assuan_deinit_server (ctx);
1070 }
1071
1072
1073 /* Send a line with status information via assuan and escape all given
1074    buffers. The variable elements are pairs of (char *, size_t),
1075    terminated with a (NULL, 0). */
1076 void
1077 send_status_info (CTRL ctrl, const char *keyword, ...)
1078 {
1079   va_list arg_ptr;
1080   const unsigned char *value;
1081   size_t valuelen;
1082   char buf[950], *p;
1083   size_t n;
1084   ASSUAN_CONTEXT ctx = ctrl->server_local->assuan_ctx;
1085   
1086   va_start (arg_ptr, keyword);
1087
1088   p = buf; 
1089   n = 0;
1090   while ( (value = va_arg (arg_ptr, const unsigned char *)) )
1091     {
1092       valuelen = va_arg (arg_ptr, size_t);
1093       if (!valuelen)
1094         continue; /* empty buffer */
1095       if (n)
1096         {
1097           *p++ = ' ';
1098           n++;
1099         }
1100       for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
1101         {
1102           if (*value < ' ' || *value == '+')
1103             {
1104               sprintf (p, "%%%02X", *value);
1105               p += 3;
1106             }
1107           else if (*value == ' ')
1108             *p++ = '+';
1109           else
1110             *p++ = *value;
1111         }
1112     }
1113   *p = 0;
1114   assuan_write_status (ctx, keyword, buf);
1115
1116   va_end (arg_ptr);
1117 }
1118