f155cfb2d6e7e648410efcf9ac8e93752abf7faf
[gnupg.git] / sm / certchain.c
1 /* certpath.c - path validation
2  *      Copyright (C) 2001 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 <gcrypt.h>
31 #include <ksba.h>
32
33 #include "gpgsm.h"
34 #include "keydb.h"
35 #include "i18n.h"
36
37 static int
38 unknown_criticals (KsbaCert cert)
39 {
40   static const char *known[] = {
41     "2.5.29.19", /* basic Constraints */
42     NULL
43   };
44   int rc = 0, i, idx, crit;
45   const char *oid;
46   KsbaError err;
47
48   for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
49                                              &oid, &crit, NULL, NULL));idx++)
50     {
51       if (!crit)
52         continue;
53       for (i=0; known[i] && strcmp (known[i],oid); i++)
54         ;
55       if (!known[i])
56         {
57           log_error (_("critical certificate extension %s is not supported\n"),
58                      oid);
59           rc = GNUPG_Unsupported_Certificate;
60         }
61     }
62   if (err && err != -1)
63     rc = map_ksba_err (err);
64
65   return rc;
66 }
67
68 static int
69 allowed_ca (KsbaCert cert, int *pathlen)
70 {
71   KsbaError err;
72   int flag;
73
74   err = ksba_cert_is_ca (cert, &flag, pathlen);
75   if (err)
76     return map_ksba_err (err);
77   if (!flag)
78     {
79       log_error (_("issuer certificate is not marked as a CA\n"));
80       return GNUPG_Bad_CA_Certificate;
81     }
82   return 0;
83 }
84
85
86 int
87 gpgsm_validate_path (KsbaCert cert)
88 {
89   int rc = 0, depth = 0, maxdepth;
90   char *issuer = NULL;
91   char *subject = NULL;
92   KEYDB_HANDLE kh = keydb_new (0);
93   KsbaCert subject_cert = NULL, issuer_cert = NULL;
94   time_t current_time = time (NULL);
95
96   if (!kh)
97     {
98       log_error (_("failed to allocated keyDB handle\n"));
99       rc = GNUPG_General_Error;
100       goto leave;
101     }
102
103   if (DBG_X509)
104     gpgsm_dump_cert ("subject", cert);
105
106   subject_cert = cert;
107   maxdepth = 50;
108
109   for (;;)
110     {
111       xfree (issuer);
112       xfree (subject);
113       issuer = ksba_cert_get_issuer (subject_cert, 0);
114       subject = ksba_cert_get_subject (subject_cert, 0);
115
116       if (!issuer)
117         {
118           log_error ("no issuer found in certificate\n");
119           rc = GNUPG_Bad_Certificate;
120           goto leave;
121         }
122
123       {
124         time_t not_before, not_after;
125
126         not_before = ksba_cert_get_validity (subject_cert, 0);
127         not_after = ksba_cert_get_validity (subject_cert, 1);
128         if (not_before == (time_t)(-1) || not_after == (time_t)(-1))
129           {
130             log_error ("certificate with invalid validity\n");
131             rc = GNUPG_Bad_Certificate;
132             goto leave;
133           }
134
135         if (current_time < not_before)
136           {
137             log_error ("certificate to young; valid from ");
138             gpgsm_dump_time (not_before);
139             log_printf ("\n");
140             rc = GNUPG_Certificate_Too_Young;
141             goto leave;
142           }            
143         if (current_time > not_after)
144           {
145             log_error ("certificate has expired at ");
146             gpgsm_dump_time (not_after);
147             log_printf ("\n");
148             rc = GNUPG_Certificate_Expired;
149             goto leave;
150           }            
151       }
152
153       rc = unknown_criticals (subject_cert);
154       if (rc)
155         goto leave;
156         
157       if (!opt.no_crl_check)
158         {
159           rc = gpgsm_dirmngr_isvalid (subject_cert);
160           if (rc)
161             {
162               switch (rc)
163                 {
164                 case GNUPG_Certificate_Revoked:
165                   log_error (_("the certificate has been revoked\n"));
166                   break;
167                 case GNUPG_No_CRL_Known:
168                   log_error (_("no CRL found for certificate\n"));
169                   break;
170                 case GNUPG_CRL_Too_Old:
171                   log_error (_("the available CRL is too old\n"));
172                   log_info (_("please make sure that the "
173                               "\"dirmngr\" is properly installed\n"));
174                   break;
175                 default:
176                   log_error (_("checking the CRL failed: %s\n"),
177                              gnupg_strerror (rc));
178                   break;
179                 }
180               goto leave;
181             }
182         }
183
184       if (subject && !strcmp (issuer, subject))
185         {
186           if (gpgsm_check_cert_sig (subject_cert, subject_cert) )
187             {
188               log_error ("selfsigned certificate has a BAD signatures\n");
189               rc = depth? GNUPG_Bad_Certificate_Path : GNUPG_Bad_Certificate;
190               goto leave;
191             }
192           rc = allowed_ca (subject_cert, NULL);
193           if (rc)
194             goto leave;
195
196           rc = gpgsm_agent_istrusted (subject_cert);
197           if (!rc)
198             ;
199           else if (rc == GNUPG_Not_Trusted)
200             {
201               char *fpr = gpgsm_get_fingerprint_string (subject_cert,
202                                                         GCRY_MD_SHA1);
203               log_error (_("root certificate is not marked trusted\n"));
204               log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
205               xfree (fpr);
206               /* fixme: print a note while we have not yet the code to
207                  ask whether the cert should be entered into the trust
208                  list */
209               gpgsm_dump_cert ("issuer", subject_cert);
210               log_info ("after checking the fingerprint, you may want "
211                         "to enter it into \"~/.gnupg-test/trustlist.txt\"\n");
212             }
213           else 
214             {
215               log_error (_("checking the trust list failed: %s\n"),
216                          gnupg_strerror (rc));
217             }
218           
219           break;  /* okay, a self-signed certicate is an end-point */
220         }
221       
222       depth++;
223       if (depth > maxdepth)
224         {
225           log_error (_("certificate path too long\n"));
226           rc = GNUPG_Bad_Certificate_Path;
227           goto leave;
228         }
229
230       /* find the next cert up the tree */
231       keydb_search_reset (kh);
232       rc = keydb_search_subject (kh, issuer);
233       if (rc)
234         {
235           log_error ("failed to find issuer's certificate: rc=%d\n", rc);
236           rc = GNUPG_Missing_Certificate;
237           goto leave;
238         }
239
240       ksba_cert_release (issuer_cert); issuer_cert = NULL;
241       rc = keydb_get_cert (kh, &issuer_cert);
242       if (rc)
243         {
244           log_error ("failed to get cert: rc=%d\n", rc);
245           rc = GNUPG_General_Error;
246           goto leave;
247         }
248
249       if (DBG_X509)
250         {
251           log_debug ("got issuer's certificate:\n");
252           gpgsm_dump_cert ("issuer", issuer_cert);
253         }
254
255       if (gpgsm_check_cert_sig (issuer_cert, subject_cert) )
256         {
257           log_error ("certificate has a BAD signatures\n");
258           rc = GNUPG_Bad_Certificate_Path;
259           goto leave;
260         }
261
262       {
263         int pathlen;
264         rc = allowed_ca (issuer_cert, &pathlen);
265         if (rc)
266           goto leave;
267         if (pathlen >= 0 && (depth - 1) > pathlen)
268           {
269             log_error (_("certificate path longer than allowed by CA (%d)\n"),
270                        pathlen);
271             rc = GNUPG_Bad_Certificate_Path;
272             goto leave;
273           }
274       }
275
276       log_info ("certificate is good\n");
277       
278       keydb_search_reset (kh);
279       subject_cert = issuer_cert;
280       issuer_cert = NULL;
281     }
282
283   if (opt.no_crl_check)
284     log_info ("CRL was not checked due to --no-crl-cechk option\n");
285
286   
287  leave:
288   xfree (issuer);
289   keydb_release (kh); 
290   ksba_cert_release (issuer_cert);
291   if (subject_cert != cert)
292     ksba_cert_release (subject_cert);
293   return rc;
294 }
295
296
297 /* Check that the given certificate is valid but DO NOT check any
298    constraints.  We assume that the issuers certificate is already in
299    the DB and that this one is valid; which it should be because it
300    has been checked using this function. */
301 int
302 gpgsm_basic_cert_check (KsbaCert cert)
303 {
304   int rc = 0;
305   char *issuer = NULL;
306   char *subject = NULL;
307   KEYDB_HANDLE kh = keydb_new (0);
308   KsbaCert issuer_cert = NULL;
309
310   if (!kh)
311     {
312       log_error (_("failed to allocated keyDB handle\n"));
313       rc = GNUPG_General_Error;
314       goto leave;
315     }
316
317   issuer = ksba_cert_get_issuer (cert, 0);
318   subject = ksba_cert_get_subject (cert, 0);
319   if (!issuer)
320     {
321       if (DBG_X509)
322         log_debug ("ERROR: issuer missing\n");
323       rc = GNUPG_Bad_Certificate;
324       goto leave;
325     }
326
327   if (subject && !strcmp (issuer, subject))
328     {
329       if (gpgsm_check_cert_sig (cert, cert) )
330         {
331           log_error ("selfsigned certificate has a BAD signatures\n");
332           rc = GNUPG_Bad_Certificate;
333           goto leave;
334         }
335     }
336   else
337     {
338       /* find the next cert up the tree */
339       keydb_search_reset (kh);
340       rc = keydb_search_subject (kh, issuer);
341       if (rc)
342         {
343           log_error ("failed to find issuer's certificate: rc=%d\n", rc);
344           rc = GNUPG_Missing_Certificate;
345           goto leave;
346         }
347       
348       ksba_cert_release (issuer_cert); issuer_cert = NULL;
349       rc = keydb_get_cert (kh, &issuer_cert);
350       if (rc)
351         {
352           log_error ("failed to get cert: rc=%d\n", rc);
353           rc = GNUPG_General_Error;
354           goto leave;
355         }
356
357       if (gpgsm_check_cert_sig (issuer_cert, cert) )
358         {
359           log_error ("certificate has a BAD signatures\n");
360           rc = GNUPG_Bad_Certificate;
361           goto leave;
362         }
363       if (opt.verbose)
364         log_info ("certificate is good\n");
365     }
366
367  leave:
368   xfree (issuer);
369   keydb_release (kh); 
370   ksba_cert_release (issuer_cert);
371   return rc;
372 }
373