From 9fc33e461c9ba519ba26aecd8e5020e078edc0e3 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Wed, 16 Oct 2019 15:08:30 -0500 Subject: [PATCH 1/6] Check names in verify callback. --- src/internal.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/internal.c b/src/internal.c index 5d5115c74..c4840c6e6 100644 --- a/src/internal.c +++ b/src/internal.c @@ -9339,11 +9339,22 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args) #endif #if defined(OPENSSL_EXTRA) /* perform domain name check on the peer certificate */ - if (args->dCertInit && args->dCert && args->dCert->subjectCN \ - && ssl->param && ssl->param->hostName[0]) { - - if(XSTRSTR(args->dCert->subjectCN, ssl->param->hostName) == NULL) { - return VERIFY_CERT_ERROR; + if (args->dCertInit && args->dCert && + ssl->param && ssl->param->hostName[0]) { + /* If altNames names is present, then subject common name is ignored */ + if (args->dCert->altNames != NULL) { + if (CheckAltNames(args->dCert, ssl->param->hostName) == 0 ) { + return VERIFY_CERT_ERROR; + } + } + else { + if (args->dCert->subjectCN) { + if (MatchDomainName(args->dCert->subjectCN, + args->dCert->subjectCNLen, + ssl->param->hostName) == 0) { + return VERIFY_CERT_ERROR; + } + } } } #endif From 58d800fbb7a863d2e37af11ab7ac0f4d5c1e6452 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Wed, 30 Oct 2019 16:21:31 -0500 Subject: [PATCH 2/6] Adding support for IP address verification --- src/internal.c | 16 +++++++++++++++- src/ssl.c | 9 +++++++-- tests/api.c | 3 +++ wolfssl/internal.h | 3 +++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/internal.c b/src/internal.c index c4840c6e6..200918c53 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8746,7 +8746,6 @@ int CheckAltNames(DecodedCert* dCert, char* domain) return match; } - #ifdef OPENSSL_EXTRA /* Check that alternative names, if they exists, match the domain. * Fail if there are wild patterns and they didn't match. @@ -8818,6 +8817,13 @@ int CheckHostName(DecodedCert* dCert, char *domainName, size_t domainNameLen) return 0; } + +int CheckIPAddr(DecodedCert* dCert, char* ipasc) +{ + WOLFSSL_MSG("Checking IPAddr"); + + return CheckHostName(dCert, ipasc, (size_t)XSTRLEN(ipasc)); +} #endif #ifdef SESSION_CERTS @@ -9357,6 +9363,14 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args) } } } + + /* perform IP address check on the peer certificate */ + if ((args->dCertInit != 0) && (args->dCert != NULL) && + (ssl->param != NULL) && (XSTRLEN(ssl->param->ipasc) > 0)) { + if (CheckIPAddr(args->dCert, ssl->param->ipasc) == 0) { + return VERIFY_CERT_ERROR; + } + } #endif /* if verify callback has been set */ if (use_cb && ssl->verifyCallback) { diff --git a/src/ssl.c b/src/ssl.c index 7cd12ae9f..786fd9c18 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -23006,8 +23006,13 @@ int wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(WOLFSSL_X509_VERIFY_PARAM *param, int ret = WOLFSSL_FAILURE; if (param != NULL) { - XSTRNCPY(param->ipasc, ipasc, WOLFSSL_MAX_IPSTR-1); - param->ipasc[WOLFSSL_MAX_IPSTR-1] = '\0'; + if (ipasc == NULL) { + param->ipasc[0] = '\0'; + } + else { + XSTRNCPY(param->ipasc, ipasc, WOLFSSL_MAX_IPSTR-1); + param->ipasc[WOLFSSL_MAX_IPSTR-1] = '\0'; + } ret = WOLFSSL_SUCCESS; } diff --git a/tests/api.c b/tests/api.c index 5d05dd635..99dc72a2b 100644 --- a/tests/api.c +++ b/tests/api.c @@ -21920,6 +21920,9 @@ static void test_wolfSSL_X509_VERIFY_PARAM(void) AssertIntEQ(1, ret); AssertIntEQ(0, XSTRNCMP(param->ipasc, testIPv4, WOLFSSL_MAX_IPSTR)); + ret = wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(param, NULL); + AssertIntEQ(1, ret); + ret = wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(param, testIPv6); AssertIntEQ(1, ret); AssertIntEQ(0, XSTRNCMP(param->ipasc, testIPv6, WOLFSSL_MAX_IPSTR)); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 383cfa404..0b72dfc27 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1666,6 +1666,9 @@ WOLFSSL_LOCAL int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_LOCAL int MatchDomainName(const char* pattern, int len, const char* str); #ifndef NO_CERTS WOLFSSL_LOCAL int CheckAltNames(DecodedCert* dCert, char* domain); +#ifdef OPENSSL_EXTRA +WOLFSSL_LOCAL int CheckIPAddr(DecodedCert* dCert, char* ipasc); +#endif #endif WOLFSSL_LOCAL int CreateTicket(WOLFSSL* ssl); WOLFSSL_LOCAL int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz); From 6839110507a9f0a0bfff370c09b9b89a5c5b9e87 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Thu, 31 Oct 2019 17:45:33 -0500 Subject: [PATCH 3/6] Update from review --- src/internal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index 200918c53..7a52725bf 100644 --- a/src/internal.c +++ b/src/internal.c @@ -9367,7 +9367,7 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args) /* perform IP address check on the peer certificate */ if ((args->dCertInit != 0) && (args->dCert != NULL) && (ssl->param != NULL) && (XSTRLEN(ssl->param->ipasc) > 0)) { - if (CheckIPAddr(args->dCert, ssl->param->ipasc) == 0) { + if (CheckIPAddr(args->dCert, ssl->param->ipasc) != 0) { return VERIFY_CERT_ERROR; } } From 54f023ac2c00f74c703e077ebec4ed2b21e5dbf7 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Fri, 1 Nov 2019 10:33:49 -0500 Subject: [PATCH 4/6] Clarify ipasc parameter usage --- src/ssl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ssl.c b/src/ssl.c index 786fd9c18..f2d338489 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -22997,7 +22997,8 @@ void wolfSSL_X509_VERIFY_PARAM_set_hostflags(WOLFSSL_X509_VERIFY_PARAM* param, * * param is a pointer to the X509_VERIFY_PARAM structure * ipasc is a NULL-terminated string with N.N.N.N for IPv4 and - * HH:HH ... HH:HH for IPv6. + * HH:HH ... HH:HH for IPv6. There is no validation performed on the + * parameter, and it must be an exact match with the IP in the cert. * * return 1 for success and 0 for failure*/ int wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(WOLFSSL_X509_VERIFY_PARAM *param, From caaab11f6001a764e829fe34b07f8ada1fbaca7e Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Wed, 6 Nov 2019 15:58:50 -0600 Subject: [PATCH 5/6] Update from review --- src/internal.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/internal.c b/src/internal.c index 7a52725bf..515d51299 100644 --- a/src/internal.c +++ b/src/internal.c @@ -9350,7 +9350,9 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args) /* If altNames names is present, then subject common name is ignored */ if (args->dCert->altNames != NULL) { if (CheckAltNames(args->dCert, ssl->param->hostName) == 0 ) { - return VERIFY_CERT_ERROR; + if (ret == 0) { + ret = VERIFY_CERT_ERROR; + } } } else { @@ -9358,7 +9360,9 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args) if (MatchDomainName(args->dCert->subjectCN, args->dCert->subjectCNLen, ssl->param->hostName) == 0) { - return VERIFY_CERT_ERROR; + if (ret == 0) { + ret = VERIFY_CERT_ERROR; + } } } } @@ -9368,7 +9372,9 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args) if ((args->dCertInit != 0) && (args->dCert != NULL) && (ssl->param != NULL) && (XSTRLEN(ssl->param->ipasc) > 0)) { if (CheckIPAddr(args->dCert, ssl->param->ipasc) != 0) { - return VERIFY_CERT_ERROR; + if (ret == 0) { + ret = VERIFY_CERT_ERROR; + } } } #endif From 8c6c4e24322e01f344849421c22973513e1762da Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Thu, 14 Nov 2019 16:02:02 -0600 Subject: [PATCH 6/6] Add unique error codes to verify failures --- src/internal.c | 9 ++++++--- wolfssl/error-ssl.h | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/internal.c b/src/internal.c index 515d51299..cd7fda804 100644 --- a/src/internal.c +++ b/src/internal.c @@ -9351,7 +9351,7 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args) if (args->dCert->altNames != NULL) { if (CheckAltNames(args->dCert, ssl->param->hostName) == 0 ) { if (ret == 0) { - ret = VERIFY_CERT_ERROR; + ret = DOMAIN_NAME_MISMATCH; } } } @@ -9361,7 +9361,7 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args) args->dCert->subjectCNLen, ssl->param->hostName) == 0) { if (ret == 0) { - ret = VERIFY_CERT_ERROR; + ret = DOMAIN_NAME_MISMATCH; } } } @@ -9373,7 +9373,7 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args) (ssl->param != NULL) && (XSTRLEN(ssl->param->ipasc) > 0)) { if (CheckIPAddr(args->dCert, ssl->param->ipasc) != 0) { if (ret == 0) { - ret = VERIFY_CERT_ERROR; + ret = IPADDR_MISMATCH; } } } @@ -16863,6 +16863,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case DOMAIN_NAME_MISMATCH : return "peer subject name mismatch"; + case IPADDR_MISMATCH : + return "peer ip address mismatch"; + case WANT_READ : case WOLFSSL_ERROR_WANT_READ : return "non-blocking socket wants data to be read"; diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 864d67b8e..d03db5661 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -57,7 +57,7 @@ enum wolfSSL_ErrorCodes { DOMAIN_NAME_MISMATCH = -322, /* peer subject name mismatch */ WANT_READ = -323, /* want read, call again */ NOT_READY_ERROR = -324, /* handshake layer not ready */ - + IPADDR_MISMATCH = -325, /* peer ip address mismatch */ VERSION_ERROR = -326, /* record layer version error */ WANT_WRITE = -327, /* want write, call again */ BUFFER_ERROR = -328, /* malformed buffer input */