* command.c (cmd_checkpin): New.
[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 #include <ksba.h>
29
30 #include <assuan.h>
31
32 #include "scdaemon.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   kc = ksba_cert_new ();
457   if (!kc)
458     {
459       rc = out_of_core ();
460       xfree (cert);
461       goto leave;
462     }
463   rc = ksba_cert_init_from_mem (kc, cert, ncert);
464   if (rc)
465     {
466       log_error ("failed to parse the certificate: %s\n", ksba_strerror (rc));
467       rc = map_ksba_err (rc);
468       goto leave;
469     }
470
471   p = ksba_cert_get_public_key (kc);
472   if (!p)
473     {
474       rc = gpg_error (GPG_ERR_NO_PUBKEY);
475       goto leave;
476     }
477
478   n = gcry_sexp_canon_len (p, 0, NULL, NULL);
479   rc = assuan_send_data (ctx, p, n);
480   rc = map_assuan_err (rc);
481   xfree (p);
482
483
484  leave:
485   ksba_cert_release (kc);
486   xfree (cert);
487   return map_to_assuan_status (rc);
488 }
489
490
491 \f
492
493 /* SETDATA <hexstring> 
494
495    The client should use this command to tell us the data he want to
496    sign.  */
497 static int
498 cmd_setdata (ASSUAN_CONTEXT ctx, char *line)
499 {
500   CTRL ctrl = assuan_get_pointer (ctx);
501   int n;
502   char *p;
503   unsigned char *buf;
504
505   /* parse the hexstring */
506   for (p=line,n=0; hexdigitp (p); p++, n++)
507     ;
508   if (*p)
509     return set_error (Parameter_Error, "invalid hexstring");
510   if (!n)
511     return set_error (Parameter_Error, "no data given");
512   if ((n&1))
513     return set_error (Parameter_Error, "odd number of digits");
514   n /= 2;
515   buf = xtrymalloc (n);
516   if (!buf)
517     return ASSUAN_Out_Of_Core;
518
519   ctrl->in_data.value = buf;
520   ctrl->in_data.valuelen = n;
521   for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++)
522     buf[n] = xtoi_2 (p);
523   return 0;
524 }
525
526
527
528 static int 
529 pin_cb (void *opaque, const char *info, char **retstr)
530 {
531   ASSUAN_CONTEXT ctx = opaque;
532   char *command;
533   int rc;
534   char *value;
535   size_t valuelen;
536
537   *retstr = NULL;
538   log_debug ("asking for PIN '%s'\n", info);
539
540   rc = asprintf (&command, "NEEDPIN %s", info);
541   if (rc < 0)
542     return out_of_core ();
543
544   /* FIXME: Write an inquire function which returns the result in
545      secure memory */
546   rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); 
547   free (command);  
548   if (rc)
549     return map_assuan_err (rc);
550
551   if (!valuelen || value[valuelen-1])
552     {
553       /* We require that the returned value is an UTF-8 string */
554       xfree (value);
555       return gpg_error (GPG_ERR_INV_RESPONSE);
556     }
557   *retstr = value;
558   return 0;
559 }
560
561
562 /* PKSIGN <hexified_id>
563
564  */
565 static int
566 cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
567 {
568   CTRL ctrl = assuan_get_pointer (ctx);
569   int rc;
570   unsigned char *outdata;
571   size_t outdatalen;
572   char *keyidstr;
573
574   if ((rc = open_card (ctrl)))
575     return rc;
576
577   /* We have to use a copy of the key ID because the function may use
578      the pin_cb which in turn uses the assuan line buffer and thus
579      overwriting the original line with the keyid */
580   keyidstr = xtrystrdup (line);
581   if (!keyidstr)
582     return ASSUAN_Out_Of_Core;
583   
584   if (ctrl->app_ctx)
585     rc = app_sign (ctrl->app_ctx,
586                     keyidstr, GCRY_MD_SHA1,
587                     pin_cb, ctx,
588                     ctrl->in_data.value, ctrl->in_data.valuelen,
589                     &outdata, &outdatalen);
590   else  
591     rc = card_sign (ctrl->card_ctx,
592                     keyidstr, GCRY_MD_SHA1,
593                     pin_cb, ctx,
594                     ctrl->in_data.value, ctrl->in_data.valuelen,
595                     &outdata, &outdatalen);
596   xfree (keyidstr);
597   if (rc)
598     {
599       log_error ("card_sign failed: %s\n", gpg_strerror (rc));
600     }
601   else
602     {
603       rc = assuan_send_data (ctx, outdata, outdatalen);
604       xfree (outdata);
605       if (rc)
606         return rc; /* that is already an assuan error code */
607     }
608
609   return map_to_assuan_status (rc);
610 }
611
612 /* PKAUTH <hexified_id>
613
614  */
615 static int
616 cmd_pkauth (ASSUAN_CONTEXT ctx, char *line)
617 {
618   CTRL ctrl = assuan_get_pointer (ctx);
619   int rc;
620   unsigned char *outdata;
621   size_t outdatalen;
622   char *keyidstr;
623
624   if ((rc = open_card (ctrl)))
625     return rc;
626
627   if (!ctrl->app_ctx)
628     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
629
630   /* We have to use a copy of the key ID because the function may use
631      the pin_cb which in turn uses the assuan line buffer and thus
632      overwriting the original line with the keyid */
633   keyidstr = xtrystrdup (line);
634   if (!keyidstr)
635     return ASSUAN_Out_Of_Core;
636   
637   rc = app_auth (ctrl->app_ctx,
638                  keyidstr,
639                  pin_cb, ctx,
640                  ctrl->in_data.value, ctrl->in_data.valuelen,
641                  &outdata, &outdatalen);
642   xfree (keyidstr);
643   if (rc)
644     {
645       log_error ("app_auth_sign failed: %s\n", gpg_strerror (rc));
646     }
647   else
648     {
649       rc = assuan_send_data (ctx, outdata, outdatalen);
650       xfree (outdata);
651       if (rc)
652         return rc; /* that is already an assuan error code */
653     }
654
655   return map_to_assuan_status (rc);
656 }
657
658 /* PKDECRYPT <hexified_id>
659
660  */
661 static int
662 cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
663 {
664   CTRL ctrl = assuan_get_pointer (ctx);
665   int rc;
666   unsigned char *outdata;
667   size_t outdatalen;
668   char *keyidstr;
669
670   if ((rc = open_card (ctrl)))
671     return rc;
672
673   keyidstr = xtrystrdup (line);
674   if (!keyidstr)
675     return ASSUAN_Out_Of_Core;
676   if (ctrl->app_ctx)
677     rc = app_decipher (ctrl->app_ctx,
678                         keyidstr, 
679                         pin_cb, ctx,
680                         ctrl->in_data.value, ctrl->in_data.valuelen,
681                         &outdata, &outdatalen);
682   else
683     rc = card_decipher (ctrl->card_ctx,
684                         keyidstr, 
685                         pin_cb, ctx,
686                         ctrl->in_data.value, ctrl->in_data.valuelen,
687                         &outdata, &outdatalen);
688   xfree (keyidstr);
689   if (rc)
690     {
691       log_error ("card_create_signature failed: %s\n", gpg_strerror (rc));
692     }
693   else
694     {
695       rc = assuan_send_data (ctx, outdata, outdatalen);
696       xfree (outdata);
697       if (rc)
698         return rc; /* that is already an assuan error code */
699     }
700
701   return map_to_assuan_status (rc);
702 }
703
704
705 /* GETATTR <name>
706
707    This command is used to retrieve data from a smartcard.  The
708    allowed names depend on the currently selected smartcard
709    application.  NAME must be percent and '+' escaped.  The value is
710    returned through status message, see the LESRN command for details.
711
712    However, the current implementation assumes that Name is not escaped;
713    this works as long as noone uses arbitrary escaping. 
714  
715 */
716 static int
717 cmd_getattr (ASSUAN_CONTEXT ctx, char *line)
718 {
719   CTRL ctrl = assuan_get_pointer (ctx);
720   int rc;
721   char *keyword;
722
723   if ((rc = open_card (ctrl)))
724     return rc;
725
726   keyword = line;
727   for (; *line && !spacep (line); line++)
728     ;
729   if (*line)
730       *line++ = 0;
731
732   /* (We ignore any garbage for now.) */
733
734   rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
735
736   return map_to_assuan_status (rc);
737 }
738
739
740 /* SETATTR <name> <value> 
741
742    This command is used to store data on a a smartcard.  The allowed
743    names and values are depend on the currently selected smartcard
744    application.  NAME and VALUE must be percent and '+' escaped.
745
746    However, the curent implementation assumes that Name is not escaped;
747    this works as long as noone uses arbitrary escaping. 
748  
749    A PIN will be requested for most NAMEs.  See the corresponding
750    setattr function of the actually used application (app-*.c) for
751    details.  */
752 static int
753 cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line)
754 {
755   CTRL ctrl = assuan_get_pointer (ctx);
756   int rc;
757   char *keyword;
758   int keywordlen;
759   size_t nbytes;
760   char *line, *linebuf;
761
762   if ((rc = open_card (ctrl)))
763     return rc;
764
765   /* We need to use a copy of LINE, because PIN_CB uses the same
766      context and thus reuses the Assuan provided LINE. */
767   line = linebuf = xtrystrdup (orig_line);
768   if (!line)
769     return ASSUAN_Out_Of_Core;
770
771   keyword = line;
772   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
773     ;
774   if (*line)
775       *line++ = 0;
776   while (spacep (line))
777     line++;
778   nbytes = percent_plus_unescape (line);
779
780   rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx, line, nbytes);
781   xfree (linebuf);
782
783   return map_to_assuan_status (rc);
784 }
785
786 /* GENKEY [--force] <no>
787
788    Generate a key on-card identified by NO, which is application
789    specific.  Return values are application specific.  For OpenPGP
790    cards 2 status lines are returned:
791
792      S KEY-FPR  <hexstring>
793      S KEY-CREATED-AT <seconds_since_epoch>
794      S KEY-DATA [p|n] <hexdata>
795      
796
797    --force is required to overwriet an already existing key.  The
798    KEY-CREATED-AT is required for further processing because it is
799    part of the hashed key material for the fingerprint.
800
801    The public part of the key can also later be retrieved using the
802    READKEY command.
803
804  */
805 static int
806 cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
807 {
808   CTRL ctrl = assuan_get_pointer (ctx);
809   int rc;
810   char *keyno;
811   int force = has_option (line, "--force");
812
813   /* Skip over options. */
814   while ( *line == '-' && line[1] == '-' )
815     {
816       while (!spacep (line))
817         line++;
818       while (spacep (line))
819         line++;
820     }
821   if (!*line)
822     return set_error (Parameter_Error, "no key number given");
823   keyno = line;
824   while (!spacep (line))
825     line++;
826   *line = 0;
827
828   if ((rc = open_card (ctrl)))
829     return rc;
830
831   if (!ctrl->app_ctx)
832     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
833
834   keyno = xtrystrdup (keyno);
835   if (!keyno)
836     return ASSUAN_Out_Of_Core;
837   rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0, pin_cb, ctx);
838   xfree (keyno);
839   return map_to_assuan_status (rc);
840 }
841
842
843 /* RANDOM <nbytes>
844
845    Get NBYTES of random from the card and send them back as data. 
846 */
847 static int
848 cmd_random (ASSUAN_CONTEXT ctx, char *line)
849 {
850   CTRL ctrl = assuan_get_pointer (ctx);
851   int rc;
852   size_t nbytes;
853   unsigned char *buffer;
854
855   if (!*line)
856     return set_error (Parameter_Error, "number of requested bytes missing");
857   nbytes = strtoul (line, NULL, 0);
858
859   if ((rc = open_card (ctrl)))
860     return rc;
861
862   if (!ctrl->app_ctx)
863     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
864
865   buffer = xtrymalloc (nbytes);
866   if (!buffer)
867     return ASSUAN_Out_Of_Core;
868
869   rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
870   if (!rc)
871     {
872       rc = assuan_send_data (ctx, buffer, nbytes);
873       xfree (buffer);
874       return rc; /* that is already an assuan error code */
875     }
876   xfree (buffer);
877
878   return map_to_assuan_status (rc);
879 }
880
881 \f
882 /* PASSWD [--reset] <chvno>
883   
884    Change the PIN or reset thye retry counter of the card holder
885    verfication vector CHVNO. */
886 static int
887 cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
888 {
889   CTRL ctrl = assuan_get_pointer (ctx);
890   int rc;
891   char *chvnostr;
892   int reset_mode = has_option (line, "--reset");
893
894   /* Skip over options. */
895   while (*line == '-' && line[1] == '-')
896     {
897       while (!spacep (line))
898         line++;
899       while (spacep (line))
900         line++;
901     }
902   if (!*line)
903     return set_error (Parameter_Error, "no CHV number given");
904   chvnostr = line;
905   while (!spacep (line))
906     line++;
907   *line = 0;
908
909   if ((rc = open_card (ctrl)))
910     return rc;
911
912   if (!ctrl->app_ctx)
913     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
914   
915   chvnostr = xtrystrdup (chvnostr);
916   if (!chvnostr)
917     return ASSUAN_Out_Of_Core;
918   rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, reset_mode, pin_cb, ctx);
919   if (rc)
920     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
921   xfree (chvnostr);
922   return map_to_assuan_status (rc);
923 }
924
925
926 /* CHECKPIN <hexified_id>
927
928  */
929 static int
930 cmd_checkpin (ASSUAN_CONTEXT ctx, char *line)
931 {
932   CTRL ctrl = assuan_get_pointer (ctx);
933   int rc;
934   char *keyidstr;
935
936   if ((rc = open_card (ctrl)))
937     return rc;
938
939   if (!ctrl->app_ctx)
940     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
941
942   /* We have to use a copy of the key ID because the function may use
943      the pin_cb which in turn uses the assuan line buffer and thus
944      overwriting the original line with the keyid. */
945   keyidstr = xtrystrdup (line);
946   if (!keyidstr)
947     return ASSUAN_Out_Of_Core;
948   
949   rc = app_check_pin (ctrl->app_ctx,
950                       keyidstr,
951                       pin_cb, ctx);
952   xfree (keyidstr);
953   if (rc)
954     log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
955
956   return map_to_assuan_status (rc);
957 }
958
959
960
961
962 \f
963 /* Tell the assuan library about our commands */
964 static int
965 register_commands (ASSUAN_CONTEXT ctx)
966 {
967   static struct {
968     const char *name;
969     int (*handler)(ASSUAN_CONTEXT, char *line);
970   } table[] = {
971     { "SERIALNO",     cmd_serialno },
972     { "LEARN",        cmd_learn },
973     { "READCERT",     cmd_readcert },
974     { "READKEY",      cmd_readkey },
975     { "SETDATA",      cmd_setdata },
976     { "PKSIGN",       cmd_pksign },
977     { "PKAUTH",       cmd_pkauth },
978     { "PKDECRYPT",    cmd_pkdecrypt },
979     { "INPUT",        NULL }, 
980     { "OUTPUT",       NULL }, 
981     { "GETATTR",      cmd_getattr },
982     { "SETATTR",      cmd_setattr },
983     { "GENKEY",       cmd_genkey },
984     { "RANDOM",       cmd_random },
985     { "PASSWD",       cmd_passwd },
986     { "CHECKPIN",     cmd_checkpin },
987     { NULL }
988   };
989   int i, rc;
990
991   for (i=0; table[i].name; i++)
992     {
993       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
994       if (rc)
995         return rc;
996     } 
997   assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
998
999   assuan_register_reset_notify (ctx, reset_notify);
1000   assuan_register_option_handler (ctx, option_handler);
1001   return 0;
1002 }
1003
1004
1005 /* Startup the server.  If LISTEN_FD is given as -1, this is simple
1006    piper server, otherwise it is a regular server */
1007 void
1008 scd_command_handler (int listen_fd)
1009 {
1010   int rc;
1011   ASSUAN_CONTEXT ctx;
1012   struct server_control_s ctrl;
1013
1014   memset (&ctrl, 0, sizeof ctrl);
1015   scd_init_default_ctrl (&ctrl);
1016   
1017   if (listen_fd == -1)
1018     {
1019       int filedes[2];
1020
1021       filedes[0] = 0;
1022       filedes[1] = 1;
1023       rc = assuan_init_pipe_server (&ctx, filedes);
1024     }
1025   else
1026     {
1027       rc = assuan_init_socket_server (&ctx, listen_fd);
1028     }
1029   if (rc)
1030     {
1031       log_error ("failed to initialize the server: %s\n",
1032                  assuan_strerror(rc));
1033       scd_exit (2);
1034     }
1035   rc = register_commands (ctx);
1036   if (rc)
1037     {
1038       log_error ("failed to register commands with Assuan: %s\n",
1039                  assuan_strerror(rc));
1040       scd_exit (2);
1041     }
1042   assuan_set_pointer (ctx, &ctrl);
1043   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
1044   ctrl.server_local->assuan_ctx = ctx;
1045
1046   if (DBG_ASSUAN)
1047     assuan_set_log_stream (ctx, log_get_stream ());
1048
1049   for (;;)
1050     {
1051       rc = assuan_accept (ctx);
1052       if (rc == -1)
1053         {
1054           break;
1055         }
1056       else if (rc)
1057         {
1058           log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
1059           break;
1060         }
1061       
1062       rc = assuan_process (ctx);
1063       if (rc)
1064         {
1065           log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
1066           continue;
1067         }
1068     }
1069   reset_notify (ctx); /* used for cleanup */
1070
1071   assuan_deinit_server (ctx);
1072 }
1073
1074
1075 /* Send a line with status information via assuan and escape all given
1076    buffers. The variable elements are pairs of (char *, size_t),
1077    terminated with a (NULL, 0). */
1078 void
1079 send_status_info (CTRL ctrl, const char *keyword, ...)
1080 {
1081   va_list arg_ptr;
1082   const unsigned char *value;
1083   size_t valuelen;
1084   char buf[950], *p;
1085   size_t n;
1086   ASSUAN_CONTEXT ctx = ctrl->server_local->assuan_ctx;
1087   
1088   va_start (arg_ptr, keyword);
1089
1090   p = buf; 
1091   n = 0;
1092   while ( (value = va_arg (arg_ptr, const unsigned char *)) )
1093     {
1094       valuelen = va_arg (arg_ptr, size_t);
1095       if (!valuelen)
1096         continue; /* empty buffer */
1097       if (n)
1098         {
1099           *p++ = ' ';
1100           n++;
1101         }
1102       for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
1103         {
1104           if (*value < ' ' || *value == '+')
1105             {
1106               sprintf (p, "%%%02X", *value);
1107               p += 3;
1108             }
1109           else if (*value == ' ')
1110             *p++ = '+';
1111           else
1112             *p++ = *value;
1113         }
1114     }
1115   *p = 0;
1116   assuan_write_status (ctx, keyword, buf);
1117
1118   va_end (arg_ptr);
1119 }
1120