belatedly pull up changes from gnome-2-10 branch
authorDan Winship <danw@src.gnome.org>
Mon, 11 Apr 2005 15:13:06 +0000 (15:13 +0000)
committerDan Winship <danw@src.gnome.org>
Mon, 11 Apr 2005 15:13:06 +0000 (15:13 +0000)
ChangeLog
libsoup/soup-connection.c
libsoup/soup-gnutls.c
libsoup/soup-socket.c
libsoup/soup-socket.h

index 14feeba..838706e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2005-03-09  Dan Winship  <danw@novell.com>
+
+       * libsoup/soup-gnutls.c (soup_gnutls_read): return G_IO_STATUS_EOF
+       if gnutls returns 0. [#73352]
+       (verify_certificate): put an #ifdef around
+       GNUTLS_CERT_NOT_TRUSTED so it works with gnutls 1.2.x. [#57811]
+
 2005-01-08  Not Zed  <NotZed@Ximian.com>
 
        ** See ximian bug #70323.
@@ -5,6 +12,30 @@
        * libsoup/soup-connection-ntlm.c: replace all unsigned long/long
        types with guint32, as the code needs 32 bit longs.
 
+2004-10-20  Dan Winship  <danw@novell.com>
+
+       * libsoup/soup-gnutls.c: Commit the alleged changes from the 10-06
+       commit, which somehow did not actually get committed then.
+
+       * libsoup/soup-connection.c (SoupConnectionPrivate): add a flag
+       indicating whether or not the connection is connected.
+       (tunnel_connect_finished): If successful, set connected. If the
+       server returns a 3xx response, translate it to 407 (under the
+       assumption that it's trying to redirect us to an HTML login page,
+       as in bug 68531). Use soup_socket_start_proxy_ssl() rather than
+       soup_socket_start_ssl().
+       (socket_connect_result, soup_connection_connect_sync): If
+       successful, set connected
+       (soup_connection_disconnect): Don't emit "disconnected" if we
+       aren't yet connected, or the message that was waiting for this
+       connection may get stranded in the queue. (also part of 68531)
+
+       * libsoup/soup-socket.c (soup_socket_start_proxy_ssl): New, starts
+       SSL and lets the caller pass the expected hostname. Fixes a
+       problem where SSL certification validation would always fail if
+       you used a proxy, because it was comparing the cert against the
+       proxy's hostname. (68583)
+
 2004-10-06  Dan Winship  <danw@novell.com>
 
        * libsoup/soup-ssl.h (SoupSocketError): add
index 3129bb7..17676f9 100644 (file)
@@ -47,7 +47,7 @@ struct SoupConnectionPrivate {
 
        SoupMessage *cur_req;
        time_t       last_used;
-       gboolean     in_use;
+       gboolean     connected, in_use;
 };
 
 #define PARENT_TYPE G_TYPE_OBJECT
@@ -355,8 +355,14 @@ tunnel_connect_finished (SoupMessage *msg, gpointer user_data)
        clear_current_request (conn);
 
        if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
-               if (!soup_socket_start_ssl (conn->priv->socket))
+               if (soup_socket_start_proxy_ssl (conn->priv->socket,
+                                                conn->priv->origin_uri->host))
+                       conn->priv->connected = TRUE;
+               else
                        status = SOUP_STATUS_SSL_FAILED;
+       } else if (SOUP_STATUS_IS_REDIRECTION (status)) {
+               /* Oops, the proxy thinks we're a web browser. */
+               status = SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED;
        }
 
        g_signal_emit (conn, signals[CONNECT_RESULT], 0,
@@ -428,6 +434,8 @@ socket_connect_result (SoupSocket *sock, guint status, gpointer user_data)
                return;
        }
 
+       conn->priv->connected = TRUE;
+
  done:
        g_signal_emit (conn, signals[CONNECT_RESULT], 0,
                       proxified_status (conn, status));
@@ -522,7 +530,9 @@ soup_connection_connect_sync (SoupConnection *conn)
                g_object_unref (connect_msg);
        }
 
