coupling: Avoid potential access by multiple threads to shared hasher
Using the same `hasher_t` instance from different threads concurrently
is not safe. The underlying implementation might e.g. use a single
shared state for multiple API calls within `get_hash()` (e.g. the openssl
plugin does that).
Fixes: 007c47088c ("Implemented permanent certificate coupling plugin")
This commit is contained in:
@@ -48,9 +48,9 @@ struct private_coupling_validator_t {
|
|||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hasher to create hashes
|
* Hasher algorithm
|
||||||
*/
|
*/
|
||||||
hasher_t *hasher;
|
hash_algorithm_t alg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* maximum number of couplings
|
* maximum number of couplings
|
||||||
@@ -64,21 +64,30 @@ struct private_coupling_validator_t {
|
|||||||
static bool get_cert_hash(private_coupling_validator_t *this,
|
static bool get_cert_hash(private_coupling_validator_t *this,
|
||||||
certificate_t *cert, char *hex)
|
certificate_t *cert, char *hex)
|
||||||
{
|
{
|
||||||
|
hasher_t *hasher;
|
||||||
char buf[MAX_HASH_SIZE];
|
char buf[MAX_HASH_SIZE];
|
||||||
chunk_t encoding;
|
chunk_t encoding;
|
||||||
|
|
||||||
if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
|
hasher = lib->crypto->create_hasher(lib->crypto, this->alg);
|
||||||
|
if (!hasher)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!this->hasher->get_hash(this->hasher, encoding, buf))
|
if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
|
||||||
|
{
|
||||||
|
hasher->destroy(hasher);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!hasher->get_hash(hasher, encoding, buf))
|
||||||
{
|
{
|
||||||
free(encoding.ptr);
|
free(encoding.ptr);
|
||||||
|
hasher->destroy(hasher);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
free(encoding.ptr);
|
free(encoding.ptr);
|
||||||
chunk_to_hex(chunk_create(buf, this->hasher->get_hash_size(this->hasher)),
|
chunk_to_hex(chunk_create(buf, hasher->get_hash_size(hasher)),
|
||||||
hex, FALSE);
|
hex, FALSE);
|
||||||
|
hasher->destroy(hasher);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +200,6 @@ METHOD(coupling_validator_t, destroy, void,
|
|||||||
{
|
{
|
||||||
fclose(this->f);
|
fclose(this->f);
|
||||||
}
|
}
|
||||||
DESTROY_IF(this->hasher);
|
|
||||||
this->mutex->destroy(this->mutex);
|
this->mutex->destroy(this->mutex);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
@@ -203,6 +211,7 @@ coupling_validator_t *coupling_validator_create()
|
|||||||
{
|
{
|
||||||
private_coupling_validator_t *this;
|
private_coupling_validator_t *this;
|
||||||
hash_algorithm_t alg;
|
hash_algorithm_t alg;
|
||||||
|
hasher_t *hasher;
|
||||||
char *path, *hash;
|
char *path, *hash;
|
||||||
|
|
||||||
INIT(this,
|
INIT(this,
|
||||||
@@ -226,13 +235,15 @@ coupling_validator_t *coupling_validator_create()
|
|||||||
destroy(this);
|
destroy(this);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
this->hasher = lib->crypto->create_hasher(lib->crypto, alg);
|
hasher = lib->crypto->create_hasher(lib->crypto, alg);
|
||||||
if (!this->hasher)
|
if (!hasher)
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "unsupported coupling hash algorithm: %s", hash);
|
DBG1(DBG_CFG, "unsupported coupling hash algorithm: %s", hash);
|
||||||
destroy(this);
|
destroy(this);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
hasher->destroy(hasher);
|
||||||
|
this->alg = alg;
|
||||||
|
|
||||||
path = lib->settings->get_str(lib->settings,
|
path = lib->settings->get_str(lib->settings,
|
||||||
"%s.plugins.coupling.file", NULL, lib->ns);
|
"%s.plugins.coupling.file", NULL, lib->ns);
|
||||||
|
|||||||
Reference in New Issue
Block a user