Line data Source code
1 : /* t-verify.c - Regression test.
2 : Copyright (C) 2000 Werner Koch (dd9jn)
3 : Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
4 :
5 : This file is part of GPGME.
6 :
7 : GPGME is free software; you can redistribute it and/or modify it
8 : under the terms of the GNU Lesser General Public License as
9 : published by the Free Software Foundation; either version 2.1 of
10 : the License, or (at your option) any later version.
11 :
12 : GPGME is distributed in the hope that it will be useful, but
13 : WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : Lesser General Public License for more details.
16 :
17 : You should have received a copy of the GNU Lesser General Public
18 : License along with this program; if not, write to the Free Software
19 : Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 : 02111-1307, USA. */
21 :
22 : /* We need to include config.h so that we know whether we are building
23 : with large file system (LFS) support. */
24 : #ifdef HAVE_CONFIG_H
25 : #include <config.h>
26 : #endif
27 :
28 : #include <stdlib.h>
29 : #include <stdio.h>
30 : #include <string.h>
31 :
32 : #include <gpgme.h>
33 :
34 : #define PGM "t-verify"
35 : #include "t-support.h"
36 :
37 :
38 :
39 : static const char test_text1[] = "Just GNU it!\n";
40 : static const char test_text1f[]= "Just GNU it?\n";
41 : static const char test_sig1[] =
42 : "-----BEGIN PGP SIGNATURE-----\n"
43 : "\n"
44 : "iN0EABECAJ0FAjoS+i9FFIAAAAAAAwA5YmFyw7bDpMO8w58gZGFzIHdhcmVuIFVt\n"
45 : "bGF1dGUgdW5kIGpldHp0IGVpbiBwcm96ZW50JS1aZWljaGVuNRSAAAAAAAgAJGZv\n"
46 : "b2Jhci4xdGhpcyBpcyBhIG5vdGF0aW9uIGRhdGEgd2l0aCAyIGxpbmVzGhpodHRw\n"
47 : "Oi8vd3d3Lmd1Lm9yZy9wb2xpY3kvAAoJEC1yfMdoaXc0JBIAoIiLlUsvpMDOyGEc\n"
48 : "dADGKXF/Hcb+AKCJWPphZCphduxSvrzH0hgzHdeQaA==\n"
49 : "=nts1\n"
50 : "-----END PGP SIGNATURE-----\n";
51 :
52 : /* The same as test_sig1 but with a second signature for which we do
53 : * not have the public key (deleted after signature creation). */
54 : static const char test_sig1_plus_unknown_key[] =
55 : "-----BEGIN PGP SIGNATURE-----\n"
56 : "\n"
57 : "iN0EABECAJ0FAjoS+i9FFIAAAAAAAwA5YmFyw7bDpMO8w58gZGFzIHdhcmVuIFVt\n"
58 : "bGF1dGUgdW5kIGpldHp0IGVpbiBwcm96ZW50JS1aZWljaGVuNRSAAAAAAAgAJGZv\n"
59 : "b2Jhci4xdGhpcyBpcyBhIG5vdGF0aW9uIGRhdGEgd2l0aCAyIGxpbmVzGhpodHRw\n"
60 : "Oi8vd3d3Lmd1Lm9yZy9wb2xpY3kvAAoJEC1yfMdoaXc0JBIAoIiLlUsvpMDOyGEc\n"
61 : "dADGKXF/Hcb+AKCJWPphZCphduxSvrzH0hgzHdeQaIh1BAAWCAAdFiEENuwqcMZC\n"
62 : "brD85btN+RyY8EnUIEwFAlrPR4cACgkQ+RyY8EnUIEyiuAEAm41LJTGUFDzhavRm\n"
63 : "jNwqUZxGGOySduW+u/X1lEfV+MYA/2lJOo75rHtD1EG+tkFVWt4Ukj0rjhR132vZ\n"
64 : "IOtrYAcG\n"
65 : "=yYwZ\n"
66 : "-----END PGP SIGNATURE-----\n";
67 :
68 : static const char test_sig2[] =
69 : "-----BEGIN PGP MESSAGE-----\n"
70 : "\n"
71 : "owGbwMvMwCSoW1RzPCOz3IRxjXQSR0lqcYleSUWJTZOvjVdpcYmCu1+oQmaJIleH\n"
72 : "GwuDIBMDGysTSIqBi1MApi+nlGGuwDeHao53HBr+FoVGP3xX+kvuu9fCMJvl6IOf\n"
73 : "y1kvP4y+8D5a11ang0udywsA\n"
74 : "=Crq6\n"
75 : "-----END PGP MESSAGE-----\n";
76 :
77 : /* A message with a prepended but unsigned plaintext packet. */
78 : static const char double_plaintext_sig[] =
79 : "-----BEGIN PGP MESSAGE-----\n"
80 : "\n"
81 : "rDRiCmZvb2Jhci50eHRF4pxNVGhpcyBpcyBteSBzbmVha3kgcGxhaW50ZXh0IG1l\n"
82 : "c3NhZ2UKowGbwMvMwCSoW1RzPCOz3IRxTWISa6JebnG666MFD1wzSzJSixQ81XMV\n"
83 : "UlITUxTyixRyKxXKE0uSMxQyEosVikvyCwpSU/S4FNCArq6Ce1F+aXJGvoJvYlGF\n"
84 : "erFCTmJxiUJ5flFKMVeHGwuDIBMDGysTyA4GLk4BmO036xgWzMgzt9V85jCtfDFn\n"
85 : "UqVooWlGXHwNw/xg/fVzt9VNbtjtJ/fhUqYo0/LyCGEA\n"
86 : "=6+AK\n"
87 : "-----END PGP MESSAGE-----\n";
88 :
89 :
90 :
91 :
92 : /* NO_OF_SIGS is the expected number of signatures. SKIP_SKIPS is
93 : * which of these signatures to check (0 based). */
94 : static void
95 5 : check_result (gpgme_verify_result_t result, int no_of_sigs, int skip_sigs,
96 : unsigned int summary, const char *fpr,
97 : gpgme_error_t status, int notation)
98 : {
99 : gpgme_signature_t sig;
100 : int n;
101 :
102 5 : sig = result->signatures;
103 12 : for (n=0; sig; sig = sig->next)
104 7 : n++;
105 5 : if (n != no_of_sigs)
106 : {
107 0 : fprintf (stderr, "%s:%i: Unexpected number of signatures"
108 : " (got %d expected %d)\n", PGM, __LINE__, n, no_of_sigs);
109 0 : exit (1);
110 : }
111 5 : if (skip_sigs >= n)
112 : {
113 0 : fprintf (stderr, "%s:%i: oops SKIPP_SIGS to high\n", PGM, __LINE__);
114 0 : exit (1);
115 : }
116 :
117 5 : for (n=0, sig = result->signatures; n < skip_sigs; sig = sig->next, n++)
118 : ;
119 :
120 5 : if (sig->summary != summary)
121 : {
122 0 : fprintf (stderr, "%s:%i:sig-%d: Unexpected signature summary: "
123 : "want=0x%x have=0x%x\n",
124 0 : PGM, __LINE__, skip_sigs, summary, sig->summary);
125 0 : exit (1);
126 : }
127 5 : if (strcmp (sig->fpr, fpr))
128 : {
129 0 : if (strlen (sig->fpr) == 16 && strlen (fpr) == 40
130 0 : && !strncmp (sig->fpr, fpr + 24, 16))
131 : ; /* okay because gnupg < 2.2.6 only shows the keyid. */
132 : else
133 : {
134 0 : fprintf (stderr, "%s:%i:sig-%d: Unexpected fingerprint: %s\n",
135 : PGM, __LINE__, skip_sigs, sig->fpr);
136 0 : exit (1);
137 : }
138 : }
139 5 : if (gpgme_err_code (sig->status) != status)
140 : {
141 0 : fprintf (stderr, "%s:%i:sig-%d: Unexpected signature status: %s\n",
142 : PGM, __LINE__, skip_sigs, gpgme_strerror (sig->status));
143 0 : exit (1);
144 : }
145 5 : if (notation)
146 : {
147 : static struct {
148 : const char *name;
149 : const char *value;
150 : int seen;
151 : } expected_notations[] = {
152 : { "bar",
153 : "\xc3\xb6\xc3\xa4\xc3\xbc\xc3\x9f"
154 : " das waren Umlaute und jetzt ein prozent%-Zeichen" },
155 : { "foobar.1",
156 : "this is a notation data with 2 lines" },
157 : { NULL,
158 : "http://www.gu.org/policy/" }
159 : };
160 : int i;
161 : gpgme_sig_notation_t r;
162 :
163 8 : for (i=0; i < DIM(expected_notations); i++ )
164 6 : expected_notations[i].seen = 0;
165 :
166 8 : for (r = sig->notations; r; r = r->next)
167 : {
168 6 : int any = 0;
169 24 : for (i=0; i < DIM(expected_notations); i++)
170 : {
171 18 : if ( ((r->name && expected_notations[i].name
172 8 : && !strcmp (r->name, expected_notations[i].name)
173 8 : && r->name_len
174 4 : == strlen (expected_notations[i].name))
175 14 : || (!r->name && !expected_notations[i].name
176 2 : && r->name_len == 0))
177 6 : && r->value
178 6 : && !strcmp (r->value, expected_notations[i].value)
179 6 : && r->value_len == strlen (expected_notations[i].value))
180 : {
181 6 : expected_notations[i].seen++;
182 6 : any++;
183 : }
184 : }
185 6 : if (!any)
186 : {
187 0 : fprintf (stderr, "%s:%i:sig-%d: Unexpected notation data\n",
188 : PGM, __LINE__, skip_sigs);
189 0 : exit (1);
190 : }
191 : }
192 8 : for (i=0; i < DIM(expected_notations); i++ )
193 : {
194 6 : if (expected_notations[i].seen != 1)
195 : {
196 0 : fprintf (stderr, "%s:%i:sig-%d: "
197 : "Missing or duplicate notation data\n",
198 : PGM, __LINE__, skip_sigs);
199 0 : exit (1);
200 : }
201 : }
202 : }
203 5 : if (sig->wrong_key_usage)
204 : {
205 0 : fprintf (stderr, "%s:%i:sig-%d: Unexpectedly wrong key usage\n",
206 : PGM, __LINE__, skip_sigs);
207 0 : exit (1);
208 : }
209 5 : if (sig->validity != GPGME_VALIDITY_UNKNOWN)
210 : {
211 0 : fprintf (stderr, "%s:%i:sig-%d: Unexpected validity: %i\n",
212 0 : PGM, __LINE__, skip_sigs, sig->validity);
213 0 : exit (1);
214 : }
215 5 : if (gpgme_err_code (sig->validity_reason) != GPG_ERR_NO_ERROR)
216 : {
217 0 : fprintf (stderr, "%s:%i:sig-%d: Unexpected validity reason: %s\n",
218 : PGM, __LINE__, skip_sigs,
219 : gpgme_strerror (sig->validity_reason));
220 0 : exit (1);
221 : }
222 5 : }
223 :
224 :
225 : int
226 1 : main (int argc, char *argv[])
227 : {
228 : gpgme_ctx_t ctx;
229 : gpgme_error_t err;
230 : gpgme_data_t sig, text;
231 : gpgme_verify_result_t result;
232 : const char *s;
233 :
234 : (void)argc;
235 : (void)argv;
236 :
237 1 : init_gpgme (GPGME_PROTOCOL_OpenPGP);
238 :
239 1 : err = gpgme_new (&ctx);
240 1 : fail_if_err (err);
241 :
242 : /* Checking a valid message. */
243 1 : err = gpgme_data_new_from_mem (&text, test_text1, strlen (test_text1), 0);
244 1 : fail_if_err (err);
245 1 : err = gpgme_data_new_from_mem (&sig, test_sig1, strlen (test_sig1), 0);
246 1 : fail_if_err (err);
247 1 : err = gpgme_op_verify (ctx, sig, text, NULL);
248 1 : fail_if_err (err);
249 1 : result = gpgme_op_verify_result (ctx);
250 1 : check_result (result, 1, 0, 0, "A0FF4590BB6122EDEF6E3C542D727CC768697734",
251 : GPG_ERR_NO_ERROR, 1);
252 :
253 : /* Checking a manipulated message. */
254 1 : gpgme_data_release (text);
255 1 : err = gpgme_data_new_from_mem (&text, test_text1f, strlen (test_text1f), 0);
256 1 : fail_if_err (err);
257 1 : gpgme_data_seek (sig, 0, SEEK_SET);
258 1 : err = gpgme_op_verify (ctx, sig, text, NULL);
259 1 : fail_if_err (err);
260 1 : result = gpgme_op_verify_result (ctx);
261 1 : check_result (result, 1, 0, GPGME_SIGSUM_RED, "2D727CC768697734",
262 : GPG_ERR_BAD_SIGNATURE, 0);
263 :
264 : /* Checking a valid message. Bu that one has a second signature
265 : * made by an unknown key. */
266 1 : gpgme_data_release (text);
267 1 : gpgme_data_release (sig);
268 1 : err = gpgme_data_new_from_mem (&text, test_text1, strlen (test_text1), 0);
269 1 : fail_if_err (err);
270 1 : err = gpgme_data_new_from_mem (&sig, test_sig1_plus_unknown_key,
271 : strlen (test_sig1_plus_unknown_key), 0);
272 1 : fail_if_err (err);
273 1 : err = gpgme_op_verify (ctx, sig, text, NULL);
274 1 : fail_if_err (err);
275 1 : result = gpgme_op_verify_result (ctx);
276 1 : check_result (result, 2, 0, 0,
277 : "A0FF4590BB6122EDEF6E3C542D727CC768697734",
278 : GPG_ERR_NO_ERROR, 1);
279 1 : check_result (result, 2, 1, GPGME_SIGSUM_KEY_MISSING,
280 : "36EC2A70C6426EB0FCE5BB4DF91C98F049D4204C",
281 : GPG_ERR_NO_PUBKEY, 0);
282 :
283 :
284 : /* Checking a normal signature. */
285 1 : gpgme_data_release (sig);
286 1 : gpgme_data_release (text);
287 1 : err = gpgme_data_new_from_mem (&sig, test_sig2, strlen (test_sig2), 0);
288 1 : fail_if_err (err);
289 1 : err = gpgme_data_new (&text);
290 1 : fail_if_err (err);
291 1 : err = gpgme_op_verify (ctx, sig, NULL, text);
292 1 : fail_if_err (err);
293 1 : result = gpgme_op_verify_result (ctx);
294 1 : check_result (result, 1, 0, 0, "A0FF4590BB6122EDEF6E3C542D727CC768697734",
295 : GPG_ERR_NO_ERROR, 0);
296 :
297 :
298 : /* Checking an invalid message. */
299 1 : gpgme_data_release (sig);
300 1 : gpgme_data_release (text);
301 1 : err = gpgme_data_new_from_mem (&sig, double_plaintext_sig,
302 : strlen (double_plaintext_sig), 0);
303 1 : fail_if_err (err);
304 1 : err = gpgme_data_new (&text);
305 1 : fail_if_err (err);
306 1 : err = gpgme_op_verify (ctx, sig, NULL, text);
307 1 : if (gpgme_err_code (err) != GPG_ERR_BAD_DATA)
308 : {
309 0 : fprintf (stderr, "%s:%i: Double plaintext message not detected\n",
310 : PGM, __LINE__);
311 0 : exit (1);
312 : }
313 :
314 : /* Checking that set/get_sernder works. */
315 1 : err = gpgme_set_sender (ctx, "foo@example.org");
316 1 : fail_if_err (err);
317 1 : s = gpgme_get_sender (ctx);
318 1 : if (!s || strcmp (s, "foo@example.org"))
319 : {
320 0 : fprintf (stderr, "%s:%i: gpgme_{set,get}_sender mismatch\n",
321 : PGM, __LINE__);
322 0 : exit (1);
323 : }
324 :
325 1 : err = gpgme_set_sender (ctx, "<bar@example.org>");
326 1 : fail_if_err (err);
327 1 : s = gpgme_get_sender (ctx);
328 1 : if (!s || strcmp (s, "bar@example.org"))
329 : {
330 0 : fprintf (stderr, "%s:%i: gpgme_{set,get}_sender mismatch\n",
331 : PGM, __LINE__);
332 0 : exit (1);
333 : }
334 :
335 1 : err = gpgme_set_sender (ctx, "Foo bar (comment) <foo@example.org>");
336 1 : fail_if_err (err);
337 1 : s = gpgme_get_sender (ctx);
338 1 : if (!s || strcmp (s, "foo@example.org"))
339 : {
340 0 : fprintf (stderr, "%s:%i: gpgme_{set,get}_sender mismatch\n",
341 : PGM, __LINE__);
342 0 : exit (1);
343 : }
344 :
345 1 : err = gpgme_set_sender (ctx, "foo");
346 1 : if (gpgme_err_code (err) != GPG_ERR_INV_VALUE)
347 : {
348 0 : fprintf (stderr, "%s:%i: gpgme_set_sender didn't detect bogus address\n",
349 : PGM, __LINE__);
350 0 : exit (1);
351 : }
352 : /* (the former address should still be there.) */
353 1 : s = gpgme_get_sender (ctx);
354 1 : if (!s || strcmp (s, "foo@example.org"))
355 : {
356 0 : fprintf (stderr, "%s:%i: gpgme_{set,get}_sender mismatch\n",
357 : PGM, __LINE__);
358 0 : exit (1);
359 : }
360 :
361 :
362 1 : gpgme_data_release (sig);
363 1 : gpgme_data_release (text);
364 1 : gpgme_release (ctx);
365 1 : return 0;
366 : }
|