[glib-networking] gnutls: Update for changes to GTlsConnection:peer-certificate, etc



commit 4180943ce3042ed11a7ecb2cbf679450025127af
Author: Dan Winship <danw gnome org>
Date:   Tue Dec 7 15:01:02 2010 +0100

    gnutls: Update for changes to GTlsConnection:peer-certificate, etc

 tls/gnutls/gtlsclientconnection-gnutls.c |   60 ++++++++-------------
 tls/gnutls/gtlsconnection-gnutls.c       |   85 +++++++++++++++++++++++++++---
 tls/gnutls/gtlsconnection-gnutls.h       |    6 ++-
 tls/gnutls/gtlsserverconnection-gnutls.c |   40 ++++++--------
 4 files changed, 123 insertions(+), 68 deletions(-)
---
diff --git a/tls/gnutls/gtlsclientconnection-gnutls.c b/tls/gnutls/gtlsclientconnection-gnutls.c
index b4f1b38..476a60b 100644
--- a/tls/gnutls/gtlsclientconnection-gnutls.c
+++ b/tls/gnutls/gtlsclientconnection-gnutls.c
@@ -50,8 +50,10 @@ static void g_tls_client_connection_gnutls_set_property (GObject      *object,
 static void g_tls_client_connection_gnutls_finalize     (GObject      *object);
 
 static void     g_tls_client_connection_gnutls_begin_handshake  (GTlsConnectionGnutls  *conn);
-static gboolean g_tls_client_connection_gnutls_finish_handshake (GTlsConnectionGnutls  *conn,
-								 gboolean               success,
+static gboolean g_tls_client_connection_gnutls_verify_peer      (GTlsConnectionGnutls  *gnutls,
+								 GTlsCertificate       *peer_certificate,
+								 GTlsCertificateFlags  *errors);
+static void     g_tls_client_connection_gnutls_finish_handshake (GTlsConnectionGnutls  *conn,
 								 GError               **inout_error);
 
 static void g_tls_client_connection_gnutls_client_connection_interface_init (GTlsClientConnectionInterface *iface);
@@ -89,7 +91,8 @@ g_tls_client_connection_gnutls_class_init (GTlsClientConnectionGnutlsClass *klas
   gobject_class->set_property = g_tls_client_connection_gnutls_set_property;
   gobject_class->finalize     = g_tls_client_connection_gnutls_finalize;
 
-  connection_gnutls_class->begin_handshake = g_tls_client_connection_gnutls_begin_handshake;
+  connection_gnutls_class->begin_handshake  = g_tls_client_connection_gnutls_begin_handshake;
+  connection_gnutls_class->verify_peer      = g_tls_client_connection_gnutls_verify_peer;
   connection_gnutls_class->finish_handshake = g_tls_client_connection_gnutls_finish_handshake;
 
   g_object_class_override_property (gobject_class, PROP_VALIDATION_FLAGS, "validation-flags");
@@ -237,27 +240,32 @@ g_tls_client_connection_gnutls_retrieve_function (gnutls_session_t             s
   return 0;
 }
 
+static void
+g_tls_client_connection_gnutls_begin_handshake (GTlsConnectionGnutls *conn)
+{
+  GTlsClientConnectionGnutls *gnutls = G_TLS_CLIENT_CONNECTION_GNUTLS (conn);
+
+  gnutls->priv->cert_requested = FALSE;
+}
+
 static gboolean
-validate_handshake (GTlsClientConnectionGnutls *gnutls)
+g_tls_client_connection_gnutls_verify_peer (GTlsConnectionGnutls  *conn_gnutls,
+					    GTlsCertificate       *peer_certificate,
+					    GTlsCertificateFlags  *errors)
 {
-  GTlsCertificate *peer;
-  GTlsCertificateFlags errors;
+  GTlsClientConnectionGnutls *gnutls = G_TLS_CLIENT_CONNECTION_GNUTLS (conn_gnutls);
   gboolean accepted;
 
-  peer = g_tls_connection_get_peer_certificate (G_TLS_CONNECTION (gnutls));
-
-  errors = g_tls_connection_gnutls_validate_peer (G_TLS_CONNECTION_GNUTLS (gnutls));
+  *errors = g_tls_connection_gnutls_validate_peer (conn_gnutls);
 
-  if ((gnutls->priv->validation_flags & G_TLS_CERTIFICATE_BAD_IDENTITY) &&
-      gnutls->priv->server_identity)
+  if (gnutls->priv->server_identity)
     {
-      errors |= g_tls_certificate_gnutls_verify_identity (G_TLS_CERTIFICATE_GNUTLS (peer),
-							  gnutls->priv->server_identity);
+      *errors |= g_tls_certificate_gnutls_verify_identity (G_TLS_CERTIFICATE_GNUTLS (peer_certificate),
+							   gnutls->priv->server_identity);
     }
 
-  errors &= gnutls->priv->validation_flags;
-  if (errors)
-    accepted = g_tls_connection_emit_accept_certificate (G_TLS_CONNECTION (gnutls), peer, errors);
+  if (*errors & gnutls->priv->validation_flags)
+    accepted = g_tls_connection_emit_accept_certificate (G_TLS_CONNECTION (gnutls), peer_certificate, *errors);
   else
     accepted = TRUE;
 
@@ -265,30 +273,11 @@ validate_handshake (GTlsClientConnectionGnutls *gnutls)
 }
 
 static void
-g_tls_client_connection_gnutls_begin_handshake (GTlsConnectionGnutls *conn)
-{
-  GTlsClientConnectionGnutls *gnutls = G_TLS_CLIENT_CONNECTION_GNUTLS (conn);
-
-  gnutls->priv->cert_requested = FALSE;
-}
-
-static gboolean
 g_tls_client_connection_gnutls_finish_handshake (GTlsConnectionGnutls  *conn,
-						 gboolean               success,
 						 GError               **inout_error)
 {
   GTlsClientConnectionGnutls *gnutls = G_TLS_CLIENT_CONNECTION_GNUTLS (conn);
 
-  if (success)
-    {
-      if (validate_handshake (gnutls))
-	return TRUE;
-
-      g_set_error_literal (inout_error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
-			   _("Unacceptable TLS certificate"));
-      return FALSE;
-    }
-
   if (g_error_matches (*inout_error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS) &&
       gnutls->priv->cert_requested)
     {
@@ -296,5 +285,4 @@ g_tls_client_connection_gnutls_finish_handshake (GTlsConnectionGnutls  *conn,
       g_set_error_literal (inout_error, G_TLS_ERROR, G_TLS_ERROR_CERTIFICATE_REQUIRED,
 			   _("Server required TLS certificate"));
     }
-  return FALSE;
 }
diff --git a/tls/gnutls/gtlsconnection-gnutls.c b/tls/gnutls/gtlsconnection-gnutls.c
index 9fab2d3..f1327f2 100644
--- a/tls/gnutls/gtlsconnection-gnutls.c
+++ b/tls/gnutls/gtlsconnection-gnutls.c
@@ -97,7 +97,10 @@ enum
   PROP_BASE_IO_STREAM,
   PROP_REQUIRE_CLOSE_NOTIFY,
   PROP_REHANDSHAKE_MODE,
-  PROP_USE_SYSTEM_CERTDB
+  PROP_USE_SYSTEM_CERTDB,
+  PROP_CERTIFICATE,
+  PROP_PEER_CERTIFICATE,
+  PROP_PEER_CERTIFICATE_ERRORS
 };
 
 struct _GTlsConnectionGnutlsPrivate
@@ -109,6 +112,9 @@ struct _GTlsConnectionGnutlsPrivate
   GList *ca_list;
   gnutls_certificate_credentials creds;
   gnutls_session session;
+
+  GTlsCertificate *certificate, *peer_certificate;
+  GTlsCertificateFlags peer_certificate_errors;
   gboolean require_close_notify;
   GTlsRehandshakeMode rehandshake_mode;
   gboolean use_system_certdb;
@@ -151,6 +157,9 @@ g_tls_connection_gnutls_class_init (GTlsConnectionGnutlsClass *klass)
   g_object_class_override_property (gobject_class, PROP_REQUIRE_CLOSE_NOTIFY, "require-close-notify");
   g_object_class_override_property (gobject_class, PROP_REHANDSHAKE_MODE, "rehandshake-mode");
   g_object_class_override_property (gobject_class, PROP_USE_SYSTEM_CERTDB, "use-system-certdb");
+  g_object_class_override_property (gobject_class, PROP_CERTIFICATE, "certificate");
+  g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE, "peer-certificate");
+  g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE_ERRORS, "peer-certificate-errors");
 }
 
 static void
