Merge pull request #10419 from douzzer/20260506-check_domain_name-local_IsValidFQDN

20260506-check_domain_name-local_IsValidFQDN
This commit is contained in:
Sean Parkinson
2026-05-07 16:59:04 +10:00
committed by GitHub
5 changed files with 101 additions and 93 deletions
+16 -13
View File
@@ -29,11 +29,6 @@ elif [ "${AM_BWRAPPED-}" != "yes" ]; then
unset AM_BWRAPPED
fi
# Workaround to not pollute the certs folder with our files that can impact other tests
RUNNING_DIR=$(mktemp -d)
cp -rp . $RUNNING_DIR/.
cd $RUNNING_DIR
revocation_code="-361"
revocation_code_openssl="23"
exit_code=1
@@ -49,13 +44,9 @@ server_pid=$no_pid
# also let's add some randomness by adding pid in case multiple 'make check's
# per source tree
ready_file=`pwd`/wolfssl_crl_ready$$
CERT_DIR=certs
remove_ready_file() {
if test -e "$ready_file"; then
echo -e "removing existing ready file"
rm "$ready_file"
fi
rm -f "$ready_file"
}
# trap this function so if user aborts with ^C or other kill signal we still
@@ -84,10 +75,22 @@ trap abort_trap INT TERM
# instead use "exit <some value>" and this function will run automatically
restore_file_system() {
remove_ready_file
cd / && rm -rf "$RUNNING_DIR"
if [ -n "$TMP_DIR" ]; then
rm -rf "$TMP_DIR"
fi
}
trap restore_file_system EXIT
# Workaround to not pollute the certs folder with our files that can impact other tests
TMP_DIR=$(mktemp -d) || exit $?
SRC_DIR="$PWD"
pushd "$TMP_DIR" || exit $?
if ! cp -R --symbolic-link "${SRC_DIR}/certs" . 2>/dev/null; then
cp -pR "${SRC_DIR}/certs" . || exit $?
fi
popd || exit $?
CERT_DIR="${TMP_DIR}/certs"
run_test() {
echo -e "\nStarting example server for crl test...\n"
@@ -121,7 +124,7 @@ run_test() {
crl_port="$(cat "$ready_file")"
# starts client on crl_port and captures the output from client
capture_out=$(./examples/client/client -p $crl_port 2>&1)
capture_out=$(cd "${CERT_DIR}/.." && "${SRC_DIR}/examples/client/client" -p $crl_port 2>&1)
client_result=$?
wait $server_pid
@@ -187,7 +190,7 @@ run_hashdir_test() {
crl_port="$(cat "$ready_file")"
# starts client on crl_port and captures the output from client
capture_out=$(./examples/client/client -p $crl_port -9 2>&1)
capture_out=$(cd "${CERT_DIR}/.." && "${SRC_DIR}/examples/client/client" -p $crl_port -9 2>&1)
client_result=$?
wait $server_pid
+83
View File
@@ -7712,12 +7712,86 @@ int wolfSSL_Cleanup(void)
return ret;
}
/* Returns 1 if name is a syntactically valid DNS FQDN per RFC 952/1123.
*
* Rules enforced:
* - Total effective length (excluding optional trailing dot) in [1, 253]
* - Each label is 1-63 octets of [a-zA-Z0-9-], with _ allowed in all but
* the last label.
* - No label starts or ends with '-'
* - At least two labels (single-label names are not "fully qualified")
* - Final label (TLD) contains at least one letter (rejects all-numeric
* strings that could be confused with IPv4 literals, and matches the
* ICANN constraint that TLDs are alphabetic)
* - Optional trailing dot is accepted (absolute FQDN form)
* - Internationalized names are valid in their ACE/punycode (xn--) form
*/
int wolfssl_local_IsValidFQDN(const char* name, word32 nameSz)
{
word32 i;
int labelLen = 0;
int labelCount = 0;
int curLabelHasAlpha = 0;
int curLabelHasUnderscore = 0;
if (name == NULL || nameSz == 0)
return 0;
/* Strip a single optional trailing dot before measuring. "example.com."
* is the absolute form of the same FQDN.
*/
if (name[nameSz - 1] == '.')
--nameSz;
if (nameSz < 1 || nameSz > 253)
return 0;
for (i = 0; i < nameSz; i++) {
byte c = (byte)name[i];
if (c == '.') {
if (labelLen == 0 || name[i - 1] == '-')
return 0;
++labelCount;
labelLen = 0;
curLabelHasAlpha = 0;
curLabelHasUnderscore = 0;
continue;
}
if (++labelLen > 63)
return 0;
if (c == '-') {
if (labelLen == 1)
return 0;
}
else if (((c | 0x20) >= 'a') && ((c | 0x20) <= 'z')) {
curLabelHasAlpha = 1;
}
else if (c == '_') {
curLabelHasUnderscore = 1;
}
else if ((c < '0') || (c > '9')) {
return 0;
}
}
/* Final label (no trailing dot in the effective range to close it) */
if ((labelLen == 0) || (name[nameSz - 1] == '-') || curLabelHasUnderscore)
return 0;
++labelCount;
return ((labelCount > 1) && curLabelHasAlpha);
}
/* call before SSL_connect, if verifying will add name check to
date check and signature check */
WOLFSSL_ABI
int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn)
{
size_t dn_len;
WOLFSSL_ENTER("wolfSSL_check_domain_name");
if (ssl == NULL || dn == NULL) {
@@ -7725,6 +7799,15 @@ int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn)
return WOLFSSL_FAILURE;
}
dn_len = XSTRLEN(dn);
if ((! wolfssl_local_IsValidFQDN(dn, (word32)dn_len)) &&
(XSTRCMP(dn, "localhost") != 0))
{
WOLFSSL_MSG("Bad function argument: fails wolfssl_local_IsValidFQDN");
return WOLFSSL_FAILURE;
}
if (ssl->buffers.domainName.buffer)
XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
-75
View File
@@ -18075,81 +18075,6 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
#endif /* IGNORE_NAME_CONSTRAINTS */
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
/* Returns 1 if name is a syntactically valid DNS FQDN per RFC 952/1123.
*
* Rules enforced:
* - Total effective length (excluding optional trailing dot) in [1, 253]
* - Each label is 1-63 octets of [a-zA-Z0-9-], with _ allowed in all but
* the last label.
* - No label starts or ends with '-'
* - At least two labels (single-label names are not "fully qualified")
* - Final label (TLD) contains at least one letter (rejects all-numeric
* strings that could be confused with IPv4 literals, and matches the
* ICANN constraint that TLDs are alphabetic)
* - Optional trailing dot is accepted (absolute FQDN form)
* - Internationalized names are valid in their ACE/punycode (xn--) form
*/
int wolfssl_local_IsValidFQDN(const char* name, word32 nameSz)
{
word32 i;
int labelLen = 0;
int labelCount = 0;
int curLabelHasAlpha = 0;
int curLabelHasUnderscore = 0;
if (name == NULL || nameSz == 0)
return 0;
/* Strip a single optional trailing dot before measuring. "example.com."
* is the absolute form of the same FQDN.
*/
if (name[nameSz - 1] == '.')
--nameSz;
if (nameSz < 1 || nameSz > 253)
return 0;
for (i = 0; i < nameSz; i++) {
byte c = (byte)name[i];
if (c == '.') {
if (labelLen == 0 || name[i - 1] == '-')
return 0;
++labelCount;
labelLen = 0;
curLabelHasAlpha = 0;
curLabelHasUnderscore = 0;
continue;
}
if (++labelLen > 63)
return 0;
if (c == '-') {
if (labelLen == 1)
return 0;
}
else if (((c | 0x20) >= 'a') && ((c | 0x20) <= 'z')) {
curLabelHasAlpha = 1;
}
else if (c == '_') {
curLabelHasUnderscore = 1;
}
else if ((c < '0') || (c > '9')) {
return 0;
}
}
/* Final label (no trailing dot in the effective range to close it) */
if ((labelLen == 0) || (name[nameSz - 1] == '-') || curLabelHasUnderscore)
return 0;
++labelCount;
return ((labelCount > 1) && curLabelHasAlpha);
}
#endif /* !WOLFCRYPT_ONLY && !NO_CERTS */
#ifdef WOLFSSL_ASN_TEMPLATE
#if defined(WOLFSSL_SEP) || defined(WOLFSSL_FPKI)
/* ASN.1 template for OtherName of an X.509 certificate.
+2
View File
@@ -3395,6 +3395,8 @@ WOLFSSL_API int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx,
/* call before SSL_connect, if verifying will add name check to
date check and signature check */
WOLFSSL_ABI WOLFSSL_API int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn);
WOLFSSL_TEST_VIS int wolfssl_local_IsValidFQDN(const char* name,
word32 nameSz);
/* call before SSL_connect, if verifying will add IP address check to
date check and signature check */
WOLFSSL_ABI WOLFSSL_API int wolfSSL_check_ip_address(WOLFSSL* ssl, const char* ipaddr);
-5
View File
@@ -3179,11 +3179,6 @@ WOLFSSL_TEST_VIS int wolfssl_local_MatchIpSubnet(const byte* ip, int ipSz,
int constraintSz);
#endif
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
WOLFSSL_TEST_VIS int wolfssl_local_IsValidFQDN(const char* name,
word32 nameSz);
#endif
#if ((defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT)) \
|| (defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_IMPORT)) \
|| (defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)) \