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