* certpath.c (gpgsm_validate_path): Ask the agent to add the
[gnupg.git] / sm / certpath.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               int rc2;
265
266               char *fpr = gpgsm_get_fingerprint_string (subject_cert,
267                                                         GCRY_MD_SHA1);
268               log_info (_("root certificate is not marked trusted\n"));
269               log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
270               xfree (fpr);
271               rc2 = gpgsm_agent_marktrusted (subject_cert);
272               if (!rc2)
273                 {
274                   log_info (_("root certificate has now"
275                               " been marked as trusted\n"));
276                   rc = 0;
277                 }
278               else 
279                 {
280                   gpgsm_dump_cert ("issuer", subject_cert);
281                   log_info ("after checking the fingerprint, you may want "
282                             "to enter it manually into "
283                             "\"~/.gnupg-test/trustlist.txt\"\n");
284                 }
285             }
286           else 
287             {
288               log_error (_("checking the trust list failed: %s\n"),
289                          gnupg_strerror (rc));
290             }
291           
292           break;  /* okay, a self-signed certicate is an end-point */
293         }
294       
295       depth++;
296       if (depth > maxdepth)
297         {
298           log_error (_("certificate path too long\n"));
299           rc = GNUPG_Bad_Certificate_Path;
300           goto leave;
301         }
302
303       /* find the next cert up the tree */
304       keydb_search_reset (kh);
305       rc = keydb_search_subject (kh, issuer);
306       if (rc)
307         {
308           if (rc == -1)
309             {
310               log_info ("issuer certificate (");
311               gpgsm_dump_string (issuer);
312               log_printf (") not found\n");
313             }
314           else
315             log_error ("failed to find issuer's certificate: rc=%d\n", rc);
316           rc = GNUPG_Missing_Certificate;
317           goto leave;
318         }
319
320       ksba_cert_release (issuer_cert); issuer_cert = NULL;
321       rc = keydb_get_cert (kh, &issuer_cert);
322       if (rc)
323         {
324           log_error ("failed to get cert: rc=%d\n", rc);
325           rc = GNUPG_General_Error;
326           goto leave;
327         }
328
329       if (DBG_X509)
330         {
331           log_debug ("got issuer's certificate:\n");
332           gpgsm_dump_cert ("issuer", issuer_cert);
333         }
334
335       if (gpgsm_check_cert_sig (issuer_cert, subject_cert) )
336         {
337           log_error ("certificate has a BAD signatures\n");
338           rc = GNUPG_Bad_Certificate_Path;
339           goto leave;
340         }
341
342       {
343         int pathlen;
344         rc = allowed_ca (issuer_cert, &pathlen);
345         if (rc)
346           goto leave;
347         if (pathlen >= 0 && (depth - 1) > pathlen)
348           {
349             log_error (_("certificate path longer than allowed by CA (%d)\n"),
350                        pathlen);
351             rc = GNUPG_Bad_Certificate_Path;
352             goto leave;
353           }
354       }
355
356       log_info ("certificate is good\n");
357       
358       keydb_search_reset (kh);
359       subject_cert = issuer_cert;
360       issuer_cert = NULL;
361     }
362
363   if (opt.no_crl_check)
364     log_info ("CRL was not checked due to --no-crl-cechk option\n");
365
366   
367  leave:
368   xfree (issuer);
369   keydb_release (kh); 
370   ksba_cert_release (issuer_cert);
371   if (subject_cert != cert)
372     ksba_cert_release (subject_cert);
373   return rc;
374 }
375
376
377 /* Check that the given certificate is valid but DO NOT check any
378    constraints.  We assume that the issuers certificate is already in
379    the DB and that this one is valid; which it should be because it
380    has been checked using this function. */
381 int
382 gpgsm_basic_cert_check (KsbaCert cert)
383 {
384   int rc = 0;
385   char *issuer = NULL;
386   char *subject = NULL;
387   KEYDB_HANDLE kh = keydb_new (0);
388   KsbaCert issuer_cert = NULL;
389
390   if (!kh)
391     {
392       log_error (_("failed to allocated keyDB handle\n"));
393       rc = GNUPG_General_Error;
394       goto leave;
395     }
396
397   issuer = ksba_cert_get_issuer (cert, 0);
398   subject = ksba_cert_get_subject (cert, 0);
399   if (!issuer)
400     {
401       if (DBG_X509)
402         log_debug ("ERROR: issuer missing\n");
403       rc = GNUPG_Bad_Certificate;
404       goto leave;
405     }
406
407   if (subject && !strcmp (issuer, subject))
408     {
409       if (gpgsm_check_cert_sig (cert, cert) )
410         {
411           log_error ("selfsigned certificate has a BAD signatures\n");
412           rc = GNUPG_Bad_Certificate;
413           goto leave;
414         }
415     }
416   else
417     {
418       /* find the next cert up the tree */
419       keydb_search_reset (kh);
420       rc = keydb_search_subject (kh, issuer);
421       if (rc)
422         {
423           if (rc == -1)
424             {
425               log_info ("issuer certificate (");
426               gpgsm_dump_string (issuer);
427               log_printf (") not found\n");
428             }
429           else
430             log_error ("failed to find issuer's certificate: rc=%d\n", rc);
431           rc = GNUPG_Missing_Certificate;
432           goto leave;
433         }
434       
435       ksba_cert_release (issuer_cert); issuer_cert = NULL;
436       rc = keydb_get_cert (kh, &issuer_cert);
437       if (rc)
438         {
439           log_error ("failed to get cert: rc=%d\n", rc);
440           rc = GNUPG_General_Error;
441           goto leave;
442         }
443
444       if (gpgsm_check_cert_sig (issuer_cert, cert) )
445         {
446           log_error ("certificate has a BAD signatures\n");
447           rc = GNUPG_Bad_Certificate;
448           goto leave;
449         }
450       if (opt.verbose)
451         log_info ("certificate is good\n");
452     }
453
454  leave:
455   xfree (issuer);
456   keydb_release (kh); 
457   ksba_cert_release (issuer_cert);
458   return rc;
459 }
460