[glib-networking] gnutls: refactor and extend IP altname check



commit f60379d2e1d64999c04d0f213def319de66be3a3
Author: Dan Winship <danw gnome org>
Date:   Mon Jul 21 12:27:34 2014 -0400

    gnutls: refactor and extend IP altname check
    
    Refactor g_tls_certificate_gnutls_verify_identity() and extend the IP
    address altname code to handle GInetSocketAddress identities as well.
    
    Extend tls/tests/certificate.c to check that case as well, and also
    check that incorrect IP addresses (as GNetworkAddress or
    GInetSocketAddress) fail to verify.

 tls/gnutls/gtlscertificate-gnutls.c |  104 +++++++++++++++++++++--------------
 tls/tests/certificate.c             |   17 +++++-
 2 files changed, 78 insertions(+), 43 deletions(-)
---
diff --git a/tls/gnutls/gtlscertificate-gnutls.c b/tls/gnutls/gtlscertificate-gnutls.c
index ba6b5d2..c513233 100644
--- a/tls/gnutls/gtlscertificate-gnutls.c
+++ b/tls/gnutls/gtlscertificate-gnutls.c
@@ -540,63 +540,83 @@ g_tls_certificate_gnutls_convert_flags (guint gnutls_flags)
   return gtls_flags;
 }
 
-GTlsCertificateFlags
-g_tls_certificate_gnutls_verify_identity (GTlsCertificateGnutls *gnutls,
-                                         GSocketConnectable    *identity)
+static gboolean
+verify_identity_hostname (GTlsCertificateGnutls *gnutls,
+                         GSocketConnectable    *identity)
 {
   const char *hostname;
-  GInetAddress *addr;
 
   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
-    hostname = NULL;
+    return FALSE;
 
-  if (!hostname)
-    return G_TLS_CERTIFICATE_BAD_IDENTITY;
+  return gnutls_x509_crt_check_hostname (gnutls->priv->cert, hostname);
+}
 
-  if (gnutls_x509_crt_check_hostname (gnutls->priv->cert, hostname))
-    return 0;
+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;
 
-  if (!g_hostname_is_ip_address (hostname))
-    return G_TLS_CERTIFICATE_BAD_IDENTITY;
+    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);
 
-  addr = g_inet_address_new_from_string (hostname);
-  if (addr)
+  for (i = 0; ret >= 0; i++)
     {
-      int i, ret = 0;
-      gsize addr_size;
-      const guint8 *addr_bytes;
-
-      addr_bytes = g_inet_address_to_bytes (addr);
-      addr_size = g_inet_address_get_native_size (addr);
-
-      /* Here we only add an additional check to support IP addresses. */
-      for (i = 0; ret >= 0; i++)
-        {
-          char san[500];
-          size_t san_size;
-
-          san_size = sizeof (san);
-          ret = gnutls_x509_crt_get_subject_alt_name (gnutls->priv->cert, i,
-                                                      san, &san_size, NULL);
-
-          if ((ret == GNUTLS_SAN_IPADDRESS) && (addr_size == san_size))
-            {
-              /* Let's check if found a matching IP. */
-              if (memcmp (addr_bytes, san, addr_size) == 0)
-                {
-                  g_object_unref (addr);
-                  return 0;
-                }
-            }
-        }
-
-      g_object_unref (addr);
+      char san[500];
+      size_t san_size;
+
+      san_size = sizeof (san);
+      ret = gnutls_x509_crt_get_subject_alt_name (gnutls->priv->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;
+           }
+       }
     }
 
+  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;
+
   /* FIXME: check sRVName and uniformResourceIdentifier
    * subjectAltNames, if appropriate for @identity.
    */
diff --git a/tls/tests/certificate.c b/tls/tests/certificate.c
index 56be9e1..6ba85d9 100644
--- a/tls/tests/certificate.c
+++ b/tls/tests/certificate.c
@@ -308,6 +308,7 @@ test_verify_certificate_good (TestVerify      *test,
                               gconstpointer    data)
 {
   GSocketConnectable *identity;
+  GSocketAddress *addr;
   GTlsCertificateFlags errors;
 
   errors = g_tls_certificate_verify (test->cert, test->identity, test->anchor);
@@ -320,6 +321,11 @@ test_verify_certificate_good (TestVerify      *test,
   errors = g_tls_certificate_verify (test->cert, identity, test->anchor);
   g_assert_cmpuint (errors, ==, 0);
   g_object_unref (identity);
+
+  addr = g_inet_socket_address_new_from_string ("192.168.1.10", 80);
+  errors = g_tls_certificate_verify (test->cert, G_SOCKET_CONNECTABLE (addr), test->anchor);
+  g_assert_cmpuint (errors, ==, 0);
+  g_object_unref (addr);
 }
 
 static void
@@ -328,13 +334,22 @@ test_verify_certificate_bad_identity (TestVerify      *test,
 {
   GSocketConnectable *identity;
   GTlsCertificateFlags errors;
+  GSocketAddress *addr;
 
   identity = g_network_address_new ("other.example.com", 80);
-
   errors = g_tls_certificate_verify (test->cert, identity, test->anchor);
   g_assert_cmpuint (errors, ==, G_TLS_CERTIFICATE_BAD_IDENTITY);
+  g_object_unref (identity);
 
+  identity = g_network_address_new ("127.0.0.1", 80);
+  errors = g_tls_certificate_verify (test->cert, identity, test->anchor);
+  g_assert_cmpuint (errors, ==, G_TLS_CERTIFICATE_BAD_IDENTITY);
   g_object_unref (identity);
+
+  addr = g_inet_socket_address_new_from_string ("127.0.0.1", 80);
+  errors = g_tls_certificate_verify (test->cert, G_SOCKET_CONNECTABLE (addr), test->anchor);
+  g_assert_cmpuint (errors, ==, G_TLS_CERTIFICATE_BAD_IDENTITY);
+  g_object_unref (addr);
 }
 
 static void


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