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