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