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