2002-04-24 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / sm / certlist.c
blob2d52ada3089f02545e27ede923c8c2b0fd42b2af
1 /* certlist.c - build list of certificates
2 * Copyright (C) 2001 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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
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>
30 #include <gcrypt.h>
31 #include <ksba.h>
33 #include "gpgsm.h"
34 #include "keydb.h"
35 #include "i18n.h"
37 /* Return 0 if the cert is usable for encryption. A MODE of 0 checks
38 for signing a MODE of 1 checks for encryption, a MODE of 2 checks
39 for verification and a MODE of 3 for decryption (just for
40 debugging) */
41 static int
42 cert_usage_p (KsbaCert cert, int mode)
44 KsbaError err;
45 unsigned int use;
47 err = ksba_cert_get_key_usage (cert, &use);
48 if (err == KSBA_No_Data)
50 if (opt.verbose && mode < 2)
51 log_info (mode?
52 _("no key usage specified - accepted for encryption\n"):
53 _("no key usage specified - accepted for signing\n"));
54 return 0;
56 if (err)
58 log_error (_("error getting key usage information: %s\n"),
59 ksba_strerror (err));
60 return map_ksba_err (err);
63 if ((use & ((mode&1)? KSBA_KEYUSAGE_DIGITAL_SIGNATURE
64 : KSBA_KEYUSAGE_KEY_ENCIPHERMENT)))
65 return 0;
66 log_info (mode==3? _("certificate should have not been used for encryption\n"):
67 mode==2? _("certificate should have not been used for signing\n"):
68 mode==1? _("certificate is not usable for encryption\n"):
69 _("certificate is not usable for signing\n"));
70 return GNUPG_Wrong_Key_Usage;
74 /* Return 0 if the cert is usable for signing */
75 int
76 gpgsm_cert_use_sign_p (KsbaCert cert)
78 return cert_usage_p (cert, 0);
82 /* Return 0 if the cert is usable for encryption */
83 int
84 gpgsm_cert_use_encrypt_p (KsbaCert cert)
86 return cert_usage_p (cert, 1);
89 int
90 gpgsm_cert_use_verify_p (KsbaCert cert)
92 return cert_usage_p (cert, 2);
95 int
96 gpgsm_cert_use_decrypt_p (KsbaCert cert)
98 return cert_usage_p (cert, 3);
101 /* add a certificate to a list of certificate and make sure that it is
102 a valid certificate */
104 gpgsm_add_to_certlist (const char *name, CERTLIST *listaddr)
106 int rc;
107 KEYDB_SEARCH_DESC desc;
108 KEYDB_HANDLE kh = NULL;
109 KsbaCert cert = NULL;
111 rc = keydb_classify_name (name, &desc);
112 if (!rc)
114 kh = keydb_new (0);
115 if (!kh)
116 rc = GNUPG_Out_Of_Core;
117 else
119 int wrong_usage = 0;
120 get_next:
121 rc = keydb_search (kh, &desc, 1);
122 if (!rc)
123 rc = keydb_get_cert (kh, &cert);
124 if (!rc)
126 rc = gpgsm_cert_use_encrypt_p (cert);
127 if (rc == GNUPG_Wrong_Key_Usage)
129 /* There might be another certificate with the
130 correct usage, so we better try again */
131 wrong_usage = rc;
132 ksba_cert_release (cert);
133 cert = NULL;
134 goto get_next;
137 /* we want the error code from the first match in this case */
138 if (wrong_usage)
139 rc = wrong_usage;
141 if (!rc)
143 /* Fixme: If we ever have two certifciates differing
144 only in the key usage, we should only bail out here
145 if the certificate differes just in the key usage.
146 However we need to find some criteria to match the
147 identities */
148 rc = keydb_search (kh, &desc, 1);
149 if (rc == -1)
150 rc = 0;
151 else if (!rc)
152 rc = GNUPG_Ambiguous_Name;
154 if (!rc)
155 rc = gpgsm_validate_path (cert);
156 if (!rc)
158 CERTLIST cl = xtrycalloc (1, sizeof *cl);
159 if (!cl)
160 rc = GNUPG_Out_Of_Core;
161 else
163 cl->cert = cert; cert = NULL;
164 cl->next = *listaddr;
165 *listaddr = cl;
171 keydb_release (kh);
172 ksba_cert_release (cert);
173 return rc == -1? GNUPG_No_Public_Key: rc;
176 void
177 gpgsm_release_certlist (CERTLIST list)
179 while (list)
181 CERTLIST cl = list->next;
182 ksba_cert_release (list->cert);
183 xfree (list);
184 list = cl;
189 /* Like gpgsm_add_to_certlist, but look only for one certificate. No
190 path validation is done */
192 gpgsm_find_cert (const char *name, KsbaCert *r_cert)
194 int rc;
195 KEYDB_SEARCH_DESC desc;
196 KEYDB_HANDLE kh = NULL;
198 *r_cert = NULL;
199 rc = keydb_classify_name (name, &desc);
200 if (!rc)
202 kh = keydb_new (0);
203 if (!kh)
204 rc = GNUPG_Out_Of_Core;
205 else
207 rc = keydb_search (kh, &desc, 1);
208 if (!rc)
209 rc = keydb_get_cert (kh, r_cert);
210 if (!rc)
212 rc = keydb_search (kh, &desc, 1);
213 if (rc == -1)
214 rc = 0;
215 else
217 if (!rc)
218 rc = GNUPG_Ambiguous_Name;
219 ksba_cert_release (*r_cert);
220 *r_cert = NULL;
226 keydb_release (kh);
227 return rc == -1? GNUPG_No_Public_Key: rc;