From b3c987234d02d603369d337ae02261b6acc25075 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Sat, 22 Dec 2012 18:35:48 -0500 Subject: [PATCH] Fix crash when/if gpg-agent dies. --- src/agent.c | 10 ++++------ src/commands.c | 32 ++++++++++++++++++++++++++------ src/crypto.c | 1 + src/pwmd.c | 6 +++--- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/agent.c b/src/agent.c index 83483f6f..96c0a979 100644 --- a/src/agent.c +++ b/src/agent.c @@ -132,7 +132,7 @@ static gpg_error_t launch_agent (struct agent_s *agent) { gpg_error_t rc; - assuan_context_t ctx; + assuan_context_t ctx = NULL; const char *t = NULL; static struct assuan_malloc_hooks mhooks = { xmalloc, xrealloc, xfree }; char *s, buf[LINE_MAX]; @@ -182,7 +182,8 @@ launch_agent (struct agent_s *agent) strv_free (fields); if (rc) { - assuan_release (ctx); + if (ctx) + assuan_release (ctx); return rc; } @@ -269,10 +270,7 @@ cleanup_agent (struct agent_s *agent) return; pinentry_free_opts (&agent->pinentry_opts); - - if (agent->ctx) - agent_disconnect (agent); - + agent_disconnect (agent); xfree (agent); } diff --git a/src/commands.c b/src/commands.c index 00e686cb..19c9b906 100644 --- a/src/commands.c +++ b/src/commands.c @@ -74,6 +74,22 @@ #define OPT_DATA 0x0400 #define OPT_NO_AGENT 0x0800 +#ifdef WITH_AGENT +/* The GETCONFIG command, for example, may fail because pwmd lost the + * gpg-agent connection. Update the recovered agent ctx. */ +#define UPDATE_AGENT_CTX(client, crypto) do { \ + if (crypto && crypto->agent && client->crypto && client->crypto->agent \ + && client->crypto->agent->ctx && \ + crypto->agent->ctx != client->crypto->agent->ctx) \ + { \ + client->crypto->agent->ctx = crypto->agent->ctx; \ + crypto->agent->ctx = NULL; \ + } \ + } while (0) +#else +#define UPDATE_AGENT_CTX(client, crypto) +#endif + struct command_table_s { const char *name; @@ -216,7 +232,7 @@ cleanup_client (struct client_s *client) #ifdef WITH_AGENT struct pinentry_option_s agent_pin_opts; - if (crypto->agent) + if (crypto && crypto->agent) memcpy (&agent_pin_opts, &crypto->agent->pinentry_opts, sizeof(struct pinentry_option_s)); #endif @@ -232,8 +248,9 @@ cleanup_client (struct client_s *client) memcpy (&client->pinentry_opts, &pin_opts, sizeof(struct pinentry_option_s)); client->flags |= no_pinentry ? FLAG_NO_PINENTRY : 0; #ifdef WITH_AGENT - memcpy (&crypto->agent->pinentry_opts, &agent_pin_opts, - sizeof(struct pinentry_option_s)); + if (crypto && crypto->agent) + memcpy (&crypto->agent->pinentry_opts, &agent_pin_opts, + sizeof(struct pinentry_option_s)); #endif } @@ -2380,7 +2397,7 @@ getconfig_command (assuan_context_t ctx, char *line) paramp = str_down (paramp); if (!strcmp (paramp, "cipher") && fp) { - struct crypto_s *crypto; + struct crypto_s *crypto = NULL; rc = init_client_crypto (&crypto); if (!rc) @@ -2399,6 +2416,7 @@ getconfig_command (assuan_context_t ctx, char *line) } } + UPDATE_AGENT_CTX (client, crypto); cleanup_crypto (&crypto); if (rc && gpg_err_code (rc) != GPG_ERR_ENOENT) return send_error (ctx, rc); @@ -2408,7 +2426,7 @@ getconfig_command (assuan_context_t ctx, char *line) } else if (!strcmp (paramp, "cipher_iterations") && fp) { - struct crypto_s *crypto; + struct crypto_s *crypto = NULL; rc = init_client_crypto (&crypto); if (!rc) @@ -2424,6 +2442,7 @@ getconfig_command (assuan_context_t ctx, char *line) } } + UPDATE_AGENT_CTX (client, crypto); cleanup_crypto (&crypto); if (rc && gpg_err_code (rc) != GPG_ERR_ENOENT) return send_error (ctx, rc); @@ -3980,7 +3999,7 @@ keygrip_command (assuan_context_t ctx, char *line) { struct client_s *client = assuan_get_pointer (ctx); gpg_error_t rc; - struct crypto_s *crypto; + struct crypto_s *crypto = NULL; struct argv_s *args[] = { &(struct argv_s) {"sign", OPTION_TYPE_NOARG, parse_keygrip_opt_sign}, NULL @@ -4028,6 +4047,7 @@ keygrip_command (assuan_context_t ctx, char *line) xfree (hexgrip); } + UPDATE_AGENT_CTX (client, crypto); cleanup_crypto (&crypto); return send_error (ctx, rc); } diff --git a/src/crypto.c b/src/crypto.c index 50851034..8a62f590 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -679,6 +679,7 @@ init_client_crypto (struct crypto_s **crypto) if (rc) { + cleanup_agent (new->agent); xfree (new); return rc; } diff --git a/src/pwmd.c b/src/pwmd.c index 18815e88..ce881ef8 100644 --- a/src/pwmd.c +++ b/src/pwmd.c @@ -148,7 +148,7 @@ catch_thread_signal (int sig, siginfo_t *info, void *ctx) static void cache_push_from_rcfile () { - struct crypto_s *crypto; + struct crypto_s *crypto = NULL; char **cache_push; gpg_error_t rc = init_client_crypto (&crypto); @@ -1059,7 +1059,7 @@ xml_import (const char *filename, const char *outfile, xmlChar *xmlbuf; xmlChar *xml; gpg_error_t rc; - struct crypto_s *crypto; + struct crypto_s *crypto = NULL; void *key = NULL; size_t keylen = 0; int algo = cipher ? cipher_string_to_gcrypt ((char *) cipher) : @@ -2675,7 +2675,7 @@ main (int argc, char *argv[]) */ if (cache_push) { - struct crypto_s *crypto; + struct crypto_s *crypto = NULL; gpg_error_t rc = init_client_crypto (&crypto); if (rc) -- 2.11.4.GIT