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