Skip to content

Commit ba5eb62

Browse files
davidbenBoringssl LUCI CQ
authored andcommitted
Add X509_STORE_get1_objects
This will be needed for python/cpython#114573. Along the way, document the various functions that expose "query from X509_STORE". Most of them unfortunately leak the weird caching thing that hash_dir does, as well as OpenSSL's generally poor handling of issuers with the same name and CRL lookup, but I don't think it's really worth trying to unexport these APIs. Change-Id: I18137bdc4cbaa4bd20ff55116a18f350df386e4a Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/65787 Auto-Submit: David Benjamin <davidben@google.com> Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Bob Beck <bbe@google.com>
1 parent 38d17d3 commit ba5eb62

3 files changed

Lines changed: 119 additions & 39 deletions

File tree

crypto/x509/x509_lu.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -230,13 +230,11 @@ int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
230230
}
231231
}
232232

233-
// if (ret->data.ptr != NULL) X509_OBJECT_free_contents(ret);
234-
233+
// TODO(crbug.com/boringssl/685): This should call
234+
// |X509_OBJECT_free_contents|.
235235
ret->type = tmp->type;
236-
ret->data.ptr = tmp->data.ptr;
237-
236+
ret->data = tmp->data;
238237
X509_OBJECT_up_ref_count(ret);
239-
240238
return 1;
241239
}
242240

@@ -391,8 +389,27 @@ static X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
391389
return sk_X509_OBJECT_value(h, idx);
392390
}
393391

394-
STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *st) {
395-
return st->objs;
392+
static X509_OBJECT *x509_object_dup(const X509_OBJECT *obj) {
393+
X509_OBJECT *ret = X509_OBJECT_new();
394+
if (ret == NULL) {
395+
return NULL;
396+
}
397+
ret->type = obj->type;
398+
ret->data = obj->data;
399+
X509_OBJECT_up_ref_count(ret);
400+
return ret;
401+
}
402+
403+
STACK_OF(X509_OBJECT) *X509_STORE_get1_objects(X509_STORE *store) {
404+
CRYPTO_MUTEX_lock_read(&store->objs_lock);
405+
STACK_OF(X509_OBJECT) *ret =
406+
sk_X509_OBJECT_deep_copy(store->objs, x509_object_dup, X509_OBJECT_free);
407+
CRYPTO_MUTEX_unlock_read(&store->objs_lock);
408+
return ret;
409+
}
410+
411+
STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *store) {
412+
return store->objs;
396413
}
397414

