gnutls: make GTlsServerConnection error out if given a bad cert
authorDan Winship <danw@gnome.org>
Sat, 19 Nov 2011 01:25:25 +0000 (20:25 -0500)
committerDan Winship <danw@gnome.org>
Sat, 19 Nov 2011 01:32:00 +0000 (20:32 -0500)
GTlsServerConnection needs a certificate that has a public key, so
make it fail g_initable_init() if it has a certificate without one.

tls/gnutls/gtlscertificate-gnutls.c
tls/gnutls/gtlscertificate-gnutls.h
tls/gnutls/gtlsconnection-gnutls.c
tls/gnutls/gtlsserverconnection-gnutls.c

index 9227ba2..30497e6 100644 (file)
@@ -460,6 +460,12 @@ g_tls_certificate_gnutls_get_cert (GTlsCertificateGnutls *gnutls)
   return gnutls->priv->cert;
 }
 
+gboolean
+g_tls_certificate_gnutls_has_key (GTlsCertificateGnutls *gnutls)
+{
+  return gnutls->priv->have_key;
+}
+
 void
 g_tls_certificate_gnutls_copy  (GTlsCertificateGnutls *gnutls,
                                 const gchar           *interaction_id,
index 202ed6e..981d4a7 100644 (file)
@@ -53,6 +53,7 @@ void                         g_tls_certificate_gnutls_set_data        (GTlsCerti
                                                                        const gnutls_datum *datum);
 
 const gnutls_x509_crt_t      g_tls_certificate_gnutls_get_cert        (GTlsCertificateGnutls *gnutls);
+gboolean                     g_tls_certificate_gnutls_has_key         (GTlsCertificateGnutls *gnutls);
 
 void                         g_tls_certificate_gnutls_copy            (GTlsCertificateGnutls *gnutls,
                                                                        const gchar           *interaction_id,
index 065fe87..8469658 100644 (file)
@@ -1159,7 +1159,7 @@ close_internal (GTlsConnectionGnutls  *gnutls,
   /* If we haven't finished the initial handshake yet, there's no
    * reason to finish it just so we can close.
    */
-  if (gnutls->priv->handshaking && !gnutls->priv->ever_handshaked)
+  if (!gnutls->priv->ever_handshaked)
     return TRUE;
 
   if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
index 990946f..9360c3a 100644 (file)
@@ -51,6 +51,10 @@ static void     g_tls_server_connection_gnutls_finish_handshake (GTlsConnectionG
                                                                 gboolean               success,
                                                                 GError               **inout_error);
 
+static void     g_tls_server_connection_gnutls_initable_interface_init (GInitableIface  *iface);
+static gboolean g_tls_server_connection_gnutls_initable_init (GInitable       *initable,
+                                                             GCancellable    *cancellable,
+                                                             GError         **error);
 static void g_tls_server_connection_gnutls_server_connection_interface_init (GTlsServerConnectionInterface *iface);
 
 static int g_tls_server_connection_gnutls_retrieve_function (gnutls_session_t             session,
@@ -60,9 +64,14 @@ static int g_tls_server_connection_gnutls_retrieve_function (gnutls_session_t
                                                              int                          pk_algos_length,
                                                              gnutls_retr2_st             *st);
 
+static GInitableIface *g_tls_server_connection_gnutls_parent_initable_iface;
+
 G_DEFINE_TYPE_WITH_CODE (GTlsServerConnectionGnutls, g_tls_server_connection_gnutls, G_TYPE_TLS_CONNECTION_GNUTLS,
+                        G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+                                               g_tls_server_connection_gnutls_initable_interface_init)
                         G_IMPLEMENT_INTERFACE (G_TYPE_TLS_SERVER_CONNECTION,
-                                               g_tls_server_connection_gnutls_server_connection_interface_init))
+                                               g_tls_server_connection_gnutls_server_connection_interface_init)
+)
 
 struct _GTlsServerConnectionGnutlsPrivate
 {
@@ -93,6 +102,14 @@ g_tls_server_connection_gnutls_server_connection_interface_init (GTlsServerConne
 }
 
 static void
+g_tls_server_connection_gnutls_initable_interface_init (GInitableIface  *iface)
+{
+  g_tls_server_connection_gnutls_parent_initable_iface = g_type_interface_peek_parent (iface);
+
+  iface->init = g_tls_server_connection_gnutls_initable_init;
+}
+
+static void
 g_tls_server_connection_gnutls_init (GTlsServerConnectionGnutls *gnutls)
 {
   gnutls_certificate_credentials_t creds;
@@ -103,6 +120,28 @@ g_tls_server_connection_gnutls_init (GTlsServerConnectionGnutls *gnutls)
   gnutls_certificate_set_retrieve_function (creds, g_tls_server_connection_gnutls_retrieve_function);
 }
 
+static gboolean
+g_tls_server_connection_gnutls_initable_init (GInitable       *initable,
+                                             GCancellable    *cancellable,
+                                             GError         **error)
+{
+  GTlsCertificate *cert;
+
+  if (!g_tls_server_connection_gnutls_parent_initable_iface->
+      init (initable, cancellable, error))
+    return FALSE;
+
+  cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (initable));
+  if (cert && !g_tls_certificate_gnutls_has_key (G_TLS_CERTIFICATE_GNUTLS (cert)))
+    {
+      g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
+                          _("Certificate has no private key"));
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
 static void
 g_tls_server_connection_gnutls_get_property (GObject    *object,
                                             guint       prop_id,