* gpgsm.c: New command --keydb-clear-some-cert-flags.
[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   gpg_error_t err;
90   ksba_reader_t reader;
91   ksba_writer_t writer = NULL;
92   ksba_cms_t cms = NULL;
93   ksba_stop_reason_t stopreason;
94   ksba_cert_t cert;
95   KEYDB_HANDLE kh;
96   gcry_md_hd_t data_md = NULL;
97   int signer;
98   const char *algoid;
99   int algo;
100   int is_detached;
101   FILE *fp = NULL;
102   char *p;
103
104   kh = keydb_new (0);
105   if (!kh)
106     {
107       log_error (_("failed to allocated keyDB handle\n"));
108       rc = gpg_error (GPG_ERR_GENERAL);
109       goto leave;
110     }
111
112
113   fp = fdopen ( dup (in_fd), "rb");
114   if (!fp)
115     {
116       rc = gpg_error (gpg_err_code_from_errno (errno));
117       log_error ("fdopen() failed: %s\n", strerror (errno));
118       goto leave;
119     }
120
121   rc = gpgsm_create_reader (&b64reader, ctrl, fp, 0, &reader);
122   if (rc)
123     {
124       log_error ("can't create reader: %s\n", gpg_strerror (rc));
125       goto leave;
126     }
127
128   if (out_fp)
129     {
130       rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
131       if (rc)
132         {
133           log_error ("can't create writer: %s\n", gpg_strerror (rc));
134           goto leave;
135         }
136     }
137
138   err = ksba_cms_new (&cms);
139   if (err)
140     {
141       rc = gpg_error (GPG_ERR_ENOMEM);
142       goto leave;
143     }
144
145   err = ksba_cms_set_reader_writer (cms, reader, writer);
146   if (err)
147     {
148       log_error ("ksba_cms_set_reader_writer failed: %s\n",
149                  gpg_strerror (err));
150       rc = err;
151       goto leave;
152     }
153
154   rc = gcry_md_open (&data_md, 0, 0);
155   if (rc)
156     {
157       log_error ("md_open failed: %s\n", gpg_strerror (rc));
158       goto leave;
159     }
160   if (DBG_HASHING)
161     gcry_md_start_debug (data_md, "vrfy.data");
162
163   is_detached = 0;
164   do 
165     {
166       err = ksba_cms_parse (cms, &stopreason);
167       if (err)
168         {
169           log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (err));
170           rc = err;
171           goto leave;
172         }
173
174       if (stopreason == KSBA_SR_NEED_HASH)
175         {
176           is_detached = 1;
177           if (opt.verbose)
178             log_info ("detached signature\n");
179         }
180
181       if (stopreason == KSBA_SR_NEED_HASH
182           || stopreason == KSBA_SR_BEGIN_DATA)
183         { /* We are now able to enable the hash algorithms */
184           for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
185             {
186               algo = gcry_md_map_name (algoid);
187               if (!algo)
188                 log_error ("unknown hash algorithm `%s'\n",
189                            algoid? algoid:"?");
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   err = 0;
242   for (signer=0; ; signer++)
243     {
244       char *issuer = NULL;
245       ksba_sexp_t sigval = NULL;
246       ksba_isotime_t sigtime, keyexptime;
247       ksba_sexp_t serial;
248       char *msgdigest = NULL;
249       size_t msgdigestlen;
250       char *ctattr;
251
252       err = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
253       if (!signer && gpg_err_code (err) == GPG_ERR_NO_DATA
254           && data_fd == -1 && is_detached)
255         {
256           log_info ("certs-only message accepted\n");
257           err = 0;
258           break;
259         }
260       if (err)
261         {
262           if (signer && err == -1)
263             err = 0;
264           break;
265         }
266
267       gpgsm_status (ctrl, STATUS_NEWSIG, NULL);
268
269       if (DBG_X509)
270         {
271           log_debug ("signer %d - issuer: `%s'\n",
272                      signer, issuer? issuer:"[NONE]");
273           log_debug ("signer %d - serial: ", signer);
274           gpgsm_dump_serial (serial);
275           log_printf ("\n");
276         }
277
278       err = ksba_cms_get_signing_time (cms, signer, sigtime);
279       if (gpg_err_code (err) == GPG_ERR_NO_DATA)
280         *sigtime = 0;
281       else if (err)
282         {
283           log_error ("error getting signing time: %s\n", gpg_strerror (err));
284           *sigtime = 0; /* FIXME: we can't encode an error in the time
285                            string. */
286         }
287
288       err = ksba_cms_get_message_digest (cms, signer,
289                                          &msgdigest, &msgdigestlen);
290       if (!err)
291         {
292           size_t is_enabled;
293
294           algoid = ksba_cms_get_digest_algo (cms, signer);
295           algo = gcry_md_map_name (algoid);
296           if (DBG_X509)
297             log_debug ("signer %d - digest algo: %d\n", signer, algo);
298           is_enabled = sizeof algo;
299           if ( gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED,
300                              &algo, &is_enabled)
301                || !is_enabled)
302             {
303               log_error ("digest algo %d has not been enabled\n", algo);
304               goto next_signer;
305             }
306         }
307       else if (gpg_err_code (err) == GPG_ERR_NO_DATA)
308         {
309           assert (!msgdigest);
310           err = 0;
311           algoid = NULL;
312           algo = 0; 
313         }
314       else /* real error */
315         break;
316
317       err = ksba_cms_get_sigattr_oids (cms, signer,
318                                        "1.2.840.113549.1.9.3",&ctattr);
319       if (!err) 
320         {
321           const char *s;
322
323           if (DBG_X509)
324             log_debug ("signer %d - content-type attribute: %s", signer, ctattr);
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 (err != -1)
338         {
339           log_error ("error getting content-type attribute: %s\n",
340                      gpg_strerror (err));
341           goto next_signer;
342         }
343       err = 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   if (err)
527     { /* FIXME: still needed? */
528       log_error ("ksba error: %s\n", gpg_strerror (err));
529       rc = err;
530     }    
531
532
533
534  leave:
535   ksba_cms_release (cms);
536   gpgsm_destroy_reader (b64reader);
537   gpgsm_destroy_writer (b64writer);
538   keydb_release (kh); 
539   gcry_md_close (data_md);
540   if (fp)
541     fclose (fp);
542
543   if (rc)
544     {
545       char numbuf[50];
546       sprintf (numbuf, "%d", rc );
547       gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave",
548                      numbuf, NULL);
549     }
550
551   return rc;
552 }
553