@@ -1706,6 +1706,94 @@ int test_wolfssl_local_IsValidFQDN(void) {
17061706 return EXPECT_RESULT ();
17071707}
17081708
1709+ /* Verify that MatchDomainName() refuses to expand wildcards across IDNA
1710+ * A-labels (xn-- prefix) per RFC 6125 sec. 6.4.3 / RFC 9525 sec. 6.3.
1711+ *
1712+ * MatchDomainName() is WOLFSSL_LOCAL but visible to the test binary because
1713+ * tests link against the in-tree library. */
1714+ int test_wolfSSL_MatchDomainName_idn (void )
1715+ {
1716+ EXPECT_DECLS ;
1717+ #if !defined(NO_CERTS )
1718+ static const struct {
1719+ const char * pattern ;
1720+ const char * host ;
1721+ unsigned int flags ;
1722+ int expected ; /* 1 = match, 0 = no match */
1723+ const char * note ;
1724+ } cases [] = {
1725+ /* Partial wildcard whose literal prefix overlaps "xn--" must NOT
1726+ * match an A-label hostname. */
1727+ { "x*.example.com" , "xn--rger-koa.example.com" , 0 , 0 ,
1728+ "partial wildcard vs A-label" },
1729+ /* Wildcard embedded inside an A-label pattern must NOT match. */
1730+ { "xn--*.example.com" , "xn--rger-koa.example.com" , 0 , 0 ,
1731+ "wildcard inside A-label pattern" },
1732+ /* Full left-most wildcard MUST NOT match an A-label hostname
1733+ * (RFC 9525 sec. 6.3 strengthens RFC 6125 SHOULD NOT to MUST NOT). */
1734+ { "*.example.com" , "xn--rger-koa.example.com" , 0 , 0 ,
1735+ "full wildcard vs A-label hostname" },
1736+ /* A-label appearing in an inner label still disables wildcard
1737+ * matching against the entire reference identifier. */
1738+ { "*.example.com" , "foo.xn--bar.example.com" , 0 , 0 ,
1739+ "wildcard with A-label in inner label" },
1740+ /* Case-insensitive A-label detection: "XN--" is also an A-label. */
1741+ { "x*.example.com" , "XN--rger-koa.example.com" , 0 , 0 ,
1742+ "uppercase A-label prefix" },
1743+ /* Control: full wildcard SHOULD continue to match plain ASCII. */
1744+ { "*.example.com" , "foo.example.com" , 0 , 1 ,
1745+ "wildcard matches non-IDN" },
1746+ /* Control: exact A-label match (no wildcard in pattern) must work. */
1747+ { "xn--rger-koa.example.com" , "xn--rger-koa.example.com" , 0 , 1 ,
1748+ "exact A-label match" },
1749+ /* Control: a label that merely begins with 'x' (not 'xn--') is not
1750+ * an A-label and must still wildcard-match. */
1751+ { "*.example.com" , "xyz.example.com" , 0 , 1 ,
1752+ "non-A-label x-prefix" },
1753+ /* Control: partial wildcard against a non-A-label still works. */
1754+ { "x*.example.com" , "xyz.example.com" , 0 , 1 ,
1755+ "partial wildcard non-IDN" },
1756+
1757+ /* Trailing-dot normalization: absolute-form FQDN ("example.com.")
1758+ * must match the same FQDN with or without the trailing dot, on
1759+ * either side of the comparison. RFC 1035 / RFC 6125. */
1760+ { "example.com" , "example.com." , 0 , 1 ,
1761+ "trailing dot on host" },
1762+ { "example.com." , "example.com" , 0 , 1 ,
1763+ "trailing dot on pattern" },
1764+ { "example.com." , "example.com." , 0 , 1 ,
1765+ "trailing dot on both" },
1766+ { "*.example.com" , "foo.example.com." , 0 , 1 ,
1767+ "trailing dot on host with wildcard pattern" },
1768+ /* Trailing dot must not cause an A-label gate to misfire. */
1769+ { "*.example.com" , "xn--rger-koa.example.com." , 0 , 0 ,
1770+ "trailing dot on A-label host" },
1771+ /* Same trailing-dot normalization under WOLFSSL_LEFT_MOST_WILDCARD_ONLY. */
1772+ { "*.example.com" , "foo.example.com." ,
1773+ WOLFSSL_LEFT_MOST_WILDCARD_ONLY , 1 ,
1774+ "trailing dot, leftWildcardOnly" },
1775+ };
1776+ size_t i ;
1777+
1778+ for (i = 0 ; i < sizeof (cases ) / sizeof (cases [0 ]); i ++ ) {
1779+ int got = MatchDomainName (
1780+ cases [i ].pattern , (int )XSTRLEN (cases [i ].pattern ),
1781+ cases [i ].host , (word32 )XSTRLEN (cases [i ].host ),
1782+ cases [i ].flags );
1783+ ExpectIntEQ (got , cases [i ].expected );
1784+ if (! EXPECT_SUCCESS ()) {
1785+ fprintf (stderr ,
1786+ "MatchDomainName(\"%s\", \"%s\", flags=0x%x) = %d, "
1787+ "expected %d (%s)\n" ,
1788+ cases [i ].pattern , cases [i ].host , cases [i ].flags ,
1789+ got , cases [i ].expected , cases [i ].note );
1790+ break ;
1791+ }
1792+ }
1793+ #endif /* !NO_CERTS */
1794+ return EXPECT_RESULT ();
1795+ }
1796+
17091797int test_wolfSSL_X509_max_altnames (void )
17101798{
17111799 EXPECT_DECLS ;
0 commit comments