Skip to content
This repository was archived by the owner on Aug 24, 2025. It is now read-only.

Commit f96d3c1

Browse files
committed
Avoid errors when loading a cert multiple times.
Manual backport of openssl#2830 to 1.1.0 Reviewed-by: Rich Salz <rsalz@openssl.org> (Merged from openssl#6861)
1 parent e0a79ae commit f96d3c1

File tree

4 files changed

+118
-39
lines changed

4 files changed

+118
-39
lines changed

crypto/x509/x509_lu.c

Lines changed: 24 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
2+
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
33
*
44
* Licensed under the OpenSSL license (the "License"). You may not use
55
* this file except in compliance with the License. You can obtain a copy
@@ -310,73 +310,59 @@ int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type,
310310
return 1;
311311
}
312312

313-
int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
313+
static int x509_store_add(X509_STORE *ctx, void *x, int crl)
314314
{
315315
X509_OBJECT *obj;
316-
int ret = 1, added = 1;
316+
int ret = 0, added = 0;
317317

318318
if (x == NULL)
319319
return 0;
320320
obj = X509_OBJECT_new();
321321
if (obj == NULL)
322322
return 0;
323-
obj->type = X509_LU_X509;
324-
obj->data.x509 = x;
323+
324+
if (crl) {
325+
obj->type = X509_LU_CRL;
326+
obj->data.crl = (X509_CRL *)x;
327+
} else {
328+
obj->type = X509_LU_X509;
329+
obj->data.x509 = (X509 *)x;
330+
}
325331
X509_OBJECT_up_ref_count(obj);
326332

327333
CRYPTO_THREAD_write_lock(ctx->lock);
328334

329335
if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
330-
X509err(X509_F_X509_STORE_ADD_CERT,
331-
X509_R_CERT_ALREADY_IN_HASH_TABLE);
332-
ret = 0;
336+
ret = 1;
333337
} else {
334338
added = sk_X509_OBJECT_push(ctx->objs, obj);
335339
ret = added != 0;
336340
}
337341

338342
CRYPTO_THREAD_unlock(ctx->lock);
339343

340-
if (!ret) /* obj not pushed */
344+
if (added == 0) /* obj not pushed */
341345
X509_OBJECT_free(obj);
342-
if (!added) /* on push failure */
343-
X509err(X509_F_X509_STORE_ADD_CERT, ERR_R_MALLOC_FAILURE);
344346

345347
return ret;
346348
}
347349

348-
int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
350+
int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
349351
{
350-
X509_OBJECT *obj;
351-
int ret = 1, added = 1;
352-
353-
if (x == NULL)
354-
return 0;
355-
obj = X509_OBJECT_new();
356-
if (obj == NULL)
352+
if (!x509_store_add(ctx, x, 0)) {
353+
X509err(X509_F_X509_STORE_ADD_CERT, ERR_R_MALLOC_FAILURE);
357354
return 0;
358-
obj->type = X509_LU_CRL;
359-
obj->data.crl = x;
360-
X509_OBJECT_up_ref_count(obj);
361-
362-
CRYPTO_THREAD_write_lock(ctx->lock);
363-
364-
if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
365-
X509err(X509_F_X509_STORE_ADD_CRL, X509_R_CERT_ALREADY_IN_HASH_TABLE);
366-
ret = 0;
367-
} else {
368-
added = sk_X509_OBJECT_push(ctx->objs, obj);
369-
ret = added != 0;
370355
}
356+
return 1;
357+
}
371358

372-
CRYPTO_THREAD_unlock(ctx->lock);
373-
374-
if (!ret) /* obj not pushed */
375-
X509_OBJECT_free(obj);
376-
if (!added) /* on push failure */
359+
int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
360+
{
361+
if (!x509_store_add(ctx, x, 1)) {
377362
X509err(X509_F_X509_STORE_ADD_CRL, ERR_R_MALLOC_FAILURE);
378-
379-
return ret;
363+
return 0;
364+
}
365+
return 1;
380366
}
381367

382368
int X509_OBJECT_up_ref_count(X509_OBJECT *a)

