changeset 2196:8811fe9d6ef0

Improve support for GnuPG v2+ If the gnupg engine detected is not 1.x, do not check the environment variable GPG_AGENT_INFO and do not set up a password callback.
author Mikael Berthe <mikael@lilotux.net>
date Wed, 07 Oct 2015 21:58:38 +0200
parents 40ddaebeb81e
children 189abf03ef24
files mcabber/mcabber/api.h mcabber/mcabber/main.c mcabber/mcabber/pgp.c mcabber/mcabber/pgp.h
diffstat 4 files changed, 67 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/mcabber/mcabber/api.h	Wed Oct 07 21:55:51 2015 +0200
+++ b/mcabber/mcabber/api.h	Wed Oct 07 21:58:38 2015 +0200
@@ -4,7 +4,7 @@
 #include <glib.h>
 #include <mcabber/config.h> // For MCABBER_BRANCH
 
-#define MCABBER_API_VERSION 38
+#define MCABBER_API_VERSION 39
 #define MCABBER_API_MIN     38
 
 #define MCABBER_BRANCH_DEV  1
--- a/mcabber/mcabber/main.c	Wed Oct 07 21:55:51 2015 +0200
+++ b/mcabber/mcabber/main.c	Wed Oct 07 21:58:38 2015 +0200
@@ -262,25 +262,39 @@
   bool pgp_agent;
   int retries;
 
+  pk = settings_opt_get("pgp_private_key");
+
+  if (!pk)
+    scr_LogPrint(LPRINT_LOGNORM, "WARNING: unknown PGP private key");
+
+  if (gpg_init(pk, NULL)) {
+    scr_LogPrint(LPRINT_LOGNORM, "WARNING: Could not initialize PGP.");
+    return;
+  }
+
+  // We're done if the PGP engine version is > 1
+  // since the agent is mandatory and password mechanism is external.
+  if (!gpg_is_version1())
+    return;
+
+
   p = getenv("GPG_AGENT_INFO");
   pgp_agent = (p && strchr(p, ':'));
 
-  pk = settings_opt_get("pgp_private_key");
-  pp = settings_opt_get("pgp_passphrase");
-
   if (settings_opt_get("pgp_passphrase_retries"))
     retries = settings_opt_get_int("pgp_passphrase_retries");
   else
     retries = 2;
 
+  pp = settings_opt_get("pgp_passphrase");
+
   if (!pk) {
-    scr_LogPrint(LPRINT_LOGNORM, "WARNING: unknown PGP private key");
     pgp_invalid = TRUE;
   } else if (!(pp || pgp_agent)) {
     // Request PGP passphrase
     pp = typed_passwd = ask_password("your PGP passphrase");
   }
-  gpg_init(pk, pp);
+  gpg_set_passphrase(pp);
   // Erase password from the settings array
   if (pp) {
     memset((char*)pp, 0, strlen(pp));
--- a/mcabber/mcabber/pgp.c	Wed Oct 07 21:55:51 2015 +0200
+++ b/mcabber/mcabber/pgp.c	Wed Oct 07 21:58:38 2015 +0200
@@ -38,7 +38,8 @@
 
 static struct gpg_struct
 {
-  int enabled;
+  int   enabled;
+  int   version1;
   char *private_key;
   char *passphrase;
 } gpg;
@@ -53,6 +54,9 @@
 {
   gpgme_error_t err;
 
+  gpgme_ctx_t ctx;
+  gpgme_engine_info_t info;
+
   // Check for version and OpenPGP protocol support.
   if (!gpgme_check_version(MIN_GPGME_VERSION)) {
     scr_LogPrint(LPRINT_LOGNORM,
@@ -75,10 +79,38 @@
   gpg_set_private_key(priv_key);
   gpg_set_passphrase(passphrase);
 
+  err = gpgme_new(&ctx);
+  if (err) return -1;
+
+  // Check OpenPGP engine version; with version 2+ the agent is mandatory
+  // and we do not manage the passphrase.
+  gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP);
+  if (err) return -1;
+
+  err = gpgme_get_engine_info (&info);
+  if (!err) {
+    while (info && info->protocol != gpgme_get_protocol (ctx))
+      info = info->next;
+
+    if (info && info->version) {
+      if (!strncmp(info->version, "1.", 2))
+        gpg.version1 = TRUE;
+      scr_log_print(LPRINT_DEBUG, "GPGME: Engine version is '%s'.",
+                    info->version);
+    }
+  }
+
   gpg.enabled = 1;
   return 0;
 }
 
+//  gpg_is_version1()
+// Return TRUE if the GnuPG OpenPGP engine version is 1.x
+int gpg_is_version1(void)
+{
+  return gpg.version1;
+}
+
 //  gpg_terminate()
 // Destroy data and free memory.
 void gpg_terminate(void)
@@ -264,7 +296,6 @@
 {
   gpgme_ctx_t ctx;
   gpgme_data_t in, out;
-  char *p;
   char *signed_data = NULL;
   size_t nread;
   gpgme_key_t key;
@@ -284,9 +315,12 @@
   gpgme_set_textmode(ctx, 0);
   gpgme_set_armor(ctx, 1);
 
-  p = getenv("GPG_AGENT_INFO");
-  if (!(p && strchr(p, ':')))
-    gpgme_set_passphrase_cb(ctx, passphrase_cb, 0);
+  if (gpg.version1) {
+    // GPG_AGENT_INFO isn't used by GnuPG version 2+
+    char *p = getenv("GPG_AGENT_INFO");
+    if (!(p && strchr(p, ':')))
+      gpgme_set_passphrase_cb(ctx, passphrase_cb, 0);
+  }
 
   err = gpgme_get_key(ctx, gpg.private_key, &key, 1);
   if (err || !key) {
@@ -332,7 +366,7 @@
 {
   gpgme_ctx_t ctx;
   gpgme_data_t in, out;
-  char *p, *data;
+  char *data;
   char *decrypted_data = NULL;
   size_t nread;
   gpgme_error_t err;
@@ -351,9 +385,12 @@
 
   gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP);
 
-  p = getenv("GPG_AGENT_INFO");
-  if (!(p && strchr(p, ':')))
-    gpgme_set_passphrase_cb(ctx, passphrase_cb, 0);
+  if (gpg.version1) {
+    // GPG_AGENT_INFO isn't used by GnuPG version 2+
+    char *p = getenv("GPG_AGENT_INFO");
+    if (!(p && strchr(p, ':')))
+      gpgme_set_passphrase_cb(ctx, passphrase_cb, 0);
+  }
 
   // Surround the given data with the prefix & suffix
   data = g_new(char, sizeof(prefix) + sizeof(suffix) + strlen(gpg_data));
--- a/mcabber/mcabber/pgp.h	Wed Oct 07 21:55:51 2015 +0200
+++ b/mcabber/mcabber/pgp.h	Wed Oct 07 21:58:38 2015 +0200
@@ -9,6 +9,7 @@
 #include <gpgme.h>
 
 int   gpg_init(const char *priv_key, const char *passphrase);
+int   gpg_is_version1(void);
 void  gpg_terminate(void);
 void  gpg_set_passphrase(const char *passphrase);
 void  gpg_set_private_key(const char *priv_keyid);