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