[glib-networking] tls: expose SAN details on GTlsCertificate
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking] tls: expose SAN details on GTlsCertificate
- Date: Wed, 23 Jun 2021 19:16:48 +0000 (UTC)
commit e12c82f74464ae098f7279e895f84d6769d3a48d
Author: Ross A. Wollman <ross wollman gmail com>
Date: Tue Jun 8 19:25:29 2021 +0000
tls: expose SAN details on GTlsCertificate
This changeset exposes
* `dns-names`
* `ip-addresses`
For more information, see related glib MR:
https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2142.
tls/gnutls/gtlscertificate-gnutls.c | 66 +++++++++++++++++++++++++++++++++++
tls/openssl/gtlscertificate-openssl.c | 61 ++++++++++++++++++++++++++++++++
tls/tests/certificate.c | 47 +++++++++++++++++++++++++
3 files changed, 174 insertions(+)
---
diff --git a/tls/gnutls/gtlscertificate-gnutls.c b/tls/gnutls/gtlscertificate-gnutls.c
index 4c27587..5de6eb5 100644
--- a/tls/gnutls/gtlscertificate-gnutls.c
+++ b/tls/gnutls/gtlscertificate-gnutls.c
@@ -46,6 +46,8 @@ enum
PROP_NOT_VALID_AFTER,
PROP_SUBJECT_NAME,
PROP_ISSUER_NAME,
+ PROP_DNS_NAMES,
+ PROP_IP_ADDRESSES,
};
struct _GTlsCertificateGnutls
@@ -90,6 +92,60 @@ g_tls_certificate_gnutls_finalize (GObject *object)
G_OBJECT_CLASS (g_tls_certificate_gnutls_parent_class)->finalize (object);
}
+static GPtrArray *
+get_subject_alt_names (GTlsCertificateGnutls *cert,
+ gnutls_x509_subject_alt_name_t type)
+{
+ GPtrArray *data = NULL;
+ guint8 *san = NULL;
+ size_t san_size;
+ guint san_type;
+ guint critical;
+ guint i;
+ guint status;
+
+ if (type == GNUTLS_SAN_IPADDRESS)
+ data = g_ptr_array_new_with_free_func (g_object_unref);
+ else
+ data = g_ptr_array_new_with_free_func ((GDestroyNotify)g_bytes_unref);
+
+ for (i = 0; ; i++)
+ {
+ san_size = 0;
+ san = NULL;
+ status = gnutls_x509_crt_get_subject_alt_name2 (cert->cert, i, san, &san_size, &san_type, &critical);
+ if (status == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+ return data;
+ else if (san_type != (guint)type)
+ continue;
+
+ if (san_size == 0)
+ continue;
+
+ san = g_malloc (san_size);
+ status = gnutls_x509_crt_get_subject_alt_name2 (cert->cert, i, san, &san_size, &san_type, &critical);
+ if (status == (guint)type)
+ {
+ if (status == (guint)GNUTLS_SAN_IPADDRESS)
+ {
+ if (san_size == 4)
+ g_ptr_array_add (data, g_inet_address_new_from_bytes (san, G_SOCKET_FAMILY_IPV4));
+ else if (san_size == 16)
+ g_ptr_array_add (data, g_inet_address_new_from_bytes (san, G_SOCKET_FAMILY_IPV6));
+ }
+ else
+ {
+ g_assert (status == (guint)GNUTLS_SAN_DNSNAME);
+ g_ptr_array_add (data, g_bytes_new (san, san_size));
+ }
+ }
+
+ g_free (san);
+ }
+
+ return data;
+}
+
static void
g_tls_certificate_gnutls_get_property (GObject *object,
guint prop_id,
@@ -202,6 +258,14 @@ g_tls_certificate_gnutls_get_property (GObject *object,
gnutls_free (data.data);
break;
+ case PROP_DNS_NAMES:
+ g_value_take_boxed (value, get_subject_alt_names (gnutls, GNUTLS_SAN_DNSNAME));
+ break;
+
+ case PROP_IP_ADDRESSES:
+ g_value_take_boxed (value, get_subject_alt_names (gnutls, GNUTLS_SAN_IPADDRESS));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -460,6 +524,8 @@ g_tls_certificate_gnutls_class_init (GTlsCertificateGnutlsClass *klass)
g_object_class_override_property (gobject_class, PROP_NOT_VALID_AFTER, "not-valid-after");
g_object_class_override_property (gobject_class, PROP_SUBJECT_NAME, "subject-name");
g_object_class_override_property (gobject_class, PROP_ISSUER_NAME, "issuer-name");
+ g_object_class_override_property (gobject_class, PROP_DNS_NAMES, "dns-names");
+ g_object_class_override_property (gobject_class, PROP_IP_ADDRESSES, "ip-addresses");
}
static void
diff --git a/tls/openssl/gtlscertificate-openssl.c b/tls/openssl/gtlscertificate-openssl.c
index cbb8f82..2ed753f 100644
--- a/tls/openssl/gtlscertificate-openssl.c
+++ b/tls/openssl/gtlscertificate-openssl.c
@@ -60,6 +60,8 @@ enum
PROP_NOT_VALID_AFTER,
PROP_SUBJECT_NAME,
PROP_ISSUER_NAME,
+ PROP_DNS_NAMES,
+ PROP_IP_ADDRESSES,
};
static void g_tls_certificate_openssl_initable_iface_init (GInitableIface *iface);
@@ -85,6 +87,55 @@ g_tls_certificate_openssl_finalize (GObject *object)
G_OBJECT_CLASS (g_tls_certificate_openssl_parent_class)->finalize (object);
}
+static GPtrArray *
+get_subject_alt_names (GTlsCertificateOpenssl *cert,
+ guint type)
+{
+ GPtrArray *data = NULL;
+ STACK_OF (GENERAL_NAME) *sans;
+ const guint8 *san = NULL;
+ size_t san_size;
+ guint alt_occurrences;
+ guint i;
+
+ if (type == GEN_IPADD)
+ data = g_ptr_array_new_with_free_func (g_object_unref);
+ else
+ data = g_ptr_array_new_with_free_func ((GDestroyNotify)g_bytes_unref);
+
+ sans = X509_get_ext_d2i (cert->cert, NID_subject_alt_name, NULL, NULL);
+ if (sans)
+ {
+ alt_occurrences = sk_GENERAL_NAME_num (sans);
+ for (i = 0; i < alt_occurrences; i++)
+ {
+ const GENERAL_NAME *value = sk_GENERAL_NAME_value (sans, i);
+ if (value->type != type)
+ continue;
+
+ if (type == GEN_IPADD)
+ {
+ g_assert (value->type == GEN_IPADD);
+ san = ASN1_STRING_get0_data (value->d.ip);
+ san_size = ASN1_STRING_length (value->d.ip);
+ if (san_size == 4)
+ g_ptr_array_add (data, g_inet_address_new_from_bytes (san, G_SOCKET_FAMILY_IPV4));
+ else if (san_size == 16)
+ g_ptr_array_add (data, g_inet_address_new_from_bytes (san, G_SOCKET_FAMILY_IPV6));
+ }
+ else
+ {
+ g_assert (value->type == GEN_DNS);
+ san = ASN1_STRING_get0_data (value->d.ia5);
+ san_size = ASN1_STRING_length (value->d.ia5);
+ g_ptr_array_add (data, g_bytes_new (san, san_size));
+ }
+ }
+ }
+
+ return data;
+}
+
static void
g_tls_certificate_openssl_get_property (GObject *object,
guint prop_id,
@@ -183,6 +234,14 @@ g_tls_certificate_openssl_get_property (GObject *object,
BIO_free_all (bio);
break;
+ case PROP_DNS_NAMES:
+ g_value_take_boxed (value, get_subject_alt_names (openssl, GEN_DNS));
+ break;
+
+ case PROP_IP_ADDRESSES:
+ g_value_take_boxed (value, get_subject_alt_names (openssl, GEN_IPADD));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -412,6 +471,8 @@ g_tls_certificate_openssl_class_init (GTlsCertificateOpensslClass *klass)
g_object_class_override_property (gobject_class, PROP_NOT_VALID_AFTER, "not-valid-after");
g_object_class_override_property (gobject_class, PROP_SUBJECT_NAME, "subject-name");
g_object_class_override_property (gobject_class, PROP_ISSUER_NAME, "issuer-name");
+ g_object_class_override_property (gobject_class, PROP_DNS_NAMES, "dns-names");
+ g_object_class_override_property (gobject_class, PROP_IP_ADDRESSES, "ip-addresses");
}
static void
diff --git a/tls/tests/certificate.c b/tls/tests/certificate.c
index 50b7dc3..32ba66c 100644
--- a/tls/tests/certificate.c
+++ b/tls/tests/certificate.c
@@ -658,6 +658,51 @@ test_certificate_issuer_name (void)
g_object_unref (cert);
}
+static void
+test_certificate_dns_names (void)
+{
+ GTlsCertificate *cert;
+ GError *error = NULL;
+ GPtrArray *actual;
+ const gchar *dns_name = "server.example.com";
+ GBytes *expected = g_bytes_new_static (dns_name, strlen (dns_name));
+
+ cert = g_tls_certificate_new_from_file (tls_test_file_path ("server.pem"), &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (cert);
+
+ actual = g_tls_certificate_get_dns_names (cert);
+ g_assert_nonnull (actual);
+ g_assert_cmpuint (actual->len, ==, 1);
+ g_assert_true (g_ptr_array_find_with_equal_func (actual, expected, (GEqualFunc)g_bytes_equal, NULL));
+
+ g_ptr_array_free (actual, FALSE);
+ g_bytes_unref (expected);
+ g_object_unref (cert);
+}
+
+static void
+test_certificate_ip_addresses (void)
+{
+ GTlsCertificate *cert;
+ GError *error = NULL;
+ GPtrArray *actual;
+ GInetAddress *expected = g_inet_address_new_from_string ("192.168.1.10");
+
+ cert = g_tls_certificate_new_from_file (tls_test_file_path ("server.pem"), &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (cert);
+
+ actual = g_tls_certificate_get_ip_addresses (cert);
+ g_assert_nonnull (actual);
+ g_assert_cmpuint (actual->len, ==, 1);
+ g_assert_true (g_ptr_array_find_with_equal_func (actual, expected, (GEqualFunc)g_inet_address_equal,
NULL));
+
+ g_ptr_array_free (actual, TRUE);
+ g_object_unref (expected);
+ g_object_unref (cert);
+}
+
int
main (int argc,
char *argv[])
@@ -720,6 +765,8 @@ main (int argc,
g_test_add_func ("/tls/" BACKEND "/certificate/not-valid-after", test_certificate_not_valid_after);
g_test_add_func ("/tls/" BACKEND "/certificate/subject-name", test_certificate_subject_name);
g_test_add_func ("/tls/" BACKEND "/certificate/issuer-name", test_certificate_issuer_name);
+ g_test_add_func ("/tls/" BACKEND "/certificate/dns-names", test_certificate_dns_names);
+ g_test_add_func ("/tls/" BACKEND "/certificate/ip-addresses", test_certificate_ip_addresses);
return g_test_run();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]