From d1fda93b2c6b34bd86144298ba7ab7747002eebd Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Thu, 10 Dec 2015 22:39:44 +1900 Subject: [PATCH] [PATCH 7/9] add a gpg_path value for notmuch_database_t --- 4e/28e9989209db194a821fb944f145698d7d517e | 242 ++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 4e/28e9989209db194a821fb944f145698d7d517e diff --git a/4e/28e9989209db194a821fb944f145698d7d517e b/4e/28e9989209db194a821fb944f145698d7d517e new file mode 100644 index 000000000..83e7f4fc1 --- /dev/null +++ b/4e/28e9989209db194a821fb944f145698d7d517e @@ -0,0 +1,242 @@ +Return-Path: +X-Original-To: notmuch@notmuchmail.org +Delivered-To: notmuch@notmuchmail.org +Received: from localhost (localhost [127.0.0.1]) + by arlo.cworth.org (Postfix) with ESMTP id 99EC46DE1601 + for ; Wed, 9 Dec 2015 19:40:15 -0800 (PST) +X-Virus-Scanned: Debian amavisd-new at cworth.org +X-Spam-Flag: NO +X-Spam-Score: -0.033 +X-Spam-Level: +X-Spam-Status: No, score=-0.033 tagged_above=-999 required=5 + tests=[AWL=-0.033] autolearn=disabled +Received: from arlo.cworth.org ([127.0.0.1]) + by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id sMav7f67XOXL for ; + Wed, 9 Dec 2015 19:40:13 -0800 (PST) +Received: from che.mayfirst.org (che.mayfirst.org [209.234.253.108]) + by arlo.cworth.org (Postfix) with ESMTP id 9D7606DE18EC + for ; Wed, 9 Dec 2015 19:40:06 -0800 (PST) +Received: from fifthhorseman.net (unknown [38.109.115.130]) + by che.mayfirst.org (Postfix) with ESMTPSA id 5965FF989 + for ; Wed, 9 Dec 2015 22:40:04 -0500 (EST) +Received: by fifthhorseman.net (Postfix, from userid 1000) + id BC38D21227; Wed, 9 Dec 2015 22:40:03 -0500 (EST) +From: Daniel Kahn Gillmor +To: Notmuch Mail +Subject: [PATCH 7/9] add a gpg_path value for notmuch_database_t +Date: Wed, 9 Dec 2015 22:39:44 -0500 +Message-Id: <1449718786-28000-8-git-send-email-dkg@fifthhorseman.net> +X-Mailer: git-send-email 2.6.2 +In-Reply-To: <1449718786-28000-1-git-send-email-dkg@fifthhorseman.net> +References: <1449718786-28000-1-git-send-email-dkg@fifthhorseman.net> +X-BeenThere: notmuch@notmuchmail.org +X-Mailman-Version: 2.1.20 +Precedence: list +List-Id: "Use and development of the notmuch mail system." + +List-Unsubscribe: , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: , + +X-List-Received-Date: Thu, 10 Dec 2015 03:40:16 -0000 + +Exposing this to the user of the library lets the user point to +arbitrary gpg executables when trying to decrypt. +--- + lib/database-private.h | 3 ++ + lib/database.cc | 93 +++++++++++++++++++++++++++++++++++++++++++------- + lib/notmuch.h | 31 +++++++++++++++++ + 3 files changed, 115 insertions(+), 12 deletions(-) + +diff --git a/lib/database-private.h b/lib/database-private.h +index 1bf76c5..9a35044 100644 +--- a/lib/database-private.h ++++ b/lib/database-private.h +@@ -171,6 +171,9 @@ struct _notmuch_database { + * notmuch_database_new_revision. */ + unsigned long revision; + const char *uuid; ++ ++ /* can be NULL, meaning "try to find gpg2 or gpg if possible" */ ++ char *gpg_path; + GMimeCryptoContext *gpg_crypto_ctx; + + Xapian::QueryParser *query_parser; +diff --git a/lib/database.cc b/lib/database.cc +index d0e8800..c40ce77 100644 +--- a/lib/database.cc ++++ b/lib/database.cc +@@ -996,6 +996,7 @@ notmuch_database_open_verbose (const char *path, + notmuch, notmuch->xapian_db->get_uuid ().c_str ()); + + notmuch->gpg_crypto_ctx = NULL; ++ notmuch->gpg_path = NULL; + + notmuch->query_parser = new Xapian::QueryParser; + notmuch->term_gen = new Xapian::TermGenerator; +@@ -1096,6 +1097,10 @@ notmuch_database_close (notmuch_database_t *notmuch) + g_object_unref (notmuch->gpg_crypto_ctx); + notmuch->gpg_crypto_ctx = NULL; + } ++ if (notmuch->gpg_path) { ++ talloc_free(notmuch->gpg_path); ++ notmuch->gpg_path = NULL; ++ } + + return status; + } +@@ -2393,17 +2398,6 @@ _notmuch_database_link_message (notmuch_database_t *notmuch, + return status; + } + +-static const char* +-_notmuch_database_get_gpg_path (notmuch_database_t *notmuch) +-{ +-#define try_gpg_path(z) if (!access(z, X_OK)) return z +- try_gpg_path("/usr/bin/gpg2"); +- try_gpg_path("/bin/gpg2"); +- try_gpg_path("/usr/bin/gpg"); +- try_gpg_path("/bin/gpg"); +- return NULL; +-} +- + notmuch_private_status_t + _notmuch_database_get_crypto_for_protocol (notmuch_database_t *notmuch, + const char *protocol, +@@ -2425,7 +2419,7 @@ _notmuch_database_get_crypto_for_protocol (notmuch_database_t *notmuch, + * here? how would this config get into the library? Is + * this an option we can set on the database object? Or + * elsewhere? */ +- notmuch->gpg_crypto_ctx = g_mime_gpg_context_new (NULL, _notmuch_database_get_gpg_path(notmuch)); ++ notmuch->gpg_crypto_ctx = g_mime_gpg_context_new (NULL, notmuch_database_get_gpg_path(notmuch)); + if (! notmuch->gpg_crypto_ctx) + return NOTMUCH_PRIVATE_STATUS_FAILED_CRYPTO_CONTEXT_CREATION; + +@@ -2752,3 +2746,78 @@ notmuch_database_status_string (const notmuch_database_t *notmuch) + { + return notmuch->status_string; + } ++ ++ ++static notmuch_bool_t ++_find_in_path(const char* path) ++{ ++ char *c = NULL, *save = NULL, *tok; ++ size_t n; ++ int dfd = -1; ++ notmuch_bool_t ret = FALSE; ++ ++ n = confstr(_CS_PATH, NULL, 0); ++ c = (char*)talloc_size(NULL, n); ++ if (!c) ++ return FALSE; ++ confstr(_CS_PATH, c, n); ++ ++ tok = strtok_r(c, ":", &save); ++ while (tok) { ++ dfd = open(tok, O_DIRECTORY | O_RDONLY); ++ if (dfd != -1) { ++ if (!faccessat(dfd, path, X_OK, 0)) { ++ ret = TRUE; ++ goto done; ++ } ++ close(dfd); ++ } ++ tok = strtok_r(NULL, ":", &save); ++ } ++done: ++ if (dfd != -1) ++ close(dfd); ++ if (c) ++ talloc_free(c); ++ return ret; ++} ++ ++notmuch_status_t ++notmuch_database_set_gpg_path (notmuch_database_t *notmuch, const char* path) ++{ ++ /* return success if this matches what is already configured */ ++ if ((!path && !notmuch->gpg_path) || ++ (path && notmuch->gpg_path && 0 == strcmp(path, notmuch->gpg_path))) ++ return NOTMUCH_STATUS_SUCCESS; ++ ++ if (!path && !_find_in_path(path)) ++ return NOTMUCH_STATUS_FILE_ERROR; ++ ++ /* clear any existing gpg_crypto_ctx, since things are changing */ ++ if (notmuch->gpg_crypto_ctx) { ++ g_object_unref (notmuch->gpg_crypto_ctx); ++ notmuch->gpg_crypto_ctx = NULL; ++ } ++ ++ if (notmuch->gpg_path) { ++ talloc_free(notmuch->gpg_path); ++ notmuch->gpg_path = NULL; ++ } ++ ++ if (path) ++ notmuch->gpg_path = talloc_strdup (notmuch, path); ++ ++ return NOTMUCH_STATUS_SUCCESS; ++} ++ ++const char* ++notmuch_database_get_gpg_path (const notmuch_database_t *notmuch) ++{ ++ if (notmuch->gpg_path) ++ return notmuch->gpg_path; ++ ++#define try_gpg_path(z) if (_find_in_path(z)) return z ++ try_gpg_path("gpg2"); ++ try_gpg_path("gpg"); ++ return NULL; ++} +diff --git a/lib/notmuch.h b/lib/notmuch.h +index 809a2ea..e9cfed3 100644 +--- a/lib/notmuch.h ++++ b/lib/notmuch.h +@@ -591,6 +591,37 @@ notmuch_database_add_message_try_decrypt (notmuch_database_t *database, + notmuch_message_t **message); + + /** ++ * Tell the notmuch database where to find GnuPG. ++ * ++ * This is only useful when notmuch might try to use GnuPG to decrypt ++ * MIME parts (see for example ++ * notmuch_database_add_message_try_decrypt). The argument needs to ++ * be an executable version of gpg. ++ * ++ * If this function has never been invoked, notmuch will try to find ++ * gpg in reasonable places. ++ * ++ * This value is not currently stored in the database on disk, it is ++ * only used for this notmuch_database_t while it exists. ++ * ++ * Return value: ++ * ++ * NOTMUCH_STATUS_SUCCESS: the path was accepted and will be used. ++ * ++ * NOTMUCH_STATUS_FILE_ERROR: the path given either wasn't found or ++ * wasn't executable. ++ */ ++notmuch_status_t ++notmuch_database_set_gpg_path (notmuch_database_t *database, const char* path); ++ ++/** ++ * Find out where the notmuch database will try to find gpg if it ++ * needs to use it. ++ */ ++const char* ++notmuch_database_get_gpg_path (const notmuch_database_t *database); ++ ++/** + * Remove a message filename from the given notmuch database. If the + * message has no more filenames, remove the message. + * +-- +2.6.2 + -- 2.26.2