aboutsummaryrefslogtreecommitdiffstats
path: root/smime
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2012-12-12 02:48:07 +0800
committerMilan Crha <mcrha@redhat.com>2012-12-12 02:48:07 +0800
commit8a1eb1f24e2a4624d78d3eeb4ab563d9e48ec865 (patch)
treea1bc41f9d06c7206fc4ba9a217b356966a99a569 /smime
parentc18043684137440e5853d5c952f89751148b6c24 (diff)
downloadgsoc2013-evolution-8a1eb1f24e2a4624d78d3eeb4ab563d9e48ec865.tar.gz
gsoc2013-evolution-8a1eb1f24e2a4624d78d3eeb4ab563d9e48ec865.tar.zst
gsoc2013-evolution-8a1eb1f24e2a4624d78d3eeb4ab563d9e48ec865.zip
Use the same certificate-viewer as the trust-prompt from eds
This way it'll be possible to copy whole files if change in one of them will be done. A real code reuse, rather than copy, would be ideal, but the trust-prompt is just a module for evolution-user-prompter.
Diffstat (limited to 'smime')
-rw-r--r--smime/gui/ca-trust-dialog.c8
-rw-r--r--smime/gui/ca-trust-dialog.h6
-rw-r--r--smime/gui/certificate-manager.c33
-rw-r--r--smime/gui/certificate-manager.h4
-rw-r--r--smime/gui/certificate-viewer.c725
-rw-r--r--smime/gui/certificate-viewer.h13
-rw-r--r--smime/gui/smime-ui.ui708
-rw-r--r--smime/lib/e-asn1-object.c916
-rw-r--r--smime/lib/e-asn1-object.h45
-rw-r--r--smime/lib/e-cert.c769
-rw-r--r--smime/lib/e-cert.h2
11 files changed, 1358 insertions, 1871 deletions
diff --git a/smime/gui/ca-trust-dialog.c b/smime/gui/ca-trust-dialog.c
index 7037b26677..332b92bcd1 100644
--- a/smime/gui/ca-trust-dialog.c
+++ b/smime/gui/ca-trust-dialog.c
@@ -26,7 +26,7 @@
#endif
#include "ca-trust-dialog.h"
-#include "certificate-viewer.h"
+#include "certificate-manager.h"
#include <glib/gi18n.h>
@@ -60,12 +60,14 @@ catd_response (GtkWidget *w,
{
switch (id) {
case GTK_RESPONSE_ACCEPT: {
- GtkWidget *dialog = certificate_viewer_show (data->cert);
+ GtkWidget *dialog;
+
+ dialog = e_cert_manager_new_certificate_viewer (GTK_WINDOW (data->dialog), data->cert);
g_signal_stop_emission_by_name (w, "response");
- gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->dialog));
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
+
break; }
}
}
diff --git a/smime/gui/ca-trust-dialog.h b/smime/gui/ca-trust-dialog.h
index 8b7d945c00..62b842d945 100644
--- a/smime/gui/ca-trust-dialog.h
+++ b/smime/gui/ca-trust-dialog.h
@@ -21,8 +21,8 @@
*
*/
-#ifndef _CA_TRUST_DIALOG_H_
-#define _CA_TRUST_DIALOG_H
+#ifndef CA_TRUST_DIALOG_H
+#define CA_TRUST_DIALOG_H
#include <gtk/gtk.h>
#include "e-cert.h"
@@ -32,4 +32,4 @@ GtkWidget * ca_trust_dialog_show (ECert *cert, gboolean importing);
void ca_trust_dialog_set_trust (GtkWidget *widget, gboolean ssl, gboolean email, gboolean objsign);
void ca_trust_dialog_get_trust (GtkWidget *widget, gboolean *ssl, gboolean *email, gboolean *objsign);
-#endif /* _CA_TRUST_DIALOG_H_ */
+#endif /* CA_TRUST_DIALOG_H */
diff --git a/smime/gui/certificate-manager.c b/smime/gui/certificate-manager.c
index 548c9c7d79..109bbba515 100644
--- a/smime/gui/certificate-manager.c
+++ b/smime/gui/certificate-manager.c
@@ -531,7 +531,13 @@ view_cert (GtkWidget *button,
-1);
if (cert) {
- GtkWidget *dialog = certificate_viewer_show (cert);
+ GtkWidget *dialog, *parent;
+
+ parent = gtk_widget_get_toplevel (button);
+ if (!parent || !GTK_IS_WINDOW (parent))
+ parent = NULL;
+
+ dialog = e_cert_manager_new_certificate_viewer ((GtkWindow *) parent, cert);
g_signal_connect (
dialog, "response",
G_CALLBACK (gtk_widget_destroy), NULL);
@@ -1107,3 +1113,28 @@ e_cert_manager_config_new (EPreferencesWindow *window)
return GTK_WIDGET (ecmc);
}
+
+GtkWidget *
+e_cert_manager_new_certificate_viewer (GtkWindow *parent,
+ ECert *cert)
+{
+ GtkWidget *dialog;
+ GList *chain, *citer;
+ GSList *issuers = NULL;
+
+ g_return_val_if_fail (cert != NULL, NULL);
+
+ chain = e_cert_get_issuers_chain (cert);
+ for (citer = chain; citer; citer = g_list_next (citer)) {
+ issuers = g_slist_append (issuers, e_cert_get_internal_cert (citer->data));
+ }
+
+ dialog = certificate_viewer_new ((GtkWindow *) parent,
+ e_cert_get_internal_cert (cert),
+ issuers);
+
+ g_list_free_full (chain, g_object_unref);
+ g_slist_free (issuers);
+
+ return dialog;
+}
diff --git a/smime/gui/certificate-manager.h b/smime/gui/certificate-manager.h
index 2eba92cd01..0f74d30694 100644
--- a/smime/gui/certificate-manager.h
+++ b/smime/gui/certificate-manager.h
@@ -65,6 +65,10 @@ GType e_cert_manager_config_get_type (void) G_GNUC_CONST;
GtkWidget *e_cert_manager_config_new (EPreferencesWindow *window);
+struct _ECert; /* forward declaration */
+GtkWidget *e_cert_manager_new_certificate_viewer (GtkWindow *parent,
+ struct _ECert *cert);
+
G_END_DECLS
#endif /* _CERTIFICATE_MANAGER_H_ */
diff --git a/smime/gui/certificate-viewer.c b/smime/gui/certificate-viewer.c
index 9f140cadaa..ce96e50d35 100644
--- a/smime/gui/certificate-viewer.c
+++ b/smime/gui/certificate-viewer.c
@@ -17,359 +17,662 @@
* Chris Toshok <toshok@ximian.com>
*
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
-#include "certificate-viewer.h"
+#include <glib/gi18n.h>
-#include "e-asn1-object.h"
+#include "pk11pub.h"
+#include "hasht.h"
-#include <glib/gi18n.h>
+#include <libedataserver/libedataserver.h>
-#include "e-util/e-util.h"
-#include "e-util/e-util-private.h"
+#include "e-asn1-object.h"
+#include "certificate-viewer.h"
-typedef struct {
- GtkBuilder *builder;
- GtkWidget *dialog;
- GtkTreeStore *hierarchy_store, *fields_store;
- GtkWidget *hierarchy_tree, *fields_tree;
- GtkWidget *field_text;
- GtkTextTag *text_tag;
+#define CERTIFICATE_VIEWER_PRIV_KEY "CertificateViewerPriv-key"
- GList *cert_chain;
-} CertificateViewerData;
+typedef struct _CertificateViewerPriv
+{
+ GtkWidget *issued_to_cn;
+ GtkWidget *issued_to_o;
+ GtkWidget *issued_to_ou;
+ GtkWidget *issued_to_serial;
+ GtkWidget *issued_by_cn;
+ GtkWidget *issued_by_o;
+ GtkWidget *issued_by_ou;
+ GtkWidget *validity_issued_on;
+ GtkWidget *validity_expires_on;
+ GtkWidget *fingerprints_sha1;
+ GtkWidget *fingerprints_md5;
+ GtkWidget *cert_hierarchy_treeview;
+ GtkWidget *cert_fields_treeview;
+ GtkWidget *cert_field_value_textview;
+
+ CERTCertificate *cert;
+ GSList *issuers;
+ GtkTextTag *monospace_tag;
+} CertificateViewerPriv;
static void
-free_data (gpointer data,
- GObject *where_the_object_was)
+free_priv_struct (gpointer ptr)
{
- CertificateViewerData *cvm = data;
+ CertificateViewerPriv *priv = ptr;
+ GSList *iter;
- g_list_foreach (cvm->cert_chain, (GFunc) g_object_unref, NULL);
- g_list_free (cvm->cert_chain);
+ if (!priv)
+ return;
- g_object_unref (cvm->builder);
- g_free (cvm);
-}
+ if (priv->cert)
+ CERT_DestroyCertificate (priv->cert);
-#define NOT_PART_OF_CERT_MARKUP "<i>&lt;Not part of certificate&gt;</i>"
+ for (iter = priv->issuers; iter; iter = iter->next) {
+ CERTCertificate *cert = iter->data;
+
+ if (cert)
+ CERT_DestroyCertificate (cert);
+ }
+
+ g_slist_free (priv->issuers);
+
+ g_free (priv);
+}
static void
-fill_in_general (CertificateViewerData *cvm_data,
- ECert *cert)
+begin_section (GtkGrid *add_to,
+ const gchar *caption,
+ gint *from_row,
+ gint for_rows)
{
- GtkWidget *label;
- const gchar *text;
- gchar *markup;
-
- /* issued to */
- label = e_builder_get_widget (cvm_data->builder, "issued-to-cn");
- if (e_cert_get_cn (cert)) {
- gtk_label_set_text (GTK_LABEL (label), e_cert_get_cn (cert));
- }
- else {
- gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP);
- }
+ GtkWidget *widget;
+ PangoAttribute *attr;
+ PangoAttrList *bold;
+
+ g_return_if_fail (add_to != NULL);
+ g_return_if_fail (caption != NULL);
+ g_return_if_fail (from_row != NULL);
+
+ bold = pango_attr_list_new ();
+ attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
+ pango_attr_list_insert (bold, attr);
+
+ widget = gtk_label_new (caption);
+ g_object_set (G_OBJECT (widget),
+ "hexpand", TRUE,
+ "halign", GTK_ALIGN_START,
+ "justify", GTK_JUSTIFY_LEFT,
+ "attributes", bold,
+ "ellipsize", PANGO_ELLIPSIZE_NONE,
+ NULL);
- label = e_builder_get_widget (cvm_data->builder, "issued-to-o");
- if (e_cert_get_org (cert)) {
- gtk_label_set_text (GTK_LABEL (label), e_cert_get_org (cert));
- }
- else {
- gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP);
- }
+ pango_attr_list_unref (bold);
- label = e_builder_get_widget (cvm_data->builder, "issued-to-ou");
- if (e_cert_get_org_unit (cert)) {
- gtk_label_set_text (GTK_LABEL (label), e_cert_get_org_unit (cert));
- }
- else {
- gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP);
- }
+ gtk_grid_attach (add_to, widget, 0, *from_row, 3, 1);
+ (*from_row)++;
- text = e_cert_get_serial_number (cert);
- label = e_builder_get_widget (cvm_data->builder, "issued-to-serial");
- gtk_label_set_text (GTK_LABEL (label), text);
+ widget = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 12, 0);
- /* issued by */
- label = e_builder_get_widget (cvm_data->builder, "issued-by-cn");
- if (e_cert_get_issuer_cn (cert)) {
- gtk_label_set_text (GTK_LABEL (label), e_cert_get_issuer_cn (cert));
- }
- else {
- gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP);
- }
+ gtk_grid_attach (add_to, widget, 0, *from_row, 1, for_rows);
+}
- label = e_builder_get_widget (cvm_data->builder, "issued-by-o");
- if (e_cert_get_issuer_org (cert)) {
- gtk_label_set_text (GTK_LABEL (label), e_cert_get_issuer_org (cert));
- }
- else {
- gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP);
- }
+static GtkWidget *
+add_info_label (GtkGrid *add_to,
+ const gchar *caption,
+ gint *at_row)
+{
+ GtkWidget *widget;
- label = e_builder_get_widget (cvm_data->builder, "issued-by-ou");
- if (e_cert_get_issuer_org_unit (cert)) {
- gtk_label_set_text (GTK_LABEL (label), e_cert_get_issuer_org_unit (cert));
- }
- else {
- gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP);
- }
+ g_return_val_if_fail (add_to != NULL, NULL);
+ g_return_val_if_fail (at_row != NULL, NULL);
- /* validity */
- label = e_builder_get_widget (cvm_data->builder, "validity-issued-on");
- if (e_cert_get_issued_on (cert)) {
- gtk_label_set_text (GTK_LABEL (label), e_cert_get_issued_on (cert));
- }
- else {
- gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP);
- }
+ if (caption) {
+ widget = gtk_label_new (caption);
+ g_object_set (G_OBJECT (widget),
+ "hexpand", FALSE,
+ "halign", GTK_ALIGN_START,
+ "justify", GTK_JUSTIFY_LEFT,
+ "ellipsize", PANGO_ELLIPSIZE_NONE,
+ NULL);
- label = e_builder_get_widget (cvm_data->builder, "validity-expires-on");
- if (e_cert_get_expires_on (cert)) {
- gtk_label_set_text (GTK_LABEL (label), e_cert_get_expires_on (cert));
+ gtk_grid_attach (add_to, widget, 1, *at_row, 1, 1);
}
- else {
- gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP);
+
+ widget = gtk_label_new ("");
+ g_object_set (G_OBJECT (widget),
+ "hexpand", TRUE,
+ "halign", GTK_ALIGN_START,
+ "justify", GTK_JUSTIFY_LEFT,
+ "ellipsize", PANGO_ELLIPSIZE_NONE,
+ "selectable", caption != NULL,
+ NULL);
+
+ gtk_grid_attach (add_to, widget, caption ? 2 : 1, *at_row, caption ? 1 : 2, 1);
+
+ (*at_row)++;
+
+ return widget;
+}
+
+static GtkWidget *
+add_scrolled_window (GtkGrid *add_to,
+ const gchar *caption,
+ gint *at_row,
+ GtkWidget *add_widget)
+{
+ GtkWidget *widget;
+ PangoAttribute *attr;
+ PangoAttrList *bold;
+
+ g_return_val_if_fail (add_to != NULL, NULL);
+ g_return_val_if_fail (caption != NULL, NULL);
+ g_return_val_if_fail (at_row != NULL, NULL);
+
+ bold = pango_attr_list_new ();
+ attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
+ pango_attr_list_insert (bold, attr);
+
+ widget = gtk_label_new (caption);
+ g_object_set (G_OBJECT (widget),
+ "hexpand", TRUE,
+ "halign", GTK_ALIGN_START,
+ "justify", GTK_JUSTIFY_LEFT,
+ "attributes", bold,
+ "ellipsize", PANGO_ELLIPSIZE_NONE,
+ NULL);
+
+ pango_attr_list_unref (bold);
+
+ gtk_grid_attach (add_to, widget, 0, *at_row, 1, 1);
+ (*at_row)++;
+
+ widget = gtk_scrolled_window_new (NULL, NULL);
+ g_object_set (G_OBJECT (widget),
+ "hexpand", TRUE,
+ "halign", GTK_ALIGN_FILL,
+ "vexpand", TRUE,
+ "valign", GTK_ALIGN_FILL,
+ "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
+ "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
+ "shadow-type", GTK_SHADOW_ETCHED_IN,
+ NULL);
+
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (widget), add_widget);
+
+ gtk_grid_attach (add_to, widget, 0, *at_row, 1, 1);
+ (*at_row)++;
+
+ return add_widget;
+}
+
+#define FLAG_NONE (0)
+#define FLAG_PORT_MEMORY (1 << 0)
+#define FLAG_MARKUP (1 << 1)
+
+static void
+set_label_text (GtkWidget *label,
+ const gchar *not_part_markup,
+ gchar *text,
+ guint32 flags)
+{
+ if (text) {
+ if ((flags & FLAG_MARKUP) != 0)
+ gtk_label_set_markup (GTK_LABEL (label), text);
+ else
+ gtk_label_set_text (GTK_LABEL (label), text);
+
+ if ((flags & FLAG_PORT_MEMORY) != 0)
+ PORT_Free (text);
+ else
+ g_free (text);
+ } else {
+ gtk_label_set_markup (GTK_LABEL (label), not_part_markup);
}
+}
- /* fingerprints */
- markup = g_strdup_printf ("<tt>%s</tt>", e_cert_get_sha1_fingerprint (cert));
- label = e_builder_get_widget (cvm_data->builder, "fingerprints-sha1");
- gtk_label_set_markup (GTK_LABEL (label), markup);
- g_free (markup);
+static void
+get_cert_times (CERTCertificate *cert,
+ gchar **issued_on,
+ gchar **expires_on)
+{
+ PRTime time_issued_on;
+ PRTime time_expires_on;
+ PRExplodedTime explodedTime;
+ struct tm exploded_tm;
+ gchar buf[128];
+
+ g_return_if_fail (cert != NULL);
+ g_return_if_fail (issued_on != NULL);
+ g_return_if_fail (expires_on != NULL);
+
+ if (SECSuccess != CERT_GetCertTimes (cert, &time_issued_on, &time_expires_on))
+ return;
+
+ PR_ExplodeTime (time_issued_on, PR_LocalTimeParameters, &explodedTime);
+ exploded_tm.tm_sec = explodedTime.tm_sec;
+ exploded_tm.tm_min = explodedTime.tm_min;
+ exploded_tm.tm_hour = explodedTime.tm_hour;
+ exploded_tm.tm_mday = explodedTime.tm_mday;
+ exploded_tm.tm_mon = explodedTime.tm_month;
+ exploded_tm.tm_year = explodedTime.tm_year - 1900;
+ e_utf8_strftime (buf, sizeof (buf), "%x", &exploded_tm);
+ *issued_on = g_strdup (buf);
+
+ PR_ExplodeTime (time_expires_on, PR_LocalTimeParameters, &explodedTime);
+ exploded_tm.tm_sec = explodedTime.tm_sec;
+ exploded_tm.tm_min = explodedTime.tm_min;
+ exploded_tm.tm_hour = explodedTime.tm_hour;
+ exploded_tm.tm_mday = explodedTime.tm_mday;
+ exploded_tm.tm_mon = explodedTime.tm_month;
+ exploded_tm.tm_year = explodedTime.tm_year - 1900;
+ e_utf8_strftime (buf, sizeof (buf), "%x", &exploded_tm);
+ *expires_on = g_strdup (buf);
+}
- markup = g_strdup_printf ("<tt>%s</tt>", e_cert_get_md5_fingerprint (cert));
- label = e_builder_get_widget (cvm_data->builder, "fingerprints-md5");
- gtk_label_set_markup (GTK_LABEL (label), markup);
- g_free (markup);
+static void
+fill_general_page (CertificateViewerPriv *priv)
+{
+ gchar *not_part_markup;
+ gchar *issued_on = NULL;
+ gchar *expires_on = NULL;
+ gchar *port_str;
+ guchar fingerprint[128];
+ SECItem fpItem;
+
+ g_return_if_fail (priv != NULL);
+
+ not_part_markup = g_strconcat ("<i>&lt;", _("Not part of certificate"), "&gt;</i>", NULL);
+
+ set_label_text (priv->issued_to_cn, not_part_markup, CERT_GetCommonName (&priv->cert->subject), FLAG_PORT_MEMORY);
+ set_label_text (priv->issued_to_o, not_part_markup, CERT_GetOrgName (&priv->cert->subject), FLAG_PORT_MEMORY);
+ set_label_text (priv->issued_to_ou, not_part_markup, CERT_GetOrgUnitName (&priv->cert->subject), FLAG_PORT_MEMORY);
+ set_label_text (priv->issued_to_serial, not_part_markup, CERT_Hexify (&priv->cert->serialNumber, TRUE), FLAG_PORT_MEMORY);
+
+ set_label_text (priv->issued_by_cn, not_part_markup, CERT_GetCommonName (&priv->cert->issuer), FLAG_PORT_MEMORY);
+ set_label_text (priv->issued_by_o, not_part_markup, CERT_GetOrgName (&priv->cert->issuer), FLAG_PORT_MEMORY);
+ set_label_text (priv->issued_by_ou, not_part_markup, CERT_GetOrgUnitName (&priv->cert->issuer), FLAG_PORT_MEMORY);
+
+ get_cert_times (priv->cert, &issued_on, &expires_on);
+ set_label_text (priv->validity_issued_on, not_part_markup, issued_on, FLAG_NONE);
+ set_label_text (priv->validity_expires_on, not_part_markup, expires_on, FLAG_NONE);
+
+ memset (fingerprint, 0, sizeof fingerprint);
+ PK11_HashBuf (
+ SEC_OID_SHA1, fingerprint,
+ priv->cert->derCert.data,
+ priv->cert->derCert.len);
+ fpItem.data = fingerprint;
+ fpItem.len = SHA1_LENGTH;
+ port_str = CERT_Hexify (&fpItem, TRUE);
+ set_label_text (priv->fingerprints_sha1, not_part_markup, g_strconcat ("<tt>", port_str, "</tt>", NULL), FLAG_MARKUP);
+ PORT_Free (port_str);
+
+ memset (fingerprint, 0, sizeof fingerprint);
+ PK11_HashBuf (
+ SEC_OID_MD5, fingerprint,
+ priv->cert->derCert.data,
+ priv->cert->derCert.len);
+ fpItem.data = fingerprint;
+ fpItem.len = MD5_LENGTH;
+ port_str = CERT_Hexify (&fpItem, TRUE);
+ set_label_text (priv->fingerprints_md5, not_part_markup, g_strconcat ("<tt>", port_str, "</tt>", NULL), FLAG_MARKUP);
+ PORT_Free (port_str);
+
+ g_free (not_part_markup);
}
static void
-populate_fields_tree (CertificateViewerData *cvm_data,
+populate_fields_tree (CertificateViewerPriv *priv,
EASN1Object *asn1,
GtkTreeIter *root)
{
+ GtkTreeStore *fields_store;
GtkTreeIter new_iter;
+ if (!asn1)
+ return;
+
+ fields_store = GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->cert_fields_treeview)));
+
/* first insert a node for the current asn1 */
- gtk_tree_store_insert (cvm_data->fields_store, &new_iter, root, -1);
+ gtk_tree_store_insert (fields_store, &new_iter, root, -1);
gtk_tree_store_set (
- cvm_data->fields_store, &new_iter,
+ fields_store, &new_iter,
0, e_asn1_object_get_display_name (asn1),
1, asn1,
-1);
if (e_asn1_object_is_valid_container (asn1)) {
GList *children = e_asn1_object_get_children (asn1);
+
if (children) {
- GList *l;
- for (l = children; l; l = l->next) {
- EASN1Object *subasn1 = l->data;
- populate_fields_tree (cvm_data, subasn1, &new_iter);
+ GList *iter;
+ for (iter = children; iter; iter = iter->next) {
+ EASN1Object *subasn1 = iter->data;
+
+ populate_fields_tree (priv, subasn1, &new_iter);
}
}
- g_list_foreach (children, (GFunc) g_object_unref, NULL);
- g_list_free (children);
+
+ g_list_free_full (children, g_object_unref);
}
}
static void
-hierarchy_selection_changed (GtkTreeSelection *selection,
- CertificateViewerData *cvm_data)
+hierarchy_selection_changed_cb (GtkTreeSelection *selection,
+ CertificateViewerPriv *priv)
{
GtkTreeIter iter;
GtkTreeModel *model;
- if (gtk_tree_selection_get_selected (selection,
- &model,
- &iter)) {
- EASN1Object *asn1_object;
- ECert *cert;
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ CERTCertificate *cert;
+ EASN1Object *asn1;
+ GtkTreeStore *fields_store;
- gtk_tree_model_get (
- model,
- &iter,
- 1, &cert,
- -1);
+ gtk_tree_model_get (model, &iter, 1, &cert, -1);
if (!cert)
return;
/* display the cert's ASN1 structure */
- asn1_object = e_cert_get_asn1_struct (cert);
+ asn1 = e_asn1_object_new_from_cert (cert);
/* wipe out the old model */
- cvm_data->fields_store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
+ fields_store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_OBJECT);
gtk_tree_view_set_model (
- GTK_TREE_VIEW (cvm_data->fields_tree),
- GTK_TREE_MODEL (cvm_data->fields_store));
+ GTK_TREE_VIEW (priv->cert_fields_treeview),
+ GTK_TREE_MODEL (fields_store));
/* populate the fields from the newly selected cert */
- populate_fields_tree (cvm_data, asn1_object, NULL);
- gtk_tree_view_expand_all (GTK_TREE_VIEW (cvm_data->fields_tree));
- g_object_unref (asn1_object);
+ populate_fields_tree (priv, asn1, NULL);
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (priv->cert_fields_treeview));
+ if (asn1)
+ g_object_unref (asn1);
/* and blow away the field value */
gtk_text_buffer_set_text (
- gtk_text_view_get_buffer (GTK_TEXT_VIEW (cvm_data->field_text)),
+ gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->cert_field_value_textview)),
"", 0);
}
}
static void
-fields_selection_changed (GtkTreeSelection *selection,
- CertificateViewerData *cvm_data)
+fields_selection_changed_cb (GtkTreeSelection *selection,
+ CertificateViewerPriv *priv)
{
GtkTreeIter iter;
GtkTreeModel *model;
- if (gtk_tree_selection_get_selected (selection,
- &model,
- &iter)) {
- EASN1Object *asn1_object;
- const gchar *value;
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ EASN1Object *asn1 = NULL;
+ const gchar *value = NULL;
+ GtkTextView *textview;
+ GtkTextBuffer *textbuffer;
- gtk_tree_model_get (
- model,
- &iter,
- 1, &asn1_object,
- -1);
+ gtk_tree_model_get (model, &iter, 1, &asn1, -1);
- value = e_asn1_object_get_display_value (asn1_object);
+ if (asn1)
+ value = e_asn1_object_get_display_value (asn1);
- gtk_text_buffer_set_text (
- gtk_text_view_get_buffer (GTK_TEXT_VIEW (cvm_data->field_text)),
- "", 0);
+ textview = GTK_TEXT_VIEW (priv->cert_field_value_textview);
+ textbuffer = gtk_text_view_get_buffer (textview);
+
+ gtk_text_buffer_set_text (textbuffer, "", 0);
if (value) {
GtkTextIter text_iter;
- gtk_text_buffer_get_start_iter (
- gtk_text_view_get_buffer (GTK_TEXT_VIEW (cvm_data->field_text)),
- &text_iter);
+ gtk_text_buffer_get_start_iter (textbuffer, &text_iter);
- gtk_text_buffer_insert_with_tags (
- gtk_text_view_get_buffer (GTK_TEXT_VIEW (cvm_data->field_text)),
- &text_iter,
+ gtk_text_buffer_insert_with_tags (textbuffer, &text_iter,
value, strlen (value),
- cvm_data->text_tag, NULL);
+ priv->monospace_tag, NULL);
}
+
+ if (asn1)
+ g_object_unref (asn1);
}
}
static void
-fill_in_details (CertificateViewerData *cvm_data,
- ECert *cert)
+fill_details_page (CertificateViewerPriv *priv)
{
- GList *l;
+ GSList *iter;
GtkTreeIter root;
GtkTreeSelection *selection;
gboolean root_set = FALSE;
+ GtkTreeStore *hierarchy_store;
- /* hook up all the hierarchy tree foo */
- cvm_data->hierarchy_store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_OBJECT);
- cvm_data->hierarchy_tree = e_builder_get_widget (cvm_data->builder, "cert-hierarchy-treeview");
+ g_return_if_fail (priv != NULL);
+
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->cert_hierarchy_treeview), FALSE);
+
+ hierarchy_store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
gtk_tree_view_set_model (
- GTK_TREE_VIEW (cvm_data->hierarchy_tree),
- GTK_TREE_MODEL (cvm_data->hierarchy_store));
+ GTK_TREE_VIEW (priv->cert_hierarchy_treeview),
+ GTK_TREE_MODEL (hierarchy_store));
gtk_tree_view_insert_column_with_attributes (
- GTK_TREE_VIEW (cvm_data->hierarchy_tree),
+ GTK_TREE_VIEW (priv->cert_hierarchy_treeview),
-1, "Cert", gtk_cell_renderer_text_new (),
"text", 0, NULL);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (cvm_data->hierarchy_tree));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->cert_hierarchy_treeview));
g_signal_connect (
selection, "changed",
- G_CALLBACK (hierarchy_selection_changed), cvm_data);
+ G_CALLBACK (hierarchy_selection_changed_cb), priv);
- /* hook up all the fields tree foo */
- cvm_data->fields_tree = e_builder_get_widget (cvm_data->builder, "cert-fields-treeview");
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->cert_fields_treeview), FALSE);
gtk_tree_view_insert_column_with_attributes (
- GTK_TREE_VIEW (cvm_data->fields_tree),
+ GTK_TREE_VIEW (priv->cert_fields_treeview),
-1, "Field", gtk_cell_renderer_text_new (),
"text", 0, NULL);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (cvm_data->fields_tree));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->cert_fields_treeview));
g_signal_connect (
selection, "changed",
- G_CALLBACK (fields_selection_changed), cvm_data);
-
- /* hook up all the field display foo */
- cvm_data->field_text = e_builder_get_widget (cvm_data->builder, "cert-field-value-textview");
+ G_CALLBACK (fields_selection_changed_cb), priv);
/* set the font of the field value viewer to be some fixed
- * width font to the hex display doesn't look like ass. */
- cvm_data->text_tag = gtk_text_buffer_create_tag (
- gtk_text_view_get_buffer (GTK_TEXT_VIEW (cvm_data->field_text)),
- "mono",
- "font", "Mono",
- NULL);
-
- /* initially populate the hierarchy from the cert's chain */
- cvm_data->cert_chain = e_cert_get_chain (cert);
- cvm_data->cert_chain = g_list_reverse (cvm_data->cert_chain);
- for (l = cvm_data->cert_chain; l; l = l->next) {
- ECert *c = l->data;
- const gchar *str;
+ * width font to the hex display looks nice. */
+ priv->monospace_tag = gtk_text_buffer_create_tag (
+ gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->cert_field_value_textview)),
+ "mono", "font", "Mono", NULL);
+
+ /* initially populate the hierarchy from the issuers' chain */
+ for (iter = priv->issuers; iter; iter = g_slist_next (iter)) {
+ CERTCertificate *cert = iter->data;
+ gchar *str;
GtkTreeIter new_iter;
- str = e_cert_get_cn (c);
- if (!str)
- str = e_cert_get_subject_name (c);
+ if (!cert)
+ continue;
+
+ str = CERT_GetCommonName (&cert->subject);
- gtk_tree_store_insert (cvm_data->hierarchy_store, &new_iter, root_set ? &root : NULL, -1);
+ gtk_tree_store_insert (hierarchy_store, &new_iter, root_set ? &root : NULL, -1);
gtk_tree_store_set (
- cvm_data->hierarchy_store, &new_iter,
- 0, str,
- 1, c,
+ hierarchy_store, &new_iter,
+ 0, str ? str : cert->subjectName,
+ 1, cert,
-1);
root = new_iter;
root_set = TRUE;
+
+ if (str)
+ PORT_Free (str);
+ }
+
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (priv->cert_hierarchy_treeview));
+}
+
+static gchar *
+get_window_title (CERTCertificate *cert)
+{
+ gchar *str;
+
+ g_return_val_if_fail (cert != NULL, NULL);
+
+ if (cert->nickname)
+ return g_strdup (cert->nickname);
+
+ str = CERT_GetCommonName (&cert->subject);
+ if (str) {
+ gchar *title;
+
+ title = g_strdup (str);
+ PORT_Free (str);
+
+ return title;
}
- gtk_tree_view_expand_all (GTK_TREE_VIEW (cvm_data->hierarchy_tree));
+ return cert->subjectName;
}
GtkWidget *
-certificate_viewer_show (ECert *cert)
+certificate_viewer_new (GtkWindow *parent,
+ const CERTCertificate *cert,
+ const GSList *issuers_chain_certs)
{
- CertificateViewerData *cvm_data;
- GtkDialog *dialog;
- GtkWidget *action_area;
+ CertificateViewerPriv *priv;
+ GtkWidget *dialog, *notebook, *widget;
+ GtkGrid *grid;
+ gint row;
+ GSList *iter;
gchar *title;
- cvm_data = g_new0 (CertificateViewerData, 1);
+ g_return_val_if_fail (cert != NULL, NULL);
+
+ priv = g_new0 (CertificateViewerPriv, 1);
+ priv->cert = CERT_DupCertificate ((CERTCertificate *) cert);
+ priv->issuers = g_slist_copy ((GSList *) issuers_chain_certs);
- cvm_data->builder = gtk_builder_new ();
- e_load_ui_builder_definition (cvm_data->builder, "smime-ui.ui");
+ /* root issuer first, then bottom down to certificate itself */
+ priv->issuers = g_slist_reverse (priv->issuers);
+ priv->issuers = g_slist_append (priv->issuers, priv->cert);
- cvm_data->dialog = e_builder_get_widget (cvm_data->builder, "certificate-viewer-dialog");
+ for (iter = priv->issuers; iter; iter = g_slist_next (iter)) {
+ iter->data = CERT_DupCertificate (iter->data);
+ }
- gtk_widget_realize (cvm_data->dialog);
+ title = get_window_title (priv->cert);
- dialog = GTK_DIALOG (cvm_data->dialog);
- action_area = gtk_dialog_get_action_area (dialog);
- gtk_container_set_border_width (GTK_CONTAINER (action_area), 12);
+ dialog = gtk_dialog_new_with_buttons (title, parent,
+ GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
+ GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+ NULL);
- title = g_strdup_printf (
- _("Certificate Viewer: %s"), e_cert_get_window_title (cert));
- gtk_window_set_title (GTK_WINDOW (cvm_data->dialog), title);
g_free (title);
- fill_in_general (cvm_data, cert);
- fill_in_details (cvm_data, cert);
+ g_object_set_data_full (G_OBJECT (dialog), CERTIFICATE_VIEWER_PRIV_KEY, priv, free_priv_struct);
+
+ notebook = gtk_notebook_new ();
+ gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), notebook);
+ gtk_container_set_border_width (GTK_CONTAINER (notebook), 12);
+
+ /* General page */
+ row = 0;
+ grid = GTK_GRID (gtk_grid_new ());
+ g_object_set (G_OBJECT (grid),
+ "hexpand", TRUE,
+ "halign", GTK_ALIGN_FILL,
+ "vexpand", FALSE,
+ "valign", GTK_ALIGN_START,
+ "border-width", 12,
+ "row-spacing", 6,
+ "column-spacing", 6,
+ NULL);
+
+ begin_section (grid, _("This certificate has been verified for the following uses:"), &row, 4);
+
+ if (!priv->cert->keyUsagePresent || (priv->cert->keyUsage & certificateUsageSSLClient) != 0) {
+ widget = add_info_label (grid, NULL, &row);
+ gtk_label_set_text (GTK_LABEL (widget), _("SSL Client Certificate"));
+ }
+
+ if (!priv->cert->keyUsagePresent || (priv->cert->keyUsage & (certificateUsageSSLServer | certificateUsageSSLCA)) != 0) {
+ widget = add_info_label (grid, NULL, &row);
+ gtk_label_set_text (GTK_LABEL (widget), _("SSL Server Certificate"));
+ }
+
+ if (!priv->cert->keyUsagePresent || (priv->cert->keyUsage & certificateUsageEmailSigner) != 0) {
+ widget = add_info_label (grid, NULL, &row);
+ gtk_label_set_text (GTK_LABEL (widget), _("Email Signer Certificate"));
+ }
+
+ if (!priv->cert->keyUsagePresent || (priv->cert->keyUsage & certificateUsageEmailRecipient) != 0) {
+ widget = add_info_label (grid, NULL, &row);
+ gtk_label_set_text (GTK_LABEL (widget), _("Email Recipient Certificate"));
+ }
+
+ widget = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+ g_object_set (G_OBJECT (widget),
+ "hexpand", TRUE,
+ "halign", GTK_ALIGN_FILL,
+ "vexpand", FALSE,
+ "valign", GTK_ALIGN_START,
+ NULL);
+
+ gtk_grid_attach (grid, widget, 0, row, 3, 1);
+ row++;
+
+ begin_section (grid, _("Issued To"), &row, 4);
+ priv->issued_to_cn = add_info_label (grid, _("Common Name (CN)"), &row);
+ priv->issued_to_o = add_info_label (grid, _("Organization (O)"), &row);
+ priv->issued_to_ou = add_info_label (grid, _("Organizational Unit (OU)"), &row);
+ priv->issued_to_serial = add_info_label (grid, _("Serial Number"), &row);
+
+ begin_section (grid, _("Issued By"), &row, 3);
+ priv->issued_by_cn = add_info_label (grid, _("Common Name (CN)"), &row);
+ priv->issued_by_o = add_info_label (grid, _("Organization (O)"), &row);
+ priv->issued_by_ou = add_info_label (grid, _("Organizational Unit (OU)"), &row);
+
+ begin_section (grid, _("Validity"), &row, 2);
+ priv->validity_issued_on = add_info_label (grid, _("Issued On"), &row);
+ priv->validity_expires_on = add_info_label (grid, _("Expires On"), &row);
+
+ begin_section (grid, _("Fingerprints"), &row, 2);
+ priv->fingerprints_sha1 = add_info_label (grid, _("SHA1 Fingerprint"), &row);
+ priv->fingerprints_md5 = add_info_label (grid, _("MD5 Fingerprint"), &row);
+
+ widget = gtk_label_new (_("General"));
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), GTK_WIDGET (grid), widget);
+
+ /* Details page */
+ row = 0;
+ grid = GTK_GRID (gtk_grid_new ());
+ g_object_set (G_OBJECT (grid),
+ "hexpand", TRUE,
+ "halign", GTK_ALIGN_FILL,
+ "vexpand", TRUE,
+ "valign", GTK_ALIGN_FILL,
+ "border-width", 12,
+ "row-spacing", 6,
+ "column-spacing", 6,
+ NULL);
+
+ priv->cert_hierarchy_treeview = add_scrolled_window (grid,
+ _("Certificate Hierarchy"), &row, gtk_tree_view_new ());
+
+ priv->cert_fields_treeview = add_scrolled_window (grid,
+ _("Certificate Fields"), &row, gtk_tree_view_new ());
+
+ priv->cert_field_value_textview = add_scrolled_window (grid,
+ _("Field Value"), &row, gtk_text_view_new ());
+
+ widget = gtk_label_new (_("Details"));
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), GTK_WIDGET (grid), widget);
+
+ gtk_widget_show_all (notebook);
- g_object_weak_ref (G_OBJECT (cvm_data->dialog), free_data, cvm_data);
+ fill_general_page (priv);
+ fill_details_page (priv);
- /* gtk_widget_show (cvm_data->dialog);*/
- return cvm_data->dialog;
+ return dialog;
}
diff --git a/smime/gui/certificate-viewer.h b/smime/gui/certificate-viewer.h
index d452b76c2c..41f2c83c7b 100644
--- a/smime/gui/certificate-viewer.h
+++ b/smime/gui/certificate-viewer.h
@@ -17,15 +17,16 @@
* Chris Toshok <toshok@ximian.com>
*
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
*/
-#ifndef _CERTIFICATE_VIEWER_H_
-#define _CERTIFICATE_VIEWER_H
+#ifndef CERTIFICATE_VIEWER_H
+#define CERTIFICATE_VIEWER_H
#include <gtk/gtk.h>
-#include "e-cert.h"
+#include <cert.h>
-GtkWidget * certificate_viewer_show (ECert *cert);
+GtkWidget * certificate_viewer_new (GtkWindow *parent,
+ const CERTCertificate *cert,
+ const GSList *issuers_chain_certs);
-#endif /* _CERTIFICATE_VIEWER_H_ */
+#endif /* CERTIFICATE_VIEWER_H */
diff --git a/smime/gui/smime-ui.ui b/smime/gui/smime-ui.ui
index 0ad3f47d81..5622c4d0e5 100644
--- a/smime/gui/smime-ui.ui
+++ b/smime/gui/smime-ui.ui
@@ -16,714 +16,6 @@
</row>
</data>
</object>
- <object class="GtkDialog" id="certificate-viewer-dialog">
- <property name="title">dialog1</property>
- <property name="window_position">center</property>
- <property name="type_hint">dialog</property>
- <child internal-child="vbox">
- <object class="GtkVBox" id="dialog-vbox1">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkNotebook" id="notebook1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="border_width">12</property>
- <child>
- <object class="GtkVBox" id="vbox1">
- <property name="visible">True</property>
- <property name="border_width">6</property>
- <property name="orientation">vertical</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkFrame" id="frame1">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <child>
- <object class="GtkVBox" id="vbox2">
- <property name="visible">True</property>
- <property name="border_width">6</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkLabel" id="ssl-client-cert-verified-label">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">SSL Client Certificate</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="ssl-server-cert-verified-label">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">SSL Server Certificate</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="email-signer-cert-verified-label">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Email Signer Certificate</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="email-recipient-cert-verified-label">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Email Recipient Certificate</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">3</property>
- </packing>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="label3">
- <property name="visible">True</property>
- <property name="label" translatable="yes">This certificate has been verified for the following uses:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkHSeparator" id="hseparator1">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkTable" id="table3">
- <property name="visible">True</property>
- <property name="border_width">3</property>
- <property name="n_rows">15</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">6</property>
- <child>
- <object class="GtkLabel" id="label25">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="yalign">1</property>
- <property name="ypad">3</property>
- <property name="label" translatable="yes">Issued To</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="right_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label26">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">6</property>
- <property name="label" translatable="yes">Common Name (CN)</property>
- </object>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label27">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">6</property>
- <property name="label" translatable="yes">Organization (O)</property>
- </object>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label28">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">6</property>
- <property name="label" translatable="yes">Organizational Unit (OU)</property>
- </object>
- <packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label29">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">6</property>
- <property name="label" translatable="yes">Serial Number</property>
- </object>
- <packing>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label31">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">6</property>
- <property name="label" translatable="yes">Common Name (CN)</property>
- </object>
- <packing>
- <property name="top_attach">6</property>
- <property name="bottom_attach">7</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label32">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">6</property>
- <property name="label" translatable="yes">Organization (O)</property>
- </object>
- <packing>
- <property name="top_attach">7</property>
- <property name="bottom_attach">8</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label33">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">6</property>
- <property name="label" translatable="yes">Organizational Unit (OU)</property>
- </object>
- <packing>
- <property name="top_attach">8</property>
- <property name="bottom_attach">9</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label36">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">6</property>
- <property name="label" translatable="yes">Issued On</property>
- </object>
- <packing>
- <property name="top_attach">10</property>
- <property name="bottom_attach">11</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label37">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">6</property>
- <property name="label" translatable="yes">Expires On</property>
- </object>
- <packing>
- <property name="top_attach">11</property>
- <property name="bottom_attach">12</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label30">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="yalign">1</property>
- <property name="ypad">3</property>
- <property name="label" translatable="yes">Issued By</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="right_attach">2</property>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label35">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="ypad">3</property>
- <property name="label" translatable="yes">Fingerprints</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="right_attach">2</property>
- <property name="top_attach">12</property>
- <property name="bottom_attach">13</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label38">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">6</property>
- <property name="label" translatable="yes">SHA1 Fingerprint</property>
- </object>
- <packing>
- <property name="top_attach">13</property>
- <property name="bottom_attach">14</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label39">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">6</property>
- <property name="label" translatable="yes">MD5 Fingerprint</property>
- </object>
- <packing>
- <property name="top_attach">14</property>
- <property name="bottom_attach">15</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="issued-to-o">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="issued-to-ou">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="issued-to-serial">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="issued-by-cn">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">6</property>
- <property name="bottom_attach">7</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="issued-by-o">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">7</property>
- <property name="bottom_attach">8</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="issued-by-ou">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">8</property>
- <property name="bottom_attach">9</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="validity-issued-on">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">10</property>
- <property name="bottom_attach">11</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="validity-expires-on">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">11</property>
- <property name="bottom_attach">12</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="fingerprints-sha1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">13</property>
- <property name="bottom_attach">14</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="fingerprints-md5">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">14</property>
- <property name="bottom_attach">15</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="issued-to-cn">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label34">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="ypad">3</property>
- <property name="label" translatable="yes">Validity</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="right_attach">2</property>
- <property name="top_attach">9</property>
- <property name="bottom_attach">10</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- </child>
- <child type="tab">
- <object class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="label" translatable="yes">General</property>
- </object>
- <packing>
- <property name="tab_fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkVBox" id="vbox3">
- <property name="visible">True</property>
- <property name="border_width">6</property>
- <property name="orientation">vertical</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkFrame" id="frame4">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <child>
- <object class="GtkScrolledWindow" id="scrolledwindow1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="border_width">6</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkTreeView" id="cert-hierarchy-treeview">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="headers_visible">False</property>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="label51">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Certificate Hierarchy</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkFrame" id="frame5">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <child>
- <object class="GtkScrolledWindow" id="scrolledwindow2">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="border_width">6</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkTreeView" id="cert-fields-treeview">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="headers_visible">False</property>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="label52">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Certificate Fields</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkFrame" id="frame6">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <child>
- <object class="GtkScrolledWindow" id="scrolledwindow3">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="border_width">6</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">etched-in</property>
- <child>
- <object class="GtkTextView" id="cert-field-value-textview">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="editable">False</property>
- <property name="cursor_visible">False</property>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="label53">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Field Value</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child type="tab">
- <object class="GtkLabel" id="label2">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Details</property>
- </object>
- <packing>
- <property name="position">1</property>
- <property name="tab_fill">False</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <object class="GtkHButtonBox" id="dialog-action_area1">
- <property name="visible">True</property>
- <property name="layout_style">end</property>
- <child>
- <object class="GtkButton" id="closebutton1">
- <property name="label">gtk-close</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="receives_default">False</property>
- <property name="use_stock">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- </child>
- <action-widgets>
- <action-widget response="-7">closebutton1</action-widget>
- </action-widgets>
- </object>
<object class="GtkWindow" id="cert-manager-config-control">
<property name="title">window1</property>
<child>
diff --git a/smime/lib/e-asn1-object.c b/smime/lib/e-asn1-object.c
index 53441516f5..7e5f27ca0c 100644
--- a/smime/lib/e-asn1-object.c
+++ b/smime/lib/e-asn1-object.c
@@ -39,13 +39,18 @@
*
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*/
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+#include <glib/gi18n.h>
+
#include "e-asn1-object.h"
-#include "secasn1.h"
+#include "pk11func.h"
+#include "certdb.h"
+#include "hasht.h"
#define E_ASN1_OBJECT_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -67,220 +72,793 @@ struct _EASN1ObjectPrivate {
G_DEFINE_TYPE (EASN1Object, e_asn1_object, G_TYPE_OBJECT)
-static void
-e_asn1_object_finalize (GObject *object)
+static gboolean
+get_int_value (SECItem *versionItem,
+ gulong *version)
{
- EASN1ObjectPrivate *priv;
+ SECStatus srv;
+ srv = SEC_ASN1DecodeInteger (versionItem,version);
+ if (srv != SECSuccess) {
+ g_warning ("could not decode version of cert");
+ return FALSE;
+ }
+ return TRUE;
+}
- priv = E_ASN1_OBJECT_GET_PRIVATE (object);
+static gboolean
+process_version (SECItem *versionItem,
+ EASN1Object **retItem)
+{
+ EASN1Object *item = e_asn1_object_new ();
+ gulong version;
- g_free (priv->display_name);
- g_free (priv->value);
+ e_asn1_object_set_display_name (item, _("Version"));
- g_list_free_full (priv->children, (GDestroyNotify) g_object_unref);
+ /* Now to figure out what version this certificate is. */
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (e_asn1_object_parent_class)->finalize (object);
+ if (versionItem->data) {
+ if (!get_int_value (versionItem, &version))
+ return FALSE;
+ } else {
+ /* If there is no version present in the cert, then rfc2459
+ * says we default to v1 (0) */
+ version = 0;
+ }
+
+ switch (version) {
+ case 0:
+ e_asn1_object_set_display_value (item, _("Version 1"));
+ break;
+ case 1:
+ e_asn1_object_set_display_value (item, _("Version 2"));
+ break;
+ case 2:
+ e_asn1_object_set_display_value (item, _("Version 3"));
+ break;
+ default:
+ g_warning ("Bad value for cert version");
+ return FALSE;
+ }
+
+ *retItem = item;
+ return TRUE;
}
-static void
-e_asn1_object_class_init (EASN1ObjectClass *class)
+static gboolean
+process_serial_number_der (SECItem *serialItem,
+ EASN1Object **retItem)
{
- GObjectClass *object_class;
+ gchar *serialNumber;
+ EASN1Object *item = e_asn1_object_new ();
- g_type_class_add_private (class, sizeof (EASN1ObjectPrivate));
+ e_asn1_object_set_display_name (item, _("Serial Number"));
- object_class = G_OBJECT_CLASS (class);
- object_class->finalize = e_asn1_object_finalize;
+ serialNumber = CERT_Hexify (serialItem, 1);
+
+ e_asn1_object_set_display_value (item, serialNumber);
+ PORT_Free (serialNumber); /* XXX the right free to use? */
+
+ *retItem = item;
+ return TRUE;
}
-static void
-e_asn1_object_init (EASN1Object *asn1)
+static gboolean
+get_default_oid_format (SECItem *oid,
+ gchar **text)
{
- asn1->priv = E_ASN1_OBJECT_GET_PRIVATE (asn1);
-
- asn1->priv->valid_container = TRUE;
+ GString *str;
+ gulong val = oid->data[0];
+ guint ii = val % 40;
+
+ val /= 40;
+
+ str = g_string_new ("");
+ g_string_append_printf (str, "%lu %u ", val, ii);
+
+ val = 0;
+ for (ii = 1; ii < oid->len; ii++) {
+ /* In this loop, we have to parse a DER formatted
+ * If the first bit is a 1, then the integer is
+ * represented by more than one byte. If the
+ * first bit is set then we continue on and add
+ * the values of the later bytes until we get
+ * a byte without the first bit set.
+ */
+ gulong jj;
+
+ jj = oid->data[ii];
+ val = (val << 7) | (jj & 0x7f);
+ if (jj & 0x80)
+ continue;
+ g_string_append_printf (str, "%lu ", val);
+
+ val = 0;
+ }
+
+ *text = g_string_free (str, FALSE);
+
+ return TRUE;
}
-/* This function is used to interpret an integer that
- * was encoded in a DER buffer. This function is used
- * when converting a DER buffer into a nsIASN1Object
- * structure. This interprets the buffer in data
- * as defined by the DER (Distinguised Encoding Rules) of
- * ASN1.
-*/
-static gint
-get_integer_256 (guchar *data,
- guint nb)
+static gboolean
+get_oid_text (SECItem *oid,
+ gchar **text)
{
- gint val;
+ SECOidTag oidTag = SECOID_FindOIDTag (oid);
+ gchar *temp;
- switch (nb) {
- case 1:
- val = data[0];
+ switch (oidTag) {
+ case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
+ *text = g_strdup (_("PKCS #1 MD2 With RSA Encryption"));
break;
- case 2:
- val = (data[0] << 8) | data[1];
+ case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
+ *text = g_strdup (_("PKCS #1 MD5 With RSA Encryption"));
+ break;
+ case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
+ *text = g_strdup (_("PKCS #1 SHA-1 With RSA Encryption"));
+ break;
+ case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
+ *text = g_strdup (_("PKCS #1 SHA-256 With RSA Encryption"));
+ break;
+ case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
+ *text = g_strdup (_("PKCS #1 SHA-384 With RSA Encryption"));
+ break;
+ case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
+ *text = g_strdup (_("PKCS #1 SHA-512 With RSA Encryption"));
+ break;
+ case SEC_OID_AVA_COUNTRY_NAME:
+ *text = g_strdup ("C");
+ break;
+ case SEC_OID_AVA_COMMON_NAME:
+ *text = g_strdup ("CN");
+ break;
+ case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
+ *text = g_strdup ("OU");
+ break;
+ case SEC_OID_AVA_ORGANIZATION_NAME:
+ *text = g_strdup ("O");
+ break;
+ case SEC_OID_AVA_LOCALITY:
+ *text = g_strdup ("L");
+ break;
+ case SEC_OID_AVA_DN_QUALIFIER:
+ *text = g_strdup ("DN");
+ break;
+ case SEC_OID_AVA_DC:
+ *text = g_strdup ("DC");
+ break;
+ case SEC_OID_AVA_STATE_OR_PROVINCE:
+ *text = g_strdup ("ST");
+ break;
+ case SEC_OID_PKCS1_RSA_ENCRYPTION:
+ *text = g_strdup (_("PKCS #1 RSA Encryption"));
+ break;
+ case SEC_OID_X509_KEY_USAGE:
+ *text = g_strdup (_("Certificate Key Usage"));
break;
- case 3:
- val = (data[0] << 16) | (data[1] << 8) | data[2];
+ case SEC_OID_NS_CERT_EXT_CERT_TYPE:
+ *text = g_strdup (_("Netscape Certificate Type"));
break;
- case 4:
- val = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+ case SEC_OID_X509_AUTH_KEY_ID:
+ *text = g_strdup (_("Certificate Authority Key Identifier"));
+ break;
+ case SEC_OID_RFC1274_UID:
+ *text = g_strdup ("UID");
+ break;
+ case SEC_OID_PKCS9_EMAIL_ADDRESS:
+ *text = g_strdup ("E");
break;
default:
- return -1;
- }
+ if (!get_default_oid_format (oid, &temp))
+ return FALSE;
- return val;
+ *text = g_strdup_printf (_("Object Identifier (%s)"), temp);
+ g_free (temp);
+
+ break;
+ }
+ return TRUE;
}
-/* This function is used to retrieve the lenght of a DER encoded
- * item. It looks to see if this a multibyte length and then
- * interprets the buffer accordingly to get the actual length value.
- * This funciton is used mostly while parsing the DER headers.
- *
- * A DER encoded item has the following structure:
- *
- * <tag><length<data consisting of lenght bytes>
- */
-static guint32
-get_der_item_length (guchar *data,
- guchar *end,
- gulong *bytesUsed,
- gboolean *indefinite)
-{
- guchar lbyte = *data++;
- PRInt32 length = -1;
-
- *indefinite = FALSE;
- if (lbyte >= 0x80) {
- /* Multibyte length */
- guint nb = (guint) (lbyte & 0x7f);
- if (nb > 4) {
- return -1;
+static gboolean
+process_raw_bytes (SECItem *data,
+ gchar **text)
+{
+ /* This function is used to display some DER bytes
+ * that we have not added support for decoding.
+ * It prints the value of the byte out into a
+ * string that can later be displayed as a byte
+ * string. We place a new line after 24 bytes
+ * to break up extermaly long sequence of bytes.
+ */
+ GString *str = g_string_new ("");
+ PRUint32 i;
+
+ for (i = 0; i < data->len; i++) {
+ g_string_append_printf (str, "%02x ", data->data[i]);
+ if ((i + 1) % 16 == 0) {
+ g_string_append (str, "\n");
}
- if (nb > 0) {
+ }
+ *text = g_string_free (str, FALSE);
+ return TRUE;
+}
- if ((data + nb) > end) {
- return -1;
- }
- length = get_integer_256 (data, nb);
- if (length < 0)
- return -1;
- } else {
- *indefinite = TRUE;
- length = 0;
- }
- *bytesUsed = nb+1;
+static gboolean
+process_sec_algorithm_id (SECAlgorithmID *algID,
+ EASN1Object **retSequence)
+{
+ EASN1Object *sequence = e_asn1_object_new ();
+ gchar *text = NULL;
+
+ *retSequence = NULL;
+
+ get_oid_text (&algID->algorithm, &text);
+
+ if (!algID->parameters.len ||
+ algID->parameters.data[0] == E_ASN1_OBJECT_TYPE_NULL) {
+ e_asn1_object_set_display_value (sequence, text);
+ e_asn1_object_set_valid_container (sequence, FALSE);
} else {
- length = lbyte;
- *bytesUsed = 1;
+ EASN1Object *subitem;
+
+ subitem = e_asn1_object_new ();
+ e_asn1_object_set_display_name (subitem, _("Algorithm Identifier"));
+ e_asn1_object_set_display_value (subitem, text);
+ e_asn1_object_append_child (sequence, subitem);
+ g_object_unref (subitem);
+
+ g_free (text);
+
+ subitem = e_asn1_object_new ();
+ e_asn1_object_set_display_name (subitem, _("Algorithm Parameters"));
+ process_raw_bytes (&algID->parameters, &text);
+ e_asn1_object_set_display_value (subitem, text);
+ e_asn1_object_append_child (sequence, subitem);
+ g_object_unref (subitem);
}
- return length;
+
+ g_free (text);
+ *retSequence = sequence;
+ return TRUE;
}
static gboolean
-build_from_der (EASN1Object *parent,
- gchar *data,
- gchar *end)
+process_subject_public_key_info (CERTSubjectPublicKeyInfo *spki,
+ EASN1Object *parentSequence)
{
- gulong bytesUsed;
- gboolean indefinite;
- PRInt32 len;
- PRUint32 type;
- guchar code, tagnum;
- EASN1Object *asn1object = NULL;
+ EASN1Object *spkiSequence = e_asn1_object_new ();
+ EASN1Object *sequenceItem;
+ EASN1Object *printableItem;
+ SECItem data;
+ gchar *text = NULL;
+
+ e_asn1_object_set_display_name (spkiSequence, _("Subject Public Key Info"));
+
+ if (!process_sec_algorithm_id (&spki->algorithm, &sequenceItem))
+ return FALSE;
+
+ e_asn1_object_set_display_name (sequenceItem, _("Subject Public Key Algorithm"));
+
+ e_asn1_object_append_child (spkiSequence, sequenceItem);
- if (data >= end)
+ /* The subjectPublicKey field is encoded as a bit string.
+ * ProcessRawBytes expects the lenght to be in bytes, so
+ * let's convert the lenght into a temporary SECItem.
+ */
+ data.data = spki->subjectPublicKey.data;
+ data.len = spki->subjectPublicKey.len / 8;
+
+ process_raw_bytes (&data, &text);
+ printableItem = e_asn1_object_new ();
+
+ e_asn1_object_set_display_value (printableItem, text);
+ e_asn1_object_set_display_name (printableItem, _("Subject's Public Key"));
+ e_asn1_object_append_child (spkiSequence, printableItem);
+ g_object_unref (printableItem);
+ g_free (text);
+
+ e_asn1_object_append_child (parentSequence, spkiSequence);
+ g_object_unref (spkiSequence);
+
+ return TRUE;
+}
+
+static gboolean
+process_ns_cert_type_extensions (SECItem *extData,
+ GString *text)
+{
+ SECItem decoded;
+ guchar nsCertType;
+
+ decoded.data = NULL;
+ decoded.len = 0;
+ if (SECSuccess != SEC_ASN1DecodeItem (NULL, &decoded,
+ SEC_ASN1_GET (SEC_BitStringTemplate), extData)) {
+ g_string_append (text, _("Error: Unable to process extension"));
return TRUE;
+ }
- /*
- * A DER item has the form of |tag|len|data
- * tag is one byte and describes the type of elment
- * we are dealing with.
- * len is a DER encoded gint telling us how long the data is
- * data is a buffer that is len bytes long and has to be
- * interpreted according to its type.
- */
+ nsCertType = decoded.data[0];
- while (data < end) {
- code = *data;
- tagnum = code & SEC_ASN1_TAGNUM_MASK;
+ PORT_Free (decoded.data); /* XXX right free? */
- /*
- * NOTE: This code does not (yet) handle the high-tag-number form!
- */
- if (tagnum == SEC_ASN1_HIGH_TAG_NUMBER) {
- return FALSE;
+ if (nsCertType & NS_CERT_TYPE_SSL_CLIENT) {
+ g_string_append (text, _("SSL Client Certificate"));
+ g_string_append (text, "\n");
+ }
+ if (nsCertType & NS_CERT_TYPE_SSL_SERVER) {
+ g_string_append (text, _("SSL Server Certificate"));
+ g_string_append (text, "\n");
+ }
+ if (nsCertType & NS_CERT_TYPE_EMAIL) {
+ g_string_append (text, _("Email"));
+ g_string_append (text, "\n");
+ }
+ if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING) {
+ g_string_append (text, _("Object Signer"));
+ g_string_append (text, "\n");
+ }
+ if (nsCertType & NS_CERT_TYPE_SSL_CA) {
+ g_string_append (text, _("SSL Certificate Authority"));
+ g_string_append (text, "\n");
+ }
+ if (nsCertType & NS_CERT_TYPE_EMAIL_CA) {
+ g_string_append (text, _("Email Certificate Authority"));
+ g_string_append (text, "\n");
+ }
+ if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING_CA) {
+ g_string_append (text, _("Object Signer"));
+ g_string_append (text, "\n");
+ }
+ return TRUE;
+}
+
+static gboolean
+process_key_usage_extensions (SECItem *extData,
+ GString *text)
+{
+ SECItem decoded;
+ guchar keyUsage;
+
+ decoded.data = NULL;
+ decoded.len = 0;
+ if (SECSuccess != SEC_ASN1DecodeItem (NULL, &decoded,
+ SEC_ASN1_GET (SEC_BitStringTemplate), extData)) {
+ g_string_append (text, _("Error: Unable to process extension"));
+ return TRUE;
+ }
+
+ keyUsage = decoded.data[0];
+ PORT_Free (decoded.data); /* XXX right free? */
+
+ if (keyUsage & KU_DIGITAL_SIGNATURE) {
+ g_string_append (text, _("Signing"));
+ g_string_append (text, "\n");
+ }
+ if (keyUsage & KU_NON_REPUDIATION) {
+ g_string_append (text, _("Non-repudiation"));
+ g_string_append (text, "\n");
+ }
+ if (keyUsage & KU_KEY_ENCIPHERMENT) {
+ g_string_append (text, _("Key Encipherment"));
+ g_string_append (text, "\n");
+ }
+ if (keyUsage & KU_DATA_ENCIPHERMENT) {
+ g_string_append (text, _("Data Encipherment"));
+ g_string_append (text, "\n");
+ }
+ if (keyUsage & KU_KEY_AGREEMENT) {
+ g_string_append (text, _("Key Agreement"));
+ g_string_append (text, "\n");
+ }
+ if (keyUsage & KU_KEY_CERT_SIGN) {
+ g_string_append (text, _("Certificate Signer"));
+ g_string_append (text, "\n");
+ }
+ if (keyUsage & KU_CRL_SIGN) {
+ g_string_append (text, _("CRL Signer"));
+ g_string_append (text, "\n");
+ }
+
+ return TRUE;
+}
+
+static gboolean
+process_extension_data (SECOidTag oidTag,
+ SECItem *extData,
+ GString *str)
+{
+ gboolean rv;
+ switch (oidTag) {
+ case SEC_OID_NS_CERT_EXT_CERT_TYPE:
+ rv = process_ns_cert_type_extensions (extData, str);
+ break;
+ case SEC_OID_X509_KEY_USAGE:
+ rv = process_key_usage_extensions (extData, str);
+ break;
+ default: {
+ gchar *text;
+ rv = process_raw_bytes (extData, &text);
+ g_string_append (str, text);
+ g_free (text);
+ break;
+ }
+ }
+ return rv;
+}
+
+static gboolean
+process_single_extension (CERTCertExtension *extension,
+ EASN1Object **retExtension)
+{
+ GString *str = g_string_new ("");
+ gchar *text;
+ EASN1Object *extensionItem;
+ SECOidTag oidTag = SECOID_FindOIDTag (&extension->id);
+
+ get_oid_text (&extension->id, &text);
+
+ extensionItem = e_asn1_object_new ();
+
+ e_asn1_object_set_display_name (extensionItem, text);
+ g_free (text);
+
+ if (extension->critical.data != NULL) {
+ if (extension->critical.data[0]) {
+ g_string_append (str, _("Critical"));
+ } else {
+ g_string_append (str, _("Not Critical"));
}
- data++;
- len = get_der_item_length (
- (guchar *) data, (guchar *) end,
- &bytesUsed, &indefinite);
- data += bytesUsed;
- if ((len < 0) || ((data + len) > end))
+ } else {
+ g_string_append (str, _("Not Critical"));
+ }
+ g_string_append (str, "\n");
+ if (!process_extension_data (oidTag, &extension->value, str)) {
+ g_string_free (str, TRUE);
+ return FALSE;
+ }
+
+ e_asn1_object_set_display_value (extensionItem, str->str);
+ g_string_free (str, TRUE);
+ *retExtension = extensionItem;
+ return TRUE;
+}
+
+static gboolean
+process_extensions (CERTCertExtension **extensions,
+ EASN1Object *parentSequence)
+{
+ EASN1Object *extensionSequence = e_asn1_object_new ();
+ PRInt32 i;
+
+ e_asn1_object_set_display_name (extensionSequence, _("Extensions"));
+
+ for (i = 0; extensions[i] != NULL; i++) {
+ EASN1Object *newExtension;
+
+ if (!process_single_extension (extensions[i],
+ &newExtension))
return FALSE;
- if (code & SEC_ASN1_CONSTRUCTED) {
- if (len > 0 || indefinite) {
- switch (code & SEC_ASN1_CLASS_MASK) {
- case SEC_ASN1_UNIVERSAL:
- type = tagnum;
- break;
- case SEC_ASN1_APPLICATION:
- type = E_ASN1_OBJECT_TYPE_APPLICATION;
- break;
- case SEC_ASN1_CONTEXT_SPECIFIC:
- type = E_ASN1_OBJECT_TYPE_CONTEXT_SPECIFIC;
- break;
- case SEC_ASN1_PRIVATE:
- type = E_ASN1_OBJECT_TYPE_PRIVATE;
- break;
- default:
- g_warning ("bad DER");
- return FALSE;
- }
-
- asn1object = e_asn1_object_new ();
- asn1object->priv->tag = tagnum;
- asn1object->priv->type = type;
-
- if (!build_from_der (
- asn1object, data,
- (len == 0) ? end : data + len)) {
- g_object_unref (asn1object);
- return FALSE;
- }
- }
- } else {
- asn1object = e_asn1_object_new ();
+ e_asn1_object_append_child (extensionSequence, newExtension);
+ }
+ e_asn1_object_append_child (parentSequence, extensionSequence);
+ return TRUE;
+}
- asn1object->priv->type = tagnum;
- asn1object->priv->tag = tagnum;
+static gboolean
+process_name (CERTName *name,
+ gchar **value)
+{
+ CERTRDN ** rdns;
+ CERTRDN ** rdn;
+ CERTAVA ** avas;
+ CERTAVA * ava;
+ SECItem *decodeItem = NULL;
+ GString *final_string = g_string_new ("");
+
+ gchar *type;
+ GString *avavalue;
+ gchar *temp;
+ CERTRDN **lastRdn;
+
+ rdns = name->rdns;
+
+ /* find last RDN */
+ lastRdn = rdns;
+ while (*lastRdn) lastRdn++;
+
+ /* The above whille loop will put us at the last member
+ * of the array which is a NULL pointer. So let's back
+ * up one spot so that we have the last non-NULL entry in
+ * the array in preparation for traversing the
+ * RDN's (Relative Distinguished Name) in reverse order.
+ */
+ lastRdn--;
- /*printableItem->SetData((gchar *)data, len);*/
+ /*
+ * Loop over name contents in _reverse_ RDN order appending to string
+ * When building the Ascii string, NSS loops over these entries in
+ * reverse order, so I will as well. The difference is that NSS
+ * will always place them in a one line string separated by commas,
+ * where I want each entry on a single line. I can't just use a comma
+ * as my delimitter because it is a valid character to have in the
+ * value portion of the AVA and could cause trouble when parsing.
+ */
+ for (rdn = lastRdn; rdn >= rdns; rdn--) {
+ avas = (*rdn)->avas;
+ while ((ava = *avas++) != 0) {
+ if (!get_oid_text (&ava->type, &type))
+ return FALSE;
+
+ /* This function returns a string in UTF8 format. */
+ decodeItem = CERT_DecodeAVAValue (&ava->value);
+ if (!decodeItem) {
+ g_free (type);
+ return FALSE;
+ }
+
+ avavalue = g_string_new_len (
+ (gchar *) decodeItem->data, decodeItem->len);
+
+ SECITEM_FreeItem (decodeItem, PR_TRUE);
+
+ /* Translators: This string is used in Certificate
+ * details for fields like Issuer or Subject, which
+ * shows the field name on the left and its respective
+ * value on the right, both as stored in the
+ * certificate itself. You probably do not need to
+ * change this string, unless changing the order of
+ * name and value. As a result example:
+ * "OU = VeriSign Trust Network" */
+ temp = g_strdup_printf (_("%s = %s"), type, avavalue->str);
+
+ g_string_append (final_string, temp);
+ g_string_append (final_string, "\n");
+ g_string_free (avavalue, TRUE);
+ g_free (temp);
+ g_free (type);
}
- data += len;
+ }
+ *value = g_string_free (final_string, FALSE);
+ return TRUE;
+}
+
+static gboolean
+create_tbs_certificate_asn1_struct (CERTCertificate *cert,
+ EASN1Object **seq)
+{
+ /*
+ ** TBSCertificate ::= SEQUENCE {
+ ** version [0] EXPLICIT Version DEFAULT v1,
+ ** serialNumber CertificateSerialNumber,
+ ** signature AlgorithmIdentifier,
+ ** issuer Name,
+ ** validity Validity,
+ ** subject Name,
+ ** subjectPublicKeyInfo SubjectPublicKeyInfo,
+ ** issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ ** -- If present, version shall be v2 or v3
+ ** subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
+ ** -- If present, version shall be v2 or v3
+ ** extensions [3] EXPLICIT Extensions OPTIONAL
+ ** -- If present, version shall be v3
+ ** }
+ **
+ ** This is the ASN1 structure we should be dealing with at this point.
+ ** The code in this method will assert this is the structure we're dealing
+ ** and then add more user friendly text for that field.
+ */
+ EASN1Object *sequence = e_asn1_object_new ();
+ gchar *text;
+ EASN1Object *subitem;
+ SECItem data;
+
+ e_asn1_object_set_display_name (sequence, _("Certificate"));
+
+ if (!process_version (&cert->version, &subitem))
+ return FALSE;
+ e_asn1_object_append_child (sequence, subitem);
+ g_object_unref (subitem);
+
+ if (!process_serial_number_der (&cert->serialNumber, &subitem))
+ return FALSE;
+ e_asn1_object_append_child (sequence, subitem);
+ g_object_unref (subitem);
+
+ if (!process_sec_algorithm_id (&cert->signature, &subitem))
+ return FALSE;
+ e_asn1_object_set_display_name (subitem, _("Certificate Signature Algorithm"));
+ e_asn1_object_append_child (sequence, subitem);
+ g_object_unref (subitem);
+
+ process_name (&cert->issuer, &text);
+ subitem = e_asn1_object_new ();
+ e_asn1_object_set_display_value (subitem, text);
+ g_free (text);
+
+ e_asn1_object_set_display_name (subitem, _("Issuer"));
+ e_asn1_object_append_child (sequence, subitem);
+ g_object_unref (subitem);
+
+#ifdef notyet
+ nsCOMPtr < nsIASN1Sequence> validitySequence = new nsNSSASN1Sequence ();
+ nssComponent->GetPIPNSSBundleString (NS_LITERAL_STRING ("CertDumpValidity").get (),
+ text);
+ validitySequence->SetDisplayName (text);
+ asn1Objects->AppendElement (validitySequence, PR_FALSE);
+ nssComponent->GetPIPNSSBundleString (NS_LITERAL_STRING ("CertDumpNotBefore").get (),
+ text);
+ nsCOMPtr < nsIX509CertValidity> validityData;
+ GetValidity (getter_AddRefs (validityData));
+ PRTime notBefore, notAfter;
+
+ validityData->GetNotBefore (&notBefore);
+ validityData->GetNotAfter (&notAfter);
+ validityData = 0;
+ rv = ProcessTime (notBefore, text.get (), validitySequence);
+ if (NS_FAILED (rv))
+ return rv;
+
+ nssComponent->GetPIPNSSBundleString (NS_LITERAL_STRING ("CertDumpNotAfter").get (),
+ text);
+ rv = ProcessTime (notAfter, text.get (), validitySequence);
+ if (NS_FAILED (rv))
+ return rv;
+#endif
+
+ subitem = e_asn1_object_new ();
+ e_asn1_object_set_display_name (subitem, _("Subject"));
+
+ process_name (&cert->subject, &text);
+ e_asn1_object_set_display_value (subitem, text);
+ g_free (text);
+ e_asn1_object_append_child (sequence, subitem);
+ g_object_unref (subitem);
+
+ if (!process_subject_public_key_info (&cert->subjectPublicKeyInfo, sequence))
+ return FALSE;
+
+ /* Is there an issuerUniqueID? */
+ if (cert->issuerID.data) {
+ /* The issuerID is encoded as a bit string.
+ * The function ProcessRawBytes expects the
+ * length to be in bytes, so let's convert the
+ * length in a temporary SECItem
+ */
+ data.data = cert->issuerID.data;
+ data.len = cert->issuerID.len / 8;
+
+ subitem = e_asn1_object_new ();
+
+ e_asn1_object_set_display_name (subitem, _("Issuer Unique ID"));
+ process_raw_bytes (&data, &text);
+ e_asn1_object_set_display_value (subitem, text);
+ g_free (text);
- parent->priv->children = g_list_append (parent->priv->children, asn1object);
+ e_asn1_object_append_child (sequence, subitem);
}
+ if (cert->subjectID.data) {
+ /* The subjectID is encoded as a bit string.
+ * The function ProcessRawBytes expects the
+ * length to be in bytes, so let's convert the
+ * length in a temporary SECItem
+ */
+ data.data = cert->issuerID.data;
+ data.len = cert->issuerID.len / 8;
+
+ subitem = e_asn1_object_new ();
+
+ e_asn1_object_set_display_name (subitem, _("Subject Unique ID"));
+ process_raw_bytes (&data, &text);
+ e_asn1_object_set_display_value (subitem, text);
+ g_free (text);
+
+ e_asn1_object_append_child (sequence, subitem);
+ }
+ if (cert->extensions) {
+ if (!process_extensions (cert->extensions, sequence))
+ return FALSE;
+ }
+
+ *seq = sequence;
+
return TRUE;
}
-EASN1Object *
-e_asn1_object_new_from_der (gchar *data,
- guint32 len)
+static gboolean
+fill_asn1_from_cert (EASN1Object *asn1,
+ CERTCertificate *cert)
{
- EASN1Object *obj = g_object_new (E_TYPE_ASN1_OBJECT, NULL);
+ EASN1Object *sequence;
+ SECItem temp;
+ gchar *text;
- if (!build_from_der (obj, data, data + len)) {
- g_object_unref (obj);
- return NULL;
+ g_return_val_if_fail (asn1 != NULL, FALSE);
+ g_return_val_if_fail (cert != NULL, FALSE);
+
+ if (cert->nickname) {
+ e_asn1_object_set_display_name (asn1, cert->nickname);
+ } else {
+ gchar *str;
+
+ str = CERT_GetCommonName (&cert->subject);
+ if (str) {
+ e_asn1_object_set_display_name (asn1, str);
+ PORT_Free (str);
+ } else {
+ e_asn1_object_set_display_name (asn1, cert->subjectName);
+ }
}
- return obj;
+ /* This sequence will be contain the tbsCertificate, signatureAlgorithm,
+ * and signatureValue. */
+
+ if (!create_tbs_certificate_asn1_struct (cert, &sequence))
+ return FALSE;
+ e_asn1_object_append_child (asn1, sequence);
+ g_object_unref (sequence);
+
+ if (!process_sec_algorithm_id (&cert->signatureWrap.signatureAlgorithm, &sequence))
+ return FALSE;
+ e_asn1_object_set_display_name (
+ sequence, _("Certificate Signature Algorithm"));
+ e_asn1_object_append_child (asn1, sequence);
+ g_object_unref (sequence);
+
+ sequence = e_asn1_object_new ();
+ e_asn1_object_set_display_name (
+ sequence, _("Certificate Signature Value"));
+
+ /* The signatureWrap is encoded as a bit string.
+ * The function ProcessRawBytes expects the
+ * length to be in bytes, so let's convert the
+ * length in a temporary SECItem */
+ temp.data = cert->signatureWrap.signature.data;
+ temp.len = cert->signatureWrap.signature.len / 8;
+ process_raw_bytes (&temp, &text);
+ e_asn1_object_set_display_value (sequence, text);
+ e_asn1_object_append_child (asn1, sequence);
+ g_free (text);
+
+ return TRUE;
+}
+
+static void
+e_asn1_object_finalize (GObject *object)
+{
+ EASN1ObjectPrivate *priv;
+
+ priv = E_ASN1_OBJECT_GET_PRIVATE (object);
+
+ g_free (priv->display_name);
+ g_free (priv->value);
+
+ g_list_free_full (priv->children, (GDestroyNotify) g_object_unref);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_asn1_object_parent_class)->finalize (object);
+}
+
+static void
+e_asn1_object_class_init (EASN1ObjectClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (EASN1ObjectPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = e_asn1_object_finalize;
+}
+
+static void
+e_asn1_object_init (EASN1Object *asn1)
+{
+ asn1->priv = E_ASN1_OBJECT_GET_PRIVATE (asn1);
+
+ asn1->priv->valid_container = TRUE;
}
EASN1Object *
@@ -289,6 +867,22 @@ e_asn1_object_new (void)
return E_ASN1_OBJECT (g_object_new (E_TYPE_ASN1_OBJECT, NULL));
}
+EASN1Object *
+e_asn1_object_new_from_cert (CERTCertificate *cert)
+{
+ EASN1Object *asn1;
+
+ g_return_val_if_fail (cert != NULL, NULL);
+
+ asn1 = e_asn1_object_new ();
+ if (!fill_asn1_from_cert (asn1, cert)) {
+ g_object_unref (asn1);
+ return NULL;
+ }
+
+ return asn1;
+}
+
void
e_asn1_object_set_valid_container (EASN1Object *obj,
gboolean flag)
diff --git a/smime/lib/e-asn1-object.h b/smime/lib/e-asn1-object.h
index 35824967d4..39b79a7b1e 100644
--- a/smime/lib/e-asn1-object.h
+++ b/smime/lib/e-asn1-object.h
@@ -1,5 +1,4 @@
/*
- *
* 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
@@ -18,15 +17,14 @@
* Chris Toshok <toshok@ximian.com>
*
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
*/
-#ifndef _E_ASN1_OBJECT_H_
-#define _E_ASN1_OBJECT_H_
+#ifndef E_ASN1_OBJECT_H
+#define E_ASN1_OBJECT_H
#include <glib-object.h>
-#include <nspr.h>
+#include <cert.h>
#define E_TYPE_ASN1_OBJECT (e_asn1_object_get_type ())
#define E_ASN1_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_ASN1_OBJECT, EASN1Object))
@@ -85,22 +83,27 @@ struct _EASN1ObjectClass {
void (*_ecert_reserved4) (void);
};
-EASN1Object *e_asn1_object_new_from_der (gchar *data, guint32 len);
-EASN1Object *e_asn1_object_new (void);
-
-void e_asn1_object_set_valid_container (EASN1Object *obj, gboolean flag);
-gboolean e_asn1_object_is_valid_container (EASN1Object *obj);
-PRUint32 e_asn1_object_get_asn1_type (EASN1Object *obj);
-PRUint32 e_asn1_object_get_asn1_tag (EASN1Object *obj);
-GList *e_asn1_object_get_children (EASN1Object *obj);
-void e_asn1_object_append_child (EASN1Object *parent, EASN1Object *child);
-void e_asn1_object_set_display_name (EASN1Object *obj, const gchar *name);
-const gchar *e_asn1_object_get_display_name (EASN1Object *obj);
-void e_asn1_object_set_display_value (EASN1Object *obj, const gchar *value);
-const gchar *e_asn1_object_get_display_value (EASN1Object *obj);
+GType e_asn1_object_get_type (void);
+EASN1Object * e_asn1_object_new (void);
+EASN1Object * e_asn1_object_new_from_cert (CERTCertificate *cert);
-void e_asn1_object_get_data (EASN1Object *obj, gchar **data, guint32 *len);
+void e_asn1_object_set_valid_container (EASN1Object *obj,
+ gboolean flag);
+gboolean e_asn1_object_is_valid_container (EASN1Object *obj);
+PRUint32 e_asn1_object_get_asn1_type (EASN1Object *obj);
+PRUint32 e_asn1_object_get_asn1_tag (EASN1Object *obj);
+GList * e_asn1_object_get_children (EASN1Object *obj);
+void e_asn1_object_append_child (EASN1Object *parent,
+ EASN1Object *child);
+void e_asn1_object_set_display_name (EASN1Object *obj,
+ const gchar *name);
+const gchar * e_asn1_object_get_display_name (EASN1Object *obj);
+void e_asn1_object_set_display_value (EASN1Object *obj,
+ const gchar *value);
+const gchar * e_asn1_object_get_display_value (EASN1Object *obj);
-GType e_asn1_object_get_type (void);
+void e_asn1_object_get_data (EASN1Object *obj,
+ gchar **data,
+ guint32 *len);
-#endif /* _E_ASN1_OBJECT_H_ */
+#endif /* E_ASN1_OBJECT_H */
diff --git a/smime/lib/e-cert.c b/smime/lib/e-cert.c
index cd92062779..969b43c9ed 100644
--- a/smime/lib/e-cert.c
+++ b/smime/lib/e-cert.c
@@ -435,18 +435,14 @@ e_cert_get_md5_fingerprint (ECert *cert)
}
GList *
-e_cert_get_chain (ECert *ecert)
+e_cert_get_issuers_chain (ECert *ecert)
{
- GList *l = NULL;
-
- g_object_ref (ecert);
+ GList *issuers = NULL;
while (ecert) {
CERTCertificate *cert = e_cert_get_internal_cert (ecert);
CERTCertificate *next_cert;
- l = g_list_append (l, ecert);
-
if (SECITEM_CompareItem (&cert->derIssuer, &cert->derSubject) == SECEqual)
break;
@@ -456,9 +452,14 @@ e_cert_get_chain (ECert *ecert)
/* next_cert has a reference already */
ecert = e_cert_new (next_cert);
+
+ if (ecert) {
+ /* the first is issuer of the original ecert */
+ issuers = g_list_append (issuers, ecert);
+ }
}
- return l;
+ return issuers;
}
ECert *
@@ -482,760 +483,16 @@ e_cert_get_ca_cert (ECert *ecert)
return e_cert_new (cert);
}
-static gboolean
-get_int_value (SECItem *versionItem,
- gulong *version)
-{
- SECStatus srv;
- srv = SEC_ASN1DecodeInteger (versionItem,version);
- if (srv != SECSuccess) {
- g_warning ("could not decode version of cert");
- return FALSE;
- }
- return TRUE;
-}
-
-static gboolean
-process_version (SECItem *versionItem,
- EASN1Object **retItem)
-{
- EASN1Object *item = e_asn1_object_new ();
- gulong version;
-
- e_asn1_object_set_display_name (item, _("Version"));
-
- /* Now to figure out what version this certificate is. */
-
- if (versionItem->data) {
- if (!get_int_value (versionItem, &version))
- return FALSE;
- } else {
- /* If there is no version present in the cert, then rfc2459
- * says we default to v1 (0) */
- version = 0;
- }
-
- switch (version) {
- case 0:
- e_asn1_object_set_display_value (item, _("Version 1"));
- break;
- case 1:
- e_asn1_object_set_display_value (item, _("Version 2"));
- break;
- case 2:
- e_asn1_object_set_display_value (item, _("Version 3"));
- break;
- default:
- g_warning ("Bad value for cert version");
- return FALSE;
- }
-
- *retItem = item;
- return TRUE;
-}
-
-static gboolean
-process_serial_number_der (SECItem *serialItem,
- EASN1Object **retItem)
-{
- gchar *serialNumber;
- EASN1Object *item = e_asn1_object_new ();
-
- e_asn1_object_set_display_name (item, _("Serial Number"));
-
- serialNumber = CERT_Hexify (serialItem, 1);
-
- e_asn1_object_set_display_value (item, serialNumber);
- PORT_Free (serialNumber); /* XXX the right free to use? */
-
- *retItem = item;
- return TRUE;
-}
-
-static gboolean
-get_default_oid_format (SECItem *oid,
- gchar **text)
-{
- gchar buf[300];
- guint len;
- gint written;
-
- gulong val = oid->data[0];
- guint i = val % 40;
- val /= 40;
- written = PR_snprintf (buf, 300, "%lu %u ", val, i);
- if (written < 0)
- return FALSE;
- len = written;
-
- val = 0;
- for (i = 1; i < oid->len; ++i) {
- /* In this loop, we have to parse a DER formatted
- * If the first bit is a 1, then the integer is
- * represented by more than one byte. If the
- * first bit is set then we continue on and add
- * the values of the later bytes until we get
- * a byte without the first bit set.
- */
- gulong j;
-
- j = oid->data[i];
- val = (val << 7) | (j & 0x7f);
- if (j & 0x80)
- continue;
- written = PR_snprintf (&buf[len], sizeof (buf) - len, "%lu ", val);
- if (written < 0)
- return FALSE;
-
- len += written;
- if (len >= sizeof (buf))
- g_warning ("OID data to big to display in 300 chars.");
- val = 0;
- }
-
- *text = g_strdup (buf);
- return TRUE;
-}
-
-static gboolean
-get_oid_text (SECItem *oid,
- gchar **text)
-{
- SECOidTag oidTag = SECOID_FindOIDTag (oid);
- gchar *temp;
-
- switch (oidTag) {
- case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
- *text = g_strdup (_("PKCS #1 MD2 With RSA Encryption"));
- break;
- case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
- *text = g_strdup (_("PKCS #1 MD5 With RSA Encryption"));
- break;
- case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
- *text = g_strdup (_("PKCS #1 SHA-1 With RSA Encryption"));
- break;
- case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
- *text = g_strdup (_("PKCS #1 SHA-256 With RSA Encryption"));
- break;
- case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
- *text = g_strdup (_("PKCS #1 SHA-384 With RSA Encryption"));
- break;
- case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
- *text = g_strdup (_("PKCS #1 SHA-512 With RSA Encryption"));
- break;
- case SEC_OID_AVA_COUNTRY_NAME:
- *text = g_strdup ("C");
- break;
- case SEC_OID_AVA_COMMON_NAME:
- *text = g_strdup ("CN");
- break;
- case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
- *text = g_strdup ("OU");
- break;
- case SEC_OID_AVA_ORGANIZATION_NAME:
- *text = g_strdup ("O");
- break;
- case SEC_OID_AVA_LOCALITY:
- *text = g_strdup ("L");
- break;
- case SEC_OID_AVA_DN_QUALIFIER:
- *text = g_strdup ("DN");
- break;
- case SEC_OID_AVA_DC:
- *text = g_strdup ("DC");
- break;
- case SEC_OID_AVA_STATE_OR_PROVINCE:
- *text = g_strdup ("ST");
- break;
- case SEC_OID_PKCS1_RSA_ENCRYPTION:
- *text = g_strdup (_("PKCS #1 RSA Encryption"));
- break;
- case SEC_OID_X509_KEY_USAGE:
- *text = g_strdup (_("Certificate Key Usage"));
- break;
- case SEC_OID_NS_CERT_EXT_CERT_TYPE:
- *text = g_strdup (_("Netscape Certificate Type"));
- break;
- case SEC_OID_X509_AUTH_KEY_ID:
- *text = g_strdup (_("Certificate Authority Key Identifier"));
- break;
- case SEC_OID_RFC1274_UID:
- *text = g_strdup ("UID");
- break;
- case SEC_OID_PKCS9_EMAIL_ADDRESS:
- *text = g_strdup ("E");
- break;
- default:
- if (!get_default_oid_format (oid, &temp))
- return FALSE;
-
- *text = g_strdup_printf (_("Object Identifier (%s)"), temp);
- g_free (temp);
-
- break;
- }
- return TRUE;
-}
-
-static gboolean
-process_raw_bytes (SECItem *data,
- gchar **text)
-{
- /* This function is used to display some DER bytes
- * that we have not added support for decoding.
- * It prints the value of the byte out into a
- * string that can later be displayed as a byte
- * string. We place a new line after 24 bytes
- * to break up extermaly long sequence of bytes.
- */
- GString *str = g_string_new ("");
- PRUint32 i;
- gchar buffer[5];
- for (i = 0; i < data->len; i++) {
- PR_snprintf (buffer, 5, "%02x ", data->data[i]);
- g_string_append (str, buffer);
- if ((i + 1) % 16 == 0) {
- g_string_append (str, "\n");
- }
- }
- *text = g_string_free (str, FALSE);
- return TRUE;
-}
-
-static gboolean
-process_sec_algorithm_id (SECAlgorithmID *algID,
- EASN1Object **retSequence)
-{
- EASN1Object *sequence = e_asn1_object_new ();
- gchar *text;
-
- *retSequence = NULL;
-
- get_oid_text (&algID->algorithm, &text);
-
- if (!algID->parameters.len ||
- algID->parameters.data[0] == E_ASN1_OBJECT_TYPE_NULL) {
- e_asn1_object_set_display_value (sequence, text);
- e_asn1_object_set_valid_container (sequence, FALSE);
- } else {
- EASN1Object *subitem;
-
- subitem = e_asn1_object_new ();
- e_asn1_object_set_display_name (subitem, _("Algorithm Identifier"));
- e_asn1_object_set_display_value (subitem, text);
- e_asn1_object_append_child (sequence, subitem);
- g_object_unref (subitem);
-
- g_free (text);
-
- subitem = e_asn1_object_new ();
- e_asn1_object_set_display_name (subitem, _("Algorithm Parameters"));
- process_raw_bytes (&algID->parameters, &text);
- e_asn1_object_set_display_value (subitem, text);
- e_asn1_object_append_child (sequence, subitem);
- g_object_unref (subitem);
- }
-
- g_free (text);
- *retSequence = sequence;
- return TRUE;
-}
-
-static gboolean
-process_subject_public_key_info (CERTSubjectPublicKeyInfo *spki,
- EASN1Object *parentSequence)
-{
- EASN1Object *spkiSequence = e_asn1_object_new ();
- EASN1Object *sequenceItem;
- EASN1Object *printableItem;
- SECItem data;
- gchar *text;
-
- e_asn1_object_set_display_name (spkiSequence, _("Subject Public Key Info"));
-
- if (!process_sec_algorithm_id (&spki->algorithm, &sequenceItem))
- return FALSE;
-
- e_asn1_object_set_display_name (sequenceItem, _("Subject Public Key Algorithm"));
-
- e_asn1_object_append_child (spkiSequence, sequenceItem);
-
- /* The subjectPublicKey field is encoded as a bit string.
- * ProcessRawBytes expects the lenght to be in bytes, so
- * let's convert the lenght into a temporary SECItem.
- */
- data.data = spki->subjectPublicKey.data;
- data.len = spki->subjectPublicKey.len / 8;
-
- process_raw_bytes (&data, &text);
- printableItem = e_asn1_object_new ();
-
- e_asn1_object_set_display_value (printableItem, text);
- e_asn1_object_set_display_name (printableItem, _("Subject's Public Key"));
- e_asn1_object_append_child (spkiSequence, printableItem);
- g_object_unref (printableItem);
-
- e_asn1_object_append_child (parentSequence, spkiSequence);
- g_object_unref (spkiSequence);
-
- return TRUE;
-}
-
-static gboolean
-process_ns_cert_type_extensions (SECItem *extData,
- GString *text)
-{
- SECItem decoded;
- guchar nsCertType;
-
- decoded.data = NULL;
- decoded.len = 0;
- if (SECSuccess != SEC_ASN1DecodeItem (NULL, &decoded,
- SEC_ASN1_GET (SEC_BitStringTemplate), extData)) {
- g_string_append (text, _("Error: Unable to process extension"));
- return TRUE;
- }
-
- nsCertType = decoded.data[0];
-
- PORT_Free (decoded.data); /* XXX right free? */
-
- if (nsCertType & NS_CERT_TYPE_SSL_CLIENT) {
- g_string_append (text, _("SSL Client Certificate"));
- g_string_append (text, "\n");
- }
- if (nsCertType & NS_CERT_TYPE_SSL_SERVER) {
- g_string_append (text, _("SSL Server Certificate"));
- g_string_append (text, "\n");
- }
- if (nsCertType & NS_CERT_TYPE_EMAIL) {
- g_string_append (text, _("Email"));
- g_string_append (text, "\n");
- }
- if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING) {
- g_string_append (text, _("Object Signer"));
- g_string_append (text, "\n");
- }
- if (nsCertType & NS_CERT_TYPE_SSL_CA) {
- g_string_append (text, _("SSL Certificate Authority"));
- g_string_append (text, "\n");
- }
- if (nsCertType & NS_CERT_TYPE_EMAIL_CA) {
- g_string_append (text, _("Email Certificate Authority"));
- g_string_append (text, "\n");
- }
- if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING_CA) {
- g_string_append (text, _("Object Signer"));
- g_string_append (text, "\n");
- }
- return TRUE;
-}
-
-static gboolean
-process_key_usage_extensions (SECItem *extData,
- GString *text)
-{
- SECItem decoded;
- guchar keyUsage;
-
- decoded.data = NULL;
- decoded.len = 0;
- if (SECSuccess != SEC_ASN1DecodeItem (NULL, &decoded,
- SEC_ASN1_GET (SEC_BitStringTemplate), extData)) {
- g_string_append (text, _("Error: Unable to process extension"));
- return TRUE;
- }
-
- keyUsage = decoded.data[0];
- PORT_Free (decoded.data); /* XXX right free? */
-
- if (keyUsage & KU_DIGITAL_SIGNATURE) {
- g_string_append (text, _("Signing"));
- g_string_append (text, "\n");
- }
- if (keyUsage & KU_NON_REPUDIATION) {
- g_string_append (text, _("Non-repudiation"));
- g_string_append (text, "\n");
- }
- if (keyUsage & KU_KEY_ENCIPHERMENT) {
- g_string_append (text, _("Key Encipherment"));
- g_string_append (text, "\n");
- }
- if (keyUsage & KU_DATA_ENCIPHERMENT) {
- g_string_append (text, _("Data Encipherment"));
- g_string_append (text, "\n");
- }
- if (keyUsage & KU_KEY_AGREEMENT) {
- g_string_append (text, _("Key Agreement"));
- g_string_append (text, "\n");
- }
- if (keyUsage & KU_KEY_CERT_SIGN) {
- g_string_append (text, _("Certificate Signer"));
- g_string_append (text, "\n");
- }
- if (keyUsage & KU_CRL_SIGN) {
- g_string_append (text, _("CRL Signer"));
- g_string_append (text, "\n");
- }
-
- return TRUE;
-}
-
-static gboolean
-process_extension_data (SECOidTag oidTag,
- SECItem *extData,
- GString *str)
-{
- gboolean rv;
- switch (oidTag) {
- case SEC_OID_NS_CERT_EXT_CERT_TYPE:
- rv = process_ns_cert_type_extensions (extData, str);
- break;
- case SEC_OID_X509_KEY_USAGE:
- rv = process_key_usage_extensions (extData, str);
- break;
- default: {
- gchar *text;
- rv = process_raw_bytes (extData, &text);
- g_string_append (str, text);
- g_free (text);
- break;
- }
- }
- return rv;
-}
-
-static gboolean
-process_single_extension (CERTCertExtension *extension,
- EASN1Object **retExtension)
-{
- GString *str = g_string_new ("");
- gchar *text;
- EASN1Object *extensionItem;
- SECOidTag oidTag = SECOID_FindOIDTag (&extension->id);
-
- get_oid_text (&extension->id, &text);
-
- extensionItem = e_asn1_object_new ();
-
- e_asn1_object_set_display_name (extensionItem, text);
- g_free (text);
-
- if (extension->critical.data != NULL) {
- if (extension->critical.data[0]) {
- g_string_append (str, _("Critical"));
- } else {
- g_string_append (str, _("Not Critical"));
- }
- } else {
- g_string_append (str, _("Not Critical"));
- }
- g_string_append (str, "\n");
- if (!process_extension_data (oidTag, &extension->value, str)) {
- g_string_free (str, TRUE);
- return FALSE;
- }
-
- e_asn1_object_set_display_value (extensionItem, str->str);
- g_string_free (str, TRUE);
- *retExtension = extensionItem;
- return TRUE;
-}
-
-static gboolean
-process_extensions (CERTCertExtension **extensions,
- EASN1Object *parentSequence)
-{
- EASN1Object *extensionSequence = e_asn1_object_new ();
- PRInt32 i;
-
- e_asn1_object_set_display_name (extensionSequence, _("Extensions"));
-
- for (i = 0; extensions[i] != NULL; i++) {
- EASN1Object *newExtension;
-
- if (!process_single_extension (extensions[i],
- &newExtension))
- return FALSE;
-
- e_asn1_object_append_child (extensionSequence, newExtension);
- }
- e_asn1_object_append_child (parentSequence, extensionSequence);
- return TRUE;
-}
-
-static gboolean
-process_name (CERTName *name,
- gchar **value)
-{
- CERTRDN ** rdns;
- CERTRDN ** rdn;
- CERTAVA ** avas;
- CERTAVA * ava;
- SECItem *decodeItem = NULL;
- GString *final_string = g_string_new ("");
-
- gchar *type;
- GString *avavalue;
- gchar *temp;
- CERTRDN **lastRdn;
-
- rdns = name->rdns;
-
- /* find last RDN */
- lastRdn = rdns;
- while (*lastRdn) lastRdn++;
-
- /* The above whille loop will put us at the last member
- * of the array which is a NULL pointer. So let's back
- * up one spot so that we have the last non-NULL entry in
- * the array in preparation for traversing the
- * RDN's (Relative Distinguished Name) in reverse order.
- */
- lastRdn--;
-
- /*
- * Loop over name contents in _reverse_ RDN order appending to string
- * When building the Ascii string, NSS loops over these entries in
- * reverse order, so I will as well. The difference is that NSS
- * will always place them in a one line string separated by commas,
- * where I want each entry on a single line. I can't just use a comma
- * as my delimitter because it is a valid character to have in the
- * value portion of the AVA and could cause trouble when parsing.
- */
- for (rdn = lastRdn; rdn >= rdns; rdn--) {
- avas = (*rdn)->avas;
- while ((ava = *avas++) != 0) {
- if (!get_oid_text (&ava->type, &type))
- return FALSE;
-
- /* This function returns a string in UTF8 format. */
- decodeItem = CERT_DecodeAVAValue (&ava->value);
- if (!decodeItem) {
- return FALSE;
- }
-
- avavalue = g_string_new_len (
- (gchar *) decodeItem->data, decodeItem->len);
-
- SECITEM_FreeItem (decodeItem, PR_TRUE);
-
- /* Translators: This string is used in Certificate
- * details for fields like Issuer or Subject, which
- * shows the field name on the left and its respective
- * value on the right, both as stored in the
- * certificate itself. You probably do not need to
- * change this string, unless changing the order of
- * name and value. As a result example:
- * "OU = VeriSign Trust Network" */
- temp = g_strdup_printf (_("%s = %s"), type, avavalue->str);
-
- g_string_append (final_string, temp);
- g_string_append (final_string, "\n");
- g_string_free (avavalue, TRUE);
- g_free (temp);
- }
- }
- *value = g_string_free (final_string, FALSE);
- return TRUE;
-}
-
-static gboolean
-create_tbs_certificate_asn1_struct (ECert *cert,
- EASN1Object **seq)
-{
- /*
- ** TBSCertificate ::= SEQUENCE {
- ** version [0] EXPLICIT Version DEFAULT v1,
- ** serialNumber CertificateSerialNumber,
- ** signature AlgorithmIdentifier,
- ** issuer Name,
- ** validity Validity,
- ** subject Name,
- ** subjectPublicKeyInfo SubjectPublicKeyInfo,
- ** issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
- ** -- If present, version shall be v2 or v3
- ** subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
- ** -- If present, version shall be v2 or v3
- ** extensions [3] EXPLICIT Extensions OPTIONAL
- ** -- If present, version shall be v3
- ** }
- **
- ** This is the ASN1 structure we should be dealing with at this point.
- ** The code in this method will assert this is the structure we're dealing
- ** and then add more user friendly text for that field.
- */
- EASN1Object *sequence = e_asn1_object_new ();
- gchar *text;
- EASN1Object *subitem;
- SECItem data;
-
- e_asn1_object_set_display_name (sequence, _("Certificate"));
-
- if (!process_version (&cert->priv->cert->version, &subitem))
- return FALSE;
- e_asn1_object_append_child (sequence, subitem);
- g_object_unref (subitem);
-
- if (!process_serial_number_der (&cert->priv->cert->serialNumber, &subitem))
- return FALSE;
- e_asn1_object_append_child (sequence, subitem);
- g_object_unref (subitem);
-
- if (!process_sec_algorithm_id (&cert->priv->cert->signature, &subitem))
- return FALSE;
- e_asn1_object_set_display_name (subitem, _("Certificate Signature Algorithm"));
- e_asn1_object_append_child (sequence, subitem);
- g_object_unref (subitem);
-
- process_name (&cert->priv->cert->issuer, &text);
- subitem = e_asn1_object_new ();
- e_asn1_object_set_display_value (subitem, text);
- g_free (text);
-
- e_asn1_object_set_display_name (subitem, _("Issuer"));
- e_asn1_object_append_child (sequence, subitem);
- g_object_unref (subitem);
-
-#ifdef notyet
- nsCOMPtr < nsIASN1Sequence> validitySequence = new nsNSSASN1Sequence ();
- nssComponent->GetPIPNSSBundleString (NS_LITERAL_STRING ("CertDumpValidity").get (),
- text);
- validitySequence->SetDisplayName (text);
- asn1Objects->AppendElement (validitySequence, PR_FALSE);
- nssComponent->GetPIPNSSBundleString (NS_LITERAL_STRING ("CertDumpNotBefore").get (),
- text);
- nsCOMPtr < nsIX509CertValidity> validityData;
- GetValidity (getter_AddRefs (validityData));
- PRTime notBefore, notAfter;
-
- validityData->GetNotBefore (&notBefore);
- validityData->GetNotAfter (&notAfter);
- validityData = 0;
- rv = ProcessTime (notBefore, text.get (), validitySequence);
- if (NS_FAILED (rv))
- return rv;
-
- nssComponent->GetPIPNSSBundleString (NS_LITERAL_STRING ("CertDumpNotAfter").get (),
- text);
- rv = ProcessTime (notAfter, text.get (), validitySequence);
- if (NS_FAILED (rv))
- return rv;
-#endif
-
- subitem = e_asn1_object_new ();
- e_asn1_object_set_display_name (subitem, _("Subject"));
-
- process_name (&cert->priv->cert->subject, &text);
- e_asn1_object_set_display_value (subitem, text);
- g_free (text);
- e_asn1_object_append_child (sequence, subitem);
- g_object_unref (subitem);
-
- if (!process_subject_public_key_info (
- &cert->priv->cert->subjectPublicKeyInfo, sequence))
- return FALSE;
-
- /* Is there an issuerUniqueID? */
- if (cert->priv->cert->issuerID.data) {
- /* The issuerID is encoded as a bit string.
- * The function ProcessRawBytes expects the
- * length to be in bytes, so let's convert the
- * length in a temporary SECItem
- */
- data.data = cert->priv->cert->issuerID.data;
- data.len = cert->priv->cert->issuerID.len / 8;
-
- subitem = e_asn1_object_new ();
-
- e_asn1_object_set_display_name (subitem, _("Issuer Unique ID"));
- process_raw_bytes (&data, &text);
- e_asn1_object_set_display_value (subitem, text);
- g_free (text);
-
- e_asn1_object_append_child (sequence, subitem);
- }
-
- if (cert->priv->cert->subjectID.data) {
- /* The subjectID is encoded as a bit string.
- * The function ProcessRawBytes expects the
- * length to be in bytes, so let's convert the
- * length in a temporary SECItem
- */
- data.data = cert->priv->cert->issuerID.data;
- data.len = cert->priv->cert->issuerID.len / 8;
-
- subitem = e_asn1_object_new ();
-
- e_asn1_object_set_display_name (subitem, _("Subject Unique ID"));
- process_raw_bytes (&data, &text);
- e_asn1_object_set_display_value (subitem, text);
- g_free (text);
-
- e_asn1_object_append_child (sequence, subitem);
- }
- if (cert->priv->cert->extensions) {
- if (!process_extensions (cert->priv->cert->extensions, sequence))
- return FALSE;
- }
-
- *seq = sequence;
-
- return TRUE;
-}
-
-static gboolean
-create_asn1_struct (ECert *cert)
-{
- EASN1Object *sequence;
- SECItem temp;
- gchar *text;
-
- cert->priv->asn1 = e_asn1_object_new ();
-
- e_asn1_object_set_display_name (cert->priv->asn1, e_cert_get_window_title (cert));
-
- /* This sequence will be contain the tbsCertificate, signatureAlgorithm,
- * and signatureValue. */
-
- if (!create_tbs_certificate_asn1_struct (cert, &sequence))
- return FALSE;
- e_asn1_object_append_child (cert->priv->asn1, sequence);
- g_object_unref (sequence);
-
- if (!process_sec_algorithm_id (
- &cert->priv->cert->signatureWrap.signatureAlgorithm, &sequence))
- return FALSE;
- e_asn1_object_set_display_name (
- sequence, _("Certificate Signature Algorithm"));
- e_asn1_object_append_child (cert->priv->asn1, sequence);
- g_object_unref (sequence);
-
- sequence = e_asn1_object_new ();
- e_asn1_object_set_display_name (
- sequence, _("Certificate Signature Value"));
-
- /* The signatureWrap is encoded as a bit string.
- * The function ProcessRawBytes expects the
- * length to be in bytes, so let's convert the
- * length in a temporary SECItem */
- temp.data = cert->priv->cert->signatureWrap.signature.data;
- temp.len = cert->priv->cert->signatureWrap.signature.len / 8;
- process_raw_bytes (&temp, &text);
- e_asn1_object_set_display_value (sequence, text);
- e_asn1_object_append_child (cert->priv->asn1, sequence);
- g_free (text);
-
- return TRUE;
-}
-
EASN1Object *
e_cert_get_asn1_struct (ECert *cert)
{
if (!cert->priv->asn1)
- create_asn1_struct (cert);
+ cert->priv->asn1 = e_asn1_object_new_from_cert (cert->priv->cert);
+
+ if (cert->priv->asn1)
+ return g_object_ref (cert->priv->asn1);
- return g_object_ref (cert->priv->asn1);
+ return NULL;
}
gboolean
diff --git a/smime/lib/e-cert.h b/smime/lib/e-cert.h
index 4159c40cb9..0096336741 100644
--- a/smime/lib/e-cert.h
+++ b/smime/lib/e-cert.h
@@ -95,7 +95,7 @@ const gchar * e_cert_get_serial_number (ECert *cert);
const gchar * e_cert_get_sha1_fingerprint (ECert *cert);
const gchar * e_cert_get_md5_fingerprint (ECert *cert);
-GList * e_cert_get_chain (ECert *cert);
+GList * e_cert_get_issuers_chain (ECert *cert);
ECert * e_cert_get_ca_cert (ECert *ecert);
EASN1Object * e_cert_get_asn1_struct (ECert *cert);