Merge pull request #4716 from julek-wolfssl/issue-4592

Verification: Domain check should only be performed on leaf certs
pull/4764/head
Sean Parkinson 2022-01-17 08:40:14 +10:00 committed by GitHub
commit 15f501358d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 175 additions and 68 deletions

View File

@ -11222,36 +11222,39 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
}
#endif
#if defined(OPENSSL_EXTRA)
/* perform domain name check on the peer certificate */
if (args->dCertInit && args->dCert && (ssl != NULL) &&
ssl->param && ssl->param->hostName[0]) {
/* If altNames names is present, then subject common name is ignored */
if (args->dCert->altNames != NULL) {
if (CheckForAltNames(args->dCert, ssl->param->hostName, NULL) != 1) {
if (ret == 0) {
ret = DOMAIN_NAME_MISMATCH;
}
}
}
else {
if (args->dCert->subjectCN) {
if (MatchDomainName(args->dCert->subjectCN,
args->dCert->subjectCNLen,
ssl->param->hostName) == 0) {
/* Perform domain and IP check only for the leaf certificate */
if (args->certIdx == 0) {
/* perform domain name check on the peer certificate */
if (args->dCertInit && args->dCert && (ssl != NULL) &&
ssl->param && ssl->param->hostName[0]) {
/* If altNames names is present, then subject common name is ignored */
if (args->dCert->altNames != NULL) {
if (CheckForAltNames(args->dCert, ssl->param->hostName, NULL) != 1) {
if (ret == 0) {
ret = DOMAIN_NAME_MISMATCH;
}
}
}
else {
if (args->dCert->subjectCN) {
if (MatchDomainName(args->dCert->subjectCN,
args->dCert->subjectCNLen,
ssl->param->hostName) == 0) {
if (ret == 0) {
ret = DOMAIN_NAME_MISMATCH;
}
}
}
}
}
}
/* perform IP address check on the peer certificate */
if ((args->dCertInit != 0) && (args->dCert != NULL) && (ssl != NULL) &&
(ssl->param != NULL) && (XSTRLEN(ssl->param->ipasc) > 0)) {
if (CheckIPAddr(args->dCert, ssl->param->ipasc) != 0) {
if (ret == 0) {
ret = IPADDR_MISMATCH;
/* perform IP address check on the peer certificate */
if ((args->dCertInit != 0) && (args->dCert != NULL) && (ssl != NULL) &&
(ssl->param != NULL) && (XSTRLEN(ssl->param->ipasc) > 0)) {
if (CheckIPAddr(args->dCert, ssl->param->ipasc) != 0) {
if (ret == 0) {
ret = IPADDR_MISMATCH;
}
}
}
}

105
src/ssl.c
View File

@ -12019,42 +12019,56 @@ int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses)
#endif /* OPENSSL_EXTRA */
typedef struct {
byte verifyPeer:1;
byte verifyNone:1;
byte failNoCert:1;
byte failNoCertxPSK:1;
byte verifyPostHandshake:1;
} SetVerifyOptions;
static SetVerifyOptions ModeToVerifyOptions(int mode)
{
SetVerifyOptions opts;
XMEMSET(&opts, 0, sizeof(SetVerifyOptions));
if (mode != WOLFSSL_VERIFY_DEFAULT) {
opts.verifyNone = (mode == WOLFSSL_VERIFY_NONE);
if (!opts.verifyNone) {
opts.verifyPeer =
(mode & WOLFSSL_VERIFY_PEER) != 0;
opts.failNoCertxPSK =
(mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) != 0;
opts.failNoCert =
(mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT) != 0;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
opts.verifyPostHandshake =
(mode & WOLFSSL_VERIFY_POST_HANDSHAKE) != 0;
#endif
}
}
return opts;
}
WOLFSSL_ABI
void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc)
{
SetVerifyOptions opts;
WOLFSSL_ENTER("wolfSSL_CTX_set_verify");
if (ctx == NULL)
return;
ctx->verifyPeer = 0;
ctx->verifyNone = 0;
ctx->failNoCert = 0;
ctx->failNoCertxPSK = 0;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
ctx->verifyPostHandshake = 0;
#endif
opts = ModeToVerifyOptions(mode);
if (mode != WOLFSSL_VERIFY_DEFAULT) {
if (mode == WOLFSSL_VERIFY_NONE) {
ctx->verifyNone = 1;
}
else {
if (mode & WOLFSSL_VERIFY_PEER) {
ctx->verifyPeer = 1;
}
if (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) {
ctx->failNoCertxPSK = 1;
}
if (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
ctx->failNoCert = 1;
}
ctx->verifyNone = opts.verifyNone;
ctx->verifyPeer = opts.verifyPeer;
ctx->failNoCert = opts.failNoCert;
ctx->failNoCertxPSK = opts.failNoCertxPSK;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
if (mode & WOLFSSL_VERIFY_POST_HANDSHAKE) {
ctx->verifyPostHandshake = 1;
}
ctx->verifyPostHandshake = opts.verifyPostHandshake;
#endif
}
}
ctx->verifyCallback = vc;
}
@ -12075,21 +12089,20 @@ void wolfSSL_CTX_set_cert_verify_callback(WOLFSSL_CTX* ctx,
void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc)
{
SetVerifyOptions opts;
WOLFSSL_ENTER("wolfSSL_set_verify");
if (ssl == NULL)
return;
/* Special case for verifyNone since WOLFSSL_VERIFY_NONE == 0 */
ssl->options.verifyNone = mode == WOLFSSL_VERIFY_NONE;
ssl->options.verifyPeer = (mode & WOLFSSL_VERIFY_PEER)
== WOLFSSL_VERIFY_PEER;
ssl->options.failNoCert = (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT)
== WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT;
ssl->options.failNoCertxPSK = (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK)
== WOLFSSL_VERIFY_FAIL_EXCEPT_PSK;
opts = ModeToVerifyOptions(mode);
ssl->options.verifyNone = opts.verifyNone;
ssl->options.verifyPeer = opts.verifyPeer;
ssl->options.failNoCert = opts.failNoCert;
ssl->options.failNoCertxPSK = opts.failNoCertxPSK;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
ssl->options.verifyPostHandshake = (mode & WOLFSSL_VERIFY_POST_HANDSHAKE)
== WOLFSSL_VERIFY_POST_HANDSHAKE;
ssl->options.verifyPostHandshake = opts.verifyPostHandshake;
#endif
ssl->verifyCallback = vc;
@ -27467,30 +27480,32 @@ int wolfSSL_X509_VERIFY_PARAM_set1_host(WOLFSSL_X509_VERIFY_PARAM* pParam,
const char* name,
unsigned int nameSz)
{
unsigned int sz = 0;
WOLFSSL_ENTER("wolfSSL_X509_VERIFY_PARAM_set1_host");
if (pParam == NULL)
return WOLFSSL_FAILURE;
XMEMSET(pParam->hostName, 0, WOLFSSL_HOST_NAME_MAX);
if (name == NULL)
return WOLFSSL_SUCCESS;
sz = (unsigned int)XSTRLEN(name);
/* If name is NULL-terminated, namelen can be set to zero. */
if (nameSz == 0 || nameSz > sz)
nameSz = sz;
if (nameSz == 0) {
nameSz = (unsigned int)XSTRLEN(name);
}
if (nameSz > 0 && name[nameSz - 1] == '\0')
nameSz--;
if (nameSz > WOLFSSL_HOST_NAME_MAX-1)
if (nameSz > WOLFSSL_HOST_NAME_MAX-1) {
WOLFSSL_MSG("Truncating name");
nameSz = WOLFSSL_HOST_NAME_MAX-1;
}
if (nameSz > 0)
if (nameSz > 0) {
XMEMCPY(pParam->hostName, name, nameSz);
XMEMSET(pParam->hostName + nameSz, 0,
WOLFSSL_HOST_NAME_MAX - nameSz);
}
pParam->hostName[nameSz] = '\0';

View File

@ -36638,6 +36638,92 @@ static void test_wolfSSL_X509_VERIFY_PARAM(void)
#endif
}
#if defined(OPENSSL_EXTRA) && defined(HAVE_IO_TESTS_DEPENDENCIES)
static int test_wolfSSL_check_domain_verify_count = 0;
static WC_INLINE int test_wolfSSL_check_domain_verify_cb(int preverify,
WOLFSSL_X509_STORE_CTX* store)
{
AssertIntEQ(X509_STORE_CTX_get_error(store), 0);
AssertIntEQ(preverify, 1);
test_wolfSSL_check_domain_verify_count++;
return 1;
}
static void test_wolfSSL_check_domain_client_cb(WOLFSSL* ssl)
{
X509_VERIFY_PARAM *param = SSL_get0_param(ssl);
/* Domain check should only be done on the leaf cert */
X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
AssertIntEQ(X509_VERIFY_PARAM_set1_host(param,
"wolfSSL Server Chain", 0), 1);
wolfSSL_set_verify(ssl, WOLFSSL_VERIFY_PEER,
test_wolfSSL_check_domain_verify_cb);
}
static void test_wolfSSL_check_domain_server_cb(WOLFSSL_CTX* ctx)
{
/* Use a cert with different domains in chain */
AssertIntEQ(wolfSSL_CTX_use_certificate_chain_file(ctx,
"certs/intermediate/server-chain.pem"), WOLFSSL_SUCCESS);
}
static void test_wolfSSL_check_domain(void)
{
tcp_ready ready;
func_args client_args;
func_args server_args;
THREAD_TYPE serverThread;
callback_functions func_cb_client;
callback_functions func_cb_server;
printf(testingFmt, "wolfSSL_check_domain");
XMEMSET(&client_args, 0, sizeof(func_args));
XMEMSET(&server_args, 0, sizeof(func_args));
XMEMSET(&func_cb_client, 0, sizeof(callback_functions));
XMEMSET(&func_cb_server, 0, sizeof(callback_functions));
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
#endif
StartTCP();
InitTcpReady(&ready);
#if defined(USE_WINDOWS_API)
/* use RNG to get random port if using windows */
ready.port = GetRandomPort();
#endif
server_args.signal = &ready;
client_args.signal = &ready;
func_cb_client.ssl_ready = &test_wolfSSL_check_domain_client_cb;
func_cb_server.ctx_ready = &test_wolfSSL_check_domain_server_cb;
client_args.callbacks = &func_cb_client;
server_args.callbacks = &func_cb_server;
start_thread(test_server_nofail, &server_args, &serverThread);
wait_tcp_ready(&server_args);
test_client_nofail(&client_args, NULL);
join_thread(serverThread);
AssertTrue(client_args.return_code);
AssertTrue(server_args.return_code);
FreeTcpReady(&ready);
/* Should have been called once for each cert in sent chain */
AssertIntEQ(test_wolfSSL_check_domain_verify_count, 3);
printf(resultFmt, passed);
}
#endif /* OPENSSL_EXTRA && HAVE_IO_TESTS_DEPENDENCIES */
static void test_wolfSSL_X509_get_X509_PUBKEY(void)
{
#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD))
@ -52295,6 +52381,9 @@ void ApiTest(void)
test_wolfSSL_X509_sign2();
test_wolfSSL_X509_get0_tbs_sigalg();
test_wolfSSL_X509_ALGOR_get0();
#if defined(OPENSSL_EXTRA) && defined(HAVE_IO_TESTS_DEPENDENCIES)
test_wolfSSL_check_domain();
#endif
test_wolfSSL_X509_get_X509_PUBKEY();
test_wolfSSL_X509_PUBKEY_RSA();
test_wolfSSL_X509_PUBKEY_EC();