mbedtls_ssl_set_hostname tests: baseline
Test the current behavior.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index d01202f..7e6b052 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -64,6 +64,7 @@
#define DFL_ARC4 -1
#define DFL_SHA1 -1
#define DFL_AUTH_MODE -1
+#define DFL_SET_HOSTNAME 1
#define DFL_MFL_CODE MBEDTLS_SSL_MAX_FRAG_LEN_NONE
#define DFL_TRUNC_HMAC -1
#define DFL_RECSPLIT -1
@@ -380,6 +381,9 @@
#define USAGE2 \
" auth_mode=%%s default: (library default: none)\n" \
" options: none, optional, required\n" \
+ " set_hostname=%%s call mbedtls_ssl_set_hostname()?" \
+ " options: no, server_name, NULL\n" \
+ " default: server_name (but ignored if certs disabled)\n" \
USAGE_IO \
USAGE_KEY_OPAQUE \
USAGE_CA_CALLBACK \
@@ -473,6 +477,8 @@
int arc4; /* flag for arc4 suites support */
int allow_sha1; /* flag for SHA-1 support */
int auth_mode; /* verify mode for connection */
+ int set_hostname; /* call mbedtls_ssl_set_hostname()? */
+ /* 0=no, 1=yes, -1=NULL */
unsigned char mfl_code; /* code for maximum fragment length */
int trunc_hmac; /* negotiate truncated hmac or not */
int recsplit; /* enable record splitting? */
@@ -796,6 +802,7 @@
opt.arc4 = DFL_ARC4;
opt.allow_sha1 = DFL_SHA1;
opt.auth_mode = DFL_AUTH_MODE;
+ opt.set_hostname = DFL_SET_HOSTNAME;
opt.mfl_code = DFL_MFL_CODE;
opt.trunc_hmac = DFL_TRUNC_HMAC;
opt.recsplit = DFL_RECSPLIT;
@@ -1148,6 +1155,16 @@
} else {
goto usage;
}
+ } else if (strcmp(p, "set_hostname") == 0) {
+ if (strcmp(q, "no") == 0) {
+ opt.set_hostname = 0;
+ } else if (strcmp(q, "server_name") == 0) {
+ opt.set_hostname = 1;
+ } else if (strcmp(q, "NULL") == 0) {
+ opt.set_hostname = -1;
+ } else {
+ goto usage;
+ }
} else if (strcmp(p, "max_frag_len") == 0) {
if (strcmp(q, "512") == 0) {
opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_512;
@@ -1893,10 +1910,24 @@
}
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
- if ((ret = mbedtls_ssl_set_hostname(&ssl, opt.server_name)) != 0) {
- mbedtls_printf(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n",
- ret);
- goto exit;
+ switch (opt.set_hostname) {
+ case -1:
+ if ((ret = mbedtls_ssl_set_hostname(&ssl, NULL)) != 0) {
+ mbedtls_printf(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n",
+ ret);
+ goto exit;
+ }
+ break;
+ case 0:
+ /* Skip the call */
+ break;
+ default:
+ if ((ret = mbedtls_ssl_set_hostname(&ssl, opt.server_name)) != 0) {
+ mbedtls_printf(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n",
+ ret);
+ goto exit;
+ }
+ break;
}
#endif
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 784391e..0d25ab4 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -4650,6 +4650,145 @@
-c "! mbedtls_ssl_handshake returned" \
-c "SSL - No CA Chain is set, but required to operate"
+# The next few tests check what happens if the server has a valid certificate
+# that does not match its name (impersonation).
+
+run_test "Authentication: hostname match, client required" \
+ "$P_SRV" \
+ "$P_CLI auth_mode=required server_name=localhost debug_level=1" \
+ 0 \
+ -C "does not match with the expected CN" \
+ -C "x509_verify_cert() returned -" \
+ -C "! mbedtls_ssl_handshake returned" \
+ -C "X509 - Certificate verification failed"
+
+run_test "Authentication: hostname mismatch (wrong), client required" \
+ "$P_SRV" \
+ "$P_CLI auth_mode=required server_name=wrong-name debug_level=1" \
+ 1 \
+ -c "does not match with the expected CN" \
+ -c "x509_verify_cert() returned -" \
+ -c "! mbedtls_ssl_handshake returned" \
+ -c "X509 - Certificate verification failed"
+
+run_test "Authentication: hostname mismatch (empty), client required" \
+ "$P_SRV" \
+ "$P_CLI auth_mode=required server_name= debug_level=1" \
+ 1 \
+ -c "does not match with the expected CN" \
+ -c "x509_verify_cert() returned -" \
+ -c "! mbedtls_ssl_handshake returned" \
+ -c "X509 - Certificate verification failed"
+
+run_test "Authentication: hostname mismatch (truncated), client required" \
+ "$P_SRV" \
+ "$P_CLI auth_mode=required server_name=localhos debug_level=1" \
+ 1 \
+ -c "does not match with the expected CN" \
+ -c "x509_verify_cert() returned -" \
+ -c "! mbedtls_ssl_handshake returned" \
+ -c "X509 - Certificate verification failed"
+
+run_test "Authentication: hostname mismatch (last char), client required" \
+ "$P_SRV" \
+ "$P_CLI auth_mode=required server_name=localhoss debug_level=1" \
+ 1 \
+ -c "does not match with the expected CN" \
+ -c "x509_verify_cert() returned -" \
+ -c "! mbedtls_ssl_handshake returned" \
+ -c "X509 - Certificate verification failed"
+
+run_test "Authentication: hostname mismatch (trailing), client required" \
+ "$P_SRV" \
+ "$P_CLI auth_mode=required server_name=localhostt debug_level=1" \
+ 1 \
+ -c "does not match with the expected CN" \
+ -c "x509_verify_cert() returned -" \
+ -c "! mbedtls_ssl_handshake returned" \
+ -c "X509 - Certificate verification failed"
+
+run_test "Authentication: hostname mismatch, client optional" \
+ "$P_SRV" \
+ "$P_CLI auth_mode=optional server_name=wrong-name debug_level=1" \
+ 0 \
+ -c "does not match with the expected CN" \
+ -c "x509_verify_cert() returned -" \
+ -C "X509 - Certificate verification failed"
+
+run_test "Authentication: hostname mismatch, client none" \
+ "$P_SRV" \
+ "$P_CLI auth_mode=none server_name=wrong-name debug_level=1" \
+ 0 \
+ -C "does not match with the expected CN" \
+ -C "x509_verify_cert() returned -" \
+ -C "X509 - Certificate verification failed"
+
+run_test "Authentication: hostname null, client required" \
+ "$P_SRV" \
+ "$P_CLI auth_mode=required set_hostname=NULL debug_level=1" \
+ 0 \
+ -C "does not match with the expected CN" \
+ -C "x509_verify_cert() returned -" \
+ -C "! mbedtls_ssl_handshake returned" \
+ -C "X509 - Certificate verification failed"
+
+run_test "Authentication: hostname null, client optional" \
+ "$P_SRV" \
+ "$P_CLI auth_mode=optional set_hostname=NULL debug_level=1" \
+ 0 \
+ -C "does not match with the expected CN" \
+ -C "x509_verify_cert() returned -" \
+ -C "X509 - Certificate verification failed"
+
+run_test "Authentication: hostname null, client none" \
+ "$P_SRV" \
+ "$P_CLI auth_mode=none set_hostname=NULL debug_level=1" \
+ 0 \
+ -C "does not match with the expected CN" \
+ -C "x509_verify_cert() returned -" \
+ -C "X509 - Certificate verification failed"
+
+run_test "Authentication: hostname unset, client required" \
+ "$P_SRV" \
+ "$P_CLI auth_mode=required set_hostname=no debug_level=1" \
+ 0 \
+ -C "does not match with the expected CN" \
+ -C "x509_verify_cert() returned -" \
+ -C "! mbedtls_ssl_handshake returned" \
+ -C "X509 - Certificate verification failed"
+
+run_test "Authentication: hostname unset, client optional" \
+ "$P_SRV" \
+ "$P_CLI auth_mode=optional set_hostname=no debug_level=1" \
+ 0 \
+ -C "does not match with the expected CN" \
+ -C "x509_verify_cert() returned -" \
+ -C "X509 - Certificate verification failed"
+
+run_test "Authentication: hostname unset, client none" \
+ "$P_SRV" \
+ "$P_CLI auth_mode=none set_hostname=no debug_level=1" \
+ 0 \
+ -C "does not match with the expected CN" \
+ -C "x509_verify_cert() returned -" \
+ -C "X509 - Certificate verification failed"
+
+run_test "Authentication: hostname unset, client default, server picks cert" \
+ "$P_SRV force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8" \
+ "$P_CLI psk=73776f726466697368 psk_identity=foo set_hostname=no debug_level=1" \
+ 0 \
+ -C "does not match with the expected CN" \
+ -C "x509_verify_cert() returned -" \
+ -C "X509 - Certificate verification failed"
+
+run_test "Authentication: hostname unset, client default, server picks PSK" \
+ "$P_SRV force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8 psk=73776f726466697368 psk_identity=foo" \
+ "$P_CLI psk=73776f726466697368 psk_identity=foo set_hostname=no debug_level=1" \
+ 0 \
+ -C "does not match with the expected CN" \
+ -C "x509_verify_cert() returned -" \
+ -C "X509 - Certificate verification failed"
+
# The purpose of the next two tests is to test the client's behaviour when receiving a server
# certificate with an unsupported elliptic curve. This should usually not happen because
# the client informs the server about the supported curves - it does, though, in the