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