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