summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2021-11-05 17:15:05 +0000
committertb <>2021-11-05 17:15:05 +0000
commitce3e1e635eb18f169ffcf8680f7f44ca582adf35 (patch)
tree4692ac58ae174ac3dd85c669147b251664e29b67
parent1bf191415816e13d5d45a0ef96bd514e64c912fb (diff)
downloadopenbsd-ce3e1e635eb18f169ffcf8680f7f44ca582adf35.tar.gz
openbsd-ce3e1e635eb18f169ffcf8680f7f44ca582adf35.tar.bz2
openbsd-ce3e1e635eb18f169ffcf8680f7f44ca582adf35.zip
Clean up X509_STORE_add_{cert,crl}().
Add a X509_STORE_add_object() function that adds an X509 object to the store and takes care of locking and cleaning up. This way we can set up an X509_OBJECT for both the cert and CRL case and hand over to the new function. There is one intentional change of behavior: if there is an attempt to add an object which is already present in the store, succeed instead of throwing an error. This makes sense and is also the OpenSSL behavior. As pointed out by jsing, this is a partial fix for the long standing GH issue #100 on libtls where connections would fail if the store contains duplicate certificates. Also: remove the internal X509_OBJECT_dec_ref_count(), which is no longer used. ok jsing
-rw-r--r--src/lib/libcrypto/x509/x509_lu.c110
1 files changed, 41 insertions, 69 deletions
diff --git a/src/lib/libcrypto/x509/x509_lu.c b/src/lib/libcrypto/x509/x509_lu.c
index 7bcd5f64de..a5ae33fac8 100644
--- a/src/lib/libcrypto/x509/x509_lu.c
+++ b/src/lib/libcrypto/x509/x509_lu.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_lu.c,v 1.45 2021/11/05 17:13:14 tb Exp $ */ 1/* $OpenBSD: x509_lu.c,v 1.46 2021/11/05 17:15:05 tb Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -65,8 +65,6 @@
65#include <openssl/x509v3.h> 65#include <openssl/x509v3.h>
66#include "x509_lcl.h" 66#include "x509_lcl.h"
67 67
68static void X509_OBJECT_dec_ref_count(X509_OBJECT *a);
69
70X509_LOOKUP * 68X509_LOOKUP *
71X509_LOOKUP_new(X509_LOOKUP_METHOD *method) 69X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
72{ 70{
@@ -351,103 +349,77 @@ X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type,
351 return 1; 349 return 1;
352} 350}
353 351
354int 352/* Add obj to the store. Takes ownership of obj. */
355X509_STORE_add_cert(X509_STORE *ctx, X509 *x) 353static int
354X509_STORE_add_object(X509_STORE *store, X509_OBJECT *obj)
356{ 355{
357 X509_OBJECT *obj; 356 int ret = 0;
358 int ret = 1;
359
360 if (x == NULL)
361 return 0;
362 obj = malloc(sizeof(X509_OBJECT));
363 if (obj == NULL) {
364 X509error(ERR_R_MALLOC_FAILURE);
365 return 0;
366 }
367 obj->type = X509_LU_X509;
368 obj->data.x509 = x;
369 357
370 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); 358 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
371 359
372 X509_OBJECT_up_ref_count(obj); 360 if (X509_OBJECT_retrieve_match(store->objs, obj) != NULL) {
361 /* Object is already present in the store. That's fine. */
362 ret = 1;
363 goto out;
364 }
373 365
374 if (X509_OBJECT_retrieve_match(ctx->objs, obj)) { 366 if (sk_X509_OBJECT_push(store->objs, obj) <= 0) {
375 X509error(X509_R_CERT_ALREADY_IN_HASH_TABLE); 367 X509error(ERR_R_MALLOC_FAILURE);
376 ret = 0; 368 goto out;
377 } else {
378 if (sk_X509_OBJECT_push(ctx->objs, obj) == 0) {
379 X509error(ERR_R_MALLOC_FAILURE);
380 ret = 0;
381 }
382 } 369 }
383 370
384 if (ret == 0) 371 obj = NULL;
385 X509_OBJECT_dec_ref_count(obj); 372 ret = 1;
386 373
374 out:
387 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); 375 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
388 376 X509_OBJECT_free(obj);
389 if (ret == 0) {
390 obj->data.x509 = NULL; /* owned by the caller */
391 X509_OBJECT_free(obj);
392 }
393 377
394 return ret; 378 return ret;
395} 379}
396 380
397int 381int
398X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) 382X509_STORE_add_cert(X509_STORE *store, X509 *x)
399{ 383{
400 X509_OBJECT *obj; 384 X509_OBJECT *obj;
401 int ret = 1;
402 385
403 if (x == NULL) 386 if (x == NULL)
404 return 0; 387 return 0;
405 obj = malloc(sizeof(X509_OBJECT)); 388
406 if (obj == NULL) { 389 if ((obj = X509_OBJECT_new()) == NULL)
407 X509error(ERR_R_MALLOC_FAILURE); 390 return 0;
391
392 if (!X509_up_ref(x)) {
393 X509_OBJECT_free(obj);
408 return 0; 394 return 0;
409 } 395 }
410 obj->type = X509_LU_CRL;
411 obj->data.crl = x;
412 396
413 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); 397 obj->type = X509_LU_X509;
398 obj->data.x509 = x;
414 399
415 X509_OBJECT_up_ref_count(obj); 400 return X509_STORE_add_object(store, obj);
401}
416 402
417 if (X509_OBJECT_retrieve_match(ctx->objs, obj)) { 403int
418 X509error(X509_R_CERT_ALREADY_IN_HASH_TABLE); 404X509_STORE_add_crl(X509_STORE *store, X509_CRL *x)
419 ret = 0; 405{
420 } else { 406 X509_OBJECT *obj;
421 if (sk_X509_OBJECT_push(ctx->objs, obj) == 0) {
422 X509error(ERR_R_MALLOC_FAILURE);
423 ret = 0;
424 }
425 }
426 407
427 if (ret == 0) 408 if (x == NULL)
428 X509_OBJECT_dec_ref_count(obj); 409 return 0;
429 410
430 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); 411 if ((obj = X509_OBJECT_new()) == NULL)
412 return 0;
431 413
432 if (ret == 0) { 414 if (!X509_CRL_up_ref(x)) {
433 obj->data.crl = NULL; /* owned by the caller */
434 X509_OBJECT_free(obj); 415 X509_OBJECT_free(obj);
416 return 0;
435 } 417 }
436 418
437 return ret; 419 obj->type = X509_LU_CRL;
438} 420 obj->data.crl = x;
439 421
440static void 422 return X509_STORE_add_object(store, obj);
441X509_OBJECT_dec_ref_count(X509_OBJECT *a)
442{
443 switch (a->type) {
444 case X509_LU_X509:
445 CRYPTO_add(&a->data.x509->references, -1, CRYPTO_LOCK_X509);
446 break;
447 case X509_LU_CRL:
448 CRYPTO_add(&a->data.crl->references, -1, CRYPTO_LOCK_X509_CRL);
449 break;
450 }
451} 423}
452 424
453int 425int