Perform SSL hostname validation
SSL stream can now verify that the remote server hostname matches the
the certificate Common Name or Subject Alternative Name.
This behavior can be disabled/enabled at the http_client scope using the
new function:
axis2_http_client_set_validate_ssl_hostname
There is also an associated getter:
axis2_http_client_get_validate_ssl_hostname
For backwards compatibility, this behavior is disabled by default.
However, this will change to being enabled by default in a future
release.
When enabled, this functionality mitigates CVE-2012-6107.
JIRA: AXIS2C-1619
diff --git a/include/axis2_http_client.h b/include/axis2_http_client.h
index a7b2dbc..edbfc3f 100644
--- a/include/axis2_http_client.h
+++ b/include/axis2_http_client.h
@@ -271,6 +271,18 @@
axis2_http_client_t * client,
const axutil_env_t * env);
+ AXIS2_EXTERN axis2_status_t AXIS2_CALL
+ axis2_http_client_set_validate_ssl_hostname(
+ axis2_http_client_t * client,
+ const axutil_env_t * env,
+ axis2_bool_t validate_host);
+
+ AXIS2_EXTERN axis2_bool_t AXIS2_CALL
+ axis2_http_client_get_validate_ssl_hostname(
+ const axis2_http_client_t * client,
+ const axutil_env_t * env);
+
+
/** @} */
#ifdef __cplusplus
diff --git a/src/core/transport/http/sender/http_client.c b/src/core/transport/http/sender/http_client.c
index eff988e..6be601b 100644
--- a/src/core/transport/http/sender/http_client.c
+++ b/src/core/transport/http/sender/http_client.c
@@ -52,6 +52,7 @@
axis2_char_t *key_file;
axis2_char_t *req_body;
int req_body_size;
+ axis2_bool_t validate_ssl_hostname;
/* These are for mtom case */
axutil_array_list_t *mime_parts;
@@ -97,6 +98,11 @@
http_client->doing_mtom = AXIS2_FALSE;
http_client->mtom_sending_callback_name = NULL;
+ /* TODO default this to false for now, but this should default
+ * to true in a future version (after 1.8)
+ */
+ http_client->validate_ssl_hostname = AXIS2_FALSE;
+
return http_client;
}
@@ -277,7 +283,8 @@
if(!client->data_stream)
client->data_stream =
axutil_stream_create_ssl(env, client->sockfd, axis2_http_client_get_server_cert(client,
- env), axis2_http_client_get_key_file(client, env), ssl_pp);
+ env), axis2_http_client_get_key_file(client, env), ssl_pp,
+ client->validate_ssl_hostname == AXIS2_TRUE ? host : NULL);
#else
axutil_network_handler_close_socket(env, client->sockfd);
client->sockfd = -1;
@@ -1052,3 +1059,22 @@
}
return AXIS2_SUCCESS;
}
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axis2_http_client_set_validate_ssl_hostname(
+ axis2_http_client_t * client,
+ const axutil_env_t * env,
+ axis2_bool_t validate_ssl_hostname)
+{
+ client->validate_ssl_hostname = validate_ssl_hostname;
+ return AXIS2_SUCCESS;
+}
+
+AXIS2_EXTERN axis2_bool_t AXIS2_CALL
+axis2_http_client_get_validate_ssl_hostname(
+ const axis2_http_client_t * client,
+ const axutil_env_t * env)
+{
+ return client->validate_ssl_hostname;
+}
+
diff --git a/src/core/transport/http/sender/ssl/ssl_stream.c b/src/core/transport/http/sender/ssl/ssl_stream.c
index 50272c5..e3d9e16 100644
--- a/src/core/transport/http/sender/ssl/ssl_stream.c
+++ b/src/core/transport/http/sender/ssl/ssl_stream.c
@@ -69,7 +69,8 @@
axis2_socket_t socket,
axis2_char_t * server_cert,
axis2_char_t * key_file,
- axis2_char_t * ssl_pp)
+ axis2_char_t * ssl_pp,
+ axis2_char_t * host)
{
ssl_stream_impl_t *stream_impl = NULL;
@@ -96,7 +97,7 @@
return NULL;
}
stream_impl->ssl = axis2_ssl_utils_initialize_ssl(env, stream_impl->ctx,
- stream_impl->socket);
+ stream_impl->socket, host);
if (!stream_impl->ssl)
{
AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_SSL_ENGINE, AXIS2_FAILURE);
diff --git a/src/core/transport/http/sender/ssl/ssl_stream.h b/src/core/transport/http/sender/ssl/ssl_stream.h
index 7d1ef09..2df504d 100644
--- a/src/core/transport/http/sender/ssl/ssl_stream.h
+++ b/src/core/transport/http/sender/ssl/ssl_stream.h
@@ -38,7 +38,8 @@
axis2_socket_t socket,
axis2_char_t * server_cert,
axis2_char_t * key_file,
- axis2_char_t * ssl_pp);
+ axis2_char_t * ssl_pp,
+ axis2_char_t * host);
void AXIS2_CALL
axis2_ssl_stream_free(
diff --git a/src/core/transport/http/sender/ssl/ssl_utils.c b/src/core/transport/http/sender/ssl/ssl_utils.c
index a904883..8f86e2d 100644
--- a/src/core/transport/http/sender/ssl/ssl_utils.c
+++ b/src/core/transport/http/sender/ssl/ssl_utils.c
@@ -171,7 +171,8 @@
axis2_ssl_utils_initialize_ssl(
const axutil_env_t * env,
SSL_CTX * ctx,
- axis2_socket_t socket)
+ axis2_socket_t socket,
+ axis2_char_t * host)
{
SSL *ssl = NULL;
BIO *sbio = NULL;
@@ -242,6 +243,17 @@
if (ASN1_STRING_cmp(peer_sig, client_sig) == 0)
{
+ /* if the caller passed a hostname, verify it against the cert */
+ if (host) {
+ if (X509_check_host(peer_cert, host, strlen(host), 0, NULL) == 1) {
+ AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI,
+ "[ssl client] peer name matches certificate CN/SAN");
+ } else {
+ AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI,
+ "[ssl client] peer name does not match certificate CN/SAN");
+ return NULL;
+ }
+ }
if (peer_cert)
{
X509_free(peer_cert);
diff --git a/src/core/transport/http/sender/ssl/ssl_utils.h b/src/core/transport/http/sender/ssl/ssl_utils.h
index 26dc16b..29f00ad 100644
--- a/src/core/transport/http/sender/ssl/ssl_utils.h
+++ b/src/core/transport/http/sender/ssl/ssl_utils.h
@@ -41,7 +41,8 @@
axis2_ssl_utils_initialize_ssl(
const axutil_env_t * env,
SSL_CTX * ctx,
- axis2_socket_t socket);
+ axis2_socket_t socket,
+ axis2_char_t * host);
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axis2_ssl_utils_cleanup_ssl(