Do not load certificate from tls_ctx_use_external_private_key()

The cert and key loading logic surrounding management-external-key and
management-external cert was somewhat intertwined.  Untangle these to
prepare for making the external key code more reusable.

The best part is that this even reduces the number of lines of code.

Signed-off-by: Steffan Karger <steffan.karger@fox-it.com>
Acked-by: Arne Schwabe <arne@rfc2549.org>
Message-Id: <1536916459-25900-1-git-send-email-steffan.karger@fox-it.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg17464.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
This commit is contained in:
Steffan Karger 2018-09-14 11:14:17 +02:00 committed by Gert Doering
parent da3f583f30
commit 98bfeeb468
4 changed files with 61 additions and 76 deletions

View file

@ -657,41 +657,37 @@ init_ssl(const struct options *options, struct tls_root_ctx *new_ctx)
}
#endif
#ifdef MANAGMENT_EXTERNAL_KEY
else if ((options->management_flags & MF_EXTERNAL_KEY)
&& (options->cert_file || options->management_flags & MF_EXTERNAL_CERT))
else if (options->management_flags & MF_EXTERNAL_CERT)
{
if (options->cert_file)
char *cert = management_query_cert(management,
options->management_certificate);
tls_ctx_load_cert_file(new_ctx, INLINE_FILE_TAG, cert);
free(cert);
}
#endif
else if (options->cert_file)
{
tls_ctx_load_cert_file(new_ctx, options->cert_file, options->cert_file_inline);
}
if (options->priv_key_file)
{
if (0 != tls_ctx_load_priv_file(new_ctx, options->priv_key_file,
options->priv_key_file_inline))
{
tls_ctx_use_external_private_key(new_ctx, options->cert_file,
options->cert_file_inline);
goto err;
}
else
}
#ifdef MANAGMENT_EXTERNAL_KEY
else if (options->management_flags & MF_EXTERNAL_KEY)
{
if (tls_ctx_use_management_external_key(new_ctx))
{
char *external_certificate = management_query_cert(management,
options->management_certificate);
tls_ctx_use_external_private_key(new_ctx, INLINE_FILE_TAG,
external_certificate);
free(external_certificate);
msg (M_WARN, "Cannot initialize mamagement-external-key");
goto err;
}
}
#endif
else
{
/* Load Certificate */
if (options->cert_file)
{
tls_ctx_load_cert_file(new_ctx, options->cert_file, options->cert_file_inline);
}
/* Load Private Key */
if (options->priv_key_file)
{
if (0 != tls_ctx_load_priv_file(new_ctx, options->priv_key_file, options->priv_key_file_inline))
{
goto err;
}
}
}
if (options->ca_file || options->ca_path)
{

View file

@ -270,8 +270,7 @@ void tls_ctx_load_cert_file(struct tls_root_ctx *ctx, const char *cert_file,
* successful.
*/
int tls_ctx_load_priv_file(struct tls_root_ctx *ctx, const char *priv_key_file,
const char *priv_key_file_inline
);
const char *priv_key_file_inline);
#ifdef MANAGMENT_EXTERNAL_KEY
@ -280,18 +279,12 @@ int tls_ctx_load_priv_file(struct tls_root_ctx *ctx, const char *priv_key_file,
* private key matching the given certificate.
*
* @param ctx TLS context to use
* @param cert_file The file name to load the certificate from, or
* "[[INLINE]]" in the case of inline files.
* @param cert_file_inline A string containing the certificate
*
* @return 1 if an error occurred, 0 if parsing was
* successful.
* @return 1 if an error occurred, 0 if successful.
*/
int tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,
const char *cert_file, const char *cert_file_inline);
#endif
int tls_ctx_use_management_external_key(struct tls_root_ctx *ctx);
#endif /* MANAGMENT_EXTERNAL_KEY */
/**
* Load certificate authority certificates from the given file or path.

View file

@ -621,15 +621,13 @@ external_key_len(void *vctx)
}
int
tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,
const char *cert_file, const char *cert_file_inline)
tls_ctx_use_management_external_key(struct tls_root_ctx *ctx)
{
ASSERT(NULL != ctx);
tls_ctx_load_cert_file(ctx, cert_file, cert_file_inline);
if (ctx->crt_chain == NULL)
{
msg (M_WARN, "ERROR: external key requires a certificate.");
return 1;
}

View file

@ -795,11 +795,9 @@ tls_ctx_add_extra_certs(struct tls_root_ctx *ctx, BIO *bio)
}
}
/* Like tls_ctx_load_cert, but returns a copy of the certificate in **X509 */
static void
tls_ctx_load_cert_file_and_copy(struct tls_root_ctx *ctx,
const char *cert_file, const char *cert_file_inline, X509 **x509
)
void
tls_ctx_load_cert_file(struct tls_root_ctx *ctx, const char *cert_file,
const char *cert_file_inline)
{
BIO *in = NULL;
X509 *x = NULL;
@ -807,10 +805,6 @@ tls_ctx_load_cert_file_and_copy(struct tls_root_ctx *ctx,
bool inline_file = false;
ASSERT(NULL != ctx);
if (NULL != x509)
{
ASSERT(NULL == *x509);
}
inline_file = (strcmp(cert_file, INLINE_FILE_TAG) == 0);
@ -861,23 +855,12 @@ end:
{
BIO_free(in);
}
if (x509)
{
*x509 = x;
}
else if (x)
{
X509_free(x);
}
}
void
tls_ctx_load_cert_file(struct tls_root_ctx *ctx, const char *cert_file,
const char *cert_file_inline)
{
tls_ctx_load_cert_file_and_copy(ctx, cert_file, cert_file_inline, NULL);
}
int
tls_ctx_load_priv_file(struct tls_root_ctx *ctx, const char *priv_key_file,
const char *priv_key_file_inline
@ -1039,7 +1022,7 @@ rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i
static int
openvpn_extkey_rsa_finish(RSA *rsa)
{
/* meth was allocated in tls_ctx_use_external_private_key() ; since
/* meth was allocated in tls_ctx_use_management_external_key() ; since
* this function is called when the parent RSA object is destroyed,
* it is no longer used after this point so kill it. */
const RSA_METHOD *meth = RSA_get_method(rsa);
@ -1288,14 +1271,20 @@ err:
#endif /* OPENSSL_VERSION_NUMBER > 1.1.0 dev */
int
tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,
const char *cert_file, const char *cert_file_inline)
tls_ctx_use_management_external_key(struct tls_root_ctx *ctx)
{
X509 *cert = NULL;
int ret = 1;
ASSERT(NULL != ctx);
tls_ctx_load_cert_file_and_copy(ctx, cert_file, cert_file_inline, &cert);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
/* OpenSSL 1.0.2 and up */
X509 *cert = SSL_CTX_get0_certificate(ctx->ctx);
#else
/* OpenSSL 1.0.1 and earlier need an SSL object to get at the certificate */
SSL *ssl = SSL_new(ctx->ctx);
X509 *cert = SSL_get_certificate(ssl);
#endif
ASSERT(NULL != cert);
@ -1308,7 +1297,7 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,
{
if (!tls_ctx_use_external_rsa_key(ctx, pkey))
{
goto err;
goto cleanup;
}
}
#if OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_EC) && !defined(LIBRESSL_VERSION_NUMBER)
@ -1316,26 +1305,35 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,
{
if (!tls_ctx_use_external_ec_key(ctx, pkey))
{
goto err;
goto cleanup;
}
}
else
{
crypto_msg(M_WARN, "management-external-key requires an RSA or EC certificate");
goto err;
goto cleanup;
}
#else
else
{
crypto_msg(M_WARN, "management-external-key requires an RSA certificate");
goto err;
goto cleanup;
}
#endif /* OPENSSL_VERSION_NUMBER > 1.1.0 dev */
return 0;
err:
crypto_msg(M_FATAL, "Cannot enable SSL external private key capability");
return 1;
ret = 0;
cleanup:
#if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
if (ssl)
{
SSL_free(ssl);
}
#endif
if (ret)
{
crypto_msg(M_FATAL, "Cannot enable SSL external private key capability");
}
return ret;
}
#endif /* ifdef MANAGMENT_EXTERNAL_KEY */