mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 15:50:51 +02:00
Merge pull request #9935 from padelsbach/padelsbach/san-ip-addr-test
Add IP SAN matching
This commit is contained in:
@@ -5435,6 +5435,22 @@ int wolfSSL_want_read(WOLFSSL* ssl);
|
||||
*/
|
||||
int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn);
|
||||
|
||||
/*!
|
||||
\ingroup Setup
|
||||
|
||||
\brief wolfSSL_connect() または wolfSSL_accept() の前にこの関数を呼ぶと、
|
||||
ピア証明書の SAN iPAddress エントリに対する IP アドレス検証を追加します。
|
||||
|
||||
\return SSL_SUCCESS 成功。
|
||||
\return SSL_FAILURE パラメータ不正またはメモリ確保失敗。
|
||||
|
||||
\param ssl wolfSSL_new() で作成された WOLFSSL 構造体へのポインタ。
|
||||
\param ipaddr 検証する NULL 終端 ASCII IP アドレス文字列。
|
||||
|
||||
\sa wolfSSL_check_domain_name
|
||||
*/
|
||||
int wolfSSL_check_ip_address(WOLFSSL* ssl, const char* ipaddr);
|
||||
|
||||
/*!
|
||||
\ingroup TLS
|
||||
|
||||
|
||||
@@ -6432,6 +6432,37 @@ int wolfSSL_want_write(WOLFSSL* ssl);
|
||||
*/
|
||||
int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn);
|
||||
|
||||
/*!
|
||||
\ingroup Setup
|
||||
|
||||
\brief Calling this function before wolfSSL_connect() or wolfSSL_accept()
|
||||
adds an IP-address identity check against the peer certificate SAN
|
||||
iPAddress entries.
|
||||
|
||||
\return SSL_SUCCESS upon success.
|
||||
\return SSL_FAILURE if parameters are invalid or memory allocation fails.
|
||||
|
||||
\param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new().
|
||||
\param ipaddr NULL-terminated ASCII IP address string to verify against the
|
||||
peer certificate.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
int ret = 0;
|
||||
WOLFSSL* ssl;
|
||||
const char* ip = "127.0.0.1";
|
||||
...
|
||||
|
||||
ret = wolfSSL_check_ip_address(ssl, ip);
|
||||
if (ret != SSL_SUCCESS) {
|
||||
// failed to enable IP check
|
||||
}
|
||||
\endcode
|
||||
|
||||
\sa wolfSSL_check_domain_name
|
||||
*/
|
||||
int wolfSSL_check_ip_address(WOLFSSL* ssl, const char* ipaddr);
|
||||
|
||||
/*!
|
||||
\ingroup TLS
|
||||
|
||||
|
||||
+13
-1
@@ -8720,6 +8720,7 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
|
||||
FreeHandshakeHashes(ssl);
|
||||
#endif
|
||||
XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
|
||||
XFREE(ssl->buffers.ipasc.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
|
||||
|
||||
/* clear keys struct after session */
|
||||
ForceZero(&ssl->keys, sizeof(Keys));
|
||||
@@ -16889,7 +16890,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
||||
(char*)ssl->buffers.domainName.buffer,
|
||||
(ssl->buffers.domainName.buffer == NULL ? 0 :
|
||||
(word32)XSTRLEN(ssl->buffers.domainName.buffer)),
|
||||
NULL, 0) != 1) {
|
||||
NULL, 0, 0) != 1) {
|
||||
WOLFSSL_MSG("DomainName match failed");
|
||||
/* try to get peer key still */
|
||||
ret = DOMAIN_NAME_MISMATCH;
|
||||
@@ -16899,6 +16900,17 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
||||
#endif /* WOLFSSL_ALL_NO_CN_IN_SAN */
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_EXTRA
|
||||
if (!ssl->options.verifyNone && ssl->buffers.ipasc.buffer) {
|
||||
if (CheckIPAddr(args->dCert,
|
||||
(const char*)ssl->buffers.ipasc.buffer) != 0) {
|
||||
WOLFSSL_MSG("IPAddr match on alt names failed");
|
||||
ret = IPADDR_MISMATCH;
|
||||
WOLFSSL_ERROR_VERBOSE(ret);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* decode peer key */
|
||||
switch (args->dCert->keyOID) {
|
||||
#ifndef NO_RSA
|
||||
|
||||
@@ -7563,6 +7563,48 @@ int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn)
|
||||
}
|
||||
}
|
||||
|
||||
/* call before SSL_connect, if verifying will add IP SAN check to
|
||||
date check and signature check */
|
||||
WOLFSSL_ABI
|
||||
int wolfSSL_check_ip_address(WOLFSSL* ssl, const char* ipaddr)
|
||||
{
|
||||
WOLFSSL_ENTER("wolfSSL_check_ip_address");
|
||||
|
||||
if (ssl == NULL || ipaddr == NULL) {
|
||||
WOLFSSL_MSG("Bad function argument: NULL");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
|
||||
if (ssl->buffers.ipasc.buffer != NULL) {
|
||||
XFREE(ssl->buffers.ipasc.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
|
||||
ssl->buffers.ipasc.buffer = NULL;
|
||||
ssl->buffers.ipasc.length = 0;
|
||||
}
|
||||
|
||||
ssl->buffers.ipasc.length = (word32)XSTRLEN(ipaddr);
|
||||
ssl->buffers.ipasc.buffer = (byte*)XMALLOC(ssl->buffers.ipasc.length + 1,
|
||||
ssl->heap, DYNAMIC_TYPE_DOMAIN);
|
||||
if (ssl->buffers.ipasc.buffer == NULL) {
|
||||
ssl->error = MEMORY_ERROR;
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
|
||||
XMEMCPY(ssl->buffers.ipasc.buffer, ipaddr, ssl->buffers.ipasc.length);
|
||||
ssl->buffers.ipasc.buffer[ssl->buffers.ipasc.length] = '\0';
|
||||
|
||||
#ifdef OPENSSL_EXTRA
|
||||
if (ssl->param == NULL) {
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
if (wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(ssl->param, ipaddr) !=
|
||||
WOLFSSL_SUCCESS) {
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return WOLFSSL_SUCCESS;
|
||||
}
|
||||
|
||||
#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
|
||||
const char *wolfSSL_get0_peername(WOLFSSL *ssl) {
|
||||
if (ssl == NULL) {
|
||||
|
||||
+100
@@ -16004,6 +16004,8 @@ static int test_wolfSSL_check_domain_basic_client_ssl(WOLFSSL* ssl)
|
||||
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
/* Verify wolfSSL_check_domain_name() controls DNS-name matching during
|
||||
* handshake with expected fail/pass outcomes. */
|
||||
static int test_wolfSSL_check_domain_basic(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
@@ -16036,6 +16038,102 @@ static int test_wolfSSL_check_domain_basic(void)
|
||||
}
|
||||
#endif /* HAVE_SSL_MEMIO_TESTS_DEPENDENCIES */
|
||||
|
||||
#if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||
(defined(WOLFSSL_IP_ALT_NAME) || defined(OPENSSL_ALL)) && \
|
||||
!defined(OPENSSL_COMPATIBLE_DEFAULTS) && !defined(NO_SHA256)
|
||||
static const char* ipaddr = NULL;
|
||||
static int test_wolfSSL_check_ip_param_client_ssl(WOLFSSL* ssl)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
X509_VERIFY_PARAM* param = NULL;
|
||||
|
||||
ExpectNotNull(param = SSL_get0_param(ssl));
|
||||
ExpectIntEQ(X509_VERIFY_PARAM_set1_ip_asc(param, ipaddr), WOLFSSL_SUCCESS);
|
||||
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/* Verify the OpenSSL-compat verify-param path:
|
||||
* SSL_get0_param() + X509_VERIFY_PARAM_set1_ip_asc() controls IP SAN matching
|
||||
* during handshake. */
|
||||
static int test_wolfSSL_check_ip_param_basic(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
test_ssl_cbf func_cb_client;
|
||||
test_ssl_cbf func_cb_server;
|
||||
|
||||
XMEMSET(&func_cb_client, 0, sizeof(func_cb_client));
|
||||
XMEMSET(&func_cb_server, 0, sizeof(func_cb_server));
|
||||
|
||||
func_cb_client.ssl_ready = &test_wolfSSL_check_ip_param_client_ssl;
|
||||
|
||||
ipaddr = "127.0.0.2";
|
||||
/* Expect to fail: cert SAN IP is 127.0.0.1 */
|
||||
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client,
|
||||
&func_cb_server, NULL), -1001);
|
||||
|
||||
ipaddr = "127.0.0.1";
|
||||
/* Expect to succeed */
|
||||
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client,
|
||||
&func_cb_server, NULL), TEST_SUCCESS);
|
||||
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
#else
|
||||
static int test_wolfSSL_check_ip_param_basic(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||
!defined(OPENSSL_COMPATIBLE_DEFAULTS) && !defined(NO_SHA256) && \
|
||||
defined(WOLFSSL_IP_ALT_NAME)
|
||||
static const char* ipaddr_api = NULL;
|
||||
static int test_wolfSSL_check_ip_address_basic_client_ssl(WOLFSSL* ssl)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
|
||||
ExpectIntEQ(wolfSSL_check_ip_address(ssl, ipaddr_api), WOLFSSL_SUCCESS);
|
||||
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/* Verify wolfSSL convenience API path:
|
||||
* wolfSSL_check_ip_address() enables IP SAN matching during handshake,
|
||||
* including the non-OPENSSL_EXTRA storage/verification flow. */
|
||||
static int test_wolfSSL_check_ip_address_basic(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
test_ssl_cbf func_cb_client;
|
||||
test_ssl_cbf func_cb_server;
|
||||
|
||||
XMEMSET(&func_cb_client, 0, sizeof(func_cb_client));
|
||||
XMEMSET(&func_cb_server, 0, sizeof(func_cb_server));
|
||||
|
||||
func_cb_client.ssl_ready = &test_wolfSSL_check_ip_address_basic_client_ssl;
|
||||
|
||||
ipaddr_api = "127.0.0.2";
|
||||
/* Expect to fail: cert SAN IP is 127.0.0.1 */
|
||||
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client,
|
||||
&func_cb_server, NULL), -1001);
|
||||
|
||||
ipaddr_api = "127.0.0.1";
|
||||
/* Expect to succeed */
|
||||
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client,
|
||||
&func_cb_server, NULL), TEST_SUCCESS);
|
||||
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
#else
|
||||
static int test_wolfSSL_check_ip_address_basic(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
#endif
|
||||
|
||||
static int test_wolfSSL_BUF(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
@@ -34201,6 +34299,8 @@ TEST_CASE testCases[] = {
|
||||
|
||||
TEST_DECL(test_wolfSSL_check_domain),
|
||||
TEST_DECL(test_wolfSSL_check_domain_basic),
|
||||
TEST_DECL(test_wolfSSL_check_ip_param_basic),
|
||||
TEST_DECL(test_wolfSSL_check_ip_address_basic),
|
||||
TEST_DECL(test_wolfSSL_cert_cb),
|
||||
TEST_DECL(test_wolfSSL_cert_cb_dyn_ciphers),
|
||||
TEST_DECL(test_wolfSSL_ciphersuite_auth),
|
||||
|
||||
@@ -4891,6 +4891,7 @@ typedef struct Buffers {
|
||||
ThreadCrypt encrypt[WOLFSSL_THREADED_CRYPT_CNT];
|
||||
#endif
|
||||
buffer domainName; /* for client check */
|
||||
buffer ipasc; /* for client IP SAN check */
|
||||
buffer clearOutputBuffer;
|
||||
buffer sig; /* signature data */
|
||||
buffer digest; /* digest data */
|
||||
|
||||
@@ -3356,6 +3356,9 @@ WOLFSSL_API int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx,
|
||||
/* call before SSL_connect, if verifying will add name check to
|
||||
date check and signature check */
|
||||
WOLFSSL_ABI WOLFSSL_API int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn);
|
||||
/* call before SSL_connect, if verifying will add IP address check to
|
||||
date check and signature check */
|
||||
WOLFSSL_ABI WOLFSSL_API int wolfSSL_check_ip_address(WOLFSSL* ssl, const char* ipaddr);
|
||||
|
||||
|
||||
/* need to call once to load library (session cache) */
|
||||
|
||||
Reference in New Issue
Block a user