@@ -264,6 +273,11 @@ g_tls_connection_gnutls_finalize (GObject *object)
   if (connection->priv->creds)
     gnutls_certificate_free_credentials (connection->priv->creds);
 
+  if (connection->priv->certificate)
+    g_object_unref (connection->priv->certificate);
+  if (connection->priv->peer_certificate)
+    g_object_unref (connection->priv->peer_certificate);
+
   if (connection->priv->error)
     g_error_free (connection->priv->error);
 
@@ -296,6 +310,18 @@ g_tls_connection_gnutls_get_property (GObject    *object,
       g_value_set_boolean (value, gnutls->priv->use_system_certdb);
       break;
 
+    case PROP_CERTIFICATE:
+      g_value_set_object (value, gnutls->priv->certificate);
+      break;
+
+    case PROP_PEER_CERTIFICATE:
+      g_value_set_object (value, gnutls->priv->peer_certificate);
+      break;
+
+    case PROP_PEER_CERTIFICATE_ERRORS:
+      g_value_set_flags (value, gnutls->priv->peer_certificate_errors);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -357,6 +383,12 @@ g_tls_connection_gnutls_set_property (GObject      *object,
 	}
       break;
 
+    case PROP_CERTIFICATE:
+      if (gnutls->priv->certificate)
+	g_object_unref (gnutls->priv->certificate);
+      gnutls->priv->certificate = g_value_dup_object (value);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -736,6 +768,8 @@ handshake_internal (GTlsConnectionGnutls  *gnutls,
 		    GCancellable          *cancellable,
 		    GError               **error)
 {
+  GTlsCertificate *peer_certificate;
+  GTlsCertificateFlags peer_certificate_errors;
   int ret;
 
   if (G_IS_TLS_SERVER_CONNECTION_GNUTLS (gnutls) &&
@@ -749,10 +783,23 @@ handshake_internal (GTlsConnectionGnutls  *gnutls,
 	return FALSE;
     }
 
-  g_tls_connection_gnutls_set_handshake_priority (gnutls);
+  if (!gnutls->priv->handshaking)
+    {
+      gnutls->priv->handshaking = TRUE;
 
-  gnutls->priv->handshaking = TRUE;
-  G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->begin_handshake (gnutls);
+      if (gnutls->priv->peer_certificate)
+	{
+	  g_object_unref (gnutls->priv->peer_certificate);
+	  gnutls->priv->peer_certificate = NULL;
+	  gnutls->priv->peer_certificate_errors = 0;
+
+	  g_object_notify (G_OBJECT (gnutls), "peer-certificate");
+	  g_object_notify (G_OBJECT (gnutls), "peer-certificate-errors");
+	}
+
+      g_tls_connection_gnutls_set_handshake_priority (gnutls);
+      G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->begin_handshake (gnutls);
+    }
 
   BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
   ret = gnutls_handshake (gnutls->priv->session);
@@ -784,12 +831,36 @@ handshake_internal (GTlsConnectionGnutls  *gnutls,
 	    }
 	}
 
-      g_tls_connection_set_peer_certificate (G_TLS_CONNECTION (gnutls), chain);
+      peer_certificate = chain;
     }
   else
-    g_tls_connection_set_peer_certificate (G_TLS_CONNECTION (gnutls), NULL);
+    peer_certificate = NULL;
+
+  if (peer_certificate)
+    {
+      if (!G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->verify_peer (gnutls, peer_certificate, &peer_certificate_errors))
+	{
+	  g_object_unref (peer_certificate);
+	  g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
+			       _("Unacceptable TLS certificate"));
+	  return FALSE;
+	}
+    }
+
+  G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->finish_handshake (gnutls, error);
 
