2006-09-01 Marcus Brinkmann <marcus@g10code.de>
[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    status - Return the status of the current slot (in the future, may
1359    also return the status of all slots).  The status is a list of
1360    one-character flags.  The following flags are currently defined:
1361      'u'  Usable card present.  This is the normal state during operation.
1362      'r'  Card removed.  A reset is necessary.
1363    These flags are exclusive.
1364 */
1365
1366 static int
1367 cmd_getinfo (assuan_context_t ctx, char *line)
1368 {
1369   int rc = 0;
1370
1371   if (!strcmp (line, "socket_name"))
1372     {
1373       const char *s = scd_get_socket_name ();
1374
1375       if (s)
1376         rc = assuan_send_data (ctx, s, strlen (s));
1377       else
1378         rc = gpg_error (GPG_ERR_NO_DATA);
1379     }
1380   else if (!strcmp (line, "status"))
1381     {
1382       ctrl_t ctrl = assuan_get_pointer (ctx);
1383       int slot = ctrl->reader_slot;
1384       char flag = 'r';
1385
1386       if (!ctrl->server_local->card_removed && slot != -1)
1387         {
1388           struct slot_status_s *ss;
1389           
1390           if (!(slot >= 0 && slot < DIM(slot_table)))
1391             BUG ();
1392
1393           ss = &slot_table[slot];
1394
1395           if (!ss->valid)
1396             BUG ();
1397
1398           if (ss->any && (ss->status & 1))
1399             flag = 'u';
1400         }
1401       rc = assuan_send_data (ctx, &flag, 1);
1402     }
1403   else
1404     rc = set_error (Parameter_Error, "unknown value for WHAT");
1405   return rc;
1406 }
1407
1408
1409 /* RESTART
1410
1411    Restart the current connection; this is a kind of warm reset.  It
1412    deletes the context used by this connection but does not send a
1413    RESET to the card.  Thus the card itself won't get reset. 
1414
1415    This is used by gpg-agent to reuse a primary pipe connection and
1416    may be used by clients to backup from a conflict in the serial
1417    command; i.e. to select another application. 
1418 */
1419
1420 static int
1421 cmd_restart (assuan_context_t ctx, char *line)
1422 {
1423   ctrl_t ctrl = assuan_get_pointer (ctx);
1424
1425   if (ctrl->app_ctx)
1426     {
1427       release_application (ctrl->app_ctx);
1428       ctrl->app_ctx = NULL;
1429     }
1430   if (locked_session && ctrl->server_local == locked_session)
1431     {
1432       locked_session = NULL;
1433       log_info ("implicitly unlocking due to RESTART\n");
1434     }
1435   return 0;
1436 }
1437
1438
1439 /* APDU [--atr] [--more] [hexstring]
1440
1441    Send an APDU to the current reader.  This command bypasses the high
1442    level functions and sends the data directly to the card.  HEXSTRING
1443    is expected to be a proper APDU.  If HEXSTRING is not given no
1444    commands are set to the card but the command will implictly check
1445    whether the card is ready for use. 
1446
1447    Using the option "--atr" returns the ATR of the card as a status
1448    message before any data like this:
1449      S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1
1450
1451    Using the option --more handles the card status word MORE_DATA
1452    (61xx) and concatenate all reponses to one block.
1453
1454  */
1455 static int
1456 cmd_apdu (assuan_context_t ctx, char *line)
1457 {
1458   ctrl_t ctrl = assuan_get_pointer (ctx);
1459   int rc;
1460   int rc_is_assuan = 0;
1461   unsigned char *apdu;
1462   size_t apdulen;
1463   int with_atr;
1464   int handle_more;
1465
1466   with_atr = has_option (line, "--atr");
1467   handle_more = has_option (line, "--more");
1468
1469   /* Skip over options. */
1470   while ( *line == '-' && line[1] == '-' )
1471     {
1472       while (*line && !spacep (line))
1473         line++;
1474       while (spacep (line))
1475         line++;
1476     }
1477
1478   if ( IS_LOCKED (ctrl) )
1479     return gpg_error (GPG_ERR_LOCKED);
1480
1481   if ((rc = open_card (ctrl, NULL)))
1482     return rc;
1483
1484   if (with_atr)
1485     {
1486       unsigned char *atr;
1487       size_t atrlen;
1488       int i;
1489       char hexbuf[400];
1490       
1491       atr = apdu_get_atr (ctrl->reader_slot, &atrlen);
1492       if (!atr || atrlen > sizeof hexbuf - 2 )
1493         {
1494           rc = gpg_error (GPG_ERR_INV_CARD);
1495           goto leave;
1496         }
1497       for (i=0; i < atrlen; i++)
1498         sprintf (hexbuf+2*i, "%02X", atr[i]);
1499       xfree (atr);
1500       send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
1501     }
1502
1503   apdu = hex_to_buffer (line, &apdulen);
1504   if (!apdu)
1505     {
1506       rc = gpg_error_from_errno (errno);
1507       goto leave;
1508     }
1509   if (apdulen)
1510     {
1511       unsigned char *result = NULL;
1512       size_t resultlen;
1513
1514       rc = apdu_send_direct (ctrl->reader_slot, apdu, apdulen, handle_more,
1515                              &result, &resultlen);
1516       if (rc)
1517         log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
1518       else
1519         {
1520           rc_is_assuan = 1;
1521           rc = assuan_send_data (ctx, result, resultlen);
1522           xfree (result);
1523         }
1524     }
1525   xfree (apdu);
1526
1527  leave:
1528   TEST_CARD_REMOVAL (ctrl, rc);
1529   return rc_is_assuan? rc : map_to_assuan_status (rc);
1530 }
1531
1532
1533
1534
1535 \f
1536 /* Tell the assuan library about our commands */
1537 static int
1538 register_commands (assuan_context_t ctx)
1539 {
1540   static struct {
1541     const char *name;
1542     int (*handler)(assuan_context_t, char *line);
1543   } table[] = {
1544     { "SERIALNO",     cmd_serialno },
1545     { "LEARN",        cmd_learn },
1546     { "READCERT",     cmd_readcert },
1547     { "READKEY",      cmd_readkey },
1548     { "SETDATA",      cmd_setdata },
1549     { "PKSIGN",       cmd_pksign },
1550     { "PKAUTH",       cmd_pkauth },
1551     { "PKDECRYPT",    cmd_pkdecrypt },
1552     { "INPUT",        NULL }, 
1553     { "OUTPUT",       NULL }, 
1554     { "GETATTR",      cmd_getattr },
1555     { "SETATTR",      cmd_setattr },
1556     { "WRITEKEY",     cmd_writekey },
1557     { "GENKEY",       cmd_genkey },
1558     { "RANDOM",       cmd_random },
1559     { "PASSWD",       cmd_passwd },
1560     { "CHECKPIN",     cmd_checkpin },
1561     { "LOCK",         cmd_lock },
1562     { "UNLOCK",       cmd_unlock },
1563     { "GETINFO",      cmd_getinfo },
1564     { "RESTART",      cmd_restart },
1565     { "APDU",         cmd_apdu },
1566     { NULL }
1567   };
1568   int i, rc;
1569
1570   for (i=0; table[i].name; i++)
1571     {
1572       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
1573       if (rc)
1574         return rc;
1575     } 
1576   assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
1577
1578   assuan_register_reset_notify (ctx, reset_notify);
1579   assuan_register_option_handler (ctx, option_handler);
1580   return 0;
1581 }
1582
1583
1584 /* Startup the server.  If FD is given as -1 this is simple pipe
1585    server, otherwise it is a regular server. */
1586 void
1587 scd_command_handler (int fd)
1588 {
1589   int rc;
1590   assuan_context_t ctx;
1591   struct server_control_s ctrl;
1592
1593   memset (&ctrl, 0, sizeof ctrl);
1594   scd_init_default_ctrl (&ctrl);
1595   
1596   if (fd == -1)
1597     {
1598       int filedes[2];
1599
1600       filedes[0] = 0;
1601       filedes[1] = 1;
1602       rc = assuan_init_pipe_server (&ctx, filedes);
1603     }
1604   else
1605     {
1606       rc = assuan_init_connected_socket_server (&ctx, fd);
1607     }
1608   if (rc)
1609     {
1610       log_error ("failed to initialize the server: %s\n",
1611                  assuan_strerror(rc));
1612       scd_exit (2);
1613     }
1614   rc = register_commands (ctx);
1615   if (rc)
1616     {
1617       log_error ("failed to register commands with Assuan: %s\n",
1618                  assuan_strerror(rc));
1619       scd_exit (2);
1620     }
1621   assuan_set_pointer (ctx, &ctrl);
1622
1623   /* Allocate and initialize the server object.  Put it into the list
1624      of active sessions. */
1625   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
1626   ctrl.server_local->next_session = session_list;
1627   session_list = ctrl.server_local;
1628   ctrl.server_local->ctrl_backlink = &ctrl;
1629   ctrl.server_local->assuan_ctx = ctx;
1630
1631   if (DBG_ASSUAN)
1632     assuan_set_log_stream (ctx, log_get_stream ());
1633
1634   /* We open the reader right at startup so that the ticker is able to
1635      update the status file. */
1636   if (ctrl.reader_slot == -1)
1637     {
1638       ctrl.reader_slot = get_reader_slot ();
1639     }
1640
1641   /* Command processing loop. */
1642   for (;;)
1643     {
1644       rc = assuan_accept (ctx);
1645       if (rc == -1)
1646         {
1647           break;
1648         }
1649       else if (rc)
1650         {
1651           log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
1652           break;
1653         }
1654       
1655       rc = assuan_process (ctx);
1656       if (rc)
1657         {
1658           log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
1659           continue;
1660         }
1661     }
1662
1663   /* Cleanup.  */
1664   do_reset (&ctrl, 0); 
1665
1666   /* Release the server object.  */
1667   if (session_list == ctrl.server_local)
1668     session_list = ctrl.server_local->next_session;
1669   else
1670     {
1671       struct server_local_s *sl;
1672       
1673       for (sl=session_list; sl->next_session; sl = sl->next_session)
1674         if (sl->next_session == ctrl.server_local)
1675           break;
1676       if (!sl->next_session)
1677           BUG ();
1678       sl->next_session = ctrl.server_local->next_session;
1679     }
1680   xfree (ctrl.server_local);
1681
1682   /* Release the Assuan context.  */
1683   assuan_deinit_server (ctx);
1684 }
1685
1686
1687 /* Send a line with status information via assuan and escape all given
1688    buffers. The variable elements are pairs of (char *, size_t),
1689    terminated with a (NULL, 0). */
1690 void
1691 send_status_info (ctrl_t ctrl, const char *keyword, ...)
1692 {
1693   va_list arg_ptr;
1694   const unsigned char *value;
1695   size_t valuelen;
1696   char buf[950], *p;
1697   size_t n;
1698   assuan_context_t ctx = ctrl->server_local->assuan_ctx;
1699   
1700   va_start (arg_ptr, keyword);
1701
1702   p = buf; 
1703   n = 0;
1704   while ( (value = va_arg (arg_ptr, const unsigned char *)) )
1705     {
1706       valuelen = va_arg (arg_ptr, size_t);
1707       if (!valuelen)
1708         continue; /* empty buffer */
1709       if (n)
1710         {
1711           *p++ = ' ';
1712           n++;
1713         }
1714       for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
1715         {
1716           if (*value < ' ' || *value == '+')
1717             {
1718               sprintf (p, "%%%02X", *value);
1719               p += 3;
1720             }
1721           else if (*value == ' ')
1722             *p++ = '+';
1723           else
1724             *p++ = *value;
1725         }
1726     }
1727   *p = 0;
1728   assuan_write_status (ctx, keyword, buf);
1729
1730   va_end (arg_ptr);
1731 }
1732
1733
1734 /* This is the core of scd_update_reader_status_file but the caller
1735    needs to take care of the locking. */
1736 static void
1737 update_reader_status_file (void)
1738 {
1739   int idx;
1740   unsigned int status, changed;
1741
1742   /* Note, that we only try to get the status, because it does not
1743      make sense to wait here for a operation to complete.  If we are
1744      busy working with a card, delays in the status file update should
1745      be acceptable. */
1746   for (idx=0; idx < DIM(slot_table); idx++)
1747     {
1748       struct slot_status_s *ss = slot_table + idx;
1749
1750       if (!ss->valid || ss->slot == -1)
1751         continue; /* Not valid or reader not yet open. */
1752       
1753       if ( apdu_get_status (ss->slot, 0, &status, &changed) )
1754         continue; /* Get status failed. */
1755
1756       if (!ss->any || ss->status != status || ss->changed != changed )
1757         {
1758           char *fname;
1759           char templ[50];
1760           FILE *fp;
1761           struct server_local_s *sl;
1762
1763           log_info ("updating status of slot %d to 0x%04X\n",
1764                     ss->slot, status);
1765             
1766           sprintf (templ, "reader_%d.status", ss->slot);
1767           fname = make_filename (opt.homedir, templ, NULL );
1768           fp = fopen (fname, "w");
1769           if (fp)
1770             {
1771               fprintf (fp, "%s\n",
1772                        (status & 1)? "USABLE":
1773                        (status & 4)? "ACTIVE":
1774                        (status & 2)? "PRESENT": "NOCARD");
1775               fclose (fp);
1776             }
1777           xfree (fname);
1778             
1779           /* Set the card removed flag for all current sessions.  We
1780              will set this on any card change because a reset or
1781              SERIALNO request must be done in any case.  */
1782           if (ss->any)
1783             update_card_removed (ss->slot, 1); /* XXX: MB: Should be idx? */
1784           
1785           ss->any = 1;
1786           ss->status = status;
1787           ss->changed = changed;
1788
1789           /* Send a signal to all clients who applied for it.  */
1790           for (sl=session_list; sl; sl = sl->next_session)
1791             if (sl->event_signal && sl->assuan_ctx)
1792               {
1793                 pid_t pid = assuan_get_pid (sl->assuan_ctx);
1794                 int signo = sl->event_signal;
1795                 
1796                 log_info ("client pid is %d, sending signal %d\n",
1797                           pid, signo);
1798 #ifndef HAVE_W32_SYSTEM
1799                 if (pid != (pid_t)(-1) && pid && signo > 0)
1800                   kill (pid, signo);
1801 #endif
1802               }
1803         }
1804     }
1805 }
1806
1807 /* This function is called by the ticker thread to check for changes
1808    of the reader stati.  It updates the reader status files and if
1809    requested by the caller also send a signal to the caller.  */
1810 void
1811 scd_update_reader_status_file (void)
1812 {
1813   if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL))
1814     return; /* locked - give up. */
1815   update_reader_status_file ();
1816   if (!pth_mutex_release (&status_file_update_lock))
1817     log_error ("failed to release status_file_update lock\n");
1818 }