diff --git a/src/internal.c b/src/internal.c index e230283c7..6e6c2b590 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8823,7 +8823,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. @@ -8895,6 +8894,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 @@ -9416,11 +9422,36 @@ 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 (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 ) { + 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; + } + } + } + } + } - if(XSTRSTR(args->dCert->subjectCN, ssl->param->hostName) == NULL) { - return VERIFY_CERT_ERROR; + /* 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 (ret == 0) { + ret = IPADDR_MISMATCH; + } } } #endif @@ -16948,6 +16979,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/src/ssl.c b/src/ssl.c index 090561b1f..8e976bceb 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -23462,7 +23462,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, @@ -23471,8 +23472,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 91b2e9346..31b2930a3 100644 --- a/tests/api.c +++ b/tests/api.c @@ -22113,6 +22113,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/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 */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index f2227a708..ba1c7a00c 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1651,6 +1651,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);