aa0e6350a56b7852e623e39dcb4e19fb48fe155b
[gnupg.git] / scd / command.c
1 /* command.c - SCdaemon command handler
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005,
3  *               2007, 2008, 2009  Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
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 #include "exechelp.h"
40 #ifdef HAVE_LIBUSB
41 #include "ccid-driver.h"
42 #endif
43
44 /* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */
45 #define MAXLEN_PIN 100
46
47 /* Maximum allowed size of key data as used in inquiries. */
48 #define MAXLEN_KEYDATA 4096
49
50 /* Maximum allowed size of certificate data as used in inquiries. */
51 #define MAXLEN_CERTDATA 16384
52
53
54 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
55
56
57 /* Macro to flag a removed card.  */
58 #define TEST_CARD_REMOVAL(c,r)                              \
59        do {                                                 \
60           int _r = (r);                                     \
61           if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \
62               || gpg_err_code (_r) == GPG_ERR_CARD_REMOVED) \
63             update_card_removed ((c)->reader_slot, 1);      \
64        } while (0)
65
66 #define IS_LOCKED(c)                                                     \
67      (locked_session && locked_session != (c)->server_local              \
68       && (c)->reader_slot != -1 && locked_session->ctrl_backlink         \
69       && (c)->reader_slot == locked_session->ctrl_backlink->reader_slot)
70
71
72 /* This structure is used to keep track of open readers (slots). */
73 struct slot_status_s 
74 {
75   int valid;  /* True if the other objects are valid. */
76   int slot;   /* Slot number of the reader or -1 if not open. */
77
78   int reset_failed; /* A reset failed. */
79
80   int any;    /* Flag indicating whether any status check has been
81                  done.  This is set once to indicate that the status
82                  tracking for the slot has been initialized.  */
83   unsigned int status;  /* Last status of the slot. */
84   unsigned int changed; /* Last change counter of the slot. */
85 };
86
87
88 /* Data used to associate an Assuan context with local server data.
89    This object describes the local properties of one session.  */
90 struct server_local_s 
91 {
92   /* We keep a list of all active sessions with the anchor at
93      SESSION_LIST (see below).  This field is used for linking. */
94   struct server_local_s *next_session; 
95
96   /* This object is usually assigned to a CTRL object (which is
97      globally visible).  While enumerating all sessions we sometimes
98      need to access data of the CTRL object; thus we keep a
99      backpointer here. */
100   ctrl_t ctrl_backlink;
101
102   /* The Assuan context used by this session/server. */
103   assuan_context_t assuan_ctx;
104
105 #ifdef HAVE_W32_SYSTEM
106   unsigned long event_signal;   /* Or 0 if not used. */
107 #else
108   int event_signal;             /* Or 0 if not used. */
109 #endif
110   
111   /* True if the card has been removed and a reset is required to
112      continue operation. */
113   int card_removed;        
114
115   /* Flag indicating that the application context needs to be released
116      at the next opportunity.  */
117   int app_ctx_marked_for_release;
118
119   /* A disconnect command has been sent.  */
120   int disconnect_allowed;
121
122   /* If set to true we will be terminate ourself at the end of the
123      this session.  */
124   int stopme;  
125
126 };
127
128
129 /* The table with information on all used slots.  FIXME: This is a
130    different slot number than the one used by the APDU layer, and
131    should be renamed.  */
132 static struct slot_status_s slot_table[10];
133
134
135 /* To keep track of all running sessions, we link all active server
136    contexts and the anchor in this variable.  */
137 static struct server_local_s *session_list;
138
139 /* If a session has been locked we store a link to its server object
140    in this variable. */
141 static struct server_local_s *locked_session;
142
143 /* While doing a reset we need to make sure that the ticker does not
144    call scd_update_reader_status_file while we are using it. */
145 static pth_mutex_t status_file_update_lock;
146
147 \f
148 /*-- Local prototypes --*/
149 static void update_reader_status_file (int set_card_removed_flag);
150
151
152 \f
153
154 /* This function must be called once to initialize this module.  This
155    has to be done before a second thread is spawned.  We can't do the
156    static initialization because Pth emulation code might not be able
157    to do a static init; in particular, it is not possible for W32. */
158 void
159 initialize_module_command (void)
160 {
161   static int initialized;
162
163   if (!initialized)
164     {
165       if (pth_mutex_init (&status_file_update_lock))
166         initialized = 1;
167     }
168 }
169
170
171 /* Update the CARD_REMOVED element of all sessions using the reader
172    given by SLOT to VALUE.  */
173 static void
174 update_card_removed (int slot, int value)
175 {
176   struct server_local_s *sl;
177
178   for (sl=session_list; sl; sl = sl->next_session)
179     if (sl->ctrl_backlink
180         && sl->ctrl_backlink->reader_slot == slot)
181       {
182         sl->card_removed = value;
183       }
184   /* Let the card application layer know about the removal.  */
185   if (value)
186     application_notify_card_reset (slot);
187 }
188
189
190
191 /* Check whether the option NAME appears in LINE.  Returns 1 or 0. */
192 static int
193 has_option (const char *line, const char *name)
194 {
195   const char *s;
196   int n = strlen (name);
197
198   s = strstr (line, name);
199   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
200 }
201
202 /* Same as has_option but does only test for the name of the option
203    and ignores an argument, i.e. with NAME being "--hash" it would
204    return a pointer for "--hash" as well as for "--hash=foo".  If
205    thhere is no such option NULL is returned.  The pointer returned
206    points right behind the option name, this may be an equal sign, Nul
207    or a space.  */
208 static const char *
209 has_option_name (const char *line, const char *name)
210 {
211   const char *s;
212   int n = strlen (name);
213
214   s = strstr (line, name);
215   return (s && (s == line || spacep (s-1))
216           && (!s[n] || spacep (s+n) || s[n] == '=')) ? (s+n) : NULL;
217 }
218
219
220 /* Skip over options.  It is assumed that leading spaces have been
221    removed (this is the case for lines passed to a handler from
222    assuan).  Blanks after the options are also removed. */
223 static char *
224 skip_options (char *line)
225 {
226   while ( *line == '-' && line[1] == '-' )
227     {
228       while (*line && !spacep (line))
229         line++;
230       while (spacep (line))
231         line++;
232     }
233   return line;
234 }
235
236
237
238 /* Convert the STRING into a newly allocated buffer while translating
239    the hex numbers.  Stops at the first invalid character.  Blanks and
240    colons are allowed to separate the hex digits.  Returns NULL on
241    error or a newly malloced buffer and its length in LENGTH.  */
242 static unsigned char *
243 hex_to_buffer (const char *string, size_t *r_length)
244 {
245   unsigned char *buffer;
246   const char *s;
247   size_t n;
248
249   buffer = xtrymalloc (strlen (string)+1);
250   if (!buffer)
251     return NULL;
252   for (s=string, n=0; *s; s++)
253     {
254       if (spacep (s) || *s == ':') 
255         continue;
256       if (hexdigitp (s) && hexdigitp (s+1))
257         {
258           buffer[n++] = xtoi_2 (s);
259           s++;
260         }
261       else
262         break;
263     }
264   *r_length = n;
265   return buffer;
266 }
267
268
269
270 /* Reset the card and free the application context.  With SEND_RESET
271    set to true actually send a RESET to the reader; this is the normal
272    way of calling the function.  */
273 static void
274 do_reset (ctrl_t ctrl, int send_reset)
275 {
276   int slot = ctrl->reader_slot;
277
278   if (!(slot == -1 || (slot >= 0 && slot < DIM(slot_table))))
279     BUG ();
280
281   /* If there is an active application, release it.  Tell all other
282      sessions using the same application to release the
283      application.  */
284   if (ctrl->app_ctx)
285     {
286       release_application (ctrl->app_ctx);
287       ctrl->app_ctx = NULL;
288       if (send_reset)
289         {
290           struct server_local_s *sl;
291           
292           for (sl=session_list; sl; sl = sl->next_session)
293             if (sl->ctrl_backlink
294                 && sl->ctrl_backlink->reader_slot == slot)
295               {
296                 sl->app_ctx_marked_for_release = 1;
297               }
298         }
299     }
300
301   /* If we want a real reset for the card, send the reset APDU and
302      tell the application layer about it.  */
303   if (slot != -1 && send_reset && !IS_LOCKED (ctrl) )
304     {
305       if (apdu_reset (slot)) 
306         {
307           slot_table[slot].reset_failed = 1;
308         }
309       application_notify_card_reset (slot);
310     }
311
312   /* If we hold a lock, unlock now. */
313   if (locked_session && ctrl->server_local == locked_session)
314     {
315       locked_session = NULL;
316       log_info ("implicitly unlocking due to RESET\n");
317     }
318
319   /* Reset the card removed flag for the current reader.  We need to
320      take the lock here so that the ticker thread won't concurrently
321      try to update the file.  Calling update_reader_status_file is
322      required to get hold of the new status of the card in the slot
323      table.  */
324   if (!pth_mutex_acquire (&status_file_update_lock, 0, NULL))
325     {
326       log_error ("failed to acquire status_fle_update lock\n");
327       ctrl->reader_slot = -1;
328       return;
329     }
330   update_reader_status_file (0);  /* Update slot status table.  */
331   update_card_removed (slot, 0);  /* Clear card_removed flag.  */
332   if (!pth_mutex_release (&status_file_update_lock))
333     log_error ("failed to release status_file_update lock\n");
334
335   /* Do this last, so that the update_card_removed above does its job.  */
336   ctrl->reader_slot = -1;
337 }
338
339 \f
340 static void
341 reset_notify (assuan_context_t ctx)
342 {
343   ctrl_t ctrl = assuan_get_pointer (ctx); 
344
345   do_reset (ctrl, 1);
346 }
347
348
349 static int
350 option_handler (assuan_context_t ctx, const char *key, const char *value)
351 {
352   ctrl_t ctrl = assuan_get_pointer (ctx);
353
354   if (!strcmp (key, "event-signal"))
355     {
356       /* A value of 0 is allowed to reset the event signal. */
357 #ifdef HAVE_W32_SYSTEM
358       if (!*value)
359         return gpg_error (GPG_ERR_ASS_PARAMETER);
360       ctrl->server_local->event_signal = strtoul (value, NULL, 16);
361 #else
362       int i = *value? atoi (value) : -1;
363       if (i < 0)
364         return gpg_error (GPG_ERR_ASS_PARAMETER);
365       ctrl->server_local->event_signal = i;
366 #endif
367     }
368
369  return 0;
370 }
371
372
373 /* Return the slot of the current reader or open the reader if no
374    other sessions are using a reader.  Note, that we currently support
375    only one reader but most of the code (except for this function)
376    should be able to cope with several readers.  */
377 static int
378 get_reader_slot (void)
379 {
380   struct slot_status_s *ss;
381
382   ss = &slot_table[0]; /* One reader for now. */
383
384   /* Initialize the item if needed. */
385   if (!ss->valid)
386     {
387       ss->slot = -1;
388       ss->valid = 1;
389     }
390
391   /* Try to open the reader. */
392   if (ss->slot == -1)
393     ss->slot = apdu_open_reader (opt.reader_port);
394
395   /* Return the slot_table index.  */
396   return 0;
397 }
398
399 /* If the card has not yet been opened, do it.  Note that this
400    function returns an Assuan error, so don't map the error a second
401    time.  */
402 static assuan_error_t
403 open_card (ctrl_t ctrl, const char *apptype)
404 {
405   gpg_error_t err;
406   int slot;
407
408   /* If we ever got a card not present error code, return that.  Only
409      the SERIALNO command and a reset are able to clear from that
410      state. */
411   if (ctrl->server_local->card_removed)
412     return gpg_error (GPG_ERR_CARD_REMOVED);
413
414   if ( IS_LOCKED (ctrl) )
415     return gpg_error (GPG_ERR_LOCKED);
416
417   /* If the application has been marked for release do it now.  We
418      can't do it immediately in do_reset because the application may
419      still be in use.  */
420   if (ctrl->server_local->app_ctx_marked_for_release)
421     {
422       ctrl->server_local->app_ctx_marked_for_release = 0;
423       release_application (ctrl->app_ctx);
424       ctrl->app_ctx = NULL;
425     }
426
427   /* If we are already initialized for one specific application we
428      need to check that the client didn't requested a specific
429      application different from the one in use before we continue. */
430   if (ctrl->app_ctx)
431     return check_application_conflict (ctrl, apptype);
432
433   /* Setup the slot and select the application.  */
434   if (ctrl->reader_slot != -1)
435     slot = ctrl->reader_slot;
436   else
437     slot = get_reader_slot ();
438   ctrl->reader_slot = slot;
439   if (slot == -1)
440     err = gpg_error (GPG_ERR_CARD);
441   else
442     {
443       /* Fixme: We should move the apdu_connect call to
444          select_application.  */
445       int sw;
446
447       ctrl->server_local->disconnect_allowed = 0;
448       sw = apdu_connect (slot);
449       if (sw && sw != SW_HOST_ALREADY_CONNECTED)
450         {
451           if (sw == SW_HOST_NO_CARD)
452             err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
453           else
454             err = gpg_error (GPG_ERR_CARD);
455         }
456       else
457         err = select_application (ctrl, slot, apptype, &ctrl->app_ctx);
458     }
459
460   TEST_CARD_REMOVAL (ctrl, err);
461   return err;
462 }
463
464
465 /* Do the percent and plus/space unescaping in place and return the
466    length of the valid buffer. */
467 static size_t
468 percent_plus_unescape (unsigned char *string)
469 {
470   unsigned char *p = string;
471   size_t n = 0;
472
473   while (*string)
474     {
475       if (*string == '%' && string[1] && string[2])
476         { 
477           string++;
478           *p++ = xtoi_2 (string);
479           n++;
480           string+= 2;
481         }
482       else if (*string == '+')
483         {
484           *p++ = ' ';
485           n++;
486           string++;
487         }
488       else
489         {
490           *p++ = *string++;
491           n++;
492         }
493     }
494
495   return n;
496 }
497
498
499
500 /* SERIALNO [APPTYPE] 
501
502    Return the serial number of the card using a status reponse.  This
503    function should be used to check for the presence of a card.
504
505    If APPTYPE is given, an application of that type is selected and an
506    error is returned if the application is not supported or available.
507    The default is to auto-select the application using a hardwired
508    preference system.  Note, that a future extension to this function
509    may allow to specify a list and order of applications to try.
510
511    This function is special in that it can be used to reset the card.
512    Most other functions will return an error when a card change has
513    been detected and the use of this function is therefore required.
514
515    Background: We want to keep the client clear of handling card
516    changes between operations; i.e. the client can assume that all
517    operations are done on the same card unless he calls this function.
518  */
519 static int
520 cmd_serialno (assuan_context_t ctx, char *line)
521 {
522   ctrl_t ctrl = assuan_get_pointer (ctx);
523   int rc = 0;
524   char *serial_and_stamp;
525   char *serial;
526   time_t stamp;
527
528   /* Clear the remove flag so that the open_card is able to reread it.  */
529   if (ctrl->server_local->card_removed)
530     {
531       if ( IS_LOCKED (ctrl) )
532         return gpg_error (GPG_ERR_LOCKED);
533       do_reset (ctrl, 1);
534     }
535
536   if ((rc = open_card (ctrl, *line? line:NULL)))
537     return rc;
538
539   rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
540   if (rc)
541     return rc;
542
543   rc = estream_asprintf (&serial_and_stamp, "%s %lu",
544                          serial, (unsigned long)stamp);
545   xfree (serial);
546   if (rc < 0)
547     return out_of_core ();
548   rc = 0;
549   assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
550   xfree (serial_and_stamp);
551   return 0;
552 }
553
554
555
556
557 /* LEARN [--force] [--keypairinfo]
558
559    Learn all useful information of the currently inserted card.  When
560    used without the force options, the command might do an INQUIRE
561    like this:
562
563       INQUIRE KNOWNCARDP <hexstring_with_serialNumber> <timestamp>
564
565    The client should just send an "END" if the processing should go on
566    or a "CANCEL" to force the function to terminate with a Cancel
567    error message.  
568
569    With the option --keypairinfo only KEYPARIINFO lstatus lines are
570    returned.
571
572    The response of this command is a list of status lines formatted as
573    this:
574
575      S APPTYPE <apptype>
576
577    This returns the type of the application, currently the strings:
578
579        P15     = PKCS-15 structure used
580        DINSIG  = DIN SIG
581        OPENPGP = OpenPGP card
582        NKS     = NetKey card
583
584    are implemented.  These strings are aliases for the AID
585
586      S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id>
587
588    If there is no certificate yet stored on the card a single "X" is
589    returned as the keygrip.  In addition to the keypair info, information
590    about all certificates stored on the card is also returned:
591
592      S CERTINFO <certtype> <hexstring_with_id>
593
594    Where CERTTYPE is a number indicating the type of certificate:
595       0   := Unknown
596       100 := Regular X.509 cert
597       101 := Trusted X.509 cert
598       102 := Useful X.509 cert
599       110 := Root CA cert (e.g. DINSIG)
600
601    For certain cards, more information will be returned:
602
603      S KEY-FPR <no> <hexstring>
604
605    For OpenPGP cards this returns the stored fingerprints of the
606    keys. This can be used check whether a key is available on the
607    card.  NO may be 1, 2 or 3.
608
609      S CA-FPR <no> <hexstring>
610
611    Similar to above, these are the fingerprints of keys assumed to be
612    ultimately trusted.
613
614      S DISP-NAME <name_of_card_holder>
615
616    The name of the card holder as stored on the card; percent
617    escaping takes place, spaces are encoded as '+'
618
619      S PUBKEY-URL <url>
620
621    The URL to be used for locating the entire public key.
622      
623    Note, that this function may even be used on a locked card.
624 */
625 static int
626 cmd_learn (assuan_context_t ctx, char *line)
627 {
628   ctrl_t ctrl = assuan_get_pointer (ctx);
629   int rc = 0;
630   int only_keypairinfo = has_option (line, "--keypairinfo");
631
632   if ((rc = open_card (ctrl, NULL)))
633     return rc;
634
635   /* Unless the force option is used we try a shortcut by identifying
636      the card using a serial number and inquiring the client with
637      that. The client may choose to cancel the operation if he already
638      knows about this card */
639   if (!only_keypairinfo)
640     {
641       char *serial_and_stamp;
642       char *serial;
643       time_t stamp;
644       
645       rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
646       if (rc)
647         return rc;
648       rc = estream_asprintf (&serial_and_stamp, "%s %lu",
649                              serial, (unsigned long)stamp);
650       xfree (serial);
651       if (rc < 0)
652         return out_of_core ();
653       rc = 0;
654       assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
655       
656       if (!has_option (line, "--force"))
657         {
658           char *command;
659           
660           rc = estream_asprintf (&command, "KNOWNCARDP %s", serial_and_stamp);
661           if (rc < 0)
662             {
663               xfree (serial_and_stamp);
664               return out_of_core ();
665             }
666           rc = 0;
667           rc = assuan_inquire (ctx, command, NULL, NULL, 0); 
668           xfree (command);
669           if (rc)
670             {
671               if (gpg_err_code (rc) != GPG_ERR_ASS_CANCELED)
672                 log_error ("inquire KNOWNCARDP failed: %s\n",
673                            gpg_strerror (rc));
674               xfree (serial_and_stamp);
675               return rc; 
676             }
677           /* Not canceled, so we have to proceeed.  */
678         }
679       xfree (serial_and_stamp);
680     }
681   
682   /* Let the application print out its collection of useful status
683      information. */
684   if (!rc)
685     rc = app_write_learn_status (ctrl->app_ctx, ctrl, only_keypairinfo);
686
687   TEST_CARD_REMOVAL (ctrl, rc);
688   return rc;
689 }
690
691
692 \f
693 /* READCERT <hexified_certid>|<keyid>
694
695    Note, that this function may even be used on a locked card.
696  */
697 static int
698 cmd_readcert (assuan_context_t ctx, char *line)
699 {
700   ctrl_t ctrl = assuan_get_pointer (ctx);
701   int rc;
702   unsigned char *cert;
703   size_t ncert;
704
705   if ((rc = open_card (ctrl, NULL)))
706     return rc;
707
708   line = xstrdup (line); /* Need a copy of the line. */
709   rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
710   if (rc)
711     log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
712   xfree (line);
713   line = NULL;
714   if (!rc)
715     {
716       rc = assuan_send_data (ctx, cert, ncert);
717       xfree (cert);
718       if (rc)
719         return rc;
720     }
721
722   TEST_CARD_REMOVAL (ctrl, rc);
723   return rc;
724 }
725
726
727 /* READKEY <keyid>
728
729    Return the public key for the given cert or key ID as an standard
730    S-Expression.
731
732    Note, that this function may even be used on a locked card.
733   */
734 static int
735 cmd_readkey (assuan_context_t ctx, char *line)
736 {
737   ctrl_t ctrl = assuan_get_pointer (ctx);
738   int rc;
739   unsigned char *cert = NULL;
740   size_t ncert, n;
741   ksba_cert_t kc = NULL;
742   ksba_sexp_t p;
743   unsigned char *pk;
744   size_t pklen;
745
746   if ((rc = open_card (ctrl, NULL)))
747     return rc;
748
749   line = xstrdup (line); /* Need a copy of the line. */
750   /* If the application supports the READKEY function we use that.
751      Otherwise we use the old way by extracting it from the
752      certificate.  */
753   rc = app_readkey (ctrl->app_ctx, line, &pk, &pklen);
754   if (!rc)
755     { /* Yeah, got that key - send it back.  */
756       rc = assuan_send_data (ctx, pk, pklen);
757       xfree (pk);
758       xfree (line);
759       line = NULL;
760       goto leave;
761     }
762
763   if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION)
764     log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
765   else  
766     {
767       rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
768       if (rc)
769         log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
770     }
771   xfree (line);
772   line = NULL;
773   if (rc)
774     goto leave;
775       
776   rc = ksba_cert_new (&kc);
777   if (rc)
778     {
779       xfree (cert);
780       goto leave;
781     }
782   rc = ksba_cert_init_from_mem (kc, cert, ncert);
783   if (rc)
784     {
785       log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
786       goto leave;
787     }
788
789   p = ksba_cert_get_public_key (kc);
790   if (!p)
791     {
792       rc = gpg_error (GPG_ERR_NO_PUBKEY);
793       goto leave;
794     }
795
796   n = gcry_sexp_canon_len (p, 0, NULL, NULL);
797   rc = assuan_send_data (ctx, p, n);
798   xfree (p);
799
800
801  leave:
802   ksba_cert_release (kc);
803   xfree (cert);
804   TEST_CARD_REMOVAL (ctrl, rc);
805   return rc;
806 }
807
808
809 \f
810
811 /* SETDATA <hexstring> 
812
813    The client should use this command to tell us the data he want to
814    sign.  */
815 static int
816 cmd_setdata (assuan_context_t ctx, char *line)
817 {
818   ctrl_t ctrl = assuan_get_pointer (ctx);
819   int n;
820   char *p;
821   unsigned char *buf;
822
823   if (locked_session && locked_session != ctrl->server_local)
824     return gpg_error (GPG_ERR_LOCKED);
825
826   /* Parse the hexstring. */
827   for (p=line,n=0; hexdigitp (p); p++, n++)
828     ;
829   if (*p)
830     return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
831   if (!n)
832     return set_error (GPG_ERR_ASS_PARAMETER, "no data given");
833   if ((n&1))
834     return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
835   n /= 2;
836   buf = xtrymalloc (n);
837   if (!buf)
838     return out_of_core ();
839
840   ctrl->in_data.value = buf;
841   ctrl->in_data.valuelen = n;
842   for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++)
843     buf[n] = xtoi_2 (p);
844   return 0;
845 }
846
847
848
849 static gpg_error_t 
850 pin_cb (void *opaque, const char *info, char **retstr)
851 {
852   assuan_context_t ctx = opaque;
853   char *command;
854   int rc;
855   unsigned char *value;
856   size_t valuelen;
857
858   if (!retstr)
859     {
860       /* We prompt for keypad entry.  To make sure that the popup has
861          been show we use an inquire and not just a status message.
862          We ignore any value returned.  */
863       if (info)
864         {
865           log_debug ("prompting for keypad entry '%s'\n", info);
866           rc = estream_asprintf (&command, "POPUPKEYPADPROMPT %s", info);
867           if (rc < 0)
868             return gpg_error (gpg_err_code_from_errno (errno));
869           rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); 
870           xfree (command);  
871         }
872       else
873         {
874           log_debug ("dismiss keypad entry prompt\n");
875           rc = assuan_inquire (ctx, "DISMISSKEYPADPROMPT",
876                                &value, &valuelen, MAXLEN_PIN); 
877         }
878       if (!rc)
879         xfree (value);
880       return rc;
881     }
882
883   *retstr = NULL;
884   log_debug ("asking for PIN '%s'\n", info);
885
886   rc = estream_asprintf (&command, "NEEDPIN %s", info);
887   if (rc < 0)
888     return gpg_error (gpg_err_code_from_errno (errno));
889
890   /* Fixme: Write an inquire function which returns the result in
891      secure memory and check all further handling of the PIN. */
892   rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); 
893   xfree (command);  
894   if (rc)
895     return rc;
896
897   if (!valuelen || value[valuelen-1])
898     {
899       /* We require that the returned value is an UTF-8 string */
900       xfree (value);
901       return gpg_error (GPG_ERR_INV_RESPONSE);
902     }
903   *retstr = (char*)value;
904   return 0;
905 }
906
907
908 /* PKSIGN [--hash=[rmd160|sha1|md5]] <hexified_id>
909
910    The --hash option is optional; the default is SHA1.
911
912  */
913 static int
914 cmd_pksign (assuan_context_t ctx, char *line)
915 {
916   ctrl_t ctrl = assuan_get_pointer (ctx);
917   int rc;
918   unsigned char *outdata;
919   size_t outdatalen;
920   char *keyidstr;
921   int hash_algo;
922
923   if (has_option (line, "--hash=rmd160"))
924     hash_algo = GCRY_MD_RMD160;
925   else if (has_option (line, "--hash=sha1"))
926     hash_algo = GCRY_MD_SHA1;
927   else if (has_option (line, "--hash=md5"))
928     hash_algo = GCRY_MD_MD5;
929   else if (!strstr (line, "--"))
930     hash_algo = GCRY_MD_SHA1; 
931   else
932     return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
933
934   line = skip_options (line);
935
936   if ( IS_LOCKED (ctrl) )
937     return gpg_error (GPG_ERR_LOCKED);
938
939   if ((rc = open_card (ctrl, NULL)))
940     return rc;
941
942   /* We have to use a copy of the key ID because the function may use
943      the pin_cb which in turn uses the assuan line buffer and thus
944      overwriting the original line with the keyid */
945   keyidstr = xtrystrdup (line);
946   if (!keyidstr)
947     return out_of_core ();
948   
949   rc = app_sign (ctrl->app_ctx,
950                  keyidstr, hash_algo,
951                  pin_cb, ctx,
952                  ctrl->in_data.value, ctrl->in_data.valuelen,
953                  &outdata, &outdatalen);
954
955   xfree (keyidstr);
956   if (rc)
957     {
958       log_error ("card_sign failed: %s\n", gpg_strerror (rc));
959     }
960   else
961     {
962       rc = assuan_send_data (ctx, outdata, outdatalen);
963       xfree (outdata);
964       if (rc)
965         return rc; /* that is already an assuan error code */
966     }
967
968   TEST_CARD_REMOVAL (ctrl, rc);
969   return rc;
970 }
971
972 /* PKAUTH <hexified_id>
973
974  */
975 static int
976 cmd_pkauth (assuan_context_t ctx, char *line)
977 {
978   ctrl_t ctrl = assuan_get_pointer (ctx);
979   int rc;
980   unsigned char *outdata;
981   size_t outdatalen;
982   char *keyidstr;
983
984   if ( IS_LOCKED (ctrl) )
985     return gpg_error (GPG_ERR_LOCKED);
986
987   if ((rc = open_card (ctrl, NULL)))
988     return rc;
989
990   if (!ctrl->app_ctx)
991     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
992
993  /* We have to use a copy of the key ID because the function may use
994      the pin_cb which in turn uses the assuan line buffer and thus
995      overwriting the original line with the keyid */
996   keyidstr = xtrystrdup (line);
997   if (!keyidstr)
998     return out_of_core ();
999   
1000   rc = app_auth (ctrl->app_ctx,
1001                  keyidstr,
1002                  pin_cb, ctx,
1003                  ctrl->in_data.value, ctrl->in_data.valuelen,
1004                  &outdata, &outdatalen);
1005   xfree (keyidstr);
1006   if (rc)
1007     {
1008       log_error ("app_auth_sign failed: %s\n", gpg_strerror (rc));
1009     }
1010   else
1011     {
1012       rc = assuan_send_data (ctx, outdata, outdatalen);
1013       xfree (outdata);
1014       if (rc)
1015         return rc; /* that is already an assuan error code */
1016     }
1017
1018   TEST_CARD_REMOVAL (ctrl, rc);
1019   return rc;
1020 }
1021
1022 /* PKDECRYPT <hexified_id>
1023
1024  */
1025 static int
1026 cmd_pkdecrypt (assuan_context_t ctx, char *line)
1027 {
1028   ctrl_t ctrl = assuan_get_pointer (ctx);
1029   int rc;
1030   unsigned char *outdata;
1031   size_t outdatalen;
1032   char *keyidstr;
1033
1034   if ( IS_LOCKED (ctrl) )
1035     return gpg_error (GPG_ERR_LOCKED);
1036
1037   if ((rc = open_card (ctrl, NULL)))
1038     return rc;
1039
1040   keyidstr = xtrystrdup (line);
1041   if (!keyidstr)
1042     return out_of_core ();
1043   rc = app_decipher (ctrl->app_ctx,
1044                      keyidstr, 
1045                      pin_cb, ctx,
1046                      ctrl->in_data.value, ctrl->in_data.valuelen,
1047                      &outdata, &outdatalen);
1048
1049   xfree (keyidstr);
1050   if (rc)
1051     {
1052       log_error ("card_create_signature failed: %s\n", gpg_strerror (rc));
1053     }
1054   else
1055     {
1056       rc = assuan_send_data (ctx, outdata, outdatalen);
1057       xfree (outdata);
1058       if (rc)
1059         return rc; /* that is already an assuan error code */
1060     }
1061
1062   TEST_CARD_REMOVAL (ctrl, rc);
1063   return rc;
1064 }
1065
1066
1067 /* GETATTR <name>
1068
1069    This command is used to retrieve data from a smartcard.  The
1070    allowed names depend on the currently selected smartcard
1071    application.  NAME must be percent and '+' escaped.  The value is
1072    returned through status message, see the LEARN command for details.
1073
1074    However, the current implementation assumes that Name is not escaped;
1075    this works as long as noone uses arbitrary escaping. 
1076  
1077    Note, that this function may even be used on a locked card.
1078 */
1079 static int
1080 cmd_getattr (assuan_context_t ctx, char *line)
1081 {
1082   ctrl_t ctrl = assuan_get_pointer (ctx);
1083   int rc;
1084   const char *keyword;
1085
1086   if ((rc = open_card (ctrl, NULL)))
1087     return rc;
1088
1089   keyword = line;
1090   for (; *line && !spacep (line); line++)
1091     ;
1092   if (*line)
1093       *line++ = 0;
1094
1095   /* (We ignore any garbage for now.) */
1096
1097   /* FIXME: Applications should not return sensitive data if the card
1098      is locked.  */
1099   rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
1100
1101   TEST_CARD_REMOVAL (ctrl, rc);
1102   return rc;
1103 }
1104
1105
1106 /* SETATTR <name> <value> 
1107
1108    This command is used to store data on a a smartcard.  The allowed
1109    names and values are depend on the currently selected smartcard
1110    application.  NAME and VALUE must be percent and '+' escaped.
1111
1112    However, the current implementation assumes that NAME is not
1113    escaped; this works as long as noone uses arbitrary escaping.
1114  
1115    A PIN will be requested for most NAMEs.  See the corresponding
1116    setattr function of the actually used application (app-*.c) for
1117    details.  */
1118 static int
1119 cmd_setattr (assuan_context_t ctx, char *orig_line)
1120 {
1121   ctrl_t ctrl = assuan_get_pointer (ctx);
1122   int rc;
1123   char *keyword;
1124   int keywordlen;
1125   size_t nbytes;
1126   char *line, *linebuf;
1127
1128   if ( IS_LOCKED (ctrl) )
1129     return gpg_error (GPG_ERR_LOCKED);
1130
1131   if ((rc = open_card (ctrl, NULL)))
1132     return rc;
1133
1134   /* We need to use a copy of LINE, because PIN_CB uses the same
1135      context and thus reuses the Assuan provided LINE. */
1136   line = linebuf = xtrystrdup (orig_line);
1137   if (!line)
1138     return out_of_core ();
1139
1140   keyword = line;
1141   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
1142     ;
1143   if (*line)
1144       *line++ = 0;
1145   while (spacep (line))
1146     line++;
1147   nbytes = percent_plus_unescape ((unsigned char*)line);
1148
1149   rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx,
1150                     (const unsigned char*)line, nbytes);
1151   xfree (linebuf);
1152
1153   TEST_CARD_REMOVAL (ctrl, rc);
1154   return rc;
1155 }
1156
1157
1158
1159 /* WRITECERT <hexified_certid>
1160
1161    This command is used to store a certifciate on a smartcard.  The
1162    allowed certids depend on the currently selected smartcard
1163    application. The actual certifciate is requested using the inquiry
1164    "CERTDATA" and needs to be provided in its raw (e.g. DER) form.
1165
1166    In almost all cases a a PIN will be requested.  See the related
1167    writecert function of the actually used application (app-*.c) for
1168    details.  */
1169 static int
1170 cmd_writecert (assuan_context_t ctx, char *line)
1171 {
1172   ctrl_t ctrl = assuan_get_pointer (ctx);
1173   int rc;
1174   char *certid;
1175   unsigned char *certdata;
1176   size_t certdatalen;
1177
1178   if ( IS_LOCKED (ctrl) )
1179     return gpg_error (GPG_ERR_LOCKED);
1180
1181   line = skip_options (line);
1182
1183   if (!*line)
1184     return set_error (GPG_ERR_ASS_PARAMETER, "no certid given");
1185   certid = line;
1186   while (*line && !spacep (line))
1187     line++;
1188   *line = 0;
1189
1190   if ((rc = open_card (ctrl, NULL)))
1191     return rc;
1192
1193   if (!ctrl->app_ctx)
1194     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1195
1196   certid = xtrystrdup (certid);
1197   if (!certid)
1198     return out_of_core ();
1199
1200   /* Now get the actual keydata. */
1201   rc = assuan_inquire (ctx, "CERTDATA",
1202                        &certdata, &certdatalen, MAXLEN_CERTDATA);
1203   if (rc)
1204     {
1205       xfree (certid);
1206       return rc;
1207     }
1208
1209   /* Write the certificate to the card. */
1210   rc = app_writecert (ctrl->app_ctx, ctrl, certid, 
1211                       pin_cb, ctx, certdata, certdatalen);
1212   xfree (certid);
1213   xfree (certdata);
1214
1215   TEST_CARD_REMOVAL (ctrl, rc);
1216   return rc;
1217 }
1218
1219
1220
1221 /* WRITEKEY [--force] <keyid> 
1222
1223    This command is used to store a secret key on a a smartcard.  The
1224    allowed keyids depend on the currently selected smartcard
1225    application. The actual keydata is requested using the inquiry
1226    "KEYDATA" and need to be provided without any protection.  With
1227    --force set an existing key under this KEYID will get overwritten.
1228    The keydata is expected to be the usual canonical encoded
1229    S-expression.
1230
1231    A PIN will be requested for most NAMEs.  See the corresponding
1232    writekey function of the actually used application (app-*.c) for
1233    details.  */
1234 static int
1235 cmd_writekey (assuan_context_t ctx, char *line)
1236 {
1237   ctrl_t ctrl = assuan_get_pointer (ctx);
1238   int rc;
1239   char *keyid;
1240   int force = has_option (line, "--force");
1241   unsigned char *keydata;
1242   size_t keydatalen;
1243
1244   if ( IS_LOCKED (ctrl) )
1245     return gpg_error (GPG_ERR_LOCKED);
1246
1247   line = skip_options (line);
1248
1249   if (!*line)
1250     return set_error (GPG_ERR_ASS_PARAMETER, "no keyid given");
1251   keyid = line;
1252   while (*line && !spacep (line))
1253     line++;
1254   *line = 0;
1255
1256   if ((rc = open_card (ctrl, NULL)))
1257     return rc;
1258
1259   if (!ctrl->app_ctx)
1260     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1261
1262   keyid = xtrystrdup (keyid);
1263   if (!keyid)
1264     return out_of_core ();
1265
1266   /* Now get the actual keydata. */
1267   assuan_begin_confidential (ctx);
1268   rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA);
1269   assuan_end_confidential (ctx);
1270   if (rc)
1271     {
1272       xfree (keyid);
1273       return rc;
1274     }
1275
1276   /* Write the key to the card. */
1277   rc = app_writekey (ctrl->app_ctx, ctrl, keyid, force? 1:0,
1278                      pin_cb, ctx, keydata, keydatalen);
1279   xfree (keyid);
1280   xfree (keydata);
1281
1282   TEST_CARD_REMOVAL (ctrl, rc);
1283   return rc;
1284 }
1285
1286
1287
1288 /* GENKEY [--force] [--timestamp=<isodate>] <no>
1289
1290    Generate a key on-card identified by NO, which is application
1291    specific.  Return values are application specific.  For OpenPGP
1292    cards 2 status lines are returned:
1293
1294      S KEY-FPR  <hexstring>
1295      S KEY-CREATED-AT <seconds_since_epoch>
1296      S KEY-DATA [p|n] <hexdata>
1297      
1298    --force is required to overwrite an already existing key.  The
1299    KEY-CREATED-AT is required for further processing because it is
1300    part of the hashed key material for the fingerprint.
1301
1302    If --timestamp is given an OpenPGP key will be created using this
1303    value.  The value needs to be in ISO Format; e.g.
1304    "--timestamp=20030316T120000" and after 1970-01-01 00:00:00.
1305
1306    The public part of the key can also later be retrieved using the
1307    READKEY command.
1308
1309  */
1310 static int
1311 cmd_genkey (assuan_context_t ctx, char *line)
1312 {
1313   ctrl_t ctrl = assuan_get_pointer (ctx);
1314   int rc;
1315   char *keyno;
1316   int force;
1317   const char *s;
1318   time_t timestamp;
1319
1320   if ( IS_LOCKED (ctrl) )
1321     return gpg_error (GPG_ERR_LOCKED);
1322
1323   force = has_option (line, "--force");
1324
1325   if ((s=has_option_name (line, "--timestamp")))
1326     {
1327       if (*s != '=')
1328         return set_error (GPG_ERR_ASS_PARAMETER, "missing value for option");
1329       timestamp = isotime2epoch (s+1);
1330       if (timestamp < 1)
1331         return set_error (GPG_ERR_ASS_PARAMETER, "invalid time value");
1332     }
1333   else
1334     timestamp = 0;
1335
1336
1337   line = skip_options (line);
1338   if (!*line)
1339     return set_error (GPG_ERR_ASS_PARAMETER, "no key number given");
1340   keyno = line;
1341   while (*line && !spacep (line))
1342     line++;
1343   *line = 0;
1344
1345   if ((rc = open_card (ctrl, NULL)))
1346     return rc;
1347
1348   if (!ctrl->app_ctx)
1349     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1350
1351   keyno = xtrystrdup (keyno);
1352   if (!keyno)
1353     return out_of_core ();
1354   rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0,
1355                    timestamp, pin_cb, ctx);
1356   xfree (keyno);
1357
1358   TEST_CARD_REMOVAL (ctrl, rc);
1359   return rc;
1360 }
1361
1362
1363 /* RANDOM <nbytes>
1364
1365    Get NBYTES of random from the card and send them back as data. 
1366
1367    Note, that this function may be even be used on a locked card.
1368 */
1369 static int
1370 cmd_random (assuan_context_t ctx, char *line)
1371 {
1372   ctrl_t ctrl = assuan_get_pointer (ctx);
1373   int rc;
1374   size_t nbytes;
1375   unsigned char *buffer;
1376
1377   if (!*line)
1378     return set_error (GPG_ERR_ASS_PARAMETER, "number of requested bytes missing");
1379   nbytes = strtoul (line, NULL, 0);
1380
1381   if ((rc = open_card (ctrl, NULL)))
1382     return rc;
1383
1384   if (!ctrl->app_ctx)
1385     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1386
1387   buffer = xtrymalloc (nbytes);
1388   if (!buffer)
1389     return out_of_core ();
1390
1391   rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
1392   if (!rc)
1393     {
1394       rc = assuan_send_data (ctx, buffer, nbytes);
1395       xfree (buffer);
1396       return rc; /* that is already an assuan error code */
1397     }
1398   xfree (buffer);
1399
1400   TEST_CARD_REMOVAL (ctrl, rc);
1401   return rc;
1402 }
1403
1404 \f
1405 /* PASSWD [--reset] [--nullpin] <chvno>
1406   
1407    Change the PIN or, if --reset is given, reset the retry counter of
1408    the card holder verfication vector CHVNO.  The option --nullpin is
1409    used for TCOS cards to set the initial PIN.  The format of CHVNO
1410    depends on the card application.  */
1411 static int
1412 cmd_passwd (assuan_context_t ctx, char *line)
1413 {
1414   ctrl_t ctrl = assuan_get_pointer (ctx);
1415   int rc;
1416   char *chvnostr;
1417   unsigned int flags = 0;
1418
1419   if (has_option (line, "--reset"))
1420     flags |= APP_CHANGE_FLAG_RESET;
1421   if (has_option (line, "--nullpin"))
1422     flags |= APP_CHANGE_FLAG_NULLPIN;
1423
1424   if ( IS_LOCKED (ctrl) )
1425     return gpg_error (GPG_ERR_LOCKED);
1426
1427   line = skip_options (line);
1428
1429   if (!*line)
1430     return set_error (GPG_ERR_ASS_PARAMETER, "no CHV number given");
1431   chvnostr = line;
1432   while (*line && !spacep (line))
1433     line++;
1434   *line = 0;
1435
1436   if ((rc = open_card (ctrl, NULL)))
1437     return rc;
1438
1439   if (!ctrl->app_ctx)
1440     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1441   
1442   chvnostr = xtrystrdup (chvnostr);
1443   if (!chvnostr)
1444     return out_of_core ();
1445   rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, flags, pin_cb, ctx);
1446   if (rc)
1447     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1448   xfree (chvnostr);
1449
1450   TEST_CARD_REMOVAL (ctrl, rc);
1451   return rc;
1452 }
1453
1454
1455 /* CHECKPIN <idstr>
1456
1457    Perform a VERIFY operation without doing anything else.  This may
1458    be used to initialize a the PIN cache earlier to long lasting
1459    operations.  Its use is highly application dependent.
1460
1461    For OpenPGP:
1462
1463       Perform a simple verify operation for CHV1 and CHV2, so that
1464       further operations won't ask for CHV2 and it is possible to do a
1465       cheap check on the PIN: If there is something wrong with the PIN
1466       entry system, only the regular CHV will get blocked and not the
1467       dangerous CHV3.  IDSTR is the usual card's serial number in hex
1468       notation; an optional fingerprint part will get ignored.  There
1469       is however a special mode if the IDSTR is sffixed with the
1470       literal string "[CHV3]": In this case the Admin PIN is checked
1471       if and only if the retry counter is still at 3.
1472
1473    For Netkey:
1474
1475       Any of the valid PIN Ids may be used.  These are the strings:
1476
1477         PW1.CH       - Global password 1
1478         PW2.CH       - Global password 2
1479         PW1.CH.SIG   - SigG password 1
1480         PW2.CH.SIG   - SigG password 2
1481
1482       For a definitive list, see the implementation in app-nks.c.
1483       Note that we call a PW2.* PIN a "PUK" despite that since TCOS
1484       3.0 they are technically alternative PINs used to mutally
1485       unblock each other.
1486
1487  */
1488 static int
1489 cmd_checkpin (assuan_context_t ctx, char *line)
1490 {
1491   ctrl_t ctrl = assuan_get_pointer (ctx);
1492   int rc;
1493   char *idstr;
1494
1495   if ( IS_LOCKED (ctrl) )
1496     return gpg_error (GPG_ERR_LOCKED);
1497
1498   if ((rc = open_card (ctrl, NULL)))
1499     return rc;
1500
1501   if (!ctrl->app_ctx)
1502     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1503
1504   /* We have to use a copy of the key ID because the function may use
1505      the pin_cb which in turn uses the assuan line buffer and thus
1506      overwriting the original line with the keyid. */
1507   idstr = xtrystrdup (line);
1508   if (!idstr)
1509     return out_of_core ();
1510   
1511   rc = app_check_pin (ctrl->app_ctx, idstr, pin_cb, ctx);
1512   xfree (idstr);
1513   if (rc)
1514     log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
1515
1516   TEST_CARD_REMOVAL (ctrl, rc);
1517   return rc;
1518 }
1519
1520
1521 /* LOCK [--wait]
1522
1523    Grant exclusive card access to this session.  Note that there is
1524    no lock counter used and a second lock from the same session will
1525    be ignored.  A single unlock (or RESET) unlocks the session.
1526    Return GPG_ERR_LOCKED if another session has locked the reader.
1527
1528    If the option --wait is given the command will wait until a
1529    lock has been released.
1530  */
1531 static int
1532 cmd_lock (assuan_context_t ctx, char *line)
1533 {
1534   ctrl_t ctrl = assuan_get_pointer (ctx);
1535   int rc = 0;
1536
1537  retry:
1538   if (locked_session)
1539     {
1540       if (locked_session != ctrl->server_local)
1541         rc = gpg_error (GPG_ERR_LOCKED);
1542     }
1543   else
1544     locked_session = ctrl->server_local;
1545
1546 #ifdef USE_GNU_PTH
1547   if (rc && has_option (line, "--wait"))
1548     {
1549       rc = 0;
1550       pth_sleep (1); /* Better implement an event mechanism. However,
1551                         for card operations this should be
1552                         sufficient. */
1553       /* FIXME: Need to check that the connection is still alive.
1554          This can be done by issuing status messages. */
1555       goto retry;
1556     }
1557 #endif /*USE_GNU_PTH*/
1558   
1559   if (rc)
1560     log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
1561   return rc;
1562 }
1563
1564
1565 /* UNLOCK
1566
1567    Release exclusive card access.
1568  */
1569 static int
1570 cmd_unlock (assuan_context_t ctx, char *line)
1571 {
1572   ctrl_t ctrl = assuan_get_pointer (ctx);
1573   int rc = 0;
1574
1575   (void)line;
1576
1577   if (locked_session)
1578     {
1579       if (locked_session != ctrl->server_local)
1580         rc = gpg_error (GPG_ERR_LOCKED);
1581       else
1582         locked_session = NULL;
1583     }
1584   else
1585     rc = gpg_error (GPG_ERR_NOT_LOCKED);
1586
1587   if (rc)
1588     log_error ("cmd_unlock failed: %s\n", gpg_strerror (rc));
1589   return rc;
1590 }
1591
1592
1593 /* GETINFO <what>
1594
1595    Multi purpose command to return certain information.  
1596    Supported values of WHAT are:
1597
1598    version     - Return the version of the program.
1599    pid         - Return the process id of the server.
1600
1601    socket_name - Return the name of the socket.
1602
1603    status - Return the status of the current slot (in the future, may
1604    also return the status of all slots).  The status is a list of
1605    one-character flags.  The following flags are currently defined:
1606      'u'  Usable card present.  This is the normal state during operation.
1607      'r'  Card removed.  A reset is necessary.
1608    These flags are exclusive.
1609
1610    reader_list - Return a list of detected card readers.  Does
1611                  currently only work with the internal CCID driver.
1612
1613    deny_admin  - Returns OK if admin commands are not allowed or
1614                  GPG_ERR_GENERAL if admin commands are allowed.
1615
1616    app_list    - Return a list of supported applications.  One
1617                  application per line, fields delimited by colons,
1618                  first field is the name.
1619 */
1620
1621 static int
1622 cmd_getinfo (assuan_context_t ctx, char *line)
1623 {
1624   int rc = 0;
1625
1626   if (!strcmp (line, "version"))
1627     {
1628       const char *s = VERSION;
1629       rc = assuan_send_data (ctx, s, strlen (s));
1630     }
1631   else if (!strcmp (line, "pid"))
1632     {
1633       char numbuf[50];
1634
1635       snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1636       rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1637     }
1638   else if (!strcmp (line, "socket_name"))
1639     {
1640       const char *s = scd_get_socket_name ();
1641
1642       if (s)
1643         rc = assuan_send_data (ctx, s, strlen (s));
1644       else
1645         rc = gpg_error (GPG_ERR_NO_DATA);
1646     }
1647   else if (!strcmp (line, "status"))
1648     {
1649       ctrl_t ctrl = assuan_get_pointer (ctx);
1650       int slot = ctrl->reader_slot;
1651       char flag = 'r';
1652
1653       if (!ctrl->server_local->card_removed && slot != -1)
1654         {
1655           struct slot_status_s *ss;
1656           
1657           if (!(slot >= 0 && slot < DIM(slot_table)))
1658             BUG ();
1659
1660           ss = &slot_table[slot];
1661
1662           if (!ss->valid)
1663             BUG ();
1664
1665           if (ss->any && (ss->status & 1))
1666             flag = 'u';
1667         }
1668       rc = assuan_send_data (ctx, &flag, 1);
1669     }
1670   else if (!strcmp (line, "reader_list"))
1671     {
1672 #ifdef HAVE_LIBUSB
1673       char *s = ccid_get_reader_list ();
1674 #else
1675       char *s = NULL;
1676 #endif
1677       
1678       if (s)
1679         rc = assuan_send_data (ctx, s, strlen (s));
1680       else
1681         rc = gpg_error (GPG_ERR_NO_DATA);
1682       xfree (s);
1683     }
1684   else if (!strcmp (line, "deny_admin"))
1685     rc = opt.allow_admin? gpg_error (GPG_ERR_GENERAL) : 0;
1686   else if (!strcmp (line, "app_list"))
1687     {
1688       char *s = get_supported_applications ();
1689       if (s)
1690         rc = assuan_send_data (ctx, s, strlen (s));
1691       else
1692         rc = 0;
1693       xfree (s);
1694     }
1695   else
1696     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1697   return rc;
1698 }
1699
1700
1701 /* RESTART
1702
1703    Restart the current connection; this is a kind of warm reset.  It
1704    deletes the context used by this connection but does not send a
1705    RESET to the card.  Thus the card itself won't get reset. 
1706
1707    This is used by gpg-agent to reuse a primary pipe connection and
1708    may be used by clients to backup from a conflict in the serial
1709    command; i.e. to select another application. 
1710 */
1711
1712 static int
1713 cmd_restart (assuan_context_t ctx, char *line)
1714 {
1715   ctrl_t ctrl = assuan_get_pointer (ctx);
1716
1717   (void)line;
1718
1719   if (ctrl->app_ctx)
1720     {
1721       release_application (ctrl->app_ctx);
1722       ctrl->app_ctx = NULL;
1723     }
1724   if (locked_session && ctrl->server_local == locked_session)
1725     {
1726       locked_session = NULL;
1727       log_info ("implicitly unlocking due to RESTART\n");
1728     }
1729   return 0;
1730 }
1731
1732
1733 /* DISCONNECT
1734
1735    Disconnect the card if it is not any longer used by other
1736    connections and the backend supports a disconnect operation. 
1737  */
1738 static int
1739 cmd_disconnect (assuan_context_t ctx, char *line)
1740 {
1741   ctrl_t ctrl = assuan_get_pointer (ctx);
1742
1743   (void)line;
1744   
1745   ctrl->server_local->disconnect_allowed = 1;
1746   return 0;
1747 }
1748
1749
1750
1751 /* APDU [--atr] [--more] [hexstring]
1752
1753    Send an APDU to the current reader.  This command bypasses the high
1754    level functions and sends the data directly to the card.  HEXSTRING
1755    is expected to be a proper APDU.  If HEXSTRING is not given no
1756    commands are set to the card but the command will implictly check
1757    whether the card is ready for use. 
1758
1759    Using the option "--atr" returns the ATR of the card as a status
1760    message before any data like this:
1761      S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1
1762
1763    Using the option --more handles the card status word MORE_DATA
1764    (61xx) and concatenate all reponses to one block.
1765
1766  */
1767 static int
1768 cmd_apdu (assuan_context_t ctx, char *line)
1769 {
1770   ctrl_t ctrl = assuan_get_pointer (ctx);
1771   int rc;
1772   unsigned char *apdu;
1773   size_t apdulen;
1774   int with_atr;
1775   int handle_more;
1776
1777   with_atr = has_option (line, "--atr");
1778   handle_more = has_option (line, "--more");
1779
1780   line = skip_options (line);
1781
1782   if ( IS_LOCKED (ctrl) )
1783     return gpg_error (GPG_ERR_LOCKED);
1784
1785   if ((rc = open_card (ctrl, NULL)))
1786     return rc;
1787
1788   if (with_atr)
1789     {
1790       unsigned char *atr;
1791       size_t atrlen;
1792       char hexbuf[400];
1793       
1794       atr = apdu_get_atr (ctrl->reader_slot, &atrlen);
1795       if (!atr || atrlen > sizeof hexbuf - 2 )
1796         {
1797           rc = gpg_error (GPG_ERR_INV_CARD);
1798           goto leave;
1799         }
1800       bin2hex (atr, atrlen, hexbuf);
1801       xfree (atr);
1802       send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
1803     }
1804
1805   apdu = hex_to_buffer (line, &apdulen);
1806   if (!apdu)
1807     {
1808       rc = gpg_error_from_syserror ();
1809       goto leave;
1810     }
1811   if (apdulen)
1812     {
1813       unsigned char *result = NULL;
1814       size_t resultlen;
1815
1816       rc = apdu_send_direct (ctrl->reader_slot, apdu, apdulen, handle_more,
1817                              &result, &resultlen);
1818       if (rc)
1819         log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
1820       else
1821         {
1822           rc = assuan_send_data (ctx, result, resultlen);
1823           xfree (result);
1824         }
1825     }
1826   xfree (apdu);
1827
1828  leave:
1829   TEST_CARD_REMOVAL (ctrl, rc);
1830   return rc;
1831 }
1832
1833
1834 /* KILLSCD - Commit suicide. */
1835 static int
1836 cmd_killscd (assuan_context_t ctx, char *line)
1837 {
1838   ctrl_t ctrl = assuan_get_pointer (ctx);
1839
1840   (void)line;
1841
1842   ctrl->server_local->stopme = 1;
1843   return gpg_error (GPG_ERR_EOF);
1844 }
1845
1846
1847 \f
1848 /* Tell the assuan library about our commands */
1849 static int
1850 register_commands (assuan_context_t ctx)
1851 {
1852   static struct {
1853     const char *name;
1854     int (*handler)(assuan_context_t, char *line);
1855   } table[] = {
1856     { "SERIALNO",     cmd_serialno },
1857     { "LEARN",        cmd_learn },
1858     { "READCERT",     cmd_readcert },
1859     { "READKEY",      cmd_readkey },
1860     { "SETDATA",      cmd_setdata },
1861     { "PKSIGN",       cmd_pksign },
1862     { "PKAUTH",       cmd_pkauth },
1863     { "PKDECRYPT",    cmd_pkdecrypt },
1864     { "INPUT",        NULL }, 
1865     { "OUTPUT",       NULL }, 
1866     { "GETATTR",      cmd_getattr },
1867     { "SETATTR",      cmd_setattr },
1868     { "WRITECERT",    cmd_writecert },
1869     { "WRITEKEY",     cmd_writekey },
1870     { "GENKEY",       cmd_genkey },
1871     { "RANDOM",       cmd_random },
1872     { "PASSWD",       cmd_passwd },
1873     { "CHECKPIN",     cmd_checkpin },
1874     { "LOCK",         cmd_lock },
1875     { "UNLOCK",       cmd_unlock },
1876     { "GETINFO",      cmd_getinfo },
1877     { "RESTART",      cmd_restart },
1878     { "DISCONNECT",   cmd_disconnect },
1879     { "APDU",         cmd_apdu },
1880     { "KILLSCD",      cmd_killscd },
1881     { NULL }
1882   };
1883   int i, rc;
1884
1885   for (i=0; table[i].name; i++)
1886     {
1887       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
1888       if (rc)
1889         return rc;
1890     } 
1891   assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
1892
1893   assuan_register_reset_notify (ctx, reset_notify);
1894   assuan_register_option_handler (ctx, option_handler);
1895   return 0;
1896 }
1897
1898
1899 /* Startup the server.  If FD is given as -1 this is simple pipe
1900    server, otherwise it is a regular server.  Returns true if there
1901    are no more active asessions.  */
1902 int
1903 scd_command_handler (ctrl_t ctrl, int fd)
1904 {
1905   int rc;
1906   assuan_context_t ctx;
1907   int stopme;
1908   
1909   if (fd == -1)
1910     {
1911       int filedes[2];
1912
1913       filedes[0] = 0;
1914       filedes[1] = 1;
1915       rc = assuan_init_pipe_server (&ctx, filedes);
1916     }
1917   else
1918     {
1919       rc = assuan_init_socket_server_ext (&ctx, INT2FD(fd), 2);
1920     }
1921   if (rc)
1922     {
1923       log_error ("failed to initialize the server: %s\n",
1924                  gpg_strerror(rc));
1925       scd_exit (2);
1926     }
1927   rc = register_commands (ctx);
1928   if (rc)
1929     {
1930       log_error ("failed to register commands with Assuan: %s\n",
1931                  gpg_strerror(rc));
1932       scd_exit (2);
1933     }
1934   assuan_set_pointer (ctx, ctrl);
1935
1936   /* Allocate and initialize the server object.  Put it into the list
1937      of active sessions. */
1938   ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
1939   ctrl->server_local->next_session = session_list;
1940   session_list = ctrl->server_local;
1941   ctrl->server_local->ctrl_backlink = ctrl;
1942   ctrl->server_local->assuan_ctx = ctx;
1943
1944   if (DBG_ASSUAN)
1945     assuan_set_log_stream (ctx, log_get_stream ());
1946
1947   /* We open the reader right at startup so that the ticker is able to
1948      update the status file. */
1949   if (ctrl->reader_slot == -1)
1950     {
1951       ctrl->reader_slot = get_reader_slot ();
1952     }
1953
1954   /* Command processing loop. */
1955   for (;;)
1956     {
1957       rc = assuan_accept (ctx);
1958       if (rc == -1)
1959         {
1960           break;
1961         }
1962       else if (rc)
1963         {
1964           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
1965           break;
1966         }
1967       
1968       rc = assuan_process (ctx);
1969       if (rc)
1970         {
1971           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
1972           continue;
1973         }
1974     }
1975
1976   /* Cleanup.  We don't send an explicit reset to the card.  */
1977   do_reset (ctrl, 0); 
1978
1979   /* Release the server object.  */
1980   if (session_list == ctrl->server_local)
1981     session_list = ctrl->server_local->next_session;
1982   else
1983     {
1984       struct server_local_s *sl;
1985       
1986       for (sl=session_list; sl->next_session; sl = sl->next_session)
1987         if (sl->next_session == ctrl->server_local)
1988           break;
1989       if (!sl->next_session)
1990           BUG ();
1991       sl->next_session = ctrl->server_local->next_session;
1992     }
1993   stopme = ctrl->server_local->stopme;
1994   xfree (ctrl->server_local);
1995   ctrl->server_local = NULL;
1996
1997   /* Release the Assuan context.  */
1998   assuan_deinit_server (ctx);
1999
2000   if (stopme)
2001     scd_exit (0);
2002
2003   /* If there are no more sessions return true.  */
2004   return !session_list;
2005 }
2006
2007
2008 /* Send a line with status information via assuan and escape all given
2009    buffers. The variable elements are pairs of (char *, size_t),
2010    terminated with a (NULL, 0). */
2011 void
2012 send_status_info (ctrl_t ctrl, const char *keyword, ...)
2013 {
2014   va_list arg_ptr;
2015   const unsigned char *value;
2016   size_t valuelen;
2017   char buf[950], *p;
2018   size_t n;
2019   assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2020   
2021   va_start (arg_ptr, keyword);
2022
2023   p = buf; 
2024   n = 0;
2025   while ( (value = va_arg (arg_ptr, const unsigned char *)) )
2026     {
2027       valuelen = va_arg (arg_ptr, size_t);
2028       if (!valuelen)
2029         continue; /* empty buffer */
2030       if (n)
2031         {
2032           *p++ = ' ';
2033           n++;
2034         }
2035       for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
2036         {
2037           if (*value < ' ' || *value == '+')
2038             {
2039               sprintf (p, "%%%02X", *value);
2040               p += 3;
2041             }
2042           else if (*value == ' ')
2043             *p++ = '+';
2044           else
2045             *p++ = *value;
2046         }
2047     }
2048   *p = 0;
2049   assuan_write_status (ctx, keyword, buf);
2050
2051   va_end (arg_ptr);
2052 }
2053
2054
2055 /* Send a ready formatted status line via assuan.  */
2056 void
2057 send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
2058 {
2059   assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2060
2061   if (strchr (args, '\n'))
2062     log_error ("error: LF detected in status line - not sending\n");
2063   else
2064     assuan_write_status (ctx, keyword, args);
2065 }
2066
2067
2068 /* Helper to send the clients a status change notification.  */
2069 static void
2070 send_client_notifications (void)
2071 {
2072   struct {
2073     pid_t pid; 
2074 #ifdef HAVE_W32_SYSTEM
2075     HANDLE handle;
2076 #else
2077     int signo; 
2078 #endif
2079   } killed[50];
2080   int killidx = 0;
2081   int kidx;
2082   struct server_local_s *sl;
2083   
2084   for (sl=session_list; sl; sl = sl->next_session)
2085     {
2086       if (sl->event_signal && sl->assuan_ctx)
2087         {
2088           pid_t pid = assuan_get_pid (sl->assuan_ctx);
2089 #ifdef HAVE_W32_SYSTEM
2090           HANDLE handle = (void *)sl->event_signal;
2091           
2092           for (kidx=0; kidx < killidx; kidx++)
2093             if (killed[kidx].pid == pid 
2094                 && killed[kidx].handle == handle)
2095               break;
2096           if (kidx < killidx)
2097             log_info ("event %lx (%p) already triggered for client %d\n",
2098                       sl->event_signal, handle, (int)pid);
2099           else
2100             {
2101               log_info ("triggering event %lx (%p) for client %d\n",
2102                         sl->event_signal, handle, (int)pid);
2103               if (!SetEvent (handle))
2104                 log_error ("SetEvent(%lx) failed: %s\n",
2105                            sl->event_signal, w32_strerror (-1));
2106               if (killidx < DIM (killed))
2107                 {
2108                   killed[killidx].pid = pid;
2109                   killed[killidx].handle = handle;
2110                   killidx++;
2111                 }
2112             }
2113 #else /*!HAVE_W32_SYSTEM*/
2114           int signo = sl->event_signal;
2115           
2116           if (pid != (pid_t)(-1) && pid && signo > 0)
2117             {
2118               for (kidx=0; kidx < killidx; kidx++)
2119                 if (killed[kidx].pid == pid 
2120                     && killed[kidx].signo == signo)
2121                   break;
2122               if (kidx < killidx)
2123                 log_info ("signal %d already sent to client %d\n",
2124                           signo, (int)pid);
2125               else
2126                 {
2127                   log_info ("sending signal %d to client %d\n",
2128                             signo, (int)pid);
2129                   kill (pid, signo);
2130                   if (killidx < DIM (killed))
2131                     {
2132                       killed[killidx].pid = pid;
2133                       killed[killidx].signo = signo;
2134                       killidx++;
2135                     }
2136                 }
2137             }
2138 #endif /*!HAVE_W32_SYSTEM*/
2139         }
2140     }
2141 }
2142
2143
2144
2145 /* This is the core of scd_update_reader_status_file but the caller
2146    needs to take care of the locking.  */
2147 static void
2148 update_reader_status_file (int set_card_removed_flag)
2149 {
2150   int idx;
2151   unsigned int status, changed;
2152
2153   /* Make sure that the reader has been opened.  Like get_reader_slot,
2154      this part of the code assumes that there is only one reader.  */
2155   if (!slot_table[0].valid)
2156     (void)get_reader_slot ();
2157
2158   /* Note, that we only try to get the status, because it does not
2159      make sense to wait here for a operation to complete.  If we are
2160      busy working with a card, delays in the status file update should
2161      be acceptable. */
2162   for (idx=0; idx < DIM(slot_table); idx++)
2163     {
2164       struct slot_status_s *ss = slot_table + idx;
2165       struct server_local_s *sl;
2166       int sw_apdu;
2167
2168       if (!ss->valid || ss->slot == -1)
2169         continue; /* Not valid or reader not yet open. */
2170       
2171       sw_apdu = apdu_get_status (ss->slot, 0, &status, &changed);
2172       if (sw_apdu)
2173         {
2174           /* Get status failed.  Ignore that.  */
2175           continue; 
2176         }
2177
2178       if (!ss->any || ss->status != status || ss->changed != changed )
2179         {
2180           char *fname;
2181           char templ[50];
2182           FILE *fp;
2183
2184           log_info ("updating slot %d status: 0x%04X->0x%04X (%u->%u)\n",
2185                     ss->slot, ss->status, status, ss->changed, changed);
2186           ss->status = status;
2187           ss->changed = changed;
2188
2189           /* FIXME: Should this be IDX instead of ss->slot?  This
2190              depends on how client sessions will associate the reader
2191              status with their session.  */
2192           snprintf (templ, sizeof templ, "reader_%d.status", ss->slot);
2193           fname = make_filename (opt.homedir, templ, NULL );
2194           fp = fopen (fname, "w");
2195           if (fp)
2196             {
2197               fprintf (fp, "%s\n",
2198                        (status & 1)? "USABLE":
2199                        (status & 4)? "ACTIVE":
2200                        (status & 2)? "PRESENT": "NOCARD");
2201               fclose (fp);
2202             }
2203           xfree (fname);
2204             
2205           /* If a status script is executable, run it. */
2206           {
2207             const char *args[9], *envs[2];
2208             char numbuf1[30], numbuf2[30], numbuf3[30];
2209             char *homestr, *envstr;
2210             gpg_error_t err;
2211             
2212             homestr = make_filename (opt.homedir, NULL);
2213             if (estream_asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
2214               log_error ("out of core while building environment\n");
2215             else
2216               {
2217                 envs[0] = envstr;
2218                 envs[1] = NULL;
2219
2220                 sprintf (numbuf1, "%d", ss->slot);
2221                 sprintf (numbuf2, "0x%04X", ss->status);
2222                 sprintf (numbuf3, "0x%04X", status);
2223                 args[0] = "--reader-port";
2224                 args[1] = numbuf1; 
2225                 args[2] = "--old-code";
2226                 args[3] = numbuf2;  
2227                 args[4] = "--new-code";
2228                 args[5] = numbuf3; 
2229                 args[6] = "--status";
2230                 args[7] = ((status & 1)? "USABLE":
2231                            (status & 4)? "ACTIVE":
2232                            (status & 2)? "PRESENT": "NOCARD");
2233                 args[8] = NULL;  
2234
2235                 fname = make_filename (opt.homedir, "scd-event", NULL);
2236                 err = gnupg_spawn_process_detached (fname, args, envs);
2237                 if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
2238                   log_error ("failed to run event handler `%s': %s\n",
2239                              fname, gpg_strerror (err));
2240                 xfree (fname);
2241                 xfree (envstr);
2242               }
2243             xfree (homestr);
2244           }
2245
2246           /* Set the card removed flag for all current sessions.  We
2247              will set this on any card change because a reset or
2248              SERIALNO request must be done in any case.  */
2249           if (ss->any && set_card_removed_flag)
2250             update_card_removed (idx, 1);
2251           
2252           ss->any = 1;
2253
2254           /* Send a signal to all clients who applied for it.  */
2255           send_client_notifications ();
2256         }
2257       
2258       /* Check whether a disconnect is pending.  */
2259       if (opt.card_timeout)
2260         {
2261           for (sl=session_list; sl; sl = sl->next_session)
2262             if (!sl->disconnect_allowed)
2263               break; 
2264           if (session_list && !sl)
2265             {
2266               /* FIXME: Use a real timeout.  */
2267               /* At least one connection and all allow a disconnect.  */
2268               log_info ("disconnecting card in slot %d\n", ss->slot);
2269               apdu_disconnect (ss->slot);
2270             }
2271         }
2272       
2273     }
2274 }
2275
2276 /* This function is called by the ticker thread to check for changes
2277    of the reader stati.  It updates the reader status files and if
2278    requested by the caller also send a signal to the caller.  */
2279 void
2280 scd_update_reader_status_file (void)
2281 {
2282   if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL))
2283     return; /* locked - give up. */
2284   update_reader_status_file (1);
2285   if (!pth_mutex_release (&status_file_update_lock))
2286     log_error ("failed to release status_file_update lock\n");
2287 }