diff --git a/src/internal.c b/src/internal.c index 87c8a981c..27956453d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -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; + } } } } diff --git a/src/ssl.c b/src/ssl.c index 32df93ed4..29d8da5bf 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -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'; diff --git a/tests/api.c b/tests/api.c index 010bd2e3a..1ea26ed89 100644 --- a/tests/api.c +++ b/tests/api.c @@ -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();