gcr: Add support for viewing certificate requests
authorStef Walter <stefw@collabora.co.uk>
Tue, 8 Nov 2011 08:32:32 +0000 (09:32 +0100)
committerStef Walter <stefw@collabora.co.uk>
Wed, 23 Nov 2011 08:10:50 +0000 (09:10 +0100)
 * Both PKCS#10/CSR and SPKAC
 * Update mime database for SPKAC and CSR
 * Associate viewer with these files

https://bugzilla.gnome.org/show_bug.cgi?id=663604

19 files changed:
egg/pkix.asn
gcr/Makefile.am
gcr/gcr-certificate-renderer-private.h [new file with mode: 0644]
gcr/gcr-certificate-renderer.c
gcr/gcr-certificate-req-renderer.c [new file with mode: 0644]
gcr/gcr-certificate-req-renderer.h [new file with mode: 0644]
gcr/gcr-certificate.c
gcr/gcr-crypto-types.xml
gcr/gcr-key-size.c [new file with mode: 0644]
gcr/gcr-key-size.h [new file with mode: 0644]
gcr/gcr-oids.list
gcr/gcr-renderer.c
gcr/gcr-types.h
gcr/gcr-viewer.desktop.in
gcr/gcr-viewer.desktop.in.in
gcr/tests/Makefile.am
gcr/tests/files/pem-with-attributes.req [new file with mode: 0644]
gcr/tests/frob-request.c [new file with mode: 0644]
po/POTFILES.in

index 6cf966b..02c2732 100644 (file)
@@ -1240,4 +1240,9 @@ SignedPublicKeyAndChallenge ::= SEQUENCE {
        signature BIT STRING
 }
 
+-- pkcs-9 extension requests: added by gnome-keyring
+-- http://mirror.switch.ch/ftp/doc/standard/pkcs/pkcs-9/pkcs-9.txt
+
+ExtensionRequest ::= SEQUENCE OF Extension
+
 END
index ebb4cc8..2045125 100644 (file)
@@ -113,6 +113,7 @@ libgcr_base_@GCR_MAJOR@_la_SOURCES = \
        gcr-importer.c gcr-importer.h \
        gcr-import-interaction.c gcr-import-interaction.h \
        gcr-internal.h \
+       gcr-key-size.c gcr-key-size.h \
        gcr-library.c gcr-library.h \
        gcr-memory.c \
        gcr-memory-icon.c gcr-memory-icon.h \
@@ -138,6 +139,7 @@ libgcr_@GCR_MAJOR@_la_SOURCES = \
        gcr-certificate-exporter.c gcr-certificate-exporter.h \
        gcr-certificate-extensions.c gcr-certificate-extensions.h \
        gcr-certificate-renderer.c gcr-certificate-renderer.h \
+       gcr-certificate-req-renderer.c gcr-certificate-req-renderer.h \
        gcr-certificate-widget.c gcr-certificate-widget.h \
        gcr-collection-model.c gcr-collection-model.h \
        gcr-combo-selector.c gcr-combo-selector.h \
@@ -150,6 +152,7 @@ libgcr_@GCR_MAJOR@_la_SOURCES = \
        gcr-gnupg-records.c gcr-gnupg-records.h \
        gcr-import-button.c gcr-import-button.h \
        gcr-key-renderer.c gcr-key-renderer.h \
+       gcr-key-size.c gcr-key-size.h \
        gcr-key-widget.c gcr-key-widget.h \
        gcr-list-selector.c gcr-list-selector.h gcr-list-selector-private.h \
        gcr-live-search.c gcr-live-search.h \
diff --git a/gcr/gcr-certificate-renderer-private.h b/gcr/gcr-certificate-renderer-private.h
new file mode 100644 (file)
index 0000000..f7dadbf
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 Stefan Walter
+ *
+ * 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.
+ */
+
+#if !defined (__GCR_INSIDE_HEADER__) && !defined (GCR_COMPILATION)
+#error "Only <gcr/gcr.h> or <gcr/gcr-base.h> can be included directly."
+#endif
+
+#ifndef __GCR_CERTIFICATE_RENDERER_PRIVATE_H__
+#define __GCR_CERTIFICATE_RENDERER_PRIVATE_H__
+
+#include "gcr-display-view.h"
+#include "gcr-renderer.h"
+
+G_BEGIN_DECLS
+
+void      _gcr_certificate_renderer_append_distinguished_name        (GcrRenderer *renderer,
+                                                                      GcrDisplayView *view,
+                                                                      GNode *dn);
+
+void      _gcr_certificate_renderer_append_subject_public_key        (GcrRenderer *renderer,
+                                                                      GcrDisplayView *view,
+                                                                      guint key_size,
+                                                                      GNode *subject_public_key);
+
+void      _gcr_certificate_renderer_append_signature                 (GcrRenderer *renderer,
+                                                                      GcrDisplayView *view,
+                                                                      GNode *asn);
+
+void      _gcr_certificate_renderer_append_extension                 (GcrRenderer *renderer,
+                                                                      GcrDisplayView *view,
+                                                                      GNode *asn);
+
+G_END_DECLS
+
+#endif /* __GCR_CERTIFICATE_RENDERER_PRIVATE_H__ */
index ebceda3..ae3f73c 100644 (file)
@@ -23,6 +23,7 @@
 #include "gcr-certificate-exporter.h"
 #include "gcr-certificate-extensions.h"
 #include "gcr-certificate-renderer.h"
+#include "gcr-certificate-renderer-private.h"
 #include "gcr-display-view.h"
 #include "gcr-fingerprint.h"
 #include "gcr-icons.h"
@@ -102,11 +103,10 @@ calculate_label (GcrCertificateRenderer *self)
 }
 
 static gboolean
