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