Use gpgme interface for error handling to avoid linking with gpg-error.
[gpgme.git] / tests / gpg / t-verify.c
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 #include "t-support.h"
35
36 \f
37 static const char test_text1[] = "Just GNU it!\n";
38 static const char test_text1f[]= "Just GNU it?\n";
39 static const char test_sig1[] =
40 #if 0
41 "-----BEGIN PGP SIGNATURE-----\n"
42 "\n"
43 "iEYEABECAAYFAjoKgjIACgkQLXJ8x2hpdzQMSwCeO/xUrhysZ7zJKPf/FyXA//u1\n"
44 "ZgIAn0204PBR7yxSdQx6CFxugstNqmRv\n"
45 "=yku6\n"
46 "-----END PGP SIGNATURE-----\n"
47 #elif 0
48 "-----BEGIN PGP SIGNATURE-----\n"
49 "Version: GnuPG v1.0.4-2 (GNU/Linux)\n"
50 "Comment: For info see http://www.gnupg.org\n"
51 "\n"
52 "iJcEABECAFcFAjoS8/E1FIAAAAAACAAkZm9vYmFyLjF0aGlzIGlzIGEgbm90YXRp\n"
53 "b24gZGF0YSB3aXRoIDIgbGluZXMaGmh0dHA6Ly93d3cuZ3Uub3JnL3BvbGljeS8A\n"
54 "CgkQLXJ8x2hpdzQLyQCbBW/fgU8ZeWSlWPM1F8umHX17bAAAoIfSNDSp5zM85XcG\n"
55 "iwxMrf+u8v4r\n"
56 "=88Zo\n"
57 "-----END PGP SIGNATURE-----\n"
58 #elif 1
59 "-----BEGIN PGP SIGNATURE-----\n"
60 "\n"
61 "iN0EABECAJ0FAjoS+i9FFIAAAAAAAwA5YmFyw7bDpMO8w58gZGFzIHdhcmVuIFVt\n"
62 "bGF1dGUgdW5kIGpldHp0IGVpbiBwcm96ZW50JS1aZWljaGVuNRSAAAAAAAgAJGZv\n"
63 "b2Jhci4xdGhpcyBpcyBhIG5vdGF0aW9uIGRhdGEgd2l0aCAyIGxpbmVzGhpodHRw\n"
64 "Oi8vd3d3Lmd1Lm9yZy9wb2xpY3kvAAoJEC1yfMdoaXc0JBIAoIiLlUsvpMDOyGEc\n"
65 "dADGKXF/Hcb+AKCJWPphZCphduxSvrzH0hgzHdeQaA==\n"
66 "=nts1\n"
67 "-----END PGP SIGNATURE-----\n"
68 #endif
69 ;
70 static const char test_sig2[] =
71 "-----BEGIN PGP MESSAGE-----\n"
72 "\n"
73 "owGbwMvMwCSoW1RzPCOz3IRxjXQSR0lqcYleSUWJTZOvjVdpcYmCu1+oQmaJIleH\n"
74 "GwuDIBMDGysTSIqBi1MApi+nlGGuwDeHao53HBr+FoVGP3xX+kvuu9fCMJvl6IOf\n"
75 "y1kvP4y+8D5a11ang0udywsA\n"
76 "=Crq6\n"
77 "-----END PGP MESSAGE-----\n";
78
79 /* A message with a prepended but unsigned plaintext packet. */
80 static const char double_plaintext_sig[] = 
81 "-----BEGIN PGP MESSAGE-----\n"
82 "\n"
83 "rDRiCmZvb2Jhci50eHRF4pxNVGhpcyBpcyBteSBzbmVha3kgcGxhaW50ZXh0IG1l\n"
84 "c3NhZ2UKowGbwMvMwCSoW1RzPCOz3IRxTWISa6JebnG666MFD1wzSzJSixQ81XMV\n"
85 "UlITUxTyixRyKxXKE0uSMxQyEosVikvyCwpSU/S4FNCArq6Ce1F+aXJGvoJvYlGF\n"
86 "erFCTmJxiUJ5flFKMVeHGwuDIBMDGysTyA4GLk4BmO036xgWzMgzt9V85jCtfDFn\n"
87 "UqVooWlGXHwNw/xg/fVzt9VNbtjtJ/fhUqYo0/LyCGEA\n"
88 "=6+AK\n"
89 "-----END PGP MESSAGE-----\n";
90
91
92
93
94 static void
95 check_result (gpgme_verify_result_t result, unsigned int summary, char *fpr,
96               gpgme_error_t status, int notation)
97 {
98   gpgme_signature_t sig;
99
100   sig = result->signatures;
101   if (!sig || sig->next)
102     {
103       fprintf (stderr, "%s:%i: Unexpected number of signatures\n",
104                __FILE__, __LINE__);
105       exit (1);
106     }
107   if (sig->summary != summary)
108     {
109       fprintf (stderr, "%s:%i: Unexpected signature summary: "
110                "want=0x%x have=0x%x\n",
111                __FILE__, __LINE__, summary, sig->summary);
112       exit (1);
113     }
114   if (strcmp (sig->fpr, fpr))
115     {
116       fprintf (stderr, "%s:%i: Unexpected fingerprint: %s\n",
117                __FILE__, __LINE__, sig->fpr);
118       exit (1);
119     }
120   if (gpgme_err_code (sig->status) != status)
121     {
122       fprintf (stderr, "%s:%i: Unexpected signature status: %s\n",
123                __FILE__, __LINE__, gpgme_strerror (sig->status));
124       exit (1);
125     }
126   if (notation)
127     {
128       static struct {
129         const char *name;
130         const char *value;
131         int seen;
132       } expected_notations[] = {
133         { "bar",
134           "\xc3\xb6\xc3\xa4\xc3\xbc\xc3\x9f"
135           " das waren Umlaute und jetzt ein prozent%-Zeichen" },
136         { "foobar.1",
137           "this is a notation data with 2 lines" },
138         { NULL, 
139           "http://www.gu.org/policy/" }
140       };
141       int i;
142       gpgme_sig_notation_t r;
143
144       for (i=0; i < DIM(expected_notations); i++ )
145         expected_notations[i].seen = 0;
146
147       for (r = sig->notations; r; r = r->next)
148         {
149           int any = 0;
150           for (i=0; i < DIM(expected_notations); i++)
151             {
152               if ( ((r->name && expected_notations[i].name
153                      && !strcmp (r->name, expected_notations[i].name)
154                      && r->name_len
155                      == strlen (expected_notations[i].name))
156                     || (!r->name && !expected_notations[i].name
157                         && r->name_len == 0))
158                    && r->value
159                    && !strcmp (r->value, expected_notations[i].value)
160                    && r->value_len == strlen (expected_notations[i].value))
161                 {
162                   expected_notations[i].seen++;
163                   any++;
164                 }
165             }
166           if (!any)
167             {
168               fprintf (stderr, "%s:%i: Unexpected notation data\n",
169                        __FILE__, __LINE__);
170               exit (1);
171             }
172         }
173       for (i=0; i < DIM(expected_notations); i++ )
174         {
175           if (expected_notations[i].seen != 1)
176             {
177               fprintf (stderr, "%s:%i: Missing or duplicate notation data\n",
178                        __FILE__, __LINE__);
179               exit (1);
180             }
181         }
182     }
183   if (sig->wrong_key_usage)
184     {
185       fprintf (stderr, "%s:%i: Unexpectedly wrong key usage\n",
186                __FILE__, __LINE__);
187       exit (1);
188     }
189   if (sig->validity != GPGME_VALIDITY_UNKNOWN)
190     {
191       fprintf (stderr, "%s:%i: Unexpected validity: %i\n",
192                __FILE__, __LINE__, sig->validity);
193       exit (1);
194     }
195   if (gpgme_err_code (sig->validity_reason) != GPG_ERR_NO_ERROR)
196     {
197       fprintf (stderr, "%s:%i: Unexpected validity reason: %s\n",
198                __FILE__, __LINE__, gpgme_strerror (sig->validity_reason));
199       exit (1);
200     }
201 }
202
203
204 int 
205 main (int argc, char *argv[])
206 {
207   gpgme_ctx_t ctx;
208   gpgme_error_t err;
209   gpgme_data_t sig, text;
210   gpgme_verify_result_t result;
211
212   init_gpgme (GPGME_PROTOCOL_OpenPGP);
213
214   err = gpgme_new (&ctx);
215   fail_if_err (err);
216
217   /* Checking a valid message.  */
218   err = gpgme_data_new_from_mem (&text, test_text1, strlen (test_text1), 0);
219   fail_if_err (err);
220   err = gpgme_data_new_from_mem (&sig, test_sig1, strlen (test_sig1), 0);
221   fail_if_err (err);
222   err = gpgme_op_verify (ctx, sig, text, NULL);
223   fail_if_err (err);
224   result = gpgme_op_verify_result (ctx);
225   check_result (result, 0, "A0FF4590BB6122EDEF6E3C542D727CC768697734",
226                 GPG_ERR_NO_ERROR, 1);
227
228   /* Checking a manipulated message.  */
229   gpgme_data_release (text);
230   err = gpgme_data_new_from_mem (&text, test_text1f, strlen (test_text1f), 0);
231   fail_if_err (err);
232   gpgme_data_seek (sig, 0, SEEK_SET);
233   err = gpgme_op_verify (ctx, sig, text, NULL);
234   fail_if_err (err);
235   result = gpgme_op_verify_result (ctx);
236   check_result (result, GPGME_SIGSUM_RED, "2D727CC768697734",
237                 GPG_ERR_BAD_SIGNATURE, 0);
238
239   /* Checking a normal signature.  */
240   gpgme_data_release (sig);
241   gpgme_data_release (text);
242   err = gpgme_data_new_from_mem (&sig, test_sig2, strlen (test_sig2), 0);
243   fail_if_err (err);
244   err = gpgme_data_new (&text);
245   fail_if_err (err);
246   err = gpgme_op_verify (ctx, sig, NULL, text);
247   fail_if_err (err);
248   result = gpgme_op_verify_result (ctx);
249   check_result (result, 0, "A0FF4590BB6122EDEF6E3C542D727CC768697734",
250                 GPG_ERR_NO_ERROR, 0);
251
252
253   /* Checking an invalid message.  */
254   gpgme_data_release (sig);
255   gpgme_data_release (text);
256   err = gpgme_data_new_from_mem (&sig, double_plaintext_sig,
257                                  strlen (double_plaintext_sig), 0);
258   fail_if_err (err);
259   err = gpgme_data_new (&text);
260   fail_if_err (err);
261   err = gpgme_op_verify (ctx, sig, NULL, text);
262   if (gpgme_err_code (err) != GPG_ERR_BAD_DATA)
263     {
264       fprintf (stderr, "%s:%i: Double plaintext message not detected\n",
265                __FILE__, __LINE__);
266       exit (1);
267     }
268
269   gpgme_data_release (sig);
270   gpgme_data_release (text);
271   gpgme_release (ctx);
272   return 0;
273 }