Made some PIN pads work.
[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   if (!retstr)
725     {
726       /* We prompt for keypad entry.  To make sure that the popup has
727          been show we use an inquire and not just a status message.
728          We ignore any value returned.  */
729       if (info)
730         {
731           log_debug ("prompting for keypad entry '%s'\n", info);
732           rc = asprintf (&command, "POPUPKEYPADPROMPT %s", info);
733           if (rc < 0)
734             return gpg_error (gpg_err_code_from_errno (errno));
735           rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); 
736           free (command);  
737         }
738       else
739         {
740           log_debug ("dismiss keypad entry prompt\n");
741           rc = assuan_inquire (ctx, "DISMISSKEYPADPROMPT",
742                                &value, &valuelen, MAXLEN_PIN); 
743         }
744       if (!rc)
745         xfree (value);
746       return rc;
747     }
748
749   *retstr = NULL;
750   log_debug ("asking for PIN '%s'\n", info);
751
752   rc = asprintf (&command, "NEEDPIN %s", info);
753   if (rc < 0)
754     return gpg_error (gpg_err_code_from_errno (errno));
755
756   /* Fixme: Write an inquire function which returns the result in
757      secure memory and check all further handling of the PIN. */
758   rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); 
759   free (command);  
760   if (rc)
761     return rc;
762
763   if (!valuelen || value[valuelen-1])
764     {
765       /* We require that the returned value is an UTF-8 string */
766       xfree (value);
767       return gpg_error (GPG_ERR_INV_RESPONSE);
768     }
769   *retstr = (char*)value;
770   return 0;
771 }
772
773
774 /* PKSIGN [--hash=[rmd160|sha1|md5]] <hexified_id>
775
776    The --hash option is optional; the default is SHA1.
777
778  */
779 static int
780 cmd_pksign (assuan_context_t ctx, char *line)
781 {
782   ctrl_t ctrl = assuan_get_pointer (ctx);
783   int rc;
784   unsigned char *outdata;
785   size_t outdatalen;
786   char *keyidstr;
787   int hash_algo;
788
789   if (has_option (line, "--hash=rmd160"))
790     hash_algo = GCRY_MD_RMD160;
791   else if (has_option (line, "--hash=sha1"))
792     hash_algo = GCRY_MD_SHA1;
793   else if (has_option (line, "--hash=md5"))
794     hash_algo = GCRY_MD_MD5;
795   else if (!strstr (line, "--"))
796     hash_algo = GCRY_MD_SHA1; 
797   else
798     return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
799   /* Skip over options. */
800   while ( *line == '-' && line[1] == '-' )
801     {
802       while (*line && !spacep (line))
803         line++;
804       while (spacep (line))
805         line++;
806     }
807
808   if ( IS_LOCKED (ctrl) )
809     return gpg_error (GPG_ERR_LOCKED);
810
811   if ((rc = open_card (ctrl, NULL)))
812     return rc;
813
814   /* We have to use a copy of the key ID because the function may use
815      the pin_cb which in turn uses the assuan line buffer and thus
816      overwriting the original line with the keyid */
817   keyidstr = xtrystrdup (line);
818   if (!keyidstr)
819     return out_of_core ();
820   
821   rc = app_sign (ctrl->app_ctx,
822                  keyidstr, hash_algo,
823                  pin_cb, ctx,
824                  ctrl->in_data.value, ctrl->in_data.valuelen,
825                  &outdata, &outdatalen);
826
827   xfree (keyidstr);
828   if (rc)
829     {
830       log_error ("card_sign failed: %s\n", gpg_strerror (rc));
831     }
832   else
833     {
834       rc = assuan_send_data (ctx, outdata, outdatalen);
835       xfree (outdata);
836       if (rc)
837         return rc; /* that is already an assuan error code */
838     }
839
840   TEST_CARD_REMOVAL (ctrl, rc);
841   return rc;
842 }
843
844 /* PKAUTH <hexified_id>
845
846  */
847 static int
848 cmd_pkauth (assuan_context_t ctx, char *line)
849 {
850   ctrl_t ctrl = assuan_get_pointer (ctx);
851   int rc;
852   unsigned char *outdata;
853   size_t outdatalen;
854   char *keyidstr;
855
856   if ( IS_LOCKED (ctrl) )
857     return gpg_error (GPG_ERR_LOCKED);
858
859   if ((rc = open_card (ctrl, NULL)))
860     return rc;
861
862   if (!ctrl->app_ctx)
863     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
864
865  /* We have to use a copy of the key ID because the function may use
866      the pin_cb which in turn uses the assuan line buffer and thus
867      overwriting the original line with the keyid */
868   keyidstr = xtrystrdup (line);
869   if (!keyidstr)
870     return out_of_core ();
871   
872   rc = app_auth (ctrl->app_ctx,
873                  keyidstr,
874                  pin_cb, ctx,
875                  ctrl->in_data.value, ctrl->in_data.valuelen,
876                  &outdata, &outdatalen);
877   xfree (keyidstr);
878   if (rc)
879     {
880       log_error ("app_auth_sign failed: %s\n", gpg_strerror (rc));
881     }
882   else
883     {
884       rc = assuan_send_data (ctx, outdata, outdatalen);
885       xfree (outdata);
886       if (rc)
887         return rc; /* that is already an assuan error code */
888     }
889
890   TEST_CARD_REMOVAL (ctrl, rc);
891   return rc;
892 }
893
894 /* PKDECRYPT <hexified_id>
895
896  */
897 static int
898 cmd_pkdecrypt (assuan_context_t ctx, char *line)
899 {
900   ctrl_t ctrl = assuan_get_pointer (ctx);
901   int rc;
902   unsigned char *outdata;
903   size_t outdatalen;
904   char *keyidstr;
905
906   if ( IS_LOCKED (ctrl) )
907     return gpg_error (GPG_ERR_LOCKED);
908
909   if ((rc = open_card (ctrl, NULL)))
910     return rc;
911
912   keyidstr = xtrystrdup (line);
913   if (!keyidstr)
914     return out_of_core ();
915   rc = app_decipher (ctrl->app_ctx,
916                      keyidstr, 
917                      pin_cb, ctx,
918                      ctrl->in_data.value, ctrl->in_data.valuelen,
919                      &outdata, &outdatalen);
920
921   xfree (keyidstr);
922   if (rc)
923     {
924       log_error ("card_create_signature failed: %s\n", gpg_strerror (rc));
925     }
926   else
927     {
928       rc = assuan_send_data (ctx, outdata, outdatalen);
929       xfree (outdata);
930       if (rc)
931         return rc; /* that is already an assuan error code */
932     }
933
934   TEST_CARD_REMOVAL (ctrl, rc);
935   return rc;
936 }
937
938
939 /* GETATTR <name>
940
941    This command is used to retrieve data from a smartcard.  The
942    allowed names depend on the currently selected smartcard
943    application.  NAME must be percent and '+' escaped.  The value is
944    returned through status message, see the LEARN command for details.
945
946    However, the current implementation assumes that Name is not escaped;
947    this works as long as noone uses arbitrary escaping. 
948  
949    Note, that this function may even be used on a locked card.
950 */
951 static int
952 cmd_getattr (assuan_context_t ctx, char *line)
953 {
954   ctrl_t ctrl = assuan_get_pointer (ctx);
955   int rc;
956   const char *keyword;
957
958   if ((rc = open_card (ctrl, NULL)))
959     return rc;
960
961   keyword = line;
962   for (; *line && !spacep (line); line++)
963     ;
964   if (*line)
965       *line++ = 0;
966
967   /* (We ignore any garbage for now.) */
968
969   /* FIXME: Applications should not return sensitive data if the card
970      is locked.  */
971   rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
972
973   TEST_CARD_REMOVAL (ctrl, rc);
974   return rc;
975 }
976
977
978 /* SETATTR <name> <value> 
979
980    This command is used to store data on a a smartcard.  The allowed
981    names and values are depend on the currently selected smartcard
982    application.  NAME and VALUE must be percent and '+' escaped.
983
984    However, the curent implementation assumes that Name is not escaped;
985    this works as long as noone uses arbitrary escaping. 
986  
987    A PIN will be requested for most NAMEs.  See the corresponding
988    setattr function of the actually used application (app-*.c) for
989    details.  */
990 static int
991 cmd_setattr (assuan_context_t ctx, char *orig_line)
992 {
993   ctrl_t ctrl = assuan_get_pointer (ctx);
994   int rc;
995   char *keyword;
996   int keywordlen;
997   size_t nbytes;
998   char *line, *linebuf;
999
1000   if ( IS_LOCKED (ctrl) )
1001     return gpg_error (GPG_ERR_LOCKED);
1002
1003   if ((rc = open_card (ctrl, NULL)))
1004     return rc;
1005
1006   /* We need to use a copy of LINE, because PIN_CB uses the same
1007      context and thus reuses the Assuan provided LINE. */
1008   line = linebuf = xtrystrdup (orig_line);
1009   if (!line)
1010     return out_of_core ();
1011
1012   keyword = line;
1013   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
1014     ;
1015   if (*line)
1016       *line++ = 0;
1017   while (spacep (line))
1018     line++;
1019   nbytes = percent_plus_unescape ((unsigned char*)line);
1020
1021   rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx,
1022                     (const unsigned char*)line, nbytes);
1023   xfree (linebuf);
1024
1025   TEST_CARD_REMOVAL (ctrl, rc);
1026   return rc;
1027 }
1028
1029
1030
1031 /* WRITEKEY [--force] <keyid> 
1032
1033    This command is used to store a secret key on a a smartcard.  The
1034    allowed keyids depend on the currently selected smartcard
1035    application. The actual keydata is requested using the inquiry
1036    "KETDATA" and need to be provided without any protection.  With
1037    --force set an existing key under this KEYID will get overwritten.
1038    The keydata is expected to be the usual canonical encoded
1039    S-expression.
1040
1041    A PIN will be requested for most NAMEs.  See the corresponding
1042    writekey function of the actually used application (app-*.c) for
1043    details.  */
1044 static int
1045 cmd_writekey (assuan_context_t ctx, char *line)
1046 {
1047   ctrl_t ctrl = assuan_get_pointer (ctx);
1048   int rc;
1049   char *keyid;
1050   int force = has_option (line, "--force");
1051   unsigned char *keydata;
1052   size_t keydatalen;
1053
1054   if ( IS_LOCKED (ctrl) )
1055     return gpg_error (GPG_ERR_LOCKED);
1056
1057   /* Skip over options. */
1058   while ( *line == '-' && line[1] == '-' )
1059     {
1060       while (*line && !spacep (line))
1061         line++;
1062       while (spacep (line))
1063         line++;
1064     }
1065   if (!*line)
1066     return set_error (GPG_ERR_ASS_PARAMETER, "no keyid given");
1067   keyid = line;
1068   while (*line && !spacep (line))
1069     line++;
1070   *line = 0;
1071
1072   if ((rc = open_card (ctrl, NULL)))
1073     return rc;
1074
1075   if (!ctrl->app_ctx)
1076     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1077
1078   keyid = xtrystrdup (keyid);
1079   if (!keyid)
1080     return out_of_core ();
1081
1082   /* Now get the actual keydata. */
1083   rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA);
1084   if (rc)
1085     {
1086       xfree (keyid);
1087       return rc;
1088     }
1089
1090   /* Write the key to the card. */
1091   rc = app_writekey (ctrl->app_ctx, ctrl, keyid, force? 1:0,
1092                      pin_cb, ctx, keydata, keydatalen);
1093   xfree (keyid);
1094   xfree (keydata);
1095
1096   TEST_CARD_REMOVAL (ctrl, rc);
1097   return rc;
1098 }
1099
1100
1101
1102 /* GENKEY [--force] <no>
1103
1104    Generate a key on-card identified by NO, which is application
1105    specific.  Return values are application specific.  For OpenPGP
1106    cards 2 status lines are returned:
1107
1108      S KEY-FPR  <hexstring>
1109      S KEY-CREATED-AT <seconds_since_epoch>
1110      S KEY-DATA [p|n] <hexdata>
1111      
1112
1113    --force is required to overwrite an already existing key.  The
1114    KEY-CREATED-AT is required for further processing because it is
1115    part of the hashed key material for the fingerprint.
1116
1117    The public part of the key can also later be retrieved using the
1118    READKEY command.
1119
1120  */
1121 static int
1122 cmd_genkey (assuan_context_t ctx, char *line)
1123 {
1124   ctrl_t ctrl = assuan_get_pointer (ctx);
1125   int rc;
1126   char *keyno;
1127   int force = has_option (line, "--force");
1128
1129   if ( IS_LOCKED (ctrl) )
1130     return gpg_error (GPG_ERR_LOCKED);
1131
1132   /* Skip over options. */
1133   while ( *line == '-' && line[1] == '-' )
1134     {
1135       while (*line && !spacep (line))
1136         line++;
1137       while (spacep (line))
1138         line++;
1139     }
1140   if (!*line)
1141     return set_error (GPG_ERR_ASS_PARAMETER, "no key number given");
1142   keyno = line;
1143   while (*line && !spacep (line))
1144     line++;
1145   *line = 0;
1146
1147   if ((rc = open_card (ctrl, NULL)))
1148     return rc;
1149
1150   if (!ctrl->app_ctx)
1151     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1152
1153   keyno = xtrystrdup (keyno);
1154   if (!keyno)
1155     return out_of_core ();
1156   rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0, pin_cb, ctx);
1157   xfree (keyno);
1158
1159   TEST_CARD_REMOVAL (ctrl, rc);
1160   return rc;
1161 }
1162
1163
1164 /* RANDOM <nbytes>
1165
1166    Get NBYTES of random from the card and send them back as data. 
1167
1168    Note, that this function may be even be used on a locked card.
1169 */
1170 static int
1171 cmd_random (assuan_context_t ctx, char *line)
1172 {
1173   ctrl_t ctrl = assuan_get_pointer (ctx);
1174   int rc;
1175   size_t nbytes;
1176   unsigned char *buffer;
1177
1178   if (!*line)
1179     return set_error (GPG_ERR_ASS_PARAMETER, "number of requested bytes missing");
1180   nbytes = strtoul (line, NULL, 0);
1181
1182   if ((rc = open_card (ctrl, NULL)))
1183     return rc;
1184
1185   if (!ctrl->app_ctx)
1186     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1187
1188   buffer = xtrymalloc (nbytes);
1189   if (!buffer)
1190     return out_of_core ();
1191
1192   rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
1193   if (!rc)
1194     {
1195       rc = assuan_send_data (ctx, buffer, nbytes);
1196       xfree (buffer);
1197       return rc; /* that is already an assuan error code */
1198     }
1199   xfree (buffer);
1200
1201   TEST_CARD_REMOVAL (ctrl, rc);
1202   return rc;
1203 }
1204
1205 \f
1206 /* PASSWD [--reset] <chvno>
1207   
1208    Change the PIN or reset the retry counter of the card holder
1209    verfication vector CHVNO. */
1210 static int
1211 cmd_passwd (assuan_context_t ctx, char *line)
1212 {
1213   ctrl_t ctrl = assuan_get_pointer (ctx);
1214   int rc;
1215   char *chvnostr;
1216   int reset_mode = has_option (line, "--reset");
1217
1218   if ( IS_LOCKED (ctrl) )
1219     return gpg_error (GPG_ERR_LOCKED);
1220
1221   /* Skip over options. */
1222   while (*line == '-' && line[1] == '-')
1223     {
1224       while (*line && !spacep (line))
1225         line++;
1226       while (spacep (line))
1227         line++;
1228     }
1229   if (!*line)
1230     return set_error (GPG_ERR_ASS_PARAMETER, "no CHV number given");
1231   chvnostr = line;
1232   while (*line && !spacep (line))
1233     line++;
1234   *line = 0;
1235
1236   if ((rc = open_card (ctrl, NULL)))
1237     return rc;
1238
1239   if (!ctrl->app_ctx)
1240     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1241   
1242   chvnostr = xtrystrdup (chvnostr);
1243   if (!chvnostr)
1244     return out_of_core ();
1245   rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, reset_mode, pin_cb, ctx);
1246   if (rc)
1247     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1248   xfree (chvnostr);
1249
1250   TEST_CARD_REMOVAL (ctrl, rc);
1251   return rc;
1252 }
1253
1254
1255 /* CHECKPIN <idstr>
1256
1257    Perform a VERIFY operation without doing anything else.  This may
1258    be used to initialize a the PIN cache earlier to long lasting
1259    operations.  Its use is highly application dependent.
1260
1261    For OpenPGP:
1262
1263       Perform a simple verify operation for CHV1 and CHV2, so that
1264       further operations won't ask for CHV2 and it is possible to do a
1265       cheap check on the PIN: If there is something wrong with the PIN
1266       entry system, only the regular CHV will get blocked and not the
1267       dangerous CHV3.  IDSTR is the usual card's serial number in hex
1268       notation; an optional fingerprint part will get ignored.  There
1269       is however a special mode if the IDSTR is sffixed with the
1270       literal string "[CHV3]": In this case the Admin PIN is checked
1271       if and only if the retry counter is still at 3.
1272
1273  */
1274 static int
1275 cmd_checkpin (assuan_context_t ctx, char *line)
1276 {
1277   ctrl_t ctrl = assuan_get_pointer (ctx);
1278   int rc;
1279   char *keyidstr;
1280
1281   if ( IS_LOCKED (ctrl) )
1282     return gpg_error (GPG_ERR_LOCKED);
1283
1284   if ((rc = open_card (ctrl, NULL)))
1285     return rc;
1286
1287   if (!ctrl->app_ctx)
1288     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1289
1290   /* We have to use a copy of the key ID because the function may use
1291      the pin_cb which in turn uses the assuan line buffer and thus
1292      overwriting the original line with the keyid. */
1293   keyidstr = xtrystrdup (line);
1294   if (!keyidstr)
1295     return out_of_core ();
1296   
1297   rc = app_check_pin (ctrl->app_ctx,
1298                       keyidstr,
1299                       pin_cb, ctx);
1300   xfree (keyidstr);
1301   if (rc)
1302     log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
1303
1304   TEST_CARD_REMOVAL (ctrl, rc);
1305   return rc;
1306 }
1307
1308
1309 /* LOCK [--wait]
1310
1311    Grant exclusive card access to this session.  Note that there is
1312    no lock counter used and a second lock from the same session will
1313    be ignored.  A single unlock (or RESET) unlocks the session.
1314    Return GPG_ERR_LOCKED if another session has locked the reader.
1315
1316    If the option --wait is given the command will wait until a
1317    lock has been released.
1318  */
1319 static int
1320 cmd_lock (assuan_context_t ctx, char *line)
1321 {
1322   ctrl_t ctrl = assuan_get_pointer (ctx);
1323   int rc = 0;
1324
1325  retry:
1326   if (locked_session)
1327     {
1328       if (locked_session != ctrl->server_local)
1329         rc = gpg_error (GPG_ERR_LOCKED);
1330     }
1331   else
1332     locked_session = ctrl->server_local;
1333
1334 #ifdef USE_GNU_PTH
1335   if (rc && has_option (line, "--wait"))
1336     {
1337       rc = 0;
1338       pth_sleep (1); /* Better implement an event mechanism. However,
1339                         for card operations this should be
1340                         sufficient. */
1341       /* FIXME: Need to check that the connection is still alive.
1342          This can be done by issuing status messages. */
1343       goto retry;
1344     }
1345 #endif /*USE_GNU_PTH*/
1346   
1347   if (rc)
1348     log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
1349   return rc;
1350 }
1351
1352
1353 /* UNLOCK
1354
1355    Release exclusive card access.
1356  */
1357 static int
1358 cmd_unlock (assuan_context_t ctx, char *line)
1359 {
1360   ctrl_t ctrl = assuan_get_pointer (ctx);
1361   int rc = 0;
1362
1363   if (locked_session)
1364     {
1365       if (locked_session != ctrl->server_local)
1366         rc = gpg_error (GPG_ERR_LOCKED);
1367       else
1368         locked_session = NULL;
1369     }
1370   else
1371     rc = gpg_error (GPG_ERR_NOT_LOCKED);
1372
1373   if (rc)
1374     log_error ("cmd_unlock failed: %s\n", gpg_strerror (rc));
1375   return rc;
1376 }
1377
1378
1379 /* GETINFO <what>
1380
1381    Multi purpose command to return certain information.  
1382    Supported values of WHAT are:
1383
1384    socket_name - Return the name of the socket.
1385    status - Return the status of the current slot (in the future, may
1386    also return the status of all slots).  The status is a list of
1387    one-character flags.  The following flags are currently defined:
1388      'u'  Usable card present.  This is the normal state during operation.
1389      'r'  Card removed.  A reset is necessary.
1390    These flags are exclusive.
1391 */
1392
1393 static int
1394 cmd_getinfo (assuan_context_t ctx, char *line)
1395 {
1396   int rc = 0;
1397
1398   if (!strcmp (line, "socket_name"))
1399     {
1400       const char *s = scd_get_socket_name ();
1401
1402       if (s)
1403         rc = assuan_send_data (ctx, s, strlen (s));
1404       else
1405         rc = gpg_error (GPG_ERR_NO_DATA);
1406     }
1407   else if (!strcmp (line, "status"))
1408     {
1409       ctrl_t ctrl = assuan_get_pointer (ctx);
1410       int slot = ctrl->reader_slot;
1411       char flag = 'r';
1412
1413       if (!ctrl->server_local->card_removed && slot != -1)
1414         {
1415           struct slot_status_s *ss;
1416           
1417           if (!(slot >= 0 && slot < DIM(slot_table)))
1418             BUG ();
1419
1420           ss = &slot_table[slot];
1421
1422           if (!ss->valid)
1423             BUG ();
1424
1425           if (ss->any && (ss->status & 1))
1426             flag = 'u';
1427         }
1428       rc = assuan_send_data (ctx, &flag, 1);
1429     }
1430   else
1431     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1432   return rc;
1433 }
1434
1435
1436 /* RESTART
1437
1438    Restart the current connection; this is a kind of warm reset.  It
1439    deletes the context used by this connection but does not send a
1440    RESET to the card.  Thus the card itself won't get reset. 
1441
1442    This is used by gpg-agent to reuse a primary pipe connection and
1443    may be used by clients to backup from a conflict in the serial
1444    command; i.e. to select another application. 
1445 */
1446
1447 static int
1448 cmd_restart (assuan_context_t ctx, char *line)
1449 {
1450   ctrl_t ctrl = assuan_get_pointer (ctx);
1451
1452   if (ctrl->app_ctx)
1453     {
1454       release_application (ctrl->app_ctx);
1455       ctrl->app_ctx = NULL;
1456     }
1457   if (locked_session && ctrl->server_local == locked_session)
1458     {
1459       locked_session = NULL;
1460       log_info ("implicitly unlocking due to RESTART\n");
1461     }
1462   return 0;
1463 }
1464
1465
1466 /* APDU [--atr] [--more] [hexstring]
1467
1468    Send an APDU to the current reader.  This command bypasses the high
1469    level functions and sends the data directly to the card.  HEXSTRING
1470    is expected to be a proper APDU.  If HEXSTRING is not given no
1471    commands are set to the card but the command will implictly check
1472    whether the card is ready for use. 
1473
1474    Using the option "--atr" returns the ATR of the card as a status
1475    message before any data like this:
1476      S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1
1477
1478    Using the option --more handles the card status word MORE_DATA
1479    (61xx) and concatenate all reponses to one block.
1480
1481  */
1482 static int
1483 cmd_apdu (assuan_context_t ctx, char *line)
1484 {
1485   ctrl_t ctrl = assuan_get_pointer (ctx);
1486   int rc;
1487   unsigned char *apdu;
1488   size_t apdulen;
1489   int with_atr;
1490   int handle_more;
1491
1492   with_atr = has_option (line, "--atr");
1493   handle_more = has_option (line, "--more");
1494
1495   /* Skip over options. */
1496   while ( *line == '-' && line[1] == '-' )
1497     {
1498       while (*line && !spacep (line))
1499         line++;
1500       while (spacep (line))
1501         line++;
1502     }
1503
1504   if ( IS_LOCKED (ctrl) )
1505     return gpg_error (GPG_ERR_LOCKED);
1506
1507   if ((rc = open_card (ctrl, NULL)))
1508     return rc;
1509
1510   if (with_atr)
1511     {
1512       unsigned char *atr;
1513       size_t atrlen;
1514       int i;
1515       char hexbuf[400];
1516       
1517       atr = apdu_get_atr (ctrl->reader_slot, &atrlen);
1518       if (!atr || atrlen > sizeof hexbuf - 2 )
1519         {
1520           rc = gpg_error (GPG_ERR_INV_CARD);
1521           goto leave;
1522         }
1523       for (i=0; i < atrlen; i++)
1524         sprintf (hexbuf+2*i, "%02X", atr[i]);
1525       xfree (atr);
1526       send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
1527     }
1528
1529   apdu = hex_to_buffer (line, &apdulen);
1530   if (!apdu)
1531     {
1532       rc = gpg_error_from_syserror ();
1533       goto leave;
1534     }
1535   if (apdulen)
1536     {
1537       unsigned char *result = NULL;
1538       size_t resultlen;
1539
1540       rc = apdu_send_direct (ctrl->reader_slot, apdu, apdulen, handle_more,
1541                              &result, &resultlen);
1542       if (rc)
1543         log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
1544       else
1545         {
1546           rc = assuan_send_data (ctx, result, resultlen);
1547           xfree (result);
1548         }
1549     }
1550   xfree (apdu);
1551
1552  leave:
1553   TEST_CARD_REMOVAL (ctrl, rc);
1554   return rc;
1555 }
1556
1557
1558
1559
1560 \f
1561 /* Tell the assuan library about our commands */
1562 static int
1563 register_commands (assuan_context_t ctx)
1564 {
1565   static struct {
1566     const char *name;
1567     int (*handler)(assuan_context_t, char *line);
1568   } table[] = {
1569     { "SERIALNO",     cmd_serialno },
1570     { "LEARN",        cmd_learn },
1571     { "READCERT",     cmd_readcert },
1572     { "READKEY",      cmd_readkey },
1573     { "SETDATA",      cmd_setdata },
1574     { "PKSIGN",       cmd_pksign },
1575     { "PKAUTH",       cmd_pkauth },
1576     { "PKDECRYPT",    cmd_pkdecrypt },
1577     { "INPUT",        NULL }, 
1578     { "OUTPUT",       NULL }, 
1579     { "GETATTR",      cmd_getattr },
1580     { "SETATTR",      cmd_setattr },
1581     { "WRITEKEY",     cmd_writekey },
1582     { "GENKEY",       cmd_genkey },
1583     { "RANDOM",       cmd_random },
1584     { "PASSWD",       cmd_passwd },
1585     { "CHECKPIN",     cmd_checkpin },
1586     { "LOCK",         cmd_lock },
1587     { "UNLOCK",       cmd_unlock },
1588     { "GETINFO",      cmd_getinfo },
1589     { "RESTART",      cmd_restart },
1590     { "APDU",         cmd_apdu },
1591     { NULL }
1592   };
1593   int i, rc;
1594
1595   for (i=0; table[i].name; i++)
1596     {
1597       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
1598       if (rc)
1599         return rc;
1600     } 
1601   assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
1602
1603   assuan_register_reset_notify (ctx, reset_notify);
1604   assuan_register_option_handler (ctx, option_handler);
1605   return 0;
1606 }
1607
1608
1609 /* Startup the server.  If FD is given as -1 this is simple pipe
1610    server, otherwise it is a regular server. */
1611 void
1612 scd_command_handler (ctrl_t ctrl, int fd)
1613 {
1614   int rc;
1615   assuan_context_t ctx;
1616   
1617   if (fd == -1)
1618     {
1619       int filedes[2];
1620
1621       filedes[0] = 0;
1622       filedes[1] = 1;
1623       rc = assuan_init_pipe_server (&ctx, filedes);
1624     }
1625   else
1626     {
1627       rc = assuan_init_socket_server_ext (&ctx, fd, 2);
1628     }
1629   if (rc)
1630     {
1631       log_error ("failed to initialize the server: %s\n",
1632                  gpg_strerror(rc));
1633       scd_exit (2);
1634     }
1635   rc = register_commands (ctx);
1636   if (rc)
1637     {
1638       log_error ("failed to register commands with Assuan: %s\n",
1639                  gpg_strerror(rc));
1640       scd_exit (2);
1641     }
1642   assuan_set_pointer (ctx, &ctrl);
1643
1644   /* Allocate and initialize the server object.  Put it into the list
1645      of active sessions. */
1646   ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
1647   ctrl->server_local->next_session = session_list;
1648   session_list = ctrl->server_local;
1649   ctrl->server_local->ctrl_backlink = ctrl;
1650   ctrl->server_local->assuan_ctx = ctx;
1651
1652   if (DBG_ASSUAN)
1653     assuan_set_log_stream (ctx, log_get_stream ());
1654
1655   /* We open the reader right at startup so that the ticker is able to
1656      update the status file. */
1657   if (ctrl->reader_slot == -1)
1658     {
1659       ctrl->reader_slot = get_reader_slot ();
1660     }
1661
1662   /* Command processing loop. */
1663   for (;;)
1664     {
1665       rc = assuan_accept (ctx);
1666       if (rc == -1)
1667         {
1668           break;
1669         }
1670       else if (rc)
1671         {
1672           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
1673           break;
1674         }
1675       
1676       rc = assuan_process (ctx);
1677       if (rc)
1678         {
1679           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
1680           continue;
1681         }
1682     }
1683
1684   /* Cleanup.  */
1685   do_reset (ctrl, 0); 
1686
1687   /* Release the server object.  */
1688   if (session_list == ctrl->server_local)
1689     session_list = ctrl->server_local->next_session;
1690   else
1691     {
1692       struct server_local_s *sl;
1693       
1694       for (sl=session_list; sl->next_session; sl = sl->next_session)
1695         if (sl->next_session == ctrl->server_local)
1696           break;
1697       if (!sl->next_session)
1698           BUG ();
1699       sl->next_session = ctrl->server_local->next_session;
1700     }
1701   xfree (ctrl->server_local);
1702   ctrl->server_local = NULL;
1703
1704   /* Release the Assuan context.  */
1705   assuan_deinit_server (ctx);
1706 }
1707
1708
1709 /* Send a line with status information via assuan and escape all given
1710    buffers. The variable elements are pairs of (char *, size_t),
1711    terminated with a (NULL, 0). */
1712 void
1713 send_status_info (ctrl_t ctrl, const char *keyword, ...)
1714 {
1715   va_list arg_ptr;
1716   const unsigned char *value;
1717   size_t valuelen;
1718   char buf[950], *p;
1719   size_t n;
1720   assuan_context_t ctx = ctrl->server_local->assuan_ctx;
1721   
1722   va_start (arg_ptr, keyword);
1723
1724   p = buf; 
1725   n = 0;
1726   while ( (value = va_arg (arg_ptr, const unsigned char *)) )
1727     {
1728       valuelen = va_arg (arg_ptr, size_t);
1729       if (!valuelen)
1730         continue; /* empty buffer */
1731       if (n)
1732         {
1733           *p++ = ' ';
1734           n++;
1735         }
1736       for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
1737         {
1738           if (*value < ' ' || *value == '+')
1739             {
1740               sprintf (p, "%%%02X", *value);
1741               p += 3;
1742             }
1743           else if (*value == ' ')
1744             *p++ = '+';
1745           else
1746             *p++ = *value;
1747         }
1748     }
1749   *p = 0;
1750   assuan_write_status (ctx, keyword, buf);
1751
1752   va_end (arg_ptr);
1753 }
1754
1755
1756 /* This is the core of scd_update_reader_status_file but the caller
1757    needs to take care of the locking. */
1758 static void
1759 update_reader_status_file (void)
1760 {
1761   int idx;
1762   unsigned int status, changed;
1763
1764   /* Note, that we only try to get the status, because it does not
1765      make sense to wait here for a operation to complete.  If we are
1766      busy working with a card, delays in the status file update should
1767      be acceptable. */
1768   for (idx=0; idx < DIM(slot_table); idx++)
1769     {
1770       struct slot_status_s *ss = slot_table + idx;
1771
1772       if (!ss->valid || ss->slot == -1)
1773         continue; /* Not valid or reader not yet open. */
1774       
1775       if ( apdu_get_status (ss->slot, 0, &status, &changed) )
1776         continue; /* Get status failed. */
1777
1778       if (!ss->any || ss->status != status || ss->changed != changed )
1779         {
1780           char *fname;
1781           char templ[50];
1782           FILE *fp;
1783           struct server_local_s *sl;
1784
1785           log_info ("updating status of slot %d to 0x%04X\n",
1786                     ss->slot, status);
1787
1788           /* FIXME: Should this be IDX instead of ss->slot?  This
1789              depends on how client sessions will associate the reader
1790              status with their session.  */
1791           sprintf (templ, "reader_%d.status", ss->slot);
1792           fname = make_filename (opt.homedir, templ, NULL );
1793           fp = fopen (fname, "w");
1794           if (fp)
1795             {
1796               fprintf (fp, "%s\n",
1797                        (status & 1)? "USABLE":
1798                        (status & 4)? "ACTIVE":
1799                        (status & 2)? "PRESENT": "NOCARD");
1800               fclose (fp);
1801             }
1802           xfree (fname);
1803             
1804           /* If a status script is executable, run it. */
1805           {
1806             const char *args[9], *envs[2];
1807             char numbuf1[30], numbuf2[30], numbuf3[30];
1808             char *homestr, *envstr;
1809             gpg_error_t err;
1810             
1811             homestr = make_filename (opt.homedir, NULL);
1812             if (asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
1813               log_error ("out of core while building environment\n");
1814             else
1815               {
1816                 envs[0] = envstr;
1817                 envs[1] = NULL;
1818
1819                 sprintf (numbuf1, "%d", ss->slot);
1820                 sprintf (numbuf2, "0x%04X", ss->status);
1821                 sprintf (numbuf3, "0x%04X", status);
1822                 args[0] = "--reader-port";
1823                 args[1] = numbuf1; 
1824                 args[2] = "--old-code";
1825                 args[3] = numbuf2;  
1826                 args[4] = "--new-code";
1827                 args[5] = numbuf3; 
1828                 args[6] = "--status";
1829                 args[7] = ((status & 1)? "USABLE":
1830                            (status & 4)? "ACTIVE":
1831                            (status & 2)? "PRESENT": "NOCARD");
1832                 args[8] = NULL;  
1833
1834                 fname = make_filename (opt.homedir, "scd-event", NULL);
1835                 err = gnupg_spawn_process_detached (fname, args, envs);
1836                 if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
1837                   log_error ("failed to run event handler `%s': %s\n",
1838                              fname, gpg_strerror (err));
1839                 xfree (fname);
1840                 free (envstr);
1841               }
1842             xfree (homestr);
1843           }
1844
1845           /* Set the card removed flag for all current sessions.  We
1846              will set this on any card change because a reset or
1847              SERIALNO request must be done in any case.  */
1848           if (ss->any)
1849             update_card_removed (idx, 1);
1850           
1851           ss->any = 1;
1852           ss->status = status;
1853           ss->changed = changed;
1854
1855           /* Send a signal to all clients who applied for it.  */
1856           for (sl=session_list; sl; sl = sl->next_session)
1857             if (sl->event_signal && sl->assuan_ctx)
1858               {
1859                 pid_t pid = assuan_get_pid (sl->assuan_ctx);
1860                 int signo = sl->event_signal;
1861                 
1862                 log_info ("client pid is %d, sending signal %d\n",
1863                           pid, signo);
1864 #ifndef HAVE_W32_SYSTEM
1865                 if (pid != (pid_t)(-1) && pid && signo > 0)
1866                   kill (pid, signo);
1867 #endif
1868               }
1869
1870         }
1871     }
1872 }
1873
1874 /* This function is called by the ticker thread to check for changes
1875    of the reader stati.  It updates the reader status files and if
1876    requested by the caller also send a signal to the caller.  */
1877 void
1878 scd_update_reader_status_file (void)
1879 {
1880   if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL))
1881     return; /* locked - give up. */
1882   update_reader_status_file ();
1883   if (!pth_mutex_release (&status_file_update_lock))
1884     log_error ("failed to release status_file_update lock\n");
1885 }