Add Kludge for RegTP sillyness.
[gnupg.git] / sm / verify.c
1 /* verify.c - Verify a messages signature
2  *      Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h> 
27 #include <time.h>
28 #include <assert.h>
29
30 #include "gpgsm.h"
31 #include <gcrypt.h>
32 #include <ksba.h>
33
34 #include "keydb.h"
35 #include "i18n.h"
36
37 static char *
38 strtimestamp_r (ksba_isotime_t atime)
39 {
40   char *buffer = xmalloc (15);
41   
42   if (!atime || !*atime)
43     strcpy (buffer, "none");
44   else
45     sprintf (buffer, "%.4s-%.2s-%.2s", atime, atime+4, atime+6);
46   return buffer;
47 }
48
49
50
51 /* Hash the data for a detached signature */
52 static void
53 hash_data (int fd, gcry_md_hd_t md)
54 {
55   FILE *fp;
56   char buffer[4096];
57   int nread;
58
59   fp = fdopen ( dup (fd), "rb");
60   if (!fp)
61     {
62       log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
63       return;
64     }
65
66   do 
67     {
68       nread = fread (buffer, 1, DIM(buffer), fp);
69       gcry_md_write (md, buffer, nread);
70     }
71   while (nread);
72   if (ferror (fp))
73       log_error ("read error on fd %d: %s\n", fd, strerror (errno));
74   fclose (fp);
75 }
76
77
78
79 \f
80 /* Perform a verify operation.  To verify detached signatures, data_fd
81    must be different than -1.  With OUT_FP given and a non-detached
82    signature, the signed material is written to that stream. */
83 int
84 gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
85 {
86   int i, rc;
87   Base64Context b64reader = NULL;
88   Base64Context b64writer = NULL;
89   ksba_reader_t reader;
90   ksba_writer_t writer = NULL;
91   ksba_cms_t cms = NULL;
92   ksba_stop_reason_t stopreason;
93   ksba_cert_t cert;
94   KEYDB_HANDLE kh;
95   gcry_md_hd_t data_md = NULL;
96   int signer;
97   const char *algoid;
98   int algo;
99   int is_detached;
100   FILE *fp = NULL;
101   char *p;
102
103   kh = keydb_new (0);
104   if (!kh)
105     {
106       log_error (_("failed to allocated keyDB handle\n"));
107       rc = gpg_error (GPG_ERR_GENERAL);
108       goto leave;
109     }
110
111
112   fp = fdopen ( dup (in_fd), "rb");
113   if (!fp)
114     {
115       rc = gpg_error (gpg_err_code_from_errno (errno));
116       log_error ("fdopen() failed: %s\n", strerror (errno));
117       goto leave;
118     }
119
120   rc = gpgsm_create_reader (&b64reader, ctrl, fp, 0, &reader);
121   if (rc)
122     {
123       log_error ("can't create reader: %s\n", gpg_strerror (rc));
124       goto leave;
125     }
126
127   if (out_fp)
128     {
129       rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
130       if (rc)
131         {
132           log_error ("can't create writer: %s\n", gpg_strerror (rc));
133           goto leave;
134         }
135     }
136
137   rc = ksba_cms_new (&cms);
138   if (rc)
139     goto leave;
140
141   rc = ksba_cms_set_reader_writer (cms, reader, writer);
142   if (rc)
143     {
144       log_error ("ksba_cms_set_reader_writer failed: %s\n",
145                  gpg_strerror (rc));
146       goto leave;
147     }
148
149   rc = gcry_md_open (&data_md, 0, 0);
150   if (rc)
151     {
152       log_error ("md_open failed: %s\n", gpg_strerror (rc));
153       goto leave;
154     }
155   if (DBG_HASHING)
156     gcry_md_start_debug (data_md, "vrfy.data");
157
158   is_detached = 0;
159   do 
160     {
161       rc = ksba_cms_parse (cms, &stopreason);
162       if (rc)
163         {
164           log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc));
165           goto leave;
166         }
167
168       if (stopreason == KSBA_SR_NEED_HASH)
169         {
170           is_detached = 1;
171           if (opt.verbose)
172             log_info ("detached signature\n");
173         }
174
175       if (stopreason == KSBA_SR_NEED_HASH
176           || stopreason == KSBA_SR_BEGIN_DATA)
177         { /* We are now able to enable the hash algorithms */
178           for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
179             {
180               algo = gcry_md_map_name (algoid);
181               if (!algo)
182                 {
183                   log_error ("unknown hash algorithm `%s'\n",
184                              algoid? algoid:"?");
185                   if (algoid
186                       && (  !strcmp (algoid, "1.2.840.113549.1.1.2")
187                           ||!strcmp (algoid, "1.2.840.113549.2.2")))
188                     log_info (_("(this is the MD2 algorithm)\n"));
189                 }
190               else
191                 gcry_md_enable (data_md, algo);
192             }
193           if (is_detached)
194             {
195               if (data_fd == -1)
196                 log_info ("detached signature w/o data "
197                           "- assuming certs-only\n");
198               else
199                 hash_data (data_fd, data_md);  
200             }
201           else
202             {
203               ksba_cms_set_hash_function (cms, HASH_FNC, data_md);
204             }
205         }
206       else if (stopreason == KSBA_SR_END_DATA)
207         { /* The data bas been hashed */
208
209         }
210     }
211   while (stopreason != KSBA_SR_READY);   
212
213   if (b64writer)
214     {
215       rc = gpgsm_finish_writer (b64writer);
216       if (rc) 
217         {
218           log_error ("write failed: %s\n", gpg_strerror (rc));
219           goto leave;
220         }
221     }
222
223   if (data_fd != -1 && !is_detached)
224     {
225       log_error ("data given for a non-detached signature\n");
226       rc = gpg_error (GPG_ERR_CONFLICT);
227       goto leave;
228     }
229
230   for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
231     {
232       /* Fixme: it might be better to check the validity of the
233          certificate first before entering it into the DB.  This way
234          we would avoid cluttering the DB with invalid
235          certificates. */
236       keydb_store_cert (cert, 0, NULL);
237       ksba_cert_release (cert);
238     }
239
240   cert = NULL;
241   for (signer=0; ; signer++)
242     {
243       char *issuer = NULL;
244       ksba_sexp_t sigval = NULL;
245       ksba_isotime_t sigtime, keyexptime;
246       ksba_sexp_t serial;
247       char *msgdigest = NULL;
248       size_t msgdigestlen;
249       char *ctattr;
250
251       rc = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
252       if (!signer && gpg_err_code (rc) == GPG_ERR_NO_DATA
253           && data_fd == -1 && is_detached)
254         {
255           log_info ("certs-only message accepted\n");
256           rc = 0;
257           break;
258         }
259       if (rc)
260         {
261           if (signer && rc == -1)
262             rc = 0;
263           break;
264         }
265
266       gpgsm_status (ctrl, STATUS_NEWSIG, NULL);
267
268       if (DBG_X509)
269         {
270           log_debug ("signer %d - issuer: `%s'\n",
271                      signer, issuer? issuer:"[NONE]");
272           log_debug ("signer %d - serial: ", signer);
273           gpgsm_dump_serial (serial);
274           log_printf ("\n");
275         }
276
277       rc = ksba_cms_get_signing_time (cms, signer, sigtime);
278       if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
279         *sigtime = 0;
280       else if (rc)
281         {
282           log_error ("error getting signing time: %s\n", gpg_strerror (rc));
283           *sigtime = 0; /* (we can't encode an error in the time string.) */
284         }
285
286       rc = ksba_cms_get_message_digest (cms, signer,
287                                         &msgdigest, &msgdigestlen);
288       if (!rc)
289         {
290           size_t is_enabled;
291
292           algoid = ksba_cms_get_digest_algo (cms, signer);
293           algo = gcry_md_map_name (algoid);
294           if (DBG_X509)
295             log_debug ("signer %d - digest algo: %d\n", signer, algo);
296           is_enabled = sizeof algo;
297           if ( gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED,
298                              &algo, &is_enabled)
299                || !is_enabled)
300             {
301               log_error ("digest algo %d has not been enabled\n", algo);
302               goto next_signer;
303             }
304         }
305       else if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
306         {
307           assert (!msgdigest);
308           rc = 0;
309           algoid = NULL;
310           algo = 0; 
311         }
312       else /* real error */
313         break;
314
315       rc = ksba_cms_get_sigattr_oids (cms, signer,
316                                       "1.2.840.113549.1.9.3", &ctattr);
317       if (!rc) 
318         {
319           const char *s;
320
321           if (DBG_X509)
322             log_debug ("signer %d - content-type attribute: %s",
323                        signer, ctattr);
324
325           s = ksba_cms_get_content_oid (cms, 1);
326           if (!s || strcmp (ctattr, s))
327             {
328               log_error ("content-type attribute does not match "
329                          "actual content-type\n");
330               ksba_free (ctattr);
331               ctattr = NULL;
332               goto next_signer;
333             }
334           ksba_free (ctattr);
335           ctattr = NULL;
336         }
337       else if (rc != -1)
338         {
339           log_error ("error getting content-type attribute: %s\n",
340                      gpg_strerror (rc));
341           goto next_signer;
342         }
343       rc = 0;
344
345
346       sigval = ksba_cms_get_sig_val (cms, signer);
347       if (!sigval)
348         {
349           log_error ("no signature value available\n");
350           goto next_signer;
351         }
352       if (DBG_X509)
353         log_debug ("signer %d - signature available", signer);
354
355       /* Find the certificate of the signer */
356       keydb_search_reset (kh);
357       rc = keydb_search_issuer_sn (kh, issuer, serial);
358       if (rc)
359         {
360           if (rc == -1)
361             {
362               log_error ("certificate not found\n");
363               rc = gpg_error (GPG_ERR_NO_PUBKEY);
364             }
365           else
366             log_error ("failed to find the certificate: %s\n",
367                        gpg_strerror(rc));
368           {
369             char numbuf[50];
370             sprintf (numbuf, "%d", rc);
371
372             gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey",
373                            numbuf, NULL);
374           }
375           /* fixme: we might want to append the issuer and serial
376              using our standard notation */
377           goto next_signer;
378         }
379
380       rc = keydb_get_cert (kh, &cert);
381       if (rc)
382         {
383           log_error ("failed to get cert: %s\n", gpg_strerror (rc));
384           goto next_signer;
385         }
386
387       log_info (_("Signature made "));
388       if (*sigtime)
389         gpgsm_dump_time (sigtime);
390       else
391         log_printf (_("[date not given]"));
392       log_printf (_(" using certificate ID %08lX\n"),
393                   gpgsm_get_short_fingerprint (cert));
394
395
396       if (msgdigest)
397         { /* Signed attributes are available. */
398           gcry_md_hd_t md;
399           unsigned char *s;
400
401           /* check that the message digest in the signed attributes
402              matches the one we calculated on the data */
403           s = gcry_md_read (data_md, algo);
404           if ( !s || !msgdigestlen
405                || gcry_md_get_algo_dlen (algo) != msgdigestlen
406                || !s || memcmp (s, msgdigest, msgdigestlen) )
407             {
408               char *fpr;
409
410               log_error ("invalid signature: message digest attribute "
411                          "does not match calculated one\n");
412               fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
413               gpgsm_status (ctrl, STATUS_BADSIG, fpr);
414               xfree (fpr);
415               goto next_signer; 
416             }
417             
418           rc = gcry_md_open (&md, algo, 0);
419           if (rc)
420             {
421               log_error ("md_open failed: %s\n", gpg_strerror (rc));
422               goto next_signer;
423             }
424           if (DBG_HASHING)
425             gcry_md_start_debug (md, "vrfy.attr");
426
427           ksba_cms_set_hash_function (cms, HASH_FNC, md);
428           rc = ksba_cms_hash_signed_attrs (cms, signer);
429           if (rc)
430             {
431               log_error ("hashing signed attrs failed: %s\n",
432                          gpg_strerror (rc));
433               gcry_md_close (md);
434               goto next_signer;
435             }
436           rc = gpgsm_check_cms_signature (cert, sigval, md, algo);
437           gcry_md_close (md);
438         }
439       else
440         {
441           rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo);
442         }
443
444       if (rc)
445         {
446           char *fpr;
447
448           log_error ("invalid signature: %s\n", gpg_strerror (rc));
449           fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
450           gpgsm_status (ctrl, STATUS_BADSIG, fpr);
451           xfree (fpr);
452           goto next_signer;
453         }
454       rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/
455       if (rc)
456         {
457           gpgsm_status_with_err_code (ctrl, STATUS_ERROR, "verify.keyusage",
458                                       gpg_err_code (rc));
459           rc = 0;
460         }
461
462       if (DBG_X509)
463         log_debug ("signature okay - checking certs\n");
464       rc = gpgsm_validate_chain (ctrl, cert, keyexptime, 0, NULL, 0);
465       if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED)
466         {
467           gpgsm_status (ctrl, STATUS_EXPKEYSIG, NULL);
468           rc = 0;
469         }
470       else
471         gpgsm_status (ctrl, STATUS_GOODSIG, NULL);
472       
473       {
474         char *buf, *fpr, *tstr;
475
476         fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
477         tstr = strtimestamp_r (sigtime);
478         buf = xmalloc ( strlen(fpr) + strlen (tstr) + 120);
479         sprintf (buf, "%s %s %s %s", fpr, tstr,
480                  *sigtime? sigtime : "0",
481                  *keyexptime? keyexptime : "0" );
482         xfree (tstr);
483         xfree (fpr);
484         gpgsm_status (ctrl, STATUS_VALIDSIG, buf);
485         xfree (buf);
486       }
487
488       if (rc) /* of validate_chain */
489         {
490           log_error ("invalid certification chain: %s\n", gpg_strerror (rc));
491           if (gpg_err_code (rc) == GPG_ERR_BAD_CERT_CHAIN
492               || gpg_err_code (rc) == GPG_ERR_BAD_CERT
493               || gpg_err_code (rc) == GPG_ERR_BAD_CA_CERT
494               || gpg_err_code (rc) == GPG_ERR_CERT_REVOKED)
495             gpgsm_status_with_err_code (ctrl, STATUS_TRUST_NEVER, NULL,
496                                         gpg_err_code (rc));
497           else
498             gpgsm_status_with_err_code (ctrl, STATUS_TRUST_UNDEFINED, NULL, 
499                                         gpg_err_code (rc));
500           goto next_signer;
501         }
502
503       for (i=0; (p = ksba_cert_get_subject (cert, i)); i++)
504         {
505           log_info (!i? _("Good signature from")
506                       : _("                aka"));
507           log_printf (" \"");
508           gpgsm_print_name (log_get_stream (), p);
509           log_printf ("\"\n");
510           ksba_free (p);
511         }
512
513       gpgsm_status (ctrl, STATUS_TRUST_FULLY, NULL);
514           
515
516     next_signer:
517       rc = 0;
518       xfree (issuer);
519       xfree (serial);
520       xfree (sigval);
521       xfree (msgdigest);
522       ksba_cert_release (cert);
523       cert = NULL;
524     }
525   rc = 0;
526
527  leave:
528   ksba_cms_release (cms);
529   gpgsm_destroy_reader (b64reader);
530   gpgsm_destroy_writer (b64writer);
531   keydb_release (kh); 
532   gcry_md_close (data_md);
533   if (fp)
534     fclose (fp);
535
536   if (rc)
537     {
538       char numbuf[50];
539       sprintf (numbuf, "%d", rc );
540       gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave",
541                      numbuf, NULL);
542     }
543
544   return rc;
545 }
546