]> git.notmuchmail.org Git - notmuch/blob - util/crypto.c
crypto: move into libnotmuch_util
[notmuch] / util / crypto.c
1 /* notmuch - Not much of an email program, (just index and search)
2  *
3  * Copyright © 2012 Jameson Rollins
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see https://www.gnu.org/licenses/ .
17  *
18  * Authors: Jameson Rollins <jrollins@finestructure.net>
19  */
20
21 #include "crypto.h"
22 #include <strings.h>
23 #define unused(x) x __attribute__ ((unused))
24
25 #define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr[0]))
26
27 #if (GMIME_MAJOR_VERSION < 3)
28 /* Create a GPG context (GMime 2.6) */
29 static GMimeCryptoContext *
30 create_gpg_context (_notmuch_crypto_t *crypto)
31 {
32     GMimeCryptoContext *gpgctx;
33
34     if (crypto->gpgctx)
35         return crypto->gpgctx;
36
37     /* TODO: GMimePasswordRequestFunc */
38     gpgctx = g_mime_gpg_context_new (NULL, crypto->gpgpath ? crypto->gpgpath : "gpg");
39     if (! gpgctx) {
40         fprintf (stderr, "Failed to construct gpg context.\n");
41         return NULL;
42     }
43     crypto->gpgctx = gpgctx;
44
45     g_mime_gpg_context_set_use_agent ((GMimeGpgContext *) gpgctx, true);
46     g_mime_gpg_context_set_always_trust ((GMimeGpgContext *) gpgctx, false);
47
48     return gpgctx;
49 }
50
51 /* Create a PKCS7 context (GMime 2.6) */
52 static GMimeCryptoContext *
53 create_pkcs7_context (_notmuch_crypto_t *crypto)
54 {
55     GMimeCryptoContext *pkcs7ctx;
56
57     if (crypto->pkcs7ctx)
58         return crypto->pkcs7ctx;
59
60     /* TODO: GMimePasswordRequestFunc */
61     pkcs7ctx = g_mime_pkcs7_context_new (NULL);
62     if (! pkcs7ctx) {
63         fprintf (stderr, "Failed to construct pkcs7 context.\n");
64         return NULL;
65     }
66     crypto->pkcs7ctx = pkcs7ctx;
67
68     g_mime_pkcs7_context_set_always_trust ((GMimePkcs7Context *) pkcs7ctx,
69                                            false);
70
71     return pkcs7ctx;
72 }
73 static const struct {
74     const char *protocol;
75     GMimeCryptoContext *(*get_context) (_notmuch_crypto_t *crypto);
76 } protocols[] = {
77     {
78         .protocol = "application/pgp-signature",
79         .get_context = create_gpg_context,
80     },
81     {
82         .protocol = "application/pgp-encrypted",
83         .get_context = create_gpg_context,
84     },
85     {
86         .protocol = "application/pkcs7-signature",
87         .get_context = create_pkcs7_context,
88     },
89     {
90         .protocol = "application/x-pkcs7-signature",
91         .get_context = create_pkcs7_context,
92     },
93 };
94
95 /* for the specified protocol return the context pointer (initializing
96  * if needed) */
97 GMimeCryptoContext *
98 _notmuch_crypto_get_gmime_context (_notmuch_crypto_t *crypto, const char *protocol)
99 {
100     GMimeCryptoContext *cryptoctx = NULL;
101     size_t i;
102
103     if (! protocol) {
104         fprintf (stderr, "Cryptographic protocol is empty.\n");
105         return cryptoctx;
106     }
107
108     /* As per RFC 1847 section 2.1: "the [protocol] value token is
109      * comprised of the type and sub-type tokens of the Content-Type".
110      * As per RFC 1521 section 2: "Content-Type values, subtypes, and
111      * parameter names as defined in this document are
112      * case-insensitive."  Thus, we use strcasecmp for the protocol.
113      */
114     for (i = 0; i < ARRAY_SIZE (protocols); i++) {
115         if (strcasecmp (protocol, protocols[i].protocol) == 0)
116             return protocols[i].get_context (crypto);
117     }
118
119     fprintf (stderr, "Unknown or unsupported cryptographic protocol %s.\n",
120              protocol);
121
122     return NULL;
123 }
124
125 void
126 _notmuch_crypto_cleanup (_notmuch_crypto_t *crypto)
127 {
128     if (crypto->gpgctx) {
129         g_object_unref (crypto->gpgctx);
130         crypto->gpgctx = NULL;
131     }
132
133     if (crypto->pkcs7ctx) {
134         g_object_unref (crypto->pkcs7ctx);
135         crypto->pkcs7ctx = NULL;
136     }
137 }
138 #else
139 void _notmuch_crypto_cleanup (unused(_notmuch_crypto_t *crypto))
140 {
141 }
142 #endif