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