mirror of
https://github.com/QuasarApp/openssl.git
synced 2025-04-28 18:54:36 +00:00
Although the store being used is adequately and properly locked, the library context is not. Due to the mechanisms used for fetching, it is possible for multiple stores to live within the same library context for short periods. This fix prevents threading issues resulting from such coincidences. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/14773)
131 lines
3.7 KiB
C
131 lines
3.7 KiB
C
/*
|
|
* Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
|
|
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
|
*
|
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
* in the file LICENSE in the source distribution or at
|
|
* https://www.openssl.org/source/license.html
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <openssl/err.h>
|
|
#include <openssl/lhash.h>
|
|
#include "internal/propertyerr.h"
|
|
#include "internal/property.h"
|
|
#include "internal/core.h"
|
|
#include "property_local.h"
|
|
|
|
/*
|
|
* Implement a property definition cache.
|
|
* These functions assume that they are called under a write lock.
|
|
* No attempt is made to clean out the cache, except when it is shut down.
|
|
*/
|
|
|
|
typedef struct {
|
|
const char *prop;
|
|
OSSL_PROPERTY_LIST *defn;
|
|
char body[1];
|
|
} PROPERTY_DEFN_ELEM;
|
|
|
|
DEFINE_LHASH_OF(PROPERTY_DEFN_ELEM);
|
|
|
|
static unsigned long property_defn_hash(const PROPERTY_DEFN_ELEM *a)
|
|
{
|
|
return OPENSSL_LH_strhash(a->prop);
|
|
}
|
|
|
|
static int property_defn_cmp(const PROPERTY_DEFN_ELEM *a,
|
|
const PROPERTY_DEFN_ELEM *b)
|
|
{
|
|
return strcmp(a->prop, b->prop);
|
|
}
|
|
|
|
static void property_defn_free(PROPERTY_DEFN_ELEM *elem)
|
|
{
|
|
ossl_property_free(elem->defn);
|
|
OPENSSL_free(elem);
|
|
}
|
|
|
|
static void property_defns_free(void *vproperty_defns)
|
|
{
|
|
LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns = vproperty_defns;
|
|
|
|
if (property_defns != NULL) {
|
|
lh_PROPERTY_DEFN_ELEM_doall(property_defns,
|
|
&property_defn_free);
|
|
lh_PROPERTY_DEFN_ELEM_free(property_defns);
|
|
}
|
|
}
|
|
|
|
static void *property_defns_new(OSSL_LIB_CTX *ctx) {
|
|
return lh_PROPERTY_DEFN_ELEM_new(&property_defn_hash, &property_defn_cmp);
|
|
}
|
|
|
|
static const OSSL_LIB_CTX_METHOD property_defns_method = {
|
|
property_defns_new,
|
|
property_defns_free,
|
|
};
|
|
|
|
OSSL_PROPERTY_LIST *ossl_prop_defn_get(OSSL_LIB_CTX *ctx, const char *prop)
|
|
{
|
|
PROPERTY_DEFN_ELEM elem, *r;
|
|
LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns;
|
|
|
|
property_defns = ossl_lib_ctx_get_data(ctx,
|
|
OSSL_LIB_CTX_PROPERTY_DEFN_INDEX,
|
|
&property_defns_method);
|
|
if (property_defns == NULL || !ossl_lib_ctx_read_lock(ctx))
|
|
return NULL;
|
|
|
|
elem.prop = prop;
|
|
r = lh_PROPERTY_DEFN_ELEM_retrieve(property_defns, &elem);
|
|
ossl_lib_ctx_unlock(ctx);
|
|
return r != NULL ? r->defn : NULL;
|
|
}
|
|
|
|
int ossl_prop_defn_set(OSSL_LIB_CTX *ctx, const char *prop,
|
|
OSSL_PROPERTY_LIST *pl)
|
|
{
|
|
PROPERTY_DEFN_ELEM elem, *old, *p = NULL;
|
|
size_t len;
|
|
LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns;
|
|
int res = 1;
|
|
|
|
property_defns = ossl_lib_ctx_get_data(ctx,
|
|
OSSL_LIB_CTX_PROPERTY_DEFN_INDEX,
|
|
&property_defns_method);
|
|
if (property_defns == NULL)
|
|
return 0;
|
|
|
|
if (prop == NULL)
|
|
return 1;
|
|
|
|
if (!ossl_lib_ctx_write_lock(ctx))
|
|
return 0;
|
|
if (pl == NULL) {
|
|
elem.prop = prop;
|
|
lh_PROPERTY_DEFN_ELEM_delete(property_defns, &elem);
|
|
goto end;
|
|
}
|
|
len = strlen(prop);
|
|
p = OPENSSL_malloc(sizeof(*p) + len);
|
|
if (p != NULL) {
|
|
p->prop = p->body;
|
|
p->defn = pl;
|
|
memcpy(p->body, prop, len + 1);
|
|
old = lh_PROPERTY_DEFN_ELEM_insert(property_defns, p);
|
|
if (old != NULL) {
|
|
property_defn_free(old);
|
|
goto end;
|
|
}
|
|
if (!lh_PROPERTY_DEFN_ELEM_error(property_defns))
|
|
goto end;
|
|
}
|
|
OPENSSL_free(p);
|
|
res = 0;
|
|
end:
|
|
ossl_lib_ctx_unlock(ctx);
|
|
return res;
|
|
}
|