(cmd_setattr): Use a copy of LINE.
[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 /* SETATTR <name> <value> 
706
707    This command is used to store data on a a smartcard.  The allowed
708    names and values are depend on the currently selected smartcard
709    application.  NAME and VALUE must be percent and '+' escaped.
710
711    However, the curent implementation assumes that Name is not escaped;
712    this works as long as noone uses arbitrary escaping. 
713  
714    A PIN will be requested for most NAMEs.  See the corresponding
715    setattr function of the actually used application (app-*.c) for
716    details.  */
717 static int
718 cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line)
719 {
720   CTRL ctrl = assuan_get_pointer (ctx);
721   int rc;
722   char *keyword;
723   int keywordlen;
724   size_t nbytes;
725   char *line, *linebuf;
726
727   if ((rc = open_card (ctrl)))
728     return rc;
729
730   /* We need to use a copy of LINE, because PIN_CB uses the same
731      context and thus reuses the Assuan provided LINE. */
732   line = linebuf = xtrystrdup (orig_line);
733   if (!line)
734     return ASSUAN_Out_Of_Core;
735
736   keyword = line;
737   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
738     ;
739   if (*line)
740       *line++ = 0;
741   while (spacep (line))
742     line++;
743   nbytes = percent_plus_unescape (line);
744
745   rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx, line, nbytes);
746   xfree (linebuf);
747
748   return map_to_assuan_status (rc);
749 }
750
751 /* GENKEY [--force] <no>
752
753    Generate a key on-card identified by NO, which is application
754    specific.  Return values are application specific.  For OpenPGP
755    cards 2 status lines are returned:
756
757      S KEY-FPR  <hexstring>
758      S KEY-CREATED-AT <seconds_since_epoch>
759      S KEY-DATA [p|n] <hexdata>
760      
761
762    --force is required to overwriet an already existing key.  The
763    KEY-CREATED-AT is required for further processing because it is
764    part of the hashed key material for the fingerprint.
765
766    The public part of the key can also later be retrieved using the
767    READKEY command.
768
769  */
770 static int
771 cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
772 {
773   CTRL ctrl = assuan_get_pointer (ctx);
774   int rc;
775   char *keyno;
776   int force = has_option (line, "--force");
777
778   /* Skip over options. */
779   while ( *line == '-' && line[1] == '-' )
780     {
781       while (!spacep (line))
782         line++;
783       while (spacep (line))
784         line++;
785     }
786   if (!*line)
787     return set_error (Parameter_Error, "no key number given");
788   keyno = line;
789   while (!spacep (line))
790     line++;
791   *line = 0;
792
793   if ((rc = open_card (ctrl)))
794     return rc;
795
796   if (!ctrl->app_ctx)
797     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
798
799   keyno = xtrystrdup (keyno);
800   if (!keyno)
801     return ASSUAN_Out_Of_Core;
802   rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0, pin_cb, ctx);
803   xfree (keyno);
804   return map_to_assuan_status (rc);
805 }
806
807
808 /* RANDOM <nbytes>
809
810    Get NBYTES of random from the card and send them back as data. 
811 */
812 static int
813 cmd_random (ASSUAN_CONTEXT ctx, char *line)
814 {
815   CTRL ctrl = assuan_get_pointer (ctx);
816   int rc;
817   size_t nbytes;
818   unsigned char *buffer;
819
820   if (!*line)
821     return set_error (Parameter_Error, "number of requested bytes missing");
822   nbytes = strtoul (line, NULL, 0);
823
824   if ((rc = open_card (ctrl)))
825     return rc;
826
827   if (!ctrl->app_ctx)
828     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
829
830   buffer = xtrymalloc (nbytes);
831   if (!buffer)
832     return ASSUAN_Out_Of_Core;
833
834   rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
835   if (!rc)
836     {
837       rc = assuan_send_data (ctx, buffer, nbytes);
838       xfree (buffer);
839       return rc; /* that is already an assuan error code */
840     }
841   xfree (buffer);
842
843   return map_to_assuan_status (rc);
844 }
845
846 \f
847 /* PASSWD [--reset] <chvno>
848   
849    Change the PIN or reset thye retry counter of the card holder
850    verfication vector CHVNO. */
851 static int
852 cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
853 {
854   CTRL ctrl = assuan_get_pointer (ctx);
855   int rc;
856   char *chvnostr;
857   int reset_mode = has_option (line, "--reset");
858
859   /* Skip over options. */
860   while (*line == '-' && line[1] == '-')
861     {
862       while (!spacep (line))
863         line++;
864       while (spacep (line))
865         line++;
866     }
867   if (!*line)
868     return set_error (Parameter_Error, "no CHV number given");
869   chvnostr = line;
870   while (!spacep (line))
871     line++;
872   *line = 0;
873
874   if ((rc = open_card (ctrl)))
875     return rc;
876
877   if (!ctrl->app_ctx)
878     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
879   
880   chvnostr = xtrystrdup (chvnostr);
881   if (!chvnostr)
882     return ASSUAN_Out_Of_Core;
883   rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, reset_mode, pin_cb, ctx);
884   if (rc)
885     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
886   xfree (chvnostr);
887   return map_to_assuan_status (rc);
888 }
889
890
891
892 \f
893 /* Tell the assuan library about our commands */
894 static int
895 register_commands (ASSUAN_CONTEXT ctx)
896 {
897   static struct {
898     const char *name;
899     int (*handler)(ASSUAN_CONTEXT, char *line);
900   } table[] = {
901     { "SERIALNO",     cmd_serialno },
902     { "LEARN",        cmd_learn },
903     { "READCERT",     cmd_readcert },
904     { "READKEY",      cmd_readkey },
905     { "SETDATA",      cmd_setdata },
906     { "PKSIGN",       cmd_pksign },
907     { "PKAUTH",       cmd_pkauth },
908     { "PKDECRYPT",    cmd_pkdecrypt },
909     { "INPUT",        NULL }, 
910     { "OUTPUT",       NULL }, 
911     { "SETATTR",      cmd_setattr },
912     { "GENKEY",       cmd_genkey },
913     { "RANDOM",       cmd_random },
914     { "PASSWD",       cmd_passwd },
915     { NULL }
916   };
917   int i, rc;
918
919   for (i=0; table[i].name; i++)
920     {
921       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
922       if (rc)
923         return rc;
924     } 
925   assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
926
927   assuan_register_reset_notify (ctx, reset_notify);
928   assuan_register_option_handler (ctx, option_handler);
929   return 0;
930 }
931
932
933 /* Startup the server.  If LISTEN_FD is given as -1, this is simple
934    piper server, otherwise it is a regular server */
935 void
936 scd_command_handler (int listen_fd)
937 {
938   int rc;
939   ASSUAN_CONTEXT ctx;
940   struct server_control_s ctrl;
941
942   memset (&ctrl, 0, sizeof ctrl);
943   scd_init_default_ctrl (&ctrl);
944   
945   if (listen_fd == -1)
946     {
947       int filedes[2];
948
949       filedes[0] = 0;
950       filedes[1] = 1;
951       rc = assuan_init_pipe_server (&ctx, filedes);
952     }
953   else
954     {
955       rc = assuan_init_socket_server (&ctx, listen_fd);
956     }
957   if (rc)
958     {
959       log_error ("failed to initialize the server: %s\n",
960                  assuan_strerror(rc));
961       scd_exit (2);
962     }
963   rc = register_commands (ctx);
964   if (rc)
965     {
966       log_error ("failed to register commands with Assuan: %s\n",
967                  assuan_strerror(rc));
968       scd_exit (2);
969     }
970   assuan_set_pointer (ctx, &ctrl);
971   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
972   ctrl.server_local->assuan_ctx = ctx;
973
974   if (DBG_ASSUAN)
975     assuan_set_log_stream (ctx, log_get_stream ());
976
977   for (;;)
978     {
979       rc = assuan_accept (ctx);
980       if (rc == -1)
981         {
982           break;
983         }
984       else if (rc)
985         {
986           log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
987           break;
988         }
989       
990       rc = assuan_process (ctx);
991       if (rc)
992         {
993           log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
994           continue;
995         }
996     }
997   reset_notify (ctx); /* used for cleanup */
998
999   assuan_deinit_server (ctx);
1000 }
1001
1002
1003 /* Send a line with status information via assuan and escape all given
1004    buffers. The variable elements are pairs of (char *, size_t),
1005    terminated with a (NULL, 0). */
1006 void
1007 send_status_info (CTRL ctrl, const char *keyword, ...)
1008 {
1009   va_list arg_ptr;
1010   const unsigned char *value;
1011   size_t valuelen;
1012   char buf[950], *p;
1013   size_t n;
1014   ASSUAN_CONTEXT ctx = ctrl->server_local->assuan_ctx;
1015   
1016   va_start (arg_ptr, keyword);
1017
1018   p = buf; 
1019   n = 0;
1020   while ( (value = va_arg (arg_ptr, const unsigned char *)) )
1021     {
1022       valuelen = va_arg (arg_ptr, size_t);
1023       if (!valuelen)
1024         continue; /* empty buffer */
1025       if (n)
1026         {
1027           *p++ = ' ';
1028           n++;
1029         }
1030       for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
1031         {
1032           if (*value < ' ' || *value == '+')
1033             {
1034               sprintf (p, "%%%02X", *value);
1035               p += 3;
1036             }
1037           else if (*value == ' ')
1038             *p++ = '+';
1039           else
1040             *p++ = *value;
1041         }
1042     }
1043   *p = 0;
1044   assuan_write_status (ctx, keyword, buf);
1045
1046   va_end (arg_ptr);
1047 }
1048