test/build.info

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ IF[{- !$disabled{tests} -}]
1818
dtlsv1listentest ct_test threadstest afalgtest d2i_test \
1919
ssl_test_ctx_test ssl_test x509aux cipherlist_test asynciotest \
2020
bioprinttest sslapitest dtlstest sslcorrupttest bio_enc_test \
21-
ocspapitest fatalerrtest x509_time_test errtest
21+
ocspapitest fatalerrtest x509_time_test x509_dup_cert_test errtest
2222

2323
SOURCE[versions]=versions.c
2424
INCLUDE[versions]=../include
@@ -301,6 +301,10 @@ IF[{- !$disabled{tests} -}]
301301
INCLUDE[x509_time_test]=.. ../include
302302
DEPEND[x509_time_test]=../libcrypto
303303

304+
SOURCE[x509_dup_cert_test]=x509_dup_cert_test.c
305+
INCLUDE[x509_dup_cert_test]=../include
306+
DEPEND[x509_dup_cert_test]=../libcrypto
307+
304308
IF[{- !$disabled{shared} -}]
305309
PROGRAMS_NO_INST=shlibloadtest
306310
SOURCE[shlibloadtest]=shlibloadtest.c
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#! /usr/bin/env perl
2+
# Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
3+
#
4+
# Licensed under the OpenSSL license (the "License"). You may not use
5+
# this file except in compliance with the License. You can obtain a copy
6+
# in the file LICENSE in the source distribution or at
7+
# https://www.openssl.org/source/license.html
8+
#
9+
# ======================================================================
10+
# Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
11+
12+
13+
use OpenSSL::Test qw/:DEFAULT srctop_file/;
14+
15+
setup("test_x509_dup_cert");
16+
17+
plan tests => 1;
18+
19+
ok(run(test(["x509_dup_cert_test", srctop_file("test", "certs", "leaf.pem")])));

test/x509_dup_cert_test.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
3+
*
4+
* Licensed under the OpenSSL license (the "License"). You may not use
5+
* this file except in compliance with the License. You can obtain a copy
6+
* in the file LICENSE in the source distribution or at
7+
* https://www.openssl.org/source/license.html
8+
*/
9+
10+
/* ====================================================================
11+
* Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
12+
*/
13+
14+
#include <stdio.h>
15+
#include <openssl/err.h>
16+
#include <openssl/x509_vfy.h>
17+
18+
static int test_509_dup_cert(const char *cert_f)
19+
{
20+
int ret = 0;
21+
X509_STORE_CTX *sctx = NULL;
22+
X509_STORE *store = NULL;
23+
X509_LOOKUP *lookup = NULL;
24+
25+
store = X509_STORE_new();
26+
if (store == NULL)
27+
goto err;
28+
29+
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
30+
if (lookup == NULL)
31+
goto err;
32+
33+
if (!X509_load_cert_file(lookup, cert_f, X509_FILETYPE_PEM))
34+
goto err;
35+
if (!X509_load_cert_file(lookup, cert_f, X509_FILETYPE_PEM))
36+
goto err;
37+
38+
ret = 1;
39+
40+
err:
41+
X509_STORE_CTX_free(sctx);
42+
X509_STORE_free(store);
43+
if (ret != 1)
44+
ERR_print_errors_fp(stderr);
45+
return ret;
46+
}
47+
48+
int main(int argc, char **argv)
49+
{
50+
CRYPTO_set_mem_debug(1);
51+
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
52+
53+
if (argc != 2) {
54+
fprintf(stderr, "usage: x509_dup_cert_test cert.pem\n");
55+
return 1;
56+
}
57+
58+
if (!test_509_dup_cert(argv[1])) {
59+
fprintf(stderr, "Test X509 duplicate cert failed\n");
60+
return 1;
61+
}
62+
63+
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
64+
if (CRYPTO_mem_leaks_fp(stderr) <= 0)
65+
return 1;
66+
#endif
67+
68+
printf("PASS\n");
69+
return 0;
70+
}

0 commit comments

Comments
 (0)