Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions raddb/mods-available/eap
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,16 @@ eap {
#
certificate_file = ${certdir}/rsa/server.pem

#
# certificate_uri:: URI which contains the certificate presented
# as the "server certificate" to the client.
#
# At least one of `certificate_file` and `certificate_uri`
# should be specified. If both are specified, then
# `certificate_file` will be used.
#
# certificate_uri = "pkcs11:"

#
# ca_file:: File which contains the root CA.
#
Expand Down Expand Up @@ -379,6 +389,19 @@ eap {
#
private_key_file = ${certdir}/rsa/server.key

#
# private_key_file:: URI which contains the private key.
#
# If the Private key & Certificate should be loaded with the same URI,
# then `private_key_uri` & `certificate_uri` should contain the
# same URI.
#
# At least one of `private_key_file` and `certificate_uri`
# should be specified. If both are specified, then
# `certificate_file` will be used.
#
# private_key_uri = "pkcs11:"

#
# verify_mode:: How we verify the certificate chain.
#
Expand Down
6 changes: 4 additions & 2 deletions src/lib/tls/conf-h
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,11 @@ typedef struct {
///< from a single file.

char const *certificate_file; //!< Path to certificate.
char const *certificate_uri; //!< URI to certificate.

char const *password; //!< Password to decrypt the certificate(s).
char const *private_key_file; //!< Path to certificate.
char const *password; //!< Password to decrypt the private key.
char const *private_key_file; //!< Path to private key.
char const *private_key_uri; //!< URI to private key.

char const **ca_files; //!< Extra certificates to load.
fr_tls_chain_verify_mode_t verify_mode; //!< How hard we try to build up a complete certificate
Expand Down
6 changes: 4 additions & 2 deletions src/lib/tls/conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,11 @@ static conf_parser_t tls_chain_config[] = {
.len = &certificate_format_table_len
},
.dflt = "pem" },
{ FR_CONF_OFFSET_FLAGS("certificate_file", CONF_FLAG_FILE_READABLE | CONF_FLAG_FILE_EXISTS | CONF_FLAG_REQUIRED, fr_tls_chain_conf_t, certificate_file) },
{ FR_CONF_OFFSET_FLAGS("certificate_file", CONF_FLAG_FILE_READABLE | CONF_FLAG_FILE_EXISTS, fr_tls_chain_conf_t, certificate_file) },
{ FR_CONF_OFFSET("certificate_uri", fr_tls_chain_conf_t, certificate_uri) },
{ FR_CONF_OFFSET_FLAGS("private_key_password", CONF_FLAG_SECRET, fr_tls_chain_conf_t, password) },
{ FR_CONF_OFFSET_FLAGS("private_key_file", CONF_FLAG_FILE_READABLE | CONF_FLAG_FILE_EXISTS | CONF_FLAG_REQUIRED, fr_tls_chain_conf_t, private_key_file) },
{ FR_CONF_OFFSET_FLAGS("private_key_file", CONF_FLAG_FILE_READABLE | CONF_FLAG_FILE_EXISTS, fr_tls_chain_conf_t, private_key_file) },
{ FR_CONF_OFFSET("private_key_uri", fr_tls_chain_conf_t, private_key_uri) },

{ FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_READABLE | CONF_FLAG_MULTI, fr_tls_chain_conf_t, ca_files) },

Expand Down
103 changes: 78 additions & 25 deletions src/lib/tls/ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
#include <openssl/dh.h>
#include <openssl/x509v3.h>
#include <openssl/provider.h>
#include <openssl/store.h>

#ifndef OPENSSL_NO_ECDH
static int ctx_ecdh_curve_set(SSL_CTX *ctx, char const *ecdh_curve, bool disable_single_dh_use)
Expand Down Expand Up @@ -234,14 +235,17 @@ static int tls_ctx_verify_chain_member(fr_unix_time_t *expires_first, X509 **sel
return 0;
}

static OSSL_STORE_INFO *tls_ctx_load_cert_chain_store_post_process(OSSL_STORE_INFO *info, void *type) {
return (int)type == OSSL_STORE_INFO_get_type(info) ? info : NULL;
}

static int tls_ctx_load_cert_chain(SSL_CTX *ctx, fr_tls_chain_conf_t *chain, bool allow_multi_self_signed)
{
char *password;

/*
* Conf parser should ensure they're both populated
*/
fr_assert(chain->certificate_file && chain->private_key_file);
X509 *certificate;
EVP_PKEY *private_key;
OSSL_STORE_CTX *store_ctx;
OSSL_STORE_INFO *store_info;

/*
* Set the password (this should have been retrieved earlier)
Expand All @@ -255,32 +259,81 @@ static int tls_ctx_load_cert_chain(SSL_CTX *ctx, fr_tls_chain_conf_t *chain, boo
*/
SSL_CTX_set_default_passwd_cb(ctx, fr_tls_session_password_cb);

switch (chain->file_format) {
case SSL_FILETYPE_PEM:
if (!(SSL_CTX_use_certificate_chain_file(ctx, chain->certificate_file))) {
fr_tls_log(NULL, "Failed reading certificate file \"%s\"",
chain->certificate_file);
if (chain->certificate_file) {
switch (chain->file_format) {
case SSL_FILETYPE_PEM:
if (!(SSL_CTX_use_certificate_chain_file(ctx, chain->certificate_file))) {
fr_tls_log(NULL, "Failed reading certificate file \"%s\"",
chain->certificate_file);
return -1;
}
break;

case SSL_FILETYPE_ASN1:
if (!(SSL_CTX_use_certificate_file(ctx, chain->certificate_file, chain->file_format))) {
fr_tls_log(NULL, "Failed reading certificate file \"%s\"",
chain->certificate_file);
return -1;
}
break;

default:
fr_assert(0);
break;
}
} else if (chain->certificate_uri) {
if (!(store_ctx = OSSL_STORE_open(chain->certificate_uri, NULL, NULL, tls_ctx_load_cert_chain_store_post_process, (void*)OSSL_STORE_INFO_CERT))) {
fr_tls_log(NULL, "Failed reading certificate from \"%s\"",
chain->certificate_uri);
return -1;
}
break;

case SSL_FILETYPE_ASN1:
if (!(SSL_CTX_use_certificate_file(ctx, chain->certificate_file, chain->file_format))) {
fr_tls_log(NULL, "Failed reading certificate file \"%s\"",
chain->certificate_file);
if (!(store_info = OSSL_STORE_load(store_ctx))) {
fr_tls_log(NULL, "Failed reading certificate from \"%s\"",
chain->certificate_uri);
OSSL_STORE_close(store_ctx);
return -1;
}
break;

default:
fr_assert(0);
break;
certificate = OSSL_STORE_INFO_get0_CERT(store_info);
fr_assert(certificate);
if (!(SSL_CTX_use_certificate(ctx, certificate))) {
fr_tls_log(NULL, "Failed reading certificate uri \"%s\"",
chain->certificate_uri);
OSSL_STORE_close(store_ctx);
return -1;
}
OSSL_STORE_close(store_ctx);
} else {
fr_tls_log(NULL, "Missing certificate. Either certificate_file or certificate_uri must be specified.");
return -1;
}

if (!(SSL_CTX_use_PrivateKey_file(ctx, chain->private_key_file, chain->file_format))) {
fr_tls_log(NULL, "Failed reading private key file \"%s\"",
chain->private_key_file);
return -1;
if (chain->private_key_file) {
if (!(SSL_CTX_use_PrivateKey_file(ctx, chain->private_key_file, chain->file_format))) {
fr_tls_log(NULL, "Failed reading private key file \"%s\"",
chain->private_key_file);
return -1;
}
} else if (chain->private_key_uri) {
if (!(store_ctx = OSSL_STORE_open(chain->private_key_uri, NULL, NULL, tls_ctx_load_cert_chain_store_post_process, (void*)OSSL_STORE_INFO_PKEY))) {
fr_tls_log(NULL, "Failed reading private key from \"%s\"",
chain->private_key_uri);
return -1;
}
if (!(store_info = OSSL_STORE_load(store_ctx))) {
fr_tls_log(NULL, "Failed reading private key from \"%s\"",
chain->private_key_uri);
OSSL_STORE_close(store_ctx);
return -1;
}
private_key = OSSL_STORE_INFO_get0_PKEY(store_info);
fr_assert(certificate);
if (!(SSL_CTX_use_PrivateKey(ctx, private_key))) {
fr_tls_log(NULL, "Failed reading private key uri \"%s\"",
chain->private_key_uri);
OSSL_STORE_close(store_ctx);
return -1;
}
OSSL_STORE_close(store_ctx);
}

{
Expand Down
8 changes: 4 additions & 4 deletions src/lib/tls/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -1921,13 +1921,13 @@ fr_tls_session_t *fr_tls_session_alloc_server(TALLOC_CTX *ctx, SSL_CTX *ssl_ctx,
* on OpenSSL's opaque error messages.
*/
} else {
if (!conf->chains || !conf->chains[0]->private_key_file) {
ERROR("TLS Server requires a private key file");
if (!conf->chains || (!conf->chains[0]->private_key_file && !conf->chains[0]->private_key_uri)) {
ERROR("TLS Server requires a private key file or URI");
goto error;
}

if (!conf->chains || !conf->chains[0]->certificate_file) {
ERROR("TLS Server requires a certificate file");
if (!conf->chains || (!conf->chains[0]->certificate_file && !conf->chains[0]->certificate_uri)) {
ERROR("TLS Server requires a certificate file or URI");
goto error;
}
}
Expand Down