1 /* command.c - gpg-agent command handler
2 * Copyright (C) 2001-2011 Free Software Foundation, Inc.
3 * Copyright (C) 2001-2013 Werner Koch
4 * Copyright (C) 2015-2021 g10 Code GmbH.
5 *
6 * This file is part of GnuPG.
7 *
8 * GnuPG is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * GnuPG is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <https://www.gnu.org/licenses/>.
20 */
21
22 /* FIXME: we should not use the default assuan buffering but setup
23 some buffering in secure mempory to protect session keys etc. */
24
25 #include <config.h>
26
27 #include <errno.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <dirent.h>
36
37 #include "agent.h"
38 #include <assuan.h>
39 #include "../common/i18n.h"
40 #include "cvt-openpgp.h"
41 #include "../common/ssh-utils.h"
42 #include "../common/asshelp.h"
43 #include "../common/server-help.h"
44
45
46 /* Maximum allowed size of the inquired ciphertext. */
47 #define MAXLEN_CIPHERTEXT 4096
48 /* Maximum allowed size of the key parameters. */
49 #define MAXLEN_KEYPARAM 1024
50 /* Maximum allowed size of key data as used in inquiries (bytes). */
51 #define MAXLEN_KEYDATA 8192
52 /* Maximum length of a secret to store under one key. */
53 #define MAXLEN_PUT_SECRET 4096
54 /* The size of the import/export KEK key (in bytes). */
55 #define KEYWRAP_KEYSIZE (128/8)
56
57 /* A shortcut to call assuan_set_error using an gpg_err_code_t and a
58 text string. */
59 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
60
61 /* Check that the maximum digest length we support has at least the
62 length of the keygrip. */
63 #if MAX_DIGEST_LEN < 20
64 #error MAX_DIGEST_LEN shorter than keygrip
65 #endif
66
67 /* Data used to associate an Assuan context with local server data.
68 This is this modules local part of the server_control_s struct. */
69 struct server_local_s
70 {
71 /* Our Assuan context. */
72 assuan_context_t assuan_ctx;
73
74 /* If this flag is true, the passphrase cache is used for signing
75 operations. It defaults to true but may be set on a per
76 connection base. The global option opt.ignore_cache_for_signing
77 takes precedence over this flag. */
78 unsigned int use_cache_for_signing : 1;
79
80 /* Flag to suppress I/O logging during a command. */
81 unsigned int pause_io_logging : 1;
82
83 /* Flag indicating that the connection is from ourselves. */
84 unsigned int connect_from_self : 1;
85
86 /* Helper flag for io_monitor to allow suppressing of our own
87 * greeting in some cases. See io_monitor for details. */
88 unsigned int greeting_seen : 1;
89
90 /* If this flag is set to true the agent will be terminated after
91 the end of the current session. */
92 unsigned int stopme : 1;
93
94 /* Flag indicating whether pinentry notifications shall be done. */
95 unsigned int allow_pinentry_notify : 1;
96
97 /* An allocated description for the next key operation. This is
98 used if a pinnetry needs to be popped up. */
99 char *keydesc;
100
101 /* Malloced KEK (Key-Encryption-Key) for the import_key command. */
102 void *import_key;
103
104 /* Malloced KEK for the export_key command. */
105 void *export_key;
106
107 /* Client is aware of the error code GPG_ERR_FULLY_CANCELED. */
108 int allow_fully_canceled;
109
110 /* Last CACHE_NONCE sent as status (malloced). */
111 char *last_cache_nonce;
112
113 /* Last PASSWD_NONCE sent as status (malloced). */
114 char *last_passwd_nonce;
115
116 /* Per connection cache of the keyinfo from the cards. The
117 * eventcounters for cards at the time the info was fetched is
118 * stored here as a freshness indicator. */
119 struct {
120 struct card_key_info_s *ki;
121 unsigned int eventno;
122 unsigned int maybe_key_change;
123 } last_card_keyinfo;
124
125 };
126
127
128 /* An entry for the getval/putval commands. */
129 struct putval_item_s
130 {
131 struct putval_item_s *next;
132 size_t off; /* Offset to the value into DATA. */
133 size_t len; /* Length of the value. */
134 char d[1]; /* Key | Nul | value. */
135 };
136
137
138 /* A list of key value pairs fpr the getval/putval commands. */
139 static struct putval_item_s *putval_list;
140
141
142
143 /* To help polling clients, we keep track of the number of certain
144 events. This structure keeps those counters. The counters are
145 integers and there should be no problem if they are overflowing as
146 callers need to check only whether a counter changed. The actual
147 values are not meaningful. */
148 struct
149 {
150 /* Incremented if any of the other counters below changed. */
151 unsigned int any;
152
153 /* Incremented if a key is added or removed from the internal privat
154 key database. */
155 unsigned int key;
156
157 /* Incremented if a change of the card readers stati has been
158 detected. */
159 unsigned int card;
160
161 /* Internal counter to track possible changes to a key.
162 * FIXME: This should be replaced by generic notifications from scd.
163 */
164 unsigned int maybe_key_change;
165
166 } eventcounter;
167
168
169
170 /* Local prototypes. */
171 static int command_has_option (const char *cmd, const char *cmdopt);
172
173
174
175
176 /* Release the memory buffer MB but first wipe out the used memory. */
177 static void
clear_outbuf(membuf_t * mb)178 clear_outbuf (membuf_t *mb)
179 {
180 void *p;
181 size_t n;
182
183 p = get_membuf (mb, &n);
184 if (p)
185 {
186 wipememory (p, n);
187 xfree (p);
188 }
189 }
190
191
192 /* Write the content of memory buffer MB as assuan data to CTX and
193 wipe the buffer out afterwards. */
194 static gpg_error_t
write_and_clear_outbuf(assuan_context_t ctx,membuf_t * mb)195 write_and_clear_outbuf (assuan_context_t ctx, membuf_t *mb)
196 {
197 gpg_error_t ae;
198 void *p;
199 size_t n;
200
201 p = get_membuf (mb, &n);
202 if (!p)
203 return out_of_core ();
204 ae = assuan_send_data (ctx, p, n);
205 memset (p, 0, n);
206 xfree (p);
207 return ae;
208 }
209
210
211 /* Clear the nonces used to enable the passphrase cache for certain
212 multi-command command sequences. */
213 static void
clear_nonce_cache(ctrl_t ctrl)214 clear_nonce_cache (ctrl_t ctrl)
215 {
216 if (ctrl->server_local->last_cache_nonce)
217 {
218 agent_put_cache (ctrl, ctrl->server_local->last_cache_nonce,
219 CACHE_MODE_NONCE, NULL, 0);
220 xfree (ctrl->server_local->last_cache_nonce);
221 ctrl->server_local->last_cache_nonce = NULL;
222 }
223 if (ctrl->server_local->last_passwd_nonce)
224 {
225 agent_put_cache (ctrl, ctrl->server_local->last_passwd_nonce,
226 CACHE_MODE_NONCE, NULL, 0);
227 xfree (ctrl->server_local->last_passwd_nonce);
228 ctrl->server_local->last_passwd_nonce = NULL;
229 }
230 }
231
232
233 /* This function is called by Libassuan whenever the client sends a
234 reset. It has been registered similar to the other Assuan
235 commands. */
236 static gpg_error_t
reset_notify(assuan_context_t ctx,char * line)237 reset_notify (assuan_context_t ctx, char *line)
238 {
239 ctrl_t ctrl = assuan_get_pointer (ctx);
240
241 (void) line;
242
243 memset (ctrl->keygrip, 0, 20);
244 ctrl->have_keygrip = 0;
245 ctrl->digest.valuelen = 0;
246 xfree (ctrl->digest.data);
247 ctrl->digest.data = NULL;
248
249 xfree (ctrl->server_local->keydesc);
250 ctrl->server_local->keydesc = NULL;
251
252 clear_nonce_cache (ctrl);
253
254 return 0;
255 }
256
257
258 /* Replace all '+' by a blank in the string S. */
259 static void
plus_to_blank(char * s)260 plus_to_blank (char *s)
261 {
262 for (; *s; s++)
263 {
264 if (*s == '+')
265 *s = ' ';
266 }
267 }
268
269
270 /* Parse a hex string. Return an Assuan error code or 0 on success and the
271 length of the parsed string in LEN. */
272 static int
parse_hexstring(assuan_context_t ctx,const char * string,size_t * len)273 parse_hexstring (assuan_context_t ctx, const char *string, size_t *len)
274 {
275 const char *p;
276 size_t n;
277
278 /* parse the hash value */
279 for (p=string, n=0; hexdigitp (p); p++, n++)
280 ;
281 if (*p != ' ' && *p != '\t' && *p)
282 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
283 if ((n&1))
284 return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
285 *len = n;
286 return 0;
287 }
288
289
290 /* Parse the keygrip in STRING into the provided buffer BUF. BUF must
291 provide space for 20 bytes. BUF is not changed if the function
292 returns an error. */
293 static int
parse_keygrip(assuan_context_t ctx,const char * string,unsigned char * buf)294 parse_keygrip (assuan_context_t ctx, const char *string, unsigned char *buf)
295 {
296 int rc;
297 size_t n = 0;
298
299 rc = parse_hexstring (ctx, string, &n);
300 if (rc)
301 return rc;
302 n /= 2;
303 if (n != 20)
304 return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of keygrip");
305
306 if (hex2bin (string, buf, 20) < 0)
307 return set_error (GPG_ERR_BUG, "hex2bin");
308
309 return 0;
310 }
311
312
313 /* Parse the TTL from STRING. Leading and trailing spaces are
314 * skipped. The value is constrained to -1 .. MAXINT. On error 0 is
315 * returned, else the number of bytes scanned. */
316 static size_t
parse_ttl(const char * string,int * r_ttl)317 parse_ttl (const char *string, int *r_ttl)
318 {
319 const char *string_orig = string;
320 long ttl;
321 char *pend;
322
323 ttl = strtol (string, &pend, 10);
324 string = pend;
325 if (string == string_orig || !(spacep (string) || !*string)
326 || ttl < -1L || (int)ttl != (long)ttl)
327 {
328 *r_ttl = 0;
329 return 0;
330 }
331 while (spacep (string) || *string== '\n')
332 string++;
333 *r_ttl = (int)ttl;
334 return string - string_orig;
335 }
336
337
338 /* Write an Assuan status line. KEYWORD is the first item on the
339 * status line. The following arguments are all separated by a space
340 * in the output. The last argument must be a NULL. Linefeeds and
341 * carriage returns characters (which are not allowed in an Assuan
342 * status line) are silently quoted in C-style. */
343 gpg_error_t
agent_write_status(ctrl_t ctrl,const char * keyword,...)344 agent_write_status (ctrl_t ctrl, const char *keyword, ...)
345 {
346 gpg_error_t err;
347 va_list arg_ptr;
348 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
349
350 va_start (arg_ptr, keyword);
351 err = vprint_assuan_status_strings (ctx, keyword, arg_ptr);
352 va_end (arg_ptr);
353 return err;
354 }
355
356
357 /* This function is similar to print_assuan_status but takes a CTRL
358 arg instead of an assuan context as first argument. */
359 gpg_error_t
agent_print_status(ctrl_t ctrl,const char * keyword,const char * format,...)360 agent_print_status (ctrl_t ctrl, const char *keyword, const char *format, ...)
361 {
362 gpg_error_t err;
363 va_list arg_ptr;
364 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
365
366 va_start (arg_ptr, format);
367 err = vprint_assuan_status (ctx, keyword, format, arg_ptr);
368 va_end (arg_ptr);
369 return err;
370 }
371
372
373 /* Helper to notify the client about a launched Pinentry. Because
374 that might disturb some older clients, this is only done if enabled
375 via an option. Returns an gpg error code. */
376 gpg_error_t
agent_inq_pinentry_launched(ctrl_t ctrl,unsigned long pid,const char * extra)377 agent_inq_pinentry_launched (ctrl_t ctrl, unsigned long pid, const char *extra)
378 {
379 char line[256];
380
381 if (!ctrl || !ctrl->server_local
382 || !ctrl->server_local->allow_pinentry_notify)
383 return 0;
384 snprintf (line, DIM(line), "PINENTRY_LAUNCHED %lu%s%s",
385 pid, extra?" ":"", extra? extra:"");
386 return assuan_inquire (ctrl->server_local->assuan_ctx, line, NULL, NULL, 0);
387 }
388
389
390 /* An agent progress callback for Libgcrypt. This has been registered
391 * to be called via the progress dispatcher mechanism from
392 * gpg-agent.c */
393 static void
progress_cb(ctrl_t ctrl,const char * what,int printchar,int current,int total)394 progress_cb (ctrl_t ctrl, const char *what, int printchar,
395 int current, int total)
396 {
397 if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
398 ;
399 else if (printchar == '\n' && what && !strcmp (what, "primegen"))
400 agent_print_status (ctrl, "PROGRESS", "%.20s X 100 100", what);
401 else
402 agent_print_status (ctrl, "PROGRESS", "%.20s %c %d %d",
403 what, printchar=='\n'?'X':printchar, current, total);
404 }
405
406
407 /* Helper to print a message while leaving a command. Note that this
408 * function does not call assuan_set_error; the caller may do this
409 * prior to calling us. */
410 static gpg_error_t
leave_cmd(assuan_context_t ctx,gpg_error_t err)411 leave_cmd (assuan_context_t ctx, gpg_error_t err)
412 {
413 if (err)
414 {
415 const char *name = assuan_get_command_name (ctx);
416 if (!name)
417 name = "?";
418
419 /* Not all users of gpg-agent know about the fully canceled
420 error code; map it back if needed. */
421 if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
422 {
423 ctrl_t ctrl = assuan_get_pointer (ctx);
424
425 if (!ctrl->server_local->allow_fully_canceled)
426 err = gpg_err_make (gpg_err_source (err), GPG_ERR_CANCELED);
427 }
428
429 /* Most code from common/ does not know the error source, thus
430 we fix this here. */
431 if (gpg_err_source (err) == GPG_ERR_SOURCE_UNKNOWN)
432 err = gpg_err_make (GPG_ERR_SOURCE_DEFAULT, gpg_err_code (err));
433
434 if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
435 log_error ("command '%s' failed: %s\n", name,
436 gpg_strerror (err));
437 else
438 log_error ("command '%s' failed: %s <%s>\n", name,
439 gpg_strerror (err), gpg_strsource (err));
440 }
441 return err;
442 }
443
444
445 /* Take the keyinfo for cards from our local cache. Actually this
446 * cache could be a global one but then we would need to employ
447 * reference counting. */
448 struct card_key_info_s *
get_keyinfo_on_cards(ctrl_t ctrl)449 get_keyinfo_on_cards (ctrl_t ctrl)
450 {
451 struct card_key_info_s *keyinfo_on_cards;
452
453 if (ctrl->server_local->last_card_keyinfo.ki
454 && ctrl->server_local->last_card_keyinfo.eventno == eventcounter.card
455 && (ctrl->server_local->last_card_keyinfo.maybe_key_change
456 == eventcounter.maybe_key_change))
457 {
458 keyinfo_on_cards = ctrl->server_local->last_card_keyinfo.ki;
459 }
460 else if (!agent_card_keyinfo (ctrl, NULL, 0, &keyinfo_on_cards))
461 {
462 agent_card_free_keyinfo (ctrl->server_local->last_card_keyinfo.ki);
463 ctrl->server_local->last_card_keyinfo.ki = keyinfo_on_cards;
464 ctrl->server_local->last_card_keyinfo.eventno = eventcounter.card;
465 ctrl->server_local->last_card_keyinfo.maybe_key_change
466 = eventcounter.maybe_key_change;
467 }
468
469 return keyinfo_on_cards;
470 }
471
472
473
474 static const char hlp_geteventcounter[] =
475 "GETEVENTCOUNTER\n"
476 "\n"
477 "Return a status line named EVENTCOUNTER with the current values\n"
478 "of all event counters. The values are decimal numbers in the range\n"
479 "0 to UINT_MAX and wrapping around to 0. The actual values should\n"
480 "not be relied upon, they shall only be used to detect a change.\n"
481 "\n"
482 "The currently defined counters are:\n"
483 "\n"
484 "ANY - Incremented with any change of any of the other counters.\n"
485 "KEY - Incremented for added or removed private keys.\n"
486 "CARD - Incremented for changes of the card readers stati.";
487 static gpg_error_t
cmd_geteventcounter(assuan_context_t ctx,char * line)488 cmd_geteventcounter (assuan_context_t ctx, char *line)
489 {
490 ctrl_t ctrl = assuan_get_pointer (ctx);
491
492 (void)line;
493
494 if (ctrl->restricted)
495 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
496
497 return agent_print_status (ctrl, "EVENTCOUNTER", "%u %u %u",
498 eventcounter.any,
499 eventcounter.key,
500 eventcounter.card);
501 }
502
503
504 /* This function should be called once for all key removals or
505 additions. This function is assured not to do any context
506 switches. */
507 void
bump_key_eventcounter(void)508 bump_key_eventcounter (void)
509 {
510 eventcounter.key++;
511 eventcounter.any++;
512 }
513
514
515 /* This function should be called for all card reader status
516 changes. This function is assured not to do any context
517 switches. */
518 void
bump_card_eventcounter(void)519 bump_card_eventcounter (void)
520 {
521 eventcounter.card++;
522 eventcounter.any++;
523 }
524
525
526
527
528 static const char hlp_istrusted[] =
529 "ISTRUSTED <hexstring_with_fingerprint>\n"
530 "\n"
531 "Return OK when we have an entry with this fingerprint in our\n"
532 "trustlist";
533 static gpg_error_t
cmd_istrusted(assuan_context_t ctx,char * line)534 cmd_istrusted (assuan_context_t ctx, char *line)
535 {
536 ctrl_t ctrl = assuan_get_pointer (ctx);
537 int rc, n, i;
538 char *p;
539 char fpr[41];
540
541 /* Parse the fingerprint value. */
542 for (p=line,n=0; hexdigitp (p); p++, n++)
543 ;
544 if (*p || !(n == 40 || n == 32))
545 return set_error (GPG_ERR_ASS_PARAMETER, "invalid fingerprint");
546 i = 0;
547 if (n==32)
548 {
549 strcpy (fpr, "00000000");
550 i += 8;
551 }
552 for (p=line; i < 40; p++, i++)
553 fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
554 fpr[i] = 0;
555 rc = agent_istrusted (ctrl, fpr, NULL);
556 if (!rc || gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
557 return rc;
558 else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF )
559 return gpg_error (GPG_ERR_NOT_TRUSTED);
560 else
561 return leave_cmd (ctx, rc);
562 }
563
564
565 static const char hlp_listtrusted[] =
566 "LISTTRUSTED\n"
567 "\n"
568 "List all entries from the trustlist.";
569 static gpg_error_t
cmd_listtrusted(assuan_context_t ctx,char * line)570 cmd_listtrusted (assuan_context_t ctx, char *line)
571 {
572 ctrl_t ctrl = assuan_get_pointer (ctx);
573 int rc;
574
575 (void)line;
576
577 if (ctrl->restricted)
578 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
579
580 rc = agent_listtrusted (ctx);
581 return leave_cmd (ctx, rc);
582 }
583
584
585 static const char hlp_martrusted[] =
586 "MARKTRUSTED <hexstring_with_fingerprint> <flag> <display_name>\n"
587 "\n"
588 "Store a new key in into the trustlist.";
589 static gpg_error_t
cmd_marktrusted(assuan_context_t ctx,char * line)590 cmd_marktrusted (assuan_context_t ctx, char *line)
591 {
592 ctrl_t ctrl = assuan_get_pointer (ctx);
593 int rc, n, i;
594 char *p;
595 char fpr[41];
596 int flag;
597
598 if (ctrl->restricted)
599 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
600
601 /* parse the fingerprint value */
602 for (p=line,n=0; hexdigitp (p); p++, n++)
603 ;
604 if (!spacep (p) || !(n == 40 || n == 32))
605 return set_error (GPG_ERR_ASS_PARAMETER, "invalid fingerprint");
606 i = 0;
607 if (n==32)
608 {
609 strcpy (fpr, "00000000");
610 i += 8;
611 }
612 for (p=line; i < 40; p++, i++)
613 fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
614 fpr[i] = 0;
615
616 while (spacep (p))
617 p++;
618 flag = *p++;
619 if ( (flag != 'S' && flag != 'P') || !spacep (p) )
620 return set_error (GPG_ERR_ASS_PARAMETER, "invalid flag - must be P or S");
621 while (spacep (p))
622 p++;
623
624 rc = agent_marktrusted (ctrl, p, fpr, flag);
625 return leave_cmd (ctx, rc);
626 }
627
628
629
630
631 static const char hlp_havekey[] =
632 "HAVEKEY <hexstrings_with_keygrips>\n"
633 "HAVEKEY --list[=<limit>]\n"
634 "\n"
635 "Return success if at least one of the secret keys with the given\n"
636 "keygrips is available. With --list return all availabale keygrips\n"
637 "as binary data; with <limit> bail out at this number of keygrips";
638 static gpg_error_t
cmd_havekey(assuan_context_t ctx,char * line)639 cmd_havekey (assuan_context_t ctx, char *line)
640 {
641 ctrl_t ctrl;
642 gpg_error_t err;
643 unsigned char grip[20];
644 char *p;
645 int list_mode; /* Less than 0 for no limit. */
646 int counter;
647 char *dirname;
648 gnupg_dir_t dir;
649 gnupg_dirent_t dir_entry;
650 char hexgrip[41];
651 struct card_key_info_s *keyinfo_on_cards, *l;
652
653 if (has_option_name (line, "--list"))
654 {
655 if ((p = option_value (line, "--list")))
656 list_mode = atoi (p);
657 else
658 list_mode = -1;
659 }
660 else
661 list_mode = 0;
662
663
664 if (!list_mode)
665 {
666 do
667 {
668 err = parse_keygrip (ctx, line, grip);
669 if (err)
670 return err;
671
672 if (!agent_key_available (grip))
673 return 0; /* Found. */
674
675 while (*line && *line != ' ' && *line != '\t')
676 line++;
677 while (*line == ' ' || *line == '\t')
678 line++;
679 }
680 while (*line);
681
682 /* No leave_cmd() here because errors are expected and would clutter
683 * the log. */
684 return gpg_error (GPG_ERR_NO_SECKEY);
685 }
686
687 /* List mode. */
688 dir = NULL;
689 dirname = NULL;
690 ctrl = assuan_get_pointer (ctx);
691
692 if (ctrl->restricted)
693 {
694 err = gpg_error (GPG_ERR_FORBIDDEN);
695 goto leave;
696 }
697
698 dirname = make_filename_try (gnupg_homedir (),
699 GNUPG_PRIVATE_KEYS_DIR, NULL);
700 if (!dirname)
701 {
702 err = gpg_error_from_syserror ();
703 goto leave;
704 }
705 dir = gnupg_opendir (dirname);
706 if (!dir)
707 {
708 err = gpg_error_from_syserror ();
709 goto leave;
710 }
711
712 counter = 0;
713 while ((dir_entry = gnupg_readdir (dir)))
714 {
715 if (strlen (dir_entry->d_name) != 44
716 || strcmp (dir_entry->d_name + 40, ".key"))
717 continue;
718 strncpy (hexgrip, dir_entry->d_name, 40);
719 hexgrip[40] = 0;
720
721 if ( hex2bin (hexgrip, grip, 20) < 0 )
722 continue; /* Bad hex string. */
723
724 if (list_mode > 0 && ++counter > list_mode)
725 {
726 err = gpg_error (GPG_ERR_TRUNCATED);
727 goto leave;
728 }
729
730 err = assuan_send_data (ctx, grip, 20);
731 if (err)
732 goto leave;
733 }
734
735 /* And now the keys from the current cards. If they already got a
736 * stub, they are listed twice but we don't care. */
737 keyinfo_on_cards = get_keyinfo_on_cards (ctrl);
738 for (l = keyinfo_on_cards; l; l = l->next)
739 {
740 if ( hex2bin (l->keygrip, grip, 20) < 0 )
741 continue; /* Bad hex string. */
742
743 if (list_mode > 0 && ++counter > list_mode)
744 {
745 err = gpg_error (GPG_ERR_TRUNCATED);
746 goto leave;
747 }
748
749 err = assuan_send_data (ctx, grip, 20);
750 if (err)
751 goto leave;
752 }
753 err = 0;
754
755 leave:
756 gnupg_closedir (dir);
757 xfree (dirname);
758 return leave_cmd (ctx, err);
759 }
760
761
762 static const char hlp_sigkey[] =
763 "SIGKEY <hexstring_with_keygrip>\n"
764 "SETKEY <hexstring_with_keygrip>\n"
765 "\n"
766 "Set the key used for a sign or decrypt operation.";
767 static gpg_error_t
cmd_sigkey(assuan_context_t ctx,char * line)768 cmd_sigkey (assuan_context_t ctx, char *line)
769 {
770 int rc;
771 ctrl_t ctrl = assuan_get_pointer (ctx);
772
773 rc = parse_keygrip (ctx, line, ctrl->keygrip);
774 if (rc)
775 return rc;
776 ctrl->have_keygrip = 1;
777 return 0;
778 }
779
780
781 static const char hlp_setkeydesc[] =
782 "SETKEYDESC plus_percent_escaped_string\n"
783 "\n"
784 "Set a description to be used for the next PKSIGN, PKDECRYPT, IMPORT_KEY\n"
785 "or EXPORT_KEY operation if this operation requires a passphrase. If\n"
786 "this command is not used a default text will be used. Note, that\n"
787 "this description implicitly selects the label used for the entry\n"
788 "box; if the string contains the string PIN (which in general will\n"
789 "not be translated), \"PIN\" is used, otherwise the translation of\n"
790 "\"passphrase\" is used. The description string should not contain\n"
791 "blanks unless they are percent or '+' escaped.\n"
792 "\n"
793 "The description is only valid for the next PKSIGN, PKDECRYPT,\n"
794 "IMPORT_KEY, EXPORT_KEY, or DELETE_KEY operation.";
795 static gpg_error_t
cmd_setkeydesc(assuan_context_t ctx,char * line)796 cmd_setkeydesc (assuan_context_t ctx, char *line)
797 {
798 ctrl_t ctrl = assuan_get_pointer (ctx);
799 char *desc, *p;
800
801 for (p=line; *p == ' '; p++)
802 ;
803 desc = p;
804 p = strchr (desc, ' ');
805 if (p)
806 *p = 0; /* We ignore any garbage; we might late use it for other args. */
807
808 if (!*desc)
809 return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
810
811 /* Note, that we only need to replace the + characters and should
812 leave the other escaping in place because the escaped string is
813 send verbatim to the pinentry which does the unescaping (but not
814 the + replacing) */
815 plus_to_blank (desc);
816
817 xfree (ctrl->server_local->keydesc);
818
819 if (ctrl->restricted)
820 {
821 ctrl->server_local->keydesc = strconcat
822 ((ctrl->restricted == 2
823 ? _("Note: Request from the web browser.")
824 : _("Note: Request from a remote site.") ), "%0A%0A", desc, NULL);
825 }
826 else
827 ctrl->server_local->keydesc = xtrystrdup (desc);
828 if (!ctrl->server_local->keydesc)
829 return out_of_core ();
830 return 0;
831 }
832
833
834 static const char hlp_sethash[] =
835 "SETHASH (--hash=<name>)|(<algonumber>) <hexstring>]\n"
836 "SETHASH [--pss] --inquire\n"
837 "\n"
838 "The client can use this command to tell the server about the data\n"
839 "(which usually is a hash) to be signed. The option --inquire is\n"
840 "used to ask back for to-be-signed data in case of PureEdDSA or\n"
841 "with --pss for pre-formatted rsaPSS.";
842 static gpg_error_t
cmd_sethash(assuan_context_t ctx,char * line)843 cmd_sethash (assuan_context_t ctx, char *line)
844 {
845 gpg_error_t err;
846 size_t n;
847 char *p;
848 ctrl_t ctrl = assuan_get_pointer (ctx);
849 unsigned char *buf;
850 char *endp;
851 int algo;
852 int opt_inquire, opt_pss;
853
854 /* Parse the alternative hash options which may be used instead of
855 the algo number. */
856 if (has_option_name (line, "--hash"))
857 {
858 if (has_option (line, "--hash=sha1"))
859 algo = GCRY_MD_SHA1;
860 else if (has_option (line, "--hash=sha224"))
861 algo = GCRY_MD_SHA224;
862 else if (has_option (line, "--hash=sha256"))
863 algo = GCRY_MD_SHA256;
864 else if (has_option (line, "--hash=sha384"))
865 algo = GCRY_MD_SHA384;
866 else if (has_option (line, "--hash=sha512"))
867 algo = GCRY_MD_SHA512;
868 else if (has_option (line, "--hash=rmd160"))
869 algo = GCRY_MD_RMD160;
870 else if (has_option (line, "--hash=md5"))
871 algo = GCRY_MD_MD5;
872 else if (has_option (line, "--hash=tls-md5sha1"))
873 algo = MD_USER_TLS_MD5SHA1;
874 else if (has_option (line, "--hash=none"))
875 algo = 0;
876 else
877 {
878 err = set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
879 goto leave;
880 }
881 }
882 else
883 algo = 0;
884
885 opt_pss = has_option (line, "--pss");
886 opt_inquire = has_option (line, "--inquire");
887 line = skip_options (line);
888
889 if (!algo && !opt_inquire)
890 {
891 /* No hash option has been given: require an algo number instead */
892 algo = (int)strtoul (line, &endp, 10);
893 for (line = endp; *line == ' ' || *line == '\t'; line++)
894 ;
895 if (!algo || gcry_md_test_algo (algo))
896 {
897 err = set_error (GPG_ERR_UNSUPPORTED_ALGORITHM, NULL);
898 goto leave;
899 }
900 }
901 xfree (ctrl->digest.data);
902 ctrl->digest.data = NULL;
903 ctrl->digest.algo = algo;
904 ctrl->digest.raw_value = 0;
905 ctrl->digest.is_pss = opt_pss;
906
907 if (opt_inquire)
908 {
909 /* We limit the to-be-signed data to some reasonable size which
910 * may eventually allow us to pass that even to smartcards. */
911 size_t maxlen = 2048;
912
913 if (algo)
914 {
915 err = set_error (GPG_ERR_ASS_PARAMETER,
916 "both --inquire and an algo are specified");
917 goto leave;
918 }
919
920 err = print_assuan_status (ctx, "INQUIRE_MAXLEN", "%zu", maxlen);
921 if (!err)
922 err = assuan_inquire (ctx, "TBSDATA", &buf, &n, maxlen);
923 if (err)
924 goto leave;
925
926 ctrl->digest.data = buf;
927 ctrl->digest.valuelen = n;
928 }
929 else
930 {
931 /* Parse the hash value. */
932 n = 0;
933 err = parse_hexstring (ctx, line, &n);
934 if (err)
935 goto leave;
936 n /= 2;
937 if (algo == MD_USER_TLS_MD5SHA1 && n == 36)
938 ;
939 else if (n != 16 && n != 20 && n != 24
940 && n != 28 && n != 32 && n != 48 && n != 64)
941 {
942 err = set_error (GPG_ERR_ASS_PARAMETER, "unsupported length of hash");
943 goto leave;
944 }
945
946 if (n > MAX_DIGEST_LEN)
947 {
948 err = set_error (GPG_ERR_ASS_PARAMETER, "hash value to long");
949 goto leave;
950 }
951
952 buf = ctrl->digest.value;
953 ctrl->digest.valuelen = n;
954 for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
955 buf[n] = xtoi_2 (p);
956 for (; n < ctrl->digest.valuelen; n++)
957 buf[n] = 0;
958 }
959
960 leave:
961 return leave_cmd (ctx, err);
962 }
963
964
965 static const char hlp_pksign[] =
966 "PKSIGN [<options>] [<cache_nonce>]\n"
967 "\n"
968 "Perform the actual sign operation. Neither input nor output are\n"
969 "sensitive to eavesdropping.";
970 static gpg_error_t
cmd_pksign(assuan_context_t ctx,char * line)971 cmd_pksign (assuan_context_t ctx, char *line)
972 {
973 gpg_error_t err;
974 cache_mode_t cache_mode = CACHE_MODE_NORMAL;
975 ctrl_t ctrl = assuan_get_pointer (ctx);
976 membuf_t outbuf;
977 char *cache_nonce = NULL;
978 char *p;
979
980 line = skip_options (line);
981
982 for (p=line; *p && *p != ' ' && *p != '\t'; p++)
983 ;
984 *p = '\0';
985 if (*line)
986 cache_nonce = xtrystrdup (line);
987
988 if (opt.ignore_cache_for_signing)
989 cache_mode = CACHE_MODE_IGNORE;
990 else if (!ctrl->server_local->use_cache_for_signing)
991 cache_mode = CACHE_MODE_IGNORE;
992
993 init_membuf (&outbuf, 512);
994
995 err = agent_pksign (ctrl, cache_nonce, ctrl->server_local->keydesc,
996 &outbuf, cache_mode);
997 if (err)
998 clear_outbuf (&outbuf);
999 else
1000 err = write_and_clear_outbuf (ctx, &outbuf);
1001
1002 xfree (cache_nonce);
1003 xfree (ctrl->server_local->keydesc);
1004 ctrl->server_local->keydesc = NULL;
1005 return leave_cmd (ctx, err);
1006 }
1007
1008
1009 static const char hlp_pkdecrypt[] =
1010 "PKDECRYPT [<options>]\n"
1011 "\n"
1012 "Perform the actual decrypt operation. Input is not\n"
1013 "sensitive to eavesdropping.";
1014 static gpg_error_t
cmd_pkdecrypt(assuan_context_t ctx,char * line)1015 cmd_pkdecrypt (assuan_context_t ctx, char *line)
1016 {
1017 int rc;
1018 ctrl_t ctrl = assuan_get_pointer (ctx);
1019 unsigned char *value;
1020 size_t valuelen;
1021 membuf_t outbuf;
1022 int padding;
1023
1024 (void)line;
1025
1026 /* First inquire the data to decrypt */
1027 rc = print_assuan_status (ctx, "INQUIRE_MAXLEN", "%u", MAXLEN_CIPHERTEXT);
1028 if (!rc)
1029 rc = assuan_inquire (ctx, "CIPHERTEXT",
1030 &value, &valuelen, MAXLEN_CIPHERTEXT);
1031 if (rc)
1032 return rc;
1033
1034 init_membuf (&outbuf, 512);
1035
1036 rc = agent_pkdecrypt (ctrl, ctrl->server_local->keydesc,
1037 value, valuelen, &outbuf, &padding);
1038 xfree (value);
1039 if (rc)
1040 clear_outbuf (&outbuf);
1041 else
1042 {
1043 if (padding != -1)
1044 rc = print_assuan_status (ctx, "PADDING", "%d", padding);
1045 else
1046 rc = 0;
1047 if (!rc)
1048 rc = write_and_clear_outbuf (ctx, &outbuf);
1049 }
1050 xfree (ctrl->server_local->keydesc);
1051 ctrl->server_local->keydesc = NULL;
1052 return leave_cmd (ctx, rc);
1053 }
1054
1055
1056 static const char hlp_genkey[] =
1057 "GENKEY [--no-protection] [--preset] [--timestamp=<isodate>]\n"
1058 " [--inq-passwd] [--passwd-nonce=<s>] [<cache_nonce>]\n"
1059 "\n"
1060 "Generate a new key, store the secret part and return the public\n"
1061 "part. Here is an example transaction:\n"
1062 "\n"
1063 " C: GENKEY\n"
1064 " S: INQUIRE KEYPARAM\n"
1065 " C: D (genkey (rsa (nbits 3072)))\n"
1066 " C: END\n"
1067 " S: D (public-key\n"
1068 " S: D (rsa (n 326487324683264) (e 10001)))\n"
1069 " S: OK key created\n"
1070 "\n"
1071 "If the --preset option is used the passphrase for the generated\n"
1072 "key will be added to the cache. If --inq-passwd is used an inquire\n"
1073 "with the keyword NEWPASSWD is used to request the passphrase for the\n"
1074 "new key. If a --passwd-nonce is used, the corresponding cached\n"
1075 "passphrase is used to protect the new key. If --timestamp is given\n"
1076 "its value is recorded as the key's creation time; the value is\n"
1077 "expected in ISO format (e.g. \"20030316T120000\").";
1078 static gpg_error_t
cmd_genkey(assuan_context_t ctx,char * line)1079 cmd_genkey (assuan_context_t ctx, char *line)
1080 {
1081 ctrl_t ctrl = assuan_get_pointer (ctx);
1082 int rc;
1083 int no_protection;
1084 unsigned char *value = NULL;
1085 size_t valuelen;
1086 unsigned char *newpasswd = NULL;
1087 membuf_t outbuf;
1088 char *cache_nonce = NULL;
1089 char *passwd_nonce = NULL;
1090 int opt_preset;
1091 int opt_inq_passwd;
1092 size_t n;
1093 char *p, *pend;
1094 const char *s;
1095 time_t opt_timestamp;
1096 int c;
1097
1098 if (ctrl->restricted)
1099 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
1100
1101 no_protection = has_option (line, "--no-protection");
1102 opt_preset = has_option (line, "--preset");
1103 opt_inq_passwd = has_option (line, "--inq-passwd");
1104 passwd_nonce = option_value (line, "--passwd-nonce");
1105 if (passwd_nonce)
1106 {
1107 for (pend = passwd_nonce; *pend && !spacep (pend); pend++)
1108 ;
1109 c = *pend;
1110 *pend = '\0';
1111 passwd_nonce = xtrystrdup (passwd_nonce);
1112 *pend = c;
1113 if (!passwd_nonce)
1114 {
1115 rc = gpg_error_from_syserror ();
1116 goto leave;
1117 }
1118 }
1119 if ((s=has_option_name (line, "--timestamp")))
1120 {
1121 if (*s != '=')
1122 {
1123 rc = set_error (GPG_ERR_ASS_PARAMETER, "missing value for option");
1124 goto leave;
1125 }
1126 opt_timestamp = isotime2epoch (s+1);
1127 if (opt_timestamp < 1)
1128 {
1129 rc = set_error (GPG_ERR_ASS_PARAMETER, "invalid time value");
1130 goto leave;
1131 }
1132 }
1133 else
1134 opt_timestamp = 0;
1135 line = skip_options (line);
1136
1137 for (p=line; *p && *p != ' ' && *p != '\t'; p++)
1138 ;
1139 *p = '\0';
1140 if (*line)
1141 cache_nonce = xtrystrdup (line);
1142
1143 eventcounter.maybe_key_change++;
1144
1145 /* First inquire the parameters */
1146 rc = print_assuan_status (ctx, "INQUIRE_MAXLEN", "%u", MAXLEN_KEYPARAM);
1147 if (rc)
1148 goto leave;
1149 rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM);
1150 if (rc)
1151 goto leave;
1152
1153 init_membuf (&outbuf, 512);
1154
1155 /* If requested, ask for the password to be used for the key. If
1156 this is not used the regular Pinentry mechanism is used. */
1157 if (opt_inq_passwd && !no_protection)
1158 {
1159 /* (N is used as a dummy) */
1160 assuan_begin_confidential (ctx);
1161 rc = assuan_inquire (ctx, "NEWPASSWD", &newpasswd, &n, 256);
1162 assuan_end_confidential (ctx);
1163 if (rc)
1164 goto leave;
1165 if (!*newpasswd)
1166 {
1167 /* Empty password given - switch to no-protection mode. */
1168 xfree (newpasswd);
1169 newpasswd = NULL;
1170 no_protection = 1;
1171 }
1172
1173 }
1174 else if (passwd_nonce)
1175 newpasswd = agent_get_cache (ctrl, passwd_nonce, CACHE_MODE_NONCE);
1176
1177 rc = agent_genkey (ctrl, cache_nonce, opt_timestamp,
1178 (char*)value, valuelen, no_protection,
1179 newpasswd, opt_preset, &outbuf);
1180
1181 leave:
1182 if (newpasswd)
1183 {
1184 /* Assuan_inquire does not allow us to read into secure memory
1185 thus we need to wipe it ourself. */
1186 wipememory (newpasswd, strlen (newpasswd));
1187 xfree (newpasswd);
1188 }
1189 xfree (value);
1190 if (rc)
1191 clear_outbuf (&outbuf);
1192 else
1193 rc = write_and_clear_outbuf (ctx, &outbuf);
1194 xfree (cache_nonce);
1195 xfree (passwd_nonce);
1196 return leave_cmd (ctx, rc);
1197 }
1198
1199
1200
1201
1202 static const char hlp_readkey[] =
1203 "READKEY [--no-data] <hexstring_with_keygrip>\n"
1204 " --card <keyid>\n"
1205 "\n"
1206 "Return the public key for the given keygrip or keyid.\n"
1207 "With --card, private key file with card information will be created.";
1208 static gpg_error_t
cmd_readkey(assuan_context_t ctx,char * line)1209 cmd_readkey (assuan_context_t ctx, char *line)
1210 {
1211 ctrl_t ctrl = assuan_get_pointer (ctx);
1212 int rc;
1213 unsigned char grip[20];
1214 gcry_sexp_t s_pkey = NULL;
1215 unsigned char *pkbuf = NULL;
1216 char *serialno = NULL;
1217 char *keyidbuf = NULL;
1218 size_t pkbuflen;
1219 int opt_card, opt_no_data;
1220
1221 if (ctrl->restricted)
1222 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
1223
1224 opt_no_data = has_option (line, "--no-data");
1225 opt_card = has_option (line, "--card");
1226 line = skip_options (line);
1227
1228 if (opt_card)
1229 {
1230 const char *keyid = line;
1231
1232 rc = agent_card_getattr (ctrl, "SERIALNO", &serialno, NULL);
1233 if (rc)
1234 {
1235 log_error (_("error getting serial number of card: %s\n"),
1236 gpg_strerror (rc));
1237 goto leave;
1238 }
1239
1240 /* Hack to create the shadow key for the OpenPGP standard keys. */
1241 if ((!strcmp (keyid, "$SIGNKEYID") || !strcmp (keyid, "$ENCRKEYID"))
1242 && !agent_card_getattr (ctrl, keyid, &keyidbuf, NULL))
1243 keyid = keyidbuf;
1244
1245 rc = agent_card_readkey (ctrl, keyid, &pkbuf, NULL);
1246 if (rc)
1247 goto leave;
1248 pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
1249 rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)pkbuf, pkbuflen);
1250 if (rc)
1251 goto leave;
1252
1253 if (!gcry_pk_get_keygrip (s_pkey, grip))
1254 {
1255 rc = gcry_pk_testkey (s_pkey);
1256 if (rc == 0)
1257 rc = gpg_error (GPG_ERR_INTERNAL);
1258
1259 goto leave;
1260 }
1261
1262 if (agent_key_available (grip))
1263 {
1264 /* (Shadow)-key is not available in our key storage. */
1265 rc = agent_write_shadow_key (grip, serialno, keyid, pkbuf, 0);
1266 if (rc)
1267 goto leave;
1268 }
1269
1270 rc = opt_no_data? 0 : assuan_send_data (ctx, pkbuf, pkbuflen);
1271 }
1272 else
1273 {
1274 rc = parse_keygrip (ctx, line, grip);
1275 if (rc)
1276 goto leave;
1277
1278 rc = agent_public_key_from_file (ctrl, grip, &s_pkey);
1279 if (!rc)
1280 {
1281 pkbuflen = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
1282 log_assert (pkbuflen);
1283 pkbuf = xtrymalloc (pkbuflen);
1284 if (!pkbuf)
1285 rc = gpg_error_from_syserror ();
1286 else
1287 {
1288 pkbuflen = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON,
1289 pkbuf, pkbuflen);
1290 rc = opt_no_data? 0 : assuan_send_data (ctx, pkbuf, pkbuflen);
1291 }
1292 }
1293 }
1294
1295 leave:
1296 xfree (keyidbuf);
1297 xfree (serialno);
1298 xfree (pkbuf);
1299 gcry_sexp_release (s_pkey);
1300 return leave_cmd (ctx, rc);
1301 }
1302
1303
1304
1305 static const char hlp_keyinfo[] =
1306 "KEYINFO [--[ssh-]list] [--data] [--ssh-fpr[=algo]] [--with-ssh] <keygrip>\n"
1307 "\n"
1308 "Return information about the key specified by the KEYGRIP. If the\n"
1309 "key is not available GPG_ERR_NOT_FOUND is returned. If the option\n"
1310 "--list is given the keygrip is ignored and information about all\n"
1311 "available keys are returned. If --ssh-list is given information\n"
1312 "about all keys listed in the sshcontrol are returned. With --with-ssh\n"
1313 "information from sshcontrol is always added to the info. Unless --data\n"
1314 "is given, the information is returned as a status line using the format:\n"
1315 "\n"
1316 " KEYINFO <keygrip> <type> <serialno> <idstr> <cached> <protection> <fpr>\n"
1317 "\n"
1318 "KEYGRIP is the keygrip.\n"
1319 "\n"
1320 "TYPE is describes the type of the key:\n"
1321 " 'D' - Regular key stored on disk,\n"
1322 " 'T' - Key is stored on a smartcard (token),\n"
1323 " 'X' - Unknown type,\n"
1324 " '-' - Key is missing.\n"
1325 "\n"
1326 "SERIALNO is an ASCII string with the serial number of the\n"
1327 " smartcard. If the serial number is not known a single\n"
1328 " dash '-' is used instead.\n"
1329 "\n"
1330 "IDSTR is the IDSTR used to distinguish keys on a smartcard. If it\n"
1331 " is not known a dash is used instead.\n"
1332 "\n"
1333 "CACHED is 1 if the passphrase for the key was found in the key cache.\n"
1334 " If not, a '-' is used instead.\n"
1335 "\n"
1336 "PROTECTION describes the key protection type:\n"
1337 " 'P' - The key is protected with a passphrase,\n"
1338 " 'C' - The key is not protected,\n"
1339 " '-' - Unknown protection.\n"
1340 "\n"
1341 "FPR returns the formatted ssh-style fingerprint of the key. It is only\n"
1342 " printed if the option --ssh-fpr has been used. If ALGO is not given\n"
1343 " to that option the default ssh fingerprint algo is used. Without the\n"
1344 " option a '-' is printed.\n"
1345 "\n"
1346 "TTL is the TTL in seconds for that key or '-' if n/a.\n"
1347 "\n"
1348 "FLAGS is a word consisting of one-letter flags:\n"
1349 " 'D' - The key has been disabled,\n"
1350 " 'S' - The key is listed in sshcontrol (requires --with-ssh),\n"
1351 " 'c' - Use of the key needs to be confirmed,\n"
1352 " 'A' - The key is available on card,\n"
1353 " '-' - No flags given.\n"
1354 "\n"
1355 "More information may be added in the future.";
1356 static gpg_error_t
do_one_keyinfo(ctrl_t ctrl,const unsigned char * grip,assuan_context_t ctx,int data,int with_ssh_fpr,int in_ssh,int ttl,int disabled,int confirm,int on_card)1357 do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx,
1358 int data, int with_ssh_fpr, int in_ssh,
1359 int ttl, int disabled, int confirm, int on_card)
1360 {
1361 gpg_error_t err;
1362 char hexgrip[40+1];
1363 char *fpr = NULL;
1364 int keytype;
1365 unsigned char *shadow_info = NULL;
1366 unsigned char *shadow_info_type = NULL;
1367 char *serialno = NULL;
1368 char *idstr = NULL;
1369 const char *keytypestr;
1370 const char *cached;
1371 const char *protectionstr;
1372 char *pw;
1373 int missing_key = 0;
1374 char ttlbuf[20];
1375 char flagsbuf[5];
1376
1377 err = agent_key_info_from_file (ctrl, grip, &keytype, &shadow_info,
1378 &shadow_info_type);
1379 if (err)
1380 {
1381 if (in_ssh && gpg_err_code (err) == GPG_ERR_NOT_FOUND)
1382 missing_key = 1;
1383 else
1384 goto leave;
1385 }
1386
1387 /* Reformat the grip so that we use uppercase as good style. */
1388 bin2hex (grip, 20, hexgrip);
1389
1390 if (ttl > 0)
1391 snprintf (ttlbuf, sizeof ttlbuf, "%d", ttl);
1392 else
1393 strcpy (ttlbuf, "-");
1394
1395 *flagsbuf = 0;
1396 if (disabled)
1397 strcat (flagsbuf, "D");
1398 if (in_ssh)
1399 strcat (flagsbuf, "S");
1400 if (confirm)
1401 strcat (flagsbuf, "c");
1402 if (on_card)
1403 strcat (flagsbuf, "A");
1404 if (!*flagsbuf)
1405 strcpy (flagsbuf, "-");
1406
1407
1408 if (missing_key)
1409 {
1410 protectionstr = "-"; keytypestr = "-";
1411 }
1412 else
1413 {
1414 switch (keytype)
1415 {
1416 case PRIVATE_KEY_CLEAR:
1417 case PRIVATE_KEY_OPENPGP_NONE:
1418 protectionstr = "C"; keytypestr = "D";
1419 break;
1420 case PRIVATE_KEY_PROTECTED: protectionstr = "P"; keytypestr = "D";
1421 break;
1422 case PRIVATE_KEY_SHADOWED: protectionstr = "-"; keytypestr = "T";
1423 break;
1424 default: protectionstr = "-"; keytypestr = "X";
1425 break;
1426 }
1427 }
1428
1429 /* Compute the ssh fingerprint if requested. */
1430 if (with_ssh_fpr)
1431 {
1432 gcry_sexp_t key;
1433
1434 if (!agent_raw_key_from_file (ctrl, grip, &key))
1435 {
1436 ssh_get_fingerprint_string (key, with_ssh_fpr, &fpr);
1437 gcry_sexp_release (key);
1438 }
1439 }
1440
1441 /* Here we have a little race by doing the cache check separately
1442 from the retrieval function. Given that the cache flag is only a
1443 hint, it should not really matter. */
1444 pw = agent_get_cache (ctrl, hexgrip, CACHE_MODE_NORMAL);
1445 cached = pw ? "1" : "-";
1446 xfree (pw);
1447
1448 if (shadow_info)
1449 {
1450 if (strcmp (shadow_info_type, "t1-v1") == 0)
1451 {
1452 err = parse_shadow_info (shadow_info, &serialno, &idstr, NULL);
1453 if (err)
1454 goto leave;
1455 }
1456 else if (strcmp (shadow_info_type, "tpm2-v1") == 0)
1457 {
1458 serialno = xstrdup("TPM-Protected");
1459 idstr = NULL;
1460 }
1461 else
1462 {
1463 log_error ("unrecognised shadow key type %s\n", shadow_info_type);
1464 err = GPG_ERR_BAD_KEY;
1465 goto leave;
1466 }
1467 }
1468
1469 if (!data)
1470 err = agent_write_status (ctrl, "KEYINFO",
1471 hexgrip,
1472 keytypestr,
1473 serialno? serialno : "-",
1474 idstr? idstr : "-",
1475 cached,
1476 protectionstr,
1477 fpr? fpr : "-",
1478 ttlbuf,
1479 flagsbuf,
1480 NULL);
1481 else
1482 {
1483 char *string;
1484
1485 string = xtryasprintf ("%s %s %s %s %s %s %s %s %s\n",
1486 hexgrip, keytypestr,
1487 serialno? serialno : "-",
1488 idstr? idstr : "-", cached, protectionstr,
1489 fpr? fpr : "-",
1490 ttlbuf,
1491 flagsbuf);
1492 if (!string)
1493 err = gpg_error_from_syserror ();
1494 else
1495 err = assuan_send_data (ctx, string, strlen(string));
1496 xfree (string);
1497 }
1498
1499 leave:
1500 xfree (fpr);
1501 xfree (shadow_info_type);
1502 xfree (shadow_info);
1503 xfree (serialno);
1504 xfree (idstr);
1505 return err;
1506 }
1507
1508
1509 /* Entry into the command KEYINFO. This function handles the
1510 * command option processing. For details see hlp_keyinfo above. */
1511 static gpg_error_t
cmd_keyinfo(assuan_context_t ctx,char * line)1512 cmd_keyinfo (assuan_context_t ctx, char *line)
1513 {
1514 ctrl_t ctrl = assuan_get_pointer (ctx);
1515 int err;
1516 unsigned char grip[20];
1517 gnupg_dir_t dir = NULL;
1518 int list_mode;
1519 int opt_data, opt_ssh_fpr, opt_with_ssh;
1520 ssh_control_file_t cf = NULL;
1521 char hexgrip[41];
1522 int disabled, ttl, confirm, is_ssh;
1523 struct card_key_info_s *keyinfo_on_cards;
1524 struct card_key_info_s *l;
1525 int on_card;
1526
1527 if (has_option (line, "--ssh-list"))
1528 list_mode = 2;
1529 else
1530 list_mode = has_option (line, "--list");
1531 opt_data = has_option (line, "--data");
1532
1533 if (has_option_name (line, "--ssh-fpr"))
1534 {
1535 if (has_option (line, "--ssh-fpr=md5"))
1536 opt_ssh_fpr = GCRY_MD_MD5;
1537 else if (has_option (line, "--ssh-fpr=sha1"))
1538 opt_ssh_fpr = GCRY_MD_SHA1;
1539 else if (has_option (line, "--ssh-fpr=sha256"))
1540 opt_ssh_fpr = GCRY_MD_SHA256;
1541 else
1542 opt_ssh_fpr = opt.ssh_fingerprint_digest;
1543 }
1544 else
1545 opt_ssh_fpr = 0;
1546
1547 opt_with_ssh = has_option (line, "--with-ssh");
1548 line = skip_options (line);
1549
1550 if (opt_with_ssh || list_mode == 2)
1551 cf = ssh_open_control_file ();
1552
1553 keyinfo_on_cards = get_keyinfo_on_cards (ctrl);
1554
1555 if (list_mode == 2)
1556 {
1557 if (ctrl->restricted)
1558 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
1559
1560 if (cf)
1561 {
1562 while (!ssh_read_control_file (cf, hexgrip,
1563 &disabled, &ttl, &confirm))
1564 {
1565 if (hex2bin (hexgrip, grip, 20) < 0 )
1566 continue; /* Bad hex string. */
1567
1568 on_card = 0;
1569 for (l = keyinfo_on_cards; l; l = l->next)
1570 if (!memcmp (l->keygrip, hexgrip, 40))
1571 on_card = 1;
1572
1573 err = do_one_keyinfo (ctrl, grip, ctx, opt_data, opt_ssh_fpr, 1,
1574 ttl, disabled, confirm, on_card);
1575 if (err)
1576 goto leave;
1577 }
1578 }
1579 err = 0;
1580 }
1581 else if (list_mode)
1582 {
1583 char *dirname;
1584 gnupg_dirent_t dir_entry;
1585
1586 if (ctrl->restricted)
1587 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
1588
1589 dirname = make_filename_try (gnupg_homedir (),
1590 GNUPG_PRIVATE_KEYS_DIR, NULL);
1591 if (!dirname)
1592 {
1593 err = gpg_error_from_syserror ();
1594 goto leave;
1595 }
1596 dir = gnupg_opendir (dirname);
1597 if (!dir)
1598 {
1599 err = gpg_error_from_syserror ();
1600 xfree (dirname);
1601 goto leave;
1602 }
1603 xfree (dirname);
1604
1605 while ( (dir_entry = gnupg_readdir (dir)) )
1606 {
1607 if (strlen (dir_entry->d_name) != 44
1608 || strcmp (dir_entry->d_name + 40, ".key"))
1609 continue;
1610 strncpy (hexgrip, dir_entry->d_name, 40);
1611 hexgrip[40] = 0;
1612
1613 if ( hex2bin (hexgrip, grip, 20) < 0 )
1614 continue; /* Bad hex string. */
1615
1616 disabled = ttl = confirm = is_ssh = 0;
1617 if (opt_with_ssh)
1618 {
1619 err = ssh_search_control_file (cf, hexgrip,
1620 &disabled, &ttl, &confirm);
1621 if (!err)
1622 is_ssh = 1;
1623 else if (gpg_err_code (err) != GPG_ERR_NOT_FOUND)
1624 goto leave;
1625 }
1626
1627 on_card = 0;
1628 for (l = keyinfo_on_cards; l; l = l->next)
1629 if (!memcmp (l->keygrip, hexgrip, 40))
1630 on_card = 1;
1631
1632 err = do_one_keyinfo (ctrl, grip, ctx, opt_data, opt_ssh_fpr, is_ssh,
1633 ttl, disabled, confirm, on_card);
1634 if (err)
1635 goto leave;
1636 }
1637 err = 0;
1638 }
1639 else
1640 {
1641 err = parse_keygrip (ctx, line, grip);
1642 if (err)
1643 goto leave;
1644 disabled = ttl = confirm = is_ssh = 0;
1645 if (opt_with_ssh)
1646 {
1647 err = ssh_search_control_file (cf, line,
1648 &disabled, &ttl, &confirm);
1649 if (!err)
1650 is_ssh = 1;
1651 else if (gpg_err_code (err) != GPG_ERR_NOT_FOUND)
1652 goto leave;
1653 }
1654
1655 on_card = 0;
1656 for (l = keyinfo_on_cards; l; l = l->next)
1657 if (!memcmp (l->keygrip, line, 40))
1658 on_card = 1;
1659
1660 err = do_one_keyinfo (ctrl, grip, ctx, opt_data, opt_ssh_fpr, is_ssh,
1661 ttl, disabled, confirm, on_card);
1662 }
1663
1664 leave:
1665 ssh_close_control_file (cf);
1666 gnupg_closedir (dir);
1667 if (err && gpg_err_code (err) != GPG_ERR_NOT_FOUND)
1668 leave_cmd (ctx, err);
1669 return err;
1670 }
1671
1672
1673
1674 /* Helper for cmd_get_passphrase. */
1675 static int
send_back_passphrase(assuan_context_t ctx,int via_data,const char * pw)1676 send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw)
1677 {
1678 size_t n;
1679 int rc;
1680
1681 assuan_begin_confidential (ctx);
1682 n = strlen (pw);
1683 if (via_data)
1684 rc = assuan_send_data (ctx, pw, n);
1685 else
1686 {
1687 char *p = xtrymalloc_secure (n*2+1);
1688 if (!p)
1689 rc = gpg_error_from_syserror ();
1690 else
1691 {
1692 bin2hex (pw, n, p);
1693 rc = assuan_set_okay_line (ctx, p);
1694 xfree (p);
1695 }
1696 }
1697 return rc;
1698 }
1699
1700
1701 /* Callback function to compare the first entered PIN with the one
1702 currently being entered. */
1703 static gpg_error_t
reenter_passphrase_cmp_cb(struct pin_entry_info_s * pi)1704 reenter_passphrase_cmp_cb (struct pin_entry_info_s *pi)
1705 {
1706 const char *pin1 = pi->check_cb_arg;
1707
1708 if (!strcmp (pin1, pi->pin))
1709 return 0; /* okay */
1710 return gpg_error (GPG_ERR_BAD_PASSPHRASE);
1711 }
1712
1713
1714 static const char hlp_get_passphrase[] =
1715 "GET_PASSPHRASE [--data] [--check] [--no-ask] [--repeat[=N]]\n"
1716 " [--qualitybar] [--newsymkey] <cache_id>\n"
1717 " [<error_message> <prompt> <description>]\n"
1718 "\n"
1719 "This function is usually used to ask for a passphrase to be used\n"
1720 "for conventional encryption, but may also be used by programs which\n"
1721 "need specal handling of passphrases. This command uses a syntax\n"
1722 "which helps clients to use the agent with minimum effort. The\n"
1723 "agent either returns with an error or with a OK followed by the hex\n"
1724 "encoded passphrase. Note that the length of the strings is\n"
1725 "implicitly limited by the maximum length of a command.\n"
1726 "\n"
1727 "If the option \"--data\" is used the passphrase is returned by usual\n"
1728 "data lines and not on the okay line.\n"
1729 "\n"
1730 "If the option \"--check\" is used the passphrase constraints checks as\n"
1731 "implemented by gpg-agent are applied. A check is not done if the\n"
1732 "passphrase has been found in the cache.\n"
1733 "\n"
1734 "If the option \"--no-ask\" is used and the passphrase is not in the\n"
1735 "cache the user will not be asked to enter a passphrase but the error\n"
1736 "code GPG_ERR_NO_DATA is returned. \n"
1737 "\n"
1738 "If the option\"--newsymkey\" is used the agent asks for a new passphrase\n"
1739 "to be used in symmetric-only encryption. This must not be empty.\n"
1740 "\n"
1741 "If the option \"--qualitybar\" is used a visual indication of the\n"
1742 "entered passphrase quality is shown. (Unless no minimum passphrase\n"
1743 "length has been configured.)";
1744 static gpg_error_t
cmd_get_passphrase(assuan_context_t ctx,char * line)1745 cmd_get_passphrase (assuan_context_t ctx, char *line)
1746 {
1747 ctrl_t ctrl = assuan_get_pointer (ctx);
1748 int rc;
1749 char *pw;
1750 char *response = NULL;
1751 char *response2 = NULL;
1752 char *cacheid = NULL; /* May point into LINE. */
1753 char *desc = NULL; /* Ditto */
1754 char *prompt = NULL; /* Ditto */
1755 char *errtext = NULL; /* Ditto */
1756 const char *desc2 = _("Please re-enter this passphrase");
1757 char *p;
1758 int opt_data, opt_check, opt_no_ask, opt_qualbar, opt_newsymkey;
1759 int opt_repeat = 0;
1760 char *entry_errtext = NULL;
1761 struct pin_entry_info_s *pi = NULL;
1762 struct pin_entry_info_s *pi2 = NULL;
1763 int is_generated;
1764
1765 if (ctrl->restricted)
1766 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
1767
1768 opt_data = has_option (line, "--data");
1769 opt_check = has_option (line, "--check");
1770 opt_no_ask = has_option (line, "--no-ask");
1771 if (has_option_name (line, "--repeat"))
1772 {
1773 p = option_value (line, "--repeat");
1774 if (p)
1775 opt_repeat = atoi (p);
1776 else
1777 opt_repeat = 1;
1778 }
1779 opt_qualbar = has_option (line, "--qualitybar");
1780 opt_newsymkey = has_option (line, "--newsymkey");
1781 line = skip_options (line);
1782
1783 cacheid = line;
1784 p = strchr (cacheid, ' ');
1785 if (p)
1786 {
1787 *p++ = 0;
1788 while (*p == ' ')
1789 p++;
1790 errtext = p;
1791 p = strchr (errtext, ' ');
1792 if (p)
1793 {
1794 *p++ = 0;
1795 while (*p == ' ')
1796 p++;
1797 prompt = p;
1798 p = strchr (prompt, ' ');
1799 if (p)
1800 {
1801 *p++ = 0;
1802 while (*p == ' ')
1803 p++;
1804 desc = p;
1805 p = strchr (desc, ' ');
1806 if (p)
1807 *p = 0; /* Ignore trailing garbage. */
1808 }
1809 }
1810 }
1811 if (!*cacheid || strlen (cacheid) > 50)
1812 return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
1813 if (!desc)
1814 return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
1815
1816 if (!strcmp (cacheid, "X"))
1817 cacheid = NULL;
1818 if (!strcmp (errtext, "X"))
1819 errtext = NULL;
1820 if (!strcmp (prompt, "X"))
1821 prompt = NULL;
1822 if (!strcmp (desc, "X"))
1823 desc = NULL;
1824
1825 pw = cacheid ? agent_get_cache (ctrl, cacheid, CACHE_MODE_USER) : NULL;
1826 if (pw)
1827 {
1828 rc = send_back_passphrase (ctx, opt_data, pw);
1829 xfree (pw);
1830 goto leave;
1831 }
1832 else if (opt_no_ask)
1833 {
1834 rc = gpg_error (GPG_ERR_NO_DATA);
1835 goto leave;
1836 }
1837
1838 /* Note, that we only need to replace the + characters and should
1839 * leave the other escaping in place because the escaped string is
1840 * send verbatim to the pinentry which does the unescaping (but not
1841 * the + replacing) */
1842 if (errtext)
1843 plus_to_blank (errtext);
1844 if (prompt)
1845 plus_to_blank (prompt);
1846 if (desc)
1847 plus_to_blank (desc);
1848
1849 /* If opt_repeat is 2 or higher we can't use our pin_entry_info_s
1850 * based method but fallback to the old simple method. It is
1851 * anyway questionable whether this extra repeat count makes any
1852 * real sense. */
1853 if (opt_newsymkey && opt_repeat < 2)
1854 {
1855 /* We do not want to break any existing usage of this command
1856 * and thus we introduced the option --newsymkey to make this
1857 * command more useful to query the passphrase for symmetric
1858 * encryption. */
1859 pi = gcry_calloc_secure (1, sizeof (*pi) + MAX_PASSPHRASE_LEN + 1);
1860 if (!pi)
1861 {
1862 rc = gpg_error_from_syserror ();
1863 goto leave;
1864 }
1865 pi2 = gcry_calloc_secure (1, sizeof (*pi2) + MAX_PASSPHRASE_LEN + 1);
1866 if (!pi2)
1867 {
1868 rc = gpg_error_from_syserror ();
1869 goto leave;
1870 }
1871 pi->max_length = MAX_PASSPHRASE_LEN + 1;
1872 pi->max_tries = 3;
1873 pi->with_qualitybar = opt_qualbar;
1874 pi->with_repeat = opt_repeat;
1875 pi->constraints_flags = (CHECK_CONSTRAINTS_NOT_EMPTY
1876 | CHECK_CONSTRAINTS_NEW_SYMKEY);
1877 pi2->max_length = MAX_PASSPHRASE_LEN + 1;
1878 pi2->max_tries = 3;
1879 pi2->check_cb = reenter_passphrase_cmp_cb;
1880 pi2->check_cb_arg = pi->pin;
1881
1882 for (;;) /* (degenerated for-loop) */
1883 {
1884 xfree (response);
1885 response = NULL;
1886 rc = agent_get_passphrase (ctrl, &response,
1887 desc,
1888 prompt,
1889 entry_errtext? entry_errtext:errtext,
1890 opt_qualbar, cacheid, CACHE_MODE_USER,
1891 pi);
1892 if (rc)
1893 goto leave;
1894 xfree (entry_errtext);
1895 entry_errtext = NULL;
1896 is_generated = !!(pi->status & PINENTRY_STATUS_PASSWORD_GENERATED);
1897
1898 /* We don't allow an empty passpharse in this mode. */
1899 if (!is_generated
1900 && check_passphrase_constraints (ctrl, pi->pin,
1901 pi->constraints_flags,
1902 &entry_errtext))
1903 {
1904 pi->failed_tries = 0;
1905 pi2->failed_tries = 0;
1906 continue;
1907 }
1908 if (*pi->pin && !pi->repeat_okay
1909 && ctrl->pinentry_mode != PINENTRY_MODE_LOOPBACK
1910 && opt_repeat)
1911 {
1912 /* The passphrase is empty and the pinentry did not
1913 * already run the repetition check, do it here. This
1914 * is only called when using an old and simple pinentry.
1915 * It is neither called in loopback mode because the
1916 * caller does any passphrase repetition by herself nor if
1917 * no repetition was requested. */
1918 xfree (response);
1919 response = NULL;
1920 rc = agent_get_passphrase (ctrl, &response,
1921 L_("Please re-enter this passphrase"),
1922 prompt,
1923 entry_errtext? entry_errtext:errtext,
1924 opt_qualbar, cacheid, CACHE_MODE_USER,
1925 pi2);
1926 if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE)
1927 { /* The re-entered passphrase one did not match and
1928 * the user did not hit cancel. */
1929 entry_errtext = xtrystrdup (L_("does not match - try again"));
1930 if (!entry_errtext)
1931 {
1932 rc = gpg_error_from_syserror ();
1933 goto leave;
1934 }
1935 continue;
1936 }
1937 }
1938 break;
1939 }
1940 if (!rc && *pi->pin)
1941 {
1942 /* Return the passphrase. */
1943 if (cacheid)
1944 agent_put_cache (ctrl, cacheid, CACHE_MODE_USER, pi->pin, 0);
1945 rc = send_back_passphrase (ctx, opt_data, pi->pin);
1946 }
1947 }
1948 else
1949 {
1950 next_try:
1951 xfree (response);
1952 response = NULL;
1953 rc = agent_get_passphrase (ctrl, &response, desc, prompt,
1954 entry_errtext? entry_errtext:errtext,
1955 opt_qualbar, cacheid, CACHE_MODE_USER, NULL);
1956 xfree (entry_errtext);
1957 entry_errtext = NULL;
1958 is_generated = 0;
1959
1960 if (!rc)
1961 {
1962 int i;
1963
1964 if (opt_check
1965 && !is_generated
1966 && check_passphrase_constraints
1967 (ctrl, response,
1968 (opt_newsymkey? CHECK_CONSTRAINTS_NEW_SYMKEY:0),
1969 &entry_errtext))
1970 {
1971 goto next_try;
1972 }
1973 for (i = 0; i < opt_repeat; i++)
1974 {
1975 if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
1976 break;
1977
1978 xfree (response2);
1979 response2 = NULL;
1980 rc = agent_get_passphrase (ctrl, &response2, desc2, prompt,
1981 errtext, 0,
1982 cacheid, CACHE_MODE_USER, NULL);
1983 if (rc)
1984 break;
1985 if (strcmp (response2, response))
1986 {
1987 entry_errtext = try_percent_escape
1988 (_("does not match - try again"), NULL);
1989 if (!entry_errtext)
1990 {
1991 rc = gpg_error_from_syserror ();
1992 break;
1993 }
1994 goto next_try;
1995 }
1996 }
1997 if (!rc)
1998 {
1999 if (cacheid)
2000 agent_put_cache (ctrl, cacheid, CACHE_MODE_USER, response, 0);
2001 rc = send_back_passphrase (ctx, opt_data, response);
2002 }
2003 }
2004 }
2005
2006 leave:
2007 xfree (response);
2008 xfree (response2);
2009 xfree (entry_errtext);
2010 xfree (pi2);
2011 xfree (pi);
2012 return leave_cmd (ctx, rc);
2013 }
2014
2015
2016 static const char hlp_clear_passphrase[] =
2017 "CLEAR_PASSPHRASE [--mode=normal] <cache_id>\n"
2018 "\n"
2019 "may be used to invalidate the cache entry for a passphrase. The\n"
2020 "function returns with OK even when there is no cached passphrase.\n"
2021 "The --mode=normal option is used to clear an entry for a cacheid\n"
2022 "added by the agent. The --mode=ssh option is used for a cacheid\n"
2023 "added for ssh.\n";
2024 static gpg_error_t
cmd_clear_passphrase(assuan_context_t ctx,char * line)2025 cmd_clear_passphrase (assuan_context_t ctx, char *line)
2026 {
2027 ctrl_t ctrl = assuan_get_pointer (ctx);
2028 char *cacheid = NULL;
2029 char *p;
2030 cache_mode_t cache_mode = CACHE_MODE_USER;
2031
2032 if (ctrl->restricted)
2033 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
2034
2035 if (has_option (line, "--mode=normal"))
2036 cache_mode = CACHE_MODE_NORMAL;
2037 else if (has_option (line, "--mode=ssh"))
2038 cache_mode = CACHE_MODE_SSH;
2039
2040 line = skip_options (line);
2041
2042 /* parse the stuff */
2043 for (p=line; *p == ' '; p++)
2044 ;
2045 cacheid = p;
2046 p = strchr (cacheid, ' ');
2047 if (p)
2048 *p = 0; /* ignore garbage */
2049 if (!*cacheid || strlen (cacheid) > 50)
2050 return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
2051
2052 agent_put_cache (ctrl, cacheid, cache_mode, NULL, 0);
2053
2054 agent_clear_passphrase (ctrl, cacheid, cache_mode);
2055
2056 return 0;
2057 }
2058
2059
2060 static const char hlp_get_confirmation[] =
2061 "GET_CONFIRMATION <description>\n"
2062 "\n"
2063 "This command may be used to ask for a simple confirmation.\n"
2064 "DESCRIPTION is displayed along with a Okay and Cancel button. This\n"
2065 "command uses a syntax which helps clients to use the agent with\n"
2066 "minimum effort. The agent either returns with an error or with a\n"
2067 "OK. Note, that the length of DESCRIPTION is implicitly limited by\n"
2068 "the maximum length of a command. DESCRIPTION should not contain\n"
2069 "any spaces, those must be encoded either percent escaped or simply\n"
2070 "as '+'.";
2071 static gpg_error_t
cmd_get_confirmation(assuan_context_t ctx,char * line)2072 cmd_get_confirmation (assuan_context_t ctx, char *line)
2073 {
2074 ctrl_t ctrl = assuan_get_pointer (ctx);
2075 int rc;
2076 char *desc = NULL;
2077 char *p;
2078
2079 if (ctrl->restricted)
2080 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
2081
2082 /* parse the stuff */
2083 for (p=line; *p == ' '; p++)
2084 ;
2085 desc = p;
2086 p = strchr (desc, ' ');
2087 if (p)
2088 *p = 0; /* We ignore any garbage -may be later used for other args. */
2089
2090 if (!*desc)
2091 return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
2092
2093 if (!strcmp (desc, "X"))
2094 desc = NULL;
2095
2096 /* Note, that we only need to replace the + characters and should
2097 leave the other escaping in place because the escaped string is
2098 send verbatim to the pinentry which does the unescaping (but not
2099 the + replacing) */
2100 if (desc)
2101 plus_to_blank (desc);
2102
2103 rc = agent_get_confirmation (ctrl, desc, NULL, NULL, 0);
2104 return leave_cmd (ctx, rc);
2105 }
2106
2107
2108
2109 static const char hlp_learn[] =
2110 "LEARN [--send] [--sendinfo] [--force]\n"
2111 "\n"
2112 "Learn something about the currently inserted smartcard. With\n"
2113 "--sendinfo information about the card is returned; with --send\n"
2114 "the available certificates are returned as D lines; with --force\n"
2115 "private key storage will be updated by the result.";
2116 static gpg_error_t
cmd_learn(assuan_context_t ctx,char * line)2117 cmd_learn (assuan_context_t ctx, char *line)
2118 {
2119 ctrl_t ctrl = assuan_get_pointer (ctx);
2120 gpg_error_t err;
2121 int send, sendinfo, force;
2122
2123 send = has_option (line, "--send");
2124 sendinfo = send? 1 : has_option (line, "--sendinfo");
2125 force = has_option (line, "--force");
2126
2127 if (ctrl->restricted)
2128 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
2129
2130 err = agent_handle_learn (ctrl, send, sendinfo? ctx : NULL, force);
2131 return leave_cmd (ctx, err);
2132 }
2133
2134
2135
2136 static const char hlp_passwd[] =
2137 "PASSWD [--cache-nonce=<c>] [--passwd-nonce=<s>] [--preset]\n"
2138 " [--verify] <hexkeygrip>\n"
2139 "\n"
2140 "Change the passphrase/PIN for the key identified by keygrip in LINE. If\n"
2141 "--preset is used then the new passphrase will be added to the cache.\n"
2142 "If --verify is used the command asks for the passphrase and verifies\n"
2143 "that the passphrase valid.\n";
2144 static gpg_error_t
cmd_passwd(assuan_context_t ctx,char * line)2145 cmd_passwd (assuan_context_t ctx, char *line)
2146 {
2147 ctrl_t ctrl = assuan_get_pointer (ctx);
2148 gpg_error_t err;
2149 int c;
2150 char *cache_nonce = NULL;
2151 char *passwd_nonce = NULL;
2152 unsigned char grip[20];
2153 gcry_sexp_t s_skey = NULL;
2154 unsigned char *shadow_info = NULL;
2155 char *passphrase = NULL;
2156 char *pend;
2157 int opt_preset, opt_verify;
2158
2159 if (ctrl->restricted)
2160 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
2161
2162 opt_preset = has_option (line, "--preset");
2163 cache_nonce = option_value (line, "--cache-nonce");
2164 opt_verify = has_option (line, "--verify");
2165 if (cache_nonce)
2166 {
2167 for (pend = cache_nonce; *pend && !spacep (pend); pend++)
2168 ;
2169 c = *pend;
2170 *pend = '\0';
2171 cache_nonce = xtrystrdup (cache_nonce);
2172 *pend = c;
2173 if (!cache_nonce)
2174 {
2175 err = gpg_error_from_syserror ();
2176 goto leave;
2177 }
2178 }
2179
2180 passwd_nonce = option_value (line, "--passwd-nonce");
2181 if (passwd_nonce)
2182 {
2183 for (pend = passwd_nonce; *pend && !spacep (pend); pend++)
2184 ;
2185 c = *pend;
2186 *pend = '\0';
2187 passwd_nonce = xtrystrdup (passwd_nonce);
2188 *pend = c;
2189 if (!passwd_nonce)
2190 {
2191 err = gpg_error_from_syserror ();
2192 goto leave;
2193 }
2194 }
2195
2196 line = skip_options (line);
2197
2198 err = parse_keygrip (ctx, line, grip);
2199 if (err)
2200 goto leave;
2201
2202 ctrl->in_passwd++;
2203 err = agent_key_from_file (ctrl,
2204 opt_verify? NULL : cache_nonce,
2205 ctrl->server_local->keydesc,
2206 grip, &shadow_info, CACHE_MODE_IGNORE, NULL,
2207 &s_skey, &passphrase);
2208 if (err)
2209 ;
2210 else if (shadow_info)
2211 {
2212 log_error ("changing a smartcard PIN is not yet supported\n");
2213 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2214 }
2215 else if (opt_verify)
2216 {
2217 /* All done. */
2218 if (passphrase)
2219 {
2220 if (!passwd_nonce)
2221 {
2222 char buf[12];
2223 gcry_create_nonce (buf, 12);
2224 passwd_nonce = bin2hex (buf, 12, NULL);
2225 }
2226 if (passwd_nonce
2227 && !agent_put_cache (ctrl, passwd_nonce, CACHE_MODE_NONCE,
2228 passphrase, CACHE_TTL_NONCE))
2229 {
2230 assuan_write_status (ctx, "PASSWD_NONCE", passwd_nonce);
2231 xfree (ctrl->server_local->last_passwd_nonce);
2232 ctrl->server_local->last_passwd_nonce = passwd_nonce;
2233 passwd_nonce = NULL;
2234 }
2235 }
2236 }
2237 else
2238 {
2239 char *newpass = NULL;
2240
2241 if (passwd_nonce)
2242 newpass = agent_get_cache (ctrl, passwd_nonce, CACHE_MODE_NONCE);
2243 err = agent_protect_and_store (ctrl, s_skey, &newpass);
2244 if (!err && passphrase)
2245 {
2246 /* A passphrase existed on the old key and the change was
2247 successful. Return a nonce for that old passphrase to
2248 let the caller try to unprotect the other subkeys with
2249 the same key. */
2250 if (!cache_nonce)
2251 {
2252 char buf[12];
2253 gcry_create_nonce (buf, 12);
2254 cache_nonce = bin2hex (buf, 12, NULL);
2255 }
2256 if (cache_nonce
2257 && !agent_put_cache (ctrl, cache_nonce, CACHE_MODE_NONCE,
2258 passphrase, CACHE_TTL_NONCE))
2259 {
2260 assuan_write_status (ctx, "CACHE_NONCE", cache_nonce);
2261 xfree (ctrl->server_local->last_cache_nonce);
2262 ctrl->server_local->last_cache_nonce = cache_nonce;
2263 cache_nonce = NULL;
2264 }
2265 if (newpass)
2266 {
2267 /* If we have a new passphrase (which might be empty) we
2268 store it under a passwd nonce so that the caller may
2269 send that nonce again to use it for another key. */
2270 if (!passwd_nonce)
2271 {
2272 char buf[12];
2273 gcry_create_nonce (buf, 12);
2274 passwd_nonce = bin2hex (buf, 12, NULL);
2275 }
2276 if (passwd_nonce
2277 && !agent_put_cache (ctrl, passwd_nonce, CACHE_MODE_NONCE,
2278 newpass, CACHE_TTL_NONCE))
2279 {
2280 assuan_write_status (ctx, "PASSWD_NONCE", passwd_nonce);
2281 xfree (ctrl->server_local->last_passwd_nonce);
2282 ctrl->server_local->last_passwd_nonce = passwd_nonce;
2283 passwd_nonce = NULL;
2284 }
2285 }
2286 }
2287 if (!err && opt_preset)
2288 {
2289 char hexgrip[40+1];
2290 bin2hex(grip, 20, hexgrip);
2291 err = agent_put_cache (ctrl, hexgrip, CACHE_MODE_ANY, newpass,
2292 ctrl->cache_ttl_opt_preset);
2293 }
2294 xfree (newpass);
2295 }
2296 ctrl->in_passwd--;
2297
2298 xfree (ctrl->server_local->keydesc);
2299 ctrl->server_local->keydesc = NULL;
2300
2301 leave:
2302 xfree (passphrase);
2303 gcry_sexp_release (s_skey);
2304 xfree (shadow_info);
2305 xfree (cache_nonce);
2306 xfree (passwd_nonce);
2307 return leave_cmd (ctx, err);
2308 }
2309
2310
2311 static const char hlp_preset_passphrase[] =
2312 "PRESET_PASSPHRASE [--inquire] <string_or_keygrip> <timeout> [<hexstring>]\n"
2313 "\n"
2314 "Set the cached passphrase/PIN for the key identified by the keygrip\n"
2315 "to passwd for the given time, where -1 means infinite and 0 means\n"
2316 "the default (currently only a timeout of -1 is allowed, which means\n"
2317 "to never expire it). If passwd is not provided, ask for it via the\n"
2318 "pinentry module unless --inquire is passed in which case the passphrase\n"
2319 "is retrieved from the client via a server inquire.\n";
2320 static gpg_error_t
cmd_preset_passphrase(assuan_context_t ctx,char * line)2321 cmd_preset_passphrase (assuan_context_t ctx, char *line)
2322 {
2323 ctrl_t ctrl = assuan_get_pointer (ctx);
2324 int rc;
2325 char *grip_clear = NULL;
2326 unsigned char *passphrase = NULL;
2327 int ttl;
2328 size_t len;
2329 int opt_inquire;
2330
2331 if (ctrl->restricted)
2332 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
2333
2334 if (!opt.allow_preset_passphrase)
2335 return set_error (GPG_ERR_NOT_SUPPORTED, "no --allow-preset-passphrase");
2336
2337 opt_inquire = has_option (line, "--inquire");
2338 line = skip_options (line);
2339 grip_clear = line;
2340 while (*line && (*line != ' ' && *line != '\t'))
2341 line++;
2342 if (!*line)
2343 return gpg_error (GPG_ERR_MISSING_VALUE);
2344 *line = '\0';
2345 line++;
2346 while (*line && (*line == ' ' || *line == '\t'))
2347 line++;
2348
2349 /* Currently, only infinite timeouts are allowed. */
2350 ttl = -1;
2351 if (line[0] != '-' || line[1] != '1')
2352 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2353 line++;
2354 line++;
2355 while (!(*line != ' ' && *line != '\t'))
2356 line++;
2357
2358 /* Syntax check the hexstring. */
2359 len = 0;
2360 rc = parse_hexstring (ctx, line, &len);
2361 if (rc)
2362 return rc;
2363 line[len] = '\0';
2364
2365 /* If there is a passphrase, use it. Currently, a passphrase is
2366 required. */
2367 if (*line)
2368 {
2369 if (opt_inquire)
2370 {
2371 rc = set_error (GPG_ERR_ASS_PARAMETER,
2372 "both --inquire and passphrase specified");
2373 goto leave;
2374 }
2375
2376 /* Do in-place conversion. */
2377 passphrase = line;
2378 if (!hex2str (passphrase, passphrase, strlen (passphrase)+1, NULL))
2379 rc = set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
2380 }
2381 else if (opt_inquire)
2382 {
2383 /* Note that the passphrase will be truncated at any null byte and the
2384 * limit is 480 characters. */
2385 size_t maxlen = 480;
2386
2387 rc = print_assuan_status (ctx, "INQUIRE_MAXLEN", "%zu", maxlen);
2388 if (!rc)
2389 rc = assuan_inquire (ctx, "PASSPHRASE", &passphrase, &len, maxlen);
2390 }
2391 else
2392 rc = set_error (GPG_ERR_NOT_IMPLEMENTED, "passphrase is required");
2393
2394 if (!rc)
2395 {
2396 rc = agent_put_cache (ctrl, grip_clear, CACHE_MODE_ANY, passphrase, ttl);
2397 if (opt_inquire)
2398 xfree (passphrase);
2399 }
2400
2401 leave:
2402 return leave_cmd (ctx, rc);
2403 }
2404
2405
2406
2407 static const char hlp_scd[] =
2408 "SCD <commands to pass to the scdaemon>\n"
2409 " \n"
2410 "This is a general quote command to redirect everything to the\n"
2411 "SCdaemon.";
2412 static gpg_error_t
cmd_scd(assuan_context_t ctx,char * line)2413 cmd_scd (assuan_context_t ctx, char *line)
2414 {
2415 int rc;
2416 #ifdef BUILD_WITH_SCDAEMON
2417 ctrl_t ctrl = assuan_get_pointer (ctx);
2418
2419 if (ctrl->restricted)
2420 {
2421 const char *argv[5];
2422 int argc;
2423 char *l;
2424
2425 l = xtrystrdup (line);
2426 if (!l)
2427 return gpg_error_from_syserror ();
2428
2429 argc = split_fields (l, argv, DIM (argv));
2430
2431 /* These commands are allowed. */
2432 if ((argc == 1 && !strcmp (argv[0], "SERIALNO"))
2433 || (argc == 2
2434 && !strcmp (argv[0], "GETINFO")
2435 && !strcmp (argv[1], "version"))
2436 || (argc == 2
2437 && !strcmp (argv[0], "GETATTR")
2438 && !strcmp (argv[1], "KEY-FPR"))
2439 || (argc == 2
2440 && !strcmp (argv[0], "KEYINFO")
2441 && !strcmp (argv[1], "--list=encr")))
2442 xfree (l);
2443 else
2444 {
2445 xfree (l);
2446 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
2447 }
2448 }
2449
2450 /* All SCD prefixed commands may change a key. */
2451 eventcounter.maybe_key_change++;
2452
2453 rc = divert_generic_cmd (ctrl, line, ctx);
2454 #else
2455 (void)ctx; (void)line;
2456 rc = gpg_error (GPG_ERR_NOT_SUPPORTED);
2457 #endif
2458 return rc;
2459 }
2460
2461
2462
2463 static const char hlp_keywrap_key[] =
2464 "KEYWRAP_KEY [--clear] <mode>\n"
2465 "\n"
2466 "Return a key to wrap another key. For now the key is returned\n"
2467 "verbatim and thus makes not much sense because an eavesdropper on\n"
2468 "the gpg-agent connection will see the key as well as the wrapped key.\n"
2469 "However, this function may either be equipped with a public key\n"
2470 "mechanism or not used at all if the key is a pre-shared key. In any\n"
2471 "case wrapping the import and export of keys is a requirement for\n"
2472 "certain cryptographic validations and thus useful. The key persists\n"
2473 "until a RESET command but may be cleared using the option --clear.\n"
2474 "\n"
2475 "Supported modes are:\n"
2476 " --import - Return a key to import a key into gpg-agent\n"
2477 " --export - Return a key to export a key from gpg-agent";
2478 static gpg_error_t
cmd_keywrap_key(assuan_context_t ctx,char * line)2479 cmd_keywrap_key (assuan_context_t ctx, char *line)
2480 {
2481 ctrl_t ctrl = assuan_get_pointer (ctx);
2482 gpg_error_t err = 0;
2483 int clearopt = has_option (line, "--clear");
2484
2485 if (ctrl->restricted)
2486 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
2487
2488 assuan_begin_confidential (ctx);
2489 if (has_option (line, "--import"))
2490 {
2491 xfree (ctrl->server_local->import_key);
2492 if (clearopt)
2493 ctrl->server_local->import_key = NULL;
2494 else if (!(ctrl->server_local->import_key =
2495 gcry_random_bytes (KEYWRAP_KEYSIZE, GCRY_STRONG_RANDOM)))
2496 err = gpg_error_from_syserror ();
2497 else
2498 err = assuan_send_data (ctx, ctrl->server_local->import_key,
2499 KEYWRAP_KEYSIZE);
2500 }
2501 else if (has_option (line, "--export"))
2502 {
2503 xfree (ctrl->server_local->export_key);
2504 if (clearopt)
2505 ctrl->server_local->export_key = NULL;
2506 else if (!(ctrl->server_local->export_key =
2507 gcry_random_bytes (KEYWRAP_KEYSIZE, GCRY_STRONG_RANDOM)))
2508 err = gpg_error_from_syserror ();
2509 else
2510 err = assuan_send_data (ctx, ctrl->server_local->export_key,
2511 KEYWRAP_KEYSIZE);
2512 }
2513 else
2514 err = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for MODE");
2515 assuan_end_confidential (ctx);
2516
2517 return leave_cmd (ctx, err);
2518 }
2519
2520
2521
2522 static const char hlp_import_key[] =
2523 "IMPORT_KEY [--unattended] [--force] [--timestamp=<isodate>]\n"
2524 " [<cache_nonce>]\n"
2525 "\n"
2526 "Import a secret key into the key store. The key is expected to be\n"
2527 "encrypted using the current session's key wrapping key (cf. command\n"
2528 "KEYWRAP_KEY) using the AESWRAP-128 algorithm. This function takes\n"
2529 "no arguments but uses the inquiry \"KEYDATA\" to ask for the actual\n"
2530 "key data. The unwrapped key must be a canonical S-expression. The\n"
2531 "option --unattended tries to import the key as-is without any\n"
2532 "re-encryption. An existing key can be overwritten with --force.\n"
2533 "If --timestamp is given its value is recorded as the key's creation\n"
2534 "time; the value is expected in ISO format (e.g. \"20030316T120000\").";
2535 static gpg_error_t
cmd_import_key(assuan_context_t ctx,char * line)2536 cmd_import_key (assuan_context_t ctx, char *line)
2537 {
2538 ctrl_t ctrl = assuan_get_pointer (ctx);
2539 gpg_error_t err;
2540 int opt_unattended;
2541 time_t opt_timestamp;
2542 int force;
2543 unsigned char *wrappedkey = NULL;
2544 size_t wrappedkeylen;
2545 gcry_cipher_hd_t cipherhd = NULL;
2546 unsigned char *key = NULL;
2547 size_t keylen, realkeylen;
2548 char *passphrase = NULL;
2549 unsigned char *finalkey = NULL;
2550 size_t finalkeylen;
2551 unsigned char grip[20];
2552 gcry_sexp_t openpgp_sexp = NULL;
2553 char *cache_nonce = NULL;
2554 char *p;
2555 const char *s;
2556
2557 if (ctrl->restricted)
2558 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
2559
2560 if (!ctrl->server_local->import_key)
2561 {
2562 err = gpg_error (GPG_ERR_MISSING_KEY);
2563 goto leave;
2564 }
2565
2566 opt_unattended = has_option (line, "--unattended");
2567 force = has_option (line, "--force");
2568 if ((s=has_option_name (line, "--timestamp")))
2569 {
2570 if (*s != '=')
2571 {
2572 err = set_error (GPG_ERR_ASS_PARAMETER, "missing value for option");
2573 goto leave;
2574 }
2575 opt_timestamp = isotime2epoch (s+1);
2576 if (opt_timestamp < 1)
2577 {
2578 err = set_error (GPG_ERR_ASS_PARAMETER, "invalid time value");
2579 goto leave;
2580 }
2581 }
2582 else
2583 opt_timestamp = 0;
2584 line = skip_options (line);
2585
2586 for (p=line; *p && *p != ' ' && *p != '\t'; p++)
2587 ;
2588 *p = '\0';
2589 if (*line)
2590 cache_nonce = xtrystrdup (line);
2591
2592 eventcounter.maybe_key_change++;
2593
2594 assuan_begin_confidential (ctx);
2595 err = assuan_inquire (ctx, "KEYDATA",
2596 &wrappedkey, &wrappedkeylen, MAXLEN_KEYDATA);
2597 assuan_end_confidential (ctx);
2598 if (err)
2599 goto leave;
2600 if (wrappedkeylen < 24)
2601 {
2602 err = gpg_error (GPG_ERR_INV_LENGTH);
2603 goto leave;
2604 }
2605 keylen = wrappedkeylen - 8;
2606 key = xtrymalloc_secure (keylen);
2607 if (!key)
2608 {
2609 err = gpg_error_from_syserror ();
2610 goto leave;
2611 }
2612
2613 err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
2614 GCRY_CIPHER_MODE_AESWRAP, 0);
2615 if (err)
2616 goto leave;
2617 err = gcry_cipher_setkey (cipherhd,
2618 ctrl->server_local->import_key, KEYWRAP_KEYSIZE);
2619 if (err)
2620 goto leave;
2621 err = gcry_cipher_decrypt (cipherhd, key, keylen, wrappedkey, wrappedkeylen);
2622 if (err)
2623 goto leave;
2624 gcry_cipher_close (cipherhd);
2625 cipherhd = NULL;
2626 xfree (wrappedkey);
2627 wrappedkey = NULL;
2628
2629 realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err);
2630 if (!realkeylen)
2631 goto leave; /* Invalid canonical encoded S-expression. */
2632
2633 err = keygrip_from_canon_sexp (key, realkeylen, grip);
2634 if (err)
2635 {
2636 /* This might be due to an unsupported S-expression format.
2637 Check whether this is openpgp-private-key and trigger that
2638 import code. */
2639 if (!gcry_sexp_sscan (&openpgp_sexp, NULL, key, realkeylen))
2640 {
2641 const char *tag;
2642 size_t taglen;
2643
2644 tag = gcry_sexp_nth_data (openpgp_sexp, 0, &taglen);
2645 if (tag && taglen == 19 && !memcmp (tag, "openpgp-private-key", 19))
2646 ;
2647 else
2648 {
2649 gcry_sexp_release (openpgp_sexp);
2650 openpgp_sexp = NULL;
2651 }
2652 }
2653 if (!openpgp_sexp)
2654 goto leave; /* Note that ERR is still set. */
2655 }
2656
2657 if (openpgp_sexp)
2658 {
2659 /* In most cases the key is encrypted and thus the conversion
2660 function from the OpenPGP format to our internal format will
2661 ask for a passphrase. That passphrase will be returned and
2662 used to protect the key using the same code as for regular
2663 key import. */
2664
2665 xfree (key);
2666 key = NULL;
2667 err = convert_from_openpgp (ctrl, openpgp_sexp, force, grip,
2668 ctrl->server_local->keydesc, cache_nonce,
2669 &key, opt_unattended? NULL : &passphrase);
2670 if (err)
2671 goto leave;
2672 realkeylen = gcry_sexp_canon_len (key, 0, NULL, &err);
2673 if (!realkeylen)
2674 goto leave; /* Invalid canonical encoded S-expression. */
2675 if (passphrase)
2676 {
2677 log_assert (!opt_unattended);
2678 if (!cache_nonce)
2679 {
2680 char buf[12];
2681 gcry_create_nonce (buf, 12);
2682 cache_nonce = bin2hex (buf, 12, NULL);
2683 }
2684 if (cache_nonce
2685 && !agent_put_cache (ctrl, cache_nonce, CACHE_MODE_NONCE,
2686 passphrase, CACHE_TTL_NONCE))
2687 assuan_write_status (ctx, "CACHE_NONCE", cache_nonce);
2688 }
2689 }
2690 else if (opt_unattended)
2691 {
2692 err = set_error (GPG_ERR_ASS_PARAMETER,
2693 "\"--unattended\" may only be used with OpenPGP keys");
2694 goto leave;
2695 }
2696 else
2697 {
2698 if (!force && !agent_key_available (grip))
2699 err = gpg_error (GPG_ERR_EEXIST);
2700 else
2701 {
2702 char *prompt = xtryasprintf
2703 (_("Please enter the passphrase to protect the "
2704 "imported object within the %s system."), GNUPG_NAME);
2705 if (!prompt)
2706 err = gpg_error_from_syserror ();
2707 else
2708 err = agent_ask_new_passphrase (ctrl, prompt, &passphrase);
2709 xfree (prompt);
2710 }
2711 if (err)
2712 goto leave;
2713 }
2714
2715 if (passphrase)
2716 {
2717 err = agent_protect (key, passphrase, &finalkey, &finalkeylen,
2718 ctrl->s2k_count, -1);
2719 if (!err)
2720 err = agent_write_private_key (grip, finalkey, finalkeylen, force,
2721 NULL, NULL, opt_timestamp);
2722 }
2723 else
2724 err = agent_write_private_key (grip, key, realkeylen, force, NULL, NULL,
2725 opt_timestamp);
2726
2727 leave:
2728 gcry_sexp_release (openpgp_sexp);
2729 xfree (finalkey);
2730 xfree (passphrase);
2731 xfree (key);
2732 gcry_cipher_close (cipherhd);
2733 xfree (wrappedkey);
2734 xfree (cache_nonce);
2735 xfree (ctrl->server_local->keydesc);
2736 ctrl->server_local->keydesc = NULL;
2737 return leave_cmd (ctx, err);
2738 }
2739
2740
2741
2742 static const char hlp_export_key[] =
2743 "EXPORT_KEY [--cache-nonce=<nonce>] [--openpgp] <hexstring_with_keygrip>\n"
2744 "\n"
2745 "Export a secret key from the key store. The key will be encrypted\n"
2746 "using the current session's key wrapping key (cf. command KEYWRAP_KEY)\n"
2747 "using the AESWRAP-128 algorithm. The caller needs to retrieve that key\n"
2748 "prior to using this command. The function takes the keygrip as argument.\n"
2749 "\n"
2750 "If --openpgp is used, the secret key material will be exported in RFC 4880\n"
2751 "compatible passphrase-protected form. Without --openpgp, the secret key\n"
2752 "material will be exported in the clear (after prompting the user to unlock\n"
2753 "it, if needed).\n";
2754 static gpg_error_t
cmd_export_key(assuan_context_t ctx,char * line)2755 cmd_export_key (assuan_context_t ctx, char *line)
2756 {
2757 ctrl_t ctrl = assuan_get_pointer (ctx);
2758 gpg_error_t err;
2759 unsigned char grip[20];
2760 gcry_sexp_t s_skey = NULL;
2761 unsigned char *key = NULL;
2762 size_t keylen;
2763 gcry_cipher_hd_t cipherhd = NULL;
2764 unsigned char *wrappedkey = NULL;
2765 size_t wrappedkeylen;
2766 int openpgp;
2767 char *cache_nonce;
2768 char *passphrase = NULL;
2769 unsigned char *shadow_info = NULL;
2770 char *pend;
2771 int c;
2772
2773 if (ctrl->restricted)
2774 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
2775
2776 openpgp = has_option (line, "--openpgp");
2777 cache_nonce = option_value (line, "--cache-nonce");
2778 if (cache_nonce)
2779 {
2780 for (pend = cache_nonce; *pend && !spacep (pend); pend++)
2781 ;
2782 c = *pend;
2783 *pend = '\0';
2784 cache_nonce = xtrystrdup (cache_nonce);
2785 *pend = c;
2786 if (!cache_nonce)
2787 {
2788 err = gpg_error_from_syserror ();
2789 goto leave;
2790 }
2791 }
2792 line = skip_options (line);
2793
2794 if (!ctrl->server_local->export_key)
2795 {
2796 err = set_error (GPG_ERR_MISSING_KEY, "did you run KEYWRAP_KEY ?");
2797 goto leave;
2798 }
2799
2800 err = parse_keygrip (ctx, line, grip);
2801 if (err)
2802 goto leave;
2803
2804 if (agent_key_available (grip))
2805 {
2806 err = gpg_error (GPG_ERR_NO_SECKEY);
2807 goto leave;
2808 }
2809
2810 /* Get the key from the file. With the openpgp flag we also ask for
2811 the passphrase so that we can use it to re-encrypt it. */
2812 err = agent_key_from_file (ctrl, cache_nonce,
2813 ctrl->server_local->keydesc, grip,
2814 &shadow_info, CACHE_MODE_IGNORE, NULL, &s_skey,
2815 openpgp ? &passphrase : NULL);
2816 if (err)
2817 goto leave;
2818 if (shadow_info)
2819 {
2820 /* Key is on a smartcard. */
2821 err = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
2822 goto leave;
2823 }
2824
2825 if (openpgp)
2826 {
2827 /* The openpgp option changes the key format into the OpenPGP
2828 key transfer format. The result is already a padded
2829 canonical S-expression. */
2830 if (!passphrase)
2831 {
2832 err = agent_ask_new_passphrase
2833 (ctrl, _("This key (or subkey) is not protected with a passphrase."
2834 " Please enter a new passphrase to export it."),
2835 &passphrase);
2836 if (err)
2837 goto leave;
2838 }
2839 err = convert_to_openpgp (ctrl, s_skey, passphrase, &key, &keylen);
2840 if (!err && passphrase)
2841 {
2842 if (!cache_nonce)
2843 {
2844 char buf[12];
2845 gcry_create_nonce (buf, 12);
2846 cache_nonce = bin2hex (buf, 12, NULL);
2847 }
2848 if (cache_nonce
2849 && !agent_put_cache (ctrl, cache_nonce, CACHE_MODE_NONCE,
2850 passphrase, CACHE_TTL_NONCE))
2851 {
2852 assuan_write_status (ctx, "CACHE_NONCE", cache_nonce);
2853 xfree (ctrl->server_local->last_cache_nonce);
2854 ctrl->server_local->last_cache_nonce = cache_nonce;
2855 cache_nonce = NULL;
2856 }
2857 }
2858 }
2859 else
2860 {
2861 /* Convert into a canonical S-expression and wrap that. */
2862 err = make_canon_sexp_pad (s_skey, 1, &key, &keylen);
2863 }
2864 if (err)
2865 goto leave;
2866 gcry_sexp_release (s_skey);
2867 s_skey = NULL;
2868
2869 err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
2870 GCRY_CIPHER_MODE_AESWRAP, 0);
2871 if (err)
2872 goto leave;
2873 err = gcry_cipher_setkey (cipherhd,
2874 ctrl->server_local->export_key, KEYWRAP_KEYSIZE);
2875 if (err)
2876 goto leave;
2877
2878 wrappedkeylen = keylen + 8;
2879 wrappedkey = xtrymalloc (wrappedkeylen);
2880 if (!wrappedkey)
2881 {
2882 err = gpg_error_from_syserror ();
2883 goto leave;
2884 }
2885
2886 err = gcry_cipher_encrypt (cipherhd, wrappedkey, wrappedkeylen, key, keylen);
2887 if (err)
2888 goto leave;
2889 xfree (key);
2890 key = NULL;
2891 gcry_cipher_close (cipherhd);
2892 cipherhd = NULL;
2893
2894 assuan_begin_confidential (ctx);
2895 err = assuan_send_data (ctx, wrappedkey, wrappedkeylen);
2896 assuan_end_confidential (ctx);
2897
2898
2899 leave:
2900 xfree (cache_nonce);
2901 xfree (passphrase);
2902 xfree (wrappedkey);
2903 gcry_cipher_close (cipherhd);
2904 xfree (key);
2905 gcry_sexp_release (s_skey);
2906 xfree (ctrl->server_local->keydesc);
2907 ctrl->server_local->keydesc = NULL;
2908 xfree (shadow_info);
2909
2910 return leave_cmd (ctx, err);
2911 }
2912
2913
2914
2915 static const char hlp_delete_key[] =
2916 "DELETE_KEY [--force|--stub-only] <hexstring_with_keygrip>\n"
2917 "\n"
2918 "Delete a secret key from the key store. If --force is used\n"
2919 "and a loopback pinentry is allowed, the agent will not ask\n"
2920 "the user for confirmation. If --stub-only is used the key will\n"
2921 "only be deleted if it is a reference to a token.";
2922 static gpg_error_t
cmd_delete_key(assuan_context_t ctx,char * line)2923 cmd_delete_key (assuan_context_t ctx, char *line)
2924 {
2925 ctrl_t ctrl = assuan_get_pointer (ctx);
2926 gpg_error_t err;
2927 int force, stub_only;
2928 unsigned char grip[20];
2929
2930 if (ctrl->restricted)
2931 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
2932
2933 force = has_option (line, "--force");
2934 stub_only = has_option (line, "--stub-only");
2935 line = skip_options (line);
2936
2937 eventcounter.maybe_key_change++;
2938
2939 /* If the use of a loopback pinentry has been disabled, we assume
2940 * that a silent deletion of keys shall also not be allowed. */
2941 if (!opt.allow_loopback_pinentry)
2942 force = 0;
2943
2944 err = parse_keygrip (ctx, line, grip);
2945 if (err)
2946 goto leave;
2947
2948 err = agent_delete_key (ctrl, ctrl->server_local->keydesc, grip,
2949 force, stub_only);
2950 if (err)
2951 goto leave;
2952
2953 leave:
2954 xfree (ctrl->server_local->keydesc);
2955 ctrl->server_local->keydesc = NULL;
2956
2957 return leave_cmd (ctx, err);
2958 }
2959
2960
2961
2962 #if SIZEOF_TIME_T > SIZEOF_UNSIGNED_LONG
2963 #define KEYTOCARD_TIMESTAMP_FORMAT "(10:created-at10:%010llu))"
2964 #else
2965 #define KEYTOCARD_TIMESTAMP_FORMAT "(10:created-at10:%010lu))"
2966 #endif
2967
2968 static const char hlp_keytocard[] =
2969 "KEYTOCARD [--force] <hexgrip> <serialno> <keyref> [<timestamp>]\n"
2970 "\n"
2971 "TIMESTAMP is required for OpenPGP and defaults to the Epoch. The\n"
2972 "SERIALNO is used for checking; use \"-\" to disable the check.";
2973 static gpg_error_t
cmd_keytocard(assuan_context_t ctx,char * line)2974 cmd_keytocard (assuan_context_t ctx, char *line)
2975 {
2976 ctrl_t ctrl = assuan_get_pointer (ctx);
2977 int force;
2978 gpg_error_t err = 0;
2979 const char *argv[5];
2980 int argc;
2981 unsigned char grip[20];
2982 const char *serialno, *timestamp_str, *keyref;
2983 gcry_sexp_t s_skey = NULL;
2984 unsigned char *keydata;
2985 size_t keydatalen;
2986 unsigned char *shadow_info = NULL;
2987 time_t timestamp;
2988
2989 if (ctrl->restricted)
2990 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
2991
2992 force = has_option (line, "--force");
2993 line = skip_options (line);
2994
2995 argc = split_fields (line, argv, DIM (argv));
2996 if (argc < 3)
2997 {
2998 err = gpg_error (GPG_ERR_MISSING_VALUE);
2999 goto leave;
3000 }
3001
3002 err = parse_keygrip (ctx, argv[0], grip);
3003 if (err)
3004 goto leave;
3005
3006 if (agent_key_available (grip))
3007 {
3008 err =gpg_error (GPG_ERR_NO_SECKEY);
3009 goto leave;
3010 }
3011
3012 /* Note that checking of the s/n is currently not implemented but we
3013 * want to provide a clean interface if we ever implement it. */
3014 serialno = argv[1];
3015 if (!strcmp (serialno, "-"))
3016 serialno = NULL;
3017
3018 keyref = argv[2];
3019
3020 /* FIXME: Default to the creation time as stored in the private
3021 * key. The parameter is here so that gpg can make sure that the
3022 * timestamp as used for key creation (and thus the openPGP
3023 * fingerprint) is used. */
3024 timestamp_str = argc > 3? argv[3] : "19700101T000000";
3025
3026 if ((timestamp = isotime2epoch (timestamp_str)) == (time_t)(-1))
3027 {
3028 err = gpg_error (GPG_ERR_INV_TIME);
3029 goto leave;
3030 }
3031
3032 err = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc, grip,
3033 &shadow_info, CACHE_MODE_IGNORE, NULL,
3034 &s_skey, NULL);
3035 if (err)
3036 goto leave;
3037 if (shadow_info)
3038 {
3039 /* Key is already on a smartcard - we can't extract it. */
3040 err = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
3041 goto leave;
3042 }
3043
3044 /* Note: We can't use make_canon_sexp because we need to allocate a
3045 * few extra bytes for our hack below. */
3046 keydatalen = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0);
3047 keydata = xtrymalloc_secure (keydatalen + 30);
3048 if (keydata == NULL)
3049 {
3050 err = gpg_error_from_syserror ();
3051 goto leave;
3052 }
3053 gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, keydata, keydatalen);
3054 gcry_sexp_release (s_skey);
3055 s_skey = NULL;
3056 keydatalen--; /* Decrement for last '\0'. */
3057 /* Hack to insert the timestamp "created-at" into the private key. */
3058 snprintf (keydata+keydatalen-1, 30, KEYTOCARD_TIMESTAMP_FORMAT, timestamp);
3059 keydatalen += 10 + 19 - 1;
3060
3061 err = divert_writekey (ctrl, force, serialno, keyref, keydata, keydatalen);
3062 xfree (keydata);
3063
3064 leave:
3065 gcry_sexp_release (s_skey);
3066 xfree (shadow_info);
3067 return leave_cmd (ctx, err);
3068 }
3069
3070
3071
3072 static const char hlp_get_secret[] =
3073 "GET_SECRET <key>\n"
3074 "\n"
3075 "Return the secret value stored under KEY\n";
3076 static gpg_error_t
cmd_get_secret(assuan_context_t ctx,char * line)3077 cmd_get_secret (assuan_context_t ctx, char *line)
3078 {
3079 ctrl_t ctrl = assuan_get_pointer (ctx);
3080 gpg_error_t err;
3081 char *p, *key;
3082 char *value = NULL;
3083 size_t valuelen;
3084
3085 /* For now we allow this only for local connections. */
3086 if (ctrl->restricted)
3087 {
3088 err = gpg_error (GPG_ERR_FORBIDDEN);
3089 goto leave;
3090 }
3091
3092 line = skip_options (line);
3093
3094 for (p=line; *p == ' '; p++)
3095 ;
3096 key = p;
3097 p = strchr (key, ' ');
3098 if (p)
3099 {
3100 *p++ = 0;
3101 for (; *p == ' '; p++)
3102 ;
3103 if (*p)
3104 {
3105 err = set_error (GPG_ERR_ASS_PARAMETER, "too many arguments");
3106 goto leave;
3107 }
3108 }
3109 if (!*key)
3110 {
3111 err = set_error (GPG_ERR_ASS_PARAMETER, "no key given");
3112 goto leave;
3113 }
3114
3115
3116 value = agent_get_cache (ctrl, key, CACHE_MODE_DATA);
3117 if (!value)
3118 {
3119 err = gpg_error (GPG_ERR_NO_DATA);
3120 goto leave;
3121 }
3122
3123 valuelen = percent_unescape_inplace (value, 0);
3124 err = assuan_send_data (ctx, value, valuelen);
3125 wipememory (value, valuelen);
3126
3127 leave:
3128 xfree (value);
3129 return leave_cmd (ctx, err);
3130 }
3131
3132
3133 static const char hlp_put_secret[] =
3134 "PUT_SECRET [--clear] <key> <ttl> [<percent_escaped_value>]\n"
3135 "\n"
3136 "This commands stores a secret under KEY in gpg-agent's in-memory\n"
3137 "cache. The TTL must be explicitly given by TTL and the options\n"
3138 "from the configuration file are not used. The value is either given\n"
3139 "percent-escaped as 3rd argument or if not given inquired by gpg-agent\n"
3140 "using the keyword \"SECRET\".\n"
3141 "The option --clear removes the secret from the cache."
3142 "";
3143 static gpg_error_t
cmd_put_secret(assuan_context_t ctx,char * line)3144 cmd_put_secret (assuan_context_t ctx, char *line)
3145 {
3146 ctrl_t ctrl = assuan_get_pointer (ctx);
3147 gpg_error_t err = 0;
3148 int opt_clear;
3149 unsigned char *value = NULL;
3150 size_t valuelen = 0;
3151 size_t n;
3152 char *p, *key, *ttlstr;
3153 unsigned char *valstr;
3154 int ttl;
3155 char *string = NULL;
3156
3157 /* For now we allow this only for local connections. */
3158 if (ctrl->restricted)
3159 {
3160 err = gpg_error (GPG_ERR_FORBIDDEN);
3161 goto leave;
3162 }
3163
3164 opt_clear = has_option (line, "--clear");
3165 line = skip_options (line);
3166
3167 for (p=line; *p == ' '; p++)
3168 ;
3169 key = p;
3170 ttlstr = NULL;
3171 valstr = NULL;
3172 p = strchr (key, ' ');
3173 if (p)
3174 {
3175 *p++ = 0;
3176 for (; *p == ' '; p++)
3177 ;
3178 if (*p)
3179 {
3180 ttlstr = p;
3181 p = strchr (ttlstr, ' ');
3182 if (p)
3183 {
3184 *p++ = 0;
3185 for (; *p == ' '; p++)
3186 ;
3187 if (*p)
3188 valstr = p;
3189 }
3190 }
3191 }
3192 if (!*key)
3193 {
3194 err = set_error (GPG_ERR_ASS_PARAMETER, "no key given");
3195 goto leave;
3196 }
3197 if (!ttlstr || !*ttlstr || !(n = parse_ttl (ttlstr, &ttl)))
3198 {
3199 err = set_error (GPG_ERR_ASS_PARAMETER, "no or invalid TTL given");
3200 goto leave;
3201 }
3202 if (valstr && opt_clear)
3203 {
3204 err = set_error (GPG_ERR_ASS_PARAMETER,
3205 "value not expected with --clear");
3206 goto leave;
3207 }
3208
3209 if (valstr)
3210 {
3211 valuelen = percent_unescape_inplace (valstr, 0);
3212 value = NULL;
3213 }
3214 else /* Inquire the value to store */
3215 {
3216 err = print_assuan_status (ctx, "INQUIRE_MAXLEN", "%u",MAXLEN_PUT_SECRET);
3217 if (!err)
3218 err = assuan_inquire (ctx, "SECRET",
3219 &value, &valuelen, MAXLEN_PUT_SECRET);
3220 if (err)
3221 goto leave;
3222 }
3223
3224 /* Our cache expects strings and thus we need to turn the buffer
3225 * into a string. Instead of resorting to base64 encoding we use a
3226 * special percent escaping which only quoted the Nul and the
3227 * percent character. */
3228 string = percent_data_escape (0, NULL, value? value : valstr, valuelen);
3229 if (!string)
3230 {
3231 err = gpg_error_from_syserror ();
3232 goto leave;
3233 }
3234 err = agent_put_cache (ctrl, key, CACHE_MODE_DATA, string, ttl);
3235
3236
3237 leave:
3238 if (string)
3239 {
3240 wipememory (string, strlen (string));
3241 xfree (string);
3242 }
3243 if (value)
3244 {
3245 wipememory (value, valuelen);
3246 xfree (value);
3247 }
3248 return leave_cmd (ctx, err);
3249 }
3250
3251
3252
3253 static const char hlp_keytotpm[] =
3254 "KEYTOTPM <hexstring_with_keygrip>\n"
3255 "\n";
3256 static gpg_error_t
cmd_keytotpm(assuan_context_t ctx,char * line)3257 cmd_keytotpm (assuan_context_t ctx, char *line)
3258 {
3259 ctrl_t ctrl = assuan_get_pointer (ctx);
3260 gpg_error_t err = 0;
3261 unsigned char grip[20];
3262 gcry_sexp_t s_skey;
3263 unsigned char *shadow_info = NULL;
3264
3265 if (ctrl->restricted)
3266 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
3267
3268 err = parse_keygrip (ctx, line, grip);
3269 if (err)
3270 goto leave;
3271
3272 if (agent_key_available (grip))
3273 {
3274 err =gpg_error (GPG_ERR_NO_SECKEY);
3275 goto leave;
3276 }
3277
3278 err = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc, grip,
3279 &shadow_info, CACHE_MODE_IGNORE, NULL,
3280 &s_skey, NULL);
3281 if (err)
3282 {
3283 xfree (shadow_info);
3284 goto leave;
3285 }
3286 if (shadow_info)
3287 {
3288 /* Key is on a TPM or smartcard already. */
3289 xfree (shadow_info);
3290 gcry_sexp_release (s_skey);
3291 err = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
3292 goto leave;
3293 }
3294
3295 err = divert_tpm2_writekey (ctrl, grip, s_skey);
3296 gcry_sexp_release (s_skey);
3297
3298 leave:
3299 return leave_cmd (ctx, err);
3300 }
3301
3302
3303
3304 static const char hlp_getval[] =
3305 "GETVAL <key>\n"
3306 "\n"
3307 "Return the value for KEY from the special environment as created by\n"
3308 "PUTVAL.";
3309 static gpg_error_t
cmd_getval(assuan_context_t ctx,char * line)3310 cmd_getval (assuan_context_t ctx, char *line)
3311 {
3312 ctrl_t ctrl = assuan_get_pointer (ctx);
3313 int rc = 0;
3314 char *key = NULL;
3315 char *p;
3316 struct putval_item_s *vl;
3317
3318 if (ctrl->restricted)
3319 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
3320
3321 for (p=line; *p == ' '; p++)
3322 ;
3323 key = p;
3324 p = strchr (key, ' ');
3325 if (p)
3326 {
3327 *p++ = 0;
3328 for (; *p == ' '; p++)
3329 ;
3330 if (*p)
3331 return set_error (GPG_ERR_ASS_PARAMETER, "too many arguments");
3332 }
3333 if (!*key)
3334 return set_error (GPG_ERR_ASS_PARAMETER, "no key given");
3335
3336
3337 for (vl=putval_list; vl; vl = vl->next)
3338 if ( !strcmp (vl->d, key) )
3339 break;
3340
3341 if (vl) /* Got an entry. */
3342 rc = assuan_send_data (ctx, vl->d+vl->off, vl->len);
3343 else
3344 return gpg_error (GPG_ERR_NO_DATA);
3345
3346 return leave_cmd (ctx, rc);
3347 }
3348
3349
3350 static const char hlp_putval[] =
3351 "PUTVAL <key> [<percent_escaped_value>]\n"
3352 "\n"
3353 "The gpg-agent maintains a kind of environment which may be used to\n"
3354 "store key/value pairs in it, so that they can be retrieved later.\n"
3355 "This may be used by helper daemons to daemonize themself on\n"
3356 "invocation and register them with gpg-agent. Callers of the\n"
3357 "daemon's service may now first try connect to get the information\n"
3358 "for that service from gpg-agent through the GETVAL command and then\n"
3359 "try to connect to that daemon. Only if that fails they may start\n"
3360 "an own instance of the service daemon. \n"
3361 "\n"
3362 "KEY is an arbitrary symbol with the same syntax rules as keys\n"
3363 "for shell environment variables. PERCENT_ESCAPED_VALUE is the\n"
3364 "corresponding value; they should be similar to the values of\n"
3365 "envronment variables but gpg-agent does not enforce any\n"
3366 "restrictions. If that value is not given any value under that KEY\n"
3367 "is removed from this special environment.";
3368 static gpg_error_t
cmd_putval(assuan_context_t ctx,char * line)3369 cmd_putval (assuan_context_t ctx, char *line)
3370 {
3371 ctrl_t ctrl = assuan_get_pointer (ctx);
3372 int rc = 0;
3373 char *key = NULL;
3374 char *value = NULL;
3375 size_t valuelen = 0;
3376 char *p;
3377 struct putval_item_s *vl, *vlprev;
3378
3379 if (ctrl->restricted)
3380 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
3381
3382 for (p=line; *p == ' '; p++)
3383 ;
3384 key = p;
3385 p = strchr (key, ' ');
3386 if (p)
3387 {
3388 *p++ = 0;
3389 for (; *p == ' '; p++)
3390 ;
3391 if (*p)
3392 {
3393 value = p;
3394 p = strchr (value, ' ');
3395 if (p)
3396 *p = 0;
3397 valuelen = percent_plus_unescape_inplace (value, 0);
3398 }
3399 }
3400 if (!*key)
3401 return set_error (GPG_ERR_ASS_PARAMETER, "no key given");
3402
3403
3404 for (vl=putval_list,vlprev=NULL; vl; vlprev=vl, vl = vl->next)
3405 if ( !strcmp (vl->d, key) )
3406 break;
3407
3408 if (vl) /* Delete old entry. */
3409 {
3410 if (vlprev)
3411 vlprev->next = vl->next;
3412 else
3413 putval_list = vl->next;
3414 xfree (vl);
3415 }
3416
3417 if (valuelen) /* Add entry. */
3418 {
3419 vl = xtrymalloc (sizeof *vl + strlen (key) + valuelen);
3420 if (!vl)
3421 rc = gpg_error_from_syserror ();
3422 else
3423 {
3424 vl->len = valuelen;
3425 vl->off = strlen (key) + 1;
3426 strcpy (vl->d, key);
3427 memcpy (vl->d + vl->off, value, valuelen);
3428 vl->next = putval_list;
3429 putval_list = vl;
3430 }
3431 }
3432
3433 return leave_cmd (ctx, rc);
3434 }
3435
3436
3437
3438
3439 static const char hlp_updatestartuptty[] =
3440 "UPDATESTARTUPTTY\n"
3441 "\n"
3442 "Set startup TTY and X11 DISPLAY variables to the values of this\n"
3443 "session. This command is useful to pull future pinentries to\n"
3444 "another screen. It is only required because there is no way in the\n"
3445 "ssh-agent protocol to convey this information.";
3446 static gpg_error_t
cmd_updatestartuptty(assuan_context_t ctx,char * line)3447 cmd_updatestartuptty (assuan_context_t ctx, char *line)
3448 {
3449 ctrl_t ctrl = assuan_get_pointer (ctx);
3450 gpg_error_t err = 0;
3451 session_env_t se;
3452 char *lc_ctype = NULL;
3453 char *lc_messages = NULL;
3454 int iterator;
3455 const char *name;
3456
3457 (void)line;
3458
3459 if (ctrl->restricted)
3460 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
3461
3462 se = session_env_new ();
3463 if (!se)
3464 err = gpg_error_from_syserror ();
3465
3466 iterator = 0;
3467 while (!err && (name = session_env_list_stdenvnames (&iterator, NULL)))
3468 {
3469 const char *value = session_env_getenv (ctrl->session_env, name);
3470 if (value)
3471 err = session_env_setenv (se, name, value);
3472 }
3473
3474 if (!err && ctrl->lc_ctype)
3475 if (!(lc_ctype = xtrystrdup (ctrl->lc_ctype)))
3476 err = gpg_error_from_syserror ();
3477
3478 if (!err && ctrl->lc_messages)
3479 if (!(lc_messages = xtrystrdup (ctrl->lc_messages)))
3480 err = gpg_error_from_syserror ();
3481
3482 if (err)
3483 {
3484 session_env_release (se);
3485 xfree (lc_ctype);
3486 xfree (lc_messages);
3487 }
3488 else
3489 {
3490 session_env_release (opt.startup_env);
3491 opt.startup_env = se;
3492 xfree (opt.startup_lc_ctype);
3493 opt.startup_lc_ctype = lc_ctype;
3494 xfree (opt.startup_lc_messages);
3495 opt.startup_lc_messages = lc_messages;
3496 }
3497
3498 return err;
3499 }
3500
3501
3502
3503 static const char hlp_killagent[] =
3504 "KILLAGENT\n"
3505 "\n"
3506 "Stop the agent.";
3507 static gpg_error_t
cmd_killagent(assuan_context_t ctx,char * line)3508 cmd_killagent (assuan_context_t ctx, char *line)
3509 {
3510 ctrl_t ctrl = assuan_get_pointer (ctx);
3511
3512 (void)line;
3513
3514 if (ctrl->restricted)
3515 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
3516
3517 ctrl->server_local->stopme = 1;
3518 assuan_set_flag (ctx, ASSUAN_FORCE_CLOSE, 1);
3519 return 0;
3520 }
3521
3522
3523 static const char hlp_reloadagent[] =
3524 "RELOADAGENT\n"
3525 "\n"
3526 "This command is an alternative to SIGHUP\n"
3527 "to reload the configuration.";
3528 static gpg_error_t
cmd_reloadagent(assuan_context_t ctx,char * line)3529 cmd_reloadagent (assuan_context_t ctx, char *line)
3530 {
3531 ctrl_t ctrl = assuan_get_pointer (ctx);
3532
3533 (void)line;
3534
3535 if (ctrl->restricted)
3536 return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
3537
3538 agent_sighup_action ();
3539 return 0;
3540 }
3541
3542
3543
3544 static const char hlp_getinfo[] =
3545 "GETINFO <what>\n"
3546 "\n"
3547 "Multipurpose function to return a variety of information.\n"
3548 "Supported values for WHAT are:\n"
3549 "\n"
3550 " version - Return the version of the program.\n"
3551 " pid - Return the process id of the server.\n"
3552 " socket_name - Return the name of the socket.\n"
3553 " ssh_socket_name - Return the name of the ssh socket.\n"
3554 " scd_running - Return OK if the SCdaemon is already running.\n"
3555 " s2k_time - Return the time in milliseconds required for S2K.\n"
3556 " s2k_count - Return the standard S2K count.\n"
3557 " s2k_count_cal - Return the calibrated S2K count.\n"
3558 " std_env_names - List the names of the standard environment.\n"
3559 " std_session_env - List the standard session environment.\n"
3560 " std_startup_env - List the standard startup environment.\n"
3561 " getenv NAME - Return value of envvar NAME.\n"
3562 " connections - Return number of active connections.\n"
3563 " jent_active - Returns OK if Libgcrypt's JENT is active.\n"
3564 " restricted - Returns OK if the connection is in restricted mode.\n"
3565 " cmd_has_option CMD OPT\n"
3566 " - Returns OK if command CMD has option OPT.\n";
3567 static gpg_error_t
cmd_getinfo(assuan_context_t ctx,char * line)3568 cmd_getinfo (assuan_context_t ctx, char *line)
3569 {
3570 ctrl_t ctrl = assuan_get_pointer (ctx);
3571 int rc = 0;
3572
3573 if (!strcmp (line, "version"))
3574 {
3575 const char *s = VERSION;
3576 rc = assuan_send_data (ctx, s, strlen (s));
3577 }
3578 else if (!strncmp (line, "cmd_has_option", 14)
3579 && (line[14] == ' ' || line[14] == '\t' || !line[14]))
3580 {
3581 char *cmd, *cmdopt;
3582 line += 14;
3583 while (*line == ' ' || *line == '\t')
3584 line++;
3585 if (!*line)
3586 rc = gpg_error (GPG_ERR_MISSING_VALUE);
3587 else
3588 {
3589 cmd = line;
3590 while (*line && (*line != ' ' && *line != '\t'))
3591 line++;
3592 if (!*line)
3593 rc = gpg_error (GPG_ERR_MISSING_VALUE);
3594 else
3595 {
3596 *line++ = 0;
3597 while (*line == ' ' || *line == '\t')
3598 line++;
3599 if (!*line)
3600 rc = gpg_error (GPG_ERR_MISSING_VALUE);
3601 else
3602 {
3603 cmdopt = line;
3604 if (!command_has_option (cmd, cmdopt))
3605 rc = gpg_error (GPG_ERR_FALSE);
3606 }
3607 }
3608 }
3609 }
3610 else if (!strcmp (line, "s2k_count"))
3611 {
3612 char numbuf[50];
3613
3614 snprintf (numbuf, sizeof numbuf, "%lu", get_standard_s2k_count ());
3615 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
3616 }
3617 else if (!strcmp (line, "restricted"))
3618 {
3619 rc = ctrl->restricted? 0 : gpg_error (GPG_ERR_FALSE);
3620 }
3621 else if (ctrl->restricted)
3622 {
3623 rc = gpg_error (GPG_ERR_FORBIDDEN);
3624 }
3625 /* All sub-commands below are not allowed in restricted mode. */
3626 else if (!strcmp (line, "pid"))
3627 {
3628 char numbuf[50];
3629
3630 snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
3631 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
3632 }
3633 else if (!strcmp (line, "socket_name"))
3634 {
3635 const char *s = get_agent_socket_name ();
3636
3637 if (s)
3638 rc = assuan_send_data (ctx, s, strlen (s));
3639 else
3640 rc = gpg_error (GPG_ERR_NO_DATA);
3641 }
3642 else if (!strcmp (line, "ssh_socket_name"))
3643 {
3644 const char *s = get_agent_ssh_socket_name ();
3645
3646 if (s)
3647 rc = assuan_send_data (ctx, s, strlen (s));
3648 else
3649 rc = gpg_error (GPG_ERR_NO_DATA);
3650 }
3651 else if (!strcmp (line, "scd_running"))
3652 {
3653 rc = agent_daemon_check_running (DAEMON_SCD)? 0:gpg_error (GPG_ERR_FALSE);
3654 }
3655 else if (!strcmp (line, "std_env_names"))
3656 {
3657 int iterator;
3658 const char *name;
3659
3660 iterator = 0;
3661 while ((name = session_env_list_stdenvnames (&iterator, NULL)))
3662 {
3663 rc = assuan_send_data (ctx, name, strlen (name)+1);
3664 if (!rc)
3665 rc = assuan_send_data (ctx, NULL, 0);
3666 if (rc)
3667 break;
3668 }
3669 }
3670 else if (!strcmp (line, "std_session_env")
3671 || !strcmp (line, "std_startup_env"))
3672 {
3673 int iterator;
3674 const char *name, *value;
3675 char *string;
3676
3677 iterator = 0;
3678 while ((name = session_env_list_stdenvnames (&iterator, NULL)))
3679 {
3680 value = session_env_getenv_or_default
3681 (line[5] == 't'? opt.startup_env:ctrl->session_env, name, NULL);
3682 if (value)
3683 {
3684 string = xtryasprintf ("%s=%s", name, value);
3685 if (!string)
3686 rc = gpg_error_from_syserror ();
3687 else
3688 {
3689 rc = assuan_send_data (ctx, string, strlen (string)+1);
3690 if (!rc)
3691 rc = assuan_send_data (ctx, NULL, 0);
3692 }
3693 if (rc)
3694 break;
3695 }
3696 }
3697 }
3698 else if (!strncmp (line, "getenv", 6)
3699 && (line[6] == ' ' || line[6] == '\t' || !line[6]))
3700 {
3701 line += 6;
3702 while (*line == ' ' || *line == '\t')
3703 line++;
3704 if (!*line)
3705 rc = gpg_error (GPG_ERR_MISSING_VALUE);
3706 else
3707 {
3708 const char *s = getenv (line);
3709 if (!s)
3710 rc = set_error (GPG_ERR_NOT_FOUND, "No such envvar");
3711 else
3712 rc = assuan_send_data (ctx, s, strlen (s));
3713 }
3714 }
3715 else if (!strcmp (line, "connections"))
3716 {
3717 char numbuf[20];
3718
3719 snprintf (numbuf, sizeof numbuf, "%d",
3720 get_agent_active_connection_count ());
3721 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
3722 }
3723 else if (!strcmp (line, "jent_active"))
3724 {
3725 char *buf;
3726 const char *fields[5];
3727
3728 buf = gcry_get_config (0, "rng-type");
3729 if (buf
3730 && split_fields_colon (buf, fields, DIM (fields)) >= 5
3731 && atoi (fields[4]) > 0)
3732 rc = 0;
3733 else
3734 rc = gpg_error (GPG_ERR_FALSE);
3735 gcry_free (buf);
3736 }
3737 else if (!strcmp (line, "s2k_count_cal"))
3738 {
3739 char numbuf[50];
3740
3741 snprintf (numbuf, sizeof numbuf, "%lu", get_calibrated_s2k_count ());
3742 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
3743 }
3744 else if (!strcmp (line, "s2k_time"))
3745 {
3746 char numbuf[50];
3747
3748 snprintf (numbuf, sizeof numbuf, "%lu", get_standard_s2k_time ());
3749 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
3750 }
3751 else
3752 rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
3753 return rc;
3754 }
3755
3756
3757
3758 /* This function is called by Libassuan to parse the OPTION command.
3759 It has been registered similar to the other Assuan commands. */
3760 static gpg_error_t
option_handler(assuan_context_t ctx,const char * key,const char * value)3761 option_handler (assuan_context_t ctx, const char *key, const char *value)
3762 {
3763 ctrl_t ctrl = assuan_get_pointer (ctx);
3764 gpg_error_t err = 0;
3765
3766 if (!strcmp (key, "agent-awareness"))
3767 {
3768 /* The value is a version string telling us of which agent
3769 version the caller is aware of. */
3770 ctrl->server_local->allow_fully_canceled =
3771 gnupg_compare_version (value, "2.1.0");
3772 }
3773 else if (ctrl->restricted)
3774 {
3775 err = gpg_error (GPG_ERR_FORBIDDEN);
3776 }
3777 /* All options below are not allowed in restricted mode. */
3778 else if (!strcmp (key, "putenv"))
3779 {
3780 /* Change the session's environment to be used for the
3781 Pinentry. Valid values are:
3782 <NAME> Delete envvar NAME
3783 <KEY>= Set envvar NAME to the empty string
3784 <KEY>=<VALUE> Set envvar NAME to VALUE
3785 */
3786 err = session_env_putenv (ctrl->session_env, value);
3787 }
3788 else if (!strcmp (key, "display"))
3789 {
3790 err = session_env_setenv (ctrl->session_env, "DISPLAY", value);
3791 }
3792 else if (!strcmp (key, "ttyname"))
3793 {
3794 if (!opt.keep_tty)
3795 err = session_env_setenv (ctrl->session_env, "GPG_TTY", value);
3796 }
3797 else if (!strcmp (key, "ttytype"))
3798 {
3799 if (!opt.keep_tty)
3800 err = session_env_setenv (ctrl->session_env, "TERM", value);
3801 }
3802 else if (!strcmp (key, "lc-ctype"))
3803 {
3804 if (ctrl->lc_ctype)
3805 xfree (ctrl->lc_ctype);
3806 ctrl->lc_ctype = xtrystrdup (value);
3807 if (!ctrl->lc_ctype)
3808 return out_of_core ();
3809 }
3810 else if (!strcmp (key, "lc-messages"))
3811 {
3812 if (ctrl->lc_messages)
3813 xfree (ctrl->lc_messages);
3814 ctrl->lc_messages = xtrystrdup (value);
3815 if (!ctrl->lc_messages)
3816 return out_of_core ();
3817 }
3818 else if (!strcmp (key, "xauthority"))
3819 {
3820 err = session_env_setenv (ctrl->session_env, "XAUTHORITY", value);
3821 }
3822 else if (!strcmp (key, "pinentry-user-data"))
3823 {
3824 err = session_env_setenv (ctrl->session_env, "PINENTRY_USER_DATA", value);
3825 }
3826 else if (!strcmp (key, "use-cache-for-signing"))
3827 ctrl->server_local->use_cache_for_signing = *value? !!atoi (value) : 0;
3828 else if (!strcmp (key, "allow-pinentry-notify"))
3829 ctrl->server_local->allow_pinentry_notify = 1;
3830 else if (!strcmp (key, "pinentry-mode"))
3831 {
3832 int tmp = parse_pinentry_mode (value);
3833 if (tmp == -1)
3834 err = gpg_error (GPG_ERR_INV_VALUE);
3835 else if (tmp == PINENTRY_MODE_LOOPBACK && !opt.allow_loopback_pinentry)
3836 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
3837 else
3838 ctrl->pinentry_mode = tmp;
3839 }
3840 else if (!strcmp (key, "cache-ttl-opt-preset"))
3841 {
3842 ctrl->cache_ttl_opt_preset = *value? atoi (value) : 0;
3843 }
3844 else if (!strcmp (key, "s2k-count"))
3845 {
3846 ctrl->s2k_count = *value? strtoul(value, NULL, 10) : 0;
3847 if (ctrl->s2k_count && ctrl->s2k_count < 65536)
3848 {
3849 ctrl->s2k_count = 0;
3850 }
3851 }
3852 else if (!strcmp (key, "pretend-request-origin"))
3853 {
3854 log_assert (!ctrl->restricted);
3855 switch (parse_request_origin (value))
3856 {
3857 case REQUEST_ORIGIN_LOCAL: ctrl->restricted = 0; break;
3858 case REQUEST_ORIGIN_REMOTE: ctrl->restricted = 1; break;
3859 case REQUEST_ORIGIN_BROWSER: ctrl->restricted = 2; break;
3860 default:
3861 err = gpg_error (GPG_ERR_INV_VALUE);
3862 /* Better pretend to be remote in case of a bad value. */
3863 ctrl->restricted = 1;
3864 break;
3865 }
3866 }
3867 else
3868 err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
3869
3870 return err;
3871 }
3872
3873
3874
3875
3876 /* Called by libassuan after all commands. ERR is the error from the
3877 last assuan operation and not the one returned from the command. */
3878 static void
post_cmd_notify(assuan_context_t ctx,gpg_error_t err)3879 post_cmd_notify (assuan_context_t ctx, gpg_error_t err)
3880 {
3881 ctrl_t ctrl = assuan_get_pointer (ctx);
3882
3883 (void)err;
3884
3885 /* Switch off any I/O monitor controlled logging pausing. */
3886 ctrl->server_local->pause_io_logging = 0;
3887 }
3888
3889
3890 /* This function is called by libassuan for all I/O. We use it here
3891 to disable logging for the GETEVENTCOUNTER commands. This is so
3892 that the debug output won't get cluttered by this primitive
3893 command. */
3894 static unsigned int
io_monitor(assuan_context_t ctx,void * hook,int direction,const char * line,size_t linelen)3895 io_monitor (assuan_context_t ctx, void *hook, int direction,
3896 const char *line, size_t linelen)
3897 {
3898 ctrl_t ctrl = assuan_get_pointer (ctx);
3899
3900 (void) hook;
3901
3902 /* We want to suppress all Assuan log messages for connections from
3903 * self. However, assuan_get_pid works only after
3904 * assuan_accept. Now, assuan_accept already logs a line ending with
3905 * the process id. We use this hack here to get the peers pid so
3906 * that we can compare it to our pid. We should add an assuan
3907 * function to return the pid for a file descriptor and use that to
3908 * detect connections to self. */
3909 if (ctx && !ctrl->server_local->greeting_seen
3910 && direction == ASSUAN_IO_TO_PEER)
3911 {
3912 ctrl->server_local->greeting_seen = 1;
3913 if (linelen > 32
3914 && !strncmp (line, "OK Pleased to meet you, process ", 32)
3915 && strtoul (line+32, NULL, 10) == getpid ())
3916 return ASSUAN_IO_MONITOR_NOLOG;
3917 }
3918
3919
3920 /* Do not log self-connections. This makes the log cleaner because
3921 * we won't see the check-our-own-socket calls. */
3922 if (ctx && ctrl->server_local->connect_from_self)
3923 return ASSUAN_IO_MONITOR_NOLOG;
3924
3925 /* Note that we only check for the uppercase name. This allows the user to
3926 see the logging for debugging if using a non-upercase command
3927 name. */
3928 if (ctx && direction == ASSUAN_IO_FROM_PEER
3929 && linelen >= 15
3930 && !strncmp (line, "GETEVENTCOUNTER", 15)
3931 && (linelen == 15 || spacep (line+15)))
3932 {
3933 ctrl->server_local->pause_io_logging = 1;
3934 }
3935
3936 return ctrl->server_local->pause_io_logging? ASSUAN_IO_MONITOR_NOLOG : 0;
3937 }
3938
3939
3940 /* Return true if the command CMD implements the option OPT. */
3941 static int
command_has_option(const char * cmd,const char * cmdopt)3942 command_has_option (const char *cmd, const char *cmdopt)
3943 {
3944 if (!strcmp (cmd, "GET_PASSPHRASE"))
3945 {
3946 if (!strcmp (cmdopt, "repeat"))
3947 return 1;
3948 if (!strcmp (cmdopt, "newsymkey"))
3949 return 1;
3950 }
3951
3952 return 0;
3953 }
3954
3955
3956 /* Tell Libassuan about our commands. Also register the other Assuan
3957 handlers. */
3958 static int
register_commands(assuan_context_t ctx)3959 register_commands (assuan_context_t ctx)
3960 {
3961 static struct {
3962 const char *name;
3963 assuan_handler_t handler;
3964 const char * const help;
3965 } table[] = {
3966 { "GETEVENTCOUNTER",cmd_geteventcounter, hlp_geteventcounter },
3967 { "ISTRUSTED", cmd_istrusted, hlp_istrusted },
3968 { "HAVEKEY", cmd_havekey, hlp_havekey },
3969 { "KEYINFO", cmd_keyinfo, hlp_keyinfo },
3970 { "SIGKEY", cmd_sigkey, hlp_sigkey },
3971 { "SETKEY", cmd_sigkey, hlp_sigkey },
3972 { "SETKEYDESC", cmd_setkeydesc,hlp_setkeydesc },
3973 { "SETHASH", cmd_sethash, hlp_sethash },
3974 { "PKSIGN", cmd_pksign, hlp_pksign },
3975 { "PKDECRYPT", cmd_pkdecrypt, hlp_pkdecrypt },
3976 { "GENKEY", cmd_genkey, hlp_genkey },
3977 { "READKEY", cmd_readkey, hlp_readkey },
3978 { "GET_PASSPHRASE", cmd_get_passphrase, hlp_get_passphrase },
3979 { "PRESET_PASSPHRASE", cmd_preset_passphrase, hlp_preset_passphrase },
3980 { "CLEAR_PASSPHRASE", cmd_clear_passphrase, hlp_clear_passphrase },
3981 { "GET_CONFIRMATION", cmd_get_confirmation, hlp_get_confirmation },
3982 { "LISTTRUSTED", cmd_listtrusted, hlp_listtrusted },
3983 { "MARKTRUSTED", cmd_marktrusted, hlp_martrusted },
3984 { "LEARN", cmd_learn, hlp_learn },
3985 { "PASSWD", cmd_passwd, hlp_passwd },
3986 { "INPUT", NULL },
3987 { "OUTPUT", NULL },
3988 { "SCD", cmd_scd, hlp_scd },
3989 { "KEYWRAP_KEY", cmd_keywrap_key, hlp_keywrap_key },
3990 { "IMPORT_KEY", cmd_import_key, hlp_import_key },
3991 { "EXPORT_KEY", cmd_export_key, hlp_export_key },
3992 { "DELETE_KEY", cmd_delete_key, hlp_delete_key },
3993 { "GET_SECRET", cmd_get_secret, hlp_get_secret },
3994 { "PUT_SECRET", cmd_put_secret, hlp_put_secret },
3995 { "GETVAL", cmd_getval, hlp_getval },
3996 { "PUTVAL", cmd_putval, hlp_putval },
3997 { "UPDATESTARTUPTTY", cmd_updatestartuptty, hlp_updatestartuptty },
3998 { "KILLAGENT", cmd_killagent, hlp_killagent },
3999 { "RELOADAGENT", cmd_reloadagent,hlp_reloadagent },
4000 { "GETINFO", cmd_getinfo, hlp_getinfo },
4001 { "KEYTOCARD", cmd_keytocard, hlp_keytocard },
4002 { "KEYTOTPM", cmd_keytotpm, hlp_keytotpm },
4003 { NULL }
4004 };
4005 int i, rc;
4006
4007 for (i=0; table[i].name; i++)
4008 {
4009 rc = assuan_register_command (ctx, table[i].name, table[i].handler,
4010 table[i].help);
4011 if (rc)
4012 return rc;
4013 }
4014 assuan_register_post_cmd_notify (ctx, post_cmd_notify);
4015 assuan_register_reset_notify (ctx, reset_notify);
4016 assuan_register_option_handler (ctx, option_handler);
4017 return 0;
4018 }
4019
4020
4021 /* Startup the server. If LISTEN_FD and FD is given as -1, this is a
4022 simple piper server, otherwise it is a regular server. CTRL is the
4023 control structure for this connection; it has only the basic
4024 initialization. */
4025 void
start_command_handler(ctrl_t ctrl,gnupg_fd_t listen_fd,gnupg_fd_t fd)4026 start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd)
4027 {
4028 int rc;
4029 assuan_context_t ctx = NULL;
4030
4031 if (ctrl->restricted)
4032 {
4033 if (agent_copy_startup_env (ctrl))
4034 return;
4035 }
4036
4037 rc = assuan_new (&ctx);
4038 if (rc)
4039 {
4040 log_error ("failed to allocate assuan context: %s\n", gpg_strerror (rc));
4041 agent_exit (2);
4042 }
4043
4044 if (listen_fd == GNUPG_INVALID_FD && fd == GNUPG_INVALID_FD)
4045 {
4046 assuan_fd_t filedes[2];
4047
4048 filedes[0] = assuan_fdopen (0);
4049 filedes[1] = assuan_fdopen (1);
4050 rc = assuan_init_pipe_server (ctx, filedes);
4051 }
4052 else if (listen_fd != GNUPG_INVALID_FD)
4053 {
4054 rc = assuan_init_socket_server (ctx, listen_fd, 0);
4055 /* FIXME: Need to call assuan_sock_set_nonce for Windows. But
4056 this branch is currently not used. */
4057 }
4058 else
4059 {
4060 rc = assuan_init_socket_server (ctx, fd, ASSUAN_SOCKET_SERVER_ACCEPTED);
4061 }
4062 if (rc)
4063 {
4064 log_error ("failed to initialize the server: %s\n",
4065 gpg_strerror(rc));
4066 agent_exit (2);
4067 }
4068 rc = register_commands (ctx);
4069 if (rc)
4070 {
4071 log_error ("failed to register commands with Assuan: %s\n",
4072 gpg_strerror(rc));
4073 agent_exit (2);
4074 }
4075
4076 assuan_set_pointer (ctx, ctrl);
4077 ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
4078 ctrl->server_local->assuan_ctx = ctx;
4079 ctrl->server_local->use_cache_for_signing = 1;
4080
4081 ctrl->digest.data = NULL;
4082 ctrl->digest.raw_value = 0;
4083 ctrl->digest.is_pss = 0;
4084
4085 assuan_set_io_monitor (ctx, io_monitor, NULL);
4086 agent_set_progress_cb (progress_cb, ctrl);
4087
4088 for (;;)
4089 {
4090 assuan_peercred_t client_creds; /* Note: Points into CTX. */
4091 pid_t pid;
4092
4093 rc = assuan_accept (ctx);
4094 if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1)
4095 {
4096 break;
4097 }
4098 else if (rc)
4099 {
4100 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
4101 break;
4102 }
4103
4104 rc = assuan_get_peercred (ctx, &client_creds);
4105 if (rc)
4106 {
4107 /* Note that on Windows we don't get the peer credentials
4108 * and thus we silence the error. */
4109 if (listen_fd == GNUPG_INVALID_FD && fd == GNUPG_INVALID_FD)
4110 ;
4111 #ifdef HAVE_W32_SYSTEM
4112 else if (gpg_err_code (rc) == GPG_ERR_ASS_GENERAL)
4113 ;
4114 #endif
4115 else
4116 log_info ("Assuan get_peercred failed: %s\n", gpg_strerror (rc));
4117 pid = assuan_get_pid (ctx);
4118 ctrl->client_uid = -1;
4119 }
4120 else
4121 {
4122 #ifdef HAVE_W32_SYSTEM
4123 pid = assuan_get_pid (ctx);
4124 ctrl->client_uid = -1;
4125 #else
4126 pid = client_creds->pid;
4127 ctrl->client_uid = client_creds->uid;
4128 #endif
4129 }
4130 ctrl->client_pid = (pid == ASSUAN_INVALID_PID)? 0 : (unsigned long)pid;
4131 ctrl->server_local->connect_from_self = (pid == getpid ());
4132
4133 rc = assuan_process (ctx);
4134 if (rc)
4135 {
4136 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
4137 continue;
4138 }
4139 }
4140
4141 /* Clear the keyinfo cache. */
4142 agent_card_free_keyinfo (ctrl->server_local->last_card_keyinfo.ki);
4143
4144 /* Reset the nonce caches. */
4145 clear_nonce_cache (ctrl);
4146
4147 /* Reset the SCD if needed. */
4148 agent_reset_daemon (ctrl);
4149
4150 /* Reset the pinentry (in case of popup messages). */
4151 agent_reset_query (ctrl);
4152
4153 /* Cleanup. */
4154 assuan_release (ctx);
4155 xfree (ctrl->server_local->keydesc);
4156 xfree (ctrl->server_local->import_key);
4157 xfree (ctrl->server_local->export_key);
4158 if (ctrl->server_local->stopme)
4159 agent_exit (0);
4160 xfree (ctrl->server_local);
4161 ctrl->server_local = NULL;
4162 }
4163
4164
4165 /* Helper for the pinentry loopback mode. It merely passes the
4166 parameters on to the client. */
4167 gpg_error_t
pinentry_loopback(ctrl_t ctrl,const char * keyword,unsigned char ** buffer,size_t * size,size_t max_length)4168 pinentry_loopback(ctrl_t ctrl, const char *keyword,
4169 unsigned char **buffer, size_t *size,
4170 size_t max_length)
4171 {
4172 gpg_error_t rc;
4173 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
4174
4175 rc = print_assuan_status (ctx, "INQUIRE_MAXLEN", "%zu", max_length);
4176 if (rc)
4177 return rc;
4178
4179 assuan_begin_confidential (ctx);
4180 rc = assuan_inquire (ctx, keyword, buffer, size, max_length);
4181 assuan_end_confidential (ctx);
4182 return rc;
4183 }
4184
4185 /* Helper for the pinentry loopback mode to ask confirmation
4186 or just to show message. */
4187 gpg_error_t
pinentry_loopback_confirm(ctrl_t ctrl,const char * desc,int ask_confirmation,const char * ok,const char * notok)4188 pinentry_loopback_confirm (ctrl_t ctrl, const char *desc,
4189 int ask_confirmation,
4190 const char *ok, const char *notok)
4191 {
4192 gpg_error_t err = 0;
4193 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
4194
4195 if (desc)
4196 err = print_assuan_status (ctx, "SETDESC", "%s", desc);
4197 if (!err && ok)
4198 err = print_assuan_status (ctx, "SETOK", "%s", ok);
4199 if (!err && notok)
4200 err = print_assuan_status (ctx, "SETNOTOK", "%s", notok);
4201
4202 if (!err)
4203 err = assuan_inquire (ctx, ask_confirmation ? "CONFIRM 1" : "CONFIRM 0",
4204 NULL, NULL, 0);
4205 return err;
4206 }
4207