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. */
33 #include <sys/types.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
53 /* Data used to associate an Assuan context with local server data */
56 assuan_context_t assuan_ctx
;
58 int use_cache_for_signing
;
59 char *keydesc
; /* Allocated description for the next key
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. */
66 int allow_pinentry_notify
; /* Set if pinentry notifications should
71 /* An entry for the getval/putval commands. */
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. */
93 /* Incremented if any of the other counters below changed. */
96 /* Incremented if a key is added or removed from the internal privat
100 /* Incremented if a change of the card readers stati has been
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. */
116 clear_outbuf (membuf_t
*mb
)
121 p
= get_membuf (mb
, &n
);
130 /* Write the content of memory buffer MB as assuan data to CTX and
131 wipe the buffer out afterwards. */
133 write_and_clear_outbuf (assuan_context_t ctx
, membuf_t
*mb
)
139 p
= get_membuf (mb
, &n
);
141 return out_of_core ();
142 ae
= assuan_send_data (ctx
, p
, n
);
150 reset_notify (assuan_context_t ctx
, char *line
)
152 ctrl_t ctrl
= assuan_get_pointer (ctx
);
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
;
166 /* Check whether the option NAME appears in LINE */
168 has_option (const char *line
, const char *name
)
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". */
181 has_option_name (const char *line
, const char *name
)
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. */
194 option_value (const char *line
, const char *name
)
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
] == '='))
204 s
+= strspn (s
, " ");
205 if (*s
&& !spacep(s
))
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. */
216 skip_options (char *line
)
218 while ( *line
== '-' && line
[1] == '-' )
220 while (*line
&& !spacep (line
))
222 while (spacep (line
))
229 /* Replace all '+' by a blank. */
231 plus_to_blank (char *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. */
244 parse_hexstring (assuan_context_t ctx
, const char *string
, size_t *len
)
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");
255 return set_error (GPG_ERR_ASS_PARAMETER
, "odd number of digits");
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
264 parse_keygrip (assuan_context_t ctx
, const char *string
, unsigned char *buf
)
269 rc
= parse_hexstring (ctx
, string
, &n
);
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");
283 /* Write an assuan status line. */
285 agent_write_status (ctrl_t ctrl
, const char *keyword
, ...)
290 assuan_context_t ctx
= ctrl
->server_local
->assuan_ctx
;
294 va_start (arg_ptr
, keyword
);
298 while ( (text
= va_arg (arg_ptr
, const char *)) )
305 for ( ; *text
&& n
< DIM (buf
)-3; n
++, text
++)
312 else if (*text
== '\r')
322 err
= assuan_write_status (ctx
, keyword
, buf
);
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. */
333 agent_inq_pinentry_launched (ctrl_t ctrl
, unsigned long pid
)
337 if (!ctrl
|| !ctrl
->server_local
338 || !ctrl
->server_local
->allow_pinentry_notify
)
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
[] =
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"
354 "The currently defined counters are:\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.";
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];
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",
381 /* This function should be called once for all key removals or
382 additions. This function is assured not to do any context
385 bump_key_eventcounter (void)
391 /* This function should be called for all card reader status
392 changes. This function is assured not to do any context
395 bump_card_eventcounter (void)
404 static const char hlp_istrusted
[] =
405 "ISTRUSTED <hexstring_with_fingerprint>\n"
407 "Return OK when we have an entry with this fingerprint in our\n"
410 cmd_istrusted (assuan_context_t ctx
, char *line
)
412 ctrl_t ctrl
= assuan_get_pointer (ctx
);
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");
425 strcpy (fpr
, "00000000");
428 for (p
=line
; i
< 40; p
++, i
++)
429 fpr
[i
] = *p
>= 'a'? (*p
& 0xdf): *p
;
431 rc
= agent_istrusted (ctrl
, fpr
, NULL
);
432 if (!rc
|| gpg_err_code (rc
) == GPG_ERR_NOT_TRUSTED
)
434 else if (rc
== -1 || gpg_err_code (rc
) == GPG_ERR_EOF
)
435 return gpg_error (GPG_ERR_NOT_TRUSTED
);
438 log_error ("command is_trusted failed: %s\n", gpg_strerror (rc
));
444 static const char hlp_listtrusted
[] =
447 "List all entries from the trustlist.";
449 cmd_listtrusted (assuan_context_t ctx
, char *line
)
455 rc
= agent_listtrusted (ctx
);
457 log_error ("command listtrusted failed: %s\n", gpg_strerror (rc
));
462 static const char hlp_martrusted
[] =
463 "MARKTRUSTED <hexstring_with_fingerprint> <flag> <display_name>\n"
465 "Store a new key in into the trustlist.";
467 cmd_marktrusted (assuan_context_t ctx
, char *line
)
469 ctrl_t ctrl
= assuan_get_pointer (ctx
);
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");
483 strcpy (fpr
, "00000000");
486 for (p
=line
; i
< 40; p
++, i
++)
487 fpr
[i
] = *p
>= 'a'? (*p
& 0xdf): *p
;
493 if ( (flag
!= 'S' && flag
!= 'P') || !spacep (p
) )
494 return set_error (GPG_ERR_ASS_PARAMETER
, "invalid flag - must be P or S");
498 rc
= agent_marktrusted (ctrl
, p
, fpr
, flag
);
500 log_error ("command marktrusted failed: %s\n", gpg_strerror (rc
));
507 static const char hlp_havekey
[] =
508 "HAVEKEY <hexstring_with_keygrip>\n"
510 "Return success when the secret key is available.";
512 cmd_havekey (assuan_context_t ctx
, char *line
)
515 unsigned char buf
[20];
517 rc
= parse_keygrip (ctx
, line
, buf
);
521 if (agent_key_available (buf
))
522 return gpg_error (GPG_ERR_NO_SECKEY
);
528 static const char hlp_sigkey
[] =
529 "SIGKEY <hexstring_with_keygrip>\n"
530 "SETKEY <hexstring_with_keygrip>\n"
532 "Set the key used for a sign or decrypt operation.";
534 cmd_sigkey (assuan_context_t ctx
, char *line
)
537 ctrl_t ctrl
= assuan_get_pointer (ctx
);
539 rc
= parse_keygrip (ctx
, line
, ctrl
->keygrip
);
542 ctrl
->have_keygrip
= 1;
547 static const char hlp_setkeydesc
[] =
548 "SETKEYDESC plus_percent_escaped_string\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"
559 "The description is only valid for the next PKSIGN or PKDECRYPT\n"
562 cmd_setkeydesc (assuan_context_t ctx
, char *line
)
564 ctrl_t ctrl
= assuan_get_pointer (ctx
);
567 for (p
=line
; *p
== ' '; p
++)
570 p
= strchr (desc
, ' ');
572 *p
= 0; /* We ignore any garbage; we might late use it for other args. */
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
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 ();
591 static const char hlp_sethash
[] =
592 "SETHASH --hash=<name>|<algonumber> <hexstring>\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.";
597 cmd_sethash (assuan_context_t ctx
, char *line
)
602 ctrl_t ctrl
= assuan_get_pointer (ctx
);
607 /* Parse the alternative hash options which may be used instead of
609 if (has_option_name (line
, "--hash"))
611 if (has_option (line
, "--hash=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"))
625 else if (has_option (line
, "--hash=tls-md5sha1"))
626 algo
= MD_USER_TLS_MD5SHA1
;
628 return set_error (GPG_ERR_ASS_PARAMETER
, "invalid hash algorithm");
633 line
= skip_options (line
);
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. */
648 rc
= parse_hexstring (ctx
, line
, &n
);
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
++)
665 for (; n
< ctrl
->digest
.valuelen
; n
++)
671 static const char hlp_pksign
[] =
674 "Perform the actual sign operation. Neither input nor output are\n"
675 "sensitive to eavesdropping.";
677 cmd_pksign (assuan_context_t ctx
, char *line
)
680 cache_mode_t cache_mode
= CACHE_MODE_NORMAL
;
681 ctrl_t ctrl
= assuan_get_pointer (ctx
);
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
);
696 clear_outbuf (&outbuf
);
698 rc
= write_and_clear_outbuf (ctx
, &outbuf
);
700 log_error ("command pksign failed: %s\n", gpg_strerror (rc
));
701 xfree (ctrl
->server_local
->keydesc
);
702 ctrl
->server_local
->keydesc
= NULL
;
707 static const char hlp_pkdecrypt
[] =
708 "PKDECRYPT <options>\n"
710 "Perform the actual decrypt operation. Input is not\n"
711 "sensitive to eavesdropping.";
713 cmd_pkdecrypt (assuan_context_t ctx
, char *line
)
716 ctrl_t ctrl
= assuan_get_pointer (ctx
);
717 unsigned char *value
;
723 /* First inquire the data to decrypt */
724 rc
= assuan_inquire (ctx
, "CIPHERTEXT",
725 &value
, &valuelen
, MAXLEN_CIPHERTEXT
);
729 init_membuf (&outbuf
, 512);
731 rc
= agent_pkdecrypt (ctrl
, ctrl
->server_local
->keydesc
,
732 value
, valuelen
, &outbuf
);
735 clear_outbuf (&outbuf
);
737 rc
= write_and_clear_outbuf (ctx
, &outbuf
);
739 log_error ("command pkdecrypt failed: %s\n", gpg_strerror (rc
));
740 xfree (ctrl
->server_local
->keydesc
);
741 ctrl
->server_local
->keydesc
= NULL
;
746 static const char hlp_genkey
[] =
749 "Generate a new key, store the secret part and return the public\n"
750 "part. Here is an example transaction:\n"
753 " S: INQUIRE KEYPARAM\n"
754 " C: D (genkey (rsa (nbits 1024)))\n"
756 " S: D (public-key\n"
757 " S: D (rsa (n 326487324683264) (e 10001)))\n"
758 " S: OK key created\n"
761 cmd_genkey (assuan_context_t ctx
, char *line
)
763 ctrl_t ctrl
= assuan_get_pointer (ctx
);
765 unsigned char *value
;
771 /* First inquire the parameters */
772 rc
= assuan_inquire (ctx
, "KEYPARAM", &value
, &valuelen
, MAXLEN_KEYPARAM
);
776 init_membuf (&outbuf
, 512);
778 rc
= agent_genkey (ctrl
, (char*)value
, valuelen
, &outbuf
);
781 clear_outbuf (&outbuf
);
783 rc
= write_and_clear_outbuf (ctx
, &outbuf
);
785 log_error ("command genkey failed: %s\n", gpg_strerror (rc
));
792 static const char hlp_readkey
[] =
793 "READKEY <hexstring_with_keygrip>\n"
795 "Return the public key for the given keygrip.";
797 cmd_readkey (assuan_context_t ctx
, char *line
)
799 ctrl_t ctrl
= assuan_get_pointer (ctx
);
801 unsigned char grip
[20];
802 gcry_sexp_t s_pkey
= NULL
;
804 rc
= parse_keygrip (ctx
, line
, grip
);
806 return rc
; /* Return immediately as this is already an Assuan error code.*/
808 rc
= agent_public_key_from_file (ctrl
, grip
, &s_pkey
);
814 len
= gcry_sexp_sprint (s_pkey
, GCRYSEXP_FMT_CANON
, NULL
, 0);
816 buf
= xtrymalloc (len
);
818 rc
= gpg_error_from_syserror ();
821 len
= gcry_sexp_sprint (s_pkey
, GCRYSEXP_FMT_CANON
, buf
, len
);
823 rc
= assuan_send_data (ctx
, buf
, len
);
826 gcry_sexp_release (s_pkey
);
830 log_error ("command readkey failed: %s\n", gpg_strerror (rc
));
836 static const char hlp_keyinfo
[] =
837 "KEYINFO [--list] <keygrip>\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"
845 " KEYINFO <keygrip> <type> <serialno> <idstr>\n"
847 "KEYGRIP is the keygrip.\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"
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"
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"
861 "More information may be added in the future.";
863 do_one_keyinfo (ctrl_t ctrl
, const unsigned char *grip
)
868 unsigned char *shadow_info
= NULL
;
869 char *serialno
= NULL
;
871 const char *keytypestr
;
873 err
= agent_key_info_from_file (ctrl
, grip
, &keytype
, &shadow_info
);
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
)
883 else if (keytype
== PRIVATE_KEY_SHADOWED
)
890 err
= parse_shadow_info (shadow_info
, &serialno
, &idstr
);
895 err
= agent_write_status (ctrl
, "KEYINFO",
898 serialno
? serialno
: "-",
910 cmd_keyinfo (assuan_context_t ctx
, char *line
)
912 ctrl_t ctrl
= assuan_get_pointer (ctx
);
914 unsigned char grip
[20];
918 list_mode
= has_option (line
, "--list");
919 line
= skip_options (line
);
924 struct dirent
*dir_entry
;
927 dirname
= make_filename_try (opt
.homedir
, GNUPG_PRIVATE_KEYS_DIR
, NULL
);
930 err
= gpg_error_from_syserror ();
933 dir
= opendir (dirname
);
936 err
= gpg_error_from_syserror ();
942 while ( (dir_entry
= readdir (dir
)) )
944 if (strlen (dir_entry
->d_name
) != 44
945 || strcmp (dir_entry
->d_name
+ 40, ".key"))
947 strncpy (hexgrip
, dir_entry
->d_name
, 40);
950 if ( hex2bin (hexgrip
, grip
, 20) < 0 )
951 continue; /* Bad hex string. */
953 err
= do_one_keyinfo (ctrl
, grip
);
961 err
= parse_keygrip (ctx
, line
, grip
);
964 err
= do_one_keyinfo (ctrl
, grip
);
970 if (err
&& gpg_err_code (err
) != GPG_ERR_NOT_FOUND
)
971 log_error ("command keyinfo failed: %s\n", gpg_strerror (err
));
978 send_back_passphrase (assuan_context_t ctx
, int via_data
, const char *pw
)
983 assuan_begin_confidential (ctx
);
986 rc
= assuan_send_data (ctx
, pw
, n
);
989 char *p
= xtrymalloc_secure (n
*2+1);
991 rc
= gpg_error_from_syserror ();
995 rc
= assuan_set_okay_line (ctx
, p
);
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"
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"
1016 "If the option \"--data\" is used the passphrase is returned by usual\n"
1017 "data lines and not on the okay line.\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"
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"
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.)";
1031 cmd_get_passphrase (assuan_context_t ctx
, char *line
)
1033 ctrl_t ctrl
= assuan_get_pointer (ctx
);
1037 char *cacheid
= NULL
, *desc
= NULL
, *prompt
= NULL
, *errtext
= NULL
;
1038 const char *desc2
= _("Please re-enter this passphrase");
1041 int opt_data
, opt_check
, opt_no_ask
, opt_qualbar
;
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");
1052 opt_repeat
= atoi (p
);
1056 opt_qualbar
= has_option (line
, "--qualitybar");
1057 line
= skip_options (line
);
1060 p
= strchr (cacheid
, ' ');
1067 p
= strchr (errtext
, ' ');
1074 p
= strchr (prompt
, ' ');
1081 p
= strchr (desc
, ' ');
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");
1090 return set_error (GPG_ERR_ASS_PARAMETER
, "no description given");
1092 if (!strcmp (cacheid
, "X"))
1094 if (!strcmp (errtext
, "X"))
1096 if (!strcmp (prompt
, "X"))
1098 if (!strcmp (desc
, "X"))
1101 pw
= cacheid
? agent_get_cache (cacheid
, CACHE_MODE_NORMAL
, &cache_marker
)
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
);
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) */
1117 plus_to_blank (errtext
);
1119 plus_to_blank (prompt
);
1121 plus_to_blank (desc
);
1124 rc
= agent_get_passphrase (ctrl
, &response
, desc
, prompt
,
1125 repeat_errtext
? repeat_errtext
:errtext
,
1127 xfree (repeat_errtext
);
1128 repeat_errtext
= NULL
;
1133 if (opt_check
&& check_passphrase_constraints (ctrl
, response
, 0))
1138 for (i
= 0; i
< opt_repeat
; i
++)
1142 rc
= agent_get_passphrase (ctrl
, &response2
, desc2
, prompt
,
1146 if (strcmp (response2
, response
))
1150 repeat_errtext
= try_percent_escape
1151 (_("does not match - try again"), NULL
);
1152 if (!repeat_errtext
)
1154 rc
= gpg_error_from_syserror ();
1164 agent_put_cache (cacheid
, CACHE_MODE_USER
, response
, 0);
1165 rc
= send_back_passphrase (ctx
, opt_data
, response
);
1172 log_error ("command get_passphrase failed: %s\n", gpg_strerror (rc
));
1177 static const char hlp_clear_passphrase
[] =
1178 "CLEAR_PASSPHRASE <cache_id>\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.";
1183 cmd_clear_passphrase (assuan_context_t ctx
, char *line
)
1185 char *cacheid
= NULL
;
1188 /* parse the stuff */
1189 for (p
=line
; *p
== ' '; p
++)
1192 p
= strchr (cacheid
, ' ');
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);
1203 static const char hlp_get_confirmation
[] =
1204 "GET_CONFIRMATION <description>\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"
1215 cmd_get_confirmation (assuan_context_t ctx
, char *line
)
1217 ctrl_t ctrl
= assuan_get_pointer (ctx
);
1222 /* parse the stuff */
1223 for (p
=line
; *p
== ' '; p
++)
1226 p
= strchr (desc
, ' ');
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"))
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
1241 plus_to_blank (desc
);
1243 rc
= agent_get_confirmation (ctrl
, desc
, NULL
, NULL
, 0);
1245 log_error ("command get_confirmation failed: %s\n", gpg_strerror (rc
));
1251 static const char hlp_learn
[] =
1254 "Learn something about the currently inserted smartcard. With\n"
1255 "--send the new certificates are send back.";
1257 cmd_learn (assuan_context_t ctx
, char *line
)
1259 ctrl_t ctrl
= assuan_get_pointer (ctx
);
1262 rc
= agent_handle_learn (ctrl
, has_option (line
, "--send")? ctx
: NULL
);
1264 log_error ("command learn failed: %s\n", gpg_strerror (rc
));
1270 static const char hlp_passwd
[] =
1271 "PASSWD <hexstring_with_keygrip>\n"
1273 "Change the passphrase/PIN for the key identified by keygrip in LINE.";
1275 cmd_passwd (assuan_context_t ctx
, char *line
)
1277 ctrl_t ctrl
= assuan_get_pointer (ctx
);
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
);
1288 rc
= agent_key_from_file (ctrl
, ctrl
->server_local
->keydesc
,
1289 grip
, &shadow_info
, CACHE_MODE_IGNORE
, NULL
,
1295 log_error ("changing a smartcard PIN is not yet supported\n");
1296 rc
= gpg_error (GPG_ERR_NOT_IMPLEMENTED
);
1299 rc
= agent_protect_and_store (ctrl
, s_skey
);
1302 xfree (ctrl
->server_local
->keydesc
);
1303 ctrl
->server_local
->keydesc
= NULL
;
1306 gcry_sexp_release (s_skey
);
1307 xfree (shadow_info
);
1309 log_error ("command passwd failed: %s\n", gpg_strerror (rc
));
1314 static const char hlp_preset_passphrase
[] =
1315 "PRESET_PASSPHRASE <string_or_keygrip> <timeout> <hexstring>\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"
1323 cmd_preset_passphrase (assuan_context_t ctx
, char *line
)
1326 char *grip_clear
= NULL
;
1327 char *passphrase
= NULL
;
1331 if (!opt
.allow_preset_passphrase
)
1332 return set_error (GPG_ERR_NOT_SUPPORTED
, "no --allow-preset-passphrase");
1335 while (*line
&& (*line
!= ' ' && *line
!= '\t'))
1338 return gpg_error (GPG_ERR_MISSING_VALUE
);
1341 while (*line
&& (*line
== ' ' || *line
== '\t'))
1344 /* Currently, only infinite timeouts are allowed. */
1346 if (line
[0] != '-' || line
[1] != '1')
1347 return gpg_error (GPG_ERR_NOT_IMPLEMENTED
);
1350 while (!(*line
!= ' ' && *line
!= '\t'))
1353 /* Syntax check the hexstring. */
1355 rc
= parse_hexstring (ctx
, line
, &len
);
1360 /* If there is a passphrase, use it. Currently, a passphrase is
1364 /* Do in-place conversion. */
1366 if (!hex2str (passphrase
, passphrase
, strlen (passphrase
)+1, NULL
))
1367 rc
= set_error (GPG_ERR_ASS_PARAMETER
, "invalid hexstring");
1370 rc
= set_error (GPG_ERR_NOT_IMPLEMENTED
, "passphrase is required");
1373 rc
= agent_put_cache (grip_clear
, CACHE_MODE_ANY
, passphrase
, ttl
);
1376 log_error ("command preset_passphrase failed: %s\n", gpg_strerror (rc
));
1383 static const char hlp_scd
[] =
1384 "SCD <commands to pass to the scdaemon>\n"
1386 "This is a general quote command to redirect everything to the\n"
1389 cmd_scd (assuan_context_t ctx
, char *line
)
1391 ctrl_t ctrl
= assuan_get_pointer (ctx
);
1394 rc
= divert_generic_cmd (ctrl
, line
, ctx
);
1401 static const char hlp_getval
[] =
1404 "Return the value for KEY from the special environment as created by\n"
1407 cmd_getval (assuan_context_t ctx
, char *line
)
1412 struct putval_item_s
*vl
;
1414 for (p
=line
; *p
== ' '; p
++)
1417 p
= strchr (key
, ' ');
1421 for (; *p
== ' '; p
++)
1424 return set_error (GPG_ERR_ASS_PARAMETER
, "too many arguments");
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
) )
1434 if (vl
) /* Got an entry. */
1435 rc
= assuan_send_data (ctx
, vl
->d
+vl
->off
, vl
->len
);
1437 return gpg_error (GPG_ERR_NO_DATA
);
1440 log_error ("command getval failed: %s\n", gpg_strerror (rc
));
1445 static const char hlp_putval
[] =
1446 "PUTVAL <key> [<percent_escaped_value>]\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"
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.";
1464 cmd_putval (assuan_context_t ctx
, char *line
)
1469 size_t valuelen
= 0;
1471 struct putval_item_s
*vl
, *vlprev
;
1473 for (p
=line
; *p
== ' '; p
++)
1476 p
= strchr (key
, ' ');
1480 for (; *p
== ' '; p
++)
1485 p
= strchr (value
, ' ');
1488 valuelen
= percent_plus_unescape_inplace (value
, 0);
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
) )
1499 if (vl
) /* Delete old entry. */
1502 vlprev
->next
= vl
->next
;
1504 putval_list
= vl
->next
;
1508 if (valuelen
) /* Add entry. */
1510 vl
= xtrymalloc (sizeof *vl
+ strlen (key
) + valuelen
);
1512 rc
= gpg_error_from_syserror ();
1516 vl
->off
= strlen (key
) + 1;
1517 strcpy (vl
->d
, key
);
1518 memcpy (vl
->d
+ vl
->off
, value
, valuelen
);
1519 vl
->next
= putval_list
;
1525 log_error ("command putval failed: %s\n", gpg_strerror (rc
));
1532 static const char hlp_updatestartuptty
[] =
1533 "UPDATESTARTUPTTY\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.";
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;
1548 char *lc_ctype
= NULL
;
1549 char *lc_messages
= NULL
;
1553 se
= session_env_new ();
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
]);
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 ();
1574 session_env_release (se
);
1576 xfree (lc_messages
);
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
;
1593 #ifdef HAVE_W32_SYSTEM
1594 static const char hlp_killagent
[] =
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.";
1600 cmd_killagent (assuan_context_t ctx
, char *line
)
1602 ctrl_t ctrl
= assuan_get_pointer (ctx
);
1606 ctrl
->server_local
->stopme
= 1;
1607 return gpg_error (GPG_ERR_EOF
);
1611 static const char hlp_reloadagent
[] =
1614 "As signals are inconvenient under Windows, we provide this command\n"
1615 "to allow reloading of the configuration.";
1617 cmd_reloadagent (assuan_context_t ctx
, char *line
)
1622 agent_sighup_action ();
1625 #endif /*HAVE_W32_SYSTEM*/
1629 static const char hlp_getinfo
[] =
1632 "Multipurpose function to return a variety of information.\n"
1633 "Supported values for WHAT are:\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"
1641 " - Returns OK if the command CMD implements the option OPT.";
1643 cmd_getinfo (assuan_context_t ctx
, char *line
)
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"))
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 ();
1664 rc
= assuan_send_data (ctx
, s
, strlen (s
));
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 ();
1673 rc
= assuan_send_data (ctx
, s
, strlen (s
));
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]))
1686 while (*line
== ' ' || *line
== '\t')
1689 rc
= gpg_error (GPG_ERR_MISSING_VALUE
);
1693 while (*line
&& (*line
!= ' ' && *line
!= '\t'))
1696 rc
= gpg_error (GPG_ERR_MISSING_VALUE
);
1700 while (*line
== ' ' || *line
== '\t')
1703 rc
= gpg_error (GPG_ERR_MISSING_VALUE
);
1707 if (!command_has_option (cmd
, cmdopt
))
1708 rc
= gpg_error (GPG_ERR_GENERAL
);
1714 rc
= set_error (GPG_ERR_ASS_PARAMETER
, "unknown value for WHAT");
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"))
1743 err
= session_env_setenv (ctrl
->session_env
, "GPG_TTY", value
);
1745 else if (!strcmp (key
, "ttytype"))
1748 err
= session_env_setenv (ctrl
->session_env
, "TERM", value
);
1750 else if (!strcmp (key
, "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;
1779 err
= gpg_error (GPG_ERR_UNKNOWN_OPTION
);
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. */
1790 post_cmd_notify (assuan_context_t ctx
, gpg_error_t err
)
1792 ctrl_t ctrl
= assuan_get_pointer (ctx
);
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
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
);
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
1816 if (ctx
&& direction
== ASSUAN_IO_FROM_PEER
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. */
1830 command_has_option (const char *cmd
, const char *cmdopt
)
1832 if (!strcmp (cmd
, "GET_PASSPHRASE"))
1834 if (!strcmp (cmdopt
, "repeat"))
1842 /* Tell the assuan library about our commands */
1844 register_commands (assuan_context_t ctx
)
1848 assuan_handler_t handler
;
1849 const char * const help
;
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
},
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
},
1881 { "GETINFO", cmd_getinfo
, hlp_getinfo
},
1886 for (i
=0; table
[i
].name
; i
++)
1888 rc
= assuan_register_command (ctx
, table
[i
].name
, table
[i
].handler
,
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
);
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
1905 start_command_handler (ctrl_t ctrl
, gnupg_fd_t listen_fd
, gnupg_fd_t fd
)
1908 assuan_context_t ctx
= NULL
;
1910 rc
= assuan_new (&ctx
);
1913 log_error ("failed to allocate assuan context: %s\n", gpg_strerror (rc
));
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. */
1933 rc
= assuan_init_socket_server (ctx
, fd
, ASSUAN_SOCKET_SERVER_ACCEPTED
);
1937 log_error ("failed to initialize the server: %s\n",
1941 rc
= register_commands (ctx
);
1944 log_error ("failed to register commands with Assuan: %s\n",
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;
1957 assuan_set_log_stream (ctx
, log_get_stream ());
1959 assuan_set_io_monitor (ctx
, io_monitor
, NULL
);
1963 rc
= assuan_accept (ctx
);
1964 if (gpg_err_code (rc
) == GPG_ERR_EOF
|| rc
== -1)
1970 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc
));
1974 rc
= assuan_process (ctx
);
1977 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc
));
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
);
1989 assuan_release (ctx
);
1990 #ifdef HAVE_W32_SYSTEM
1991 if (ctrl
->server_local
->stopme
)
1994 xfree (ctrl
->server_local
);
1995 ctrl
->server_local
= NULL
;