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