-append_extension_basic_constraints (GcrCertificateRenderer *self,
+append_extension_basic_constraints (GcrRenderer *renderer,
                                     GcrDisplayView *view,
                                     EggBytes *data)
 {
-       GcrRenderer *renderer = GCR_RENDERER (self);
        gboolean is_ca = FALSE;
        gint path_len = -1;
        gchar *number;
@@ -128,11 +128,10 @@ append_extension_basic_constraints (GcrCertificateRenderer *self,
 }
 
 static gboolean
-append_extension_extended_key_usage (GcrCertificateRenderer *self,
+append_extension_extended_key_usage (GcrRenderer *renderer,
                                      GcrDisplayView *view,
                                      EggBytes *data)
 {
-       GcrRenderer *renderer = GCR_RENDERER (self);
        GQuark *oids;
        GString *text;
        guint i;
@@ -161,11 +160,10 @@ append_extension_extended_key_usage (GcrCertificateRenderer *self,
 }
 
 static gboolean
-append_extension_subject_key_identifier (GcrCertificateRenderer *self,
+append_extension_subject_key_identifier (GcrRenderer *renderer,
                                          GcrDisplayView *view,
                                          EggBytes *data)
 {
-       GcrRenderer *renderer = GCR_RENDERER (self);
        gpointer keyid;
        gsize n_keyid;
 
@@ -194,11 +192,10 @@ static const struct {
 };
 
 static gboolean
-append_extension_key_usage (GcrCertificateRenderer *self,
+append_extension_key_usage (GcrRenderer *renderer,
                             GcrDisplayView *view,
                             EggBytes *data)
 {
-       GcrRenderer *renderer = GCR_RENDERER (self);
        gulong key_usage;
        GString *text;
        guint i;
@@ -225,11 +222,10 @@ append_extension_key_usage (GcrCertificateRenderer *self,
 }
 
 static gboolean
-append_extension_subject_alt_name (GcrCertificateRenderer *self,
+append_extension_subject_alt_name (GcrRenderer *renderer,
                                    GcrDisplayView *view,
                                    EggBytes *data)
 {
-       GcrRenderer *renderer = GCR_RENDERER (self);
        GArray *general_names;
        GcrGeneralName *general;
        guint i;
@@ -256,12 +252,13 @@ append_extension_subject_alt_name (GcrCertificateRenderer *self,
        return TRUE;
 }
 
-
 static gboolean
-append_extension_hex (GcrCertificateRenderer *self, GcrDisplayView *view,
-                      GQuark oid, gconstpointer data, gsize n_data)
+append_extension_hex (GcrRenderer *renderer,
+                      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"));
@@ -275,107 +272,6 @@ append_extension_hex (GcrCertificateRenderer *self, GcrDisplayView *view,
 }
 
 static gboolean
-append_extension (GcrCertificateRenderer *self,
-                  GcrDisplayView *view,
-                  GNode *asn,
-                  gint index)
-{
-       GcrRenderer *renderer = GCR_RENDERER (self);
-       GNode *node;
-       GQuark oid;
-       EggBytes *value;
-       gboolean critical;
-       gboolean ret = FALSE;
-
-       /* Make sure it is present */
-       node = egg_asn1x_node (asn, "tbsCertificate", "extensions", index, NULL);
-       if (node == NULL)
-               return FALSE;
-
-       /* Dig out the OID */
-       oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (node, "extnID", NULL));
-       g_return_val_if_fail (oid, FALSE);
-
-       /* Extension value */
-       value = egg_asn1x_get_raw_value (egg_asn1x_node (node, "extnValue", NULL));
-
-       /* The custom parsers */
-       if (oid == GCR_OID_BASIC_CONSTRAINTS)
-               ret = append_extension_basic_constraints (self, view, value);
-       else if (oid == GCR_OID_EXTENDED_KEY_USAGE)
-               ret = append_extension_extended_key_usage (self, view, value);
-       else if (oid == GCR_OID_SUBJECT_KEY_IDENTIFIER)
-               ret = append_extension_subject_key_identifier (self, view, value);
-       else if (oid == GCR_OID_KEY_USAGE)
-               ret = append_extension_key_usage (self, view, value);
-       else if (oid == GCR_OID_SUBJECT_ALT_NAME)
-               ret = append_extension_subject_alt_name (self, view, value);
-
-       /* Otherwise the default raw display */
-       if (ret == FALSE)
-               ret = append_extension_hex (self, view, oid,
-                                           egg_bytes_get_data (value),
-                                           egg_bytes_get_size (value));
-
-       /* Critical */
-       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);
-       }
-
-       egg_bytes_unref (value);
-       return ret;
-}
-
-typedef struct _on_parsed_dn_args {
-       GcrCertificateRenderer *renderer;
-       GcrDisplayView *view;
-} on_parsed_dn_args;
-
-static void
-on_parsed_dn_part (guint index,
-                   GQuark oid,
-                   EggBytes *value,
-                   gpointer user_data)
-{
-       GcrCertificateRenderer *self = ((on_parsed_dn_args*)user_data)->renderer;
-       GcrDisplayView *view = ((on_parsed_dn_args*)user_data)->view;
-       const gchar *attr;
-       const gchar *desc;
-       gchar *field = NULL;
-       gchar *display;
-
-       g_return_if_fail (GCR_IS_CERTIFICATE_RENDERER (self));
-
-       attr = egg_oid_get_name (oid);
-       desc = egg_oid_get_description (oid);
-
-       /* Combine them into something sane */
-       if (attr && desc) {
-               if (strcmp (attr, desc) == 0)
-                       field = g_strdup (attr);
-               else
-                       field = g_strdup_printf ("%s (%s)", attr, desc);
-       } else if (!attr && !desc) {
-               field = g_strdup ("");
-       } else if (attr) {
-               field = g_strdup (attr);
-       } else if (desc) {
-               field = g_strdup (desc);
-       } else {
-               g_assert_not_reached ();
-       }
-
-       display = egg_dn_print_value (oid, value);
-       if (display == NULL)
-               display = g_strdup ("");
-
-       _gcr_display_view_append_value (view, GCR_RENDERER (self), field, display, FALSE);
-       g_free (field);
-       g_free (display);
-}
-
-static gboolean
 on_delete_unref_dialog (GtkWidget *widget, GdkEvent *event, gpointer data)
 {
        g_object_unref (widget);
@@ -574,21 +470,17 @@ static void
 gcr_certificate_renderer_render (GcrRenderer *renderer, GcrViewer *viewer)
 {
        GcrCertificateRenderer *self;
+       GNode *extension;
        gconstpointer data;
-       gsize n_data, n_raw;
+       gsize n_data;
        GcrDisplayView *view;
-       on_parsed_dn_args args;
-       const gchar *text;
        GcrCertificate *cert;
-       gpointer raw;
        EggBytes *number;
        gulong version;
        guint bits, index;
        gchar *display;
        EggBytes *bytes;
-       EggBytes *value;
        GNode *asn;
-       GQuark oid;
        GDate date;
        GIcon *icon;
 
@@ -643,16 +535,15 @@ gcr_certificate_renderer_render (GcrRenderer *renderer, GcrViewer *viewer)
 
        _gcr_display_view_start_details (view, renderer);
 
-       args.renderer = self;
-       args.view = view;
-
        /* The subject */
        _gcr_display_view_append_heading (view, renderer, _("Subject Name"));
-       egg_dn_parse (egg_asn1x_node (asn, "tbsCertificate", "subject", "rdnSequence", NULL), on_parsed_dn_part, &args);
+       _gcr_certificate_renderer_append_distinguished_name (renderer, view,
+                                                            egg_asn1x_node (asn, "tbsCertificate", "subject", "rdnSequence", NULL));
 
        /* The Issuer */
        _gcr_display_view_append_heading (view, renderer, _("Issuer Name"));
-       egg_dn_parse (egg_asn1x_node (asn, "tbsCertificate", "issuer", "rdnSequence", NULL), on_parsed_dn_part, &args);
+       _gcr_certificate_renderer_append_distinguished_name (renderer, view,
+                                                            egg_asn1x_node (asn, "tbsCertificate", "issuer", "rdnSequence", NULL));
 
        /* The Issued Parameters */
        _gcr_display_view_append_heading (view, renderer, _("Issued Certificate"));
@@ -689,73 +580,25 @@ gcr_certificate_renderer_render (GcrRenderer *renderer, GcrViewer *viewer)
        _gcr_display_view_append_fingerprint (view, renderer, data, n_data, "SHA1", G_CHECKSUM_SHA1);
        _gcr_display_view_append_fingerprint (view, renderer, data, n_data, "MD5", G_CHECKSUM_MD5);
 
-       /* Signature */
-       _gcr_display_view_append_heading (view, renderer, _("Signature"));
-
-       oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "signatureAlgorithm", "algorithm", NULL));
-       text = egg_oid_get_description (oid);
-       _gcr_display_view_append_value (view, renderer, _("Signature Algorithm"), text, FALSE);
-
-       value = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "signatureAlgorithm", "parameters", NULL));
-       if (value) {
-               _gcr_display_view_append_hex (view, renderer, _("Signature Parameters"),
-                                             egg_bytes_get_data (value),
-                                             egg_bytes_get_size (value));
-               egg_bytes_unref (value);
-       }
-
-       value = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "signature", NULL), &bits);
-       g_return_if_fail (value != NULL);
-       _gcr_display_view_append_hex (view, renderer, _("Signature"),
-                                     egg_bytes_get_data (value), bits / 8);
-       egg_bytes_unref (value);
-
        /* Public Key Info */
        _gcr_display_view_append_heading (view, renderer, _("Public Key Info"));
-
-       oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo",
-                                                         "algorithm", "algorithm", NULL));
-       text = egg_oid_get_description (oid);
-       _gcr_display_view_append_value (view, renderer, _("Key Algorithm"), text, FALSE);
-
-       value = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo",
-                                                          "algorithm", "parameters", NULL));
-       if (value) {
-               _gcr_display_view_append_hex (view, renderer, _("Key Parameters"),
-                                             egg_bytes_get_data (value),
-                                             egg_bytes_get_size (value));
-               egg_bytes_unref (value);
-       }
-
        bits = gcr_certificate_get_key_size (cert);
-       if (bits > 0) {
-               display = g_strdup_printf ("%u", bits);
-               _gcr_display_view_append_value (view, renderer, _("Key Size"), display, FALSE);
-               g_free (display);
-       }
-
-       value = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "tbsCertificate",
-                                                          "subjectPublicKeyInfo", NULL));
-       raw = gcr_fingerprint_from_subject_public_key_info (egg_bytes_get_data (value),
-                                                           egg_bytes_get_size (value),
-                                                           G_CHECKSUM_SHA1, &n_raw);
-       _gcr_display_view_append_hex (view, renderer, _("Key SHA1 Fingerprint"), raw, n_raw);
-       egg_bytes_unref (value);
-       g_free (raw);
-
-       value = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo",
-                                                          "subjectPublicKey", NULL), &bits);
-       g_return_if_fail (value != NULL);
-       _gcr_display_view_append_hex (view, renderer, _("Public Key"),
-                                     egg_bytes_get_data (value), bits / 8);
-       egg_bytes_unref (value);
+       _gcr_certificate_renderer_append_subject_public_key (renderer, view, bits,
+                                                            egg_asn1x_node (asn, "tbsCertificate",
+                                                                            "subjectPublicKeyInfo", NULL));
 
        /* Extensions */
        for (index = 1; TRUE; ++index) {
-               if (!append_extension (self, view, asn, index))
+               extension = egg_asn1x_node (asn, "tbsCertificate", "extensions", index, NULL);
+               if (extension == NULL)
                        break;
+               _gcr_certificate_renderer_append_extension (renderer, view, extension);
        }
 
