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