(gpgsm_sign): Include a short list of capabilities.
[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       if (DBG_X509)
267         {
268           log_debug ("signer %d - issuer: `%s'\n",
269                      signer, issuer? issuer:"[NONE]");
270           log_debug ("signer %d - serial: ", signer);
271           gpgsm_dump_serial (serial);
272           log_printf ("\n");
273         }
274
275       err = ksba_cms_get_signing_time (cms, signer, sigtime);
276       if (gpg_err_code (err) == GPG_ERR_NO_DATA)
277         *sigtime = 0;
278       else if (err)
279         {
280           log_error ("error getting signing time: %s\n", gpg_strerror (err));
281           *sigtime = 0; /* FIXME: we can't encode an error in the time
282                            string. */
283         }
284
285       err = ksba_cms_get_message_digest (cms, signer,
286                                          &msgdigest, &msgdigestlen);
287       if (!err)
288         {
289           size_t is_enabled;
290
291           algoid = ksba_cms_get_digest_algo (cms, signer);
292           algo = gcry_md_map_name (algoid);
293           if (DBG_X509)
294             log_debug ("signer %d - digest algo: %d\n", signer, algo);
295           is_enabled = sizeof algo;
296           if ( gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED,
297                              &algo, &is_enabled)
298                || !is_enabled)
299             {
300               log_error ("digest algo %d has not been enabled\n", algo);
301               goto next_signer;
302             }
303         }
304       else if (gpg_err_code (err) == GPG_ERR_NO_DATA)
305         {
306           assert (!msgdigest);
307           err = 0;
308           algoid = NULL;
309           algo = 0; 
310         }
311       else /* real error */
312         break;
313
314       err = ksba_cms_get_sigattr_oids (cms, signer,
315                                        "1.2.840.113549.1.9.3",&ctattr);
316       if (!err) 
317         {
318           const char *s;
319
320           if (DBG_X509)
321             log_debug ("signer %d - content-type attribute: %s", signer, ctattr);
322           s = ksba_cms_get_content_oid (cms, 1);
323           if (!s || strcmp (ctattr, s))
324             {
325               log_error ("content-type attribute does not match "
326                          "actual content-type\n");
327               ksba_free (ctattr);
328               ctattr = NULL;
329               goto next_signer;
330             }
331           ksba_free (ctattr);
332           ctattr = NULL;
333         }
334       else if (err != -1)
335         {
336           log_error ("error getting content-type attribute: %s\n",
337                      gpg_strerror (err));
338           goto next_signer;
339         }
340       err = 0;
341
342
343       sigval = ksba_cms_get_sig_val (cms, signer);
344       if (!sigval)
345         {
346           log_error ("no signature value available\n");
347           goto next_signer;
348         }
349       if (DBG_X509)
350         log_debug ("signer %d - signature available", signer);
351
352       /* Find the certificate of the signer */
353       keydb_search_reset (kh);
354       rc = keydb_search_issuer_sn (kh, issuer, serial);
355       if (rc)
356         {
357           if (rc == -1)
358             {
359               log_error ("certificate not found\n");
360               rc = gpg_error (GPG_ERR_NO_PUBKEY);
361             }
362           else
363             log_error ("failed to find the certificate: %s\n",
364                        gpg_strerror(rc));
365           {
366             char numbuf[50];
367             sprintf (numbuf, "%d", rc);
368
369             gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey",
370                            numbuf, NULL);
371           }
372           /* fixme: we might want to append the issuer and serial
373              using our standard notation */
374           goto next_signer;
375         }
376
377       rc = keydb_get_cert (kh, &cert);
378       if (rc)
379         {
380           log_error ("failed to get cert: %s\n", gpg_strerror (rc));
381           goto next_signer;
382         }
383
384       log_info (_("Signature made "));
385       if (*sigtime)
386         gpgsm_dump_time (sigtime);
387       else
388         log_printf (_("[date not given]"));
389       log_printf (_(" using certificate ID %08lX\n"),
390                   gpgsm_get_short_fingerprint (cert));
391
392
393       if (msgdigest)
394         { /* Signed attributes are available. */
395           gcry_md_hd_t md;
396           unsigned char *s;
397
398           /* check that the message digest in the signed attributes
399              matches the one we calculated on the data */
400           s = gcry_md_read (data_md, algo);
401           if ( !s || !msgdigestlen
402                || gcry_md_get_algo_dlen (algo) != msgdigestlen
403                || !s || memcmp (s, msgdigest, msgdigestlen) )
404             {
405               char *fpr;
406
407               log_error ("invalid signature: message digest attribute "
408                          "does not match calculated one\n");
409               fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
410               gpgsm_status (ctrl, STATUS_BADSIG, fpr);
411               xfree (fpr);
412               goto next_signer; 
413             }
414             
415           rc = gcry_md_open (&md, algo, 0);
416           if (rc)
417             {
418               log_error ("md_open failed: %s\n", gpg_strerror (rc));
419               goto next_signer;
420             }
421           if (DBG_HASHING)
422             gcry_md_start_debug (md, "vrfy.attr");
423
424           ksba_cms_set_hash_function (cms, HASH_FNC, md);
425           rc = ksba_cms_hash_signed_attrs (cms, signer);
426           if (rc)
427             {
428               log_error ("hashing signed attrs failed: %s\n",
429                          gpg_strerror (rc));
430               gcry_md_close (md);
431               goto next_signer;
432             }
433           rc = gpgsm_check_cms_signature (cert, sigval, md, algo);
434           gcry_md_close (md);
435         }
436       else
437         {
438           rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo);
439         }
440
441       if (rc)
442         {
443           char *fpr;
444
445           log_error ("invalid signature: %s\n", gpg_strerror (rc));
446           fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
447           gpgsm_status (ctrl, STATUS_BADSIG, fpr);
448           xfree (fpr);
449           goto next_signer;
450         }
451       rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/
452       if (rc)
453         {
454           gpgsm_status_with_err_code (ctrl, STATUS_ERROR, "verify.keyusage",
455                                       gpg_err_code (rc));
456           rc = 0;
457         }
458
459       if (DBG_X509)
460         log_debug ("signature okay - checking certs\n");
461       rc = gpgsm_validate_chain (ctrl, cert, keyexptime, 0, NULL);
462       if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED)
463         {
464           gpgsm_status (ctrl, STATUS_EXPKEYSIG, NULL);
465           rc = 0;
466         }
467       else
468         gpgsm_status (ctrl, STATUS_GOODSIG, NULL);
469       
470       {
471         char *buf, *fpr, *tstr;
472
473         fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
474         tstr = strtimestamp_r (sigtime);
475         buf = xmalloc ( strlen(fpr) + strlen (tstr) + 120);
476         sprintf (buf, "%s %s %s %s", fpr, tstr,
477                  *sigtime? sigtime : "0",
478                  *keyexptime? keyexptime : "0" );
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     { /* FIXME: still needed? */
525       log_error ("ksba error: %s\n", gpg_strerror (err));
526       rc = err;
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