+       /* Signature */
+       _gcr_display_view_append_heading (view, renderer, _("Signature"));
+       _gcr_certificate_renderer_append_signature (renderer, view, asn);
+
        egg_asn1x_destroy (asn);
        _gcr_display_view_end (view, renderer);
 }
@@ -939,3 +782,184 @@ gcr_certificate_renderer_set_attributes (GcrCertificateRenderer *self, GckAttrib
        g_object_notify (G_OBJECT (self), "attributes");
 
 }
+
+typedef struct {
+       GcrRenderer *renderer;
+       GcrDisplayView *view;
+} AppendDnClosure;
+
+static void
+on_parsed_dn_part (guint index,
+                   GQuark oid,
+                   EggBytes *value,
+                   gpointer user_data)
+{
+       GcrRenderer *renderer = ((AppendDnClosure *)user_data)->renderer;
+       GcrDisplayView *view = ((AppendDnClosure *)user_data)->view;
+       const gchar *attr;
+       const gchar *desc;
+       gchar *field = NULL;
+       gchar *display;
+
+       attr = egg_oid_get_name (oid);
+       desc = egg_oid_get_description (oid);
+
+       /* Combine them into something sane */
+       if (attr && desc) {
+               if (strcmp (attr, desc) == 0)
+                       field = g_strdup (attr);
+               else
+                       field = g_strdup_printf ("%s (%s)", attr, desc);
+       } else if (!attr && !desc) {
+               field = g_strdup ("");
+       } else if (attr) {
+               field = g_strdup (attr);
+       } else if (desc) {
+               field = g_strdup (desc);
+       } else {
+               g_assert_not_reached ();
+       }
+
+       display = egg_dn_print_value (oid, value);
+       if (display == NULL)
+               display = g_strdup ("");
+
+       _gcr_display_view_append_value (view, renderer, field, display, FALSE);
+       g_free (field);
+       g_free (display);
+}
+
+
+void
+_gcr_certificate_renderer_append_distinguished_name (GcrRenderer *renderer,
+                                                     GcrDisplayView *view,
+                                                     GNode *dn)
+{
+       AppendDnClosure closure;
+
+       g_return_if_fail (GCR_IS_RENDERER (renderer));
+       g_return_if_fail (GCR_IS_DISPLAY_VIEW (view));
+       g_return_if_fail (dn != NULL);
+
+       closure.renderer = renderer;
+       closure.view = view;
+       egg_dn_parse (dn, on_parsed_dn_part, &closure);
+}
+
+void
+_gcr_certificate_renderer_append_subject_public_key (GcrRenderer *renderer,
+                                                     GcrDisplayView *view,
+                                                     guint key_nbits,
+                                                     GNode *subject_public_key)
+{
+       const gchar *text;
+       gchar *display;
+       EggBytes *value;
+       guchar *raw;
+       gsize n_raw;
+       GQuark oid;
+       guint bits;
+
+       oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (subject_public_key,
+                                                         "algorithm", "algorithm", NULL));
+       text = egg_oid_get_description (oid);
+       _gcr_display_view_append_value (view, renderer, _("Key Algorithm"), text, FALSE);
+
+       value = egg_asn1x_get_raw_element (egg_asn1x_node (subject_public_key,
+                                                          "algorithm", "parameters", NULL));
+       if (value) {
+               _gcr_display_view_append_hex (view, renderer, _("Key Parameters"),
+                                             egg_bytes_get_data (value),
+                                             egg_bytes_get_size (value));
+               egg_bytes_unref (value);
+       }
+
+       if (key_nbits > 0) {
+               display = g_strdup_printf ("%u", key_nbits);
+               _gcr_display_view_append_value (view, renderer, _("Key Size"), display, FALSE);
+               g_free (display);
+       }
+
+       value = egg_asn1x_get_raw_element (subject_public_key);
+       raw = gcr_fingerprint_from_subject_public_key_info (egg_bytes_get_data (value),
+                                                           egg_bytes_get_size (value),
+                                                           G_CHECKSUM_SHA1, &n_raw);
+       _gcr_display_view_append_hex (view, renderer, _("Key SHA1 Fingerprint"), raw, n_raw);
+       egg_bytes_unref (value);
+       g_free (raw);
+
+       value = egg_asn1x_get_bits_as_raw (egg_asn1x_node (subject_public_key, "subjectPublicKey", NULL), &bits);
+       _gcr_display_view_append_hex (view, renderer, _("Public Key"),
+                                     egg_bytes_get_data (value), bits / 8);
+       egg_bytes_unref (value);
+}
+
+void
+_gcr_certificate_renderer_append_signature (GcrRenderer *renderer,
+                                            GcrDisplayView *view,
+                                            GNode *asn)
+{
+       const gchar *text;
+       EggBytes *value;
+       GQuark oid;
+       guint bits;
+
+       oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "signatureAlgorithm", "algorithm", NULL));
+       text = egg_oid_get_description (oid);
+       _gcr_display_view_append_value (view, renderer, _("Signature Algorithm"), text, FALSE);
+
+       value = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "signatureAlgorithm", "parameters", NULL));
+       if (value) {
+               _gcr_display_view_append_hex (view, renderer, _("Signature Parameters"),
+                                             egg_bytes_get_data (value),
+                                             egg_bytes_get_size (value));
+               egg_bytes_unref (value);
+       }
+
+       value = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "signature", NULL), &bits);
+       _gcr_display_view_append_hex (view, renderer, _("Signature"),
+                                     egg_bytes_get_data (value), bits / 8);
+       egg_bytes_unref (value);
+}
+
+void
+_gcr_certificate_renderer_append_extension (GcrRenderer *renderer,
+                                            GcrDisplayView *view,
+                                            GNode *node)
+{
+       GQuark oid;
+       EggBytes *value;
+       gboolean critical;
+       gboolean ret = FALSE;
+
+       /* Dig out the OID */
+       oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (node, "extnID", NULL));
+       g_return_if_fail (oid);
+
+       /* Extension value */
+       value = egg_asn1x_get_raw_value (egg_asn1x_node (node, "extnValue", NULL));
+
+       /* The custom parsers */
+       if (oid == GCR_OID_BASIC_CONSTRAINTS)
+               ret = append_extension_basic_constraints (renderer, view, value);
+       else if (oid == GCR_OID_EXTENDED_KEY_USAGE)
+               ret = append_extension_extended_key_usage (renderer, view, value);
+       else if (oid == GCR_OID_SUBJECT_KEY_IDENTIFIER)
+               ret = append_extension_subject_key_identifier (renderer, view, value);
+       else if (oid == GCR_OID_KEY_USAGE)
+               ret = append_extension_key_usage (renderer, view, value);
+       else if (oid == GCR_OID_SUBJECT_ALT_NAME)
+               ret = append_extension_subject_alt_name (renderer, view, value);
+
+       /* Otherwise the default raw display */
+       if (ret == FALSE)
+               ret = append_extension_hex (renderer, view, oid,
+                                           egg_bytes_get_data (value),
+                                           egg_bytes_get_size (value));
+
+       /* Critical */
+       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);
+       }
+}
diff --git a/gcr/gcr-certificate-req-renderer.c b/gcr/gcr-certificate-req-renderer.c
new file mode 100644 (file)
index 0000000..78ebad6
--- /dev/null
@@ -0,0 +1,550 @@
+/*
+ * Copyright (C) 2010 Stefan Walter
+ *
+ * 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.
+ */
+
+#include "config.h"
+
+#include "gcr-certificate-renderer-private.h"
+#include "gcr-certificate-req-renderer.h"
+#include "gcr-display-view.h"
+#include "gcr-key-size.h"
+#include "gcr-oids.h"
+
+#if 0
+#include "gcr-certificate.h"
+#include "gcr-certificate-exporter.h"
+#include "gcr-certificate-extensions.h"
+#include "gcr-certificate-renderer.h"
+#include "gcr-fingerprint.h"
+#include "gcr-icons.h"
+#include "gcr-oids.h"
+#include "gcr-simple-certificate.h"
+#include "gcr-renderer.h"
+#endif
+
+#include "egg/egg-asn1x.h"
+#include "egg/egg-asn1-defs.h"
+#include "egg/egg-dn.h"
+#include "egg/egg-oid.h"
+
+#include "gck/gck.h"
+
+#include <glib/gi18n-lib.h>
+
+/**
+ * GcrCertificateReqRenderer:
+ *
+ * An implementation of #GcrRenderer which renders certificate requests
+ */
+
+/**
+ * GcrCertificateReqRendererClass:
+ * @parent_class: The parent class
+ *
+ * The class for #GcrCertificateReqRenderer
+ */
+
+enum {
+       PROP_0,
+       PROP_LABEL,
+       PROP_ATTRIBUTES
+};
+
+struct _GcrCertificateReqRendererPrivate {
+       GckAttributes *attrs;
+       gchar *label;
+
+       guint key_size;
+       gulong type;
+       GNode *asn;
+};
+
+static void     _gcr_certificate_req_renderer_iface    (GcrRendererIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GcrCertificateReqRenderer, _gcr_certificate_req_renderer, G_TYPE_OBJECT,
+       G_IMPLEMENT_INTERFACE (GCR_TYPE_RENDERER, _gcr_certificate_req_renderer_iface);
+);
+
+static gchar*
+calculate_label (GcrCertificateReqRenderer *self)
+{
+       gchar *label = NULL;
+
+       if (self->pv->label)
+               return g_strdup (self->pv->label);
+
+       if (self->pv->attrs) {
+               if (gck_attributes_find_string (self->pv->attrs, CKA_LABEL, &label))
+                       return label;
+       }
+
+       if (self->pv->asn && self->pv->type == CKQ_GCR_PKCS10) {
+               label = egg_dn_read_part (egg_asn1x_node (self->pv->asn,
+                                                         "certificationRequestInfo",
+                                                         "subject",
+                                                         "rdnSequence",
+                                                         NULL), "CN");
+       }
+
+       if (label != NULL)
+               return label;
+
+       return g_strdup (_("Certificate request"));
+}
+
+static void
+_gcr_certificate_req_renderer_init (GcrCertificateReqRenderer *self)
+{
+       self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_CERTIFICATE_REQ_RENDERER,
+                                                GcrCertificateReqRendererPrivate));
+}
+
+static void
+_gcr_certificate_req_renderer_finalize (GObject *obj)
+{
+       GcrCertificateReqRenderer *self = GCR_CERTIFICATE_REQ_RENDERER (obj);
+
+       if (self->pv->attrs)
+               gck_attributes_unref (self->pv->attrs);
+       self->pv->attrs = NULL;
+
+       g_free (self->pv->label);
+       self->pv->label = NULL;
+
+       egg_asn1x_destroy (self->pv->asn);
+
+       G_OBJECT_CLASS (_gcr_certificate_req_renderer_parent_class)->finalize (obj);
+}
+
+static void
+_gcr_certificate_req_renderer_set_property (GObject *obj,
+                                            guint prop_id,
+                                            const GValue *value,
+                                            GParamSpec *pspec)
+{
+       GcrCertificateReqRenderer *self = GCR_CERTIFICATE_REQ_RENDERER (obj);
+
+       switch (prop_id) {
+       case PROP_LABEL:
+               g_free (self->pv->label);
+               self->pv->label = g_value_dup_string (value);
+               g_object_notify (obj, "label");
+               gcr_renderer_emit_data_changed (GCR_RENDERER (self));
+               break;
+       case PROP_ATTRIBUTES:
+               _gcr_certificate_req_renderer_set_attributes (self, g_value_get_boxed (value));
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+_gcr_certificate_req_renderer_get_property (GObject *obj,
+                                            guint prop_id,
+                                            GValue *value,
+                                            GParamSpec *pspec)
+{
+       GcrCertificateReqRenderer *self = GCR_CERTIFICATE_REQ_RENDERER (obj);
+
+       switch (prop_id) {
+       case PROP_LABEL:
+               g_value_take_string (value, calculate_label (self));
+               break;
+       case PROP_ATTRIBUTES:
+               g_value_set_boxed (value, self->pv->attrs);
+               break;
+       default:
+               gcr_certificate_mixin_get_property (obj, prop_id, value, pspec);
+               break;
+       }
+}
+
+static void
+_gcr_certificate_req_renderer_class_init (GcrCertificateReqRendererClass *klass)
+{
+       GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+       GckAttributes *registered;
+
+       _gcr_oids_init ();
+
+       g_type_class_add_private (klass, sizeof (GcrCertificateReqRendererPrivate));
+
+       gobject_class->finalize = _gcr_certificate_req_renderer_finalize;
+       gobject_class->set_property = _gcr_certificate_req_renderer_set_property;
+       gobject_class->get_property = _gcr_certificate_req_renderer_get_property;
+
+       /**
+        * GcrCertificateReqRenderer:attributes:
+        *
+        * The certificate attributes to display. One of the attributes must be
+        * a CKA_VALUE type attribute which contains a DER encoded certificate.
+        */
+       g_object_class_install_property (gobject_class, PROP_ATTRIBUTES,
+                  g_param_spec_boxed ("attributes", "Attributes", "Certificate pkcs11 attributes",
+                                      GCK_TYPE_ATTRIBUTES, G_PARAM_READWRITE));
+
+       /**
+        * GcrCertificateReqRenderer:label:
+        *
+        * The label to display.
+        */
+       g_object_class_install_property (gobject_class, PROP_LABEL,
+                  g_param_spec_string ("label", "Label", "Certificate Label",
+                                       "", G_PARAM_READWRITE));
+
+       /* Register this as a renderer which can be loaded */
+       registered = gck_attributes_new ();
+       gck_attributes_add_ulong (registered, CKA_CLASS, CKO_GCR_CERTIFICATE_REQUEST);
+       gck_attributes_add_ulong (registered, CKA_GCR_CERTIFICATE_REQUEST_TYPE, CKQ_GCR_PKCS10);
+       gcr_renderer_register (GCR_TYPE_CERTIFICATE_REQ_RENDERER, registered);
+       gck_attributes_unref (registered);
+
+       registered = gck_attributes_new ();
+       gck_attributes_add_ulong (registered, CKA_CLASS, CKO_GCR_CERTIFICATE_REQUEST);
+       gck_attributes_add_ulong (registered, CKA_GCR_CERTIFICATE_REQUEST_TYPE, CKQ_GCR_SPKAC);
+       gcr_renderer_register (GCR_TYPE_CERTIFICATE_REQ_RENDERER, registered);
+       gck_attributes_unref (registered);
+}
+
+static gboolean
+append_extension_request (GcrRenderer *renderer,
+                          GcrDisplayView *view,
+                          GNode *attribute)
+{
+       EggBytes *value;
+       GNode *node;
+       GNode *asn;
+       guint i;
+
+       node = egg_asn1x_node (attribute, "values", 1, NULL);
+       if (node == NULL)
+               return FALSE;
+
+       value = egg_asn1x_get_raw_element (node);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "ExtensionRequest", value);
+       if (asn == NULL)
+               return FALSE;
+
+       for (i = 1; TRUE; i++) {
+               node = egg_asn1x_node (asn, i, NULL);
+               if (node == NULL)
+                       break;
+               _gcr_certificate_renderer_append_extension (renderer, view, node);
+       }
+
+       egg_asn1x_destroy (asn);
+       return TRUE;
+}
+
+static void
+append_attribute (GcrRenderer *renderer,
+                  GcrDisplayView *view,
+                  GNode *attribute)
+{
+       GQuark oid;
+       EggBytes *value;
+       const gchar *text;
+       GNode *node;
+       gboolean ret = FALSE;
+       gint i;
+
+       /* Dig out the OID */
+       oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (attribute, "type", NULL));
+       g_return_if_fail (oid);
+
+       if (oid == GCR_OID_PKCS9_ATTRIBUTE_EXTENSION_REQ)
+               ret = append_extension_request (renderer, view, attribute);
+
+       if (!ret) {
+               _gcr_display_view_append_heading (view, renderer, _("Attribute"));
+
+               /* Extension type */
+               text = egg_oid_get_description (oid);
+               _gcr_display_view_append_value (view, renderer, _("Type"), text, FALSE);
+
+               for (i = 1; TRUE; i++) {
+                       node = egg_asn1x_node (attribute, "values", i, NULL);
+                       if (node == NULL)
+                               break;
+                       value = egg_asn1x_get_raw_element (node);
+                       _gcr_display_view_append_hex (view, renderer, _("Value"),
+                                                     egg_bytes_get_data (value),
+                                                     egg_bytes_get_size (value));
+                       egg_bytes_unref (value);
+               }
+       }
+}
+
+static guint
+ensure_key_size (GcrCertificateReqRenderer *self,
+                 GNode *public_key)
+{
+       if (self->pv->key_size)
+               return self->pv->key_size;
+
+       self->pv->key_size = _gcr_key_size_calculate (public_key);
+       return self->pv->key_size;
+}
+
+static void
+render_pkcs10_certificate_req (GcrCertificateReqRenderer *self,
+                               GcrDisplayView *view)
+{
+       GcrRenderer *renderer = GCR_RENDERER (self);
+       GNode *public_key;
+       GNode *attribute;
+       GNode *subject;
+       gchar *display;
+       gulong version;
+       guint bits;
+       guint i;
+
+       display = calculate_label (self);
+       _gcr_display_view_append_title (view, renderer, display);
+       g_free (display);
+
+       _gcr_display_view_append_content (view, renderer, _("Certificate request"), NULL);
+
+       subject = egg_asn1x_node (self->pv->asn, "certificationRequestInfo",
+                                 "subject", "rdnSequence", NULL);
+       display = egg_dn_read_part (subject, "CN");
+       _gcr_display_view_append_content (view, renderer, _("Identity"), display);
+       g_free (display);
+
+       _gcr_display_view_start_details (view, renderer);
+
+       /* The subject */
+       _gcr_display_view_append_heading (view, renderer, _("Subject Name"));
+       _gcr_certificate_renderer_append_distinguished_name (renderer, view, subject);
+
+       /* The certificate request type */
+       _gcr_display_view_append_heading (view, renderer, _("Certificate request"));
+       _gcr_display_view_append_value (view, renderer, _("Type"), "PKCS#10", FALSE);
+       if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (self->pv->asn,
+                                                            "certificationRequestInfo",
+                                                            "version", NULL), &version))
+               g_return_if_reached ();
+       display = g_strdup_printf ("%lu", version + 1);
+       _gcr_display_view_append_value (view, renderer, _("Version"), display, FALSE);
+       g_free (display);
+
+       _gcr_display_view_append_heading (view, renderer, _("Public Key Info"));
+       public_key = egg_asn1x_node (self->pv->asn, "certificationRequestInfo", "subjectPKInfo", NULL);
+       bits = ensure_key_size (self, public_key);
+       _gcr_certificate_renderer_append_subject_public_key (renderer, view,
+                                                            bits, public_key);
+
+       /* Attributes */
+       for (i = 1; TRUE; ++i) {
+               /* Make sure it is present */
+               attribute = egg_asn1x_node (self->pv->asn, "certificationRequestInfo", "attributes", i, NULL);
+               if (attribute == NULL)
+                       break;
+               append_attribute (renderer, view, attribute);
+       }
+
+       /* Signature */
+       _gcr_display_view_append_heading (view, renderer, _("Signature"));
+       _gcr_certificate_renderer_append_signature (renderer, view, self->pv->asn);
+}
+
+static void
+render_spkac_certificate_req (GcrCertificateReqRenderer *self,
+                              GcrDisplayView *view)
+{
+       GcrRenderer *renderer = GCR_RENDERER (self);
+       GNode *public_key;
+       gchar *display;
+       guint bits;
+
+       display = calculate_label (self);
+       _gcr_display_view_append_title (view, renderer, display);
+       g_free (display);
+
+       _gcr_display_view_append_content (view, renderer, _("Certificate request"), NULL);
+
+       _gcr_display_view_start_details (view, renderer);
+
+       /* The certificate request type */
+       _gcr_display_view_append_heading (view, renderer, _("Certificate request"));
+       _gcr_display_view_append_value (view, renderer, _("Type"), "SPKAC", FALSE);
+
+       display = egg_asn1x_get_string_as_utf8 (egg_asn1x_node (self->pv->asn, "publicKeyAndChallenge",
+                                                               "challenge", NULL), NULL);
+       _gcr_display_view_append_value (view, renderer, _("Challenge"), display, FALSE);
+       g_free (display);
+
+       _gcr_display_view_append_heading (view, renderer, _("Public Key Info"));
+       public_key = egg_asn1x_node (self->pv->asn, "publicKeyAndChallenge", "spki", NULL);
+       bits = ensure_key_size (self, public_key);
+       _gcr_certificate_renderer_append_subject_public_key (renderer, view,
+                                                            bits, public_key);
+
+       /* Signature */
+       _gcr_display_view_append_heading (view, renderer, _("Signature"));
+       _gcr_certificate_renderer_append_signature (renderer, view, self->pv->asn);
+}
+
+static void
+gcr_certificate_req_renderer_render (GcrRenderer *renderer,
+                                     GcrViewer *viewer)
+{
+       GcrCertificateReqRenderer *self;
+       GcrDisplayView *view;
+       GIcon *icon;
+
+       self = GCR_CERTIFICATE_REQ_RENDERER (renderer);
+
+       if (GCR_IS_DISPLAY_VIEW (viewer)) {
+               view = GCR_DISPLAY_VIEW (viewer);
+
+       } else {
+               g_warning ("GcrCertificateReqRenderer only works with internal specific "
+                          "GcrViewer returned by gcr_viewer_new().");
+               return;
+       }
+
+       _gcr_display_view_begin (view, renderer);
+
+       icon = g_themed_icon_new ("dialog-question");
+       _gcr_display_view_set_icon (view, GCR_RENDERER (self), icon);
+       g_object_unref (icon);
+
+       switch (self->pv->type) {
+       case CKQ_GCR_PKCS10:
+               render_pkcs10_certificate_req (self, view);
+               break;
+       case CKQ_GCR_SPKAC:
+               render_spkac_certificate_req (self, view);
+               break;
+       default:
+               g_warning ("unknown request type in GcrCertificateReqRenderer");
+               break;
+       }
+
+       _gcr_display_view_end (view, renderer);
+}
+
+static void
+_gcr_certificate_req_renderer_iface (GcrRendererIface *iface)
+{
+       iface->render_view = gcr_certificate_req_renderer_render;
+}
+
+/**
+ * gcr_certificate_req_renderer_new_for_attributes:
+ * @label: (allow-none): the label to display
+ * @attrs: the attributes to display
+ *
+ * Create a new certificate request renderer to display the label and attributes.
+ * One of the attributes should be a CKA_VALUE type attribute containing a DER
+ * encoded PKCS\#10 certificate request or an SPKAC request.
+ *
+ * Returns: (transfer full): a newly allocated #GcrCertificateReqRenderer, which
+ *          should be released with g_object_unref()
+ */
+GcrRenderer *
+_gcr_certificate_req_renderer_new_for_attributes (const gchar *label,
+                                                  GckAttributes *attrs)
+{
+       return g_object_new (GCR_TYPE_CERTIFICATE_REQ_RENDERER,
+                            "label", label,
+                            "attributes", attrs,
+                            NULL);
+}
+
+/**
+ * gcr_certificate_req_renderer_get_attributes:
+ * @self: the renderer
+ *
+ * Get the PKCS\#11 attributes, if any, set for this renderer to display.
+ *
+ * Returns: (allow-none) (transfer none): the attributes, owned by the renderer
+ */
+GckAttributes *
+_gcr_certificate_req_renderer_get_attributes (GcrCertificateReqRenderer *self)
+{
+       g_return_val_if_fail (GCR_IS_CERTIFICATE_REQ_RENDERER (self), NULL);
+       return self->pv->attrs;
+}
+
+/**
+ * gcr_certificate_req_renderer_set_attributes:
+ * @self: the renderer
+ * @attrs: (allow-none): attributes to set
+ *
+ * Set the PKCS\#11 attributes for this renderer to display. One of the attributes
+ * should be a CKA_VALUE type attribute containing a DER encoded PKCS\#10
+ * certificate request or an SPKAC request.
+ */
+void
+_gcr_certificate_req_renderer_set_attributes (GcrCertificateReqRenderer *self,
+                                              GckAttributes *attrs)
+{
+       GckAttribute *value;
+       GNode *asn = NULL;
+       gulong type = 0;
+       EggBytes *bytes;
+
+       g_return_if_fail (GCR_IS_CERTIFICATE_REQ_RENDERER (self));
+
+       if (attrs) {
+               value = gck_attributes_find (attrs, CKA_VALUE);
+               if (value == NULL) {
+                       g_warning ("no CKA_VALUE found in attributes passed to "
+                                  "GcrCertificateReqRenderer attributes property");
+                       return;
+               }
+
+               bytes = egg_bytes_new_with_free_func (value->value, value->length,
+                                                     gck_attributes_unref, gck_attributes_ref (attrs));
+
+               asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-10-CertificationRequest", bytes);
+               if (asn != NULL) {
+                       type = CKQ_GCR_PKCS10;
+               } else {
+                       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SignedPublicKeyAndChallenge", bytes);
+                       if (asn != NULL) {
+                               type = CKQ_GCR_SPKAC;
+                       } else {
+                               g_warning ("the data contained in the CKA_VALUE attribute passed to "
+                                          "GcrCertificateReqRenderer was not valid DER encoded PKCS#10 "
+                                          "or SPKAC");
+                       }
+               }
+
+               egg_bytes_unref (bytes);
+
+               if (type == 0)
+                       return;
+
+               gck_attributes_ref (attrs);
+       }
+
+       if (self->pv->attrs)
+               gck_attributes_unref (self->pv->attrs);
+       self->pv->attrs = attrs;
+       self->pv->asn = asn;
+       self->pv->type = type;
+       self->pv->key_size = 0; /* calculated later */
+
+       gcr_renderer_emit_data_changed (GCR_RENDERER (self));
+       g_object_notify (G_OBJECT (self), "attributes");
+}
diff --git a/gcr/gcr-certificate-req-renderer.h b/gcr/gcr-certificate-req-renderer.h
new file mode 100644 (file)
index 0000000..856f925
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 Stefan Walter
+ *
+ * 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.
+ */
+
+#if !defined (__GCR_INSIDE_HEADER__) && !defined (GCR_COMPILATION)
+#error "Only <gcr/gcr.h> or <gcr/gcr-base.h> can be included directly."
+#endif
+
+#ifndef __GCR_CERTIFICATE_REQ_RENDERER_H__
+#define __GCR_CERTIFICATE_REQ_RENDERER_H__
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "gcr-certificate.h"
+#include "gcr-renderer.h"
+#include "gcr-types.h"
+
+G_BEGIN_DECLS
+
+#define GCR_TYPE_CERTIFICATE_REQ_RENDERER               (_gcr_certificate_req_renderer_get_type ())
+#define GCR_CERTIFICATE_REQ_RENDERER(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_CERTIFICATE_REQ_RENDERER, GcrCertificateReqRenderer))
+#define GCR_CERTIFICATE_REQ_RENDERER_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_CERTIFICATE_REQ_RENDERER, GcrCertificateReqRendererClass))
+#define GCR_IS_CERTIFICATE_REQ_RENDERER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_CERTIFICATE_REQ_RENDERER))
+#define GCR_IS_CERTIFICATE_REQ_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_CERTIFICATE_REQ_RENDERER))
+#define GCR_CERTIFICATE_REQ_RENDERER_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_CERTIFICATE_REQ_RENDERER, GcrCertificateReqRendererClass))
+
+typedef struct _GcrCertificateReqRenderer GcrCertificateReqRenderer;
+typedef struct _GcrCertificateReqRendererClass GcrCertificateReqRendererClass;
+typedef struct _GcrCertificateReqRendererPrivate GcrCertificateReqRendererPrivate;
+
+struct _GcrCertificateReqRenderer {
+       GObject parent;
+
+       /*< private >*/
+       GcrCertificateReqRendererPrivate *pv;
+};
+
+struct _GcrCertificateReqRendererClass {
+       GObjectClass parent_class;
+};
+
+GType             _gcr_certificate_req_renderer_get_type              (void);
+
+GcrRenderer *     _gcr_certificate_req_renderer_new_for_attributes    (const gchar *label,
+                                                                       struct _GckAttributes *attrs);
+
+GckAttributes *   _gcr_certificate_req_renderer_get_attributes        (GcrCertificateReqRenderer *self);
+
+void              _gcr_certificate_req_renderer_set_attributes        (GcrCertificateReqRenderer *self,
+                                                                       GckAttributes *attrs);
+
+G_END_DECLS
+
+#endif /* __GCR_CERTIFICATE_REQ_RENDERER_H__ */
index 889c67a..75860b5 100644 (file)
@@ -25,6 +25,7 @@
 #include "gcr-comparable.h"
 #include "gcr-icons.h"
 #include "gcr-internal.h"
