From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by arlo.cworth.org (Postfix) with ESMTP id 600AD6DE0243 for ; Sat, 14 Oct 2017 23:48:19 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at cworth.org X-Spam-Flag: NO X-Spam-Score: -0.035 X-Spam-Level: X-Spam-Status: No, score=-0.035 tagged_above=-999 required=5 tests=[AWL=-0.035] 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 RPS-dAin9go2 for ; Sat, 14 Oct 2017 23:48:18 -0700 (PDT) Received: from che.mayfirst.org (che.mayfirst.org [162.247.75.118]) by arlo.cworth.org (Postfix) with ESMTP id 1EC956DE024A for ; Sat, 14 Oct 2017 23:48:16 -0700 (PDT) Received: from fifthhorseman.net (ool-6c3a0662.static.optonline.net [108.58.6.98]) by che.mayfirst.org (Postfix) with ESMTPSA id 3DD2AF9A0 for ; Sun, 15 Oct 2017 02:48:15 -0400 (EDT) Received: by fifthhorseman.net (Postfix, from userid 1000) id 6D14320628; Sun, 15 Oct 2017 02:48:11 -0400 (EDT) From: Daniel Kahn Gillmor To: Notmuch Mail Subject: [PATCH v5 02/12] crypto: make shared crypto code behave library-like Date: Sun, 15 Oct 2017 02:47:57 -0400 Message-Id: <20171015064807.14205-3-dkg@fifthhorseman.net> X-Mailer: git-send-email 2.14.2 In-Reply-To: <20171015064807.14205-1-dkg@fifthhorseman.net> References: <20171015064807.14205-1-dkg@fifthhorseman.net> X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.23 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: Sun, 15 Oct 2017 06:48:19 -0000 If we're going to reuse the crypto code across both the library and the client, then it needs to report error states properly and not write to stderr. --- lib/database.cc | 6 ++++ lib/notmuch.h | 17 +++++++++++ mime-node.c | 7 ++++- util/crypto.c | 92 ++++++++++++++++++++++++++++----------------------------- util/crypto.h | 7 +++-- 5 files changed, 79 insertions(+), 50 deletions(-) diff --git a/lib/database.cc b/lib/database.cc index 35c66939..02444e09 100644 --- a/lib/database.cc +++ b/lib/database.cc @@ -413,6 +413,12 @@ notmuch_status_to_string (notmuch_status_t status) return "Operation requires a database upgrade"; case NOTMUCH_STATUS_PATH_ERROR: return "Path supplied is illegal for this function"; + case NOTMUCH_STATUS_MALFORMED_CRYPTO_PROTOCOL: + return "Crypto protocol missing, malformed, or unintelligible"; + case NOTMUCH_STATUS_FAILED_CRYPTO_CONTEXT_CREATION: + return "Crypto engine initialization failure"; + case NOTMUCH_STATUS_UNKNOWN_CRYPTO_PROTOCOL: + return "Unknown crypto protocol"; default: case NOTMUCH_STATUS_LAST_STATUS: return "Unknown error status value"; diff --git a/lib/notmuch.h b/lib/notmuch.h index e8e0cc12..669e01b1 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -191,6 +191,23 @@ typedef enum _notmuch_status { * function, in a way not covered by a more specific argument. */ NOTMUCH_STATUS_ILLEGAL_ARGUMENT, + /** + * A MIME object claimed to have cryptographic protection which + * notmuch tried to handle, but the protocol was not specified in + * an intelligible way. + */ + NOTMUCH_STATUS_MALFORMED_CRYPTO_PROTOCOL, + /** + * Notmuch attempted to do crypto processing, but could not + * initialize the engine needed to do so. + */ + NOTMUCH_STATUS_FAILED_CRYPTO_CONTEXT_CREATION, + /** + * A MIME object claimed to have cryptographic protection, and + * notmuch attempted to process it, but the specific protocol was + * something that notmuch doesn't know how to handle. + */ + NOTMUCH_STATUS_UNKNOWN_CRYPTO_PROTOCOL, /** * Not an actual status value. Just a way to find out how many * valid status values there are. diff --git a/mime-node.c b/mime-node.c index d48be4c4..c3d5cb9b 100644 --- a/mime-node.c +++ b/mime-node.c @@ -269,7 +269,12 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) || (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->verify)) { GMimeContentType *content_type = g_mime_object_get_content_type (part); const char *protocol = g_mime_content_type_get_parameter (content_type, "protocol"); - cryptoctx = _notmuch_crypto_get_gmime_context (node->ctx->crypto, protocol); + notmuch_status_t status; + status = _notmuch_crypto_get_gmime_ctx_for_protocol (node->ctx->crypto, + protocol, &cryptoctx); + if (status) /* this is a warning, not an error */ + fprintf (stderr, "Warning: %s (%s).\n", notmuch_status_to_string (status), + protocol ? protocol : "NULL"); if (!cryptoctx) return NULL; } diff --git a/util/crypto.c b/util/crypto.c index c51d67ed..5c84282e 100644 --- a/util/crypto.c +++ b/util/crypto.c @@ -25,85 +25,86 @@ #define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr[0])) #if (GMIME_MAJOR_VERSION < 3) -/* Create a GPG context (GMime 2.6) */ -static GMimeCryptoContext * -create_gpg_context (_notmuch_crypto_t *crypto) +/* Create or pass on a GPG context (GMime 2.6) */ +static notmuch_status_t +get_gpg_context (_notmuch_crypto_t *crypto, GMimeCryptoContext **ctx) { - GMimeCryptoContext *gpgctx; + if (ctx == NULL || crypto == NULL) + return NOTMUCH_STATUS_NULL_POINTER; - if (crypto->gpgctx) - return crypto->gpgctx; + if (crypto->gpgctx) { + *ctx = crypto->gpgctx; + return NOTMUCH_STATUS_SUCCESS; + } /* TODO: GMimePasswordRequestFunc */ - gpgctx = g_mime_gpg_context_new (NULL, crypto->gpgpath ? crypto->gpgpath : "gpg"); - if (! gpgctx) { - fprintf (stderr, "Failed to construct gpg context.\n"); - return NULL; + crypto->gpgctx = g_mime_gpg_context_new (NULL, crypto->gpgpath ? crypto->gpgpath : "gpg"); + if (! crypto->gpgctx) { + return NOTMUCH_STATUS_FAILED_CRYPTO_CONTEXT_CREATION; } - crypto->gpgctx = gpgctx; - g_mime_gpg_context_set_use_agent ((GMimeGpgContext *) gpgctx, true); - g_mime_gpg_context_set_always_trust ((GMimeGpgContext *) gpgctx, false); + g_mime_gpg_context_set_use_agent ((GMimeGpgContext *) crypto->gpgctx, true); + g_mime_gpg_context_set_always_trust ((GMimeGpgContext *) crypto->gpgctx, false); - return gpgctx; + *ctx = crypto->gpgctx; + return NOTMUCH_STATUS_SUCCESS; } -/* Create a PKCS7 context (GMime 2.6) */ -static GMimeCryptoContext * -create_pkcs7_context (_notmuch_crypto_t *crypto) +/* Create or pass on a PKCS7 context (GMime 2.6) */ +static notmuch_status_t +get_pkcs7_context (_notmuch_crypto_t *crypto, GMimeCryptoContext **ctx) { - GMimeCryptoContext *pkcs7ctx; + if (ctx == NULL || crypto == NULL) + return NOTMUCH_STATUS_NULL_POINTER; - if (crypto->pkcs7ctx) - return crypto->pkcs7ctx; + if (crypto->pkcs7ctx) { + *ctx = crypto->pkcs7ctx; + return NOTMUCH_STATUS_SUCCESS; + } /* TODO: GMimePasswordRequestFunc */ - pkcs7ctx = g_mime_pkcs7_context_new (NULL); - if (! pkcs7ctx) { - fprintf (stderr, "Failed to construct pkcs7 context.\n"); - return NULL; + crypto->pkcs7ctx = g_mime_pkcs7_context_new (NULL); + if (! crypto->pkcs7ctx) { + return NOTMUCH_STATUS_FAILED_CRYPTO_CONTEXT_CREATION; } - crypto->pkcs7ctx = pkcs7ctx; - g_mime_pkcs7_context_set_always_trust ((GMimePkcs7Context *) pkcs7ctx, + g_mime_pkcs7_context_set_always_trust ((GMimePkcs7Context *) crypto->pkcs7ctx, false); - return pkcs7ctx; + *ctx = crypto->pkcs7ctx; + return NOTMUCH_STATUS_SUCCESS; } static const struct { const char *protocol; - GMimeCryptoContext *(*get_context) (_notmuch_crypto_t *crypto); + notmuch_status_t (*get_context) (_notmuch_crypto_t *crypto, GMimeCryptoContext **ctx); } protocols[] = { { .protocol = "application/pgp-signature", - .get_context = create_gpg_context, + .get_context = get_gpg_context, }, { .protocol = "application/pgp-encrypted", - .get_context = create_gpg_context, + .get_context = get_gpg_context, }, { .protocol = "application/pkcs7-signature", - .get_context = create_pkcs7_context, + .get_context = get_pkcs7_context, }, { .protocol = "application/x-pkcs7-signature", - .get_context = create_pkcs7_context, + .get_context = get_pkcs7_context, }, }; /* for the specified protocol return the context pointer (initializing * if needed) */ -GMimeCryptoContext * -_notmuch_crypto_get_gmime_context (_notmuch_crypto_t *crypto, const char *protocol) +notmuch_status_t +_notmuch_crypto_get_gmime_ctx_for_protocol (_notmuch_crypto_t *crypto, + const char *protocol, + GMimeCryptoContext **ctx) { - GMimeCryptoContext *cryptoctx = NULL; - size_t i; - - if (! protocol) { - fprintf (stderr, "Cryptographic protocol is empty.\n"); - return cryptoctx; - } + if (! protocol) + return NOTMUCH_STATUS_MALFORMED_CRYPTO_PROTOCOL; /* As per RFC 1847 section 2.1: "the [protocol] value token is * comprised of the type and sub-type tokens of the Content-Type". @@ -111,15 +112,12 @@ _notmuch_crypto_get_gmime_context (_notmuch_crypto_t *crypto, const char *protoc * parameter names as defined in this document are * case-insensitive." Thus, we use strcasecmp for the protocol. */ - for (i = 0; i < ARRAY_SIZE (protocols); i++) { + for (size_t i = 0; i < ARRAY_SIZE (protocols); i++) { if (strcasecmp (protocol, protocols[i].protocol) == 0) - return protocols[i].get_context (crypto); + return protocols[i].get_context (crypto, ctx); } - fprintf (stderr, "Unknown or unsupported cryptographic protocol %s.\n", - protocol); - - return NULL; + return NOTMUCH_STATUS_UNKNOWN_CRYPTO_PROTOCOL; } void diff --git a/util/crypto.h b/util/crypto.h index 80628dc5..1ff0297d 100644 --- a/util/crypto.h +++ b/util/crypto.h @@ -4,6 +4,7 @@ #include #if (GMIME_MAJOR_VERSION < 3) #include "gmime-extra.h" +#include "notmuch.h" #endif typedef struct _notmuch_crypto { @@ -18,8 +19,10 @@ typedef struct _notmuch_crypto { #if (GMIME_MAJOR_VERSION < 3) -GMimeCryptoContext * -_notmuch_crypto_get_gmime_context (_notmuch_crypto_t *crypto, const char *protocol); +notmuch_status_t +_notmuch_crypto_get_gmime_ctx_for_protocol (_notmuch_crypto_t *crypto, + const char *protocol, + GMimeCryptoContext **ctx); #endif void -- 2.14.2