398415
STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm) {

crypto/x509/x509_test.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,11 @@ TEST(X509Test, StoreThreads) {
13821382
threads.emplace_back([&] {
13831383
ASSERT_TRUE(X509_STORE_add_cert(store.get(), other2.get()));
13841384
});
1385+
threads.emplace_back([&] {
1386+
bssl::UniquePtr<STACK_OF(X509_OBJECT)> objs(
1387+
X509_STORE_get1_objects(store.get()));
1388+
ASSERT_TRUE(objs);
1389+
});
13851390
}
13861391
for (auto &thread : threads) {
13871392
thread.join();

include/openssl/x509.h

Lines changed: 90 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2215,6 +2215,9 @@ OPENSSL_EXPORT ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr,
22152215
// functions which take a non-const pointer may not. Callers that wish to modify
22162216
// verification parameters in a shared |X509_STORE| should instead modify
22172217
// |X509_STORE_CTX|s individually.
2218+
//
2219+
// Objects in an |X509_STORE| are represented as an |X509_OBJECT|. Some
2220+
// functions in this library return values with this type.
22182221

22192222
// X509_STORE_new returns a newly-allocated |X509_STORE|, or NULL on error.
22202223
OPENSSL_EXPORT X509_STORE *X509_STORE_new(void);
@@ -2303,6 +2306,41 @@ OPENSSL_EXPORT int X509_STORE_set_purpose(X509_STORE *store, int purpose);
23032306
// |X509_VERIFY_PARAM_set_trust| for details.
23042307
OPENSSL_EXPORT int X509_STORE_set_trust(X509_STORE *store, int trust);
23052308

2309+
// The following constants indicate the type of an |X509_OBJECT|.
2310+
#define X509_LU_NONE 0
2311+
#define X509_LU_X509 1
2312+
#define X509_LU_CRL 2
2313+
#define X509_LU_PKEY 3
2314+
2315+
DEFINE_STACK_OF(X509_OBJECT)
2316+
2317+
// X509_OBJECT_new returns a newly-allocated, empty |X509_OBJECT| or NULL on
2318+
// error.
2319+
OPENSSL_EXPORT X509_OBJECT *X509_OBJECT_new(void);
2320+
2321+
// X509_OBJECT_free releases memory associated with |obj|.
2322+
OPENSSL_EXPORT void X509_OBJECT_free(X509_OBJECT *obj);
2323+
2324+
// X509_OBJECT_get_type returns the type of |obj|, which will be one of the
2325+
// |X509_LU_*| constants.
2326+
OPENSSL_EXPORT int X509_OBJECT_get_type(const X509_OBJECT *obj);
2327+
2328+
// X509_OBJECT_get0_X509 returns |obj| as a certificate, or NULL if |obj| is not
2329+
// a certificate.
2330+
OPENSSL_EXPORT X509 *X509_OBJECT_get0_X509(const X509_OBJECT *obj);
2331+
2332+
// X509_STORE_get1_objects returns a newly-allocated stack containing the
2333+
// contents of |store|, or NULL on error. The caller must release the result
2334+
// with |sk_X509_OBJECT_pop_free| and |X509_OBJECT_free| when done.
2335+
//
2336+
// The result will include all certificates and CRLs added via
2337+
// |X509_STORE_add_cert| and |X509_STORE_add_crl|, as well as any cached objects
2338+
// added by |X509_LOOKUP_hash_dir|. The last of these may change over time, as
2339+
// different objects are loaded from the filesystem. Callers should not depend
2340+
// on this caching behavior. The objects are returned in no particular order.
2341+
OPENSSL_EXPORT STACK_OF(X509_OBJECT) *X509_STORE_get1_objects(
2342+
X509_STORE *store);
2343+
23062344

23072345
// Certificate verification.
23082346
//
@@ -3787,6 +3825,43 @@ OPENSSL_EXPORT int X509_check_purpose(X509 *x509, int purpose, int ca);
37873825
// |flags| should be zero and is ignored.
37883826
OPENSSL_EXPORT int X509_check_trust(X509 *x509, int id, int flags);
37893827

3828+
// X509_STORE_CTX_get1_certs returns a newly-allocated stack containing all
3829+
// trusted certificates in |ctx|'s |X509_STORE| whose subject matches |name|, or
3830+
// NULL on error. The caller must release the result with |sk_X509_pop_free| and
3831+
// |X509_free| when done.
3832+
//
3833+
// TODO(crbug.com/boringssl/407): |name| should be const.
3834+
OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx,
3835+
X509_NAME *name);
3836+
3837+
// X509_STORE_CTX_get1_crls returns a newly-allocated stack containing all
3838+
// CRLs in |ctx|'s |X509_STORE| whose subject matches |name|, or NULL on error.
3839+
// The caller must release the result with |sk_X509_CRL_pop_free| and
3840+
// |X509_CRL_free| when done.
3841+
//
3842+
// TODO(crbug.com/boringssl/407): |name| should be const.
3843+
OPENSSL_EXPORT STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *ctx,
3844+
X509_NAME *name);
3845+
3846+
// X509_STORE_CTX_get_by_subject looks up an object of type |type| in |ctx|'s
3847+
// |X509_STORE| that matches |name|. |type| should be one of the |X509_LU_*|
3848+
// constants to indicate the type of object. If a match was found, it stores the
3849+
// result in |ret| and returns one. Otherwise, it returns zero. If multiple
3850+
// objects match, this function outputs an arbitray one.
3851+
//
3852+
// WARNING: |ret| must be in the empty state, as returned by |X509_OBJECT_new|.
3853+
// Otherwise, the object currently in |ret| will be leaked when overwritten.
3854+
// https://crbug.com/boringssl/685 tracks fixing this.
3855+
//
3856+
// WARNING: Multiple trusted certificates or CRLs may share a name. In this
3857+
// case, this function returns an arbitrary match. Use
3858+
// |X509_STORE_CTX_get1_certs| or |X509_STORE_CTX_get1_crls| instead.
3859+
//
3860+
// TODO(crbug.com/boringssl/407): |name| should be const.
3861+
OPENSSL_EXPORT int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *ctx, int type,
3862+
X509_NAME *name,
3863+
X509_OBJECT *ret);
3864+
37903865

37913866
// X.509 information.
37923867
//
@@ -4224,6 +4299,20 @@ OPENSSL_EXPORT void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx,
42244299
// always enabled.
42254300
#define X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS 0
42264301