+#include "gcr-key-size.h"
 #include "gcr-oids.h"
 
 #include "egg/egg-asn1x.h"
@@ -177,97 +178,6 @@ certificate_info_load (GcrCertificate *cert)
        return info;
 }
 
-static guint
-calculate_rsa_key_size (EggBytes *data)
-{
-       EggBytes *content;
-       guint key_size;
-       GNode *asn;
-
-       asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPublicKey", data);
-       g_return_val_if_fail (asn != NULL, 0);
-
-       content = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "modulus", NULL));
-       if (!content)
-               g_return_val_if_reached (0);
-
-       egg_asn1x_destroy (asn);
-
-       /* Removes the complement */
-       key_size = (egg_bytes_get_size (content) / 2) * 2 * 8;
-
-       egg_bytes_unref (content);
-       return key_size;
-}
-
-static guint
-calculate_dsa_params_size (EggBytes *data)
-{
-       EggBytes *content;
-       gsize params_size;
-       GNode *asn;
-
-       asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", data);
-       g_return_val_if_fail (asn != NULL, 0);
-
-       content = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "p", NULL));
-       if (!content)
-               g_return_val_if_reached (0);
-
-       egg_asn1x_destroy (asn);
-
-       /* Removes the complement */
-       params_size = (egg_bytes_get_size (content) / 2) * 2 * 8;
-
-       egg_bytes_unref (content);
-       return params_size;
-}
-
-static guint
-calculate_key_size (GcrCertificateInfo *info)
-{
-       GNode *asn;
-       EggBytes *data;
-       guint key_size = 0, n_bits;
-       EggBytes *key;
-       GQuark oid;
-
-       data = egg_asn1x_get_raw_element (egg_asn1x_node (info->asn1, "tbsCertificate", "subjectPublicKeyInfo", NULL));
-       g_return_val_if_fail (data != NULL, 0);
-
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SubjectPublicKeyInfo", data);
-       g_return_val_if_fail (asn != NULL, 0);
-
-       egg_bytes_unref (data);
-
-       /* Figure out the algorithm */
-       oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "algorithm", "algorithm", NULL));
-       g_return_val_if_fail (oid, 0);
-
-       /* RSA keys are stored in the main subjectPublicKey field */
-       if (oid == GCR_OID_PKIX1_RSA) {
-
-               /* A bit string so we cannot process in place */
-               key = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "subjectPublicKey", NULL), &n_bits);
-               g_return_val_if_fail (key != NULL, 0);
-               key_size = calculate_rsa_key_size (key);
-               egg_bytes_unref (key);
-
-       /* The DSA key size is discovered by the prime in params */
-       } else if (oid == GCR_OID_PKIX1_DSA) {
-               key = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "algorithm", "parameters", NULL));
-               key_size = calculate_dsa_params_size (key);
-               egg_bytes_unref (key);
-
-       } else {
-               g_message ("unsupported key algorithm in certificate: %s", g_quark_to_string (oid));
-       }
-
-       egg_asn1x_destroy (asn);
-
-       return key_size;
-}
-
 static GChecksum*
 digest_certificate (GcrCertificate *self, GChecksumType type)
 {
@@ -815,14 +725,18 @@ guint
 gcr_certificate_get_key_size (GcrCertificate *self)
 {
        GcrCertificateInfo *info;
+       GNode *subject_public_key;
 
        g_return_val_if_fail (GCR_IS_CERTIFICATE (self), 0);
 
        info = certificate_info_load (self);
        g_return_val_if_fail (info, 0);
 
-       if (!info->key_size)
-               info->key_size = calculate_key_size (info);
+       if (!info->key_size) {
+               subject_public_key = egg_asn1x_node (info->asn1, "tbsCertificate",
+                                                    "subjectPublicKeyInfo", NULL);
+               info->key_size = _gcr_key_size_calculate (subject_public_key);
+       }
 
        return info->key_size;
 }
index b911ccd..c92577c 100644 (file)
                <comment>PKCS#10 Certificate Request</comment>
                <acronym>PKCS#10</acronym>
                <glob pattern="*.p10"/>
+               <glob pattern="*.csr"/>
        </mime-type>
 
        <!-- Non standard: OpenSSL PEM format -->
                </magic>
        </mime-type>
 
+       <!-- Non standard: SPKAC DER format -->
+       <mime-type type="application/x-spkac">
+               <comment>SPKAC Certificate Request</comment>
+               <glob pattern="*.spkac"/>
+       </mime-type>
+
+       <!-- Non standard: SPKAC DER format -->
+       <mime-type type="application/x-spkac+base64">
+               <comment>SPKAC Certificate Request in OpenSSL format</comment>
+               <sub-class-of type="text/plain"/>
+               <magic priority="75">
+                       <match type="string" value="SPKAC=" offset="0"/>
+               </magic>
+       </mime-type>
+
        <!-- Non standard: OpenSSL PEM format -->
        <mime-type type="application/x-pem-key">
                <comment>Private Key in PEM format</comment>
diff --git a/gcr/gcr-key-size.c b/gcr/gcr-key-size.c
new file mode 100644 (file)
index 0000000..06c5c09
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2010 Stefan Walter
+ *
+ * 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.
+ */
+
+#include "config.h"
+
+#include "gcr-key-size.h"
+#include "gcr-oids.h"
+
+#include "egg/egg-asn1x.h"
+#include "egg/egg-asn1-defs.h"
+
+static guint
+calculate_rsa_key_size (EggBytes *data)
+{
+       GNode *asn;
+       EggBytes *content;
+       guint key_size;
+
+       asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPublicKey", data);
+       g_return_val_if_fail (asn, 0);
+
+       content = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "modulus", NULL));
+       if (!content)
+               g_return_val_if_reached (0);
+
+       egg_asn1x_destroy (asn);
+
+       /* Removes the complement */
+       key_size = (egg_bytes_get_size (content) / 2) * 2 * 8;
+
+       egg_bytes_unref (content);
+       return key_size;
+}
+
+static guint
+calculate_dsa_params_size (EggBytes *data)
+{
+       GNode *asn;
+       EggBytes *content;
+       guint key_size;
+
+       asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", data);
+       g_return_val_if_fail (asn, 0);
+
+       content = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "p", NULL));
+       if (!content)
+               g_return_val_if_reached (0);
+
+       egg_asn1x_destroy (asn);
+
+       /* Removes the complement */
+       key_size = (egg_bytes_get_size (content) / 2) * 2 * 8;
+
+       egg_bytes_unref (content);
+       return key_size;
+}
+
+guint
+_gcr_key_size_calculate (GNode *subject_public_key)
+{
+       EggBytes *key;
+       guint key_size = 0, n_bits;
+       GQuark oid;
+
+       /* Figure out the algorithm */
+       oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (subject_public_key,
+                                                         "algorithm", "algorithm", NULL));
+       g_return_val_if_fail (oid, 0);
+
+       /* RSA keys are stored in the main subjectPublicKey field */
+       if (oid == GCR_OID_PKIX1_RSA) {
+
+               /* A bit string so we cannot process in place */
+               key = egg_asn1x_get_bits_as_raw (egg_asn1x_node (subject_public_key, "subjectPublicKey", NULL), &n_bits);
+               g_return_val_if_fail (key != NULL, 0);
+               key_size = calculate_rsa_key_size (key);
+               egg_bytes_unref (key);
+
+       /* The DSA key size is discovered by the prime in params */
+       } else if (oid == GCR_OID_PKIX1_DSA) {
+               key = egg_asn1x_get_raw_element (egg_asn1x_node (subject_public_key, "algorithm", "parameters", NULL));
+               key_size = calculate_dsa_params_size (key);
+               egg_bytes_unref (key);
+
+       } else {
+               g_message ("unsupported key algorithm in certificate: %s", g_quark_to_string (oid));
+       }
+
+       return key_size;
+}
diff --git a/gcr/gcr-key-size.h b/gcr/gcr-key-size.h
new file mode 100644 (file)
index 0000000..8232cd3
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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>
+ */
+
+#ifndef __GCR_KEY_SIZE_H__
+#define __GCR_KEY_SIZE_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+guint       _gcr_key_size_calculate           (GNode *subject_public_key);
+
+G_END_DECLS
+
+#endif /* __GCR_KEY_RENDERER_H__ */
index 552c601..2fe3364 100644 (file)
@@ -12,6 +12,7 @@ PKCS7_SIGNED_DATA             1.2.840.113549.1.7.2
 PKCS7_ENCRYPTED_DATA           1.2.840.113549.1.7.6
 PKCS9_ATTRIBUTE_FRIENDLY       1.2.840.113549.1.9.20
 PKCS9_ATTRIBUTE_LOCAL_KEY_ID   1.2.840.113549.1.9.21
