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