* gpg.texi: Reference to --s2k-count in --s2k-mode.
[gnupg.git] / scd / command.c
blob5116461d4ba3d3053f790d2816f2f734936b1116
1 /* command.c - SCdaemon command handler
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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.
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
34 #include <assuan.h>
36 #include "scdaemon.h"
37 #include <ksba.h>
38 #include "app-common.h"
39 #include "apdu.h" /* Required for apdu_*_reader (). */
40 #include "exechelp.h"
42 /* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */
43 #define MAXLEN_PIN 100
45 /* Maximum allowed size of key data as used in inquiries. */
46 #define MAXLEN_KEYDATA 4096
49 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
52 /* Macro to flag a removed card. */
53 #define TEST_CARD_REMOVAL(c,r) \
54 do { \
55 int _r = (r); \
56 if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \
57 || gpg_err_code (_r) == GPG_ERR_CARD_REMOVED) \
58 update_card_removed ((c)->reader_slot, 1); \
59 } while (0)
61 #define IS_LOCKED(c) \
62 (locked_session && locked_session != (c)->server_local \
63 && (c)->reader_slot != -1 && locked_session->ctrl_backlink \
64 && (c)->reader_slot == locked_session->ctrl_backlink->reader_slot)
67 /* This structure is used to keep track of open readers (slots). */
68 struct slot_status_s
70 int valid; /* True if the other objects are valid. */
71 int slot; /* Slot number of the reader or -1 if not open. */
73 int reset_failed; /* A reset failed. */
75 int any; /* Flag indicating whether any status check has been
76 done. This is set once to indicate that the status
77 tracking for the slot has been initialized. */
78 unsigned int status; /* Last status of the slot. */
79 unsigned int changed; /* Last change counter of teh slot. */
83 /* Data used to associate an Assuan context with local server data.
84 This object describes the local properties of one session. */
85 struct server_local_s
87 /* We keep a list of all active sessions with the anchor at
88 SESSION_LIST (see below). This field is used for linking. */
89 struct server_local_s *next_session;
91 /* This object is usually assigned to a CTRL object (which is
92 globally visible). While enumerating all sessions we sometimes
93 need to access data of the CTRL object; thus we keep a
94 backpointer here. */
95 ctrl_t ctrl_backlink;
97 /* The Assuan context used by this session/server. */
98 assuan_context_t assuan_ctx;
100 int event_signal; /* Or 0 if not used. */
102 /* True if the card has been removed and a reset is required to
103 continue operation. */
104 int card_removed;
108 /* The table with information on all used slots. FIXME: This is a
109 different slot number than the one used by the APDU layer, and
110 should be renamed. */
111 static struct slot_status_s slot_table[10];
114 /* To keep track of all running sessions, we link all active server
115 contexts and the anchor in this variable. */
116 static struct server_local_s *session_list;
118 /* If a session has been locked we store a link to its server object
119 in this variable. */
120 static struct server_local_s *locked_session;
122 /* While doing a reset we need to make sure that the ticker does not
123 call scd_update_reader_status_file while we are using it. */
124 static pth_mutex_t status_file_update_lock = PTH_MUTEX_INIT;
127 /*-- Local prototypes --*/
128 static void update_reader_status_file (void);
132 /* Update the CARD_REMOVED element of all sessions using the reader
133 given by SLOT to VALUE */
134 static void
135 update_card_removed (int slot, int value)
137 struct server_local_s *sl;
139 for (sl=session_list; sl; sl = sl->next_session)
140 if (sl->ctrl_backlink
141 && sl->ctrl_backlink->reader_slot == slot)
143 sl->card_removed = value;
145 if (value)
146 application_notify_card_removed (slot);
151 /* Check whether the option NAME appears in LINE */
152 static int
153 has_option (const char *line, const char *name)
155 const char *s;
156 int n = strlen (name);
158 s = strstr (line, name);
159 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
163 /* Convert the STRING into a newly allocated buffer while translating
164 the hex numbers. Stops at the first invalid character. Blanks and
165 colons are allowed to separate the hex digits. Returns NULL on
166 error or a newly malloced buffer and its length in LENGTH. */
167 static unsigned char *
168 hex_to_buffer (const char *string, size_t *r_length)
170 unsigned char *buffer;
171 const char *s;
172 size_t n;
174 buffer = xtrymalloc (strlen (string)+1);
175 if (!buffer)
176 return NULL;
177 for (s=string, n=0; *s; s++)
179 if (spacep (s) || *s == ':')
180 continue;
181 if (hexdigitp (s) && hexdigitp (s+1))
183 buffer[n++] = xtoi_2 (s);
184 s++;
186 else
187 break;
189 *r_length = n;
190 return buffer;
195 /* Reset the card and free the application context. With SEND_RESET
196 set to true actually send a RESET to the reader. */
197 static void
198 do_reset (ctrl_t ctrl, int send_reset)
200 int slot = ctrl->reader_slot;
202 if (!(slot == -1 || (slot >= 0 && slot < DIM(slot_table))))
203 BUG ();
205 if (ctrl->app_ctx)
207 release_application (ctrl->app_ctx);
208 ctrl->app_ctx = NULL;
211 if (slot != -1 && send_reset && !IS_LOCKED (ctrl) )
213 if (apdu_reset (slot))
215 slot_table[slot].reset_failed = 1;
219 /* If we hold a lock, unlock now. */
220 if (locked_session && ctrl->server_local == locked_session)
222 locked_session = NULL;
223 log_info ("implicitly unlocking due to RESET\n");
226 /* Reset card removed flag for the current reader. We need to take
227 the lock here so that the ticker thread won't concurrently try to
228 update the file. Note that the update function will set the card
229 removed flag and we will later reset it - not a particualar nice
230 way of implementing it but it works. */
231 if (!pth_mutex_acquire (&status_file_update_lock, 0, NULL))
233 log_error ("failed to acquire status_fle_update lock\n");
234 ctrl->reader_slot = -1;
235 return;
237 update_reader_status_file ();
238 update_card_removed (slot, 0);
239 if (!pth_mutex_release (&status_file_update_lock))
240 log_error ("failed to release status_file_update lock\n");
242 /* Do this last, so that update_card_removed does its job. */
243 ctrl->reader_slot = -1;
247 static void
248 reset_notify (assuan_context_t ctx)
250 ctrl_t ctrl = assuan_get_pointer (ctx);
252 do_reset (ctrl, 1);
256 static int
257 option_handler (assuan_context_t ctx, const char *key, const char *value)
259 ctrl_t ctrl = assuan_get_pointer (ctx);
261 if (!strcmp (key, "event-signal"))
263 /* A value of 0 is allowed to reset the event signal. */
264 int i = *value? atoi (value) : -1;
265 if (i < 0)
266 return gpg_error (GPG_ERR_ASS_PARAMETER);
267 ctrl->server_local->event_signal = i;
270 return 0;
274 /* Return the slot of the current reader or open the reader if no
275 other sessions are using a reader. Note, that we currently support
276 only one reader but most of the code (except for this function)
277 should be able to cope with several readers. */
278 static int
279 get_reader_slot (void)
281 struct slot_status_s *ss;
283 ss = &slot_table[0]; /* One reader for now. */
285 /* Initialize the item if needed. */
286 if (!ss->valid)
288 ss->slot = -1;
289 ss->valid = 1;
292 /* Try to open the reader. */
293 if (ss->slot == -1)
294 ss->slot = apdu_open_reader (opt.reader_port);
296 /* Return the slot_table index. */
297 return 0;
300 /* If the card has not yet been opened, do it. Note that this
301 function returns an Assuan error, so don't map the error a second
302 time. */
303 static assuan_error_t
304 open_card (ctrl_t ctrl, const char *apptype)
306 gpg_error_t err;
307 int slot;
309 /* If we ever got a card not present error code, return that. Only
310 the SERIALNO command and a reset are able to clear from that
311 state. */
312 if (ctrl->server_local->card_removed)
313 return gpg_error (GPG_ERR_CARD_REMOVED);
315 if ( IS_LOCKED (ctrl) )
316 return gpg_error (GPG_ERR_LOCKED);
318 if (ctrl->app_ctx)
320 /* Already initialized for one specific application. Need to
321 check that the client didn't requested a specific application
322 different from the one in use. */
323 return check_application_conflict (ctrl, apptype);
326 if (ctrl->reader_slot != -1)
327 slot = ctrl->reader_slot;
328 else
329 slot = get_reader_slot ();
330 ctrl->reader_slot = slot;
331 if (slot == -1)
332 err = gpg_error (GPG_ERR_CARD);
333 else
334 err = select_application (ctrl, slot, apptype, &ctrl->app_ctx);
336 TEST_CARD_REMOVAL (ctrl, err);
337 return err;
341 /* Do the percent and plus/space unescaping in place and return the
342 length of the valid buffer. */
343 static size_t
344 percent_plus_unescape (unsigned char *string)
346 unsigned char *p = string;
347 size_t n = 0;
349 while (*string)
351 if (*string == '%' && string[1] && string[2])
353 string++;
354 *p++ = xtoi_2 (string);
355 n++;
356 string+= 2;
358 else if (*string == '+')
360 *p++ = ' ';
361 n++;
362 string++;
364 else
366 *p++ = *string++;
367 n++;
371 return n;
376 /* SERIALNO [APPTYPE]
378 Return the serial number of the card using a status reponse. This
379 functon should be used to check for the presence of a card.
381 If APPTYPE is given, an application of that type is selected and an
382 error is returned if the application is not supported or available.
383 The default is to auto-select the application using a hardwired
384 preference system. Note, that a future extension to this function
385 may allow to specify a list and order of applications to try.
387 This function is special in that it can be used to reset the card.
388 Most other functions will return an error when a card change has
389 been detected and the use of this function is therefore required.
391 Background: We want to keep the client clear of handling card
392 changes between operations; i.e. the client can assume that all
393 operations are done on the same card unless he calls this function.
395 static int
396 cmd_serialno (assuan_context_t ctx, char *line)
398 ctrl_t ctrl = assuan_get_pointer (ctx);
399 int rc = 0;
400 char *serial_and_stamp;
401 char *serial;
402 time_t stamp;
404 /* Clear the remove flag so that the open_card is able to reread it. */
405 if (ctrl->server_local->card_removed)
407 if ( IS_LOCKED (ctrl) )
408 return gpg_error (GPG_ERR_LOCKED);
409 do_reset (ctrl, 1);
412 if ((rc = open_card (ctrl, *line? line:NULL)))
413 return rc;
415 rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
416 if (rc)
417 return rc;
419 rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp);
420 xfree (serial);
421 if (rc < 0)
422 return out_of_core ();
423 rc = 0;
424 assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
425 free (serial_and_stamp);
426 return 0;
432 /* LEARN [--force]
434 Learn all useful information of the currently inserted card. When
435 used without the force options, the command might do an INQUIRE
436 like this:
438 INQUIRE KNOWNCARDP <hexstring_with_serialNumber> <timestamp>
440 The client should just send an "END" if the processing should go on
441 or a "CANCEL" to force the function to terminate with a Cancel
442 error message. The response of this command is a list of status
443 lines formatted as this:
445 S APPTYPE <apptype>
447 This returns the type of the application, currently the strings:
449 P15 = PKCS-15 structure used
450 DINSIG = DIN SIG
451 OPENPGP = OpenPGP card
453 are implemented. These strings are aliases for the AID
455 S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id>
457 If there is no certificate yet stored on the card a single "X" is
458 returned as the keygrip. In addition to the keypair info, information
459 about all certificates stored on the card is also returned:
461 S CERTINFO <certtype> <hexstring_with_id>
463 Where CERTTYPE is a number indicating the type of certificate:
464 0 := Unknown
465 100 := Regular X.509 cert
466 101 := Trusted X.509 cert
467 102 := Useful X.509 cert
468 110 := Root CA cert (DINSIG)
470 For certain cards, more information will be returned:
472 S KEY-FPR <no> <hexstring>
474 For OpenPGP cards this returns the stored fingerprints of the
475 keys. This can be used check whether a key is available on the
476 card. NO may be 1, 2 or 3.
478 S CA-FPR <no> <hexstring>
480 Similar to above, these are the fingerprints of keys assumed to be
481 ultimately trusted.
483 S DISP-NAME <name_of_card_holder>
485 The name of the card holder as stored on the card; percent
486 escaping takes place, spaces are encoded as '+'
488 S PUBKEY-URL <url>
490 The URL to be used for locating the entire public key.
492 Note, that this function may be even be used on a locked card.
494 static int
495 cmd_learn (assuan_context_t ctx, char *line)
497 ctrl_t ctrl = assuan_get_pointer (ctx);
498 int rc = 0;
500 if ((rc = open_card (ctrl, NULL)))
501 return rc;
503 /* Unless the force option is used we try a shortcut by identifying
504 the card using a serial number and inquiring the client with
505 that. The client may choose to cancel the operation if he already
506 knows about this card */
508 char *serial_and_stamp;
509 char *serial;
510 time_t stamp;
512 rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
513 if (rc)
514 return rc;
515 rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp);
516 xfree (serial);
517 if (rc < 0)
518 return out_of_core ();
519 rc = 0;
520 assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
522 if (!has_option (line, "--force"))
524 char *command;
526 rc = asprintf (&command, "KNOWNCARDP %s", serial_and_stamp);
527 if (rc < 0)
529 free (serial_and_stamp);
530 return out_of_core ();
532 rc = 0;
533 rc = assuan_inquire (ctx, command, NULL, NULL, 0);
534 free (command); /* (must use standard free here) */
535 if (rc)
537 if (gpg_err_code (rc) != GPG_ERR_ASS_CANCELED)
538 log_error ("inquire KNOWNCARDP failed: %s\n",
539 gpg_strerror (rc));
540 free (serial_and_stamp);
541 return rc;
543 /* not canceled, so we have to proceeed */
545 free (serial_and_stamp);
548 /* Let the application print out its collection of useful status
549 information. */
550 if (!rc)
551 rc = app_write_learn_status (ctrl->app_ctx, ctrl);
553 TEST_CARD_REMOVAL (ctrl, rc);
554 return rc;
559 /* READCERT <hexified_certid>
561 Note, that this function may even be used on a locked card.
563 static int
564 cmd_readcert (assuan_context_t ctx, char *line)
566 ctrl_t ctrl = assuan_get_pointer (ctx);
567 int rc;
568 unsigned char *cert;
569 size_t ncert;
571 if ((rc = open_card (ctrl, NULL)))
572 return rc;
574 line = xstrdup (line); /* Need a copy of the line. */
575 rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
576 if (rc)
577 log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
578 xfree (line);
579 line = NULL;
580 if (!rc)
582 rc = assuan_send_data (ctx, cert, ncert);
583 xfree (cert);
584 if (rc)
585 return rc;
588 TEST_CARD_REMOVAL (ctrl, rc);
589 return rc;
593 /* READKEY <keyid>
595 Return the public key for the given cert or key ID as an standard
596 S-Expression.
598 Note, that this function may even be used on a locked card.
600 static int
601 cmd_readkey (assuan_context_t ctx, char *line)
603 ctrl_t ctrl = assuan_get_pointer (ctx);
604 int rc;
605 unsigned char *cert = NULL;
606 size_t ncert, n;
607 ksba_cert_t kc = NULL;
608 ksba_sexp_t p;
609 unsigned char *pk;
610 size_t pklen;
612 if ((rc = open_card (ctrl, NULL)))
613 return rc;
615 line = xstrdup (line); /* Need a copy of the line. */
616 /* If the application supports the READKEY function we use that.
617 Otherwise we use the old way by extracting it from the
618 certificate. */
619 rc = app_readkey (ctrl->app_ctx, line, &pk, &pklen);
620 if (!rc)
621 { /* Yeah, got that key - send it back. */
622 rc = assuan_send_data (ctx, pk, pklen);
623 xfree (pk);
624 xfree (line);
625 line = NULL;
626 goto leave;
629 if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION)
630 log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
631 else
633 rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
634 if (rc)
635 log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
637 xfree (line);
638 line = NULL;
639 if (rc)
640 goto leave;
642 rc = ksba_cert_new (&kc);
643 if (rc)
645 xfree (cert);
646 goto leave;
648 rc = ksba_cert_init_from_mem (kc, cert, ncert);
649 if (rc)
651 log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
652 goto leave;
655 p = ksba_cert_get_public_key (kc);
656 if (!p)
658 rc = gpg_error (GPG_ERR_NO_PUBKEY);
659 goto leave;
662 n = gcry_sexp_canon_len (p, 0, NULL, NULL);
663 rc = assuan_send_data (ctx, p, n);
664 xfree (p);
667 leave:
668 ksba_cert_release (kc);
669 xfree (cert);
670 TEST_CARD_REMOVAL (ctrl, rc);
671 return rc;
677 /* SETDATA <hexstring>
679 The client should use this command to tell us the data he want to
680 sign. */
681 static int
682 cmd_setdata (assuan_context_t ctx, char *line)
684 ctrl_t ctrl = assuan_get_pointer (ctx);
685 int n;
686 char *p;
687 unsigned char *buf;
689 if (locked_session && locked_session != ctrl->server_local)
690 return gpg_error (GPG_ERR_LOCKED);
692 /* Parse the hexstring. */
693 for (p=line,n=0; hexdigitp (p); p++, n++)
695 if (*p)
696 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
697 if (!n)
698 return set_error (GPG_ERR_ASS_PARAMETER, "no data given");
699 if ((n&1))
700 return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
701 n /= 2;
702 buf = xtrymalloc (n);
703 if (!buf)
704 return out_of_core ();
706 ctrl->in_data.value = buf;
707 ctrl->in_data.valuelen = n;
708 for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++)
709 buf[n] = xtoi_2 (p);
710 return 0;
715 static gpg_error_t
716 pin_cb (void *opaque, const char *info, char **retstr)
718 assuan_context_t ctx = opaque;
719 char *command;
720 int rc;
721 unsigned char *value;
722 size_t valuelen;
724 *retstr = NULL;
725 log_debug ("asking for PIN '%s'\n", info);
727 rc = asprintf (&command, "NEEDPIN %s", info);
728 if (rc < 0)
729 return gpg_error (gpg_err_code_from_errno (errno));
731 /* Fixme: Write an inquire function which returns the result in
732 secure memory and check all further handling of the PIN. */
733 rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
734 free (command);
735 if (rc)
736 return rc;
738 if (!valuelen || value[valuelen-1])
740 /* We require that the returned value is an UTF-8 string */
741 xfree (value);
742 return gpg_error (GPG_ERR_INV_RESPONSE);
744 *retstr = (char*)value;
745 return 0;
749 /* PKSIGN [--hash=[rmd160|sha1|md5]] <hexified_id>
751 The --hash option is optional; the default is SHA1.
754 static int
755 cmd_pksign (assuan_context_t ctx, char *line)
757 ctrl_t ctrl = assuan_get_pointer (ctx);
758 int rc;
759 unsigned char *outdata;
760 size_t outdatalen;
761 char *keyidstr;
762 int hash_algo;
764 if (has_option (line, "--hash=rmd160"))
765 hash_algo = GCRY_MD_RMD160;
766 else if (has_option (line, "--hash=sha1"))
767 hash_algo = GCRY_MD_SHA1;
768 else if (has_option (line, "--hash=md5"))
769 hash_algo = GCRY_MD_MD5;
770 else if (!strstr (line, "--"))
771 hash_algo = GCRY_MD_SHA1;
772 else
773 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
774 /* Skip over options. */
775 while ( *line == '-' && line[1] == '-' )
777 while (*line && !spacep (line))
778 line++;
779 while (spacep (line))
780 line++;
783 if ( IS_LOCKED (ctrl) )
784 return gpg_error (GPG_ERR_LOCKED);
786 if ((rc = open_card (ctrl, NULL)))
787 return rc;
789 /* We have to use a copy of the key ID because the function may use
790 the pin_cb which in turn uses the assuan line buffer and thus
791 overwriting the original line with the keyid */
792 keyidstr = xtrystrdup (line);
793 if (!keyidstr)
794 return out_of_core ();
796 rc = app_sign (ctrl->app_ctx,
797 keyidstr, hash_algo,
798 pin_cb, ctx,
799 ctrl->in_data.value, ctrl->in_data.valuelen,
800 &outdata, &outdatalen);
802 xfree (keyidstr);
803 if (rc)
805 log_error ("card_sign failed: %s\n", gpg_strerror (rc));
807 else
809 rc = assuan_send_data (ctx, outdata, outdatalen);
810 xfree (outdata);
811 if (rc)
812 return rc; /* that is already an assuan error code */
815 TEST_CARD_REMOVAL (ctrl, rc);
816 return rc;
819 /* PKAUTH <hexified_id>
822 static int
823 cmd_pkauth (assuan_context_t ctx, char *line)
825 ctrl_t ctrl = assuan_get_pointer (ctx);
826 int rc;
827 unsigned char *outdata;
828 size_t outdatalen;
829 char *keyidstr;
831 if ( IS_LOCKED (ctrl) )
832 return gpg_error (GPG_ERR_LOCKED);
834 if ((rc = open_card (ctrl, NULL)))
835 return rc;
837 if (!ctrl->app_ctx)
838 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
840 /* We have to use a copy of the key ID because the function may use
841 the pin_cb which in turn uses the assuan line buffer and thus
842 overwriting the original line with the keyid */
843 keyidstr = xtrystrdup (line);
844 if (!keyidstr)
845 return out_of_core ();
847 rc = app_auth (ctrl->app_ctx,
848 keyidstr,
849 pin_cb, ctx,
850 ctrl->in_data.value, ctrl->in_data.valuelen,
851 &outdata, &outdatalen);
852 xfree (keyidstr);
853 if (rc)
855 log_error ("app_auth_sign failed: %s\n", gpg_strerror (rc));
857 else
859 rc = assuan_send_data (ctx, outdata, outdatalen);
860 xfree (outdata);
861 if (rc)
862 return rc; /* that is already an assuan error code */
865 TEST_CARD_REMOVAL (ctrl, rc);
866 return rc;
869 /* PKDECRYPT <hexified_id>
872 static int
873 cmd_pkdecrypt (assuan_context_t ctx, char *line)
875 ctrl_t ctrl = assuan_get_pointer (ctx);
876 int rc;
877 unsigned char *outdata;
878 size_t outdatalen;
879 char *keyidstr;
881 if ( IS_LOCKED (ctrl) )
882 return gpg_error (GPG_ERR_LOCKED);
884 if ((rc = open_card (ctrl, NULL)))
885 return rc;
887 keyidstr = xtrystrdup (line);
888 if (!keyidstr)
889 return out_of_core ();
890 rc = app_decipher (ctrl->app_ctx,
891 keyidstr,
892 pin_cb, ctx,
893 ctrl->in_data.value, ctrl->in_data.valuelen,
894 &outdata, &outdatalen);
896 xfree (keyidstr);
897 if (rc)
899 log_error ("card_create_signature failed: %s\n", gpg_strerror (rc));
901 else
903 rc = assuan_send_data (ctx, outdata, outdatalen);
904 xfree (outdata);
905 if (rc)
906 return rc; /* that is already an assuan error code */
909 TEST_CARD_REMOVAL (ctrl, rc);
910 return rc;
914 /* GETATTR <name>
916 This command is used to retrieve data from a smartcard. The
917 allowed names depend on the currently selected smartcard
918 application. NAME must be percent and '+' escaped. The value is
919 returned through status message, see the LEARN command for details.
921 However, the current implementation assumes that Name is not escaped;
922 this works as long as noone uses arbitrary escaping.
924 Note, that this function may even be used on a locked card.
926 static int
927 cmd_getattr (assuan_context_t ctx, char *line)
929 ctrl_t ctrl = assuan_get_pointer (ctx);
930 int rc;
931 const char *keyword;
933 if ((rc = open_card (ctrl, NULL)))
934 return rc;
936 keyword = line;
937 for (; *line && !spacep (line); line++)
939 if (*line)
940 *line++ = 0;
942 /* (We ignore any garbage for now.) */
944 /* FIXME: Applications should not return sensitive data if the card
945 is locked. */
946 rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
948 TEST_CARD_REMOVAL (ctrl, rc);
949 return rc;
953 /* SETATTR <name> <value>
955 This command is used to store data on a a smartcard. The allowed
956 names and values are depend on the currently selected smartcard
957 application. NAME and VALUE must be percent and '+' escaped.
959 However, the curent implementation assumes that Name is not escaped;
960 this works as long as noone uses arbitrary escaping.
962 A PIN will be requested for most NAMEs. See the corresponding
963 setattr function of the actually used application (app-*.c) for
964 details. */
965 static int
966 cmd_setattr (assuan_context_t ctx, char *orig_line)
968 ctrl_t ctrl = assuan_get_pointer (ctx);
969 int rc;
970 char *keyword;
971 int keywordlen;
972 size_t nbytes;
973 char *line, *linebuf;
975 if ( IS_LOCKED (ctrl) )
976 return gpg_error (GPG_ERR_LOCKED);
978 if ((rc = open_card (ctrl, NULL)))
979 return rc;
981 /* We need to use a copy of LINE, because PIN_CB uses the same
982 context and thus reuses the Assuan provided LINE. */
983 line = linebuf = xtrystrdup (orig_line);
984 if (!line)
985 return out_of_core ();
987 keyword = line;
988 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
990 if (*line)
991 *line++ = 0;
992 while (spacep (line))
993 line++;
994 nbytes = percent_plus_unescape ((unsigned char*)line);
996 rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx,
997 (const unsigned char*)line, nbytes);
998 xfree (linebuf);
1000 TEST_CARD_REMOVAL (ctrl, rc);
1001 return rc;
1006 /* WRITEKEY [--force] <keyid>
1008 This command is used to store a secret key on a a smartcard. The
1009 allowed keyids depend on the currently selected smartcard
1010 application. The actual keydata is requested using the inquiry
1011 "KETDATA" and need to be provided without any protection. With
1012 --force set an existing key under this KEYID will get overwritten.
1013 The keydata is expected to be the usual canonical encoded
1014 S-expression.
1016 A PIN will be requested for most NAMEs. See the corresponding
1017 writekey function of the actually used application (app-*.c) for
1018 details. */
1019 static int
1020 cmd_writekey (assuan_context_t ctx, char *line)
1022 ctrl_t ctrl = assuan_get_pointer (ctx);
1023 int rc;
1024 char *keyid;
1025 int force = has_option (line, "--force");
1026 unsigned char *keydata;
1027 size_t keydatalen;
1029 if ( IS_LOCKED (ctrl) )
1030 return gpg_error (GPG_ERR_LOCKED);
1032 /* Skip over options. */
1033 while ( *line == '-' && line[1] == '-' )
1035 while (*line && !spacep (line))
1036 line++;
1037 while (spacep (line))
1038 line++;
1040 if (!*line)
1041 return set_error (GPG_ERR_ASS_PARAMETER, "no keyid given");
1042 keyid = line;
1043 while (*line && !spacep (line))
1044 line++;
1045 *line = 0;
1047 if ((rc = open_card (ctrl, NULL)))
1048 return rc;
1050 if (!ctrl->app_ctx)
1051 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1053 keyid = xtrystrdup (keyid);
1054 if (!keyid)
1055 return out_of_core ();
1057 /* Now get the actual keydata. */
1058 rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA);
1059 if (rc)
1061 xfree (keyid);
1062 return rc;
1065 /* Write the key to the card. */
1066 rc = app_writekey (ctrl->app_ctx, ctrl, keyid, force? 1:0,
1067 pin_cb, ctx, keydata, keydatalen);
1068 xfree (keyid);
1069 xfree (keydata);
1071 TEST_CARD_REMOVAL (ctrl, rc);
1072 return rc;
1077 /* GENKEY [--force] <no>
1079 Generate a key on-card identified by NO, which is application
1080 specific. Return values are application specific. For OpenPGP
1081 cards 2 status lines are returned:
1083 S KEY-FPR <hexstring>
1084 S KEY-CREATED-AT <seconds_since_epoch>
1085 S KEY-DATA [p|n] <hexdata>
1088 --force is required to overwrite an already existing key. The
1089 KEY-CREATED-AT is required for further processing because it is
1090 part of the hashed key material for the fingerprint.
1092 The public part of the key can also later be retrieved using the
1093 READKEY command.
1096 static int
1097 cmd_genkey (assuan_context_t ctx, char *line)
1099 ctrl_t ctrl = assuan_get_pointer (ctx);
1100 int rc;
1101 char *keyno;
1102 int force = has_option (line, "--force");
1104 if ( IS_LOCKED (ctrl) )
1105 return gpg_error (GPG_ERR_LOCKED);
1107 /* Skip over options. */
1108 while ( *line == '-' && line[1] == '-' )
1110 while (*line && !spacep (line))
1111 line++;
1112 while (spacep (line))
1113 line++;
1115 if (!*line)
1116 return set_error (GPG_ERR_ASS_PARAMETER, "no key number given");
1117 keyno = line;
1118 while (*line && !spacep (line))
1119 line++;
1120 *line = 0;
1122 if ((rc = open_card (ctrl, NULL)))
1123 return rc;
1125 if (!ctrl->app_ctx)
1126 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1128 keyno = xtrystrdup (keyno);
1129 if (!keyno)
1130 return out_of_core ();
1131 rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0, pin_cb, ctx);
1132 xfree (keyno);
1134 TEST_CARD_REMOVAL (ctrl, rc);
1135 return rc;
1139 /* RANDOM <nbytes>
1141 Get NBYTES of random from the card and send them back as data.
1143 Note, that this function may be even be used on a locked card.
1145 static int
1146 cmd_random (assuan_context_t ctx, char *line)
1148 ctrl_t ctrl = assuan_get_pointer (ctx);
1149 int rc;
1150 size_t nbytes;
1151 unsigned char *buffer;
1153 if (!*line)
1154 return set_error (GPG_ERR_ASS_PARAMETER, "number of requested bytes missing");
1155 nbytes = strtoul (line, NULL, 0);
1157 if ((rc = open_card (ctrl, NULL)))
1158 return rc;
1160 if (!ctrl->app_ctx)
1161 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1163 buffer = xtrymalloc (nbytes);
1164 if (!buffer)
1165 return out_of_core ();
1167 rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
1168 if (!rc)
1170 rc = assuan_send_data (ctx, buffer, nbytes);
1171 xfree (buffer);
1172 return rc; /* that is already an assuan error code */
1174 xfree (buffer);
1176 TEST_CARD_REMOVAL (ctrl, rc);
1177 return rc;
1181 /* PASSWD [--reset] <chvno>
1183 Change the PIN or reset the retry counter of the card holder
1184 verfication vector CHVNO. */
1185 static int
1186 cmd_passwd (assuan_context_t ctx, char *line)
1188 ctrl_t ctrl = assuan_get_pointer (ctx);
1189 int rc;
1190 char *chvnostr;
1191 int reset_mode = has_option (line, "--reset");
1193 if ( IS_LOCKED (ctrl) )
1194 return gpg_error (GPG_ERR_LOCKED);
1196 /* Skip over options. */
1197 while (*line == '-' && line[1] == '-')
1199 while (*line && !spacep (line))
1200 line++;
1201 while (spacep (line))
1202 line++;
1204 if (!*line)
1205 return set_error (GPG_ERR_ASS_PARAMETER, "no CHV number given");
1206 chvnostr = line;
1207 while (*line && !spacep (line))
1208 line++;
1209 *line = 0;
1211 if ((rc = open_card (ctrl, NULL)))
1212 return rc;
1214 if (!ctrl->app_ctx)
1215 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1217 chvnostr = xtrystrdup (chvnostr);
1218 if (!chvnostr)
1219 return out_of_core ();
1220 rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, reset_mode, pin_cb, ctx);
1221 if (rc)
1222 log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1223 xfree (chvnostr);
1225 TEST_CARD_REMOVAL (ctrl, rc);
1226 return rc;
1230 /* CHECKPIN <idstr>
1232 Perform a VERIFY operation without doing anything else. This may
1233 be used to initialize a the PIN cache earlier to long lasting
1234 operations. Its use is highly application dependent.
1236 For OpenPGP:
1238 Perform a simple verify operation for CHV1 and CHV2, so that
1239 further operations won't ask for CHV2 and it is possible to do a
1240 cheap check on the PIN: If there is something wrong with the PIN
1241 entry system, only the regular CHV will get blocked and not the
1242 dangerous CHV3. IDSTR is the usual card's serial number in hex
1243 notation; an optional fingerprint part will get ignored. There
1244 is however a special mode if the IDSTR is sffixed with the
1245 literal string "[CHV3]": In this case the Admin PIN is checked
1246 if and only if the retry counter is still at 3.
1249 static int
1250 cmd_checkpin (assuan_context_t ctx, char *line)
1252 ctrl_t ctrl = assuan_get_pointer (ctx);
1253 int rc;
1254 char *keyidstr;
1256 if ( IS_LOCKED (ctrl) )
1257 return gpg_error (GPG_ERR_LOCKED);
1259 if ((rc = open_card (ctrl, NULL)))
1260 return rc;
1262 if (!ctrl->app_ctx)
1263 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1265 /* We have to use a copy of the key ID because the function may use
1266 the pin_cb which in turn uses the assuan line buffer and thus
1267 overwriting the original line with the keyid. */
1268 keyidstr = xtrystrdup (line);
1269 if (!keyidstr)
1270 return out_of_core ();
1272 rc = app_check_pin (ctrl->app_ctx,
1273 keyidstr,
1274 pin_cb, ctx);
1275 xfree (keyidstr);
1276 if (rc)
1277 log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
1279 TEST_CARD_REMOVAL (ctrl, rc);
1280 return rc;
1284 /* LOCK [--wait]
1286 Grant exclusive card access to this session. Note that there is
1287 no lock counter used and a second lock from the same session will
1288 be ignored. A single unlock (or RESET) unlocks the session.
1289 Return GPG_ERR_LOCKED if another session has locked the reader.
1291 If the option --wait is given the command will wait until a
1292 lock has been released.
1294 static int
1295 cmd_lock (assuan_context_t ctx, char *line)
1297 ctrl_t ctrl = assuan_get_pointer (ctx);
1298 int rc = 0;
1300 retry:
1301 if (locked_session)
1303 if (locked_session != ctrl->server_local)
1304 rc = gpg_error (GPG_ERR_LOCKED);
1306 else
1307 locked_session = ctrl->server_local;
1309 #ifdef USE_GNU_PTH
1310 if (rc && has_option (line, "--wait"))
1312 rc = 0;
1313 pth_sleep (1); /* Better implement an event mechanism. However,
1314 for card operations this should be
1315 sufficient. */
1316 /* FIXME: Need to check that the connection is still alive.
1317 This can be done by issuing status messages. */
1318 goto retry;
1320 #endif /*USE_GNU_PTH*/
1322 if (rc)
1323 log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
1324 return rc;
1328 /* UNLOCK
1330 Release exclusive card access.
1332 static int
1333 cmd_unlock (assuan_context_t ctx, char *line)
1335 ctrl_t ctrl = assuan_get_pointer (ctx);
1336 int rc = 0;
1338 if (locked_session)
1340 if (locked_session != ctrl->server_local)
1341 rc = gpg_error (GPG_ERR_LOCKED);
1342 else
1343 locked_session = NULL;
1345 else
1346 rc = gpg_error (GPG_ERR_NOT_LOCKED);
1348 if (rc)
1349 log_error ("cmd_unlock failed: %s\n", gpg_strerror (rc));
1350 return rc;
1354 /* GETINFO <what>
1356 Multi purpose command to return certain information.
1357 Supported values of WHAT are:
1359 socket_name - Return the name of the socket.
1360 status - Return the status of the current slot (in the future, may
1361 also return the status of all slots). The status is a list of
1362 one-character flags. The following flags are currently defined:
1363 'u' Usable card present. This is the normal state during operation.
1364 'r' Card removed. A reset is necessary.
1365 These flags are exclusive.
1368 static int
1369 cmd_getinfo (assuan_context_t ctx, char *line)
1371 int rc = 0;
1373 if (!strcmp (line, "socket_name"))
1375 const char *s = scd_get_socket_name ();
1377 if (s)
1378 rc = assuan_send_data (ctx, s, strlen (s));
1379 else
1380 rc = gpg_error (GPG_ERR_NO_DATA);
1382 else if (!strcmp (line, "status"))
1384 ctrl_t ctrl = assuan_get_pointer (ctx);
1385 int slot = ctrl->reader_slot;
1386 char flag = 'r';
1388 if (!ctrl->server_local->card_removed && slot != -1)
1390 struct slot_status_s *ss;
1392 if (!(slot >= 0 && slot < DIM(slot_table)))
1393 BUG ();
1395 ss = &slot_table[slot];
1397 if (!ss->valid)
1398 BUG ();
1400 if (ss->any && (ss->status & 1))
1401 flag = 'u';
1403 rc = assuan_send_data (ctx, &flag, 1);
1405 else
1406 rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1407 return rc;
1411 /* RESTART
1413 Restart the current connection; this is a kind of warm reset. It
1414 deletes the context used by this connection but does not send a
1415 RESET to the card. Thus the card itself won't get reset.
1417 This is used by gpg-agent to reuse a primary pipe connection and
1418 may be used by clients to backup from a conflict in the serial
1419 command; i.e. to select another application.
1422 static int
1423 cmd_restart (assuan_context_t ctx, char *line)
1425 ctrl_t ctrl = assuan_get_pointer (ctx);
1427 if (ctrl->app_ctx)
1429 release_application (ctrl->app_ctx);
1430 ctrl->app_ctx = NULL;
1432 if (locked_session && ctrl->server_local == locked_session)
1434 locked_session = NULL;
1435 log_info ("implicitly unlocking due to RESTART\n");
1437 return 0;
1441 /* APDU [--atr] [--more] [hexstring]
1443 Send an APDU to the current reader. This command bypasses the high
1444 level functions and sends the data directly to the card. HEXSTRING
1445 is expected to be a proper APDU. If HEXSTRING is not given no
1446 commands are set to the card but the command will implictly check
1447 whether the card is ready for use.
1449 Using the option "--atr" returns the ATR of the card as a status
1450 message before any data like this:
1451 S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1
1453 Using the option --more handles the card status word MORE_DATA
1454 (61xx) and concatenate all reponses to one block.
1457 static int
1458 cmd_apdu (assuan_context_t ctx, char *line)
1460 ctrl_t ctrl = assuan_get_pointer (ctx);
1461 int rc;
1462 unsigned char *apdu;
1463 size_t apdulen;
1464 int with_atr;
1465 int handle_more;
1467 with_atr = has_option (line, "--atr");
1468 handle_more = has_option (line, "--more");
1470 /* Skip over options. */
1471 while ( *line == '-' && line[1] == '-' )
1473 while (*line && !spacep (line))
1474 line++;
1475 while (spacep (line))
1476 line++;
1479 if ( IS_LOCKED (ctrl) )
1480 return gpg_error (GPG_ERR_LOCKED);
1482 if ((rc = open_card (ctrl, NULL)))
1483 return rc;
1485 if (with_atr)
1487 unsigned char *atr;
1488 size_t atrlen;
1489 int i;
1490 char hexbuf[400];
1492 atr = apdu_get_atr (ctrl->reader_slot, &atrlen);
1493 if (!atr || atrlen > sizeof hexbuf - 2 )
1495 rc = gpg_error (GPG_ERR_INV_CARD);
1496 goto leave;
1498 for (i=0; i < atrlen; i++)
1499 sprintf (hexbuf+2*i, "%02X", atr[i]);
1500 xfree (atr);
1501 send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
1504 apdu = hex_to_buffer (line, &apdulen);
1505 if (!apdu)
1507 rc = gpg_error_from_syserror ();
1508 goto leave;
1510 if (apdulen)
1512 unsigned char *result = NULL;
1513 size_t resultlen;
1515 rc = apdu_send_direct (ctrl->reader_slot, apdu, apdulen, handle_more,
1516 &result, &resultlen);
1517 if (rc)
1518 log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
1519 else
1521 rc = assuan_send_data (ctx, result, resultlen);
1522 xfree (result);
1525 xfree (apdu);
1527 leave:
1528 TEST_CARD_REMOVAL (ctrl, rc);
1529 return rc;
1536 /* Tell the assuan library about our commands */
1537 static int
1538 register_commands (assuan_context_t ctx)
1540 static struct {
1541 const char *name;
1542 int (*handler)(assuan_context_t, char *line);
1543 } table[] = {
1544 { "SERIALNO", cmd_serialno },
1545 { "LEARN", cmd_learn },
1546 { "READCERT", cmd_readcert },
1547 { "READKEY", cmd_readkey },
1548 { "SETDATA", cmd_setdata },
1549 { "PKSIGN", cmd_pksign },
1550 { "PKAUTH", cmd_pkauth },
1551 { "PKDECRYPT", cmd_pkdecrypt },
1552 { "INPUT", NULL },
1553 { "OUTPUT", NULL },
1554 { "GETATTR", cmd_getattr },
1555 { "SETATTR", cmd_setattr },
1556 { "WRITEKEY", cmd_writekey },
1557 { "GENKEY", cmd_genkey },
1558 { "RANDOM", cmd_random },
1559 { "PASSWD", cmd_passwd },
1560 { "CHECKPIN", cmd_checkpin },
1561 { "LOCK", cmd_lock },
1562 { "UNLOCK", cmd_unlock },
1563 { "GETINFO", cmd_getinfo },
1564 { "RESTART", cmd_restart },
1565 { "APDU", cmd_apdu },
1566 { NULL }
1568 int i, rc;
1570 for (i=0; table[i].name; i++)
1572 rc = assuan_register_command (ctx, table[i].name, table[i].handler);
1573 if (rc)
1574 return rc;
1576 assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
1578 assuan_register_reset_notify (ctx, reset_notify);
1579 assuan_register_option_handler (ctx, option_handler);
1580 return 0;
1584 /* Startup the server. If FD is given as -1 this is simple pipe
1585 server, otherwise it is a regular server. */
1586 void
1587 scd_command_handler (int fd)
1589 int rc;
1590 assuan_context_t ctx;
1591 struct server_control_s ctrl;
1593 memset (&ctrl, 0, sizeof ctrl);
1594 scd_init_default_ctrl (&ctrl);
1596 if (fd == -1)
1598 int filedes[2];
1600 filedes[0] = 0;
1601 filedes[1] = 1;
1602 rc = assuan_init_pipe_server (&ctx, filedes);
1604 else
1606 rc = assuan_init_socket_server_ext (&ctx, fd, 2);
1608 if (rc)
1610 log_error ("failed to initialize the server: %s\n",
1611 gpg_strerror(rc));
1612 scd_exit (2);
1614 rc = register_commands (ctx);
1615 if (rc)
1617 log_error ("failed to register commands with Assuan: %s\n",
1618 gpg_strerror(rc));
1619 scd_exit (2);
1621 assuan_set_pointer (ctx, &ctrl);
1623 /* Allocate and initialize the server object. Put it into the list
1624 of active sessions. */
1625 ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
1626 ctrl.server_local->next_session = session_list;
1627 session_list = ctrl.server_local;
1628 ctrl.server_local->ctrl_backlink = &ctrl;
1629 ctrl.server_local->assuan_ctx = ctx;
1631 if (DBG_ASSUAN)
1632 assuan_set_log_stream (ctx, log_get_stream ());
1634 /* We open the reader right at startup so that the ticker is able to
1635 update the status file. */
1636 if (ctrl.reader_slot == -1)
1638 ctrl.reader_slot = get_reader_slot ();
1641 /* Command processing loop. */
1642 for (;;)
1644 rc = assuan_accept (ctx);
1645 if (rc == -1)
1647 break;
1649 else if (rc)
1651 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
1652 break;
1655 rc = assuan_process (ctx);
1656 if (rc)
1658 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
1659 continue;
1663 /* Cleanup. */
1664 do_reset (&ctrl, 0);
1666 /* Release the server object. */
1667 if (session_list == ctrl.server_local)
1668 session_list = ctrl.server_local->next_session;
1669 else
1671 struct server_local_s *sl;
1673 for (sl=session_list; sl->next_session; sl = sl->next_session)
1674 if (sl->next_session == ctrl.server_local)
1675 break;
1676 if (!sl->next_session)
1677 BUG ();
1678 sl->next_session = ctrl.server_local->next_session;
1680 xfree (ctrl.server_local);
1682 /* Release the Assuan context. */
1683 assuan_deinit_server (ctx);
1687 /* Send a line with status information via assuan and escape all given
1688 buffers. The variable elements are pairs of (char *, size_t),
1689 terminated with a (NULL, 0). */
1690 void
1691 send_status_info (ctrl_t ctrl, const char *keyword, ...)
1693 va_list arg_ptr;
1694 const unsigned char *value;
1695 size_t valuelen;
1696 char buf[950], *p;
1697 size_t n;
1698 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
1700 va_start (arg_ptr, keyword);
1702 p = buf;
1703 n = 0;
1704 while ( (value = va_arg (arg_ptr, const unsigned char *)) )
1706 valuelen = va_arg (arg_ptr, size_t);
1707 if (!valuelen)
1708 continue; /* empty buffer */
1709 if (n)
1711 *p++ = ' ';
1712 n++;
1714 for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
1716 if (*value < ' ' || *value == '+')
1718 sprintf (p, "%%%02X", *value);
1719 p += 3;
1721 else if (*value == ' ')
1722 *p++ = '+';
1723 else
1724 *p++ = *value;
1727 *p = 0;
1728 assuan_write_status (ctx, keyword, buf);
1730 va_end (arg_ptr);
1734 /* This is the core of scd_update_reader_status_file but the caller
1735 needs to take care of the locking. */
1736 static void
1737 update_reader_status_file (void)
1739 int idx;
1740 unsigned int status, changed;
1742 /* Note, that we only try to get the status, because it does not
1743 make sense to wait here for a operation to complete. If we are
1744 busy working with a card, delays in the status file update should
1745 be acceptable. */
1746 for (idx=0; idx < DIM(slot_table); idx++)
1748 struct slot_status_s *ss = slot_table + idx;
1750 if (!ss->valid || ss->slot == -1)
1751 continue; /* Not valid or reader not yet open. */
1753 if ( apdu_get_status (ss->slot, 0, &status, &changed) )
1754 continue; /* Get status failed. */
1756 if (!ss->any || ss->status != status || ss->changed != changed )
1758 char *fname;
1759 char templ[50];
1760 FILE *fp;
1761 struct server_local_s *sl;
1763 log_info ("updating status of slot %d to 0x%04X\n",
1764 ss->slot, status);
1766 /* FIXME: Should this be IDX instead of ss->slot? This
1767 depends on how client sessions will associate the reader
1768 status with their session. */
1769 sprintf (templ, "reader_%d.status", ss->slot);
1770 fname = make_filename (opt.homedir, templ, NULL );
1771 fp = fopen (fname, "w");
1772 if (fp)
1774 fprintf (fp, "%s\n",
1775 (status & 1)? "USABLE":
1776 (status & 4)? "ACTIVE":
1777 (status & 2)? "PRESENT": "NOCARD");
1778 fclose (fp);
1780 xfree (fname);
1782 /* If a status script is executable, run it. */
1784 const char *args[9], *envs[2];
1785 char numbuf1[30], numbuf2[30], numbuf3[30];
1786 char *homestr, *envstr;
1787 gpg_error_t err;
1789 homestr = make_filename (opt.homedir, NULL);
1790 if (asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
1791 log_error ("out of core while building environment\n");
1792 else
1794 envs[0] = envstr;
1795 envs[1] = NULL;
1797 sprintf (numbuf1, "%d", ss->slot);
1798 sprintf (numbuf2, "0x%04X", ss->status);
1799 sprintf (numbuf3, "0x%04X", status);
1800 args[0] = "--reader-port";
1801 args[1] = numbuf1;
1802 args[2] = "--old-code";
1803 args[3] = numbuf2;
1804 args[4] = "--new-code";
1805 args[5] = numbuf3;
1806 args[6] = "--status";
1807 args[7] = ((status & 1)? "USABLE":
1808 (status & 4)? "ACTIVE":
1809 (status & 2)? "PRESENT": "NOCARD");
1810 args[8] = NULL;
1812 fname = make_filename (opt.homedir, "scd-event", NULL);
1813 err = gnupg_spawn_process_detached (fname, args, envs);
1814 if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
1815 log_error ("failed to run event handler `%s': %s\n",
1816 fname, gpg_strerror (err));
1817 xfree (fname);
1818 free (envstr);
1820 xfree (homestr);
1823 /* Set the card removed flag for all current sessions. We
1824 will set this on any card change because a reset or
1825 SERIALNO request must be done in any case. */
1826 if (ss->any)
1827 update_card_removed (idx, 1);
1829 ss->any = 1;
1830 ss->status = status;
1831 ss->changed = changed;
1833 /* Send a signal to all clients who applied for it. */
1834 for (sl=session_list; sl; sl = sl->next_session)
1835 if (sl->event_signal && sl->assuan_ctx)
1837 pid_t pid = assuan_get_pid (sl->assuan_ctx);
1838 int signo = sl->event_signal;
1840 log_info ("client pid is %d, sending signal %d\n",
1841 pid, signo);
1842 #ifndef HAVE_W32_SYSTEM
1843 if (pid != (pid_t)(-1) && pid && signo > 0)
1844 kill (pid, signo);
1845 #endif
1852 /* This function is called by the ticker thread to check for changes
1853 of the reader stati. It updates the reader status files and if
1854 requested by the caller also send a signal to the caller. */
1855 void
1856 scd_update_reader_status_file (void)
1858 if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL))
1859 return; /* locked - give up. */
1860 update_reader_status_file ();
1861 if (!pth_mutex_release (&status_file_update_lock))
1862 log_error ("failed to release status_file_update lock\n");