+PKCS9_ATTRIBUTE_EXTENSION_REQ  1.2.840.113549.1.9.14
 PKCS12_BAG_PKCS8_KEY           1.2.840.113549.1.12.10.1.1
 PKCS12_BAG_PKCS8_ENCRYPTED_KEY 1.2.840.113549.1.12.10.1.2
 PKCS12_BAG_CERTIFICATE         1.2.840.113549.1.12.10.1.3
index c98376b..296bcf0 100644 (file)
@@ -25,6 +25,7 @@
 #include "gcr-renderer.h"
 
 #include "gcr-certificate-renderer.h"
+#include "gcr-certificate-req-renderer.h"
 #include "gcr-gnupg-renderer.h"
 #include "gcr-key-renderer.h"
 
@@ -289,6 +290,7 @@ void
 gcr_renderer_register_well_known (void)
 {
        g_type_class_unref (g_type_class_ref (GCR_TYPE_CERTIFICATE_RENDERER));
+       g_type_class_unref (g_type_class_ref (GCR_TYPE_CERTIFICATE_REQ_RENDERER));
        g_type_class_unref (g_type_class_ref (GCR_TYPE_KEY_RENDERER));
        g_type_class_unref (g_type_class_ref (GCR_TYPE_GNUPG_RENDERER));
 }
