* gpgsm.c: Add option --enable-crl-checks.
[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 int
38 gpgsm_validate_path (KsbaCert cert)
39 {
40   int rc = 0, depth = 0;
41   char *issuer = NULL;
42   char *subject = NULL;
43   KEYDB_HANDLE kh = keydb_new (0);
44   KsbaCert subject_cert = NULL, issuer_cert = NULL;
45
46   if (!kh)
47     {
48       log_error (_("failed to allocated keyDB handle\n"));
49       rc = GNUPG_General_Error;
50       goto leave;
51     }
52
53   if (DBG_X509)
54     gpgsm_dump_cert ("subject", cert);
55
56   subject_cert = cert;
57
58   /* FIXME: We need to check that none of the certs didexpire */
59
60   for (;;)
61     {
62       xfree (issuer);
63       xfree (subject);
64       issuer = ksba_cert_get_issuer (subject_cert, 0);
65       subject = ksba_cert_get_subject (subject_cert, 0);
66
67       if (!issuer)
68         {
69           if (DBG_X509)
70             log_debug ("ERROR: issuer missing\n");
71           rc = GNUPG_Bad_Certificate;
72           goto leave;
73         }
74
75       if (!opt.no_crl_check)
76         {
77           rc = gpgsm_dirmngr_isvalid (subject_cert);
78           if (rc)
79             {
80               switch (rc)
81                 {
82                 case GNUPG_Certificate_Revoked:
83                   log_error (_("the certificate has been revoked\n"));
84                   break;
85                 case GNUPG_No_CRL_Known:
86                   log_error (_("no CRL found for certificate\n"));
87                   break;
88                 case GNUPG_CRL_Too_Old:
89                   log_error (_("the available CRL is too old\n"));
90                   log_info (_("please make sure that the "
91                               "\"dirmngr\" is properly installed\n"));
92                   break;
93                 default:
94                   log_error (_("checking the CRL failed: %s\n"),
95                              gnupg_strerror (rc));
96                   break;
97                 }
98               goto leave;
99             }
100         }
101
102       if (subject && !strcmp (issuer, subject))
103         {
104           if (gpgsm_check_cert_sig (subject_cert, subject_cert) )
105             {
106               log_error ("selfsigned certificate has a BAD signatures\n");
107               rc = depth? GNUPG_Bad_Certificate_Path : GNUPG_Bad_Certificate;
108               goto leave;
109             }
110           rc = gpgsm_agent_istrusted (subject_cert);
111           if (!rc)
112             ;
113           else if (rc == GNUPG_Not_Trusted)
114             {
115               char *fpr = gpgsm_get_fingerprint_string (subject_cert,
116                                                         GCRY_MD_SHA1);
117               log_error (_("root certificate is not marked trusted\n"));
118               log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
119               xfree (fpr);
120               /* fixme: print a note while we have not yet the code to
121                  ask whether the cert should be netered into the trust
122                  list */
123               gpgsm_dump_cert ("issuer", subject_cert);
124               log_info ("after checking the fingerprint, you may want "
125                         "to enter it into \"~/.gnupg-test/trustlist.txt\"\n");
126             }
127           else 
128             {
129               log_error (_("checking the trust list failed: %s\n"),
130                          gnupg_strerror (rc));
131             }
132           
133           break;  /* okay, a self-signed certicate is an end-point */
134         }
135       
136       depth++;
137       /* fixme: check against a maximum path length */
138
139       /* find the next cert up the tree */
140       keydb_search_reset (kh);
141       rc = keydb_search_subject (kh, issuer);
142       if (rc)
143         {
144           log_error ("failed to find issuer's certificate: rc=%d\n", rc);
145           rc = GNUPG_Missing_Certificate;
146           goto leave;
147         }
148
149       ksba_cert_release (issuer_cert); issuer_cert = NULL;
150       rc = keydb_get_cert (kh, &issuer_cert);
151       if (rc)
152         {
153           log_error ("failed to get cert: rc=%d\n", rc);
154           rc = GNUPG_General_Error;
155           goto leave;
156         }
157
158       if (DBG_X509)
159         {
160           log_debug ("got issuer's certificate:\n");
161           gpgsm_dump_cert ("issuer", issuer_cert);
162         }
163
164       if (gpgsm_check_cert_sig (issuer_cert, subject_cert) )
165         {
166           log_error ("certificate has a BAD signatures\n");
167           rc = GNUPG_Bad_Certificate_Path;
168           goto leave;
169         }
170       if (opt.verbose)
171         log_info ("certificate is good\n");
172       
173       keydb_search_reset (kh);
174       subject_cert = issuer_cert;
175       issuer_cert = NULL;
176     }
177
178   if (opt.no_crl_check)
179     log_info ("CRL was not checked due to --no-crl-cechk option\n");
180
181   
182  leave:
183   xfree (issuer);
184   keydb_release (kh); 
185   ksba_cert_release (issuer_cert);
186   if (subject_cert != cert)
187     ksba_cert_release (subject_cert);
188   return rc;
189 }
190
191
192 /* Check that the given certificate is valid but DO NOT check any
193    constraints.  We assume that the issuers certificate is already in
194    the DB and that this one is valid; which it should be because it
195    has been checked using this function. */
196 int
197 gpgsm_basic_cert_check (KsbaCert cert)
198 {
199   int rc = 0;
200   char *issuer = NULL;
201   char *subject = NULL;
202   KEYDB_HANDLE kh = keydb_new (0);
203   KsbaCert issuer_cert = NULL;
204
205   if (!kh)
206     {
207       log_error (_("failed to allocated keyDB handle\n"));
208       rc = GNUPG_General_Error;
209       goto leave;
210     }
211
212   issuer = ksba_cert_get_issuer (cert, 0);
213   subject = ksba_cert_get_subject (cert, 0);
214   if (!issuer)
215     {
216       if (DBG_X509)
217         log_debug ("ERROR: issuer missing\n");
218       rc = GNUPG_Bad_Certificate;
219       goto leave;
220     }
221
222   if (subject && !strcmp (issuer, subject))
223     {
224       if (gpgsm_check_cert_sig (cert, cert) )
225         {
226           log_error ("selfsigned certificate has a BAD signatures\n");
227           rc = GNUPG_Bad_Certificate;
228           goto leave;
229         }
230     }
231   else
232     {
233       /* find the next cert up the tree */
234       keydb_search_reset (kh);
235       rc = keydb_search_subject (kh, issuer);
236       if (rc)
237         {
238           log_error ("failed to find issuer's certificate: rc=%d\n", rc);
239           rc = GNUPG_Missing_Certificate;
240           goto leave;
241         }
242       
243       ksba_cert_release (issuer_cert); issuer_cert = NULL;
244       rc = keydb_get_cert (kh, &issuer_cert);
245       if (rc)
246         {
247           log_error ("failed to get cert: rc=%d\n", rc);
248           rc = GNUPG_General_Error;
249           goto leave;
250         }
251
252       if (gpgsm_check_cert_sig (issuer_cert, cert) )
253         {
254           log_error ("certificate has a BAD signatures\n");
255           rc = GNUPG_Bad_Certificate;
256           goto leave;
257         }
258       if (opt.verbose)
259         log_info ("certificate is good\n");
260     }
261
262  leave:
263   xfree (issuer);
264   keydb_release (kh); 
265   ksba_cert_release (issuer_cert);
266   return rc;
267 }
268