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