diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index f009a3169b..fa61c6cb1f 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -68,6 +68,7 @@ int main(void) #define DFL_MAX_VERSION -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 @@ -403,6 +404,9 @@ int main(void) #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 \ @@ -505,6 +509,8 @@ struct options { int max_version; /* maximum protocol version accepted */ 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? */ @@ -953,6 +959,7 @@ int main(int argc, char *argv[]) opt.max_version = DFL_MAX_VERSION; 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; @@ -1344,6 +1351,16 @@ usage: } 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; @@ -2052,10 +2069,24 @@ usage: #endif /* MBEDTLS_SSL_DTLS_SRTP */ #if defined(MBEDTLS_SSL_HANDSHAKE_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 ce661fcc83..e541a81983 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -5938,6 +5938,163 @@ run_test "Authentication: server goodcert, client none, no trusted CA (1.2)" -C "X509 - Certificate verification failed" \ -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, 1.2" \ + "$P_SRV force_version=tls12 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" + +requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED +run_test "Authentication: hostname unset, client default, server picks cert, 1.3" \ + "$P_SRV force_version=tls13 tls13_kex_modes=ephemeral" \ + "$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, 1.2" \ + "$P_SRV force_version=tls12 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" + +requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED +run_test "Authentication: hostname unset, client default, server picks PSK, 1.3" \ + "$P_SRV force_version=tls13 tls13_kex_modes=psk 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