From 1034f9afc591674647755273c074ebe007c5ee86 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Wed, 6 Apr 2011 12:22:24 +0200 Subject: [PATCH] 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 + 6 files changed, 577 insertions(+), 30 deletions(-) create mode 100644 gcr/gcr-certificate-extensions.c create mode 100644 gcr/gcr-certificate-extensions.h diff --git a/egg/egg-oid.c b/egg/egg-oid.c index e026c0f..4f2da9c 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 5196618..bec3711 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 + */ +#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 + +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 + */ + +#if !defined (__GCR_H_INSIDE__) && !defined (GCR_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef GCR_CERTIFICATE_EXTENSIONS_H +#define GCR_CERTIFICATE_EXTENSIONS_H + +#include + +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)) -- 2.7.4