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