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 <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <config.h>
22 : #include <errno.h>
23 : #include <stdio.h>
24 : #include <stdlib.h>
25 : #include <string.h>
26 : #include <ctype.h>
27 : #include <unistd.h>
28 : #include <signal.h>
29 : #ifdef USE_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 <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 : "\n"
737 : "Note, that this function may even be used on a locked card.";
738 : static gpg_error_t
739 0 : cmd_readkey (assuan_context_t ctx, char *line)
740 : {
741 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
742 : int rc;
743 0 : unsigned char *cert = NULL;
744 : size_t ncert, n;
745 0 : ksba_cert_t kc = NULL;
746 : ksba_sexp_t p;
747 : unsigned char *pk;
748 : size_t pklen;
749 :
750 0 : if ((rc = open_card (ctrl, NULL)))
751 0 : return rc;
752 :
753 0 : line = xstrdup (line); /* Need a copy of the line. */
754 : /* If the application supports the READKEY function we use that.
755 : Otherwise we use the old way by extracting it from the
756 : certificate. */
757 0 : rc = app_readkey (ctrl->app_ctx, line, &pk, &pklen);
758 0 : if (!rc)
759 : { /* Yeah, got that key - send it back. */
760 0 : rc = assuan_send_data (ctx, pk, pklen);
761 0 : xfree (pk);
762 0 : xfree (line);
763 0 : line = NULL;
764 0 : goto leave;
765 : }
766 :
767 0 : if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION)
768 0 : log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
769 : else
770 : {
771 0 : rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
772 0 : if (rc)
773 0 : log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
774 : }
775 0 : xfree (line);
776 0 : line = NULL;
777 0 : if (rc)
778 0 : goto leave;
779 :
780 0 : rc = ksba_cert_new (&kc);
781 0 : if (rc)
782 0 : goto leave;
783 :
784 0 : rc = ksba_cert_init_from_mem (kc, cert, ncert);
785 0 : if (rc)
786 : {
787 0 : log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
788 0 : goto leave;
789 : }
790 :
791 0 : p = ksba_cert_get_public_key (kc);
792 0 : if (!p)
793 : {
794 0 : rc = gpg_error (GPG_ERR_NO_PUBKEY);
795 0 : goto leave;
796 : }
797 :
798 0 : n = gcry_sexp_canon_len (p, 0, NULL, NULL);
799 0 : rc = assuan_send_data (ctx, p, n);
800 0 : xfree (p);
801 :
802 :
803 : leave:
804 0 : ksba_cert_release (kc);
805 0 : xfree (cert);
806 0 : TEST_CARD_REMOVAL (ctrl, rc);
807 0 : return rc;
808 : }
809 :
810 :
811 :
812 : static const char hlp_setdata[] =
813 : "SETDATA [--append] <hexstring>\n"
814 : "\n"
815 : "The client should use this command to tell us the data he want to sign.\n"
816 : "With the option --append, the data is appended to the data set by a\n"
817 : "previous SETDATA command.";
818 : static gpg_error_t
819 0 : cmd_setdata (assuan_context_t ctx, char *line)
820 : {
821 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
822 : int append;
823 : int n, i, off;
824 : char *p;
825 : unsigned char *buf;
826 :
827 0 : append = (ctrl->in_data.value && has_option (line, "--append"));
828 :
829 0 : line = skip_options (line);
830 :
831 0 : if (locked_session && locked_session != ctrl->server_local)
832 0 : return gpg_error (GPG_ERR_LOCKED);
833 :
834 : /* Parse the hexstring. */
835 0 : for (p=line,n=0; hexdigitp (p); p++, n++)
836 : ;
837 0 : if (*p)
838 0 : return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
839 0 : if (!n)
840 0 : return set_error (GPG_ERR_ASS_PARAMETER, "no data given");
841 0 : if ((n&1))
842 0 : return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
843 0 : n /= 2;
844 0 : if (append)
845 : {
846 0 : if (ctrl->in_data.valuelen + n > MAXLEN_SETDATA)
847 0 : return set_error (GPG_ERR_TOO_LARGE,
848 : "limit on total size of data reached");
849 0 : buf = xtrymalloc (ctrl->in_data.valuelen + n);
850 : }
851 : else
852 0 : buf = xtrymalloc (n);
853 0 : if (!buf)
854 0 : return out_of_core ();
855 :
856 0 : if (append)
857 : {
858 0 : memcpy (buf, ctrl->in_data.value, ctrl->in_data.valuelen);
859 0 : off = ctrl->in_data.valuelen;
860 : }
861 : else
862 0 : off = 0;
863 0 : for (p=line, i=0; i < n; p += 2, i++)
864 0 : buf[off+i] = xtoi_2 (p);
865 :
866 0 : xfree (ctrl->in_data.value);
867 0 : ctrl->in_data.value = buf;
868 0 : ctrl->in_data.valuelen = off+n;
869 0 : return 0;
870 : }
871 :
872 :
873 :
874 : static gpg_error_t
875 0 : pin_cb (void *opaque, const char *info, char **retstr)
876 : {
877 0 : assuan_context_t ctx = opaque;
878 : char *command;
879 : int rc;
880 : unsigned char *value;
881 : size_t valuelen;
882 :
883 0 : if (!retstr)
884 : {
885 : /* We prompt for pinpad entry. To make sure that the popup has
886 : been show we use an inquire and not just a status message.
887 : We ignore any value returned. */
888 0 : if (info)
889 : {
890 0 : log_debug ("prompting for pinpad entry '%s'\n", info);
891 0 : rc = gpgrt_asprintf (&command, "POPUPPINPADPROMPT %s", info);
892 0 : if (rc < 0)
893 0 : return gpg_error (gpg_err_code_from_errno (errno));
894 0 : rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
895 0 : xfree (command);
896 : }
897 : else
898 : {
899 0 : log_debug ("dismiss pinpad entry prompt\n");
900 0 : rc = assuan_inquire (ctx, "DISMISSPINPADPROMPT",
901 : &value, &valuelen, MAXLEN_PIN);
902 : }
903 0 : if (!rc)
904 0 : xfree (value);
905 0 : return rc;
906 : }
907 :
908 0 : *retstr = NULL;
909 0 : log_debug ("asking for PIN '%s'\n", info);
910 :
911 0 : rc = gpgrt_asprintf (&command, "NEEDPIN %s", info);
912 0 : if (rc < 0)
913 0 : return gpg_error (gpg_err_code_from_errno (errno));
914 :
915 : /* Fixme: Write an inquire function which returns the result in
916 : secure memory and check all further handling of the PIN. */
917 0 : rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
918 0 : xfree (command);
919 0 : if (rc)
920 0 : return rc;
921 :
922 0 : if (!valuelen || value[valuelen-1])
923 : {
924 : /* We require that the returned value is an UTF-8 string */
925 0 : xfree (value);
926 0 : return gpg_error (GPG_ERR_INV_RESPONSE);
927 : }
928 0 : *retstr = (char*)value;
929 0 : return 0;
930 : }
931 :
932 :
933 : static const char hlp_pksign[] =
934 : "PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5]] <hexified_id>\n"
935 : "\n"
936 : "The --hash option is optional; the default is SHA1.";
937 : static gpg_error_t
938 0 : cmd_pksign (assuan_context_t ctx, char *line)
939 : {
940 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
941 : int rc;
942 : unsigned char *outdata;
943 : size_t outdatalen;
944 : char *keyidstr;
945 : int hash_algo;
946 :
947 0 : if (has_option (line, "--hash=rmd160"))
948 0 : hash_algo = GCRY_MD_RMD160;
949 0 : else if (has_option (line, "--hash=sha1"))
950 0 : hash_algo = GCRY_MD_SHA1;
951 0 : else if (has_option (line, "--hash=sha224"))
952 0 : hash_algo = GCRY_MD_SHA224;
953 0 : else if (has_option (line, "--hash=sha256"))
954 0 : hash_algo = GCRY_MD_SHA256;
955 0 : else if (has_option (line, "--hash=sha384"))
956 0 : hash_algo = GCRY_MD_SHA384;
957 0 : else if (has_option (line, "--hash=sha512"))
958 0 : hash_algo = GCRY_MD_SHA512;
959 0 : else if (has_option (line, "--hash=md5"))
960 0 : hash_algo = GCRY_MD_MD5;
961 0 : else if (!strstr (line, "--"))
962 0 : hash_algo = GCRY_MD_SHA1;
963 : else
964 0 : return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
965 :
966 0 : line = skip_options (line);
967 :
968 0 : if ( IS_LOCKED (ctrl) )
969 0 : return gpg_error (GPG_ERR_LOCKED);
970 :
971 0 : if ((rc = open_card (ctrl, NULL)))
972 0 : return rc;
973 :
974 : /* We have to use a copy of the key ID because the function may use
975 : the pin_cb which in turn uses the assuan line buffer and thus
976 : overwriting the original line with the keyid */
977 0 : keyidstr = xtrystrdup (line);
978 0 : if (!keyidstr)
979 0 : return out_of_core ();
980 :
981 0 : rc = app_sign (ctrl->app_ctx,
982 : keyidstr, hash_algo,
983 : pin_cb, ctx,
984 0 : ctrl->in_data.value, ctrl->in_data.valuelen,
985 : &outdata, &outdatalen);
986 :
987 0 : xfree (keyidstr);
988 0 : if (rc)
989 : {
990 0 : log_error ("app_sign failed: %s\n", gpg_strerror (rc));
991 : }
992 : else
993 : {
994 0 : rc = assuan_send_data (ctx, outdata, outdatalen);
995 0 : xfree (outdata);
996 0 : if (rc)
997 0 : return rc; /* that is already an assuan error code */
998 : }
999 :
1000 0 : TEST_CARD_REMOVAL (ctrl, rc);
1001 0 : return rc;
1002 : }
1003 :
1004 :
1005 : static const char hlp_pkauth[] =
1006 : "PKAUTH <hexified_id>";
1007 : static gpg_error_t
1008 0 : cmd_pkauth (assuan_context_t ctx, char *line)
1009 : {
1010 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1011 : int rc;
1012 : unsigned char *outdata;
1013 : size_t outdatalen;
1014 : char *keyidstr;
1015 :
1016 0 : if ( IS_LOCKED (ctrl) )
1017 0 : return gpg_error (GPG_ERR_LOCKED);
1018 :
1019 0 : if ((rc = open_card (ctrl, NULL)))
1020 0 : return rc;
1021 :
1022 0 : if (!ctrl->app_ctx)
1023 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1024 :
1025 : /* We have to use a copy of the key ID because the function may use
1026 : the pin_cb which in turn uses the assuan line buffer and thus
1027 : overwriting the original line with the keyid */
1028 0 : keyidstr = xtrystrdup (line);
1029 0 : if (!keyidstr)
1030 0 : return out_of_core ();
1031 :
1032 0 : rc = app_auth (ctrl->app_ctx,
1033 : keyidstr,
1034 : pin_cb, ctx,
1035 0 : ctrl->in_data.value, ctrl->in_data.valuelen,
1036 : &outdata, &outdatalen);
1037 0 : xfree (keyidstr);
1038 0 : if (rc)
1039 : {
1040 0 : log_error ("app_auth failed: %s\n", gpg_strerror (rc));
1041 : }
1042 : else
1043 : {
1044 0 : rc = assuan_send_data (ctx, outdata, outdatalen);
1045 0 : xfree (outdata);
1046 0 : if (rc)
1047 0 : return rc; /* that is already an assuan error code */
1048 : }
1049 :
1050 0 : TEST_CARD_REMOVAL (ctrl, rc);
1051 0 : return rc;
1052 : }
1053 :
1054 :
1055 : static const char hlp_pkdecrypt[] =
1056 : "PKDECRYPT <hexified_id>";
1057 : static gpg_error_t
1058 0 : cmd_pkdecrypt (assuan_context_t ctx, char *line)
1059 : {
1060 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1061 : int rc;
1062 : unsigned char *outdata;
1063 : size_t outdatalen;
1064 : char *keyidstr;
1065 : unsigned int infoflags;
1066 :
1067 0 : if ( IS_LOCKED (ctrl) )
1068 0 : return gpg_error (GPG_ERR_LOCKED);
1069 :
1070 0 : if ((rc = open_card (ctrl, NULL)))
1071 0 : return rc;
1072 :
1073 0 : keyidstr = xtrystrdup (line);
1074 0 : if (!keyidstr)
1075 0 : return out_of_core ();
1076 0 : rc = app_decipher (ctrl->app_ctx,
1077 : keyidstr,
1078 : pin_cb, ctx,
1079 0 : ctrl->in_data.value, ctrl->in_data.valuelen,
1080 : &outdata, &outdatalen, &infoflags);
1081 :
1082 0 : xfree (keyidstr);
1083 0 : if (rc)
1084 : {
1085 0 : log_error ("app_decipher failed: %s\n", gpg_strerror (rc));
1086 : }
1087 : else
1088 : {
1089 : /* If the card driver told us that there is no padding, send a
1090 : status line. If there is a padding it is assumed that the
1091 : caller knows what padding is used. It would have been better
1092 : to always send that information but for backward
1093 : compatibility we can't do that. */
1094 0 : if ((infoflags & APP_DECIPHER_INFO_NOPAD))
1095 0 : send_status_direct (ctrl, "PADDING", "0");
1096 0 : rc = assuan_send_data (ctx, outdata, outdatalen);
1097 0 : xfree (outdata);
1098 0 : if (rc)
1099 0 : return rc; /* that is already an assuan error code */
1100 : }
1101 :
1102 0 : TEST_CARD_REMOVAL (ctrl, rc);
1103 0 : return rc;
1104 : }
1105 :
1106 :
1107 : static const char hlp_getattr[] =
1108 : "GETATTR <name>\n"
1109 : "\n"
1110 : "This command is used to retrieve data from a smartcard. The\n"
1111 : "allowed names depend on the currently selected smartcard\n"
1112 : "application. NAME must be percent and '+' escaped. The value is\n"
1113 : "returned through status message, see the LEARN command for details.\n"
1114 : "\n"
1115 : "However, the current implementation assumes that Name is not escaped;\n"
1116 : "this works as long as no one uses arbitrary escaping. \n"
1117 : "\n"
1118 : "Note, that this function may even be used on a locked card.";
1119 : static gpg_error_t
1120 0 : cmd_getattr (assuan_context_t ctx, char *line)
1121 : {
1122 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1123 : int rc;
1124 : const char *keyword;
1125 :
1126 0 : if ((rc = open_card (ctrl, NULL)))
1127 0 : return rc;
1128 :
1129 0 : keyword = line;
1130 0 : for (; *line && !spacep (line); line++)
1131 : ;
1132 0 : if (*line)
1133 0 : *line++ = 0;
1134 :
1135 : /* (We ignore any garbage for now.) */
1136 :
1137 : /* FIXME: Applications should not return sensitive data if the card
1138 : is locked. */
1139 0 : rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
1140 :
1141 0 : TEST_CARD_REMOVAL (ctrl, rc);
1142 0 : return rc;
1143 : }
1144 :
1145 :
1146 : static const char hlp_setattr[] =
1147 : "SETATTR <name> <value> \n"
1148 : "\n"
1149 : "This command is used to store data on a a smartcard. The allowed\n"
1150 : "names and values are depend on the currently selected smartcard\n"
1151 : "application. NAME and VALUE must be percent and '+' escaped.\n"
1152 : "\n"
1153 : "However, the current implementation assumes that NAME is not\n"
1154 : "escaped; this works as long as no one uses arbitrary escaping.\n"
1155 : "\n"
1156 : "A PIN will be requested for most NAMEs. See the corresponding\n"
1157 : "setattr function of the actually used application (app-*.c) for\n"
1158 : "details.";
1159 : static gpg_error_t
1160 0 : cmd_setattr (assuan_context_t ctx, char *orig_line)
1161 : {
1162 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1163 : int rc;
1164 : char *keyword;
1165 : int keywordlen;
1166 : size_t nbytes;
1167 : char *line, *linebuf;
1168 :
1169 0 : if ( IS_LOCKED (ctrl) )
1170 0 : return gpg_error (GPG_ERR_LOCKED);
1171 :
1172 0 : if ((rc = open_card (ctrl, NULL)))
1173 0 : return rc;
1174 :
1175 : /* We need to use a copy of LINE, because PIN_CB uses the same
1176 : context and thus reuses the Assuan provided LINE. */
1177 0 : line = linebuf = xtrystrdup (orig_line);
1178 0 : if (!line)
1179 0 : return out_of_core ();
1180 :
1181 0 : keyword = line;
1182 0 : for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
1183 : ;
1184 0 : if (*line)
1185 0 : *line++ = 0;
1186 0 : while (spacep (line))
1187 0 : line++;
1188 0 : nbytes = percent_plus_unescape_inplace (line, 0);
1189 :
1190 0 : rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx,
1191 : (const unsigned char*)line, nbytes);
1192 0 : xfree (linebuf);
1193 :
1194 0 : TEST_CARD_REMOVAL (ctrl, rc);
1195 0 : return rc;
1196 : }
1197 :
1198 :
1199 : static const char hlp_writecert[] =
1200 : "WRITECERT <hexified_certid>\n"
1201 : "\n"
1202 : "This command is used to store a certifciate on a smartcard. The\n"
1203 : "allowed certids depend on the currently selected smartcard\n"
1204 : "application. The actual certifciate is requested using the inquiry\n"
1205 : "\"CERTDATA\" and needs to be provided in its raw (e.g. DER) form.\n"
1206 : "\n"
1207 : "In almost all cases a a PIN will be requested. See the related\n"
1208 : "writecert function of the actually used application (app-*.c) for\n"
1209 : "details.";
1210 : static gpg_error_t
1211 0 : cmd_writecert (assuan_context_t ctx, char *line)
1212 : {
1213 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1214 : int rc;
1215 : char *certid;
1216 : unsigned char *certdata;
1217 : size_t certdatalen;
1218 :
1219 0 : if ( IS_LOCKED (ctrl) )
1220 0 : return gpg_error (GPG_ERR_LOCKED);
1221 :
1222 0 : line = skip_options (line);
1223 :
1224 0 : if (!*line)
1225 0 : return set_error (GPG_ERR_ASS_PARAMETER, "no certid given");
1226 0 : certid = line;
1227 0 : while (*line && !spacep (line))
1228 0 : line++;
1229 0 : *line = 0;
1230 :
1231 0 : if ((rc = open_card (ctrl, NULL)))
1232 0 : return rc;
1233 :
1234 0 : if (!ctrl->app_ctx)
1235 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1236 :
1237 0 : certid = xtrystrdup (certid);
1238 0 : if (!certid)
1239 0 : return out_of_core ();
1240 :
1241 : /* Now get the actual keydata. */
1242 0 : rc = assuan_inquire (ctx, "CERTDATA",
1243 : &certdata, &certdatalen, MAXLEN_CERTDATA);
1244 0 : if (rc)
1245 : {
1246 0 : xfree (certid);
1247 0 : return rc;
1248 : }
1249 :
1250 : /* Write the certificate to the card. */
1251 0 : rc = app_writecert (ctrl->app_ctx, ctrl, certid,
1252 : pin_cb, ctx, certdata, certdatalen);
1253 0 : xfree (certid);
1254 0 : xfree (certdata);
1255 :
1256 0 : TEST_CARD_REMOVAL (ctrl, rc);
1257 0 : return rc;
1258 : }
1259 :
1260 :
1261 : static const char hlp_writekey[] =
1262 : "WRITEKEY [--force] <keyid> \n"
1263 : "\n"
1264 : "This command is used to store a secret key on a a smartcard. The\n"
1265 : "allowed keyids depend on the currently selected smartcard\n"
1266 : "application. The actual keydata is requested using the inquiry\n"
1267 : "\"KEYDATA\" and need to be provided without any protection. With\n"
1268 : "--force set an existing key under this KEYID will get overwritten.\n"
1269 : "The keydata is expected to be the usual canonical encoded\n"
1270 : "S-expression.\n"
1271 : "\n"
1272 : "A PIN will be requested for most NAMEs. See the corresponding\n"
1273 : "writekey function of the actually used application (app-*.c) for\n"
1274 : "details.";
1275 : static gpg_error_t
1276 0 : cmd_writekey (assuan_context_t ctx, char *line)
1277 : {
1278 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1279 : int rc;
1280 : char *keyid;
1281 0 : int force = has_option (line, "--force");
1282 : unsigned char *keydata;
1283 : size_t keydatalen;
1284 :
1285 0 : if ( IS_LOCKED (ctrl) )
1286 0 : return gpg_error (GPG_ERR_LOCKED);
1287 :
1288 0 : line = skip_options (line);
1289 :
1290 0 : if (!*line)
1291 0 : return set_error (GPG_ERR_ASS_PARAMETER, "no keyid given");
1292 0 : keyid = line;
1293 0 : while (*line && !spacep (line))
1294 0 : line++;
1295 0 : *line = 0;
1296 :
1297 0 : if ((rc = open_card (ctrl, NULL)))
1298 0 : return rc;
1299 :
1300 0 : if (!ctrl->app_ctx)
1301 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1302 :
1303 0 : keyid = xtrystrdup (keyid);
1304 0 : if (!keyid)
1305 0 : return out_of_core ();
1306 :
1307 : /* Now get the actual keydata. */
1308 0 : assuan_begin_confidential (ctx);
1309 0 : rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA);
1310 0 : assuan_end_confidential (ctx);
1311 0 : if (rc)
1312 : {
1313 0 : xfree (keyid);
1314 0 : return rc;
1315 : }
1316 :
1317 : /* Write the key to the card. */
1318 0 : rc = app_writekey (ctrl->app_ctx, ctrl, keyid, force? 1:0,
1319 : pin_cb, ctx, keydata, keydatalen);
1320 0 : xfree (keyid);
1321 0 : xfree (keydata);
1322 :
1323 0 : TEST_CARD_REMOVAL (ctrl, rc);
1324 0 : return rc;
1325 : }
1326 :
1327 :
1328 : static const char hlp_genkey[] =
1329 : "GENKEY [--force] [--timestamp=<isodate>] <no>\n"
1330 : "\n"
1331 : "Generate a key on-card identified by NO, which is application\n"
1332 : "specific. Return values are application specific. For OpenPGP\n"
1333 : "cards 3 status lines are returned:\n"
1334 : "\n"
1335 : " S KEY-FPR <hexstring>\n"
1336 : " S KEY-CREATED-AT <seconds_since_epoch>\n"
1337 : " S KEY-DATA [-|p|n] <hexdata>\n"
1338 : "\n"
1339 : " 'p' and 'n' are the names of the RSA parameters; '-' is used to\n"
1340 : " indicate that HEXDATA is the first chunk of a parameter given\n"
1341 : " by the next KEY-DATA.\n"
1342 : "\n"
1343 : "--force is required to overwrite an already existing key. The\n"
1344 : "KEY-CREATED-AT is required for further processing because it is\n"
1345 : "part of the hashed key material for the fingerprint.\n"
1346 : "\n"
1347 : "If --timestamp is given an OpenPGP key will be created using this\n"
1348 : "value. The value needs to be in ISO Format; e.g.\n"
1349 : "\"--timestamp=20030316T120000\" and after 1970-01-01 00:00:00.\n"
1350 : "\n"
1351 : "The public part of the key can also later be retrieved using the\n"
1352 : "READKEY command.";
1353 : static gpg_error_t
1354 0 : cmd_genkey (assuan_context_t ctx, char *line)
1355 : {
1356 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1357 : int rc;
1358 : char *keyno;
1359 : int force;
1360 : const char *s;
1361 : time_t timestamp;
1362 :
1363 0 : if ( IS_LOCKED (ctrl) )
1364 0 : return gpg_error (GPG_ERR_LOCKED);
1365 :
1366 0 : force = has_option (line, "--force");
1367 :
1368 0 : if ((s=has_option_name (line, "--timestamp")))
1369 : {
1370 0 : if (*s != '=')
1371 0 : return set_error (GPG_ERR_ASS_PARAMETER, "missing value for option");
1372 0 : timestamp = isotime2epoch (s+1);
1373 0 : if (timestamp < 1)
1374 0 : return set_error (GPG_ERR_ASS_PARAMETER, "invalid time value");
1375 : }
1376 : else
1377 0 : timestamp = 0;
1378 :
1379 :
1380 0 : line = skip_options (line);
1381 0 : if (!*line)
1382 0 : return set_error (GPG_ERR_ASS_PARAMETER, "no key number given");
1383 0 : keyno = line;
1384 0 : while (*line && !spacep (line))
1385 0 : line++;
1386 0 : *line = 0;
1387 :
1388 0 : if ((rc = open_card (ctrl, NULL)))
1389 0 : return rc;
1390 :
1391 0 : if (!ctrl->app_ctx)
1392 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1393 :
1394 0 : keyno = xtrystrdup (keyno);
1395 0 : if (!keyno)
1396 0 : return out_of_core ();
1397 0 : rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0,
1398 : timestamp, pin_cb, ctx);
1399 0 : xfree (keyno);
1400 :
1401 0 : TEST_CARD_REMOVAL (ctrl, rc);
1402 0 : return rc;
1403 : }
1404 :
1405 :
1406 : static const char hlp_random[] =
1407 : "RANDOM <nbytes>\n"
1408 : "\n"
1409 : "Get NBYTES of random from the card and send them back as data.\n"
1410 : "This usually involves EEPROM write on the card and thus excessive\n"
1411 : "use of this command may destroy the card.\n"
1412 : "\n"
1413 : "Note, that this function may be even be used on a locked card.";
1414 : static gpg_error_t
1415 0 : cmd_random (assuan_context_t ctx, char *line)
1416 : {
1417 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1418 : int rc;
1419 : size_t nbytes;
1420 : unsigned char *buffer;
1421 :
1422 0 : if (!*line)
1423 0 : return set_error (GPG_ERR_ASS_PARAMETER,
1424 : "number of requested bytes missing");
1425 0 : nbytes = strtoul (line, NULL, 0);
1426 :
1427 0 : if ((rc = open_card (ctrl, NULL)))
1428 0 : return rc;
1429 :
1430 0 : if (!ctrl->app_ctx)
1431 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1432 :
1433 0 : buffer = xtrymalloc (nbytes);
1434 0 : if (!buffer)
1435 0 : return out_of_core ();
1436 :
1437 0 : rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
1438 0 : if (!rc)
1439 : {
1440 0 : rc = assuan_send_data (ctx, buffer, nbytes);
1441 0 : xfree (buffer);
1442 0 : return rc; /* that is already an assuan error code */
1443 : }
1444 0 : xfree (buffer);
1445 :
1446 0 : TEST_CARD_REMOVAL (ctrl, rc);
1447 0 : return rc;
1448 : }
1449 :
1450 :
1451 :
1452 : static const char hlp_passwd[] =
1453 : "PASSWD [--reset] [--nullpin] <chvno>\n"
1454 : "\n"
1455 : "Change the PIN or, if --reset is given, reset the retry counter of\n"
1456 : "the card holder verification vector CHVNO. The option --nullpin is\n"
1457 : "used for TCOS cards to set the initial PIN. The format of CHVNO\n"
1458 : "depends on the card application.";
1459 : static gpg_error_t
1460 0 : cmd_passwd (assuan_context_t ctx, char *line)
1461 : {
1462 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1463 : int rc;
1464 : char *chvnostr;
1465 0 : unsigned int flags = 0;
1466 :
1467 0 : if (has_option (line, "--reset"))
1468 0 : flags |= APP_CHANGE_FLAG_RESET;
1469 0 : if (has_option (line, "--nullpin"))
1470 0 : flags |= APP_CHANGE_FLAG_NULLPIN;
1471 :
1472 0 : if ( IS_LOCKED (ctrl) )
1473 0 : return gpg_error (GPG_ERR_LOCKED);
1474 :
1475 0 : line = skip_options (line);
1476 :
1477 0 : if (!*line)
1478 0 : return set_error (GPG_ERR_ASS_PARAMETER, "no CHV number given");
1479 0 : chvnostr = line;
1480 0 : while (*line && !spacep (line))
1481 0 : line++;
1482 0 : *line = 0;
1483 :
1484 0 : if ((rc = open_card (ctrl, NULL)))
1485 0 : return rc;
1486 :
1487 0 : if (!ctrl->app_ctx)
1488 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1489 :
1490 0 : chvnostr = xtrystrdup (chvnostr);
1491 0 : if (!chvnostr)
1492 0 : return out_of_core ();
1493 0 : rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, flags, pin_cb, ctx);
1494 0 : if (rc)
1495 0 : log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1496 0 : xfree (chvnostr);
1497 :
1498 0 : TEST_CARD_REMOVAL (ctrl, rc);
1499 0 : return rc;
1500 : }
1501 :
1502 :
1503 : static const char hlp_checkpin[] =
1504 : "CHECKPIN <idstr>\n"
1505 : "\n"
1506 : "Perform a VERIFY operation without doing anything else. This may\n"
1507 : "be used to initialize a the PIN cache earlier to long lasting\n"
1508 : "operations. Its use is highly application dependent.\n"
1509 : "\n"
1510 : "For OpenPGP:\n"
1511 : "\n"
1512 : " Perform a simple verify operation for CHV1 and CHV2, so that\n"
1513 : " further operations won't ask for CHV2 and it is possible to do a\n"
1514 : " cheap check on the PIN: If there is something wrong with the PIN\n"
1515 : " entry system, only the regular CHV will get blocked and not the\n"
1516 : " dangerous CHV3. IDSTR is the usual card's serial number in hex\n"
1517 : " notation; an optional fingerprint part will get ignored. There\n"
1518 : " is however a special mode if the IDSTR is sffixed with the\n"
1519 : " literal string \"[CHV3]\": In this case the Admin PIN is checked\n"
1520 : " if and only if the retry counter is still at 3.\n"
1521 : "\n"
1522 : "For Netkey:\n"
1523 : "\n"
1524 : " Any of the valid PIN Ids may be used. These are the strings:\n"
1525 : "\n"
1526 : " PW1.CH - Global password 1\n"
1527 : " PW2.CH - Global password 2\n"
1528 : " PW1.CH.SIG - SigG password 1\n"
1529 : " PW2.CH.SIG - SigG password 2\n"
1530 : "\n"
1531 : " For a definitive list, see the implementation in app-nks.c.\n"
1532 : " Note that we call a PW2.* PIN a \"PUK\" despite that since TCOS\n"
1533 : " 3.0 they are technically alternative PINs used to mutally\n"
1534 : " unblock each other.";
1535 : static gpg_error_t
1536 0 : cmd_checkpin (assuan_context_t ctx, char *line)
1537 : {
1538 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1539 : int rc;
1540 : char *idstr;
1541 :
1542 0 : if ( IS_LOCKED (ctrl) )
1543 0 : return gpg_error (GPG_ERR_LOCKED);
1544 :
1545 0 : if ((rc = open_card (ctrl, NULL)))
1546 0 : return rc;
1547 :
1548 0 : if (!ctrl->app_ctx)
1549 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1550 :
1551 : /* We have to use a copy of the key ID because the function may use
1552 : the pin_cb which in turn uses the assuan line buffer and thus
1553 : overwriting the original line with the keyid. */
1554 0 : idstr = xtrystrdup (line);
1555 0 : if (!idstr)
1556 0 : return out_of_core ();
1557 :
1558 0 : rc = app_check_pin (ctrl->app_ctx, idstr, pin_cb, ctx);
1559 0 : xfree (idstr);
1560 0 : if (rc)
1561 0 : log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
1562 :
1563 0 : TEST_CARD_REMOVAL (ctrl, rc);
1564 0 : return rc;
1565 : }
1566 :
1567 :
1568 : static const char hlp_lock[] =
1569 : "LOCK [--wait]\n"
1570 : "\n"
1571 : "Grant exclusive card access to this session. Note that there is\n"
1572 : "no lock counter used and a second lock from the same session will\n"
1573 : "be ignored. A single unlock (or RESET) unlocks the session.\n"
1574 : "Return GPG_ERR_LOCKED if another session has locked the reader.\n"
1575 : "\n"
1576 : "If the option --wait is given the command will wait until a\n"
1577 : "lock has been released.";
1578 : static gpg_error_t
1579 0 : cmd_lock (assuan_context_t ctx, char *line)
1580 : {
1581 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1582 0 : int rc = 0;
1583 :
1584 : retry:
1585 0 : if (locked_session)
1586 : {
1587 0 : if (locked_session != ctrl->server_local)
1588 0 : rc = gpg_error (GPG_ERR_LOCKED);
1589 : }
1590 : else
1591 0 : locked_session = ctrl->server_local;
1592 :
1593 : #ifdef USE_NPTH
1594 0 : if (rc && has_option (line, "--wait"))
1595 : {
1596 0 : rc = 0;
1597 0 : npth_sleep (1); /* Better implement an event mechanism. However,
1598 : for card operations this should be
1599 : sufficient. */
1600 : /* FIXME: Need to check that the connection is still alive.
1601 : This can be done by issuing status messages. */
1602 0 : goto retry;
1603 : }
1604 : #endif /*USE_NPTH*/
1605 :
1606 0 : if (rc)
1607 0 : log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
1608 0 : return rc;
1609 : }
1610 :
1611 :
1612 : static const char hlp_unlock[] =
1613 : "UNLOCK\n"
1614 : "\n"
1615 : "Release exclusive card access.";
1616 : static gpg_error_t
1617 0 : cmd_unlock (assuan_context_t ctx, char *line)
1618 : {
1619 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1620 0 : int rc = 0;
1621 :
1622 : (void)line;
1623 :
1624 0 : if (locked_session)
1625 : {
1626 0 : if (locked_session != ctrl->server_local)
1627 0 : rc = gpg_error (GPG_ERR_LOCKED);
1628 : else
1629 0 : locked_session = NULL;
1630 : }
1631 : else
1632 0 : rc = gpg_error (GPG_ERR_NOT_LOCKED);
1633 :
1634 0 : if (rc)
1635 0 : log_error ("cmd_unlock failed: %s\n", gpg_strerror (rc));
1636 0 : return rc;
1637 : }
1638 :
1639 :
1640 : static const char hlp_getinfo[] =
1641 : "GETINFO <what>\n"
1642 : "\n"
1643 : "Multi purpose command to return certain information. \n"
1644 : "Supported values of WHAT are:\n"
1645 : "\n"
1646 : "version - Return the version of the program.\n"
1647 : "pid - Return the process id of the server.\n"
1648 : "\n"
1649 : "socket_name - Return the name of the socket.\n"
1650 : "\n"
1651 : "status - Return the status of the current reader (in the future, may\n"
1652 : "also return the status of all readers). The status is a list of\n"
1653 : "one-character flags. The following flags are currently defined:\n"
1654 : " 'u' Usable card present. This is the normal state during operation.\n"
1655 : " 'r' Card removed. A reset is necessary.\n"
1656 : "These flags are exclusive.\n"
1657 : "\n"
1658 : "reader_list - Return a list of detected card readers. Does\n"
1659 : " currently only work with the internal CCID driver.\n"
1660 : "\n"
1661 : "deny_admin - Returns OK if admin commands are not allowed or\n"
1662 : " GPG_ERR_GENERAL if admin commands are allowed.\n"
1663 : "\n"
1664 : "app_list - Return a list of supported applications. One\n"
1665 : " application per line, fields delimited by colons,\n"
1666 : " first field is the name.";
1667 : static gpg_error_t
1668 0 : cmd_getinfo (assuan_context_t ctx, char *line)
1669 : {
1670 0 : int rc = 0;
1671 :
1672 0 : if (!strcmp (line, "version"))
1673 : {
1674 0 : const char *s = VERSION;
1675 0 : rc = assuan_send_data (ctx, s, strlen (s));
1676 : }
1677 0 : else if (!strcmp (line, "pid"))
1678 : {
1679 : char numbuf[50];
1680 :
1681 0 : snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1682 0 : rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1683 : }
1684 0 : else if (!strcmp (line, "socket_name"))
1685 : {
1686 0 : const char *s = scd_get_socket_name ();
1687 :
1688 0 : if (s)
1689 0 : rc = assuan_send_data (ctx, s, strlen (s));
1690 : else
1691 0 : rc = gpg_error (GPG_ERR_NO_DATA);
1692 : }
1693 0 : else if (!strcmp (line, "status"))
1694 : {
1695 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1696 0 : int vrdr = ctrl->server_local->vreader_idx;
1697 0 : char flag = 'r';
1698 :
1699 0 : if (!ctrl->server_local->card_removed && vrdr != -1)
1700 : {
1701 : struct vreader_s *vr;
1702 :
1703 0 : if (!(vrdr >= 0 && vrdr < DIM(vreader_table)))
1704 0 : BUG ();
1705 :
1706 0 : vr = &vreader_table[vrdr];
1707 0 : if (vr->valid && vr->any && (vr->status & 1))
1708 0 : flag = 'u';
1709 : }
1710 0 : rc = assuan_send_data (ctx, &flag, 1);
1711 : }
1712 0 : else if (!strcmp (line, "reader_list"))
1713 : {
1714 : #ifdef HAVE_LIBUSB
1715 0 : char *s = ccid_get_reader_list ();
1716 : #else
1717 : char *s = NULL;
1718 : #endif
1719 :
1720 0 : if (s)
1721 0 : rc = assuan_send_data (ctx, s, strlen (s));
1722 : else
1723 0 : rc = gpg_error (GPG_ERR_NO_DATA);
1724 0 : xfree (s);
1725 : }
1726 0 : else if (!strcmp (line, "deny_admin"))
1727 0 : rc = opt.allow_admin? gpg_error (GPG_ERR_GENERAL) : 0;
1728 0 : else if (!strcmp (line, "app_list"))
1729 : {
1730 0 : char *s = get_supported_applications ();
1731 0 : if (s)
1732 0 : rc = assuan_send_data (ctx, s, strlen (s));
1733 : else
1734 0 : rc = 0;
1735 0 : xfree (s);
1736 : }
1737 : else
1738 0 : rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1739 0 : return rc;
1740 : }
1741 :
1742 :
1743 : static const char hlp_restart[] =
1744 : "RESTART\n"
1745 : "\n"
1746 : "Restart the current connection; this is a kind of warm reset. It\n"
1747 : "deletes the context used by this connection but does not send a\n"
1748 : "RESET to the card. Thus the card itself won't get reset. \n"
1749 : "\n"
1750 : "This is used by gpg-agent to reuse a primary pipe connection and\n"
1751 : "may be used by clients to backup from a conflict in the serial\n"
1752 : "command; i.e. to select another application.";
1753 : static gpg_error_t
1754 0 : cmd_restart (assuan_context_t ctx, char *line)
1755 : {
1756 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1757 0 : struct app_ctx_s *app = ctrl->app_ctx;
1758 :
1759 : (void)line;
1760 :
1761 0 : if (app)
1762 : {
1763 0 : ctrl->app_ctx = NULL;
1764 0 : release_application (app);
1765 : }
1766 0 : if (locked_session && ctrl->server_local == locked_session)
1767 : {
1768 0 : locked_session = NULL;
1769 0 : log_info ("implicitly unlocking due to RESTART\n");
1770 : }
1771 0 : return 0;
1772 : }
1773 :
1774 :
1775 : static const char hlp_disconnect[] =
1776 : "DISCONNECT\n"
1777 : "\n"
1778 : "Disconnect the card if it is not any longer used by other\n"
1779 : "connections and the backend supports a disconnect operation.";
1780 : static gpg_error_t
1781 0 : cmd_disconnect (assuan_context_t ctx, char *line)
1782 : {
1783 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1784 :
1785 : (void)line;
1786 :
1787 0 : ctrl->server_local->disconnect_allowed = 1;
1788 0 : return 0;
1789 : }
1790 :
1791 :
1792 :
1793 : static const char hlp_apdu[] =
1794 : "APDU [--[dump-]atr] [--more] [--exlen[=N]] [hexstring]\n"
1795 : "\n"
1796 : "Send an APDU to the current reader. This command bypasses the high\n"
1797 : "level functions and sends the data directly to the card. HEXSTRING\n"
1798 : "is expected to be a proper APDU. If HEXSTRING is not given no\n"
1799 : "commands are set to the card but the command will implictly check\n"
1800 : "whether the card is ready for use. \n"
1801 : "\n"
1802 : "Using the option \"--atr\" returns the ATR of the card as a status\n"
1803 : "message before any data like this:\n"
1804 : " S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1\n"
1805 : "\n"
1806 : "Using the option --more handles the card status word MORE_DATA\n"
1807 : "(61xx) and concatenates all responses to one block.\n"
1808 : "\n"
1809 : "Using the option \"--exlen\" the returned APDU may use extended\n"
1810 : "length up to N bytes. If N is not given a default value is used\n"
1811 : "(currently 4096).";
1812 : static gpg_error_t
1813 0 : cmd_apdu (assuan_context_t ctx, char *line)
1814 : {
1815 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1816 : int rc;
1817 : unsigned char *apdu;
1818 : size_t apdulen;
1819 : int with_atr;
1820 : int handle_more;
1821 : const char *s;
1822 : size_t exlen;
1823 : int slot;
1824 :
1825 0 : if (has_option (line, "--dump-atr"))
1826 0 : with_atr = 2;
1827 : else
1828 0 : with_atr = has_option (line, "--atr");
1829 0 : handle_more = has_option (line, "--more");
1830 :
1831 0 : if ((s=has_option_name (line, "--exlen")))
1832 : {
1833 0 : if (*s == '=')
1834 0 : exlen = strtoul (s+1, NULL, 0);
1835 : else
1836 0 : exlen = 4096;
1837 : }
1838 : else
1839 0 : exlen = 0;
1840 :
1841 0 : line = skip_options (line);
1842 :
1843 0 : if ( IS_LOCKED (ctrl) )
1844 0 : return gpg_error (GPG_ERR_LOCKED);
1845 :
1846 0 : if ((rc = open_card (ctrl, NULL)))
1847 0 : return rc;
1848 :
1849 0 : slot = vreader_slot (ctrl->server_local->vreader_idx);
1850 :
1851 0 : if (with_atr)
1852 : {
1853 : unsigned char *atr;
1854 : size_t atrlen;
1855 : char hexbuf[400];
1856 :
1857 0 : atr = apdu_get_atr (slot, &atrlen);
1858 0 : if (!atr || atrlen > sizeof hexbuf - 2 )
1859 : {
1860 0 : rc = gpg_error (GPG_ERR_INV_CARD);
1861 0 : goto leave;
1862 : }
1863 0 : if (with_atr == 2)
1864 : {
1865 : char *string, *p, *pend;
1866 :
1867 0 : string = atr_dump (atr, atrlen);
1868 0 : if (string)
1869 : {
1870 0 : for (rc=0, p=string; !rc && (pend = strchr (p, '\n')); p = pend+1)
1871 : {
1872 0 : rc = assuan_send_data (ctx, p, pend - p + 1);
1873 0 : if (!rc)
1874 0 : rc = assuan_send_data (ctx, NULL, 0);
1875 : }
1876 0 : if (!rc && *p)
1877 0 : rc = assuan_send_data (ctx, p, strlen (p));
1878 0 : es_free (string);
1879 0 : if (rc)
1880 0 : goto leave;
1881 : }
1882 : }
1883 : else
1884 : {
1885 0 : bin2hex (atr, atrlen, hexbuf);
1886 0 : send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
1887 : }
1888 0 : xfree (atr);
1889 : }
1890 :
1891 0 : apdu = hex_to_buffer (line, &apdulen);
1892 0 : if (!apdu)
1893 : {
1894 0 : rc = gpg_error_from_syserror ();
1895 0 : goto leave;
1896 : }
1897 0 : if (apdulen)
1898 : {
1899 0 : unsigned char *result = NULL;
1900 : size_t resultlen;
1901 :
1902 0 : rc = apdu_send_direct (slot, exlen,
1903 : apdu, apdulen, handle_more,
1904 : &result, &resultlen);
1905 0 : if (rc)
1906 0 : log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
1907 : else
1908 : {
1909 0 : rc = assuan_send_data (ctx, result, resultlen);
1910 0 : xfree (result);
1911 : }
1912 : }
1913 0 : xfree (apdu);
1914 :
1915 : leave:
1916 0 : TEST_CARD_REMOVAL (ctrl, rc);
1917 0 : return rc;
1918 : }
1919 :
1920 :
1921 : static const char hlp_killscd[] =
1922 : "KILLSCD\n"
1923 : "\n"
1924 : "Commit suicide.";
1925 : static gpg_error_t
1926 0 : cmd_killscd (assuan_context_t ctx, char *line)
1927 : {
1928 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1929 :
1930 : (void)line;
1931 :
1932 0 : ctrl->server_local->stopme = 1;
1933 0 : assuan_set_flag (ctx, ASSUAN_FORCE_CLOSE, 1);
1934 0 : return 0;
1935 : }
1936 :
1937 :
1938 :
1939 : /* Tell the assuan library about our commands */
1940 : static int
1941 0 : register_commands (assuan_context_t ctx)
1942 : {
1943 : static struct {
1944 : const char *name;
1945 : assuan_handler_t handler;
1946 : const char * const help;
1947 : } table[] = {
1948 : { "SERIALNO", cmd_serialno, hlp_serialno },
1949 : { "LEARN", cmd_learn, hlp_learn },
1950 : { "READCERT", cmd_readcert, hlp_readcert },
1951 : { "READKEY", cmd_readkey, hlp_readkey },
1952 : { "SETDATA", cmd_setdata, hlp_setdata },
1953 : { "PKSIGN", cmd_pksign, hlp_pksign },
1954 : { "PKAUTH", cmd_pkauth, hlp_pkauth },
1955 : { "PKDECRYPT", cmd_pkdecrypt,hlp_pkdecrypt },
1956 : { "INPUT", NULL },
1957 : { "OUTPUT", NULL },
1958 : { "GETATTR", cmd_getattr, hlp_getattr },
1959 : { "SETATTR", cmd_setattr, hlp_setattr },
1960 : { "WRITECERT", cmd_writecert,hlp_writecert },
1961 : { "WRITEKEY", cmd_writekey, hlp_writekey },
1962 : { "GENKEY", cmd_genkey, hlp_genkey },
1963 : { "RANDOM", cmd_random, hlp_random },
1964 : { "PASSWD", cmd_passwd, hlp_passwd },
1965 : { "CHECKPIN", cmd_checkpin, hlp_checkpin },
1966 : { "LOCK", cmd_lock, hlp_lock },
1967 : { "UNLOCK", cmd_unlock, hlp_unlock },
1968 : { "GETINFO", cmd_getinfo, hlp_getinfo },
1969 : { "RESTART", cmd_restart, hlp_restart },
1970 : { "DISCONNECT", cmd_disconnect,hlp_disconnect },
1971 : { "APDU", cmd_apdu, hlp_apdu },
1972 : { "KILLSCD", cmd_killscd, hlp_killscd },
1973 : { NULL }
1974 : };
1975 : int i, rc;
1976 :
1977 0 : for (i=0; table[i].name; i++)
1978 : {
1979 0 : rc = assuan_register_command (ctx, table[i].name, table[i].handler,
1980 : table[i].help);
1981 0 : if (rc)
1982 0 : return rc;
1983 : }
1984 0 : assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
1985 :
1986 0 : assuan_register_reset_notify (ctx, reset_notify);
1987 0 : assuan_register_option_handler (ctx, option_handler);
1988 0 : return 0;
1989 : }
1990 :
1991 :
1992 : /* Startup the server. If FD is given as -1 this is simple pipe
1993 : server, otherwise it is a regular server. Returns true if there
1994 : are no more active asessions. */
1995 : int
1996 0 : scd_command_handler (ctrl_t ctrl, int fd)
1997 : {
1998 : int rc;
1999 0 : assuan_context_t ctx = NULL;
2000 : int stopme;
2001 :
2002 0 : rc = assuan_new (&ctx);
2003 0 : if (rc)
2004 : {
2005 0 : log_error ("failed to allocate assuan context: %s\n",
2006 : gpg_strerror (rc));
2007 0 : scd_exit (2);
2008 : }
2009 :
2010 0 : if (fd == -1)
2011 : {
2012 : assuan_fd_t filedes[2];
2013 :
2014 0 : filedes[0] = assuan_fdopen (0);
2015 0 : filedes[1] = assuan_fdopen (1);
2016 0 : rc = assuan_init_pipe_server (ctx, filedes);
2017 : }
2018 : else
2019 : {
2020 0 : rc = assuan_init_socket_server (ctx, INT2FD(fd),
2021 : ASSUAN_SOCKET_SERVER_ACCEPTED);
2022 : }
2023 0 : if (rc)
2024 : {
2025 0 : log_error ("failed to initialize the server: %s\n",
2026 : gpg_strerror(rc));
2027 0 : scd_exit (2);
2028 : }
2029 0 : rc = register_commands (ctx);
2030 0 : if (rc)
2031 : {
2032 0 : log_error ("failed to register commands with Assuan: %s\n",
2033 : gpg_strerror(rc));
2034 0 : scd_exit (2);
2035 : }
2036 0 : assuan_set_pointer (ctx, ctrl);
2037 :
2038 : /* Allocate and initialize the server object. Put it into the list
2039 : of active sessions. */
2040 0 : ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
2041 0 : ctrl->server_local->next_session = session_list;
2042 0 : session_list = ctrl->server_local;
2043 0 : ctrl->server_local->ctrl_backlink = ctrl;
2044 0 : ctrl->server_local->assuan_ctx = ctx;
2045 :
2046 : /* We open the reader right at startup so that the ticker is able to
2047 : update the status file. */
2048 0 : ctrl->server_local->vreader_idx = get_current_reader ();
2049 :
2050 : /* Command processing loop. */
2051 : for (;;)
2052 : {
2053 0 : rc = assuan_accept (ctx);
2054 0 : if (rc == -1)
2055 : {
2056 0 : break;
2057 : }
2058 0 : else if (rc)
2059 : {
2060 0 : log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
2061 0 : break;
2062 : }
2063 :
2064 0 : rc = assuan_process (ctx);
2065 0 : if (rc)
2066 : {
2067 0 : log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
2068 0 : continue;
2069 : }
2070 0 : }
2071 :
2072 : /* Cleanup. We don't send an explicit reset to the card. */
2073 0 : do_reset (ctrl, 0);
2074 :
2075 : /* Release the server object. */
2076 0 : if (session_list == ctrl->server_local)
2077 0 : session_list = ctrl->server_local->next_session;
2078 : else
2079 : {
2080 : struct server_local_s *sl;
2081 :
2082 0 : for (sl=session_list; sl->next_session; sl = sl->next_session)
2083 0 : if (sl->next_session == ctrl->server_local)
2084 0 : break;
2085 0 : if (!sl->next_session)
2086 0 : BUG ();
2087 0 : sl->next_session = ctrl->server_local->next_session;
2088 : }
2089 0 : stopme = ctrl->server_local->stopme;
2090 0 : xfree (ctrl->server_local);
2091 0 : ctrl->server_local = NULL;
2092 :
2093 : /* Release the Assuan context. */
2094 0 : assuan_release (ctx);
2095 :
2096 0 : if (stopme)
2097 0 : scd_exit (0);
2098 :
2099 : /* If there are no more sessions return true. */
2100 0 : return !session_list;
2101 : }
2102 :
2103 :
2104 : /* Send a line with status information via assuan and escape all given
2105 : buffers. The variable elements are pairs of (char *, size_t),
2106 : terminated with a (NULL, 0). */
2107 : void
2108 0 : send_status_info (ctrl_t ctrl, const char *keyword, ...)
2109 : {
2110 : va_list arg_ptr;
2111 : const unsigned char *value;
2112 : size_t valuelen;
2113 : char buf[950], *p;
2114 : size_t n;
2115 0 : assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2116 :
2117 0 : va_start (arg_ptr, keyword);
2118 :
2119 0 : p = buf;
2120 0 : n = 0;
2121 0 : while ( (value = va_arg (arg_ptr, const unsigned char *)) )
2122 : {
2123 0 : valuelen = va_arg (arg_ptr, size_t);
2124 0 : if (!valuelen)
2125 0 : continue; /* empty buffer */
2126 0 : if (n)
2127 : {
2128 0 : *p++ = ' ';
2129 0 : n++;
2130 : }
2131 0 : for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
2132 : {
2133 0 : if (*value < ' ' || *value == '+')
2134 : {
2135 0 : sprintf (p, "%%%02X", *value);
2136 0 : p += 3;
2137 : }
2138 0 : else if (*value == ' ')
2139 0 : *p++ = '+';
2140 : else
2141 0 : *p++ = *value;
2142 : }
2143 : }
2144 0 : *p = 0;
2145 0 : assuan_write_status (ctx, keyword, buf);
2146 :
2147 0 : va_end (arg_ptr);
2148 0 : }
2149 :
2150 :
2151 : /* Send a ready formatted status line via assuan. */
2152 : void
2153 0 : send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
2154 : {
2155 0 : assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2156 :
2157 0 : if (strchr (args, '\n'))
2158 0 : log_error ("error: LF detected in status line - not sending\n");
2159 : else
2160 0 : assuan_write_status (ctx, keyword, args);
2161 0 : }
2162 :
2163 :
2164 : /* Helper to send the clients a status change notification. */
2165 : static void
2166 0 : send_client_notifications (void)
2167 : {
2168 : struct {
2169 : pid_t pid;
2170 : #ifdef HAVE_W32_SYSTEM
2171 : HANDLE handle;
2172 : #else
2173 : int signo;
2174 : #endif
2175 : } killed[50];
2176 0 : int killidx = 0;
2177 : int kidx;
2178 : struct server_local_s *sl;
2179 :
2180 0 : for (sl=session_list; sl; sl = sl->next_session)
2181 : {
2182 0 : if (sl->event_signal && sl->assuan_ctx)
2183 : {
2184 0 : pid_t pid = assuan_get_pid (sl->assuan_ctx);
2185 : #ifdef HAVE_W32_SYSTEM
2186 : HANDLE handle = (void *)sl->event_signal;
2187 :
2188 : for (kidx=0; kidx < killidx; kidx++)
2189 : if (killed[kidx].pid == pid
2190 : && killed[kidx].handle == handle)
2191 : break;
2192 : if (kidx < killidx)
2193 : log_info ("event %lx (%p) already triggered for client %d\n",
2194 : sl->event_signal, handle, (int)pid);
2195 : else
2196 : {
2197 : log_info ("triggering event %lx (%p) for client %d\n",
2198 : sl->event_signal, handle, (int)pid);
2199 : if (!SetEvent (handle))
2200 : log_error ("SetEvent(%lx) failed: %s\n",
2201 : sl->event_signal, w32_strerror (-1));
2202 : if (killidx < DIM (killed))
2203 : {
2204 : killed[killidx].pid = pid;
2205 : killed[killidx].handle = handle;
2206 : killidx++;
2207 : }
2208 : }
2209 : #else /*!HAVE_W32_SYSTEM*/
2210 0 : int signo = sl->event_signal;
2211 :
2212 0 : if (pid != (pid_t)(-1) && pid && signo > 0)
2213 : {
2214 0 : for (kidx=0; kidx < killidx; kidx++)
2215 0 : if (killed[kidx].pid == pid
2216 0 : && killed[kidx].signo == signo)
2217 0 : break;
2218 0 : if (kidx < killidx)
2219 0 : log_info ("signal %d already sent to client %d\n",
2220 : signo, (int)pid);
2221 : else
2222 : {
2223 0 : log_info ("sending signal %d to client %d\n",
2224 : signo, (int)pid);
2225 0 : kill (pid, signo);
2226 0 : if (killidx < DIM (killed))
2227 : {
2228 0 : killed[killidx].pid = pid;
2229 0 : killed[killidx].signo = signo;
2230 0 : killidx++;
2231 : }
2232 : }
2233 : }
2234 : #endif /*!HAVE_W32_SYSTEM*/
2235 : }
2236 : }
2237 0 : }
2238 :
2239 :
2240 :
2241 : /* This is the core of scd_update_reader_status_file but the caller
2242 : needs to take care of the locking. */
2243 : static void
2244 0 : update_reader_status_file (int set_card_removed_flag)
2245 : {
2246 : int idx;
2247 : unsigned int status, changed;
2248 :
2249 : /* Note, that we only try to get the status, because it does not
2250 : make sense to wait here for a operation to complete. If we are
2251 : busy working with a card, delays in the status file update should
2252 : be acceptable. */
2253 0 : for (idx=0; idx < DIM(vreader_table); idx++)
2254 : {
2255 0 : struct vreader_s *vr = vreader_table + idx;
2256 : struct server_local_s *sl;
2257 : int sw_apdu;
2258 :
2259 0 : if (!vr->valid || vr->slot == -1)
2260 0 : continue; /* Not valid or reader not yet open. */
2261 :
2262 0 : sw_apdu = apdu_get_status (vr->slot, 0, &status, &changed);
2263 0 : if (sw_apdu == SW_HOST_NO_READER)
2264 : {
2265 : /* Most likely the _reader_ has been unplugged. */
2266 0 : apdu_close_reader (vr->slot);
2267 0 : status = 0;
2268 0 : changed = vr->changed;
2269 : }
2270 0 : else if (sw_apdu)
2271 : {
2272 : /* Get status failed. Ignore that. */
2273 0 : continue;
2274 : }
2275 :
2276 0 : if (!vr->any || vr->status != status || vr->changed != changed )
2277 : {
2278 : char *fname;
2279 : char templ[50];
2280 : FILE *fp;
2281 :
2282 0 : log_info ("updating reader %d (%d) status: 0x%04X->0x%04X (%u->%u)\n",
2283 : idx, vr->slot, vr->status, status, vr->changed, changed);
2284 0 : vr->status = status;
2285 0 : vr->changed = changed;
2286 :
2287 : /* FIXME: Should this be IDX instead of vr->slot? This
2288 : depends on how client sessions will associate the reader
2289 : status with their session. */
2290 0 : snprintf (templ, sizeof templ, "reader_%d.status", vr->slot);
2291 0 : fname = make_filename (gnupg_homedir (), templ, NULL );
2292 0 : fp = fopen (fname, "w");
2293 0 : if (fp)
2294 : {
2295 0 : fprintf (fp, "%s\n",
2296 0 : (status & 1)? "USABLE":
2297 0 : (status & 4)? "ACTIVE":
2298 0 : (status & 2)? "PRESENT": "NOCARD");
2299 0 : fclose (fp);
2300 : }
2301 0 : xfree (fname);
2302 :
2303 : /* If a status script is executable, run it. */
2304 : {
2305 : const char *args[9], *envs[2];
2306 : char numbuf1[30], numbuf2[30], numbuf3[30];
2307 : char *homestr, *envstr;
2308 : gpg_error_t err;
2309 :
2310 0 : homestr = make_filename (gnupg_homedir (), NULL);
2311 0 : if (gpgrt_asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
2312 0 : log_error ("out of core while building environment\n");
2313 : else
2314 : {
2315 0 : envs[0] = envstr;
2316 0 : envs[1] = NULL;
2317 :
2318 0 : sprintf (numbuf1, "%d", vr->slot);
2319 0 : sprintf (numbuf2, "0x%04X", vr->status);
2320 0 : sprintf (numbuf3, "0x%04X", status);
2321 0 : args[0] = "--reader-port";
2322 0 : args[1] = numbuf1;
2323 0 : args[2] = "--old-code";
2324 0 : args[3] = numbuf2;
2325 0 : args[4] = "--new-code";
2326 0 : args[5] = numbuf3;
2327 0 : args[6] = "--status";
2328 0 : args[7] = ((status & 1)? "USABLE":
2329 0 : (status & 4)? "ACTIVE":
2330 0 : (status & 2)? "PRESENT": "NOCARD");
2331 0 : args[8] = NULL;
2332 :
2333 0 : fname = make_filename (gnupg_homedir (), "scd-event", NULL);
2334 0 : err = gnupg_spawn_process_detached (fname, args, envs);
2335 0 : if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
2336 0 : log_error ("failed to run event handler '%s': %s\n",
2337 : fname, gpg_strerror (err));
2338 0 : xfree (fname);
2339 0 : xfree (envstr);
2340 : }
2341 0 : xfree (homestr);
2342 : }
2343 :
2344 : /* Set the card removed flag for all current sessions. */
2345 0 : if (vr->any && vr->status == 0 && set_card_removed_flag)
2346 0 : update_card_removed (idx, 1);
2347 :
2348 0 : vr->any = 1;
2349 :
2350 : /* Send a signal to all clients who applied for it. */
2351 0 : send_client_notifications ();
2352 : }
2353 :
2354 : /* Check whether a disconnect is pending. */
2355 0 : if (opt.card_timeout)
2356 : {
2357 0 : for (sl=session_list; sl; sl = sl->next_session)
2358 0 : if (!sl->disconnect_allowed)
2359 0 : break;
2360 0 : if (session_list && !sl)
2361 : {
2362 : /* FIXME: Use a real timeout. */
2363 : /* At least one connection and all allow a disconnect. */
2364 0 : log_info ("disconnecting card in reader %d (%d)\n",
2365 : idx, vr->slot);
2366 0 : apdu_disconnect (vr->slot);
2367 : }
2368 : }
2369 :
2370 : }
2371 0 : }
2372 :
2373 : /* This function is called by the ticker thread to check for changes
2374 : of the reader stati. It updates the reader status files and if
2375 : requested by the caller also send a signal to the caller. */
2376 : void
2377 0 : scd_update_reader_status_file (void)
2378 : {
2379 : int err;
2380 0 : err = npth_mutex_lock (&status_file_update_lock);
2381 0 : if (err)
2382 0 : return; /* locked - give up. */
2383 0 : update_reader_status_file (1);
2384 0 : err = npth_mutex_unlock (&status_file_update_lock);
2385 0 : if (err)
2386 0 : log_error ("failed to release status_file_update lock: %s\n",
2387 : strerror (err));
2388 : }
|