index e43e7ef..dd522be 100644 (file)
@@ -120,7 +120,7 @@ enum {
 };
 
 enum {
-       CKQ_GCR_PKCS10,
+       CKQ_GCR_PKCS10 = 1,
        CKQ_GCR_SPKAC
 };
 
index 4d4a432..3f45c8a 100644 (file)
@@ -1,6 +1,6 @@
 [Desktop Entry]
 Name=View file
-MimeType=application/pkcs12;application/pkcs12+pem;application/pkcs7-mime;application/pkcs7-mime+pem;application/pkcs8;application/pkcs8+pem;application/pkix-cert;application/pkix-cert+pem;application/pkix-crl;application/pkix-crl+pem;application/x-pem-file;application/x-pem-key;application/x-pkcs12;application/x-pkcs7-certificates;application/x-x509-ca-cert;application/x-x509-user-cert;
+MimeType=application/pkcs12;application/pkcs12+pem;application/pkcs7-mime;application/pkcs7-mime+pem;application/pkcs8;application/pkcs8+pem;application/pkix-cert;application/pkix-cert+pem;application/pkix-crl;application/pkix-crl+pem;application/x-pem-file;application/x-pem-key;application/x-pkcs12;application/x-pkcs7-certificates;application/x-x509-ca-cert;application/x-x509-user-cert;application/pkcs10;application/pkcs10+pem;application/x-spkac;application/x-spkac+base64;
 Exec=gcr-viewer
 Type=Application
 Terminal=false
