[glib-networking/mcatanzaro/identity: 2/2] gnutls: remove manual identity verification code




commit ffb66818621f8b5ebba3da3252e94e858c826324
Author: Michael Catanzaro <mcatanzaro redhat com>
Date:   Fri Jun 25 10:56:17 2021 -0500

    gnutls: remove manual identity verification code
    
    Currently GTlsDatabase and GTlsConnection both rely on GnuTLS to verify
    the peer identity, but GTlsCertificate does it manually. There's no good
    reason for this.

 tls/gnutls/gtlscertificate-gnutls.c | 100 +++++++++++-------------------------
 tls/gnutls/gtlscertificate-gnutls.h |   5 +-
 tls/gnutls/gtlsdatabase-gnutls.c    |  35 ++-----------
 3 files changed, 37 insertions(+), 103 deletions(-)
---
diff --git a/tls/gnutls/gtlscertificate-gnutls.c b/tls/gnutls/gtlscertificate-gnutls.c
index 7d9a1ff..0461974 100644
--- a/tls/gnutls/gtlscertificate-gnutls.c
+++ b/tls/gnutls/gtlscertificate-gnutls.c
@@ -510,6 +510,7 @@ g_tls_certificate_gnutls_verify (GTlsCertificate     *cert,
   guint num_certs, i;
   gnutls_x509_crt_t *chain;
   GTlsCertificateFlags gtls_flags;
+  GError *error = NULL;
 
   cert_gnutls = G_TLS_CERTIFICATE_GNUTLS (cert);
   num_certs = 0;
@@ -554,7 +555,14 @@ g_tls_certificate_gnutls_verify (GTlsCertificate     *cert,
   g_free (chain);
 
   if (identity)
-    gtls_flags |= g_tls_certificate_gnutls_verify_identity (G_TLS_CERTIFICATE_GNUTLS (cert), identity);
+    {
+      gtls_flags |= g_tls_certificate_gnutls_verify_identity (G_TLS_CERTIFICATE_GNUTLS (cert), identity, 
&error);
+      if (error)
+        {
+          g_warning ("Error verifying TLS certificate: %s", error->message);
+          g_error_free (error);
+        }
+    }
 
   return gtls_flags;
 }
@@ -772,88 +780,40 @@ g_tls_certificate_gnutls_convert_flags (guint gnutls_flags)
   return gtls_flags;
 }
 
-static gboolean
-verify_identity_hostname (GTlsCertificateGnutls *gnutls,
-                          GSocketConnectable    *identity)
+GTlsCertificateFlags
+g_tls_certificate_gnutls_verify_identity (GTlsCertificateGnutls  *gnutls,
+                                          GSocketConnectable     *identity,
+                                          GError                **error)
 {
+  GTlsCertificateFlags result = 0;
   const char *hostname;
+  char *free_hostname = NULL;
 
   if (G_IS_NETWORK_ADDRESS (identity))
     hostname = g_network_address_get_hostname (G_NETWORK_ADDRESS (identity));
   else if (G_IS_NETWORK_SERVICE (identity))
     hostname = g_network_service_get_domain (G_NETWORK_SERVICE (identity));
-  else
-    return FALSE;
-
-  return gnutls_x509_crt_check_hostname (gnutls->cert, hostname);
-}
-
-static gboolean
-verify_identity_ip (GTlsCertificateGnutls *gnutls,
-                    GSocketConnectable    *identity)
-{
-  GInetAddress *addr;
-  int i, ret = 0;
-  gsize addr_size;
-  const guint8 *addr_bytes;
-
-  if (G_IS_INET_SOCKET_ADDRESS (identity))
-    addr = g_object_ref (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (identity)));
-  else {
-    const char *hostname;
-
-    if (G_IS_NETWORK_ADDRESS (identity))
-      hostname = g_network_address_get_hostname (G_NETWORK_ADDRESS (identity));
-    else if (G_IS_NETWORK_SERVICE (identity))
-      hostname = g_network_service_get_domain (G_NETWORK_SERVICE (identity));
-    else
-      return FALSE;
-
-    addr = g_inet_address_new_from_string (hostname);
-    if (!addr)
-      return FALSE;
-  }
-
-  addr_bytes = g_inet_address_to_bytes (addr);
-  addr_size = g_inet_address_get_native_size (addr);
-
-  for (i = 0; ret >= 0; i++)
+  else if (G_IS_INET_SOCKET_ADDRESS (identity))
     {
-      char san[500];
-      size_t san_size;
+      GInetAddress *addr;
 
-      san_size = sizeof (san);
-      ret = gnutls_x509_crt_get_subject_alt_name (gnutls->cert, i,
-                                                  san, &san_size, NULL);
-
-      if ((ret == GNUTLS_SAN_IPADDRESS) && (addr_size == san_size))
-        {
-          if (memcmp (addr_bytes, san, addr_size) == 0)
-            {
-              g_object_unref (addr);
-              return TRUE;
-            }
-        }
+      addr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (identity));
+      hostname = free_hostname = g_inet_address_to_string (addr);
+    }
+  else
+    {
+      g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
+                   _("Cannot verify peer identity of unexpected type %s"), G_OBJECT_TYPE_NAME (identity));
+      return G_TLS_CERTIFICATE_BAD_IDENTITY;
     }
 
