[gnome-keyring: 1/2] gcr: Parse and display certificate extensions.
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring: 1/2] gcr: Parse and display certificate extensions.
- Date: Sat, 4 Jun 2011 07:40:04 +0000 (UTC)
commit 65c9d546623d31f35b15f4c0d412513ae82df6fd
Author: Stef Walter <stefw collabora co uk>
Date: Wed Apr 6 12:22:24 2011 +0200
gcr: Parse and display certificate extensions.
* Subject Alt Name
* Basic Constraints
* Extended Key Usage
* Key Usage
* Subject Key Identifier
https://bugzilla.gnome.org/show_bug.cgi?id=646907
egg/egg-oid.c | 31 +++--
gcr/Makefile.am | 1 +
gcr/gcr-certificate-extensions.c | 269 ++++++++++++++++++++++++++++++++++++++
gcr/gcr-certificate-extensions.h | 88 +++++++++++++
gcr/gcr-certificate-renderer.c | 216 ++++++++++++++++++++++++++++--
gcr/gcr-display-view.h | 2 +
po/POTFILES.in | 1 +
7 files changed, 578 insertions(+), 30 deletions(-)
---
diff --git a/egg/egg-oid.c b/egg/egg-oid.c
index d0bc6bf..5ab7ea6 100644
--- a/egg/egg-oid.c
+++ b/egg/egg-oid.c
@@ -57,9 +57,9 @@ static OidInfo oid_info[] = {
EGG_OID_PRINTABLE },
{ 0, "1.3.6.1.5.5.7.9.3", "gender", N_("Gender"),
EGG_OID_PRINTABLE },
- { 0, "1.3.6.1.5.5.7.9.4", "countryOfCitizenship", N_("Country of Citizenship"),
+ { 0, "1.3.6.1.5.5.7.9.4", "countryOfCitizenship", N_("Country of Citizenship"),
EGG_OID_PRINTABLE },
- { 0, "1.3.6.1.5.5.7.9.5", "countryOfResidence", N_("Country of Residence"),
+ { 0, "1.3.6.1.5.5.7.9.5", "countryOfResidence", N_("Country of Residence"),
EGG_OID_PRINTABLE },
{ 0, "2.5.4.3", "CN", N_("Common Name"),
@@ -95,19 +95,20 @@ static OidInfo oid_info[] = {
{ 0, "2.5.4.65", "pseudonym", N_("Pseudonym"),
EGG_OID_PRINTABLE | EGG_OID_IS_CHOICE },
- { 0, "1.2.840.113549.1.1.1", "rsaEncryption", N_("RSA"),
- 0 },
- { 0, "1.2.840.113549.1.1.2", "md2WithRSAEncryption", N_("MD2 with RSA"),
- 0 },
- { 0, "1.2.840.113549.1.1.4", "md5WithRSAEncryption", N_("MD5 with RSA"),
- 0 },
- { 0, "1.2.840.113549.1.1.5", "sha1WithRSAEncryption", N_("SHA1 with RSA"),
- 0 },
-
- { 0, "1.2.840.10040.4.1", "dsa", N_("DSA"),
- 0 },
- { 0, "1.2.840.10040.4.3", "sha1WithDSA", N_("SHA1 with DSA"),
- 0 },
+ { 0, "1.2.840.113549.1.1.1", "rsaEncryption", N_("RSA"), 0 },
+ { 0, "1.2.840.113549.1.1.2", "md2WithRSAEncryption", N_("MD2 with RSA"), 0 },
+ { 0, "1.2.840.113549.1.1.4", "md5WithRSAEncryption", N_("MD5 with RSA"), 0 },
+ { 0, "1.2.840.113549.1.1.5", "sha1WithRSAEncryption", N_("SHA1 with RSA"), 0 },
+
+ { 0, "1.2.840.10040.4.1", "dsa", N_("DSA"), 0 },
+ { 0, "1.2.840.10040.4.3", "sha1WithDSA", N_("SHA1 with DSA"), 0 },
+
+ /* Extended Key Usages */
+ { 0, "1.3.6.1.5.5.7.3.1", NULL, N_("Server Authentication"), 0 },
+ { 0, "1.3.6.1.5.5.7.3.2", NULL, N_("Client Authentication"), 0 },
+ { 0, "1.3.6.1.5.5.7.3.3", NULL, N_("Code Signing"), 0 },
+ { 0, "1.3.6.1.5.5.7.3.4", NULL, N_("Email Protection"), 0 },
+ { 0, "1.3.6.1.5.5.7.3.8", NULL, N_("Time Stamping"), 0 },
{ 0, NULL, NULL, NULL, FALSE }
};
diff --git a/gcr/Makefile.am b/gcr/Makefile.am
index 8ccc601..f565827 100644
--- a/gcr/Makefile.am
+++ b/gcr/Makefile.am
@@ -75,6 +75,7 @@ libgcr GCR_VERSION_SUFFIX@_la_SOURCES = \
gcr-certificate-chain.c gcr-certificate-chain.h \
gcr-certificate-renderer.c gcr-certificate-renderer.h \
gcr-certificate-exporter.c gcr-certificate-exporter.h \
+ gcr-certificate-extensions.c gcr-certificate-extensions.h \
gcr-certificate-widget.c gcr-certificate-widget.h \
gcr-collection.c gcr-collection.h \
gcr-collection-model.c gcr-collection-model.h \
diff --git a/gcr/gcr-certificate-extensions.c b/gcr/gcr-certificate-extensions.c
new file mode 100644
index 0000000..2c24466
--- /dev/null
+++ b/gcr/gcr-certificate-extensions.c
@@ -0,0 +1,269 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+#include "config.h"
+
+#include "gcr-certificate-extensions.h"
+
+#include "egg/egg-asn1x.h"
+#include "egg/egg-asn1-defs.h"
+#include "egg/egg-dn.h"
+
+#include <glib/gi18n-lib.h>
+
+gboolean
+_gcr_certificate_extension_basic_constraints (gconstpointer data, gsize n_data,
+ gboolean *is_ca, gint *path_len)
+{
+ gboolean ret = TRUE;
+ GNode *asn = NULL;
+ GNode *node;
+ gulong value;
+
+ g_return_val_if_fail (data, FALSE);
+ g_return_val_if_fail (n_data, FALSE);
+
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "BasicConstraints", data, n_data);
+ if (asn == NULL)
+ return FALSE;
+
+ if (path_len) {
+ node = egg_asn1x_node (asn, "pathLenConstraint", NULL);
+ if (!egg_asn1x_have (node))
+ *path_len = -1;
+ else if (!egg_asn1x_get_integer_as_ulong (node, &value))
+ ret = FALSE;
+ else
+ *path_len = value;
+ }
+
+ if (is_ca) {
+ node = egg_asn1x_node (asn, "cA", NULL);
+ if (!egg_asn1x_have (node))
+ *is_ca = FALSE;
+ else if (!egg_asn1x_get_boolean (node, is_ca))
+ ret = FALSE;
+ }
+
+ egg_asn1x_destroy (asn);
+ return ret;
+}
+
+GQuark*
+_gcr_certificate_extension_extended_key_usage (gconstpointer data, gsize n_data)
+{
+ GNode *asn = NULL;
+ GNode *node;
+ GArray *array;
+ GQuark oid;
+ int i;
+
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "ExtKeyUsageSyntax", data, n_data);
+ if (asn == NULL)
+ return NULL;
+
+ array = g_array_new (TRUE, TRUE, sizeof (GQuark));
+ for (i = 0; TRUE; ++i) {
+ node = egg_asn1x_node (asn, i + 1, NULL);
+ if (node == NULL)
+ break;
+ oid = egg_asn1x_get_oid_as_quark (node);
+ g_array_append_val (array, oid);
+ }
+
+ egg_asn1x_destroy (asn);
+ return (GQuark*)g_array_free (array, FALSE);
+}
+
+gpointer
+_gcr_certificate_extension_subject_key_identifier (gconstpointer data, gsize n_data,
+ gsize *n_keyid)
+{
+ GNode *asn = NULL;
+ gpointer result;
+
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SubjectKeyIdentifier", data, n_data);
+ if (asn == NULL)
+ return NULL;
+
+ result = egg_asn1x_get_string_as_raw (asn, g_realloc, n_keyid);
+ egg_asn1x_destroy (asn);
+
+ return result;
+}
+
+gboolean
+_gcr_certificate_extension_key_usage (gconstpointer data, gsize n_data,
+ gulong *key_usage)
+{
+ GNode *asn = NULL;
+ gboolean ret = TRUE;
+ guint n_bits;
+
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "KeyUsage", data, n_data);
+ if (asn == NULL)
+ return FALSE;
+
+ ret = egg_asn1x_get_bits_as_ulong (asn, key_usage, &n_bits);
+ egg_asn1x_destroy (asn);
+ return ret;
+}
+
+static void
+general_name_parse_other (GNode *node, GcrGeneralName *general)
+{
+ general->type = GCR_GENERAL_NAME_OTHER;
+ general->description = _("Other Name");
+}
+
+static void
+general_name_parse_rfc822 (GNode *node, GcrGeneralName *general)
+{
+ general->type = GCR_GENERAL_NAME_RFC822;
+ general->description = _("Email");
+ general->display = egg_asn1x_get_string_as_utf8 (node, g_realloc);
+}
+
+static void
+general_name_parse_dns (GNode *node, GcrGeneralName *general)
+{
+ general->type = GCR_GENERAL_NAME_DNS;
+ general->description = _("DNS");
+ general->display = egg_asn1x_get_string_as_utf8 (node, g_realloc);
+}
+
+static void
+general_name_parse_x400 (GNode *node, GcrGeneralName *general)
+{
+ general->type = GCR_GENERAL_NAME_X400;
+ general->description = _("X400 Address");
+}
+
+static void
+general_name_parse_dn (GNode *node, GcrGeneralName *general)
+{
+ general->type = GCR_GENERAL_NAME_DNS;
+ general->description = _("Directory Name");
+ general->display = egg_dn_read (node);
+}
+
+static void
+general_name_parse_edi (GNode *node, GcrGeneralName *general)
+{
+ general->type = GCR_GENERAL_NAME_EDI;
+ general->description = _("EDI Party Name");
+}
+
+static void
+general_name_parse_uri (GNode *node, GcrGeneralName *general)
+{
+ general->type = GCR_GENERAL_NAME_URI;
+ general->description = _("URI");
+ general->display = egg_asn1x_get_string_as_utf8 (node, g_realloc);
+}
+
+static void
+general_name_parse_ip (GNode *node, GcrGeneralName *general)
+{
+ general->type = GCR_GENERAL_NAME_IP;
+ general->description = _("IP Address");
+ general->display = egg_asn1x_get_string_as_utf8 (node, g_realloc);
+}
+
+static void
+general_name_parse_registered (GNode *node, GcrGeneralName *general)
+{
+ general->type = GCR_GENERAL_NAME_REGISTERED_ID;
+ general->description = _("Registered ID");
+ general->display = egg_asn1x_get_oid_as_string (node);
+}
+
+GArray*
+_gcr_certificate_extension_subject_alt_name (gconstpointer data, gsize n_data)
+{
+ GNode *asn = NULL;
+ guint count, i;
+ const gchar *node_name;
+ GArray *names;
+ GcrGeneralName general;
+ GNode *choice;
+
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SubjectAltName", data, n_data);
+ if (asn == NULL)
+ return NULL;
+
+ names = g_array_new (FALSE, TRUE, sizeof (GcrGeneralName));
+ count = egg_asn1x_count (asn);
+
+ for (i = 0; i < count; i++) {
+ choice = egg_asn1x_get_choice (egg_asn1x_node (asn, i + 1, NULL));
+ g_return_val_if_fail (choice, NULL);
+
+ node_name = egg_asn1x_name (choice);
+ g_return_val_if_fail (node_name, NULL);
+
+ memset (&general, 0, sizeof (general));
+
+ if (g_str_equal (node_name, "otherName"))
+ general_name_parse_other (choice, &general);
+
+ else if (g_str_equal (node_name, "rfc822Name"))
+ general_name_parse_rfc822 (choice, &general);
+
+ else if (g_str_equal (node_name, "dNSName"))
+ general_name_parse_dns (choice, &general);
+
+ else if (g_str_equal (node_name, "x400Address"))
+ general_name_parse_x400 (choice, &general);
+
+ else if (g_str_equal (node_name, "directoryName"))
+ general_name_parse_dn (choice, &general);
+
+ else if (g_str_equal (node_name, "ediPartyName"))
+ general_name_parse_edi (choice, &general);
+
+ else if (g_str_equal (node_name, "uniformResourceIdentifier"))
+ general_name_parse_uri (choice, &general);
+
+ else if (g_str_equal (node_name, "IPAddress"))
+ general_name_parse_ip (choice, &general);
+
+ else if (g_str_equal (node_name, "registeredID"))
+ general_name_parse_registered (choice, &general);
+
+ general.raw = egg_asn1x_get_raw_value (choice, &general.n_raw);
+ g_array_append_val (names, general);
+ }
+
+ egg_asn1x_destroy (asn);
+ return names;
+}
+
+void
+_gcr_general_names_free (GArray *names)
+{
+ guint i;
+
+ for (i = 0; names && i < names->len; i++)
+ g_free (g_array_index (names, GcrGeneralName, i).display);
+ g_array_free (names, TRUE);
+}
diff --git a/gcr/gcr-certificate-extensions.h b/gcr/gcr-certificate-extensions.h
new file mode 100644
index 0000000..ab22d42
--- /dev/null
+++ b/gcr/gcr-certificate-extensions.h
@@ -0,0 +1,88 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#if !defined (__GCR_H_INSIDE__) && !defined (GCR_COMPILATION)
+#error "Only <gcr/gcr.h> can be included directly."
+#endif
+
+#ifndef GCR_CERTIFICATE_EXTENSIONS_H
+#define GCR_CERTIFICATE_EXTENSIONS_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+gboolean _gcr_certificate_extension_basic_constraints (gconstpointer data,
+ gsize n_data,
+ gboolean *is_ca,
+ gint *path_len);
+
+GQuark* _gcr_certificate_extension_extended_key_usage (gconstpointer data,
+ gsize n_data);
+
+gpointer _gcr_certificate_extension_subject_key_identifier (gconstpointer data,
+ gsize n_data,
+ gsize *n_keyid);
+
+typedef enum {
+ GCR_KEY_USAGE_DIGITAL_SIGNATURE = 1 << 0,
+ GCR_KEY_USAGE_NON_REPUDIATION = 1 << 1,
+ GCR_KEY_USAGE_KEY_ENCIPHERMENT = 1 << 2,
+ GCR_KEY_USAGE_DATA_ENCIPHERMENT = 1 << 3,
+ GCR_KEY_USAGE_KEY_AGREEMENT = 1 << 4,
+ GCR_KEY_USAGE_KEY_CERT_SIGN = 1 << 5,
+ GCR_KEY_USAGE_CRL_SIGN = 1 << 6,
+} GcrCertificateExtensionKeyUsage;
+
+gboolean _gcr_certificate_extension_key_usage (gconstpointer data,
+ gsize n_data,
+ gulong *key_usage);
+
+typedef enum {
+ GCR_GENERAL_NAME_OTHER,
+ GCR_GENERAL_NAME_RFC822,
+ GCR_GENERAL_NAME_DNS,
+ GCR_GENERAL_NAME_X400,
+ GCR_GENERAL_NAME_DN,
+ GCR_GENERAL_NAME_EDI,
+ GCR_GENERAL_NAME_URI,
+ GCR_GENERAL_NAME_IP,
+ GCR_GENERAL_NAME_REGISTERED_ID,
+} GcrGeneralNameType;
+
+typedef struct {
+ GcrGeneralNameType type;
+ const gchar *description;
+ gchar *display;
+ gconstpointer raw;
+ gsize n_raw;
+} GcrGeneralName;
+
+GArray * _gcr_certificate_extension_subject_alt_name (gconstpointer data,
+ gsize n_data);
+
+void _gcr_general_names_free (GArray *names);
+
+G_END_DECLS
+
+#endif /* GCR_CERTIFICATE_H */
diff --git a/gcr/gcr-certificate-renderer.c b/gcr/gcr-certificate-renderer.c
index 45a7f40..9f965aa 100644
--- a/gcr/gcr-certificate-renderer.c
+++ b/gcr/gcr-certificate-renderer.c
@@ -21,6 +21,7 @@
#include "gcr-certificate.h"
#include "gcr-certificate-exporter.h"
+#include "gcr-certificate-extensions.h"
#include "gcr-certificate-renderer.h"
#include "gcr-display-view.h"
#include "gcr-fingerprint.h"
@@ -75,6 +76,12 @@ G_DEFINE_TYPE_WITH_CODE (GcrCertificateRenderer, gcr_certificate_renderer, G_TYP
G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, gcr_renderer_certificate_iface_init);
);
+static GQuark OID_BASIC_CONSTRAINTS = 0;
+static GQuark OID_EXTENDED_KEY_USAGE = 0;
+static GQuark OID_SUBJECT_KEY_IDENTIFIER = 0;
+static GQuark OID_KEY_USAGE = 0;
+static GQuark OID_SUBJECT_ALT_NAME = 0;
+
/* -----------------------------------------------------------------------------
* INTERNAL
*/
@@ -100,6 +107,173 @@ calculate_label (GcrCertificateRenderer *self)
}
static gboolean
+append_extension_basic_constraints (GcrCertificateRenderer *self, GcrDisplayView *view,
+ gconstpointer data, gsize n_data)
+{
+ GcrRenderer *renderer = GCR_RENDERER (self);
+ gboolean is_ca = FALSE;
+ gint path_len = -1;
+ gchar *number;
+
+ if (!_gcr_certificate_extension_basic_constraints (data, n_data, &is_ca, &path_len))
+ return FALSE;
+
+ _gcr_display_view_append_heading (view, renderer, _("Basic Constraints"));
+
+ _gcr_display_view_append_value (view, renderer, _("Certificate Authority"),
+ is_ca ? _("Yes") : _("No"), FALSE);
+
+ number = g_strdup_printf ("%d", path_len);
+ _gcr_display_view_append_value (view, renderer, _("Max Path Length"),
+ path_len < 0 ? _("Unlimited") : number, FALSE);
+ g_free (number);
+
+ return TRUE;
+}
+
+static gboolean
+append_extension_extended_key_usage (GcrCertificateRenderer *self, GcrDisplayView *view,
+ gconstpointer data, gsize n_data)
+{
+ GcrRenderer *renderer = GCR_RENDERER (self);
+ GQuark *oids;
+ GString *text;
+ guint i;
+
+ oids = _gcr_certificate_extension_extended_key_usage (data, n_data);
+ if (oids == NULL)
+ return FALSE;
+
+ _gcr_display_view_append_heading (view, renderer, _("Extended Key Usage"));
+
+ text = g_string_new ("");
+ for (i = 0; oids[i] != 0; i++) {
+ if (i > 0)
+ g_string_append_unichar (text, GCR_DISPLAY_VIEW_LINE_BREAK);
+ g_string_append (text, egg_oid_get_description (oids[i]));
+ }
+
+ g_free (oids);
+
+ _gcr_display_view_append_value (view, renderer, _("Allowed Purposes"),
+ text->str, FALSE);
+
+ g_string_free (text, TRUE);
+
+ return TRUE;
+}
+
+static gboolean
+append_extension_subject_key_identifier (GcrCertificateRenderer *self, GcrDisplayView *view,
+ gconstpointer data, gsize n_data)
+{
+ GcrRenderer *renderer = GCR_RENDERER (self);
+ gpointer keyid;
+ gsize n_keyid;
+
+ keyid = _gcr_certificate_extension_subject_key_identifier (data, n_data, &n_keyid);
+ if (keyid == NULL)
+ return FALSE;
+
+ _gcr_display_view_append_heading (view, renderer, _("Subject Key Identifier"));
+ _gcr_display_view_append_hex (view, renderer, _("Key Identifier"), keyid, n_keyid);
+
+ g_free (keyid);
+
+ return TRUE;
+}
+
+static const struct {
+ guint usage;
+ const gchar *description;
+} usage_descriptions[] = {
+ { GCR_KEY_USAGE_DIGITAL_SIGNATURE, N_("Digital signature") },
+ { GCR_KEY_USAGE_KEY_ENCIPHERMENT, N_("Key encipherment") },
+ { GCR_KEY_USAGE_DATA_ENCIPHERMENT, N_("Data encipherment") },
+ { GCR_KEY_USAGE_KEY_AGREEMENT, N_("Key agreement") },
+ { GCR_KEY_USAGE_KEY_CERT_SIGN, N_("Certificate signature") },
+ { GCR_KEY_USAGE_CRL_SIGN, N_("Revocation list signature") }
+};
+
+static gboolean
+append_extension_key_usage (GcrCertificateRenderer *self, GcrDisplayView *view,
+ gconstpointer data, gsize n_data)
+{
+ GcrRenderer *renderer = GCR_RENDERER (self);
+ gulong key_usage;
+ GString *text;
+ guint i;
+
+ if (!_gcr_certificate_extension_key_usage (data, n_data, &key_usage))
+ return FALSE;
+
+ text = g_string_new ("");
+
+ for (i = 0; i < G_N_ELEMENTS (usage_descriptions); i++) {
+ if (key_usage & usage_descriptions[i].usage) {
+ if (text->len > 0)
+ g_string_append_unichar (text, GCR_DISPLAY_VIEW_LINE_BREAK);
+ g_string_append (text, gettext (usage_descriptions[i].description));
+ }
+ }
+
+ _gcr_display_view_append_heading (view, renderer, _("Key Usage"));
+ _gcr_display_view_append_value (view, renderer, _("Usages"), text->str, FALSE);
+
+ g_string_free (text, TRUE);
+
+ return TRUE;
+}
+
+static gboolean
+append_extension_subject_alt_name (GcrCertificateRenderer *self, GcrDisplayView *view,
+ gconstpointer data, gsize n_data)
+{
+ GcrRenderer *renderer = GCR_RENDERER (self);
+ GArray *general_names;
+ GcrGeneralName *general;
+ guint i;
+
+ general_names = _gcr_certificate_extension_subject_alt_name (data, n_data);
+ if (general_names == NULL)
+ return FALSE;
+
+ _gcr_display_view_append_heading (view, renderer, _("Subject Alternative Names"));
+
+ for (i = 0; i < general_names->len; i++) {
+ general = &g_array_index (general_names, GcrGeneralName, i);
+ if (general->display == NULL)
+ _gcr_display_view_append_hex (view, renderer, general->description,
+ general->raw, general->n_raw);
+ else
+ _gcr_display_view_append_value (view, renderer, general->description,
+ general->display, FALSE);
+ }
+
+ _gcr_general_names_free (general_names);
+
+ return TRUE;
+}
+
+
+static gboolean
+append_extension_hex (GcrCertificateRenderer *self, GcrDisplayView *view,
+ GQuark oid, gconstpointer data, gsize n_data)
+{
+ GcrRenderer *renderer = GCR_RENDERER (self);
+ const gchar *text;
+
+ _gcr_display_view_append_heading (view, renderer, _("Extension"));
+
+ /* Extension type */
+ text = egg_oid_get_description (oid);
+ _gcr_display_view_append_value (view, renderer, _("Identifier"), text, FALSE);
+ _gcr_display_view_append_hex (view, renderer, _("Value"), data, n_data);
+
+ return TRUE;
+}
+
+static gboolean
append_extension (GcrCertificateRenderer *self, GcrDisplayView *view,
GNode *asn, const guchar *data, gsize n_data, gint index)
{
@@ -108,8 +282,8 @@ append_extension (GcrCertificateRenderer *self, GcrDisplayView *view,
GQuark oid;
gsize n_value;
const guchar *value;
- const gchar *text;
gboolean critical;
+ gboolean ret = FALSE;
/* Make sure it is present */
node = egg_asn1x_node (asn, "tbsCertificate", "extensions", index, NULL);
@@ -120,26 +294,32 @@ append_extension (GcrCertificateRenderer *self, GcrDisplayView *view,
oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (node, "extnID", NULL));
g_return_val_if_fail (oid, FALSE);
- _gcr_display_view_append_heading (view, renderer, _("Extension"));
-
-
- /* Extension type */
- text = egg_oid_get_description (oid);
- _gcr_display_view_append_value (view, renderer, _("Identifier"), text, FALSE);
-
-
/* Extension value */
value = egg_asn1x_get_raw_value (egg_asn1x_node (node, "extnValue", NULL), &n_value);
- /* TODO: Parsing of extensions that we understand */
- _gcr_display_view_append_hex (view, renderer, _("Value"), value, n_value);
-
+ /* The custom parsers */
+ if (oid == OID_BASIC_CONSTRAINTS)
+ ret = append_extension_basic_constraints (self, view, value, n_value);
+ else if (oid == OID_EXTENDED_KEY_USAGE)
+ ret = append_extension_extended_key_usage (self, view, value, n_value);
+ else if (oid == OID_SUBJECT_KEY_IDENTIFIER)
+ ret = append_extension_subject_key_identifier (self, view, value, n_value);
+ else if (oid == OID_KEY_USAGE)
+ ret = append_extension_key_usage (self, view, value, n_value);
+ else if (oid == OID_SUBJECT_ALT_NAME)
+ ret = append_extension_subject_alt_name (self, view, value, n_value);
+
+ /* Otherwise the default raw display */
+ if (ret == FALSE)
+ ret = append_extension_hex (self, view, oid, value, n_value);
/* Critical */
- if (egg_asn1x_get_boolean (egg_asn1x_node (node, "critical", NULL), &critical))
- _gcr_display_view_append_value (view, renderer, _("Critical"), critical ? _("Yes") : _("No"), FALSE);
+ if (ret == TRUE && egg_asn1x_get_boolean (egg_asn1x_node (node, "critical", NULL), &critical)) {
+ _gcr_display_view_append_value (view, renderer, _("Critical"),
+ critical ? _("Yes") : _("No"), FALSE);
+ }
- return TRUE;
+ return ret;
}
typedef struct _on_parsed_dn_args {
@@ -336,6 +516,12 @@ gcr_certificate_renderer_class_init (GcrCertificateRendererClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GckAttributes *registered;
+ OID_SUBJECT_KEY_IDENTIFIER = g_quark_from_static_string ("2.5.29.14");
+ OID_BASIC_CONSTRAINTS = g_quark_from_static_string ("2.5.29.19");
+ OID_EXTENDED_KEY_USAGE = g_quark_from_static_string ("2.5.29.37");
+ OID_KEY_USAGE = g_quark_from_static_string ("2.5.29.15");
+ OID_SUBJECT_ALT_NAME = g_quark_from_static_string ("2.5.29.17");
+
gcr_certificate_renderer_parent_class = g_type_class_peek_parent (klass);
g_type_class_add_private (klass, sizeof (GcrCertificateRendererPrivate));
diff --git a/gcr/gcr-display-view.h b/gcr/gcr-display-view.h
index 5bd85d3..5f0f2ee 100644
--- a/gcr/gcr-display-view.h
+++ b/gcr/gcr-display-view.h
@@ -29,6 +29,8 @@
G_BEGIN_DECLS
+#define GCR_DISPLAY_VIEW_LINE_BREAK 0x2028
+
#define GCR_TYPE_DISPLAY_VIEW (_gcr_display_view_get_type ())
#define GCR_DISPLAY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_DISPLAY_VIEW, GcrDisplayView))
#define GCR_DISPLAY_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_DISPLAY_VIEW, GcrDisplayViewClass))
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 59d7bf6..d47be72 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -14,6 +14,7 @@ egg/egg-oid.c
egg/egg-spawn.c
gcr/gcr-certificate.c
gcr/gcr-certificate-exporter.c
+gcr/gcr-certificate-extensions.c
gcr/gcr-certificate-renderer.c
gcr/gcr-certificate-widget.c
gcr/gcr-display-view.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]