index 6cd913a..a9622ac 100644 (file)
@@ -1,6 +1,6 @@
 [Desktop Entry]
 Name=View file
-MimeType=application/pkcs12;application/pkcs12+pem;application/pkcs7-mime;application/pkcs7-mime+pem;application/pkcs8;application/pkcs8+pem;application/pkix-cert;application/pkix-cert+pem;application/pkix-crl;application/pkix-crl+pem;application/x-pem-file;application/x-pem-key;application/x-pkcs12;application/x-pkcs7-certificates;application/x-x509-ca-cert;application/x-x509-user-cert;
+MimeType=application/pkcs12;application/pkcs12+pem;application/pkcs7-mime;application/pkcs7-mime+pem;application/pkcs8;application/pkcs8+pem;application/pkix-cert;application/pkix-cert+pem;application/pkix-crl;application/pkix-crl+pem;application/x-pem-file;application/x-pem-key;application/x-pkcs12;application/x-pkcs7-certificates;application/x-x509-ca-cert;application/x-x509-user-cert;application/pkcs10;application/pkcs10+pem;application/x-spkac;application/x-spkac+base64;
 Exec=gcr-viewer
 Type=Application
 Terminal=false
index 5ac8369..c133c17 100644 (file)
@@ -64,6 +64,7 @@ noinst_PROGRAMS = \
        frob-tree-selector \
        frob-openpgp \
        frob-parser \
+       frob-request \
        frob-unlock \
        frob-unlock-options
 