-  return G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->finish_handshake (gnutls, ret == 0, error);
+  if (ret == 0)
+    {
+      gnutls->priv->peer_certificate = peer_certificate;
+      gnutls->priv->peer_certificate_errors = peer_certificate_errors;
+
+      g_object_notify (G_OBJECT (gnutls), "peer-certificate");
+      g_object_notify (G_OBJECT (gnutls), "peer-certificate-errors");
+
+      return TRUE;
+    }
+  else
+    return FALSE;
 }
 
 static gboolean
diff --git a/tls/gnutls/gtlsconnection-gnutls.h b/tls/gnutls/gtlsconnection-gnutls.h
index 834fc16..0e54df8 100644
--- a/tls/gnutls/gtlsconnection-gnutls.h
+++ b/tls/gnutls/gtlsconnection-gnutls.h
@@ -34,8 +34,10 @@ struct _GTlsConnectionGnutlsClass
   GTlsConnectionClass parent_class;
 
   void     (*begin_handshake)  (GTlsConnectionGnutls  *gnutls);
-  gboolean (*finish_handshake) (GTlsConnectionGnutls  *gnutls,
-				gboolean               success,
+  gboolean (*verify_peer)      (GTlsConnectionGnutls  *gnutls,
+				GTlsCertificate       *peer_certificate,
+				GTlsCertificateFlags  *errors);
+  void     (*finish_handshake) (GTlsConnectionGnutls  *gnutls,
 				GError               **inout_error);
 };
 
