573a917069e79c0d4fe166f717fa1a7990be10a9
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #include <config.h>
23 #include <errno.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <unistd.h>
29 #include <signal.h>
30 #ifdef USE_GNU_PTH
31 # include <pth.h>
32 #endif
33
34 #include <assuan.h>
35
36 #include "scdaemon.h"
37 #include <ksba.h>
38 #include "app-common.h"
39 #include "apdu.h" /* Required for apdu_*_reader (). */
40 #include "exechelp.h"
41
42 /* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */
43 #define MAXLEN_PIN 100
44
45 /* Maximum allowed size of key data as used in inquiries. */
46 #define MAXLEN_KEYDATA 4096
47
48
49 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
50
51
52 /* Macro to flag a removed card.  */
53 #define TEST_CARD_REMOVAL(c,r)                              \
54        do {                                                 \
55           int _r = (r);                                     \
56           if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \
57               || gpg_err_code (_r) == GPG_ERR_CARD_REMOVED) \
58             update_card_removed ((c)->reader_slot, 1);      \
59        } while (0)
60
61 #define IS_LOCKED(c)                                                     \
62      (locked_session && locked_session != (c)->server_local              \
63       && (c)->reader_slot != -1 && locked_session->ctrl_backlink         \
64       && (c)->reader_slot == locked_session->ctrl_backlink->reader_slot)
65
66
67 /* This structure is used to keep track of open readers (slots). */
68 struct slot_status_s 
69 {
70   int valid;  /* True if the other objects are valid. */
71   int slot;   /* Slot number of the reader or -1 if not open. */
72
73   int reset_failed; /* A reset failed. */
74
75   int any;    /* Flag indicating whether any status check has been
76                  done.  This is set once to indicate that the status
77                  tracking for the slot has been initialized.  */
78   unsigned int status;  /* Last status of the slot. */
79   unsigned int changed; /* Last change counter of teh slot. */
80 };
81
82
83 /* Data used to associate an Assuan context with local server data.
84    This object describes the local properties of one session.  */
85 struct server_local_s 
86 {
87   /* We keep a list of all active sessions with the anchor at
88      SESSION_LIST (see below).  This field is used for linking. */
89   struct server_local_s *next_session; 
90
91   /* This object is usually assigned to a CTRL object (which is
92      globally visible).  While enumerating all sessions we sometimes
93      need to access data of the CTRL object; thus we keep a
94      backpointer here. */
95   ctrl_t ctrl_backlink;
96
97   /* The Assuan context used by this session/server. */
98   assuan_context_t assuan_ctx;
99
100   int event_signal;        /* Or 0 if not used. */
101
102   /* True if the card has been removed and a reset is required to
103      continue operation. */
104   int card_removed;        
105 };
106
107
108 /* The table with information on all used slots.  FIXME: This is a
109    different slot number than the one used by the APDU layer, and
110    should be renamed.  */
111 static struct slot_status_s slot_table[10];
112
113
114 /* To keep track of all running sessions, we link all active server
115    contexts and the anchor in this variable.  */
116 static struct server_local_s *session_list;
117
118 /* If a session has been locked we store a link to its server object
119    in this variable. */
120 static struct server_local_s *locked_session;
121
122 /* While doing a reset we need to make sure that the ticker does not
123    call scd_update_reader_status_file while we are using it. */
124 static pth_mutex_t status_file_update_lock = PTH_MUTEX_INIT;
125
126 \f
127 /*-- Local prototypes --*/
128 static void update_reader_status_file (void);
129
130
131 \f
132 /* Update the CARD_REMOVED element of all sessions using the reader
133    given by SLOT to VALUE  */
134 static void
135 update_card_removed (int slot, int value)
136 {
137   struct server_local_s *sl;
138
139   for (sl=session_list; sl; sl = sl->next_session)
140     if (sl->ctrl_backlink
141         && sl->ctrl_backlink->reader_slot == slot)
142       {
143         sl->card_removed = value;
144       }
145   if (value)
146     application_notify_card_removed (slot);
147 }
148
149
150
151 /* Check whether the option NAME appears in LINE */
152 static int
153 has_option (const char *line, const char *name)
154 {
155   const char *s;
156   int n = strlen (name);
157
158   s = strstr (line, name);
159   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
160 }
161
162
163 /* Convert the STRING into a newly allocated buffer while translating
164    the hex numbers.  Stops at the first invalid character.  Blanks and
165    colons are allowed to separate the hex digits.  Returns NULL on
166    error or a newly malloced buffer and its length in LENGTH.  */
167 static unsigned char *
168 hex_to_buffer (const char *string, size_t *r_length)
169 {
170   unsigned char *buffer;
171   const char *s;
172   size_t n;
173
174   buffer = xtrymalloc (strlen (string)+1);
175   if (!buffer)
176     return NULL;
177   for (s=string, n=0; *s; s++)
178     {
179       if (spacep (s) || *s == ':') 
180         continue;
181       if (hexdigitp (s) && hexdigitp (s+1))
182         {
183           buffer[n++] = xtoi_2 (s);
184           s++;
185         }
186       else
187         break;
188     }
189   *r_length = n;
190   return buffer;
191 }
192
193
194
195 /* Reset the card and free the application context.  With SEND_RESET
196    set to true actually send a RESET to the reader. */
197 static void
198 do_reset (ctrl_t ctrl, int send_reset)
199 {
200   int slot = ctrl->reader_slot;
201
202   if (!(slot == -1 || (slot >= 0 && slot < DIM(slot_table))))
203     BUG ();
204
205   if (ctrl->app_ctx)
206     {
207       release_application (ctrl->app_ctx);
208       ctrl->app_ctx = NULL;
209     }
210
211   if (slot != -1 && send_reset && !IS_LOCKED (ctrl) )
212     {
213       if (apdu_reset (slot)) 
214         {
215           slot_table[slot].reset_failed = 1;
216         }
217     }
218
219   /* If we hold a lock, unlock now. */
220   if (locked_session && ctrl->server_local == locked_session)
221     {
222       locked_session = NULL;
223       log_info ("implicitly unlocking due to RESET\n");
224     }
225
226   /* Reset card removed flag for the current reader.  We need to take
227      the lock here so that the ticker thread won't concurrently try to
228      update the file.  Note that the update function will set the card
229      removed flag and we will later reset it - not a particualar nice
230      way of implementing it but it works. */
231   if (!pth_mutex_acquire (&status_file_update_lock, 0, NULL))
232     {
233       log_error ("failed to acquire status_fle_update lock\n");
234       ctrl->reader_slot = -1;
235       return;
236     }
237   update_reader_status_file ();
238   update_card_removed (slot, 0);
239   if (!pth_mutex_release (&status_file_update_lock))
240     log_error ("failed to release status_file_update lock\n");
241
242   /* Do this last, so that update_card_removed does its job.  */
243   ctrl->reader_slot = -1;
244 }
245
246 \f
247 static void
248 reset_notify (assuan_context_t ctx)
249 {
250   ctrl_t ctrl = assuan_get_pointer (ctx); 
251
252   do_reset (ctrl, 1);
253 }
254
255
256 static int
257 option_handler (assuan_context_t ctx, const char *key, const char *value)
258 {
259   ctrl_t ctrl = assuan_get_pointer (ctx);
260
261   if (!strcmp (key, "event-signal"))
262     {
263       /* A value of 0 is allowed to reset the event signal. */
264       int i = *value? atoi (value) : -1;
265       if (i < 0)
266         return gpg_error (GPG_ERR_ASS_PARAMETER);
267       ctrl->server_local->event_signal = i;
268     }
269
270  return 0;
271 }
272
273
274 /* Return the slot of the current reader or open the reader if no
275    other sessions are using a reader.  Note, that we currently support
276    only one reader but most of the code (except for this function)
277    should be able to cope with several readers.  */
278 static int
279 get_reader_slot (void)
280 {
281   struct slot_status_s *ss;
282
283   ss = &slot_table[0]; /* One reader for now. */
284
285   /* Initialize the item if needed. */
286   if (!ss->valid)
287     {
288       ss->slot = -1;
289       ss->valid = 1;
290     }
291
292   /* Try to open the reader. */
293   if (ss->slot == -1)
294     ss->slot = apdu_open_reader (opt.reader_port);
295
296   /* Return the slot_table index.  */
297   return 0;
298 }
299
300 /* If the card has not yet been opened, do it.  Note that this
301    function returns an Assuan error, so don't map the error a second
302    time.  */
303 static assuan_error_t
304 open_card (ctrl_t ctrl, const char *apptype)
305 {
306   gpg_error_t err;
307   int slot;
308
309   /* If we ever got a card not present error code, return that.  Only
310      the SERIALNO command and a reset are able to clear from that
311      state. */
312   if (ctrl->server_local->card_removed)
313     return gpg_error (GPG_ERR_CARD_REMOVED);
314
315   if ( IS_LOCKED (ctrl) )
316     return gpg_error (GPG_ERR_LOCKED);
317
318   if (ctrl->app_ctx)
319     {
320       /* Already initialized for one specific application.  Need to
321          check that the client didn't requested a specific application
322          different from the one in use. */
323       return check_application_conflict (ctrl, apptype);
324     }
325
326   if (ctrl->reader_slot != -1)
327     slot = ctrl->reader_slot;
328   else
329     slot = get_reader_slot ();
330   ctrl->reader_slot = slot;
331   if (slot == -1)
332     err = gpg_error (GPG_ERR_CARD);
333   else
334     err = select_application (ctrl, slot, apptype, &ctrl->app_ctx);
335
336   TEST_CARD_REMOVAL (ctrl, err);
337   return err;
338 }
339
340
341 /* Do the percent and plus/space unescaping in place and return the
342    length of the valid buffer. */
343 static size_t
344 percent_plus_unescape (unsigned char *string)
345 {
346   unsigned char *p = string;
347   size_t n = 0;
348
349   while (*string)
350     {
351       if (*string == '%' && string[1] && string[2])
352         { 
353           string++;
354           *p++ = xtoi_2 (string);
355           n++;
356           string+= 2;
357         }
358       else if (*string == '+')
359         {
360           *p++ = ' ';
361           n++;
362           string++;
363         }
364       else
365         {
366           *p++ = *string++;
367           n++;
368         }
369     }
370
371   return n;
372 }
373
374
375
376 /* SERIALNO [APPTYPE] 
377
378    Return the serial number of the card using a status reponse.  This
379    functon should be used to check for the presence of a card.
380
381    If APPTYPE is given, an application of that type is selected and an
382    error is returned if the application is not supported or available.
383    The default is to auto-select the application using a hardwired
384    preference system.  Note, that a future extension to this function
385    may allow to specify a list and order of applications to try.
386
387    This function is special in that it can be used to reset the card.
388    Most other functions will return an error when a card change has
389    been detected and the use of this function is therefore required.
390
391    Background: We want to keep the client clear of handling card
392    changes between operations; i.e. the client can assume that all
393    operations are done on the same card unless he calls this function.
394  */
395 static int
396 cmd_serialno (assuan_context_t ctx, char *line)
397 {
398   ctrl_t ctrl = assuan_get_pointer (ctx);
399   int rc = 0;
400   char *serial_and_stamp;
401   char *serial;
402   time_t stamp;
403
404   /* Clear the remove flag so that the open_card is able to reread it.  */
405   if (ctrl->server_local->card_removed)
406     {
407       if ( IS_LOCKED (ctrl) )
408         return gpg_error (GPG_ERR_LOCKED);
409       do_reset (ctrl, 1);
410     }
411
412   if ((rc = open_card (ctrl, *line? line:NULL)))
413     return rc;
414
415   rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
416   if (rc)
417     return rc;
418
419   rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp);
420   xfree (serial);
421   if (rc < 0)
422     return out_of_core ();
423   rc = 0;
424   assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
425   free (serial_and_stamp);
426   return 0;
427 }
428
429
430
431
432 /* LEARN [--force]
433
434    Learn all useful information of the currently inserted card.  When
435    used without the force options, the command might do an INQUIRE
436    like this:
437
438       INQUIRE KNOWNCARDP <hexstring_with_serialNumber> <timestamp>
439
440    The client should just send an "END" if the processing should go on
441    or a "CANCEL" to force the function to terminate with a Cancel
442    error message.  The response of this command is a list of status
443    lines formatted as this:
444
445      S APPTYPE <apptype>
446
447    This returns the type of the application, currently the strings:
448
449        P15     = PKCS-15 structure used
450        DINSIG  = DIN SIG
451        OPENPGP = OpenPGP card
452  
453    are implemented.  These strings are aliases for the AID
454
455      S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id>
456
457    If there is no certificate yet stored on the card a single "X" is
458    returned as the keygrip.  In addition to the keypair info, information
459    about all certificates stored on the card is also returned:
460
461      S CERTINFO <certtype> <hexstring_with_id>
462
463    Where CERTTYPE is a number indicating the type of certificate:
464       0   := Unknown
465       100 := Regular X.509 cert
466       101 := Trusted X.509 cert
467       102 := Useful X.509 cert
468       110 := Root CA cert (DINSIG)
469
470    For certain cards, more information will be returned:
471
472      S KEY-FPR <no> <hexstring>
473
474    For OpenPGP cards this returns the stored fingerprints of the
475    keys. This can be used check whether a key is available on the
476    card.  NO may be 1, 2 or 3.
477
478      S CA-FPR <no> <hexstring>
479
480    Similar to above, these are the fingerprints of keys assumed to be
481    ultimately trusted.
482
483      S DISP-NAME <name_of_card_holder>
484
485    The name of the card holder as stored on the card; percent
486    escaping takes place, spaces are encoded as '+'
487
488      S PUBKEY-URL <url>
489
490    The URL to be used for locating the entire public key.
491      
492    Note, that this function may be even be used on a locked card.
493 */
494 static int
495 cmd_learn (assuan_context_t ctx, char *line)
496 {
497   ctrl_t ctrl = assuan_get_pointer (ctx);
498   int rc = 0;
499
500   if ((rc = open_card (ctrl, NULL)))
501     return rc;
502
503   /* Unless the force option is used we try a shortcut by identifying
504      the card using a serial number and inquiring the client with
505      that. The client may choose to cancel the operation if he already
506      knows about this card */
507   {
508     char *serial_and_stamp;
509     char *serial;
510     time_t stamp;
511
512     rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
513     if (rc)
514       return rc;
515     rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp);
516     xfree (serial);
517     if (rc < 0)
518       return out_of_core ();
519     rc = 0;
520     assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
521
522     if (!has_option (line, "--force"))
523       {
524         char *command;
525
526         rc = asprintf (&command, "KNOWNCARDP %s", serial_and_stamp);
527         if (rc < 0)
528           {
529             free (serial_and_stamp);
530             return out_of_core ();
531           }
532         rc = 0;
533         rc = assuan_inquire (ctx, command, NULL, NULL, 0); 
534         free (command);  /* (must use standard free here) */
535         if (rc)
536           {
537             if (gpg_err_code (rc) != GPG_ERR_ASS_CANCELED)
538               log_error ("inquire KNOWNCARDP failed: %s\n",
539                          gpg_strerror (rc));
540             free (serial_and_stamp);
541             return rc; 
542           }
543         /* not canceled, so we have to proceeed */
544       }
545     free (serial_and_stamp);
546   }
547
548   /* Let the application print out its collection of useful status
549      information. */
550   if (!rc)
551     rc = app_write_learn_status (ctrl->app_ctx, ctrl);
552
553   TEST_CARD_REMOVAL (ctrl, rc);
554   return rc;
555 }
556
557
558 \f
559 /* READCERT <hexified_certid>
560
561    Note, that this function may even be used on a locked card.
562  */
563 static int
564 cmd_readcert (assuan_context_t ctx, char *line)
565 {
566   ctrl_t ctrl = assuan_get_pointer (ctx);
567   int rc;
568   unsigned char *cert;
569   size_t ncert;
570
571   if ((rc = open_card (ctrl, NULL)))
572     return rc;
573
574   line = xstrdup (line); /* Need a copy of the line. */
575   rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
576   if (rc)
577     log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
578   xfree (line);
579   line = NULL;
580   if (!rc)
581     {
582       rc = assuan_send_data (ctx, cert, ncert);
583       xfree (cert);
584       if (rc)
585         return rc;
586     }
587
588   TEST_CARD_REMOVAL (ctrl, rc);
589   return rc;
590 }
591
592
593 /* READKEY <keyid>
594
595    Return the public key for the given cert or key ID as an standard
596    S-Expression.
597
598    Note, that this function may even be used on a locked card.
599   */
600 static int
601 cmd_readkey (assuan_context_t ctx, char *line)
602 {
603   ctrl_t ctrl = assuan_get_pointer (ctx);
604   int rc;
605   unsigned char *cert = NULL;
606   size_t ncert, n;
607   ksba_cert_t kc = NULL;
608   ksba_sexp_t p;
609   unsigned char *pk;
610   size_t pklen;
611
612   if ((rc = open_card (ctrl, NULL)))
613     return rc;
614
615   line = xstrdup (line); /* Need a copy of the line. */
616   /* If the application supports the READKEY function we use that.
617      Otherwise we use the old way by extracting it from the
618      certificate.  */
619   rc = app_readkey (ctrl->app_ctx, line, &pk, &pklen);
620   if (!rc)
621     { /* Yeah, got that key - send it back.  */
622       rc = assuan_send_data (ctx, pk, pklen);
623       xfree (pk);
624       xfree (line);
625       line = NULL;
626       goto leave;
627     }
628
629   if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION)
630     log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
631   else  
632     {
633       rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
634       if (rc)
635         log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
636     }
637   xfree (line);
638   line = NULL;
639   if (rc)
640     goto leave;
641       
642   rc = ksba_cert_new (&kc);
643   if (rc)
644     {
645       xfree (cert);
646       goto leave;
647     }
648   rc = ksba_cert_init_from_mem (kc, cert, ncert);
649   if (rc)
650     {
651       log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
652       goto leave;
653     }
654
655   p = ksba_cert_get_public_key (kc);
656   if (!p)
657     {
658       rc = gpg_error (GPG_ERR_NO_PUBKEY);
659       goto leave;
660     }
661
662   n = gcry_sexp_canon_len (p, 0, NULL, NULL);
663   rc = assuan_send_data (ctx, p, n);
664   xfree (p);
665
666
667  leave:
668   ksba_cert_release (kc);
669   xfree (cert);
670   TEST_CARD_REMOVAL (ctrl, rc);
671   return rc;
672 }
673
674
675 \f
676
677 /* SETDATA <hexstring> 
678
679    The client should use this command to tell us the data he want to
680    sign.  */
681 static int
682 cmd_setdata (assuan_context_t ctx, char *line)
683 {
684   ctrl_t ctrl = assuan_get_pointer (ctx);
685   int n;
686   char *p;
687   unsigned char *buf;
688
689   if (locked_session && locked_session != ctrl->server_local)
690     return gpg_error (GPG_ERR_LOCKED);
691
692   /* Parse the hexstring. */
693   for (p=line,n=0; hexdigitp (p); p++, n++)
694     ;
695   if (*p)
696     return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
697   if (!n)
698     return set_error (GPG_ERR_ASS_PARAMETER, "no data given");
699   if ((n&1))
700     return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
701   n /= 2;
702   buf = xtrymalloc (n);
703   if (!buf)
704     return out_of_core ();
705
706   ctrl->in_data.value = buf;
707   ctrl->in_data.valuelen = n;
708   for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++)
709     buf[n] = xtoi_2 (p);
710   return 0;
711 }
712
713
714
715 static gpg_error_t 
716 pin_cb (void *opaque, const char *info, char **retstr)
717 {
718   assuan_context_t ctx = opaque;
719   char *command;
720   int rc;
721   unsigned char *value;
722   size_t valuelen;
723
724   *retstr = NULL;
725   log_debug ("asking for PIN '%s'\n", info);
726
727   rc = asprintf (&command, "NEEDPIN %s", info);
728   if (rc < 0)
729     return gpg_error (gpg_err_code_from_errno (errno));
730
731   /* Fixme: Write an inquire function which returns the result in
732      secure memory and check all further handling of the PIN. */
733   rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); 
734   free (command);  
735   if (rc)
736     return rc;
737
738   if (!valuelen || value[valuelen-1])
739     {
740       /* We require that the returned value is an UTF-8 string */
741       xfree (value);
742       return gpg_error (GPG_ERR_INV_RESPONSE);
743     }
744   *retstr = (char*)value;
745   return 0;
746 }
747
748
749 /* PKSIGN [--hash=[rmd160|sha1|md5]] <hexified_id>
750
751    The --hash option is optional; the default is SHA1.
752
753  */
754 static int
755 cmd_pksign (assuan_context_t ctx, char *line)
756 {
757   ctrl_t ctrl = assuan_get_pointer (ctx);
758   int rc;
759   unsigned char *outdata;
760   size_t outdatalen;
761   char *keyidstr;
762   int hash_algo;
763
764   if (has_option (line, "--hash=rmd160"))
765     hash_algo = GCRY_MD_RMD160;
766   else if (has_option (line, "--hash=sha1"))
767     hash_algo = GCRY_MD_SHA1;
768   else if (has_option (line, "--hash=md5"))
769     hash_algo = GCRY_MD_MD5;
770   else if (!strstr (line, "--"))
771     hash_algo = GCRY_MD_SHA1; 
772   else
773     return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
774   /* Skip over options. */
775   while ( *line == '-' && line[1] == '-' )
776     {
777       while (*line && !spacep (line))
778         line++;
779       while (spacep (line))
780         line++;
781     }
782
783   if ( IS_LOCKED (ctrl) )
784     return gpg_error (GPG_ERR_LOCKED);
785
786   if ((rc = open_card (ctrl, NULL)))
787     return rc;
788
789   /* We have to use a copy of the key ID because the function may use
790      the pin_cb which in turn uses the assuan line buffer and thus
791      overwriting the original line with the keyid */
792   keyidstr = xtrystrdup (line);
793   if (!keyidstr)
794     return out_of_core ();
795   
796   rc = app_sign (ctrl->app_ctx,
797                  keyidstr, hash_algo,
798                  pin_cb, ctx,
799                  ctrl->in_data.value, ctrl->in_data.valuelen,
800                  &outdata, &outdatalen);
801
802   xfree (keyidstr);
803   if (rc)
804     {
805       log_error ("card_sign failed: %s\n", gpg_strerror (rc));
806     }
807   else
808     {
809       rc = assuan_send_data (ctx, outdata, outdatalen);
810       xfree (outdata);
811       if (rc)
812         return rc; /* that is already an assuan error code */
813     }
814
815   TEST_CARD_REMOVAL (ctrl, rc);
816   return rc;
817 }
818
819 /* PKAUTH <hexified_id>
820
821  */
822 static int
823 cmd_pkauth (assuan_context_t ctx, char *line)
824 {
825   ctrl_t ctrl = assuan_get_pointer (ctx);
826   int rc;
827   unsigned char *outdata;
828   size_t outdatalen;
829   char *keyidstr;
830
831   if ( IS_LOCKED (ctrl) )
832     return gpg_error (GPG_ERR_LOCKED);
833
834   if ((rc = open_card (ctrl, NULL)))
835     return rc;
836
837   if (!ctrl->app_ctx)
838     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
839
840  /* We have to use a copy of the key ID because the function may use
841      the pin_cb which in turn uses the assuan line buffer and thus
842      overwriting the original line with the keyid */
843   keyidstr = xtrystrdup (line);
844   if (!keyidstr)
845     return out_of_core ();
846   
847   rc = app_auth (ctrl->app_ctx,
848                  keyidstr,
849                  pin_cb, ctx,
850                  ctrl->in_data.value, ctrl->in_data.valuelen,
851                  &outdata, &outdatalen);
852   xfree (keyidstr);
853   if (rc)
854     {
855       log_error ("app_auth_sign failed: %s\n", gpg_strerror (rc));
856     }
857   else
858     {
859       rc = assuan_send_data (ctx, outdata, outdatalen);
860       xfree (outdata);
861       if (rc)
862         return rc; /* that is already an assuan error code */
863     }
864
865   TEST_CARD_REMOVAL (ctrl, rc);
866   return rc;
867 }
868
869 /* PKDECRYPT <hexified_id>
870
871  */
872 static int
873 cmd_pkdecrypt (assuan_context_t ctx, char *line)
874 {
875   ctrl_t ctrl = assuan_get_pointer (ctx);
876   int rc;
877   unsigned char *outdata;
878   size_t outdatalen;
879   char *keyidstr;
880
881   if ( IS_LOCKED (ctrl) )
882     return gpg_error (GPG_ERR_LOCKED);
883
884   if ((rc = open_card (ctrl, NULL)))
885     return rc;
886
887   keyidstr = xtrystrdup (line);
888   if (!keyidstr)
889     return out_of_core ();
890   rc = app_decipher (ctrl->app_ctx,
891                      keyidstr, 
892                      pin_cb, ctx,
893                      ctrl->in_data.value, ctrl->in_data.valuelen,
894                      &outdata, &outdatalen);
895
896   xfree (keyidstr);
897   if (rc)
898     {
899       log_error ("card_create_signature failed: %s\n", gpg_strerror (rc));
900     }
901   else
902     {
903       rc = assuan_send_data (ctx, outdata, outdatalen);
904       xfree (outdata);
905       if (rc)
906         return rc; /* that is already an assuan error code */
907     }
908
909   TEST_CARD_REMOVAL (ctrl, rc);
910   return rc;
911 }
912
913
914 /* GETATTR <name>
915
916    This command is used to retrieve data from a smartcard.  The
917    allowed names depend on the currently selected smartcard
918    application.  NAME must be percent and '+' escaped.  The value is
919    returned through status message, see the LEARN command for details.
920
921    However, the current implementation assumes that Name is not escaped;
922    this works as long as noone uses arbitrary escaping. 
923  
924    Note, that this function may even be used on a locked card.
925 */
926 static int
927 cmd_getattr (assuan_context_t ctx, char *line)
928 {
929   ctrl_t ctrl = assuan_get_pointer (ctx);
930   int rc;
931   const char *keyword;
932
933   if ((rc = open_card (ctrl, NULL)))
934     return rc;
935
936   keyword = line;
937   for (; *line && !spacep (line); line++)
938     ;
939   if (*line)
940       *line++ = 0;
941
942   /* (We ignore any garbage for now.) */
943
944   /* FIXME: Applications should not return sensistive data if the card
945      is locked.  */
946   rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
947
948   TEST_CARD_REMOVAL (ctrl, rc);
949   return rc;
950 }
951
952
953 /* SETATTR <name> <value> 
954
955    This command is used to store data on a a smartcard.  The allowed
956    names and values are depend on the currently selected smartcard
957    application.  NAME and VALUE must be percent and '+' escaped.
958
959    However, the curent implementation assumes that Name is not escaped;
960    this works as long as noone uses arbitrary escaping. 
961  
962    A PIN will be requested for most NAMEs.  See the corresponding
963    setattr function of the actually used application (app-*.c) for
964    details.  */
965 static int
966 cmd_setattr (assuan_context_t ctx, char *orig_line)
967 {
968   ctrl_t ctrl = assuan_get_pointer (ctx);
969   int rc;
970   char *keyword;
971   int keywordlen;
972   size_t nbytes;
973   char *line, *linebuf;
974
975   if ( IS_LOCKED (ctrl) )
976     return gpg_error (GPG_ERR_LOCKED);
977
978   if ((rc = open_card (ctrl, NULL)))
979     return rc;
980
981   /* We need to use a copy of LINE, because PIN_CB uses the same
982      context and thus reuses the Assuan provided LINE. */
983   line = linebuf = xtrystrdup (orig_line);
984   if (!line)
985     return out_of_core ();
986
987   keyword = line;
988   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
989     ;
990   if (*line)
991       *line++ = 0;
992   while (spacep (line))
993     line++;
994   nbytes = percent_plus_unescape ((unsigned char*)line);
995
996   rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx,
997                     (const unsigned char*)line, nbytes);
998   xfree (linebuf);
999
1000   TEST_CARD_REMOVAL (ctrl, rc);
1001   return rc;
1002 }
1003
1004
1005
1006 /* WRITEKEY [--force] <keyid> 
1007
1008    This command is used to store a secret key on a a smartcard.  The
1009    allowed keyids depend on the currently selected smartcard
1010    application. The actual keydata is requested using the inquiry
1011    "KETDATA" and need to be provided without any protection.  With
1012    --force set an existing key under this KEYID will get overwritten.
1013    The keydata is expected to be the usual canonical encoded
1014    S-expression.
1015
1016    A PIN will be requested for most NAMEs.  See the corresponding
1017    writekey function of the actually used application (app-*.c) for
1018    details.  */
1019 static int
1020 cmd_writekey (assuan_context_t ctx, char *line)
1021 {
1022   ctrl_t ctrl = assuan_get_pointer (ctx);
1023   int rc;
1024   char *keyid;
1025   int force = has_option (line, "--force");
1026   unsigned char *keydata;
1027   size_t keydatalen;
1028
1029   if ( IS_LOCKED (ctrl) )
1030     return gpg_error (GPG_ERR_LOCKED);
1031
1032   /* Skip over options. */
1033   while ( *line == '-' && line[1] == '-' )
1034     {
1035       while (*line && !spacep (line))
1036         line++;
1037       while (spacep (line))
1038         line++;
1039     }
1040   if (!*line)
1041     return set_error (GPG_ERR_ASS_PARAMETER, "no keyid given");
1042   keyid = line;
1043   while (*line && !spacep (line))
1044     line++;
1045   *line = 0;
1046
1047   if ((rc = open_card (ctrl, NULL)))
1048     return rc;
1049
1050   if (!ctrl->app_ctx)
1051     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1052
1053   keyid = xtrystrdup (keyid);
1054   if (!keyid)
1055     return out_of_core ();
1056
1057   /* Now get the actual keydata. */
1058   rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA);
1059   if (rc)
1060     {
1061       xfree (keyid);
1062       return rc;
1063     }
1064
1065   /* Write the key to the card. */
1066   rc = app_writekey (ctrl->app_ctx, ctrl, keyid, force? 1:0,
1067                      pin_cb, ctx, keydata, keydatalen);
1068   xfree (keyid);
1069   xfree (keydata);
1070
1071   TEST_CARD_REMOVAL (ctrl, rc);
1072   return rc;
1073 }
1074
1075
1076
1077 /* GENKEY [--force] <no>
1078
1079    Generate a key on-card identified by NO, which is application
1080    specific.  Return values are application specific.  For OpenPGP
1081    cards 2 status lines are returned:
1082
1083      S KEY-FPR  <hexstring>
1084      S KEY-CREATED-AT <seconds_since_epoch>
1085      S KEY-DATA [p|n] <hexdata>
1086      
1087
1088    --force is required to overwrite an already existing key.  The
1089    KEY-CREATED-AT is required for further processing because it is
1090    part of the hashed key material for the fingerprint.
1091
1092    The public part of the key can also later be retrieved using the
1093    READKEY command.
1094
1095  */
1096 static int
1097 cmd_genkey (assuan_context_t ctx, char *line)
1098 {
1099   ctrl_t ctrl = assuan_get_pointer (ctx);
1100   int rc;
1101   char *keyno;
1102   int force = has_option (line, "--force");
1103
1104   if ( IS_LOCKED (ctrl) )
1105     return gpg_error (GPG_ERR_LOCKED);
1106
1107   /* Skip over options. */
1108   while ( *line == '-' && line[1] == '-' )
1109     {
1110       while (*line && !spacep (line))
1111         line++;
1112       while (spacep (line))
1113         line++;
1114     }
1115   if (!*line)
1116     return set_error (GPG_ERR_ASS_PARAMETER, "no key number given");
1117   keyno = line;
1118   while (*line && !spacep (line))
1119     line++;
1120   *line = 0;
1121
1122   if ((rc = open_card (ctrl, NULL)))
1123     return rc;
1124
1125   if (!ctrl->app_ctx)
1126     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1127
1128   keyno = xtrystrdup (keyno);
1129   if (!keyno)
1130     return out_of_core ();
1131   rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0, pin_cb, ctx);
1132   xfree (keyno);
1133
1134   TEST_CARD_REMOVAL (ctrl, rc);
1135   return rc;
1136 }
1137
1138
1139 /* RANDOM <nbytes>
1140
1141    Get NBYTES of random from the card and send them back as data. 
1142
1143    Note, that this function may be even be used on a locked card.
1144 */
1145 static int
1146 cmd_random (assuan_context_t ctx, char *line)
1147 {
1148   ctrl_t ctrl = assuan_get_pointer (ctx);
1149   int rc;
1150   size_t nbytes;
1151   unsigned char *buffer;
1152
1153   if (!*line)
1154     return set_error (GPG_ERR_ASS_PARAMETER, "number of requested bytes missing");
1155   nbytes = strtoul (line, NULL, 0);
1156
1157   if ((rc = open_card (ctrl, NULL)))
1158     return rc;
1159
1160   if (!ctrl->app_ctx)
1161     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1162
1163   buffer = xtrymalloc (nbytes);
1164   if (!buffer)
1165     return out_of_core ();
1166
1167   rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
1168   if (!rc)
1169     {
1170       rc = assuan_send_data (ctx, buffer, nbytes);
1171       xfree (buffer);
1172       return rc; /* that is already an assuan error code */
1173     }
1174   xfree (buffer);
1175
1176   TEST_CARD_REMOVAL (ctrl, rc);
1177   return rc;
1178 }
1179
1180 \f
1181 /* PASSWD [--reset] <chvno>
1182   
1183    Change the PIN or reset the retry counter of the card holder
1184    verfication vector CHVNO. */
1185 static int
1186 cmd_passwd (assuan_context_t ctx, char *line)
1187 {
1188   ctrl_t ctrl = assuan_get_pointer (ctx);
1189   int rc;
1190   char *chvnostr;
1191   int reset_mode = has_option (line, "--reset");
1192
1193   if ( IS_LOCKED (ctrl) )
1194     return gpg_error (GPG_ERR_LOCKED);
1195
1196   /* Skip over options. */
1197   while (*line == '-' && line[1] == '-')
1198     {
1199       while (*line && !spacep (line))
1200         line++;
1201       while (spacep (line))
1202         line++;
1203     }
1204   if (!*line)
1205     return set_error (GPG_ERR_ASS_PARAMETER, "no CHV number given");
1206   chvnostr = line;
1207   while (*line && !spacep (line))
1208     line++;
1209   *line = 0;
1210
1211   if ((rc = open_card (ctrl, NULL)))
1212     return rc;
1213
1214   if (!ctrl->app_ctx)
1215     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1216   
1217   chvnostr = xtrystrdup (chvnostr);
1218   if (!chvnostr)
1219     return out_of_core ();
1220   rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, reset_mode, pin_cb, ctx);
1221   if (rc)
1222     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1223   xfree (chvnostr);
1224
1225   TEST_CARD_REMOVAL (ctrl, rc);
1226   return rc;
1227 }
1228
1229
1230 /* CHECKPIN <idstr>
1231
1232    Perform a VERIFY operation without doing anything else.  This may
1233    be used to initialize a the PIN cache earlier to long lasting
1234    operations.  Its use is highly application dependent.
1235
1236    For OpenPGP:
1237
1238       Perform a simple verify operation for CHV1 and CHV2, so that
1239       further operations won't ask for CHV2 and it is possible to do a
1240       cheap check on the PIN: If there is something wrong with the PIN
1241       entry system, only the regular CHV will get blocked and not the
1242       dangerous CHV3.  IDSTR is the usual card's serial number in hex
1243       notation; an optional fingerprint part will get ignored.  There
1244       is however a special mode if the IDSTR is sffixed with the
1245       literal string "[CHV3]": In this case the Admin PIN is checked
1246       if and only if the retry counter is still at 3.
1247
1248  */
1249 static int
1250 cmd_checkpin (assuan_context_t ctx, char *line)
1251 {
1252   ctrl_t ctrl = assuan_get_pointer (ctx);
1253   int rc;
1254   char *keyidstr;
1255
1256   if ( IS_LOCKED (ctrl) )
1257     return gpg_error (GPG_ERR_LOCKED);
1258
1259   if ((rc = open_card (ctrl, NULL)))
1260     return rc;
1261
1262   if (!ctrl->app_ctx)
1263     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1264
1265   /* We have to use a copy of the key ID because the function may use
1266      the pin_cb which in turn uses the assuan line buffer and thus
1267      overwriting the original line with the keyid. */
1268   keyidstr = xtrystrdup (line);
1269   if (!keyidstr)
1270     return out_of_core ();
1271   
1272   rc = app_check_pin (ctrl->app_ctx,
1273                       keyidstr,
1274                       pin_cb, ctx);
1275   xfree (keyidstr);
1276   if (rc)
1277     log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
1278
1279   TEST_CARD_REMOVAL (ctrl, rc);
1280   return rc;
1281 }
1282
1283
1284 /* LOCK [--wait]
1285
1286    Grant exclusive card access to this session.  Note that there is
1287    no lock counter used and a second lock from the same session will
1288    be ignored.  A single unlock (or RESET) unlocks the session.
1289    Return GPG_ERR_LOCKED if another session has locked the reader.
1290
1291    If the option --wait is given the command will wait until a
1292    lock has been released.
1293  */
1294 static int
1295 cmd_lock (assuan_context_t ctx, char *line)
1296 {
1297   ctrl_t ctrl = assuan_get_pointer (ctx);
1298   int rc = 0;
1299
1300  retry:
1301   if (locked_session)
1302     {
1303       if (locked_session != ctrl->server_local)
1304         rc = gpg_error (GPG_ERR_LOCKED);
1305     }
1306   else
1307     locked_session = ctrl->server_local;
1308
1309 #ifdef USE_GNU_PTH
1310   if (rc && has_option (line, "--wait"))
1311     {
1312       rc = 0;
1313       pth_sleep (1); /* Better implement an event mechanism. However,
1314                         for card operations this should be
1315                         sufficient. */
1316       /* FIXME: Need to check that the connection is still alive.
1317          This can be done by issuing status messages. */
1318       goto retry;
1319     }
1320 #endif /*USE_GNU_PTH*/
1321   
1322   if (rc)
1323     log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
1324   return rc;
1325 }
1326
1327
1328 /* UNLOCK
1329
1330    Release exclusive card access.
1331  */
1332 static int
1333 cmd_unlock (assuan_context_t ctx, char *line)
1334 {
1335   ctrl_t ctrl = assuan_get_pointer (ctx);
1336   int rc = 0;
1337
1338   if (locked_session)
1339     {
1340       if (locked_session != ctrl->server_local)
1341         rc = gpg_error (GPG_ERR_LOCKED);
1342       else
1343         locked_session = NULL;
1344     }
1345   else
1346     rc = gpg_error (GPG_ERR_NOT_LOCKED);
1347
1348   if (rc)
1349     log_error ("cmd_unlock failed: %s\n", gpg_strerror (rc));
1350   return rc;
1351 }
1352
1353
1354 /* GETINFO <what>
1355
1356    Multi purpose command to return certain information.  
1357    Supported values of WHAT are:
1358
1359    socket_name - Return the name of the socket.
1360    status - Return the status of the current slot (in the future, may
1361    also return the status of all slots).  The status is a list of
1362    one-character flags.  The following flags are currently defined:
1363      'u'  Usable card present.  This is the normal state during operation.
1364      'r'  Card removed.  A reset is necessary.
1365    These flags are exclusive.
1366 */
1367
1368 static int
1369 cmd_getinfo (assuan_context_t ctx, char *line)
1370 {
1371   int rc = 0;
1372
1373   if (!strcmp (line, "socket_name"))
1374     {
1375       const char *s = scd_get_socket_name ();
1376
1377       if (s)
1378         rc = assuan_send_data (ctx, s, strlen (s));
1379       else
1380         rc = gpg_error (GPG_ERR_NO_DATA);
1381     }
1382   else if (!strcmp (line, "status"))
1383     {
1384       ctrl_t ctrl = assuan_get_pointer (ctx);
1385       int slot = ctrl->reader_slot;
1386       char flag = 'r';
1387
1388       if (!ctrl->server_local->card_removed && slot != -1)
1389         {
1390           struct slot_status_s *ss;
1391           
1392           if (!(slot >= 0 && slot < DIM(slot_table)))
1393             BUG ();
1394
1395           ss = &slot_table[slot];
1396
1397           if (!ss->valid)
1398             BUG ();
1399
1400           if (ss->any && (ss->status & 1))
1401             flag = 'u';
1402         }
1403       rc = assuan_send_data (ctx, &flag, 1);
1404     }
1405   else
1406     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1407   return rc;
1408 }
1409
1410
1411 /* RESTART
1412
1413    Restart the current connection; this is a kind of warm reset.  It
1414    deletes the context used by this connection but does not send a
1415    RESET to the card.  Thus the card itself won't get reset. 
1416
1417    This is used by gpg-agent to reuse a primary pipe connection and
1418    may be used by clients to backup from a conflict in the serial
1419    command; i.e. to select another application. 
1420 */
1421
1422 static int
1423 cmd_restart (assuan_context_t ctx, char *line)
1424 {
1425   ctrl_t ctrl = assuan_get_pointer (ctx);
1426
1427   if (ctrl->app_ctx)
1428     {
1429       release_application (ctrl->app_ctx);
1430       ctrl->app_ctx = NULL;
1431     }
1432   if (locked_session && ctrl->server_local == locked_session)
1433     {
1434       locked_session = NULL;
1435       log_info ("implicitly unlocking due to RESTART\n");
1436     }
1437   return 0;
1438 }
1439
1440
1441 /* APDU [--atr] [--more] [hexstring]
1442
1443    Send an APDU to the current reader.  This command bypasses the high
1444    level functions and sends the data directly to the card.  HEXSTRING
1445    is expected to be a proper APDU.  If HEXSTRING is not given no
1446    commands are set to the card but the command will implictly check
1447    whether the card is ready for use. 
1448
1449    Using the option "--atr" returns the ATR of the card as a status
1450    message before any data like this:
1451      S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1
1452
1453    Using the option --more handles the card status word MORE_DATA
1454    (61xx) and concatenate all reponses to one block.
1455
1456  */
1457 static int
1458 cmd_apdu (assuan_context_t ctx, char *line)
1459 {
1460   ctrl_t ctrl = assuan_get_pointer (ctx);
1461   int rc;
1462   unsigned char *apdu;
1463   size_t apdulen;
1464   int with_atr;
1465   int handle_more;
1466
1467   with_atr = has_option (line, "--atr");
1468   handle_more = has_option (line, "--more");
1469
1470   /* Skip over options. */
1471   while ( *line == '-' && line[1] == '-' )
1472     {
1473       while (*line && !spacep (line))
1474         line++;
1475       while (spacep (line))
1476         line++;
1477     }
1478
1479   if ( IS_LOCKED (ctrl) )
1480     return gpg_error (GPG_ERR_LOCKED);
1481
1482   if ((rc = open_card (ctrl, NULL)))
1483     return rc;
1484
1485   if (with_atr)
1486     {
1487       unsigned char *atr;
1488       size_t atrlen;
1489       int i;
1490       char hexbuf[400];
1491       
1492       atr = apdu_get_atr (ctrl->reader_slot, &atrlen);
1493       if (!atr || atrlen > sizeof hexbuf - 2 )
1494         {
1495           rc = gpg_error (GPG_ERR_INV_CARD);
1496           goto leave;
1497         }
1498       for (i=0; i < atrlen; i++)
1499         sprintf (hexbuf+2*i, "%02X", atr[i]);
1500       xfree (atr);
1501       send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
1502     }
1503
1504   apdu = hex_to_buffer (line, &apdulen);
1505   if (!apdu)
1506     {
1507       rc = gpg_error_from_errno (errno);
1508       goto leave;
1509     }
1510   if (apdulen)
1511     {
1512       unsigned char *result = NULL;
1513       size_t resultlen;
1514
1515       rc = apdu_send_direct (ctrl->reader_slot, apdu, apdulen, handle_more,
1516                              &result, &resultlen);
1517       if (rc)
1518         log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
1519       else
1520         {
1521           rc = assuan_send_data (ctx, result, resultlen);
1522           xfree (result);
1523         }
1524     }
1525   xfree (apdu);
1526
1527  leave:
1528   TEST_CARD_REMOVAL (ctrl, rc);
1529   return rc;
1530 }
1531
1532
1533
1534
1535 \f
1536 /* Tell the assuan library about our commands */
1537 static int
1538 register_commands (assuan_context_t ctx)
1539 {
1540   static struct {
1541     const char *name;
1542     int (*handler)(assuan_context_t, char *line);
1543   } table[] = {
1544     { "SERIALNO",     cmd_serialno },
1545     { "LEARN",        cmd_learn },
1546     { "READCERT",     cmd_readcert },
1547     { "READKEY",      cmd_readkey },
1548     { "SETDATA",      cmd_setdata },
1549     { "PKSIGN",       cmd_pksign },
1550     { "PKAUTH",       cmd_pkauth },
1551     { "PKDECRYPT",    cmd_pkdecrypt },
1552     { "INPUT",        NULL }, 
1553     { "OUTPUT",       NULL }, 
1554     { "GETATTR",      cmd_getattr },
1555     { "SETATTR",      cmd_setattr },
1556     { "WRITEKEY",     cmd_writekey },
1557     { "GENKEY",       cmd_genkey },
1558     { "RANDOM",       cmd_random },
1559     { "PASSWD",       cmd_passwd },
1560     { "CHECKPIN",     cmd_checkpin },
1561     { "LOCK",         cmd_lock },
1562     { "UNLOCK",       cmd_unlock },
1563     { "GETINFO",      cmd_getinfo },
1564     { "RESTART",      cmd_restart },
1565     { "APDU",         cmd_apdu },
1566     { NULL }
1567   };
1568   int i, rc;
1569
1570   for (i=0; table[i].name; i++)
1571     {
1572       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
1573       if (rc)
1574         return rc;
1575     } 
1576   assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
1577
1578   assuan_register_reset_notify (ctx, reset_notify);
1579   assuan_register_option_handler (ctx, option_handler);
1580   return 0;
1581 }
1582
1583
1584 /* Startup the server.  If FD is given as -1 this is simple pipe
1585    server, otherwise it is a regular server. */
1586 void
1587 scd_command_handler (int fd)
1588 {
1589   int rc;
1590   assuan_context_t ctx;
1591   struct server_control_s ctrl;
1592
1593   memset (&ctrl, 0, sizeof ctrl);
1594   scd_init_default_ctrl (&ctrl);
1595   
1596   if (fd == -1)
1597     {
1598       int filedes[2];
1599
1600       filedes[0] = 0;
1601       filedes[1] = 1;
1602       rc = assuan_init_pipe_server (&ctx, filedes);
1603     }
1604   else
1605     {
1606       rc = assuan_init_connected_socket_server (&ctx, fd);
1607     }
1608   if (rc)
1609     {
1610       log_error ("failed to initialize the server: %s\n",
1611                  gpg_strerror(rc));
1612       scd_exit (2);
1613     }
1614   rc = register_commands (ctx);
1615   if (rc)
1616     {
1617       log_error ("failed to register commands with Assuan: %s\n",
1618                  gpg_strerror(rc));
1619       scd_exit (2);
1620     }
1621   assuan_set_pointer (ctx, &ctrl);
1622
1623   /* Allocate and initialize the server object.  Put it into the list
1624      of active sessions. */
1625   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
1626   ctrl.server_local->next_session = session_list;
1627   session_list = ctrl.server_local;
1628   ctrl.server_local->ctrl_backlink = &ctrl;
1629   ctrl.server_local->assuan_ctx = ctx;
1630
1631   if (DBG_ASSUAN)
1632     assuan_set_log_stream (ctx, log_get_stream ());
1633
1634   /* We open the reader right at startup so that the ticker is able to
1635      update the status file. */
1636   if (ctrl.reader_slot == -1)
1637     {
1638       ctrl.reader_slot = get_reader_slot ();
1639     }
1640
1641   /* Command processing loop. */
1642   for (;;)
1643     {
1644       rc = assuan_accept (ctx);
1645       if (rc == -1)
1646         {
1647           break;
1648         }
1649       else if (rc)
1650         {
1651           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
1652           break;
1653         }
1654       
1655       rc = assuan_process (ctx);
1656       if (rc)
1657         {
1658           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
1659           continue;
1660         }
1661     }
1662
1663   /* Cleanup.  */
1664   do_reset (&ctrl, 0); 
1665
1666   /* Release the server object.  */
1667   if (session_list == ctrl.server_local)
1668     session_list = ctrl.server_local->next_session;
1669   else
1670     {
1671       struct server_local_s *sl;
1672       
1673       for (sl=session_list; sl->next_session; sl = sl->next_session)
1674         if (sl->next_session == ctrl.server_local)
1675           break;
1676       if (!sl->next_session)
1677           BUG ();
1678       sl->next_session = ctrl.server_local->next_session;
1679     }
1680   xfree (ctrl.server_local);
1681
1682   /* Release the Assuan context.  */
1683   assuan_deinit_server (ctx);
1684 }
1685
1686
1687 /* Send a line with status information via assuan and escape all given
1688    buffers. The variable elements are pairs of (char *, size_t),
1689    terminated with a (NULL, 0). */
1690 void
1691 send_status_info (ctrl_t ctrl, const char *keyword, ...)
1692 {
1693   va_list arg_ptr;
1694   const unsigned char *value;
1695   size_t valuelen;
1696   char buf[950], *p;
1697   size_t n;
1698   assuan_context_t ctx = ctrl->server_local->assuan_ctx;
1699   
1700   va_start (arg_ptr, keyword);
1701
1702   p = buf; 
1703   n = 0;
1704   while ( (value = va_arg (arg_ptr, const unsigned char *)) )
1705     {
1706       valuelen = va_arg (arg_ptr, size_t);
1707       if (!valuelen)
1708         continue; /* empty buffer */
1709       if (n)
1710         {
1711           *p++ = ' ';
1712           n++;
1713         }
1714       for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
1715         {
1716           if (*value < ' ' || *value == '+')
1717             {
1718               sprintf (p, "%%%02X", *value);
1719               p += 3;
1720             }
1721           else if (*value == ' ')
1722             *p++ = '+';
1723           else
1724             *p++ = *value;
1725         }
1726     }
1727   *p = 0;
1728   assuan_write_status (ctx, keyword, buf);
1729
1730   va_end (arg_ptr);
1731 }
1732
1733
1734 /* This is the core of scd_update_reader_status_file but the caller
1735    needs to take care of the locking. */
1736 static void
1737 update_reader_status_file (void)
1738 {
1739   int idx;
1740   unsigned int status, changed;
1741
1742   /* Note, that we only try to get the status, because it does not
1743      make sense to wait here for a operation to complete.  If we are
1744      busy working with a card, delays in the status file update should
1745      be acceptable. */
1746   for (idx=0; idx < DIM(slot_table); idx++)
1747     {
1748       struct slot_status_s *ss = slot_table + idx;
1749
1750       if (!ss->valid || ss->slot == -1)
1751         continue; /* Not valid or reader not yet open. */
1752       
1753       if ( apdu_get_status (ss->slot, 0, &status, &changed) )
1754         continue; /* Get status failed. */
1755
1756       if (!ss->any || ss->status != status || ss->changed != changed )
1757         {
1758           char *fname;
1759           char templ[50];
1760           FILE *fp;
1761           struct server_local_s *sl;
1762
1763           log_info ("updating status of slot %d to 0x%04X\n",
1764                     ss->slot, status);
1765
1766           /* FIXME: Should this be IDX instead of ss->slot?  This
1767              depends on how client sessions will associate the reader
1768              status with their session.  */
1769           sprintf (templ, "reader_%d.status", ss->slot);
1770           fname = make_filename (opt.homedir, templ, NULL );
1771           fp = fopen (fname, "w");
1772           if (fp)
1773             {
1774               fprintf (fp, "%s\n",
1775                        (status & 1)? "USABLE":
1776                        (status & 4)? "ACTIVE":
1777                        (status & 2)? "PRESENT": "NOCARD");
1778               fclose (fp);
1779             }
1780           xfree (fname);
1781             
1782           /* If a status script is executable, run it. */
1783           {
1784             const char *args[9], *envs[2];
1785             char numbuf1[30], numbuf2[3], numbuf3[30];
1786             char *homestr, *envstr;
1787             gpg_error_t err;
1788             
1789             homestr = make_filename (opt.homedir, NULL);
1790             if (asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
1791               log_error ("out of core while building environment\n");
1792             else
1793               {
1794                 envs[0] = envstr;
1795                 envs[1] = NULL;
1796
1797                 sprintf (numbuf1, "%d", ss->slot);
1798                 sprintf (numbuf2, "0x%04X", ss->status);
1799                 sprintf (numbuf3, "0x%04X", status);
1800                 args[0] = "--reader-port";
1801                 args[1] = numbuf1; 
1802                 args[2] = "--old-code";
1803                 args[3] = numbuf2;  
1804                 args[4] = "--new-code";
1805                 args[5] = numbuf3; 
1806                 args[6] = "--status";
1807                 args[7] = ((status & 1)? "USABLE":
1808                            (status & 4)? "ACTIVE":
1809                            (status & 2)? "PRESENT": "NOCARD");
1810                 args[8] = NULL;  
1811
1812                 fname = make_filename (opt.homedir, "scd-event", NULL);
1813                 err = gnupg_spawn_process_detached (fname, args, envs);
1814                 if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
1815                   log_error ("failed to run event handler `%s': %s\n",
1816                              fname, gpg_strerror (err));
1817                 xfree (fname);
1818                 free (envstr);
1819               }
1820             xfree (homestr);
1821           }
1822
1823           /* Set the card removed flag for all current sessions.  We
1824              will set this on any card change because a reset or
1825              SERIALNO request must be done in any case.  */
1826           if (ss->any)
1827             update_card_removed (idx, 1);
1828           
1829           ss->any = 1;
1830           ss->status = status;
1831           ss->changed = changed;
1832
1833           /* Send a signal to all clients who applied for it.  */
1834           for (sl=session_list; sl; sl = sl->next_session)
1835             if (sl->event_signal && sl->assuan_ctx)
1836               {
1837                 pid_t pid = assuan_get_pid (sl->assuan_ctx);
1838                 int signo = sl->event_signal;
1839                 
1840                 log_info ("client pid is %d, sending signal %d\n",
1841                           pid, signo);
1842 #ifndef HAVE_W32_SYSTEM
1843                 if (pid != (pid_t)(-1) && pid && signo > 0)
1844                   kill (pid, signo);
1845 #endif
1846               }
1847
1848         }
1849     }
1850 }
1851
1852 /* This function is called by the ticker thread to check for changes
1853    of the reader stati.  It updates the reader status files and if
1854    requested by the caller also send a signal to the caller.  */
1855 void
1856 scd_update_reader_status_file (void)
1857 {
1858   if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL))
1859     return; /* locked - give up. */
1860   update_reader_status_file ();
1861   if (!pth_mutex_release (&status_file_update_lock))
1862     log_error ("failed to release status_file_update lock\n");
1863 }