diff --git a/src/internal.c b/src/internal.c index b18a12c57..c03b74479 100644 --- a/src/internal.c +++ b/src/internal.c @@ -9312,31 +9312,6 @@ int MatchDomainName(const char* pattern, int len, const char* str) } -/* try to find an altName match to domain, return 1 on success */ -int CheckAltNames(DecodedCert* dCert, char* domain) -{ - int match = 0; - DNS_entry* altName = NULL; - - WOLFSSL_MSG("Checking AltNames"); - - if (dCert) - altName = dCert->altNames; - - while (altName) { - WOLFSSL_MSG("\tindividual AltName check"); - - if (MatchDomainName(altName->name, altName->len, domain)){ - match = 1; - break; - } - - altName = altName->next; - } - - return match; -} - /* Check that alternative names, if they exists, match the domain. * Fail if there are wild patterns and they didn't match. * Check the common name if no alternative names matched. @@ -9348,30 +9323,66 @@ int CheckAltNames(DecodedCert* dCert, char* domain) * 0 : no match found. * -1 : No matches and wild pattern match failed. */ -static int CheckForAltNames(DecodedCert* dCert, const char* domain, int* checkCN) +int CheckForAltNames(DecodedCert* dCert, const char* domain, int* checkCN) { - int match; + int match = 0; DNS_entry* altName = NULL; + char *buf; + word32 len; WOLFSSL_MSG("Checking AltNames"); if (dCert) altName = dCert->altNames; - *checkCN = altName == NULL; - match = 0; + if (checkCN != NULL) { + *checkCN = altName == NULL; + } + while (altName) { WOLFSSL_MSG("\tindividual AltName check"); - if (MatchDomainName(altName->name, altName->len, domain)) { +#if defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME) + char name[WOLFSSL_MAX_IPSTR] = {0}; + /* check if alt name is stored as IP addr octet */ + if (altName->type == ASN_IP_TYPE) { + char tmp[4]; + int i; + word32 idx = 0; + for (i = 0; (idx < WOLFSSL_MAX_IPSTR) && (i < altName->len); i++) { + XMEMSET(tmp, 0, sizeof(tmp)); + XSNPRINTF(tmp, sizeof(tmp), (altName->len <= 4) ? "%u" : "%02X", + altName->name[i]); + idx += XSTRLEN(tmp); + XSTRNCAT(name, tmp, (altName->len <= 4) ? 3 : 2); + if ((idx < WOLFSSL_MAX_IPSTR ) && ((i + 1) < altName->len)) { + name[idx++] = (altName->len <= 4) ? '.' : ':'; + } + } + if (idx >= WOLFSSL_MAX_IPSTR) { + idx = WOLFSSL_MAX_IPSTR -1; + } + name[idx] = '\0'; + buf = name; + len = (word32)XSTRLEN(name); + } + else +#endif /* OPENSSL_ALL || WOLFSSL_IP_ALT_NAME */ + { + buf = altName->name; + len = altName->len; + } + + if (MatchDomainName(buf, len, domain)) { match = 1; - *checkCN = 0; + if (checkCN != NULL) { + *checkCN = 0; + } WOLFSSL_MSG("\tmatch found"); break; } /* No matches and wild pattern match failed. */ - else if (altName->name && altName->len >=1 && - altName->name[0] == '*' && match == 0) { + else if (buf && (len >=1) && (buf[0] == '*')) { match = -1; WOLFSSL_MSG("\twildcard match failed"); } @@ -9975,7 +9986,7 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, 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 (CheckForAltNames(args->dCert, ssl->param->hostName, NULL) != 1) { if (ret == 0) { ret = DOMAIN_NAME_MISMATCH; } @@ -11255,8 +11266,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, * are to be bound into a certificate, the subject * alternative name extension MUST be used." */ if (args->dCert->altNames) { - if (CheckAltNames(args->dCert, - (char*)ssl->buffers.domainName.buffer) == 0 ) { + if (CheckForAltNames(args->dCert, + (char*)ssl->buffers.domainName.buffer, + NULL) != 1) { WOLFSSL_MSG("DomainName match on alt names failed"); /* try to get peer key still */ ret = DOMAIN_NAME_MISMATCH; @@ -11277,8 +11289,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, args->dCert->subjectCNLen, (char*)ssl->buffers.domainName.buffer) == 0) { WOLFSSL_MSG("DomainName match on common name failed"); - if (CheckAltNames(args->dCert, - (char*)ssl->buffers.domainName.buffer) == 0 ) { + if (CheckForAltNames(args->dCert, + (char*)ssl->buffers.domainName.buffer, + NULL) != 1) { WOLFSSL_MSG( "DomainName match on alt names failed too"); /* try to get peer key still */ diff --git a/src/ssl.c b/src/ssl.c index fd04c354c..bf7cf307f 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -9526,20 +9526,16 @@ err: #ifdef OPENSSL_EXTRA #ifndef NO_CERTS -int wolfSSL_X509_add_altname(WOLFSSL_X509* x509, const char* name, int type) +int wolfSSL_X509_add_altname_ex(WOLFSSL_X509* x509, const char* name, + word32 nameSz, int type) { DNS_entry* newAltName = NULL; char* nameCopy = NULL; - word32 nameSz; if (x509 == NULL) return WOLFSSL_FAILURE; - if (name == NULL) - return WOLFSSL_SUCCESS; - - nameSz = (word32)XSTRLEN(name); - if (nameSz == 0) + if ((name == NULL) || (nameSz == 0)) return WOLFSSL_SUCCESS; newAltName = (DNS_entry*)XMALLOC(sizeof(DNS_entry), @@ -9553,7 +9549,9 @@ int wolfSSL_X509_add_altname(WOLFSSL_X509* x509, const char* name, int type) return WOLFSSL_FAILURE; } - XMEMCPY(nameCopy, name, nameSz + 1); + XMEMCPY(nameCopy, name, nameSz); + + nameCopy[nameSz] = '\0'; newAltName->next = x509->altNames; newAltName->type = type; @@ -9564,6 +9562,25 @@ int wolfSSL_X509_add_altname(WOLFSSL_X509* x509, const char* name, int type) return WOLFSSL_SUCCESS; } +int wolfSSL_X509_add_altname(WOLFSSL_X509* x509, const char* name, int type) +{ + word32 nameSz; + + if (name == NULL) + return WOLFSSL_SUCCESS; + + nameSz = (word32)XSTRLEN(name); + if (nameSz == 0) + return WOLFSSL_SUCCESS; + + if (type == ASN_IP_TYPE) { + WOLFSSL_MSG("Type not supported, use wolfSSL_X509_add_altname_ex"); + return WOLFSSL_FAILURE; + } + + return wolfSSL_X509_add_altname_ex(x509, name, nameSz, type); +} + #ifndef NO_WOLFSSL_STUB int wolfSSL_X509_add_ext(WOLFSSL_X509 *x509, WOLFSSL_X509_EXTENSION *ext, int loc) diff --git a/tests/api.c b/tests/api.c index d13ddc207..dbea97bdb 100644 --- a/tests/api.c +++ b/tests/api.c @@ -27423,7 +27423,7 @@ static void test_wolfSSL_X509_sign(void) #ifdef WOLFSSL_ALT_NAMES /* Add some subject alt names */ AssertIntNE(wolfSSL_X509_add_altname(NULL, - NULL, ASN_DNS_TYPE), SSL_SUCCESS); + "ipsum", ASN_DNS_TYPE), SSL_SUCCESS); AssertIntEQ(wolfSSL_X509_add_altname(x509, NULL, ASN_DNS_TYPE), SSL_SUCCESS); AssertIntEQ(wolfSSL_X509_add_altname(x509, @@ -27435,7 +27435,15 @@ static void test_wolfSSL_X509_sign(void) AssertIntEQ(wolfSSL_X509_add_altname(x509, "Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch", ASN_DNS_TYPE), SSL_SUCCESS); +#if defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME) + { + unsigned char ip_type[] = {127,0,0,1}; + AssertIntEQ(wolfSSL_X509_add_altname_ex(x509, (char*)ip_type, + sizeof(ip_type), ASN_IP_TYPE), SSL_SUCCESS); + } +#endif #endif /* WOLFSSL_ALT_NAMES */ + /* Test invalid parameters */ AssertIntEQ(X509_sign(NULL, priv, EVP_sha256()), 0); AssertIntEQ(X509_sign(x509, NULL, EVP_sha256()), 0); @@ -27443,6 +27451,10 @@ static void test_wolfSSL_X509_sign(void) ret = X509_sign(x509, priv, EVP_sha256()); +#if defined(WOLFSSL_ALT_NAMES) && (defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME)) + AssertIntEQ(wolfSSL_X509_check_ip_asc(x509, "127.0.0.1", 0), 1); +#endif + #if 0 /* example for writing to file */ XFILE tmpFile = XFOPEN("./signed.der", "wb"); @@ -27472,8 +27484,13 @@ static void test_wolfSSL_X509_sign(void) /* Valid case - size should be 798 with 16 byte serial number */ AssertIntEQ(ret, 782 + snSz); #else /* WOLFSSL_ALT_NAMES */ + #if defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME) + /* Valid case - size should be 936 with 16 byte serial number */ + AssertIntEQ(ret, 920 + snSz); + #else /* Valid case - size should be 927 with 16 byte serial number */ AssertIntEQ(ret, 911 + snSz); + #endif #endif /* WOLFSSL_ALT_NAMES */ X509_NAME_free(name); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index d8127d825..e61a89dd2 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1694,7 +1694,7 @@ WOLFSSL_LOCAL void FreeSuites(WOLFSSL* ssl); WOLFSSL_LOCAL int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size); WOLFSSL_LOCAL int MatchDomainName(const char* pattern, int len, const char* str); #ifndef NO_CERTS -WOLFSSL_LOCAL int CheckAltNames(DecodedCert* dCert, char* domain); +WOLFSSL_LOCAL int CheckForAltNames(DecodedCert* dCert, const char* domain, int* checkCN); WOLFSSL_LOCAL int CheckIPAddr(DecodedCert* dCert, const char* ipasc); #endif WOLFSSL_LOCAL int CreateTicket(WOLFSSL* ssl); diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index dac204653..fa876fa00 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -2149,6 +2149,7 @@ WOLFSSL_API int wolfSSL_X509_version(WOLFSSL_X509*); WOLFSSL_API int wolfSSL_cmp_peer_cert_to_file(WOLFSSL*, const char*); WOLFSSL_ABI WOLFSSL_API char* wolfSSL_X509_get_next_altname(WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_X509_add_altname_ex(WOLFSSL_X509*, const char*, word32, int); WOLFSSL_API int wolfSSL_X509_add_altname(WOLFSSL_X509*, const char*, int); WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509(WOLFSSL_X509** x509,