diff --git a/gcr/tests/files/pem-with-attributes.req b/gcr/tests/files/pem-with-attributes.req
new file mode 100644 (file)
index 0000000..bcbe8f5
--- /dev/null
@@ -0,0 +1,64 @@
+Certificate Request:
+    Data:
+        Version: 0 (0x0)
+        Subject: CN=test.example.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:c9:45:f5:a6:a6:f6:d1:96:1a:4d:1b:2b:18:a7:
+                    ba:69:4e:90:3b:64:9d:14:71:9a:38:0d:fe:66:89:
+                    cd:c6:34:05:c0:c9:2a:02:22:5f:3e:c9:10:c2:df:
+                    e8:c8:a5:d9:78:20:6a:81:ad:80:b0:16:a2:d1:6b:
+                    e9:ed:2f:95:69:c2:52:2b:db:76:48:00:c9:56:44:
+                    fa:a7:f4:64:a6:7b:08:58:14:b6:2d:3c:c3:6a:80:
+                    3e:25:48:a8:52:2a:a0:ff:fc:4a:5e:01:05:f8:c3:
+                    58:db:26:58:8f:42:85:f0:7a:e8:8d:cd:28:a8:c7:
+                    24:cd:65:6d:26:86:88:f0:8b:ab:a2:58:8b:fc:91:
+                    45:66:49:03:79:44:f3:d9:d6:0b:49:6c:e6:d2:25:
+                    83:0c:1e:1f:61:e4:b8:53:ab:c7:8a:58:a6:c1:ce:
+                    a4:04:b4:3f:36:48:d5:02:50:85:b3:2c:4c:af:f7:
+                    88:85:be:f1:cf:32:db:cd:52:23:90:71:2b:ad:04:
+                    be:18:be:7d:67:4d:0b:bc:d6:92:82:ae:a4:27:98:
+                    f1:72:cc:16:f2:5d:f3:78:fa:76:0d:c5:13:88:a5:
+                    87:02:3e:41:a2:a2:36:b9:90:07:4f:53:b9:9c:17:
+                    05:65:9b:da:6d:f4:62:ab:3d:05:7a:8a:fe:e3:c3:
+                    1e:31
+                Exponent: 65537 (0x10001)
+        Attributes:
+        Requested Extensions:
+            X509v3 Subject Alternative Name:
+                DNS:test.example.com, DNS:other.example.com
+    Signature Algorithm: sha1WithRSAEncryption
+        b9:97:4a:53:7e:0f:14:46:ae:d7:6f:fc:1a:33:b1:40:c7:ae:
+        64:06:c8:2d:b5:5a:a0:e8:bf:8e:af:92:e1:7d:ad:3c:6b:c0:
+        c6:d2:cb:c4:98:e7:2c:fa:d6:d5:ee:77:dc:5e:99:9d:33:23:
+        d0:f7:61:30:ef:86:00:b3:08:4a:24:ce:5a:86:8d:91:95:84:
+        bc:4b:16:33:46:1e:92:3f:7a:fb:f0:f2:27:c3:07:e3:b0:b6:
+        1c:a4:88:ef:69:69:9f:16:fd:4c:79:46:63:f9:84:8a:a7:16:
+        8d:80:ee:a5:a8:54:a2:a4:0b:4b:0b:a7:38:a3:e9:d5:14:0f:
+        0c:1a:5d:25:93:fa:6e:29:95:71:30:90:ca:15:a2:41:2d:e0:
+        97:0b:36:b2:4c:36:66:16:24:3d:26:c0:26:6a:c8:10:57:ca:
+        79:b1:b7:ae:e4:95:38:b9:75:66:09:3b:40:31:87:7f:6d:73:
+        1f:ee:18:b3:de:c8:9c:11:78:00:eb:56:63:5d:f8:a3:58:aa:
+        44:d1:94:50:46:ff:19:77:7e:85:f8:7c:ba:a4:b9:25:3c:8a:
+        ba:19:c1:10:bc:b6:43:af:ad:60:76:2d:cd:5d:ef:86:4a:1d:
+        b0:0a:91:8a:20:98:cd:c8:9e:43:d5:7c:9c:a9:e2:8b:f3:86:
+        fe:a4:00:1a
+-----BEGIN CERTIFICATE REQUEST-----
+MIICoTCCAYkCAQAwGzEZMBcGA1UEAxMQdGVzdC5leGFtcGxlLmNvbTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMlF9aam9tGWGk0bKxinumlOkDtknRRx
+mjgN/maJzcY0BcDJKgIiXz7JEMLf6Mil2XggaoGtgLAWotFr6e0vlWnCUivbdkgA
+yVZE+qf0ZKZ7CFgUti08w2qAPiVIqFIqoP/8Sl4BBfjDWNsmWI9ChfB66I3NKKjH
+JM1lbSaGiPCLq6JYi/yRRWZJA3lE89nWC0ls5tIlgwweH2HkuFOrx4pYpsHOpAS0
+PzZI1QJQhbMsTK/3iIW+8c8y281SI5BxK60Evhi+fWdNC7zWkoKupCeY8XLMFvJd
+83j6dg3FE4ilhwI+QaKiNrmQB09TuZwXBWWb2m30Yqs9BXqK/uPDHjECAwEAAaBB
+MD8GCSqGSIb3DQEJDjEyMDAwLgYDVR0RBCcwJYIQdGVzdC5leGFtcGxlLmNvbYIR
+b3RoZXIuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQEFBQADggEBALmXSlN+DxRGrtdv
+/BozsUDHrmQGyC21WqDov46vkuF9rTxrwMbSy8SY5yz61tXud9xemZ0zI9D3YTDv
+hgCzCEokzlqGjZGVhLxLFjNGHpI/evvw8ifDB+OwthykiO9paZ8W/Ux5RmP5hIqn
+Fo2A7qWoVKKkC0sLpzij6dUUDwwaXSWT+m4plXEwkMoVokEt4JcLNrJMNmYWJD0m
+wCZqyBBXynmxt67klTi5dWYJO0Axh39tcx/uGLPeyJwReADrVmNd+KNYqkTRlFBG
+/xl3foX4fLqkuSU8iroZwRC8tkOvrWB2Lc1d74ZKHbAKkYogmM3InkPVfJyp4ovz
+hv6kABo=
+-----END CERTIFICATE REQUEST-----
diff --git a/gcr/tests/frob-request.c b/gcr/tests/frob-request.c
new file mode 100644 (file)
index 0000000..68b5d0e
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * 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/gcr.h"
+#include "gcr/gcr-certificate-req-renderer.h"
+
+#include <gtk/gtk.h>
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+static void
+on_parser_parsed (GcrParser *parser,
+                  gpointer user_data)
+{
+       GcrViewer *viewer;
+       GcrRenderer *renderer;
+       GtkDialog *dialog = GTK_DIALOG (user_data);
+
+       viewer = gcr_viewer_new_scrolled ();
+       renderer = _gcr_certificate_req_renderer_new_for_attributes (gcr_parser_get_parsed_label (parser),
+                                                                    gcr_parser_get_parsed_attributes (parser));
+       gcr_viewer_add_renderer (viewer, renderer);
+       g_object_unref (renderer);
+       gtk_widget_show (GTK_WIDGET (viewer));
+       gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (dialog)), GTK_WIDGET (viewer));
+
+       gtk_container_set_border_width (GTK_CONTAINER (dialog), 20);
+}
+
+static void
+test_request (const gchar *path)
+{
+       GcrParser *parser;
+       GError *err = NULL;
+       guchar *data;
+       gsize n_data;
+       GtkWidget *dialog;
+
+       if (!g_file_get_contents (path, (gchar**)&data, &n_data, NULL))
+               g_error ("couldn't read file: %s", path);
+
+       dialog = gtk_dialog_new ();
+       g_object_ref_sink (dialog);
+
+       parser = gcr_parser_new ();
+       g_signal_connect (parser, "parsed", G_CALLBACK (on_parser_parsed), dialog);
+       if (!gcr_parser_parse_data (parser, data, n_data, &err))
+               g_error ("couldn't parse data: %s", err->message);
+
+       g_object_unref (parser);
+       g_free (data);
+
+       gtk_widget_show (dialog);
+       g_signal_connect (dialog, "delete-event", G_CALLBACK (gtk_main_quit), NULL);
+       gtk_main ();
+
+       g_object_unref (dialog);
+}
+
+int
+main(int argc, char *argv[])
+{
+       gtk_init (&argc, &argv);
+       g_set_prgname ("frob-request");
+
+       if (argc > 1)
+               test_request (argv[1]);
+       else
+               test_request (SRCDIR "/files/der-rsa-2048.p10");
+
+       return 0;
+}
index a3a74eb..c5c8b38 100644 (file)
@@ -7,6 +7,7 @@ gcr/gcr-callback-output-stream.c
 gcr/gcr-certificate.c
 gcr/gcr-certificate-exporter.c
 gcr/gcr-certificate-extensions.c
+gcr/gcr-certificate-req-renderer.c
 gcr/gcr-certificate-renderer.c
 gcr/gcr-certificate-widget.c
 gcr/gcr-display-view.c