2006-05-19 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / sm / certlist.c
1 /* certlist.c - build list of certificates
2  *      Copyright (C) 2001, 2003, 2004, 2005 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
38 static const char oid_kp_serverAuth[]     = "1.3.6.1.5.5.7.3.1";
39 static const char oid_kp_clientAuth[]     = "1.3.6.1.5.5.7.3.2";
40 static const char oid_kp_codeSigning[]    = "1.3.6.1.5.5.7.3.3";
41 static const char oid_kp_emailProtection[]= "1.3.6.1.5.5.7.3.4";
42 static const char oid_kp_timeStamping[]   = "1.3.6.1.5.5.7.3.8";
43 static const char oid_kp_ocspSigning[]    = "1.3.6.1.5.5.7.3.9";
44
45 /* Return 0 if the cert is usable for encryption.  A MODE of 0 checks
46    for signing a MODE of 1 checks for encryption, a MODE of 2 checks
47    for verification and a MODE of 3 for decryption (just for
48    debugging).  MODE 4 is for certificate signing, MODE for COSP
49    response signing. */
50 static int
51 cert_usage_p (ksba_cert_t cert, int mode)
52 {
53   gpg_error_t err;
54   unsigned int use;
55   char *extkeyusages;
56   int have_ocsp_signing = 0;
57
58   err = ksba_cert_get_ext_key_usages (cert, &extkeyusages);
59   if (gpg_err_code (err) == GPG_ERR_NO_DATA)
60     err = 0; /* no policy given */
61   if (!err)
62     {
63       unsigned int extusemask = ~0; /* Allow all. */
64
65       if (extkeyusages)
66         {
67           char *p, *pend;
68           int any_critical = 0;
69
70           extusemask = 0;
71
72           p = extkeyusages;
73           while (p && (pend=strchr (p, ':')))
74             {
75               *pend++ = 0;
76               /* Only care about critical flagged usages. */
77               if ( *pend == 'C' )
78                 {
79                   any_critical = 1;
80                   if ( !strcmp (p, oid_kp_serverAuth))
81                     extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE
82                                    | KSBA_KEYUSAGE_KEY_ENCIPHERMENT
83                                    | KSBA_KEYUSAGE_KEY_AGREEMENT);
84                   else if ( !strcmp (p, oid_kp_clientAuth))
85                     extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE
86                                    | KSBA_KEYUSAGE_KEY_AGREEMENT);
87                   else if ( !strcmp (p, oid_kp_codeSigning))
88                     extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE);
89                   else if ( !strcmp (p, oid_kp_emailProtection))
90                     extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE
91                                    | KSBA_KEYUSAGE_NON_REPUDIATION
92                                    | KSBA_KEYUSAGE_KEY_ENCIPHERMENT
93                                    | KSBA_KEYUSAGE_KEY_AGREEMENT);
94                   else if ( !strcmp (p, oid_kp_timeStamping))
95                     extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE
96                                    | KSBA_KEYUSAGE_NON_REPUDIATION);
97                 }
98               
99               /* This is a hack to cope with OCSP.  Note that we do
100                  not yet fully comply with the requirements and that
101                  the entire CRL/OCSP checking thing should undergo a
102                  thorough review and probably redesign. */
103               if ( !strcmp (p, oid_kp_ocspSigning))
104                 have_ocsp_signing = 1;
105
106               if ((p = strchr (pend, '\n')))
107                 p++;
108             }
109           xfree (extkeyusages);
110           extkeyusages = NULL;
111           
112           if (!any_critical)
113             extusemask = ~0; /* Reset to the don't care mask. */
114         }
115
116
117       err = ksba_cert_get_key_usage (cert, &use);
118       if (gpg_err_code (err) == GPG_ERR_NO_DATA)
119         {
120           err = 0;
121           if (opt.verbose && mode < 2)
122             log_info (_("no key usage specified - assuming all usages\n"));
123           use = ~0;
124         }
125
126       /* Apply extKeyUsage. */
127       use &= extusemask;
128
129     }
130   if (err)
131     { 
132       log_error (_("error getting key usage information: %s\n"),
133                  gpg_strerror (err));
134       xfree (extkeyusages);
135       return err;
136     } 
137
138   if (mode == 4)
139     {
140       if ((use & (KSBA_KEYUSAGE_KEY_CERT_SIGN)))
141         return 0;
142       log_info (_("certificate should have not "
143                   "been used for certification\n"));
144       return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
145     }
146
147   if (mode == 5)
148     {
149       if (use != ~0 
150           && (have_ocsp_signing
151               || (use & (KSBA_KEYUSAGE_KEY_CERT_SIGN
152                          |KSBA_KEYUSAGE_CRL_SIGN))))
153         return 0;
154       log_info (_("certificate should have not "
155                   "been used for OCSP response signing\n"));
156       return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
157     }
158
159   if ((use & ((mode&1)?
160               (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT):
161               (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
162       )
163     return 0;
164
165   log_info (mode==3? _("certificate should have not been used for encryption\n"):
166             mode==2? _("certificate should have not been used for signing\n"):
167             mode==1? _("certificate is not usable for encryption\n"):
168                      _("certificate is not usable for signing\n"));
169   return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
170 }
171
172
173 /* Return 0 if the cert is usable for signing */
174 int
175 gpgsm_cert_use_sign_p (ksba_cert_t cert)
176 {
177   return cert_usage_p (cert, 0);
178 }
179
180
181 /* Return 0 if the cert is usable for encryption */
182 int
183 gpgsm_cert_use_encrypt_p (ksba_cert_t cert)
184 {
185   return cert_usage_p (cert, 1);
186 }
187
188 int
189 gpgsm_cert_use_verify_p (ksba_cert_t cert)
190 {
191   return cert_usage_p (cert, 2);
192 }
193
194 int
195 gpgsm_cert_use_decrypt_p (ksba_cert_t cert)
196 {
197   return cert_usage_p (cert, 3);
198 }
199
200 int
201 gpgsm_cert_use_cert_p (ksba_cert_t cert)
202 {
203   return cert_usage_p (cert, 4);
204 }
205
206 int
207 gpgsm_cert_use_ocsp_p (ksba_cert_t cert)
208 {
209   return cert_usage_p (cert, 5);
210 }
211
212
213 static int
214 same_subject_issuer (const char *subject, const char *issuer, ksba_cert_t cert)
215 {
216   char *subject2 = ksba_cert_get_subject (cert, 0);
217   char *issuer2 = ksba_cert_get_subject (cert, 0);
218   int tmp;
219   
220   tmp = (subject && subject2
221          && !strcmp (subject, subject2)
222          && issuer && issuer2
223          && !strcmp (issuer, issuer2));
224   xfree (subject2);
225   xfree (issuer2);
226   return tmp;
227 }
228
229 /* Return true if CERT is already contained in CERTLIST. */
230 static int
231 is_cert_in_certlist (ksba_cert_t cert, certlist_t certlist)
232 {
233   const unsigned char *img_a, *img_b;
234   size_t len_a, len_b;
235
236   img_a = ksba_cert_get_image (cert, &len_a);
237   if (img_a)
238     {
239       for ( ; certlist; certlist = certlist->next)
240         {
241           img_b = ksba_cert_get_image (certlist->cert, &len_b);
242           if (img_b && len_a == len_b && !memcmp (img_a, img_b, len_a))
243             return 1; /* Already contained. */
244         }
245     }
246   return 0;
247 }
248
249
250 /* Add CERT to the list of certificates at CERTADDR but avoid
251    duplicates. */
252 int 
253 gpgsm_add_cert_to_certlist (ctrl_t ctrl, ksba_cert_t cert,
254                             certlist_t *listaddr, int is_encrypt_to)
255 {
256   if (!is_cert_in_certlist (cert, *listaddr))
257     {
258       certlist_t cl = xtrycalloc (1, sizeof *cl);
259       if (!cl)
260         return OUT_OF_CORE (errno);
261       cl->cert = cert;
262       ksba_cert_ref (cert);
263       cl->next = *listaddr;
264       cl->is_encrypt_to = is_encrypt_to;
265       *listaddr = cl;
266     }
267    return 0;
268 }
269
270 /* Add a certificate to a list of certificate and make sure that it is
271    a valid certificate.  With SECRET set to true a secret key must be
272    available for the certificate. IS_ENCRYPT_TO sets the corresponding
273    flag in the new create LISTADDR item.  */
274 int
275 gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret,
276                        CERTLIST *listaddr, int is_encrypt_to)
277 {
278   int rc;
279   KEYDB_SEARCH_DESC desc;
280   KEYDB_HANDLE kh = NULL;
281   ksba_cert_t cert = NULL;
282
283   rc = keydb_classify_name (name, &desc);
284   if (!rc)
285     {
286       kh = keydb_new (0);
287       if (!kh)
288         rc = gpg_error (GPG_ERR_ENOMEM);
289       else
290         {
291           int wrong_usage = 0;
292           char *subject = NULL;
293           char *issuer = NULL;
294
295         get_next:
296           rc = keydb_search (kh, &desc, 1);
297           if (!rc)
298             rc = keydb_get_cert (kh, &cert);
299           if (!rc)
300             {
301               rc = secret? gpgsm_cert_use_sign_p (cert)
302                          : gpgsm_cert_use_encrypt_p (cert);
303               if (gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE)
304                 {
305                   /* There might be another certificate with the
306                      correct usage, so we try again */
307                   if (!wrong_usage)
308                     { /* save the first match */
309                       wrong_usage = rc;
310                       subject = ksba_cert_get_subject (cert, 0);
311                       issuer = ksba_cert_get_subject (cert, 0);
312                       ksba_cert_release (cert);
313                       cert = NULL;
314                       goto get_next;
315                     }
316                   else if (same_subject_issuer (subject, issuer, cert))
317                     {
318                       wrong_usage = rc;
319                       ksba_cert_release (cert);
320                       cert = NULL;
321                       goto get_next;
322                     }
323                   else
324                     wrong_usage = rc;
325
326                 }
327             }
328           /* We want the error code from the first match in this case. */
329           if (rc && wrong_usage)
330             rc = wrong_usage;
331           
332           if (!rc)
333             {
334             next_ambigious:
335               rc = keydb_search (kh, &desc, 1);
336               if (rc == -1)
337                 rc = 0;
338               else if (!rc)
339                 {
340                   ksba_cert_t cert2 = NULL;
341
342                   /* We have to ignore ambigious names as long as
343                      there only fault is a bad key usage */
344                   if (!keydb_get_cert (kh, &cert2))
345                     {
346                       int tmp = (same_subject_issuer (subject, issuer, cert2)
347                                  && ((gpg_err_code (
348                                       secret? gpgsm_cert_use_sign_p (cert2)
349                                             : gpgsm_cert_use_encrypt_p (cert2)
350                                       )
351                                      )  == GPG_ERR_WRONG_KEY_USAGE));
352                       ksba_cert_release (cert2);
353                       if (tmp)
354                         goto next_ambigious;
355                     }
356                   rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
357                 }
358             }
359           xfree (subject);
360           xfree (issuer);
361
362           if (!rc && !is_cert_in_certlist (cert, *listaddr))
363             {
364               if (!rc && secret) 
365                 {
366                   char *p;
367                   
368                   rc = gpg_error (GPG_ERR_NO_SECKEY);
369                   p = gpgsm_get_keygrip_hexstring (cert);
370                   if (p)
371                     {
372                       if (!gpgsm_agent_havekey (ctrl, p))
373                         rc = 0;
374                       xfree (p);
375                     }
376                 }
377               if (!rc)
378                 rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0);
379               if (!rc)
380                 {
381                   CERTLIST cl = xtrycalloc (1, sizeof *cl);
382                   if (!cl)
383                     rc = OUT_OF_CORE (errno);
384                   else 
385                     {
386                       cl->cert = cert; cert = NULL;
387                       cl->next = *listaddr;
388                       cl->is_encrypt_to = is_encrypt_to;
389                       *listaddr = cl;
390                     }
391                 }
392             }
393         }
394     }
395   
396   keydb_release (kh);
397   ksba_cert_release (cert);
398   return rc == -1? gpg_error (GPG_ERR_NO_PUBKEY): rc;
399 }
400
401 void
402 gpgsm_release_certlist (CERTLIST list)
403 {
404   while (list)
405     {
406       CERTLIST cl = list->next;
407       ksba_cert_release (list->cert);
408       xfree (list);
409       list = cl;
410     }
411 }
412
413 \f
414 /* Like gpgsm_add_to_certlist, but look only for one certificate.  No
415    chain validation is done. If KEYID is not NULL it is take as an
416    additional filter value which must match the
417    subjectKeyIdentifier. */
418 int
419 gpgsm_find_cert (const char *name, ksba_sexp_t keyid, ksba_cert_t *r_cert)
420 {
421   int rc;
422   KEYDB_SEARCH_DESC desc;
423   KEYDB_HANDLE kh = NULL;
424
425   *r_cert = NULL;
426   rc = keydb_classify_name (name, &desc);
427   if (!rc)
428     {
429       kh = keydb_new (0);
430       if (!kh)
431         rc = gpg_error (GPG_ERR_ENOMEM);
432       else
433         {
434         nextone:
435           rc = keydb_search (kh, &desc, 1);
436           if (!rc)
437             {
438               rc = keydb_get_cert (kh, r_cert);
439               if (!rc && keyid)
440                 {
441                   ksba_sexp_t subj;
442                   
443                   rc = ksba_cert_get_subj_key_id (*r_cert, NULL, &subj);
444                   if (!rc)
445                     {
446                       if (cmp_simple_canon_sexp (keyid, subj))
447                         {
448                           xfree (subj);
449                           goto nextone;
450                         }
451                       xfree (subj);
452                       /* Okay: Here we know that the certificate's
453                          subjectKeyIdentifier matches the requested
454                          one. */
455                     }
456                   else if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
457                     goto nextone;
458                 }
459             }
460
461           /* If we don't have the KEYID filter we need to check for
462              ambigious search results.  Note, that it is somehwat
463              reasonable to assume that a specification of a KEYID
464              won't lead to ambiguous names. */
465           if (!rc && !keyid)
466             {
467               rc = keydb_search (kh, &desc, 1);
468               if (rc == -1)
469                 rc = 0;
470               else 
471                 {
472                   if (!rc)
473                     rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
474                   ksba_cert_release (*r_cert);
475                   *r_cert = NULL;
476                 }
477             }
478         }
479     }
480   
481   keydb_release (kh);
482   return rc == -1? gpg_error (GPG_ERR_NO_PUBKEY): rc;
483 }
484