summaryrefslogtreecommitdiff
path: root/libsoup/soup-socket.c
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2011-08-07 13:02:51 -0400
committerDan Winship <danw@gnome.org>2011-08-07 13:07:09 -0400
commit5ddafe9abc8b594016f401c0b53a481e706e74c6 (patch)
tree68d1e61ad23c7f61db14d78596369191547b7d46 /libsoup/soup-socket.c
parentca6f8d53ab3dbbfee1cfb56d080f44afc4b0e5b4 (diff)
downloadlibsoup-5ddafe9abc8b594016f401c0b53a481e706e74c6.tar.gz
Default to TLS for https connections, and fall back to SSLv3 on failure
Rather than always using SSLv3, try proper TLS+extensions first, and fall back to SSLv3-without-extensions if that gives an error that looks like it might mean "broken SSLv3-only server". Use SoupSessionHost to record the fallback status for a host. https://bugzilla.gnome.org/show_bug.cgi?id=581342
Diffstat (limited to 'libsoup/soup-socket.c')
-rw-r--r--libsoup/soup-socket.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c
index 935b7619..a4d9f541 100644
--- a/libsoup/soup-socket.c
+++ b/libsoup/soup-socket.c
@@ -54,6 +54,7 @@ enum {
PROP_IS_SERVER,
PROP_SSL_CREDENTIALS,
PROP_SSL_STRICT,
+ PROP_SSL_FALLBACK,
PROP_ASYNC_CONTEXT,
PROP_TIMEOUT,
PROP_TRUSTED_CERTIFICATE,
@@ -75,6 +76,7 @@ typedef struct {
guint non_blocking:1;
guint is_server:1;
guint ssl_strict:1;
+ guint ssl_fallback:1;
guint ssl_ca_in_creds:1;
guint clean_dispose:1;
gpointer ssl_creds;
@@ -353,7 +355,7 @@ soup_socket_class_init (SoupSocketClass *socket_class)
/**
* SOUP_SOCKET_SSL_STRICT:
*
- * Alias for the #SoupSocket:ignore-ssl-cert-errors property.
+ * Alias for the #SoupSocket:ssl-strict property.
**/
g_object_class_install_property (
object_class, PROP_SSL_STRICT,
@@ -363,6 +365,18 @@ soup_socket_class_init (SoupSocketClass *socket_class)
TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
/**
+ * SOUP_SOCKET_SSL_FALLBACK:
+ *
+ * Alias for the #SoupSocket:ssl-fallback property.
+ **/
+ g_object_class_install_property (
+ object_class, PROP_SSL_FALLBACK,
+ g_param_spec_boolean (SOUP_SOCKET_SSL_FALLBACK,
+ "SSLv3 fallback",
+ "Use SSLv3 instead of TLS (client-side only)",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ /**
* SOUP_SOCKET_TRUSTED_CERTIFICATE:
*
* Alias for the #SoupSocket:trusted-certificate
@@ -484,6 +498,9 @@ set_property (GObject *object, guint prop_id,
case PROP_SSL_STRICT:
priv->ssl_strict = g_value_get_boolean (value);
break;
+ case PROP_SSL_FALLBACK:
+ priv->ssl_fallback = g_value_get_boolean (value);
+ break;
case PROP_ASYNC_CONTEXT:
priv->async_context = g_value_get_pointer (value);
if (priv->async_context)
@@ -528,6 +545,9 @@ get_property (GObject *object, guint prop_id,
case PROP_SSL_STRICT:
g_value_set_boolean (value, priv->ssl_strict);
break;
+ case PROP_SSL_FALLBACK:
+ g_value_set_boolean (value, priv->ssl_fallback);
+ break;
case PROP_TRUSTED_CERTIFICATE:
g_value_set_boolean (value, priv->tls_errors == 0);
break;
@@ -935,7 +955,7 @@ soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host,
"server-identity", identity,
"use-system-certdb", FALSE,
"require-close-notify", FALSE,
- "use-ssl3", TRUE,
+ "use-ssl3", priv->ssl_fallback,
NULL);
g_object_unref (identity);
@@ -979,12 +999,19 @@ soup_socket_handshake_sync (SoupSocket *sock,
GCancellable *cancellable)
{
SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
+ GError *error = NULL;
if (g_tls_connection_handshake (G_TLS_CONNECTION (priv->conn),
- cancellable, NULL))
+ cancellable, &error))
return SOUP_STATUS_OK;
- else
+ else if (!priv->ssl_fallback &&
+ g_error_matches (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS)) {
+ g_error_free (error);
+ return SOUP_STATUS_TLS_FAILED;
+ } else {
+ g_error_free (error);
return SOUP_STATUS_SSL_FAILED;
+ }
}
static void
@@ -992,16 +1019,21 @@ handshake_async_ready (GObject *source, GAsyncResult *result, gpointer user_data
{
SoupSocketAsyncConnectData *data = user_data;
SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (data->sock);
+ GError *error = NULL;
guint status;
if (priv->async_context)
g_main_context_pop_thread_default (priv->async_context);
if (g_tls_connection_handshake_finish (G_TLS_CONNECTION (priv->conn),
- result, NULL))
+ result, &error))
status = SOUP_STATUS_OK;
+ else if (!priv->ssl_fallback &&
+ g_error_matches (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS))
+ status = SOUP_STATUS_TLS_FAILED;
else
status = SOUP_STATUS_SSL_FAILED;
+ g_clear_error (&error);
data->callback (data->sock, status, data->user_data);
g_object_unref (data->sock);