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