-       if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
+       if (SOUP_STATUS_IS_SUCCESSFUL (status))
+               conn->priv->connected = TRUE;
+       else {
        fail:
                if (conn->priv->socket) {
                        g_object_unref (conn->priv->socket);
@@ -556,6 +566,12 @@ soup_connection_disconnect (SoupConnection *conn)
        soup_socket_disconnect (conn->priv->socket);
        g_object_unref (conn->priv->socket);
        conn->priv->socket = NULL;
+
+       /* Don't emit "disconnected" if we aren't yet connected */
+       if (!conn->priv->connected)
+               return;
+
+       conn->priv->connected = FALSE;
        g_signal_emit (conn, signals[DISCONNECTED], 0);
 
        if (!conn->priv->cur_req ||
index 4de1ea1..4d41b59 100644 (file)
@@ -49,32 +49,42 @@ typedef struct {
 } SoupGNUTLSChannel;
 
 static gboolean
-verify_certificate (gnutls_session session, const char *hostname)
+verify_certificate (gnutls_session session, const char *hostname, GError **err)
 {
        int status;
 
        status = gnutls_certificate_verify_peers (session);
 
        if (status == GNUTLS_E_NO_CERTIFICATE_FOUND) {
-               g_warning ("No certificate was sent.");
+               g_set_error (err, SOUP_SSL_ERROR,
+                            SOUP_SSL_ERROR_CERTIFICATE,
+                            "No SSL certificate was sent.");
                return FALSE;
        }
 
        if (status & GNUTLS_CERT_INVALID ||
+#ifdef GNUTLS_CERT_NOT_TRUSTED
            status & GNUTLS_CERT_NOT_TRUSTED ||
+#endif
            status & GNUTLS_CERT_REVOKED)
        {
-               g_warning ("The certificate is not trusted.");
+               g_set_error (err, SOUP_SSL_ERROR,
+                            SOUP_SSL_ERROR_CERTIFICATE,
+                            "The SSL certificate is not trusted.");
                return FALSE;
        }
 
        if (gnutls_certificate_expiration_time_peers (session) < time (0)) {
-               g_warning ("The certificate has expired.");
+               g_set_error (err, SOUP_SSL_ERROR,
+                            SOUP_SSL_ERROR_CERTIFICATE,
+                            "The SSL certificate has expired.");
                return FALSE;
        }
 
        if (gnutls_certificate_activation_time_peers (session) > time (0)) {
-               g_warning ("The certificate is not yet activated.");
+               g_set_error (err, SOUP_SSL_ERROR,
+                            SOUP_SSL_ERROR_CERTIFICATE,
+                            "The SSL certificate is not yet activated.");
                return FALSE;
        }
 
@@ -84,7 +94,9 @@ verify_certificate (gnutls_session session, const char *hostname)
                gnutls_x509_crt cert;
 
                if (gnutls_x509_crt_init (&cert) < 0) {
-                       g_warning ("Error initializing certificate.");
+                       g_set_error (err, SOUP_SSL_ERROR,
+                                    SOUP_SSL_ERROR_CERTIFICATE,
+                                    "Error initializing SSL certificate.");
                        return FALSE;
                }
       
@@ -92,22 +104,28 @@ verify_certificate (gnutls_session session, const char *hostname)
                        session, &cert_list_size);
 
                if (cert_list == NULL) {
-                       g_warning ("No certificate was found.");
+                       g_set_error (err, SOUP_SSL_ERROR,
+                                    SOUP_SSL_ERROR_CERTIFICATE,
+                                    "No SSL certificate was found.");
                        return FALSE;
                }
 
                if (gnutls_x509_crt_import (cert, &cert_list[0],
                                            GNUTLS_X509_FMT_DER) < 0) {
-                       g_warning ("The certificate could not be parsed.");
+                       g_set_error (err, SOUP_SSL_ERROR,
+                                    SOUP_SSL_ERROR_CERTIFICATE,
+                                    "The SSL certificate could not be parsed.");
                        return FALSE;
                }
 
                if (!gnutls_x509_crt_check_hostname (cert, hostname)) {
-                       g_warning ("The certificate does not match hostname.");
+                       g_set_error (err, SOUP_SSL_ERROR,
+                                    SOUP_SSL_ERROR_CERTIFICATE,
+                                    "The SSL certificate does not match the hostname.");
                        return FALSE;
                }
        }
-   
+
        return TRUE;
 }
 
@@ -135,15 +153,9 @@ do_handshake (SoupGNUTLSChannel *chan, GError **err)
                return G_IO_STATUS_ERROR;
        }
 
-       if (chan->type == SOUP_SSL_TYPE_CLIENT &&
-           chan->cred->have_ca_file) {
-               if (!verify_certificate (chan->session, chan->hostname)) {
-                       g_set_error (err, G_IO_CHANNEL_ERROR,
-                                    G_IO_CHANNEL_ERROR_FAILED,
-                                    "Unable to verify certificate");
-                       return G_IO_STATUS_ERROR;
-               }
-       }
+       if (chan->type == SOUP_SSL_TYPE_CLIENT && chan->cred->have_ca_file &&
+           !verify_certificate (chan->session, chan->hostname, err))
+               return G_IO_STATUS_ERROR;
 
        return G_IO_STATUS_NORMAL;
 }
@@ -188,7 +200,7 @@ soup_gnutls_read (GIOChannel   *channel,
        } else {
                *bytes_read = result;
 
-               return G_IO_STATUS_NORMAL;
+               return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
        }
 }
 
index 2fde20b..d1de93e 100644 (file)
@@ -600,14 +600,29 @@ soup_socket_listen (SoupSocket *sock, SoupAddress *local_addr)
 gboolean
 soup_socket_start_ssl (SoupSocket *sock)
 {
+       return soup_socket_start_proxy_ssl (sock, soup_address_get_name (sock->priv->remote_addr));
+}
+       
+/**
+ * soup_socket_start_proxy_ssl:
+ * @sock: the socket
+ * @ssl_host: hostname of the SSL server
+ *
+ * Starts using SSL on @socket, expecting to find a host named
+ * @ssl_host.
+ *
+ * Return value: success or failure
+ **/
+gboolean
+soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host)
+{
        GIOChannel *ssl_chan;
 
        get_iochannel (sock);
        ssl_chan = soup_ssl_wrap_iochannel (
                sock->priv->iochannel, sock->priv->is_server ?
                SOUP_SSL_TYPE_SERVER : SOUP_SSL_TYPE_CLIENT,
-               soup_address_get_name (sock->priv->remote_addr),
-               sock->priv->ssl_creds);
+               ssl_host, sock->priv->ssl_creds);
 
        if (!ssl_chan)
                return FALSE;
index 81b59b2..49e88a9 100644 (file)
@@ -51,6 +51,8 @@ guint          soup_socket_connect            (SoupSocket         *sock,
 gboolean       soup_socket_listen             (SoupSocket         *sock,
                                               SoupAddress        *local_addr);
 gboolean       soup_socket_start_ssl          (SoupSocket         *sock);
+gboolean       soup_socket_start_proxy_ssl    (SoupSocket         *sock,
+                                              const char         *ssl_host);
 
 void           soup_socket_disconnect         (SoupSocket         *sock);
 gboolean       soup_socket_is_connected       (SoupSocket         *sock);