Skip to content

Commit 1432e85

Browse files
committed
Rework the "by store" X509_LOOKUP method to open the given URI early
The cached X509_LOOKUP method data is no longer just the URI, but now includes the OSSL_STORE_CTX pointer, and required parameters to reopen the URI at any time. cache_objects() is modified to handle this, and only (re)open the URI when it wasn't previously opened, or when it was closed by an earlier call. This way, we can call OSSL_STORE_open_ex() in by_store_ctrl_ex(), and get to see possible errors when the URI is loaded. This assumes that if the URI could be opened once, it can be opened again. Fixes #27461 (cherry picked from commit 0c48ee2) Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from #27551) (cherry picked from commit 08220ef)
1 parent 037ac5c commit 1432e85

File tree

1 file changed

+84
-27
lines changed

1 file changed

+84
-27
lines changed

crypto/x509/by_store.c

Lines changed: 84 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,34 @@
77
* https://www.openssl.org/source/license.html
88
*/
99

10+
#include <openssl/safestack.h>
1011
#include <openssl/store.h>
1112
#include "internal/cryptlib.h"
1213
#include "crypto/x509.h"
1314
#include "x509_local.h"
1415

16+
typedef struct cached_store_st {
17+
char *uri;
18+
OSSL_LIB_CTX *libctx;
19+
char *propq;
20+
OSSL_STORE_CTX *ctx;
21+
} CACHED_STORE;
22+
23+
DEFINE_STACK_OF(CACHED_STORE)
24+
1525
/* Generic object loader, given expected type and criterion */
16-
static int cache_objects(X509_LOOKUP *lctx, const char *uri,
17-
const OSSL_STORE_SEARCH *criterion,
18-
int depth, OSSL_LIB_CTX *libctx, const char *propq)
26+
static int cache_objects(X509_LOOKUP *lctx, CACHED_STORE *store,
27+
const OSSL_STORE_SEARCH *criterion, int depth)
1928
{
2029
int ok = 0;
21-
OSSL_STORE_CTX *ctx = NULL;
30+
OSSL_STORE_CTX *ctx = store->ctx;
2231
X509_STORE *xstore = X509_LOOKUP_get_store(lctx);
2332

24-
if ((ctx = OSSL_STORE_open_ex(uri, libctx, propq, NULL, NULL, NULL,
25-
NULL, NULL)) == NULL)
33+
if (ctx == NULL
34+
&& (ctx = OSSL_STORE_open_ex(store->uri, store->libctx, store->propq,
35+
NULL, NULL, NULL, NULL, NULL)) == NULL)
2636
return 0;
37+
store->ctx = ctx;
2738

2839
/*
2940
* We try to set the criterion, but don't care if it was valid or not.
@@ -62,9 +73,15 @@ static int cache_objects(X509_LOOKUP *lctx, const char *uri,
6273
* This is an entry in the "directory" represented by the current
6374
* uri. if |depth| allows, dive into it.
6475
*/
65-
if (depth > 0)
66-
ok = cache_objects(lctx, OSSL_STORE_INFO_get0_NAME(info),
67-
criterion, depth - 1, libctx, propq);
76+
if (depth > 0) {
77+
CACHED_STORE substore;
78+
79+
substore.uri = (char *)OSSL_STORE_INFO_get0_NAME(info);
80+
substore.libctx = store->libctx;
81+
substore.propq = store->propq;
82+
substore.ctx = NULL;
83+
ok = cache_objects(lctx, &substore, criterion, depth - 1);
84+
}
6885
} else {
6986
/*
7087
* We know that X509_STORE_add_{cert|crl} increments the object's
@@ -88,27 +105,38 @@ static int cache_objects(X509_LOOKUP *lctx, const char *uri,
88105
break;
89106
}
90107
OSSL_STORE_close(ctx);
108+
store->ctx = NULL;
91109

92110
return ok;
93111
}
94112

95113

96-
/* Because OPENSSL_free is a macro and for C type match */
97-
static void free_uri(OPENSSL_STRING data)
114+
static void free_store(CACHED_STORE *store)
98115
{
99-
OPENSSL_free(data);
116+
if (store != NULL) {
117+
OSSL_STORE_close(store->ctx);
118+
OPENSSL_free(store->uri);
119+
OPENSSL_free(store->propq);
120+
OPENSSL_free(store);
121+
}
100122
}
101123

102124
static void by_store_free(X509_LOOKUP *ctx)
103125
{
104-
STACK_OF(OPENSSL_STRING) *uris = X509_LOOKUP_get_method_data(ctx);
105-
sk_OPENSSL_STRING_pop_free(uris, free_uri);
126+
STACK_OF(CACHED_STORE) *stores = X509_LOOKUP_get_method_data(ctx);
127+
sk_CACHED_STORE_pop_free(stores, free_store);
106128
}
107129

108130
static int by_store_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argp,
109131
long argl, char **retp, OSSL_LIB_CTX *libctx,
110132
const char *propq)
111133
{
134+
/*
135+
* In some cases below, failing to use the defaults shouldn't result in
136+
* an error. |use_default| is used as the return code in those cases.
137+
*/
138+
int use_default = argp == NULL;
139+
112140
switch (cmd) {
113141
case X509_L_ADD_STORE:
114142
/* If no URI is given, use the default cert dir as default URI */
@@ -119,21 +147,50 @@ static int by_store_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argp,
119147
argp = X509_get_default_cert_dir();
120148

121149
{
122-
STACK_OF(OPENSSL_STRING) *uris = X509_LOOKUP_get_method_data(ctx);
123-
char *data = OPENSSL_strdup(argp);
150+
STACK_OF(CACHED_STORE) *stores = X509_LOOKUP_get_method_data(ctx);
151+
CACHED_STORE *store = OPENSSL_zalloc(sizeof(*store));
124152

125-
if (data == NULL) {
153+
if (store == NULL) {
126154
return 0;
127155
}
128-
if (uris == NULL) {
129-
uris = sk_OPENSSL_STRING_new_null();
130-
X509_LOOKUP_set_method_data(ctx, uris);
156+
157+
store->uri = OPENSSL_strdup(argp);
158+
store->libctx = libctx;
159+
if (propq != NULL)
160+
store->propq = OPENSSL_strdup(propq);
161+
store->ctx = OSSL_STORE_open_ex(argp, libctx, propq, NULL, NULL,
162+
NULL, NULL, NULL);
163+
if (store->ctx == NULL
164+
|| (propq != NULL && store->propq == NULL)
165+
|| store->uri == NULL) {
166+
free_store(store);
167+
return use_default;
168+
}
169+
170+
if (stores == NULL) {
171+
stores = sk_CACHED_STORE_new_null();
172+
if (stores != NULL)
173+
X509_LOOKUP_set_method_data(ctx, stores);
174+
}
175+
if (stores == NULL || sk_CACHED_STORE_push(stores, store) <= 0) {
176+
free_store(store);
177+
return 0;
131178
}
132-
return sk_OPENSSL_STRING_push(uris, data) > 0;
179+
return 1;
133180
}
134-
case X509_L_LOAD_STORE:
181+
case X509_L_LOAD_STORE: {
135182
/* This is a shortcut for quick loading of specific containers */
136-
return cache_objects(ctx, argp, NULL, 0, libctx, propq);
183+
CACHED_STORE store;
184+
185+
store.uri = (char *)argp;
186+
store.libctx = libctx;
187+
store.propq = (char *)propq;
188+
store.ctx = NULL;
189+
return cache_objects(ctx, &store, NULL, 0);
190+
}
191+
default:
192+
/* Unsupported command */
193+
return 0;
137194
}
138195

139196
return 0;
@@ -149,13 +206,13 @@ static int by_store(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
149206
const OSSL_STORE_SEARCH *criterion, X509_OBJECT *ret,
150207
OSSL_LIB_CTX *libctx, const char *propq)
151208
{
152-
STACK_OF(OPENSSL_STRING) *uris = X509_LOOKUP_get_method_data(ctx);
209+
STACK_OF(CACHED_STORE) *stores = X509_LOOKUP_get_method_data(ctx);
153210
int i;
154211
int ok = 0;
155212

156-
for (i = 0; i < sk_OPENSSL_STRING_num(uris); i++) {
157-
ok = cache_objects(ctx, sk_OPENSSL_STRING_value(uris, i), criterion,
158-
1 /* depth */, libctx, propq);
213+
for (i = 0; i < sk_CACHED_STORE_num(stores); i++) {
214+
ok = cache_objects(ctx, sk_CACHED_STORE_value(stores, i), criterion,
215+
1 /* depth */);
159216

160217
if (ok)
161218
break;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy