@@ -1081,11 +1081,19 @@ int test_wolfSSL_X509_check_ip_asc(void)
10811081 ExpectIntEQ (wolfSSL_X509_check_ip_asc (cn_lit , "127.0.0.1" , 0 ), 0 );
10821082 /* CN=*.0.0.1 with no SAN must NOT wildcard-match "127.0.0.1". */
10831083 ExpectIntEQ (wolfSSL_X509_check_ip_asc (cn_wild , "127.0.0.1" , 0 ), 0 );
1084+
10841085 /* CN-based hostname matching must still work for hostname checks
10851086 * (sanity check that the fix didn't over-correct). */
10861087 ExpectIntEQ (wolfSSL_X509_check_host (cn_wild , "1.0.0.1" ,
10871088 XSTRLEN ("1.0.0.1" ), 0 , NULL ), 1 );
10881089
1090+ /* However, when WOLFSSL_LEFT_MOST_WILDCARD_ONLY, CN-based hostname
1091+ * matching must not apply wildcards when the supplied hostname isn't a
1092+ * well-formed FQDN.
1093+ */
1094+ ExpectIntEQ (wolfSSL_X509_check_host (cn_wild , "1.0.0.1" ,
1095+ XSTRLEN ("1.0.0.1" ), WOLFSSL_LEFT_MOST_WILDCARD_ONLY , NULL ), 0 );
1096+
10891097 wolfSSL_X509_free (cn_wild );
10901098 wolfSSL_X509_free (cn_lit );
10911099 }
@@ -1610,6 +1618,94 @@ int test_wolfSSL_X509_name_match3(void)
16101618 return EXPECT_RESULT ();
16111619}
16121620
1621+ int test_wolfssl_local_IsValidFQDN (void ) {
1622+ EXPECT_DECLS ;
1623+
1624+ static const struct { const char * str ; int is_FQDN ; } test_cases [] = {
1625+ {"example.com" , 1 },
1626+ {"example.com." , 1 }, /* trailing dot (absolute form) */
1627+ {"sub.example.com" , 1 },
1628+ {"a.b" , 1 }, /* minimal two-label */
1629+ {"xn--nxasmq5b.com" , 1 }, /* punycode / IDN (ACE form) */
1630+ {"test_underscore.example.com" , 1 }, /* underscore in non-TLD label */
1631+ {"_leading.example.com" , 1 }, /* underscore at start of label */
1632+ {"trailing_.example.com" , 1 },/* underscore at end of non-TLD label */
1633+ {"123.numericlabel.example.com" , 1 }, /* numeric labels are fine */
1634+ {"example.12a3" , 1 }, /* TLD with letters + digits */
1635+ {"ex--ample.com" , 1 }, /* double hyphen inside label (allowed) */
1636+ {"A.B.C" , 1 }, /* uppercase OK (case-insensitive rules) */
1637+
1638+ {"example" , 0 }, /* single label (not fully qualified) */
1639+ {"example." , 0 }, /* becomes single label after dot strip */
1640+ {".example.com" , 0 }, /* leading dot -- empty first label */
1641+ {"example..com" , 0 }, /* empty label (consecutive dots) */
1642+ {"-example.com" , 0 }, /* label starts with '-' */
1643+ {"example-.com" , 0 }, /* label ends with '-' */
1644+ {"example.com-" , 0 }, /* final label ends with '-' */
1645+ {"example.com_" , 0 }, /* underscore in TLD (forbidden) */
1646+ {"example._com" , 0 }, /* underscore in TLD (forbidden) */
1647+ {"ex@mple.com" , 0 }, /* illegal character '@' */
1648+ {"example com.com" , 0 }, /* illegal character ' ' */
1649+ {"" , 0 }, /* empty string */
1650+ {NULL , 0 }, /* NULL pointer */
1651+ {"com" , 0 }, /* single label */
1652+ {"123.456" , 0 }, /* all-numeric final label (no alpha) */
1653+ {"example.123" , 0 }, /* all-numeric TLD (no alpha) */
1654+ {"a" , 0 }, /* single label, too short */
1655+ {"example.123a" , 1 }, /* TLD with at least one letter -- valid */
1656+ };
1657+
1658+ int i ;
1659+ for (i = 0 ; i < (int )(sizeof (test_cases ) / sizeof (test_cases [0 ])); i ++ ) {
1660+ ExpectIntEQ (wolfssl_local_IsValidFQDN (
1661+ test_cases [i ].str ,
1662+ test_cases [i ].str ? (word32 )strlen (test_cases [i ].str ) : 0 ),
1663+ test_cases [i ].is_FQDN );
1664+ if (! EXPECT_SUCCESS ()) {
1665+ fprintf (stderr , "wolfssl_local_IsValidFQDN() wrong result for "
1666+ "case %d \"%s\"\n" , i , test_cases [i ].str );
1667+ break ;
1668+ }
1669+ }
1670+
1671+ /* Additional corner cases (length & label-size boundaries) */
1672+ {
1673+ char buf [300 ];
1674+
1675+ /* 253 chars (max allowed), with 63 byte labels (max allowed) - valid */
1676+ memset (buf , 'a' , 251 );
1677+ for (i = 63 ; i < 251 ; i += 64 )
1678+ buf [i ] = '.' ;
1679+ buf [251 ] = '.' ;
1680+ buf [252 ] = 'b' ;
1681+ buf [253 ] = '\0' ;
1682+ ExpectIntEQ (wolfssl_local_IsValidFQDN (buf , (word32 )strlen (buf )), 1 );
1683+
1684+ /* 254 chars (one too long) - invalid */
1685+ memset (buf , 'a' , 252 );
1686+ for (i = 63 ; i < 251 ; i += 64 )
1687+ buf [i ] = '.' ;
1688+ buf [252 ] = '.' ;
1689+ buf [253 ] = 'b' ;
1690+ buf [254 ] = '\0' ;
1691+ ExpectIntEQ (wolfssl_local_IsValidFQDN (buf , (word32 )strlen (buf )), 0 );
1692+
1693+ /* 64-char label (one too long) */
1694+ memset (buf , 'a' , 64 );
1695+ buf [64 ] = '.' ;
1696+ buf [65 ] = 'c' ;
1697+ buf [66 ] = 'o' ;
1698+ buf [67 ] = 'm' ;
1699+ buf [68 ] = '\0' ;
1700+ ExpectIntEQ (wolfssl_local_IsValidFQDN (buf , (word32 )strlen (buf )), 0 );
1701+
1702+ /* Explicit nameSz == 0 (even with non-NULL pointer) */
1703+ ExpectIntEQ (wolfssl_local_IsValidFQDN ("example.com" , 0 ), 0 );
1704+ }
1705+
1706+ return EXPECT_RESULT ();
1707+ }
1708+
16131709int test_wolfSSL_X509_max_altnames (void )
16141710{
16151711 EXPECT_DECLS ;
0 commit comments