4302+
// X509_STORE_get0_objects returns a non-owning pointer of |store|'s internal
4303+
// object list. Although this function is not const, callers must not modify
4304+
// the result of this function.
4305+
//
4306+
// WARNING: This function is not thread-safe. If |store| is shared across
4307+
// multiple threads, callers cannot safely inspect the result of this function,
4308+
// because another thread may have concurrently added to it. In particular,
4309+
// |X509_LOOKUP_hash_dir| treats this list as a cache and may add to it in the
4310+
// course of certificate verification. This API additionally prevents fixing
4311+
// some quadratic worst-case behavior in |X509_STORE| and may be removed in the
4312+
// future. Use |X509_STORE_get1_objects| instead.
4313+
OPENSSL_EXPORT STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(
4314+
X509_STORE *store);
4315+
42274316

42284317
// Private structures.
42294318

@@ -4324,13 +4413,6 @@ The X509_STORE then calls a function to actually verify the
43244413
certificate chain.
43254414
*/
43264415

4327-
#define X509_LU_NONE 0
4328-
#define X509_LU_X509 1
4329-
#define X509_LU_CRL 2
4330-
#define X509_LU_PKEY 3
4331-
4332-
DEFINE_STACK_OF(X509_OBJECT)
4333-
43344416
#define X509_STORE_CTX_set_app_data(ctx, data) \
43354417
X509_STORE_CTX_set_ex_data(ctx, 0, data)
43364418
#define X509_STORE_CTX_get_app_data(ctx) X509_STORE_CTX_get_ex_data(ctx, 0)
@@ -4407,37 +4489,12 @@ OPENSSL_EXPORT int X509_LOOKUP_add_dir(X509_LOOKUP *lookup, const char *path,
44074489
// verification.
44084490
#define X509_V_FLAG_NO_CHECK_TIME 0x200000
44094491

4410-
// X509_OBJECT_new returns a newly-allocated, empty |X509_OBJECT| or NULL on
4411-
// error.
4412-
OPENSSL_EXPORT X509_OBJECT *X509_OBJECT_new(void);
4413-
4414-
// X509_OBJECT_free releases memory associated with |obj|.
4415-
OPENSSL_EXPORT void X509_OBJECT_free(X509_OBJECT *obj);
4416-
4417-
// X509_OBJECT_get_type returns the type of |obj|, which will be one of the
4418-
// |X509_LU_*| constants.
4419-
OPENSSL_EXPORT int X509_OBJECT_get_type(const X509_OBJECT *obj);
4420-
4421-
// X509_OBJECT_get0_X509 returns |obj| as a certificate, or NULL if |obj| is not
4422-
// a certificate.
4423-
OPENSSL_EXPORT X509 *X509_OBJECT_get0_X509(const X509_OBJECT *obj);
4424-
4425-
OPENSSL_EXPORT STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *st);
4426-
OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *st,
4427-
X509_NAME *nm);
4428-
OPENSSL_EXPORT STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *st,
4429-
X509_NAME *nm);
4430-
44314492
OPENSSL_EXPORT X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v,
44324493
const X509_LOOKUP_METHOD *m);
44334494

44344495
OPENSSL_EXPORT const X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void);
44354496
OPENSSL_EXPORT const X509_LOOKUP_METHOD *X509_LOOKUP_file(void);
44364497

4437-
OPENSSL_EXPORT int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, int type,
4438-
X509_NAME *name,
4439-
X509_OBJECT *ret);
4440-
44414498
OPENSSL_EXPORT int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
44424499
long argl, char **ret);
44434500

@@ -4885,6 +4942,7 @@ BORINGSSL_MAKE_DELETER(X509_INFO, X509_INFO_free)
48854942
BORINGSSL_MAKE_DELETER(X509_LOOKUP, X509_LOOKUP_free)
48864943
BORINGSSL_MAKE_DELETER(X509_NAME, X509_NAME_free)
48874944
BORINGSSL_MAKE_DELETER(X509_NAME_ENTRY, X509_NAME_ENTRY_free)
4945+
BORINGSSL_MAKE_DELETER(X509_OBJECT, X509_OBJECT_free)
48884946
BORINGSSL_MAKE_DELETER(X509_PUBKEY, X509_PUBKEY_free)
48894947
BORINGSSL_MAKE_DELETER(X509_REQ, X509_REQ_free)
48904948
BORINGSSL_MAKE_DELETER(X509_REVOKED, X509_REVOKED_free)

0 commit comments

Comments
 (0)