2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-22 01:49:11 +00:00

cert files can contain the full chain of trust, so load all certs in every case for verification

This commit is contained in:
Laszlo Orban 2019-12-06 11:17:12 +01:00
parent 4b6de608c2
commit 5e36cc655c

View File

@ -909,46 +909,22 @@ signal_cb(int signo, int what, void *v)
}
#if defined(HAVE_OPENSSL)
static X509 *
load_cert(const char *file)
{
X509 *x509 = NULL;
BIO *cert = NULL;
debug_decl(load_cert, SUDO_DEBUG_UTIL)
if ((cert = BIO_new(BIO_s_file())) == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to allocate new BIO object for certificate: %s",
ERR_error_string(ERR_get_error(), NULL));
goto exit;
}
if (BIO_read_filename(cert, file) <= 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to read certificate file: %s",
ERR_error_string(ERR_get_error(), NULL));
goto exit;
}
x509 = PEM_read_bio_X509_AUX(cert, NULL, NULL, NULL);
exit:
if (cert)
BIO_free(cert);
debug_return_ptr(x509);
}
static bool
check_cert(X509_STORE *ca_store_ctx, SSL_CTX *ctx, const char *cert_file)
verify_server_cert(SSL_CTX *ctx, const struct logsrvd_tls_config *tls_config)
{
bool ret = false;
X509_STORE_CTX *store_ctx = NULL;
X509 *x509 = NULL;
debug_decl(check_cert, SUDO_DEBUG_UTIL)
X509_STORE *ca_store;
STACK_OF(X509) *chain_certs;
X509 *x509;
debug_decl(verify_server_cert, SUDO_DEBUG_UTIL)
if ((x509 = load_cert(cert_file)) == NULL)
if ((x509 = SSL_CTX_get0_certificate(ctx)) == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to get X509 object from SSL_CTX: %s",
ERR_error_string(ERR_get_error(), NULL));
goto exit;
}
if ((store_ctx = X509_STORE_CTX_new()) == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
@ -957,9 +933,17 @@ check_cert(X509_STORE *ca_store_ctx, SSL_CTX *ctx, const char *cert_file)
goto exit;
}
X509_STORE_set_flags(ca_store_ctx, X509_V_FLAG_X509_STRICT);
if (!SSL_CTX_get0_chain_certs(ctx, &chain_certs)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to get chain certs: %s",
ERR_error_string(ERR_get_error(), NULL));
goto exit;
}
if (!X509_STORE_CTX_init(store_ctx, ca_store_ctx, x509, 0)) {
if ((ca_store = SSL_CTX_get_cert_store(ctx)) != NULL)
X509_STORE_set_flags(ca_store, X509_V_FLAG_X509_STRICT);
if (!X509_STORE_CTX_init(store_ctx, ca_store, x509, chain_certs)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to initialize X509_STORE_CTX object: %s",
ERR_error_string(ERR_get_error(), NULL));
@ -968,61 +952,14 @@ check_cert(X509_STORE *ca_store_ctx, SSL_CTX *ctx, const char *cert_file)
if (X509_verify_cert(store_ctx) <= 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to verify cert: %s",
"unable to verify cert %s: %s", tls_config->cert_path,
ERR_error_string(ERR_get_error(), NULL));
goto exit;
}
/* everything is good, use this server certificate during TLS handshakes */
if (!SSL_CTX_use_certificate(ctx, x509)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to load cert to the ssl context: %s",
ERR_error_string(ERR_get_error(), NULL));
goto exit;
}
ret = true;
exit:
X509_STORE_CTX_free(store_ctx);
X509_free(x509);
debug_return_bool(ret);
}
static bool
verify_server_cert(SSL_CTX *ctx, const struct logsrvd_tls_config *tls_config)
{
bool ret = false;
X509_STORE *ca_store_ctx = NULL;
X509_LOOKUP *x509_lookup = NULL;
debug_decl(verify_server_cert, SUDO_DEBUG_UTIL)
if ((ca_store_ctx = X509_STORE_new()) == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to allocate X509_STORE object for CA bundle: %s",
ERR_error_string(ERR_get_error(), NULL));
goto exit;
}
if ((x509_lookup = X509_STORE_add_lookup(ca_store_ctx, X509_LOOKUP_file())) == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to set lookup method: %s",
ERR_error_string(ERR_get_error(), NULL));
goto exit;
}
if (!X509_LOOKUP_load_file(x509_lookup, tls_config->cacert_path, X509_FILETYPE_PEM)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to load CA bundle file: %s",
ERR_error_string(ERR_get_error(), NULL));
goto exit;
}
ret = check_cert(ca_store_ctx, ctx, tls_config->cert_path);
exit:
X509_STORE_free(ca_store_ctx);
debug_return_bool(ret);
}
@ -1116,30 +1053,40 @@ init_tls_server_context(void)
goto bad;
}
/* verify server certification against the CA bundle file */
if (SSL_CTX_use_certificate_chain_file(ctx, tls_config->cert_path) <= 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to load cert %s: %s", tls_config->cert_path,
ERR_error_string(ERR_get_error(), NULL));
goto bad;
}
if (tls_config->cacert_path != NULL) {
STACK_OF(X509_NAME) *cacerts =
SSL_load_client_CA_file(tls_config->cacert_path);
if (cacerts == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"calling SSL_load_client_CA_file() failed: %s",
ERR_error_string(ERR_get_error(), NULL));
goto bad;
} else {
SSL_CTX_set_client_CA_list(ctx, cacerts);
/* set the location of the CA bundle file for verification */
if (SSL_CTX_load_verify_locations(ctx, tls_config->cacert_path, NULL) <= 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"calling SSL_CTX_load_verify_locations() failed: %s",
ERR_error_string(ERR_get_error(), NULL));
goto bad;
}
}
}
if (!verify_server_cert(ctx, tls_config)) {
goto bad;
}
/* if peer authentication is enabled, verify client cert during TLS handshake */
if (tls_config->check_peer) {
X509 *cacert = load_cert(tls_config->cacert_path);
/* server will send the name of the CA to the client during the handshake */
if (SSL_CTX_add_client_CA(ctx, cacert) <= 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"calling SSL_CTX_add_client_CA() failed: %s",
ERR_error_string(ERR_get_error(), NULL));
}
/* sets the location of the CA bundle file for verification purposes */
if (SSL_CTX_load_verify_locations(ctx, tls_config->cacert_path, NULL) <= 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"calling SSL_CTX_load_verify_locations() failed: %s",
ERR_error_string(ERR_get_error(), NULL));
}
/* server will send a client certificate request to the peer during the handshake */
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
}
@ -1148,13 +1095,13 @@ init_tls_server_context(void)
if (!SSL_CTX_use_PrivateKey_file(ctx, pkey, SSL_FILETYPE_PEM)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to load key file: %s",
"unable to load key file %s: %s", pkey,
ERR_error_string(ERR_get_error(), NULL));
goto bad;
}
if (!SSL_CTX_check_private_key(ctx)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to verify key file: %s",
"unable to verify key file %s: %s", pkey,
ERR_error_string(ERR_get_error(), NULL));
goto bad;
}