From 8fc961998706d3e8f18e9b6b096b583693d2f1b3 Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Thu, 18 Feb 2010 14:05:15 -0200 Subject: [PATCH] New SoupMessageFlag to report whether it has dealt with a trusted certificate https://bugzilla.gnome.org/show_bug.cgi?id=610374 --- libsoup/soup-message-io.c | 11 +++++++++++ libsoup/soup-message.c | 4 ++++ libsoup/soup-message.h | 7 ++++--- libsoup/soup-socket.c | 31 +++++++++++++++++++++++++++++++ libsoup/soup-socket.h | 17 +++++++++-------- 5 files changed, 59 insertions(+), 11 deletions(-) diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c index 73c8ae6..fc0e14d 100644 --- a/libsoup/soup-message-io.c +++ b/libsoup/soup-message-io.c @@ -342,6 +342,17 @@ read_metadata (SoupMessage *msg, gboolean to_blank) } } + if (soup_socket_is_ssl (io->sock)) { + gboolean trusted_certificate; + + g_object_get (io->sock, + SOUP_SOCKET_TRUSTED_CERTIFICATE, &trusted_certificate, + NULL); + + if (trusted_certificate) + soup_message_set_flags (msg, priv->msg_flags | SOUP_MESSAGE_CERTIFICATE_TRUSTED); + } + return TRUE; } diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index ded0198..7c0b802 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -1258,6 +1258,7 @@ soup_message_cleanup_response (SoupMessage *req) priv->decoders = g_slist_delete_link (priv->decoders, priv->decoders); } priv->msg_flags &= ~SOUP_MESSAGE_CONTENT_DECODED; + priv->msg_flags &= ~SOUP_MESSAGE_CERTIFICATE_TRUSTED; req->status_code = SOUP_STATUS_NONE; if (req->reason_phrase) { @@ -1283,6 +1284,9 @@ soup_message_cleanup_response (SoupMessage *req) * indicate that it has removed the Content-Encoding on a message (and * so headers such as Content-Length may no longer accurately describe * the body). + * @SOUP_MESSAGE_CERTIFICATE_TRUSTED: if %TRUE after an https response + * has been received, indicates that the server's SSL certificate is + * trusted according to the session's CA. * * Various flags that can be set on a #SoupMessage to alter its * behavior. diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h index 2638620..3f3ee14 100644 --- a/libsoup/soup-message.h +++ b/libsoup/soup-message.h @@ -105,11 +105,12 @@ SoupURI *soup_message_get_first_party (SoupMessage *msg); void soup_message_set_first_party (SoupMessage *msg, SoupURI *first_party); typedef enum { - SOUP_MESSAGE_NO_REDIRECT = (1 << 1), + SOUP_MESSAGE_NO_REDIRECT = (1 << 1), #ifndef LIBSOUP_DISABLE_DEPRECATED - SOUP_MESSAGE_OVERWRITE_CHUNKS = (1 << 3), + SOUP_MESSAGE_OVERWRITE_CHUNKS = (1 << 3), #endif - SOUP_MESSAGE_CONTENT_DECODED = (1 << 4) + SOUP_MESSAGE_CONTENT_DECODED = (1 << 4), + SOUP_MESSAGE_CERTIFICATE_TRUSTED = (1 << 5) } SoupMessageFlags; void soup_message_set_flags (SoupMessage *msg, diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index 2bbf22d..4f570a7 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -69,6 +69,7 @@ enum { PROP_SSL_STRICT, PROP_ASYNC_CONTEXT, PROP_TIMEOUT, + PROP_TRUSTED_CERTIFICATE, LAST_PROP }; @@ -83,6 +84,7 @@ typedef struct { guint timed_out:1; gpointer ssl_creds; gboolean ssl_strict; + gboolean trusted_certificate; GMainContext *async_context; GSource *watch_src; @@ -368,6 +370,21 @@ soup_socket_class_init (SoupSocketClass *socket_class) TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); /** + * SOUP_SOCKET_TRUSTED_CERTIFICATE: + * + * Alias for the #SoupSocket:trusted-certificate + * property. Notice that this property's value is only useful + * if the socket is for an SSL connection, and only reliable + * after some data has been transferred to or from it. + **/ + g_object_class_install_property ( + object_class, PROP_TRUSTED_CERTIFICATE, + g_param_spec_boolean (SOUP_SOCKET_TRUSTED_CERTIFICATE, + "Trusted Certificate", + "Whether the server certificate is trusted, if this is an SSL socket", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** * SOUP_SOCKET_ASYNC_CONTEXT: * * Alias for the #SoupSocket:async-context property. (The @@ -509,6 +526,9 @@ set_property (GObject *object, guint prop_id, case PROP_SSL_STRICT: priv->ssl_strict = g_value_get_boolean (value); break; + case PROP_TRUSTED_CERTIFICATE: + priv->trusted_certificate = g_value_get_boolean (value); + break; case PROP_ASYNC_CONTEXT: priv->async_context = g_value_get_pointer (value); if (priv->async_context) @@ -548,6 +568,9 @@ get_property (GObject *object, guint prop_id, case PROP_SSL_STRICT: g_value_set_boolean (value, priv->ssl_strict); break; + case PROP_TRUSTED_CERTIFICATE: + g_value_set_boolean (value, priv->trusted_certificate); + break; case PROP_ASYNC_CONTEXT: g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL); break; @@ -1011,6 +1034,12 @@ soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host, if (!ssl_chan) return FALSE; + /* This is optimistic, we will set this to false if we get a + * cert error from one of the I/O calls + */ + if (priv->ssl_creds) + priv->trusted_certificate = TRUE; + priv->iochannel = ssl_chan; g_io_channel_unref (real_chan); @@ -1245,6 +1274,7 @@ again: if (g_error_matches (my_err, SOUP_SSL_ERROR, SOUP_SSL_ERROR_CERTIFICATE) && !priv->ssl_strict) { + priv->trusted_certificate = FALSE; g_clear_error (&my_err); goto again; } @@ -1552,6 +1582,7 @@ again: if (g_error_matches (my_err, SOUP_SSL_ERROR, SOUP_SSL_ERROR_CERTIFICATE) && !priv->ssl_strict) { + priv->trusted_certificate = FALSE; g_clear_error (&my_err); goto again; } diff --git a/libsoup/soup-socket.h b/libsoup/soup-socket.h index 4106e86..2e039d9 100644 --- a/libsoup/soup-socket.h +++ b/libsoup/soup-socket.h @@ -40,14 +40,15 @@ typedef struct { void (*_libsoup_reserved4) (void); } SoupSocketClass; -#define SOUP_SOCKET_LOCAL_ADDRESS "local-address" -#define SOUP_SOCKET_REMOTE_ADDRESS "remote-address" -#define SOUP_SOCKET_FLAG_NONBLOCKING "non-blocking" -#define SOUP_SOCKET_IS_SERVER "is-server" -#define SOUP_SOCKET_SSL_CREDENTIALS "ssl-creds" -#define SOUP_SOCKET_SSL_STRICT "ssl-strict" -#define SOUP_SOCKET_ASYNC_CONTEXT "async-context" -#define SOUP_SOCKET_TIMEOUT "timeout" +#define SOUP_SOCKET_LOCAL_ADDRESS "local-address" +#define SOUP_SOCKET_REMOTE_ADDRESS "remote-address" +#define SOUP_SOCKET_FLAG_NONBLOCKING "non-blocking" +#define SOUP_SOCKET_IS_SERVER "is-server" +#define SOUP_SOCKET_SSL_CREDENTIALS "ssl-creds" +#define SOUP_SOCKET_SSL_STRICT "ssl-strict" +#define SOUP_SOCKET_TRUSTED_CERTIFICATE "trusted-certificate" +#define SOUP_SOCKET_ASYNC_CONTEXT "async-context" +#define SOUP_SOCKET_TIMEOUT "timeout" typedef void (*SoupSocketCallback) (SoupSocket *sock, guint status, -- 2.7.4