Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief test suite for the gpgme plugin.
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : * @author Peter Nirschl
8 : *
9 : */
10 :
11 : #include <gpgme.h>
12 : #include <kdbinternal.h>
13 : #include <locale.h>
14 : #include <stdio.h>
15 : #include <stdlib.h>
16 : #include <string.h>
17 : #include <tests_internal.h>
18 : #include <tests_plugin.h>
19 : #include <unistd.h>
20 :
21 : #include "gpgme.h"
22 :
23 : #include "../crypto/gpgagent_teardown.h"
24 :
25 : // GPG private key for importing and testing
26 : #include "../crypto/test_key.h"
27 :
28 : #define TEST_KEY_ID "DDEBEF9EE2DC931701338212DAF635B17F230E8D"
29 : #define GPGME_PLUGIN_NAME "gpgme"
30 : #define KEYNAME_UNCHANGED "user:/crypto/test/nochange"
31 : #define KEYNAME_NULL "user:/crypto/test/mynull"
32 : #define KEYNAME_STRING "user:/crypto/test/mystring"
33 : #define KEYNAME_BIN "user:/crypto/test/mybin"
34 :
35 : static const char strVal[] = "gpgme test value";
36 : static const kdb_octet_t binVal[] = { 0xCA, 0xFE, 0xBA, 0xBE };
37 :
38 : static inline ssize_t MIN (ssize_t a, ssize_t b)
39 : {
40 6 : return (a < b) ? a : b;
41 : }
42 :
43 2 : static void init_gpgme (void)
44 : {
45 2 : gpgme_error_t err;
46 :
47 2 : gpgme_check_version (NULL);
48 : // NOTE the code below is recommended by the gpgme manual
49 : // gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
50 : //#ifndef HAVE_W32_SYSTEM
51 : // gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
52 : //#endif
53 :
54 2 : err = gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP);
55 2 : succeed_if (!err, "failed to initialize gpgme");
56 2 : }
57 :
58 4 : static KeySet * newPluginConfiguration (void)
59 : {
60 4 : return ksNew (3, keyNew (ELEKTRA_RECIPIENT_KEY, KEY_VALUE, TEST_KEY_ID, KEY_END),
61 : keyNew (ELEKTRA_GPGME_CONFIG_TEXTMODE, KEY_VALUE, "0", KEY_END),
62 : keyNew (ELEKTRA_GPGME_UNIT_TEST, KEY_VALUE, "1", KEY_END), KS_END);
63 : }
64 :
65 4 : static KeySet * newTestdataKeySet (void)
66 : {
67 4 : Key * kUnchanged = keyNew (KEYNAME_UNCHANGED, KEY_END);
68 4 : Key * kNull = keyNew (KEYNAME_NULL, KEY_END);
69 4 : Key * kString = keyNew (KEYNAME_STRING, KEY_END);
70 4 : Key * kBin = keyNew (KEYNAME_BIN, KEY_END);
71 :
72 4 : keySetString (kUnchanged, strVal);
73 :
74 4 : keySetBinary (kNull, NULL, 0);
75 4 : keySetMeta (kNull, ELEKTRA_GPGME_META_ENCRYPT, "1");
76 :
77 4 : keySetString (kString, strVal);
78 4 : keySetMeta (kString, ELEKTRA_GPGME_META_ENCRYPT, "1");
79 :
80 4 : keySetBinary (kBin, binVal, sizeof (binVal));
81 4 : keySetMeta (kBin, ELEKTRA_GPGME_META_ENCRYPT, "1");
82 :
83 4 : return ksNew (4, kUnchanged, kNull, kString, kBin, KS_END);
84 : }
85 :
86 2 : static void test_import_key (void)
87 : {
88 2 : gpgme_error_t err;
89 2 : gpgme_data_t keydata;
90 2 : gpgme_import_result_t result;
91 2 : gpgme_ctx_t ctx;
92 :
93 2 : err = gpgme_new (&ctx);
94 2 : succeed_if (!err, "failed to initialize gpgme handle");
95 :
96 2 : err = gpgme_data_new_from_mem (&keydata, (const char *) test_key_asc, test_key_asc_len, 1);
97 2 : succeed_if (!err, "failed to transform the test key to gpgme data structure");
98 :
99 2 : err = gpgme_op_import (ctx, keydata);
100 2 : succeed_if (!err, "failed to import GPG test key");
101 :
102 2 : if (!err)
103 : {
104 2 : result = gpgme_op_import_result (ctx);
105 2 : succeed_if (result->imported + result->unchanged == 1, "the GPG import failed");
106 : }
107 :
108 2 : gpgme_data_release (keydata);
109 2 : gpgme_release (ctx);
110 2 : }
111 :
112 2 : static void test_init (void)
113 : {
114 2 : Plugin * plugin = NULL;
115 2 : Key * parentKey = keyNew ("system:/", KEY_END);
116 2 : KeySet * modules = ksNew (0, KS_END);
117 2 : KeySet * configKs = newPluginConfiguration ();
118 2 : elektraModulesInit (modules, 0);
119 :
120 2 : plugin = elektraPluginOpen (GPGME_PLUGIN_NAME, modules, configKs, 0);
121 2 : succeed_if (plugin != 0, "failed to open the plugin");
122 2 : if (plugin)
123 : {
124 2 : succeed_if (!strcmp (plugin->name, GPGME_PLUGIN_NAME), "got wrong name");
125 :
126 2 : KeySet * config = elektraPluginGetConfig (plugin);
127 2 : succeed_if (config != 0, "there should be a config");
128 :
129 2 : succeed_if (plugin->kdbOpen != 0, "no open pointer");
130 2 : succeed_if (plugin->kdbClose != 0, "no close pointer");
131 2 : succeed_if (plugin->kdbGet != 0, "no get pointer");
132 2 : succeed_if (plugin->kdbSet != 0, "no set pointer");
133 :
134 : // try re-opening the plugin
135 2 : succeed_if (plugin->kdbClose (plugin, parentKey) == 1, "kdb close failed");
136 2 : succeed_if (plugin->kdbOpen (plugin, parentKey) == 1, "re-opening the plugin failed");
137 2 : succeed_if (plugin->kdbClose (plugin, parentKey) == 1, "kdb close failed");
138 :
139 2 : elektraPluginClose (plugin, 0);
140 : }
141 :
142 2 : elektraModulesClose (modules, 0);
143 2 : ksDel (modules);
144 2 : keyDel (parentKey);
145 2 : }
146 :
147 2 : static void test_incomplete_config (void)
148 : {
149 2 : Plugin * plugin = NULL;
150 2 : Key * parentKey = keyNew ("system:/", KEY_END);
151 2 : KeySet * modules = ksNew (0, KS_END);
152 2 : KeySet * configKs = ksNew (0, KS_END);
153 2 : elektraModulesInit (modules, 0);
154 :
155 2 : plugin = elektraPluginOpen (GPGME_PLUGIN_NAME, modules, configKs, 0);
156 2 : succeed_if (plugin != 0, "failed to open the plugin");
157 2 : if (plugin)
158 : {
159 2 : KeySet * data = newTestdataKeySet ();
160 2 : succeed_if (plugin->kdbSet (plugin, data, parentKey) == -1, "kdb set succeeded with incomplete configuration");
161 2 : ksDel (data);
162 2 : elektraPluginClose (plugin, 0);
163 : }
164 :
165 2 : elektraModulesClose (modules, 0);
166 2 : ksDel (modules);
167 2 : keyDel (parentKey);
168 2 : }
169 :
170 2 : static void test_encryption_decryption (void)
171 : {
172 2 : Plugin * plugin = NULL;
173 2 : Key * parentKey = keyNew ("system:/", KEY_END);
174 2 : KeySet * modules = ksNew (0, KS_END);
175 2 : KeySet * config = newPluginConfiguration ();
176 :
177 2 : elektraModulesInit (modules, 0);
178 :
179 2 : plugin = elektraPluginOpen (GPGME_PLUGIN_NAME, modules, config, 0);
180 2 : if (plugin)
181 : {
182 2 : Key * k;
183 2 : KeySet * data = newTestdataKeySet ();
184 2 : KeySet * original = ksDup (data);
185 :
186 : // test encryption with kdb set
187 2 : succeed_if (plugin->kdbSet (plugin, data, parentKey) == 1, "kdb set failed");
188 :
189 : // - unchanged
190 2 : k = ksLookupByName (data, KEYNAME_UNCHANGED, 0);
191 2 : succeed_if (k, "missing key " KEYNAME_UNCHANGED " in dataset");
192 2 : if (k)
193 : {
194 2 : succeed_if (keyIsString (k), "key type has been modified but was not marked for encryption");
195 2 : succeed_if (strcmp (keyString (k), strVal) == 0, "Key value changed but was not marked for encryption");
196 : }
197 :
198 : // - string value
199 2 : k = ksLookupByName (data, KEYNAME_STRING, 0);
200 2 : succeed_if (k, "missing key " KEYNAME_STRING " in dataset");
201 2 : if (k)
202 : {
203 2 : succeed_if (keyIsBinary (k), "key type not set to binary during encryption");
204 2 : succeed_if (memcmp (keyValue (k), strVal, MIN (keyGetValueSize (k), strlen (strVal))) != 0,
205 2 : "key content did not change during encryption");
206 : }
207 :
208 : // - binary value
209 2 : k = ksLookupByName (data, KEYNAME_BIN, 0);
210 2 : succeed_if (k, "missing key " KEYNAME_BIN " in dataset");
211 2 : if (k)
212 : {
213 2 : succeed_if (keyIsBinary (k), "key type not set to binary during encryption");
214 2 : succeed_if (memcmp (keyValue (k), binVal, MIN (keyGetValueSize (k), sizeof (binVal))) != 0,
215 2 : "key content did not change during encryption");
216 : }
217 :
218 : // - null value
219 2 : k = ksLookupByName (data, KEYNAME_NULL, 0);
220 2 : succeed_if (k, "missing key " KEYNAME_NULL " in dataset");
221 2 : if (k)
222 : {
223 2 : succeed_if (keyGetValueSize (k) == 0, "null value was changed unexpectedly");
224 : }
225 :
226 : // test decryption with kdb get
227 2 : succeed_if (plugin->kdbGet (plugin, data, parentKey) == 1, "kdb get failed");
228 :
229 : // - unchanged
230 2 : k = ksLookupByName (data, KEYNAME_UNCHANGED, 0);
231 2 : succeed_if (k, "missing key " KEYNAME_UNCHANGED " in dataset");
232 2 : if (k)
233 : {
234 2 : succeed_if (keyIsString (k), "key type has been modified but was not marked for decryption");
235 2 : succeed_if (strcmp (keyString (k), strVal) == 0, "Key value changed but was not marked for decryption");
236 : }
237 :
238 : // - string value
239 2 : k = ksLookupByName (data, KEYNAME_STRING, 0);
240 2 : succeed_if (k, "missing key " KEYNAME_STRING " in dataset");
241 2 : if (k)
242 : {
243 2 : succeed_if (keyIsString (k), "key type not restored to string during decryption");
244 2 : succeed_if (strcmp (keyString (k), strVal) == 0, "key content not restored during decryption");
245 : }
246 :
247 : // - binary value
248 2 : k = ksLookupByName (data, KEYNAME_BIN, 0);
249 2 : succeed_if (k, "missing key " KEYNAME_BIN " in dataset");
250 2 : if (k)
251 : {
252 2 : succeed_if (keyIsBinary (k), "key type not restored to binary during decryption");
253 2 : succeed_if (memcmp (keyValue (k), binVal, MIN (keyGetValueSize (k), sizeof (binVal))) == 0,
254 2 : "key content not restored during decryption");
255 : }
256 :
257 : // - null value
258 2 : k = ksLookupByName (data, KEYNAME_NULL, 0);
259 2 : succeed_if (k, "missing key " KEYNAME_NULL " in dataset");
260 2 : if (k)
261 : {
262 2 : succeed_if (keyGetValueSize (k) == 0, "null value was changed unexpectedly");
263 : }
264 :
265 2 : ksDel (original);
266 2 : ksDel (data);
267 2 : elektraPluginClose (plugin, 0);
268 : }
269 :
270 2 : elektraModulesClose (modules, 0);
271 2 : ksDel (modules);
272 2 : keyDel (parentKey);
273 2 : }
274 :
275 2 : int main (int argc, char ** argv)
276 : {
277 2 : printf ("GPGME TESTS\n");
278 2 : printf ("==================\n\n");
279 :
280 2 : init (argc, argv);
281 :
282 2 : init_gpgme ();
283 2 : test_import_key ();
284 2 : test_init ();
285 2 : test_incomplete_config ();
286 2 : test_encryption_decryption ();
287 2 : test_teardown ();
288 :
289 6 : print_result ("gpgme");
290 2 : return nbError;
291 : }
|