agent/
[gnupg.git] / agent / command.c
blob5d082ed8ac03f9530fb784fc3dfff6cdf97acff4
1 /* command.c - gpg-agent command handler
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005,
3 * 2006, 2008, 2009 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 /* FIXME: we should not use the default assuan buffering but setup
22 some buffering in secure mempory to protect session keys etc. */
24 #include <config.h>
26 #include <errno.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <unistd.h>
32 #include <assert.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <dirent.h>
37 #include "agent.h"
38 #include <assuan.h>
39 #include "i18n.h"
41 /* maximum allowed size of the inquired ciphertext */
42 #define MAXLEN_CIPHERTEXT 4096
43 /* maximum allowed size of the key parameters */
44 #define MAXLEN_KEYPARAM 1024
46 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
49 #if MAX_DIGEST_LEN < 20
50 #error MAX_DIGEST_LEN shorter than keygrip
51 #endif
53 /* Data used to associate an Assuan context with local server data */
54 struct server_local_s
56 assuan_context_t assuan_ctx;
57 int message_fd;
58 int use_cache_for_signing;
59 char *keydesc; /* Allocated description for the next key
60 operation. */
61 int pause_io_logging; /* Used to suppress I/O logging during a command */
62 #ifdef HAVE_W32_SYSTEM
63 int stopme; /* If set to true the agent will be terminated after
64 the end of this session. */
65 #endif
66 int allow_pinentry_notify; /* Set if pinentry notifications should
67 be done. */
71 /* An entry for the getval/putval commands. */
72 struct putval_item_s
74 struct putval_item_s *next;
75 size_t off; /* Offset to the value into DATA. */
76 size_t len; /* Length of the value. */
77 char d[1]; /* Key | Nul | value. */
81 /* A list of key value pairs fpr the getval/putval commands. */
82 static struct putval_item_s *putval_list;
86 /* To help polling clients, we keep track of the number of certain
87 events. This structure keeps those counters. The counters are
88 integers and there should be no problem if they are overflowing as
89 callers need to check only whether a counter changed. The actual
90 values are not meaningful. */
91 struct
93 /* Incremented if any of the other counters below changed. */
94 unsigned int any;
96 /* Incremented if a key is added or removed from the internal privat
97 key database. */
98 unsigned int key;
100 /* Incremented if a change of the card readers stati has been
101 detected. */
102 unsigned int card;
104 } eventcounter;
108 /* Local prototypes. */
109 static int command_has_option (const char *cmd, const char *cmdopt);
114 /* Release the memory buffer MB but first wipe out the used memory. */
115 static void
116 clear_outbuf (membuf_t *mb)
118 void *p;
119 size_t n;
121 p = get_membuf (mb, &n);
122 if (p)
124 memset (p, 0, n);
125 xfree (p);
130 /* Write the content of memory buffer MB as assuan data to CTX and
131 wipe the buffer out afterwards. */
132 static gpg_error_t
133 write_and_clear_outbuf (assuan_context_t ctx, membuf_t *mb)
135 gpg_error_t ae;
136 void *p;
137 size_t n;
139 p = get_membuf (mb, &n);
140 if (!p)
141 return out_of_core ();
142 ae = assuan_send_data (ctx, p, n);
143 memset (p, 0, n);
144 xfree (p);
145 return ae;
149 static gpg_error_t
150 reset_notify (assuan_context_t ctx, char *line)
152 ctrl_t ctrl = assuan_get_pointer (ctx);
154 (void) line;
156 memset (ctrl->keygrip, 0, 20);
157 ctrl->have_keygrip = 0;
158 ctrl->digest.valuelen = 0;
160 xfree (ctrl->server_local->keydesc);
161 ctrl->server_local->keydesc = NULL;
162 return 0;
166 /* Check whether the option NAME appears in LINE */
167 static int
168 has_option (const char *line, const char *name)
170 const char *s;
171 int n = strlen (name);
173 s = strstr (line, name);
174 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
177 /* Same as has_option but does only test for the name of the option
178 and ignores an argument, i.e. with NAME being "--hash" it would
179 return true for "--hash" as well as for "--hash=foo". */
180 static int
181 has_option_name (const char *line, const char *name)
183 const char *s;
184 int n = strlen (name);
186 s = strstr (line, name);
187 return (s && (s == line || spacep (s-1))
188 && (!s[n] || spacep (s+n) || s[n] == '='));
191 /* Return a pointer to the argument of the option with NAME. If such
192 an option is not given, it returns NULL. */
193 static char *
194 option_value (const char *line, const char *name)
196 char *s;
197 int n = strlen (name);
199 s = strstr (line, name);
200 if (s && (s == line || spacep (s-1))
201 && s[n] && (spacep (s+n) || s[n] == '='))
203 s += n + 1;
204 s += strspn (s, " ");
205 if (*s && !spacep(s))
206 return s;
208 return NULL;
212 /* Skip over options. It is assumed that leading spaces have been
213 removed (this is the case for lines passed to a handler from
214 assuan). Blanks after the options are also removed. */
215 static char *
216 skip_options (char *line)
218 while ( *line == '-' && line[1] == '-' )
220 while (*line && !spacep (line))
221 line++;
222 while (spacep (line))
223 line++;
225 return line;
229 /* Replace all '+' by a blank. */
230 static void
231 plus_to_blank (char *s)
233 for (; *s; s++)
235 if (*s == '+')
236 *s = ' ';
241 /* Parse a hex string. Return an Assuan error code or 0 on success and the
242 length of the parsed string in LEN. */
243 static int
244 parse_hexstring (assuan_context_t ctx, const char *string, size_t *len)
246 const char *p;
247 size_t n;
249 /* parse the hash value */
250 for (p=string, n=0; hexdigitp (p); p++, n++)
252 if (*p != ' ' && *p != '\t' && *p)
253 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
254 if ((n&1))
255 return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
256 *len = n;
257 return 0;
260 /* Parse the keygrip in STRING into the provided buffer BUF. BUF must
261 provide space for 20 bytes. BUF is not changed if the function
262 returns an error. */
263 static int
264 parse_keygrip (assuan_context_t ctx, const char *string, unsigned char *buf)
266 int rc;
267 size_t n = 0;
269 rc = parse_hexstring (ctx, string, &n);
270 if (rc)
271 return rc;
272 n /= 2;
273 if (n != 20)
274 return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of keygrip");
276 if (hex2bin (string, buf, 20) < 0)
277 return set_error (GPG_ERR_BUG, "hex2bin");
279 return 0;
283 /* Write an assuan status line. */
284 gpg_error_t
285 agent_write_status (ctrl_t ctrl, const char *keyword, ...)
287 gpg_error_t err = 0;
288 va_list arg_ptr;
289 const char *text;
290 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
291 char buf[950], *p;
292 size_t n;
294 va_start (arg_ptr, keyword);
296 p = buf;
297 n = 0;
298 while ( (text = va_arg (arg_ptr, const char *)) )
300 if (n)
302 *p++ = ' ';
303 n++;
305 for ( ; *text && n < DIM (buf)-3; n++, text++)
307 if (*text == '\n')
309 *p++ = '\\';
310 *p++ = 'n';
312 else if (*text == '\r')
314 *p++ = '\\';
315 *p++ = 'r';
317 else
318 *p++ = *text;
321 *p = 0;
322 err = assuan_write_status (ctx, keyword, buf);
324 va_end (arg_ptr);
325 return err;
329 /* Helper to notify the client about a launched Pinentry. Because
330 that might disturb some older clients, this is only done if enabled
331 via an option. Returns an gpg error code. */
332 gpg_error_t
333 agent_inq_pinentry_launched (ctrl_t ctrl, unsigned long pid)
335 char line[100];
337 if (!ctrl || !ctrl->server_local
338 || !ctrl->server_local->allow_pinentry_notify)
339 return 0;
340 snprintf (line, DIM(line)-1, "PINENTRY_LAUNCHED %lu", pid);
341 return assuan_inquire (ctrl->server_local->assuan_ctx, line, NULL, NULL, 0);
346 static const char hlp_geteventcounter[] =
347 "GETEVENTCOUNTER\n"
348 "\n"
349 "Return a a status line named EVENTCOUNTER with the current values\n"
350 "of all event counters. The values are decimal numbers in the range\n"
351 "0 to UINT_MAX and wrapping around to 0. The actual values should\n"
352 "not be relied upon, they shall only be used to detect a change.\n"
353 "\n"
354 "The currently defined counters are:\n"
355 "\n"
356 "ANY - Incremented with any change of any of the other counters.\n"
357 "KEY - Incremented for added or removed private keys.\n"
358 "CARD - Incremented for changes of the card readers stati.";
359 static gpg_error_t
360 cmd_geteventcounter (assuan_context_t ctx, char *line)
362 ctrl_t ctrl = assuan_get_pointer (ctx);
363 char any_counter[25];
364 char key_counter[25];
365 char card_counter[25];
367 (void)line;
369 snprintf (any_counter, sizeof any_counter, "%u", eventcounter.any);
370 snprintf (key_counter, sizeof key_counter, "%u", eventcounter.key);
371 snprintf (card_counter, sizeof card_counter, "%u", eventcounter.card);
373 return agent_write_status (ctrl, "EVENTCOUNTER",
374 any_counter,
375 key_counter,
376 card_counter,
377 NULL);
381 /* This function should be called once for all key removals or
382 additions. This function is assured not to do any context
383 switches. */
384 void
385 bump_key_eventcounter (void)
387 eventcounter.key++;
388 eventcounter.any++;
391 /* This function should be called for all card reader status
392 changes. This function is assured not to do any context
393 switches. */
394 void
395 bump_card_eventcounter (void)
397 eventcounter.card++;
398 eventcounter.any++;
404 static const char hlp_istrusted[] =
405 "ISTRUSTED <hexstring_with_fingerprint>\n"
406 "\n"
407 "Return OK when we have an entry with this fingerprint in our\n"
408 "trustlist";
409 static gpg_error_t
410 cmd_istrusted (assuan_context_t ctx, char *line)
412 ctrl_t ctrl = assuan_get_pointer (ctx);
413 int rc, n, i;
414 char *p;
415 char fpr[41];
417 /* Parse the fingerprint value. */
418 for (p=line,n=0; hexdigitp (p); p++, n++)
420 if (*p || !(n == 40 || n == 32))
421 return set_error (GPG_ERR_ASS_PARAMETER, "invalid fingerprint");
422 i = 0;
423 if (n==32)
425 strcpy (fpr, "00000000");
426 i += 8;
428 for (p=line; i < 40; p++, i++)
429 fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
430 fpr[i] = 0;
431 rc = agent_istrusted (ctrl, fpr, NULL);
432 if (!rc || gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
433 return rc;
434 else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF )
435 return gpg_error (GPG_ERR_NOT_TRUSTED);
436 else
438 log_error ("command is_trusted failed: %s\n", gpg_strerror (rc));
439 return rc;
444 static const char hlp_listtrusted[] =
445 "LISTTRUSTED\n"
446 "\n"
447 "List all entries from the trustlist.";
448 static gpg_error_t
449 cmd_listtrusted (assuan_context_t ctx, char *line)
451 int rc;
453 (void)line;
455 rc = agent_listtrusted (ctx);
456 if (rc)
457 log_error ("command listtrusted failed: %s\n", gpg_strerror (rc));
458 return rc;
462 static const char hlp_martrusted[] =
463 "MARKTRUSTED <hexstring_with_fingerprint> <flag> <display_name>\n"
464 "\n"
465 "Store a new key in into the trustlist.";
466 static gpg_error_t
467 cmd_marktrusted (assuan_context_t ctx, char *line)
469 ctrl_t ctrl = assuan_get_pointer (ctx);
470 int rc, n, i;
471 char *p;
472 char fpr[41];
473 int flag;
475 /* parse the fingerprint value */
476 for (p=line,n=0; hexdigitp (p); p++, n++)
478 if (!spacep (p) || !(n == 40 || n == 32))
479 return set_error (GPG_ERR_ASS_PARAMETER, "invalid fingerprint");
480 i = 0;
481 if (n==32)
483 strcpy (fpr, "00000000");
484 i += 8;
486 for (p=line; i < 40; p++, i++)
487 fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
488 fpr[i] = 0;
490 while (spacep (p))
491 p++;
492 flag = *p++;
493 if ( (flag != 'S' && flag != 'P') || !spacep (p) )
494 return set_error (GPG_ERR_ASS_PARAMETER, "invalid flag - must be P or S");
495 while (spacep (p))
496 p++;
498 rc = agent_marktrusted (ctrl, p, fpr, flag);
499 if (rc)
500 log_error ("command marktrusted failed: %s\n", gpg_strerror (rc));
501 return rc;
507 static const char hlp_havekey[] =
508 "HAVEKEY <hexstring_with_keygrip>\n"
509 "\n"
510 "Return success when the secret key is available.";
511 static gpg_error_t
512 cmd_havekey (assuan_context_t ctx, char *line)
514 int rc;
515 unsigned char buf[20];
517 rc = parse_keygrip (ctx, line, buf);
518 if (rc)
519 return rc;
521 if (agent_key_available (buf))
522 return gpg_error (GPG_ERR_NO_SECKEY);
524 return 0;
528 static const char hlp_sigkey[] =
529 "SIGKEY <hexstring_with_keygrip>\n"
530 "SETKEY <hexstring_with_keygrip>\n"
531 "\n"
532 "Set the key used for a sign or decrypt operation.";
533 static gpg_error_t
534 cmd_sigkey (assuan_context_t ctx, char *line)
536 int rc;
537 ctrl_t ctrl = assuan_get_pointer (ctx);
539 rc = parse_keygrip (ctx, line, ctrl->keygrip);
540 if (rc)
541 return rc;
542 ctrl->have_keygrip = 1;
543 return 0;
547 static const char hlp_setkeydesc[] =
548 "SETKEYDESC plus_percent_escaped_string\n"
549 "\n"
550 "Set a description to be used for the next PKSIGN or PKDECRYPT\n"
551 "operation if this operation requires the entry of a passphrase. If\n"
552 "this command is not used a default text will be used. Note, that\n"
553 "this description implictly selects the label used for the entry\n"
554 "box; if the string contains the string PIN (which in general will\n"
555 "not be translated), \"PIN\" is used, otherwise the translation of\n"
556 "\"passphrase\" is used. The description string should not contain\n"
557 "blanks unless they are percent or '+' escaped.\n"
558 "\n"
559 "The description is only valid for the next PKSIGN or PKDECRYPT\n"
560 "operation.";
561 static gpg_error_t
562 cmd_setkeydesc (assuan_context_t ctx, char *line)
564 ctrl_t ctrl = assuan_get_pointer (ctx);
565 char *desc, *p;
567 for (p=line; *p == ' '; p++)
569 desc = p;
570 p = strchr (desc, ' ');
571 if (p)
572 *p = 0; /* We ignore any garbage; we might late use it for other args. */
574 if (!desc || !*desc)
575 return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
577 /* Note, that we only need to replace the + characters and should
578 leave the other escaping in place because the escaped string is
579 send verbatim to the pinentry which does the unescaping (but not
580 the + replacing) */
581 plus_to_blank (desc);
583 xfree (ctrl->server_local->keydesc);
584 ctrl->server_local->keydesc = xtrystrdup (desc);
585 if (!ctrl->server_local->keydesc)
586 return out_of_core ();
587 return 0;
591 static const char hlp_sethash[] =
592 "SETHASH --hash=<name>|<algonumber> <hexstring>\n"
593 "\n"
594 "The client can use this command to tell the server about the data\n"
595 "(which usually is a hash) to be signed.";
596 static gpg_error_t
597 cmd_sethash (assuan_context_t ctx, char *line)
599 int rc;
600 size_t n;
601 char *p;
602 ctrl_t ctrl = assuan_get_pointer (ctx);
603 unsigned char *buf;
604 char *endp;
605 int algo;
607 /* Parse the alternative hash options which may be used instead of
608 the algo number. */
609 if (has_option_name (line, "--hash"))
611 if (has_option (line, "--hash=sha1"))
612 algo = GCRY_MD_SHA1;
613 else if (has_option (line, "--hash=sha224"))
614 algo = GCRY_MD_SHA224;
615 else if (has_option (line, "--hash=sha256"))
616 algo = GCRY_MD_SHA256;
617 else if (has_option (line, "--hash=sha384"))
618 algo = GCRY_MD_SHA384;
619 else if (has_option (line, "--hash=sha512"))
620 algo = GCRY_MD_SHA512;
621 else if (has_option (line, "--hash=rmd160"))
622 algo = GCRY_MD_RMD160;
623 else if (has_option (line, "--hash=md5"))
624 algo = GCRY_MD_MD5;
625 else if (has_option (line, "--hash=tls-md5sha1"))
626 algo = MD_USER_TLS_MD5SHA1;
627 else
628 return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
630 else
631 algo = 0;
633 line = skip_options (line);
635 if (!algo)
637 /* No hash option has been given: require an algo number instead */
638 algo = (int)strtoul (line, &endp, 10);
639 for (line = endp; *line == ' ' || *line == '\t'; line++)
641 if (!algo || gcry_md_test_algo (algo))
642 return set_error (GPG_ERR_UNSUPPORTED_ALGORITHM, NULL);
644 ctrl->digest.algo = algo;
646 /* Parse the hash value. */
647 n = 0;
648 rc = parse_hexstring (ctx, line, &n);
649 if (rc)
650 return rc;
651 n /= 2;
652 if (algo == MD_USER_TLS_MD5SHA1 && n == 36)
654 else if (n != 16 && n != 20 && n != 24
655 && n != 28 && n != 32 && n != 48 && n != 64)
656 return set_error (GPG_ERR_ASS_PARAMETER, "unsupported length of hash");
658 if (n > MAX_DIGEST_LEN)
659 return set_error (GPG_ERR_ASS_PARAMETER, "hash value to long");
661 buf = ctrl->digest.value;
662 ctrl->digest.valuelen = n;
663 for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
664 buf[n] = xtoi_2 (p);
665 for (; n < ctrl->digest.valuelen; n++)
666 buf[n] = 0;
667 return 0;
671 static const char hlp_pksign[] =
672 "PKSIGN [options]\n"
673 "\n"
674 "Perform the actual sign operation. Neither input nor output are\n"
675 "sensitive to eavesdropping.";
676 static gpg_error_t
677 cmd_pksign (assuan_context_t ctx, char *line)
679 int rc;
680 cache_mode_t cache_mode = CACHE_MODE_NORMAL;
681 ctrl_t ctrl = assuan_get_pointer (ctx);
682 membuf_t outbuf;
684 (void)line;
686 if (opt.ignore_cache_for_signing)
687 cache_mode = CACHE_MODE_IGNORE;
688 else if (!ctrl->server_local->use_cache_for_signing)
689 cache_mode = CACHE_MODE_IGNORE;
691 init_membuf (&outbuf, 512);
693 rc = agent_pksign (ctrl, ctrl->server_local->keydesc,
694 &outbuf, cache_mode);
695 if (rc)
696 clear_outbuf (&outbuf);
697 else
698 rc = write_and_clear_outbuf (ctx, &outbuf);
699 if (rc)
700 log_error ("command pksign failed: %s\n", gpg_strerror (rc));
701 xfree (ctrl->server_local->keydesc);
702 ctrl->server_local->keydesc = NULL;
703 return rc;
707 static const char hlp_pkdecrypt[] =
708 "PKDECRYPT <options>\n"
709 "\n"
710 "Perform the actual decrypt operation. Input is not\n"
711 "sensitive to eavesdropping.";
712 static gpg_error_t
713 cmd_pkdecrypt (assuan_context_t ctx, char *line)
715 int rc;
716 ctrl_t ctrl = assuan_get_pointer (ctx);
717 unsigned char *value;
718 size_t valuelen;
719 membuf_t outbuf;
721 (void)line;
723 /* First inquire the data to decrypt */
724 rc = assuan_inquire (ctx, "CIPHERTEXT",
725 &value, &valuelen, MAXLEN_CIPHERTEXT);
726 if (rc)
727 return rc;
729 init_membuf (&outbuf, 512);
731 rc = agent_pkdecrypt (ctrl, ctrl->server_local->keydesc,
732 value, valuelen, &outbuf);
733 xfree (value);
734 if (rc)
735 clear_outbuf (&outbuf);
736 else
737 rc = write_and_clear_outbuf (ctx, &outbuf);
738 if (rc)
739 log_error ("command pkdecrypt failed: %s\n", gpg_strerror (rc));
740 xfree (ctrl->server_local->keydesc);
741 ctrl->server_local->keydesc = NULL;
742 return rc;
746 static const char hlp_genkey[] =
747 "GENKEY\n"
748 "\n"
749 "Generate a new key, store the secret part and return the public\n"
750 "part. Here is an example transaction:\n"
751 "\n"
752 " C: GENKEY\n"
753 " S: INQUIRE KEYPARAM\n"
754 " C: D (genkey (rsa (nbits 1024)))\n"
755 " C: END\n"
756 " S: D (public-key\n"
757 " S: D (rsa (n 326487324683264) (e 10001)))\n"
758 " S: OK key created\n"
759 "\n";
760 static gpg_error_t
761 cmd_genkey (assuan_context_t ctx, char *line)
763 ctrl_t ctrl = assuan_get_pointer (ctx);
764 int rc;
765 unsigned char *value;
766 size_t valuelen;
767 membuf_t outbuf;
769 (void)line;
771 /* First inquire the parameters */
772 rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM);
773 if (rc)
774 return rc;
776 init_membuf (&outbuf, 512);
778 rc = agent_genkey (ctrl, (char*)value, valuelen, &outbuf);
779 xfree (value);
780 if (rc)
781 clear_outbuf (&outbuf);
782 else
783 rc = write_and_clear_outbuf (ctx, &outbuf);
784 if (rc)
785 log_error ("command genkey failed: %s\n", gpg_strerror (rc));
786 return rc;
792 static const char hlp_readkey[] =
793 "READKEY <hexstring_with_keygrip>\n"
794 "\n"
795 "Return the public key for the given keygrip.";
796 static gpg_error_t
797 cmd_readkey (assuan_context_t ctx, char *line)
799 ctrl_t ctrl = assuan_get_pointer (ctx);
800 int rc;
801 unsigned char grip[20];
802 gcry_sexp_t s_pkey = NULL;
804 rc = parse_keygrip (ctx, line, grip);
805 if (rc)
806 return rc; /* Return immediately as this is already an Assuan error code.*/
808 rc = agent_public_key_from_file (ctrl, grip, &s_pkey);
809 if (!rc)
811 size_t len;
812 unsigned char *buf;
814 len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
815 assert (len);
816 buf = xtrymalloc (len);
817 if (!buf)
818 rc = gpg_error_from_syserror ();
819 else
821 len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, buf, len);
822 assert (len);
823 rc = assuan_send_data (ctx, buf, len);
824 xfree (buf);
826 gcry_sexp_release (s_pkey);
829 if (rc)
830 log_error ("command readkey failed: %s\n", gpg_strerror (rc));
831 return rc;
836 static const char hlp_keyinfo[] =
837 "KEYINFO [--list] <keygrip>\n"
838 "\n"
839 "Return information about the key specified by the KEYGRIP. If the\n"
840 "key is not available GPG_ERR_NOT_FOUND is returned. If the option\n"
841 "--list is given the keygrip is ignored and information about all\n"
842 "available keys are returned. The information is returned as a\n"
843 "status line with this format:\n"
844 "\n"
845 " KEYINFO <keygrip> <type> <serialno> <idstr>\n"
846 "\n"
847 "KEYGRIP is the keygrip.\n"
848 "\n"
849 "TYPE is describes the type of the key:\n"
850 " 'D' - Regular key stored on disk,\n"
851 " 'T' - Key is stored on a smartcard (token).\n"
852 " '-' - Unknown type.\n"
853 "\n"
854 "SERIALNO is an ASCII string with the serial number of the\n"
855 " smartcard. If the serial number is not known a single\n"
856 " dash '-' is used instead.\n"
857 "\n"
858 "IDSTR is the IDSTR used to distinguish keys on a smartcard. If it\n"
859 " is not known a dash is used instead.\n"
860 "\n"
861 "More information may be added in the future.";
862 static gpg_error_t
863 do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip)
865 gpg_error_t err;
866 char hexgrip[40+1];
867 int keytype;
868 unsigned char *shadow_info = NULL;
869 char *serialno = NULL;
870 char *idstr = NULL;
871 const char *keytypestr;
873 err = agent_key_info_from_file (ctrl, grip, &keytype, &shadow_info);
874 if (err)
875 goto leave;
877 /* Reformat the grip so that we use uppercase as good style. */
878 bin2hex (grip, 20, hexgrip);
880 if (keytype == PRIVATE_KEY_CLEAR
881 || keytype == PRIVATE_KEY_PROTECTED)
882 keytypestr = "D";
883 else if (keytype == PRIVATE_KEY_SHADOWED)
884 keytypestr = "T";
885 else
886 keytypestr = "-";
888 if (shadow_info)
890 err = parse_shadow_info (shadow_info, &serialno, &idstr);
891 if (err)
892 goto leave;
895 err = agent_write_status (ctrl, "KEYINFO",
896 hexgrip,
897 keytypestr,
898 serialno? serialno : "-",
899 idstr? idstr : "-",
900 NULL);
901 leave:
902 xfree (shadow_info);
903 xfree (serialno);
904 xfree (idstr);
905 return err;
909 static gpg_error_t
910 cmd_keyinfo (assuan_context_t ctx, char *line)
912 ctrl_t ctrl = assuan_get_pointer (ctx);
913 int err;
914 unsigned char grip[20];
915 DIR *dir = NULL;
916 int list_mode;
918 list_mode = has_option (line, "--list");
919 line = skip_options (line);
921 if (list_mode)
923 char *dirname;
924 struct dirent *dir_entry;
925 char hexgrip[41];
927 dirname = make_filename_try (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL);
928 if (!dirname)
930 err = gpg_error_from_syserror ();
931 goto leave;
933 dir = opendir (dirname);
934 if (!dir)
936 err = gpg_error_from_syserror ();
937 xfree (dirname);
938 goto leave;
940 xfree (dirname);
942 while ( (dir_entry = readdir (dir)) )
944 if (strlen (dir_entry->d_name) != 44
945 || strcmp (dir_entry->d_name + 40, ".key"))
946 continue;
947 strncpy (hexgrip, dir_entry->d_name, 40);
948 hexgrip[40] = 0;
950 if ( hex2bin (hexgrip, grip, 20) < 0 )
951 continue; /* Bad hex string. */
953 err = do_one_keyinfo (ctrl, grip);
954 if (err)
955 goto leave;
957 err = 0;
959 else
961 err = parse_keygrip (ctx, line, grip);
962 if (err)
963 goto leave;
964 err = do_one_keyinfo (ctrl, grip);
967 leave:
968 if (dir)
969 closedir (dir);
970 if (err && gpg_err_code (err) != GPG_ERR_NOT_FOUND)
971 log_error ("command keyinfo failed: %s\n", gpg_strerror (err));
972 return err;
977 static int
978 send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw)
980 size_t n;
981 int rc;
983 assuan_begin_confidential (ctx);
984 n = strlen (pw);
985 if (via_data)
986 rc = assuan_send_data (ctx, pw, n);
987 else
989 char *p = xtrymalloc_secure (n*2+1);
990 if (!p)
991 rc = gpg_error_from_syserror ();
992 else
994 bin2hex (pw, n, p);
995 rc = assuan_set_okay_line (ctx, p);
996 xfree (p);
999 return rc;
1003 static const char hlp_get_passphrase[] =
1004 "GET_PASSPHRASE [--data] [--check] [--no-ask] [--repeat[=N]]\n"
1005 " [--qualitybar] <cache_id>\n"
1006 " [<error_message> <prompt> <description>]\n"
1007 "\n"
1008 "This function is usually used to ask for a passphrase to be used\n"
1009 "for conventional encryption, but may also be used by programs which\n"
1010 "need specal handling of passphrases. This command uses a syntax\n"
1011 "which helps clients to use the agent with minimum effort. The\n"
1012 "agent either returns with an error or with a OK followed by the hex\n"
1013 "encoded passphrase. Note that the length of the strings is\n"
1014 "implicitly limited by the maximum length of a command.\n"
1015 "\n"
1016 "If the option \"--data\" is used the passphrase is returned by usual\n"
1017 "data lines and not on the okay line.\n"
1018 "\n"
1019 "If the option \"--check\" is used the passphrase constraints checks as\n"
1020 "implemented by gpg-agent are applied. A check is not done if the\n"
1021 "passphrase has been found in the cache.\n"
1022 "\n"
1023 "If the option \"--no-ask\" is used and the passphrase is not in the\n"
1024 "cache the user will not be asked to enter a passphrase but the error\n"
1025 "code GPG_ERR_NO_DATA is returned. \n"
1026 "\n"
1027 "If the option \"--qualitybar\" is used a visual indication of the\n"
1028 "entered passphrase quality is shown. (Unless no minimum passphrase\n"
1029 "length has been configured.)";
1030 static gpg_error_t
1031 cmd_get_passphrase (assuan_context_t ctx, char *line)
1033 ctrl_t ctrl = assuan_get_pointer (ctx);
1034 int rc;
1035 const char *pw;
1036 char *response;
1037 char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
1038 const char *desc2 = _("Please re-enter this passphrase");
1039 char *p;
1040 void *cache_marker;
1041 int opt_data, opt_check, opt_no_ask, opt_qualbar;
1042 int opt_repeat = 0;
1043 char *repeat_errtext = NULL;
1045 opt_data = has_option (line, "--data");
1046 opt_check = has_option (line, "--check");
1047 opt_no_ask = has_option (line, "--no-ask");
1048 if (has_option_name (line, "--repeat"))
1050 p = option_value (line, "--repeat");
1051 if (p)
1052 opt_repeat = atoi (p);
1053 else
1054 opt_repeat = 1;
1056 opt_qualbar = has_option (line, "--qualitybar");
1057 line = skip_options (line);
1059 cacheid = line;
1060 p = strchr (cacheid, ' ');
1061 if (p)
1063 *p++ = 0;
1064 while (*p == ' ')
1065 p++;
1066 errtext = p;
1067 p = strchr (errtext, ' ');
1068 if (p)
1070 *p++ = 0;
1071 while (*p == ' ')
1072 p++;
1073 prompt = p;
1074 p = strchr (prompt, ' ');
1075 if (p)
1077 *p++ = 0;
1078 while (*p == ' ')
1079 p++;
1080 desc = p;
1081 p = strchr (desc, ' ');
1082 if (p)
1083 *p = 0; /* Ignore trailing garbage. */
1087 if (!cacheid || !*cacheid || strlen (cacheid) > 50)
1088 return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
1089 if (!desc)
1090 return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
1092 if (!strcmp (cacheid, "X"))
1093 cacheid = NULL;
1094 if (!strcmp (errtext, "X"))
1095 errtext = NULL;
1096 if (!strcmp (prompt, "X"))
1097 prompt = NULL;
1098 if (!strcmp (desc, "X"))
1099 desc = NULL;
1101 pw = cacheid ? agent_get_cache (cacheid, CACHE_MODE_NORMAL, &cache_marker)
1102 : NULL;
1103 if (pw)
1105 rc = send_back_passphrase (ctx, opt_data, pw);
1106 agent_unlock_cache_entry (&cache_marker);
1108 else if (opt_no_ask)
1109 rc = gpg_error (GPG_ERR_NO_DATA);
1110 else
1112 /* Note, that we only need to replace the + characters and
1113 should leave the other escaping in place because the escaped
1114 string is send verbatim to the pinentry which does the
1115 unescaping (but not the + replacing) */
1116 if (errtext)
1117 plus_to_blank (errtext);
1118 if (prompt)
1119 plus_to_blank (prompt);
1120 if (desc)
1121 plus_to_blank (desc);
1123 next_try:
1124 rc = agent_get_passphrase (ctrl, &response, desc, prompt,
1125 repeat_errtext? repeat_errtext:errtext,
1126 opt_qualbar);
1127 xfree (repeat_errtext);
1128 repeat_errtext = NULL;
1129 if (!rc)
1131 int i;
1133 if (opt_check && check_passphrase_constraints (ctrl, response, 0))
1135 xfree (response);
1136 goto next_try;
1138 for (i = 0; i < opt_repeat; i++)
1140 char *response2;
1142 rc = agent_get_passphrase (ctrl, &response2, desc2, prompt,
1143 errtext, 0);
1144 if (rc)
1145 break;
1146 if (strcmp (response2, response))
1148 xfree (response2);
1149 xfree (response);
1150 repeat_errtext = try_percent_escape
1151 (_("does not match - try again"), NULL);
1152 if (!repeat_errtext)
1154 rc = gpg_error_from_syserror ();
1155 break;
1157 goto next_try;
1159 xfree (response2);
1161 if (!rc)
1163 if (cacheid)
1164 agent_put_cache (cacheid, CACHE_MODE_USER, response, 0);
1165 rc = send_back_passphrase (ctx, opt_data, response);
1167 xfree (response);
1171 if (rc)
1172 log_error ("command get_passphrase failed: %s\n", gpg_strerror (rc));
1173 return rc;
1177 static const char hlp_clear_passphrase[] =
1178 "CLEAR_PASSPHRASE <cache_id>\n"
1179 "\n"
1180 "may be used to invalidate the cache entry for a passphrase. The\n"
1181 "function returns with OK even when there is no cached passphrase.";
1182 static gpg_error_t
1183 cmd_clear_passphrase (assuan_context_t ctx, char *line)
1185 char *cacheid = NULL;
1186 char *p;
1188 /* parse the stuff */
1189 for (p=line; *p == ' '; p++)
1191 cacheid = p;
1192 p = strchr (cacheid, ' ');
1193 if (p)
1194 *p = 0; /* ignore garbage */
1195 if (!cacheid || !*cacheid || strlen (cacheid) > 50)
1196 return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
1198 agent_put_cache (cacheid, CACHE_MODE_USER, NULL, 0);
1199 return 0;
1203 static const char hlp_get_confirmation[] =
1204 "GET_CONFIRMATION <description>\n"
1205 "\n"
1206 "This command may be used to ask for a simple confirmation.\n"
1207 "DESCRIPTION is displayed along with a Okay and Cancel button. This\n"
1208 "command uses a syntax which helps clients to use the agent with\n"
1209 "minimum effort. The agent either returns with an error or with a\n"
1210 "OK. Note, that the length of DESCRIPTION is implicitly limited by\n"
1211 "the maximum length of a command. DESCRIPTION should not contain\n"
1212 "any spaces, those must be encoded either percent escaped or simply\n"
1213 "as '+'.";
1214 static gpg_error_t
1215 cmd_get_confirmation (assuan_context_t ctx, char *line)
1217 ctrl_t ctrl = assuan_get_pointer (ctx);
1218 int rc;
1219 char *desc = NULL;
1220 char *p;
1222 /* parse the stuff */
1223 for (p=line; *p == ' '; p++)
1225 desc = p;
1226 p = strchr (desc, ' ');
1227 if (p)
1228 *p = 0; /* We ignore any garbage -may be later used for other args. */
1230 if (!desc || !*desc)
1231 return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
1233 if (!strcmp (desc, "X"))
1234 desc = NULL;
1236 /* Note, that we only need to replace the + characters and should
1237 leave the other escaping in place because the escaped string is
1238 send verbatim to the pinentry which does the unescaping (but not
1239 the + replacing) */
1240 if (desc)
1241 plus_to_blank (desc);
1243 rc = agent_get_confirmation (ctrl, desc, NULL, NULL, 0);
1244 if (rc)
1245 log_error ("command get_confirmation failed: %s\n", gpg_strerror (rc));
1246 return rc;
1251 static const char hlp_learn[] =
1252 "LEARN [--send]\n"
1253 "\n"
1254 "Learn something about the currently inserted smartcard. With\n"
1255 "--send the new certificates are send back.";
1256 static gpg_error_t
1257 cmd_learn (assuan_context_t ctx, char *line)
1259 ctrl_t ctrl = assuan_get_pointer (ctx);
1260 int rc;
1262 rc = agent_handle_learn (ctrl, has_option (line, "--send")? ctx : NULL);
1263 if (rc)
1264 log_error ("command learn failed: %s\n", gpg_strerror (rc));
1265 return rc;
1270 static const char hlp_passwd[] =
1271 "PASSWD <hexstring_with_keygrip>\n"
1272 "\n"
1273 "Change the passphrase/PIN for the key identified by keygrip in LINE.";
1274 static gpg_error_t
1275 cmd_passwd (assuan_context_t ctx, char *line)
1277 ctrl_t ctrl = assuan_get_pointer (ctx);
1278 int rc;
1279 unsigned char grip[20];
1280 gcry_sexp_t s_skey = NULL;
1281 unsigned char *shadow_info = NULL;
1283 rc = parse_keygrip (ctx, line, grip);
1284 if (rc)
1285 goto leave;
1287 ctrl->in_passwd++;
1288 rc = agent_key_from_file (ctrl, ctrl->server_local->keydesc,
1289 grip, &shadow_info, CACHE_MODE_IGNORE, NULL,
1290 &s_skey);
1291 if (rc)
1293 else if (!s_skey)
1295 log_error ("changing a smartcard PIN is not yet supported\n");
1296 rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1298 else
1299 rc = agent_protect_and_store (ctrl, s_skey);
1300 ctrl->in_passwd--;
1302 xfree (ctrl->server_local->keydesc);
1303 ctrl->server_local->keydesc = NULL;
1305 leave:
1306 gcry_sexp_release (s_skey);
1307 xfree (shadow_info);
1308 if (rc)
1309 log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1310 return rc;
1314 static const char hlp_preset_passphrase[] =
1315 "PRESET_PASSPHRASE <string_or_keygrip> <timeout> <hexstring>\n"
1316 "\n"
1317 "Set the cached passphrase/PIN for the key identified by the keygrip\n"
1318 "to passwd for the given time, where -1 means infinite and 0 means\n"
1319 "the default (currently only a timeout of -1 is allowed, which means\n"
1320 "to never expire it). If passwd is not provided, ask for it via the\n"
1321 "pinentry module.";
1322 static gpg_error_t
1323 cmd_preset_passphrase (assuan_context_t ctx, char *line)
1325 int rc;
1326 char *grip_clear = NULL;
1327 char *passphrase = NULL;
1328 int ttl;
1329 size_t len;
1331 if (!opt.allow_preset_passphrase)
1332 return set_error (GPG_ERR_NOT_SUPPORTED, "no --allow-preset-passphrase");
1334 grip_clear = line;
1335 while (*line && (*line != ' ' && *line != '\t'))
1336 line++;
1337 if (!*line)
1338 return gpg_error (GPG_ERR_MISSING_VALUE);
1339 *line = '\0';
1340 line++;
1341 while (*line && (*line == ' ' || *line == '\t'))
1342 line++;
1344 /* Currently, only infinite timeouts are allowed. */
1345 ttl = -1;
1346 if (line[0] != '-' || line[1] != '1')
1347 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1348 line++;
1349 line++;
1350 while (!(*line != ' ' && *line != '\t'))
1351 line++;
1353 /* Syntax check the hexstring. */
1354 len = 0;
1355 rc = parse_hexstring (ctx, line, &len);
1356 if (rc)
1357 return rc;
1358 line[len] = '\0';
1360 /* If there is a passphrase, use it. Currently, a passphrase is
1361 required. */
1362 if (*line)
1364 /* Do in-place conversion. */
1365 passphrase = line;
1366 if (!hex2str (passphrase, passphrase, strlen (passphrase)+1, NULL))
1367 rc = set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
1369 else
1370 rc = set_error (GPG_ERR_NOT_IMPLEMENTED, "passphrase is required");
1372 if (!rc)
1373 rc = agent_put_cache (grip_clear, CACHE_MODE_ANY, passphrase, ttl);
1375 if (rc)
1376 log_error ("command preset_passphrase failed: %s\n", gpg_strerror (rc));
1378 return rc;
1383 static const char hlp_scd[] =
1384 "SCD <commands to pass to the scdaemon>\n"
1385 " \n"
1386 "This is a general quote command to redirect everything to the\n"
1387 "SCdaemon.";
1388 static gpg_error_t
1389 cmd_scd (assuan_context_t ctx, char *line)
1391 ctrl_t ctrl = assuan_get_pointer (ctx);
1392 int rc;
1394 rc = divert_generic_cmd (ctrl, line, ctx);
1396 return rc;
1401 static const char hlp_getval[] =
1402 "GETVAL <key>\n"
1403 "\n"
1404 "Return the value for KEY from the special environment as created by\n"
1405 "PUTVAL.";
1406 static gpg_error_t
1407 cmd_getval (assuan_context_t ctx, char *line)
1409 int rc = 0;
1410 char *key = NULL;
1411 char *p;
1412 struct putval_item_s *vl;
1414 for (p=line; *p == ' '; p++)
1416 key = p;
1417 p = strchr (key, ' ');
1418 if (p)
1420 *p++ = 0;
1421 for (; *p == ' '; p++)
1423 if (*p)
1424 return set_error (GPG_ERR_ASS_PARAMETER, "too many arguments");
1426 if (!key || !*key)
1427 return set_error (GPG_ERR_ASS_PARAMETER, "no key given");
1430 for (vl=putval_list; vl; vl = vl->next)
1431 if ( !strcmp (vl->d, key) )
1432 break;
1434 if (vl) /* Got an entry. */
1435 rc = assuan_send_data (ctx, vl->d+vl->off, vl->len);
1436 else
1437 return gpg_error (GPG_ERR_NO_DATA);
1439 if (rc)
1440 log_error ("command getval failed: %s\n", gpg_strerror (rc));
1441 return rc;
1445 static const char hlp_putval[] =
1446 "PUTVAL <key> [<percent_escaped_value>]\n"
1447 "\n"
1448 "The gpg-agent maintains a kind of environment which may be used to\n"
1449 "store key/value pairs in it, so that they can be retrieved later.\n"
1450 "This may be used by helper daemons to daemonize themself on\n"
1451 "invocation and register them with gpg-agent. Callers of the\n"
1452 "daemon's service may now first try connect to get the information\n"
1453 "for that service from gpg-agent through the GETVAL command and then\n"
1454 "try to connect to that daemon. Only if that fails they may start\n"
1455 "an own instance of the service daemon. \n"
1456 "\n"
1457 "KEY is an an arbitrary symbol with the same syntax rules as keys\n"
1458 "for shell environment variables. PERCENT_ESCAPED_VALUE is the\n"
1459 "corresponsing value; they should be similar to the values of\n"
1460 "envronment variables but gpg-agent does not enforce any\n"
1461 "restrictions. If that value is not given any value under that KEY\n"
1462 "is removed from this special environment.";
1463 static gpg_error_t
1464 cmd_putval (assuan_context_t ctx, char *line)
1466 int rc = 0;
1467 char *key = NULL;
1468 char *value = NULL;
1469 size_t valuelen = 0;
1470 char *p;
1471 struct putval_item_s *vl, *vlprev;
1473 for (p=line; *p == ' '; p++)
1475 key = p;
1476 p = strchr (key, ' ');
1477 if (p)
1479 *p++ = 0;
1480 for (; *p == ' '; p++)
1482 if (*p)
1484 value = p;
1485 p = strchr (value, ' ');
1486 if (p)
1487 *p = 0;
1488 valuelen = percent_plus_unescape_inplace (value, 0);
1491 if (!key || !*key)
1492 return set_error (GPG_ERR_ASS_PARAMETER, "no key given");
1495 for (vl=putval_list,vlprev=NULL; vl; vlprev=vl, vl = vl->next)
1496 if ( !strcmp (vl->d, key) )
1497 break;
1499 if (vl) /* Delete old entry. */
1501 if (vlprev)
1502 vlprev->next = vl->next;
1503 else
1504 putval_list = vl->next;
1505 xfree (vl);
1508 if (valuelen) /* Add entry. */
1510 vl = xtrymalloc (sizeof *vl + strlen (key) + valuelen);
1511 if (!vl)
1512 rc = gpg_error_from_syserror ();
1513 else
1515 vl->len = valuelen;
1516 vl->off = strlen (key) + 1;
1517 strcpy (vl->d, key);
1518 memcpy (vl->d + vl->off, value, valuelen);
1519 vl->next = putval_list;
1520 putval_list = vl;
1524 if (rc)
1525 log_error ("command putval failed: %s\n", gpg_strerror (rc));
1526 return rc;
1532 static const char hlp_updatestartuptty[] =
1533 "UPDATESTARTUPTTY\n"
1534 "\n"
1535 "Set startup TTY and X11 DISPLAY variables to the values of this\n"
1536 "session. This command is useful to pull future pinentries to\n"
1537 "another screen. It is only required because there is no way in the\n"
1538 "ssh-agent protocol to convey this information.";
1539 static gpg_error_t
1540 cmd_updatestartuptty (assuan_context_t ctx, char *line)
1542 static const char *names[] =
1543 { "GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL };
1544 ctrl_t ctrl = assuan_get_pointer (ctx);
1545 gpg_error_t err = 0;
1546 session_env_t se;
1547 int idx;
1548 char *lc_ctype = NULL;
1549 char *lc_messages = NULL;
1551 (void)line;
1553 se = session_env_new ();
1554 if (!se)
1555 err = gpg_error_from_syserror ();
1557 for (idx=0; !err && names[idx]; idx++)
1559 const char *value = session_env_getenv (ctrl->session_env, names[idx]);
1560 if (value)
1561 err = session_env_setenv (se, names[idx], value);
1564 if (!err && ctrl->lc_ctype)
1565 if (!(lc_ctype = xtrystrdup (ctrl->lc_ctype)))
1566 err = gpg_error_from_syserror ();
1568 if (!err && ctrl->lc_messages)
1569 if (!(lc_messages = xtrystrdup (ctrl->lc_messages)))
1570 err = gpg_error_from_syserror ();
1572 if (err)
1574 session_env_release (se);
1575 xfree (lc_ctype);
1576 xfree (lc_messages);
1578 else
1580 session_env_release (opt.startup_env);
1581 opt.startup_env = se;
1582 xfree (opt.startup_lc_ctype);
1583 opt.startup_lc_ctype = lc_ctype;
1584 xfree (opt.startup_lc_messages);
1585 opt.startup_lc_messages = lc_messages;
1588 return err;
1593 #ifdef HAVE_W32_SYSTEM
1594 static const char hlp_killagent[] =
1595 "KILLAGENT\n"
1596 "\n"
1597 "Under Windows we start the agent on the fly. Thus it also make\n"
1598 "sense to allow a client to stop the agent.";
1599 static gpg_error_t
1600 cmd_killagent (assuan_context_t ctx, char *line)
1602 ctrl_t ctrl = assuan_get_pointer (ctx);
1604 (void)line;
1606 ctrl->server_local->stopme = 1;
1607 return gpg_error (GPG_ERR_EOF);
1611 static const char hlp_reloadagent[] =
1612 "RELOADAGENT\n"
1613 "\n"
1614 "As signals are inconvenient under Windows, we provide this command\n"
1615 "to allow reloading of the configuration.";
1616 static gpg_error_t
1617 cmd_reloadagent (assuan_context_t ctx, char *line)
1619 (void)ctx;
1620 (void)line;
1622 agent_sighup_action ();
1623 return 0;
1625 #endif /*HAVE_W32_SYSTEM*/
1629 static const char hlp_getinfo[] =
1630 "GETINFO <what>\n"
1631 "\n"
1632 "Multipurpose function to return a variety of information.\n"
1633 "Supported values for WHAT are:\n"
1634 "\n"
1635 " version - Return the version of the program.\n"
1636 " pid - Return the process id of the server.\n"
1637 " socket_name - Return the name of the socket.\n"
1638 " ssh_socket_name - Return the name of the ssh socket.\n"
1639 " scd_running - Return OK if the SCdaemon is already running.\n"
1640 " cmd_has_option\n"
1641 " - Returns OK if the command CMD implements the option OPT.";
1642 static gpg_error_t
1643 cmd_getinfo (assuan_context_t ctx, char *line)
1645 int rc = 0;
1647 if (!strcmp (line, "version"))
1649 const char *s = VERSION;
1650 rc = assuan_send_data (ctx, s, strlen (s));
1652 else if (!strcmp (line, "pid"))
1654 char numbuf[50];
1656 snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1657 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1659 else if (!strcmp (line, "socket_name"))
1661 const char *s = get_agent_socket_name ();
1663 if (s)
1664 rc = assuan_send_data (ctx, s, strlen (s));
1665 else
1666 rc = gpg_error (GPG_ERR_NO_DATA);
1668 else if (!strcmp (line, "ssh_socket_name"))
1670 const char *s = get_agent_ssh_socket_name ();
1672 if (s)
1673 rc = assuan_send_data (ctx, s, strlen (s));
1674 else
1675 rc = gpg_error (GPG_ERR_NO_DATA);
1677 else if (!strcmp (line, "scd_running"))
1679 rc = agent_scd_check_running ()? 0 : gpg_error (GPG_ERR_GENERAL);
1681 else if (!strncmp (line, "cmd_has_option", 14)
1682 && (line[14] == ' ' || line[14] == '\t' || !line[14]))
1684 char *cmd, *cmdopt;
1685 line += 14;
1686 while (*line == ' ' || *line == '\t')
1687 line++;
1688 if (!*line)
1689 rc = gpg_error (GPG_ERR_MISSING_VALUE);
1690 else
1692 cmd = line;
1693 while (*line && (*line != ' ' && *line != '\t'))
1694 line++;
1695 if (!*line)
1696 rc = gpg_error (GPG_ERR_MISSING_VALUE);
1697 else
1699 *line++ = 0;
1700 while (*line == ' ' || *line == '\t')
1701 line++;
1702 if (!*line)
1703 rc = gpg_error (GPG_ERR_MISSING_VALUE);
1704 else
1706 cmdopt = line;
1707 if (!command_has_option (cmd, cmdopt))
1708 rc = gpg_error (GPG_ERR_GENERAL);
1713 else
1714 rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1715 return rc;
1720 static gpg_error_t
1721 option_handler (assuan_context_t ctx, const char *key, const char *value)
1723 ctrl_t ctrl = assuan_get_pointer (ctx);
1724 gpg_error_t err = 0;
1726 if (!strcmp (key, "putenv"))
1728 /* Change the session's environment to be used for the
1729 Pinentry. Valid values are:
1730 <NAME> Delete envvar NAME
1731 <KEY>= Set envvar NAME to the empty string
1732 <KEY>=<VALUE> Set envvar NAME to VALUE
1734 err = session_env_putenv (ctrl->session_env, value);
1736 else if (!strcmp (key, "display"))
1738 err = session_env_setenv (ctrl->session_env, "DISPLAY", value);
1740 else if (!strcmp (key, "ttyname"))
1742 if (!opt.keep_tty)
1743 err = session_env_setenv (ctrl->session_env, "GPG_TTY", value);
1745 else if (!strcmp (key, "ttytype"))
1747 if (!opt.keep_tty)
1748 err = session_env_setenv (ctrl->session_env, "TERM", value);
1750 else if (!strcmp (key, "lc-ctype"))
1752 if (ctrl->lc_ctype)
1753 xfree (ctrl->lc_ctype);
1754 ctrl->lc_ctype = xtrystrdup (value);
1755 if (!ctrl->lc_ctype)
1756 return out_of_core ();
1758 else if (!strcmp (key, "lc-messages"))
1760 if (ctrl->lc_messages)
1761 xfree (ctrl->lc_messages);
1762 ctrl->lc_messages = xtrystrdup (value);
1763 if (!ctrl->lc_messages)
1764 return out_of_core ();
1766 else if (!strcmp (key, "xauthority"))
1768 err = session_env_setenv (ctrl->session_env, "XAUTHORITY", value);
1770 else if (!strcmp (key, "pinentry-user-data"))
1772 err = session_env_setenv (ctrl->session_env, "PINENTRY_USER_DATA", value);
1774 else if (!strcmp (key, "use-cache-for-signing"))
1775 ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0;
1776 else if (!strcmp (key, "allow-pinentry-notify"))
1777 ctrl->server_local->allow_pinentry_notify = 1;
1778 else
1779 err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
1781 return err;
1787 /* Called by libassuan after all commands. ERR is the error from the
1788 last assuan operation and not the one returned from the command. */
1789 static void
1790 post_cmd_notify (assuan_context_t ctx, gpg_error_t err)
1792 ctrl_t ctrl = assuan_get_pointer (ctx);
1794 (void)err;
1796 /* Switch off any I/O monitor controlled logging pausing. */
1797 ctrl->server_local->pause_io_logging = 0;
1801 /* This function is called by libassuan for all I/O. We use it here
1802 to disable logging for the GETEVENTCOUNTER commands. This is so
1803 that the debug output won't get cluttered by this primitive
1804 command. */
1805 static unsigned int
1806 io_monitor (assuan_context_t ctx, void *hook, int direction,
1807 const char *line, size_t linelen)
1809 ctrl_t ctrl = assuan_get_pointer (ctx);
1811 (void) hook;
1813 /* Note that we only check for the uppercase name. This allows to
1814 see the logging for debugging if using a non-upercase command
1815 name. */
1816 if (ctx && direction == ASSUAN_IO_FROM_PEER
1817 && linelen >= 15
1818 && !strncmp (line, "GETEVENTCOUNTER", 15)
1819 && (linelen == 15 || spacep (line+15)))
1821 ctrl->server_local->pause_io_logging = 1;
1824 return ctrl->server_local->pause_io_logging? ASSUAN_IO_MONITOR_NOLOG : 0;
1828 /* Return true if the command CMD implements the option OPT. */
1829 static int
1830 command_has_option (const char *cmd, const char *cmdopt)
1832 if (!strcmp (cmd, "GET_PASSPHRASE"))
1834 if (!strcmp (cmdopt, "repeat"))
1835 return 1;
1838 return 0;
1842 /* Tell the assuan library about our commands */
1843 static int
1844 register_commands (assuan_context_t ctx)
1846 static struct {
1847 const char *name;
1848 assuan_handler_t handler;
1849 const char * const help;
1850 } table[] = {
1851 { "GETEVENTCOUNTER",cmd_geteventcounter, hlp_geteventcounter },
1852 { "ISTRUSTED", cmd_istrusted, hlp_istrusted },
1853 { "HAVEKEY", cmd_havekey, hlp_havekey },
1854 { "KEYINFO", cmd_keyinfo, hlp_keyinfo },
1855 { "SIGKEY", cmd_sigkey, hlp_sigkey },
1856 { "SETKEY", cmd_sigkey, hlp_sigkey },
1857 { "SETKEYDESC", cmd_setkeydesc,hlp_setkeydesc },
1858 { "SETHASH", cmd_sethash, hlp_sethash },
1859 { "PKSIGN", cmd_pksign, hlp_pksign },
1860 { "PKDECRYPT", cmd_pkdecrypt, hlp_pkdecrypt },
1861 { "GENKEY", cmd_genkey, hlp_genkey },
1862 { "READKEY", cmd_readkey, hlp_readkey },
1863 { "GET_PASSPHRASE", cmd_get_passphrase, hlp_get_passphrase },
1864 { "PRESET_PASSPHRASE", cmd_preset_passphrase, hlp_preset_passphrase },
1865 { "CLEAR_PASSPHRASE", cmd_clear_passphrase, hlp_clear_passphrase },
1866 { "GET_CONFIRMATION", cmd_get_confirmation, hlp_get_confirmation },
1867 { "LISTTRUSTED", cmd_listtrusted, hlp_listtrusted },
1868 { "MARKTRUSTED", cmd_marktrusted, hlp_martrusted },
1869 { "LEARN", cmd_learn, hlp_learn },
1870 { "PASSWD", cmd_passwd, hlp_passwd },
1871 { "INPUT", NULL },
1872 { "OUTPUT", NULL },
1873 { "SCD", cmd_scd, hlp_scd },
1874 { "GETVAL", cmd_getval, hlp_getval },
1875 { "PUTVAL", cmd_putval, hlp_putval },
1876 { "UPDATESTARTUPTTY", cmd_updatestartuptty, hlp_updatestartuptty },
1877 #ifdef HAVE_W32_SYSTEM
1878 { "KILLAGENT", cmd_killagent, hlp_killagent },
1879 { "RELOADAGENT", cmd_reloadagent,hlp_reloadagent },
1880 #endif
1881 { "GETINFO", cmd_getinfo, hlp_getinfo },
1882 { NULL }
1884 int i, rc;
1886 for (i=0; table[i].name; i++)
1888 rc = assuan_register_command (ctx, table[i].name, table[i].handler,
1889 table[i].help);
1890 if (rc)
1891 return rc;
1893 assuan_register_post_cmd_notify (ctx, post_cmd_notify);
1894 assuan_register_reset_notify (ctx, reset_notify);
1895 assuan_register_option_handler (ctx, option_handler);
1896 return 0;
1900 /* Startup the server. If LISTEN_FD and FD is given as -1, this is a
1901 simple piper server, otherwise it is a regular server. CTRL is the
1902 control structure for this connection; it has only the basic
1903 intialization. */
1904 void
1905 start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd)
1907 int rc;
1908 assuan_context_t ctx = NULL;
1910 rc = assuan_new (&ctx);
1911 if (rc)
1913 log_error ("failed to allocate assuan context: %s\n", gpg_strerror (rc));
1914 agent_exit (2);
1917 if (listen_fd == GNUPG_INVALID_FD && fd == GNUPG_INVALID_FD)
1919 assuan_fd_t filedes[2];
1921 filedes[0] = assuan_fdopen (0);
1922 filedes[1] = assuan_fdopen (1);
1923 rc = assuan_init_pipe_server (ctx, filedes);
1925 else if (listen_fd != GNUPG_INVALID_FD)
1927 rc = assuan_init_socket_server (ctx, listen_fd, 0);
1928 /* FIXME: Need to call assuan_sock_set_nonce for Windows. But
1929 this branch is currently not used. */
1931 else
1933 rc = assuan_init_socket_server (ctx, fd, ASSUAN_SOCKET_SERVER_ACCEPTED);
1935 if (rc)
1937 log_error ("failed to initialize the server: %s\n",
1938 gpg_strerror(rc));
1939 agent_exit (2);
1941 rc = register_commands (ctx);
1942 if (rc)
1944 log_error ("failed to register commands with Assuan: %s\n",
1945 gpg_strerror(rc));
1946 agent_exit (2);
1949 assuan_set_pointer (ctx, ctrl);
1950 ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
1951 ctrl->server_local->assuan_ctx = ctx;
1952 ctrl->server_local->message_fd = -1;
1953 ctrl->server_local->use_cache_for_signing = 1;
1954 ctrl->digest.raw_value = 0;
1956 if (DBG_ASSUAN)
1957 assuan_set_log_stream (ctx, log_get_stream ());
1959 assuan_set_io_monitor (ctx, io_monitor, NULL);
1961 for (;;)
1963 rc = assuan_accept (ctx);
1964 if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1)
1966 break;
1968 else if (rc)
1970 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
1971 break;
1974 rc = assuan_process (ctx);
1975 if (rc)
1977 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
1978 continue;
1982 /* Reset the SCD if needed. */
1983 agent_reset_scd (ctrl);
1985 /* Reset the pinentry (in case of popup messages). */
1986 agent_reset_query (ctrl);
1988 /* Cleanup. */
1989 assuan_release (ctx);
1990 #ifdef HAVE_W32_SYSTEM
1991 if (ctrl->server_local->stopme)
1992 agent_exit (0);
1993 #endif
1994 xfree (ctrl->server_local);
1995 ctrl->server_local = NULL;