-  g_object_unref (addr);
-  return FALSE;
-}
-
-GTlsCertificateFlags
-g_tls_certificate_gnutls_verify_identity (GTlsCertificateGnutls *gnutls,
-                                          GSocketConnectable    *identity)
-{
-  if (verify_identity_hostname (gnutls, identity))
-    return 0;
-  else if (verify_identity_ip (gnutls, identity))
-    return 0;
+  g_assert (hostname);
+  if (!gnutls_x509_crt_check_hostname (gnutls->cert, hostname))
+    result |= G_TLS_CERTIFICATE_BAD_IDENTITY;
 
-  /* FIXME: check sRVName and uniformResourceIdentifier
-   * subjectAltNames, if appropriate for @identity.
-   */
+  g_free (free_hostname);
 
-  return G_TLS_CERTIFICATE_BAD_IDENTITY;
+  return result;
 }
 
 void
diff --git a/tls/gnutls/gtlscertificate-gnutls.h b/tls/gnutls/gtlscertificate-gnutls.h
index 838f7db..257e1ec 100644
--- a/tls/gnutls/gtlscertificate-gnutls.h
+++ b/tls/gnutls/gtlscertificate-gnutls.h
@@ -56,8 +56,9 @@ void                         g_tls_certificate_gnutls_copy_free       (gnutls_pc
                                                                        unsigned int            pcert_length,
                                                                        gnutls_privkey_t        pkey);
 
-GTlsCertificateFlags         g_tls_certificate_gnutls_verify_identity (GTlsCertificateGnutls *gnutls,
-                                                                       GSocketConnectable    *identity);
+GTlsCertificateFlags         g_tls_certificate_gnutls_verify_identity (GTlsCertificateGnutls  *gnutls,
+                                                                       GSocketConnectable     *identity,
+                                                                       GError                **error);
 
 GTlsCertificateFlags         g_tls_certificate_gnutls_convert_flags   (guint                  gnutls_flags);
 
diff --git a/tls/gnutls/gtlsdatabase-gnutls.c b/tls/gnutls/gtlsdatabase-gnutls.c
index 1bd1a8a..e418157 100644
--- a/tls/gnutls/gtlsdatabase-gnutls.c
+++ b/tls/gnutls/gtlsdatabase-gnutls.c
@@ -492,8 +492,6 @@ g_tls_database_gnutls_verify_chain (GTlsDatabase             *database,
   GTlsCertificateFlags result;
   guint gnutls_result;
   CertificateChain *gnutls_chain;
-  const char *hostname = NULL;
-  char *free_hostname = NULL;
   int gerr;
 
   g_return_val_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (chain),
@@ -521,35 +519,10 @@ g_tls_database_gnutls_verify_chain (GTlsDatabase             *database,
 
   result = g_tls_certificate_gnutls_convert_flags (gnutls_result);
 
-  if (G_IS_NETWORK_ADDRESS (identity))
-    hostname = g_network_address_get_hostname (G_NETWORK_ADDRESS (identity));
-  else if (G_IS_NETWORK_SERVICE (identity))
-    hostname = g_network_service_get_domain (G_NETWORK_SERVICE (identity));
-  else if (G_IS_INET_SOCKET_ADDRESS (identity))
-    {
-      GInetAddress *addr;
-
-      addr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (identity));
-      hostname = free_hostname = g_inet_address_to_string (addr);
-    }
-
-  if (hostname)
-    {
-      if (!gnutls_x509_crt_check_hostname (gnutls_chain->chain[0], hostname))
-        result |= G_TLS_CERTIFICATE_BAD_IDENTITY;
-      g_free (free_hostname);
-    }
-  else if (identity)
-    {
-      /* If identity is NULL, then the application has requested that we not
-       * verify identity. But if the application passes an identity of a
-       * type we don't expect, then the application surely expects it to be
-       * used, so we'd better not fail silently.
-       */
-      g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
-                   _("Cannot verify peer identity of unexpected type %s"), G_OBJECT_TYPE_NAME (identity));
-      result |= G_TLS_CERTIFICATE_BAD_IDENTITY;
-    }
+  if (identity)
+    result |= g_tls_certificate_gnutls_verify_identity (G_TLS_CERTIFICATE_GNUTLS (chain),
+                                                        identity,
+                                                        error);
 
   certificate_chain_free (gnutls_chain);
   return result;


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