diff --git a/tls/gnutls/gtlsserverconnection-gnutls.c b/tls/gnutls/gtlsserverconnection-gnutls.c
index 119f847..6e9a8bd 100644
--- a/tls/gnutls/gtlsserverconnection-gnutls.c
+++ b/tls/gnutls/gtlsserverconnection-gnutls.c
@@ -45,8 +45,10 @@ static void g_tls_server_connection_gnutls_set_property (GObject      *object,
 							 GParamSpec   *pspec);
 
 static void     g_tls_server_connection_gnutls_begin_handshake  (GTlsConnectionGnutls  *conn);
-static gboolean g_tls_server_connection_gnutls_finish_handshake (GTlsConnectionGnutls  *conn,
-								 gboolean               success,
+static gboolean g_tls_server_connection_gnutls_verify_peer      (GTlsConnectionGnutls  *gnutls,
+								 GTlsCertificate       *peer_certificate,
+								 GTlsCertificateFlags  *errors);
+static void     g_tls_server_connection_gnutls_finish_handshake (GTlsConnectionGnutls  *conn,
 								 GError               **inout_error);
 
 static void g_tls_server_connection_gnutls_server_connection_interface_init (GTlsServerConnectionInterface *iface);
@@ -74,7 +76,8 @@ g_tls_server_connection_gnutls_class_init (GTlsServerConnectionGnutlsClass *klas
   gobject_class->get_property = g_tls_server_connection_gnutls_get_property;
   gobject_class->set_property = g_tls_server_connection_gnutls_set_property;
 
-  connection_gnutls_class->begin_handshake = g_tls_server_connection_gnutls_begin_handshake;
+  connection_gnutls_class->begin_handshake  = g_tls_server_connection_gnutls_begin_handshake;
+  connection_gnutls_class->verify_peer      = g_tls_server_connection_gnutls_verify_peer;
   connection_gnutls_class->finish_handshake = g_tls_server_connection_gnutls_finish_handshake;
 
   g_object_class_override_property (gobject_class, PROP_AUTHENTICATION_MODE, "authentication-mode");
@@ -167,27 +170,18 @@ g_tls_server_connection_gnutls_begin_handshake (GTlsConnectionGnutls *conn)
 }
 
 static gboolean
-g_tls_server_connection_gnutls_finish_handshake (GTlsConnectionGnutls  *gnutls,
-						 gboolean               success,
-						 GError               **inout_error)
+g_tls_server_connection_gnutls_verify_peer (GTlsConnectionGnutls  *gnutls,
+					    GTlsCertificate       *peer_certificate,
+					    GTlsCertificateFlags  *errors)
 {
-  GTlsCertificateFlags gtls_errors;
-  GTlsCertificate *peer;
-
-  if (!success)
-    return FALSE;
+  *errors = g_tls_connection_gnutls_validate_peer (G_TLS_CONNECTION_GNUTLS (gnutls));
 
-  peer = g_tls_connection_get_peer_certificate (G_TLS_CONNECTION (gnutls));
-  if (peer)
-    {
-      gtls_errors = g_tls_connection_gnutls_validate_peer (gnutls);
-      if (!g_tls_connection_emit_accept_certificate (G_TLS_CONNECTION (gnutls), peer, gtls_errors))
-	{
-	  g_set_error_literal (inout_error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
-			       _("Unacceptable TLS certificate"));
-	  return FALSE;
-	}
-    }
+  return g_tls_connection_emit_accept_certificate (G_TLS_CONNECTION (gnutls),
+						   peer_certificate, *errors);
+}
 
-  return TRUE;
+static void
+g_tls_server_connection_gnutls_finish_handshake (GTlsConnectionGnutls  *gnutls,
+						 GError               **inout_error)
+{
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]