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