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