summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2024-01-06 17:17:08 +0000
committertb <>2024-01-06 17:17:08 +0000
commitca00b1e55ab503cc77058c62611b0b6ec94882f2 (patch)
tree542d1e5cc853bc1b3fbe0eb77ff56e21067b795b
parentc75f680fbdc8f13b45b60c1e3502617bea21071d (diff)
downloadopenbsd-ca00b1e55ab503cc77058c62611b0b6ec94882f2.tar.gz
openbsd-ca00b1e55ab503cc77058c62611b0b6ec94882f2.tar.bz2
openbsd-ca00b1e55ab503cc77058c62611b0b6ec94882f2.zip
Remove X509_PURPOSE extensibility
Another bit of global state without lock protection. The by now familiar complications of a stack to make this user configurable, which, of course, no one ever did. The table is not currently const, and the API exposes its entries directly, so anyone can modify it. This fits very well with the safety guarantees of Rust's 'static lifetime, which is how rust-openssl exposes it (for no good reason). Remove the stack and make the X509_PURPOSE_add() API always fail. Simplify the other bits accordingly. In addition, this API inflicts the charming difference between purpose identifiers and purpose indexes (the former minus one) onto the user. Neither of the two obvious solutions to avoid this trap seems to have crossed the implementer's mind. ok jsing
-rw-r--r--src/lib/libcrypto/x509/x509_purp.c122
1 files changed, 10 insertions, 112 deletions
diff --git a/src/lib/libcrypto/x509/x509_purp.c b/src/lib/libcrypto/x509/x509_purp.c
index de6e03df2b..dbae7bcb7c 100644
--- a/src/lib/libcrypto/x509/x509_purp.c
+++ b/src/lib/libcrypto/x509/x509_purp.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_purp.c,v 1.33 2023/12/31 07:19:13 tb Exp $ */ 1/* $OpenBSD: x509_purp.c,v 1.34 2024/01/06 17:17:08 tb Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2001. 3 * project 2001.
4 */ 4 */
@@ -95,9 +95,6 @@ static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
95static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca); 95static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca);
96static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca); 96static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca);
97 97
98static int xp_cmp(const X509_PURPOSE * const *a, const X509_PURPOSE * const *b);
99static void xptable_free(X509_PURPOSE *p);
100
101static X509_PURPOSE xstandard[] = { 98static X509_PURPOSE xstandard[] = {
102 { 99 {
103 .purpose = X509_PURPOSE_SSL_CLIENT, 100 .purpose = X509_PURPOSE_SSL_CLIENT,
@@ -166,14 +163,6 @@ static X509_PURPOSE xstandard[] = {
166 163
167#define X509_PURPOSE_COUNT (sizeof(xstandard) / sizeof(xstandard[0])) 164#define X509_PURPOSE_COUNT (sizeof(xstandard) / sizeof(xstandard[0]))
168 165
169static STACK_OF(X509_PURPOSE) *xptable = NULL;
170
171static int
172xp_cmp(const X509_PURPOSE * const *a, const X509_PURPOSE * const *b)
173{
174 return (*a)->purpose - (*b)->purpose;
175}
176
177/* As much as I'd like to make X509_check_purpose use a "const" X509* 166/* As much as I'd like to make X509_check_purpose use a "const" X509*
178 * I really can't because it does recalculate hashes and do other non-const 167 * I really can't because it does recalculate hashes and do other non-const
179 * things. */ 168 * things. */
@@ -211,20 +200,17 @@ LCRYPTO_ALIAS(X509_PURPOSE_set);
211int 200int
212X509_PURPOSE_get_count(void) 201X509_PURPOSE_get_count(void)
213{ 202{
214 if (!xptable) 203 return X509_PURPOSE_COUNT;
215 return X509_PURPOSE_COUNT;
216 return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT;
217} 204}
218LCRYPTO_ALIAS(X509_PURPOSE_get_count); 205LCRYPTO_ALIAS(X509_PURPOSE_get_count);
219 206
220X509_PURPOSE * 207X509_PURPOSE *
221X509_PURPOSE_get0(int idx) 208X509_PURPOSE_get0(int idx)
222{ 209{
223 if (idx < 0) 210 if (idx < 0 || (size_t)idx >= X509_PURPOSE_COUNT)
224 return NULL; 211 return NULL;
225 if (idx < (int)X509_PURPOSE_COUNT) 212
226 return xstandard + idx; 213 return &xstandard[idx];
227 return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT);
228} 214}
229LCRYPTO_ALIAS(X509_PURPOSE_get0); 215LCRYPTO_ALIAS(X509_PURPOSE_get0);
230 216
@@ -246,18 +232,11 @@ LCRYPTO_ALIAS(X509_PURPOSE_get_by_sname);
246int 232int
247X509_PURPOSE_get_by_id(int purpose) 233X509_PURPOSE_get_by_id(int purpose)
248{ 234{
249 X509_PURPOSE tmp; 235 /* X509_PURPOSE_MIN == 1, so the bounds are correct. */
250 int idx; 236 if (purpose < X509_PURPOSE_MIN || purpose > X509_PURPOSE_MAX)
251
252 if ((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX))
253 return purpose - X509_PURPOSE_MIN;
254 tmp.purpose = purpose;
255 if (!xptable)
256 return -1;
257 idx = sk_X509_PURPOSE_find(xptable, &tmp);
258 if (idx == -1)
259 return -1; 237 return -1;
260 return idx + X509_PURPOSE_COUNT; 238
239 return purpose - X509_PURPOSE_MIN;
261} 240}
262LCRYPTO_ALIAS(X509_PURPOSE_get_by_id); 241LCRYPTO_ALIAS(X509_PURPOSE_get_by_id);
263 242
@@ -266,95 +245,14 @@ X509_PURPOSE_add(int id, int trust, int flags,
266 int (*ck)(const X509_PURPOSE *, const X509 *, int), const char *name, 245 int (*ck)(const X509_PURPOSE *, const X509 *, int), const char *name,
267 const char *sname, void *arg) 246 const char *sname, void *arg)
268{ 247{
269 int idx; 248 X509error(ERR_R_DISABLED);
270 X509_PURPOSE *ptmp;
271 char *name_dup, *sname_dup;
272
273 name_dup = sname_dup = NULL;
274
275 if (name == NULL || sname == NULL) {
276 X509V3error(X509V3_R_INVALID_NULL_ARGUMENT);
277 return 0;
278 }
279
280 /* This is set according to what we change: application can't set it */
281 flags &= ~X509_PURPOSE_DYNAMIC;
282 /* This will always be set for application modified trust entries */
283 flags |= X509_PURPOSE_DYNAMIC_NAME;
284 /* Get existing entry if any */
285 idx = X509_PURPOSE_get_by_id(id);
286 /* Need a new entry */
287 if (idx == -1) {
288 if ((ptmp = malloc(sizeof(X509_PURPOSE))) == NULL) {
289 X509V3error(ERR_R_MALLOC_FAILURE);
290 return 0;
291 }
292 ptmp->flags = X509_PURPOSE_DYNAMIC;
293 } else
294 ptmp = X509_PURPOSE_get0(idx);
295
296 if ((name_dup = strdup(name)) == NULL)
297 goto err;
298 if ((sname_dup = strdup(sname)) == NULL)
299 goto err;
300
301 /* free existing name if dynamic */
302 if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) {
303 free(ptmp->name);
304 free(ptmp->sname);
305 }
306 /* dup supplied name */
307 ptmp->name = name_dup;
308 ptmp->sname = sname_dup;
309 /* Keep the dynamic flag of existing entry */
310 ptmp->flags &= X509_PURPOSE_DYNAMIC;
311 /* Set all other flags */
312 ptmp->flags |= flags;
313
314 ptmp->purpose = id;
315 ptmp->trust = trust;
316 ptmp->check_purpose = ck;
317 ptmp->usr_data = arg;
318
319 /* If its a new entry manage the dynamic table */
320 if (idx == -1) {
321 if (xptable == NULL &&
322 (xptable = sk_X509_PURPOSE_new(xp_cmp)) == NULL)
323 goto err;
324 if (sk_X509_PURPOSE_push(xptable, ptmp) == 0)
325 goto err;
326 }
327 return 1;
328
329err:
330 free(name_dup);
331 free(sname_dup);
332 if (idx == -1)
333 free(ptmp);
334 X509V3error(ERR_R_MALLOC_FAILURE);
335 return 0; 249 return 0;
336} 250}
337LCRYPTO_ALIAS(X509_PURPOSE_add); 251LCRYPTO_ALIAS(X509_PURPOSE_add);
338 252
339static void
340xptable_free(X509_PURPOSE *p)
341{
342 if (!p)
343 return;
344 if (p->flags & X509_PURPOSE_DYNAMIC) {
345 if (p->flags & X509_PURPOSE_DYNAMIC_NAME) {
346 free(p->name);
347 free(p->sname);
348 }
349 free(p);
350 }
351}
352
353void 253void
354X509_PURPOSE_cleanup(void) 254X509_PURPOSE_cleanup(void)
355{ 255{
356 sk_X509_PURPOSE_pop_free(xptable, xptable_free);
357 xptable = NULL;
358} 256}
359LCRYPTO_ALIAS(X509_PURPOSE_cleanup); 257LCRYPTO_ALIAS(X509_PURPOSE_cleanup);
360 258