aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Toshok <toshok@ximian.com>2003-12-04 04:48:05 +0800
committerChris Toshok <toshok@src.gnome.org>2003-12-04 04:48:05 +0800
commit2831ada5a5554a4a3c1920d73b43343d618f0e02 (patch)
tree718b56037a2e87c36f6c1fa9c9cdb8a62cf825d3
parentd5cf06d5c681e540a545ccc11dfb9f1413ee02d6 (diff)
downloadgsoc2013-evolution-2831ada5a5554a4a3c1920d73b43343d618f0e02.tar.gz
gsoc2013-evolution-2831ada5a5554a4a3c1920d73b43343d618f0e02.tar.zst
gsoc2013-evolution-2831ada5a5554a4a3c1920d73b43343d618f0e02.zip
add e-asn1-object.[ch]
2003-12-03 Chris Toshok <toshok@ximian.com> * lib/Makefile.am (libessmime_la_SOURCES): add e-asn1-object.[ch] * gui/smime-ui.glade: rename the ca trust dialog, and give it a proper id. * gui/certificate-manager.c (yourcerts_selection_changed): just use @selection. (contactcerts_selection_changed): same. (authoritycerts_selection_changed): same. * gui/certificate-viewer.c (free_data): free the cert chain. (fill_in_general): move all the general tab stuff here. (hierarchy_selection_changed): new function. not finished. (fields_selection_changed): new function, unimplemented. (fill_in_details): new function, fill in the heirarchy and hook up signals and stuff. (certificate_viewer_show): call fill_in_general/fill_in_details. * lib/e-cert.c (e_cert_get_chain): new function. * lib/e-cert.h: add prototype for e_cert_get_chain. svn path=/trunk/; revision=23622
-rw-r--r--smime/ChangeLog24
-rw-r--r--smime/gui/certificate-manager.c6
-rw-r--r--smime/gui/certificate-viewer.c127
-rw-r--r--smime/gui/smime-ui.glade4
-rw-r--r--smime/lib/Makefile.am2
-rw-r--r--smime/lib/e-asn1-object.c369
-rw-r--r--smime/lib/e-asn1-object.h81
-rw-r--r--smime/lib/e-cert.c25
-rw-r--r--smime/lib/e-cert.h2
9 files changed, 623 insertions, 17 deletions
diff --git a/smime/ChangeLog b/smime/ChangeLog
index 243ad27657..7794f799f6 100644
--- a/smime/ChangeLog
+++ b/smime/ChangeLog
@@ -1,5 +1,29 @@
2003-12-03 Chris Toshok <toshok@ximian.com>
+ * lib/Makefile.am (libessmime_la_SOURCES): add e-asn1-object.[ch]
+
+ * gui/smime-ui.glade: rename the ca trust dialog, and give it a
+ proper id.
+
+ * gui/certificate-manager.c (yourcerts_selection_changed): just
+ use @selection.
+ (contactcerts_selection_changed): same.
+ (authoritycerts_selection_changed): same.
+
+ * gui/certificate-viewer.c (free_data): free the cert chain.
+ (fill_in_general): move all the general tab stuff here.
+ (hierarchy_selection_changed): new function. not finished.
+ (fields_selection_changed): new function, unimplemented.
+ (fill_in_details): new function, fill in the heirarchy and hook up
+ signals and stuff.
+ (certificate_viewer_show): call fill_in_general/fill_in_details.
+
+ * lib/e-cert.c (e_cert_get_chain): new function.
+
+ * lib/e-cert.h: add prototype for e_cert_get_chain.
+
+2003-12-03 Chris Toshok <toshok@ximian.com>
+
* lib/e-cert-db.c (e_cert_db_class_init): grovel around at startup
time for mozilla's pkcs11 module so we can get the same default
set of root certs.
diff --git a/smime/gui/certificate-manager.c b/smime/gui/certificate-manager.c
index 41caa775a5..d2ae5e4fea 100644
--- a/smime/gui/certificate-manager.c
+++ b/smime/gui/certificate-manager.c
@@ -139,7 +139,7 @@ import_your (GtkWidget *widget, CertificateManagerData *cfm)
static void
yourcerts_selection_changed (GtkTreeSelection *selection, CertificateManagerData *cfm)
{
- handle_selection_changed (gtk_tree_view_get_selection (GTK_TREE_VIEW(cfm->yourcerts_treeview)),
+ handle_selection_changed (selection,
4,
cfm->view_your_button,
cfm->backup_your_button, /* yes yes, not really "edit", it's a hack :) */
@@ -290,7 +290,7 @@ delete_contact (GtkWidget *widget, CertificateManagerData *cfm)
static void
contactcerts_selection_changed (GtkTreeSelection *selection, CertificateManagerData *cfm)
{
- handle_selection_changed (gtk_tree_view_get_selection (GTK_TREE_VIEW(cfm->contactcerts_treeview)),
+ handle_selection_changed (selection,
3,
cfm->view_contact_button,
cfm->edit_contact_button,
@@ -447,7 +447,7 @@ delete_ca (GtkWidget *widget, CertificateManagerData *cfm)
static void
authoritycerts_selection_changed (GtkTreeSelection *selection, CertificateManagerData *cfm)
{
- handle_selection_changed (gtk_tree_view_get_selection (GTK_TREE_VIEW(cfm->authoritycerts_treeview)),
+ handle_selection_changed (selection,
1,
cfm->view_ca_button,
cfm->edit_ca_button,
diff --git a/smime/gui/certificate-viewer.c b/smime/gui/certificate-viewer.c
index 4a0bc3327d..9314ac5c1e 100644
--- a/smime/gui/certificate-viewer.c
+++ b/smime/gui/certificate-viewer.c
@@ -22,6 +22,8 @@
#include "certificate-viewer.h"
+#include "e-asn1-object.h"
+
#include <gtk/gtk.h>
#include <libgnome/gnome-i18n.h>
@@ -32,6 +34,11 @@
typedef struct {
GladeXML *gui;
GtkWidget *dialog;
+ GtkTreeStore *hierarchy_store, *fields_store;
+ GtkWidget *hierarchy_tree, *fields_tree;
+ GtkWidget *field_text;
+
+ GList *cert_chain;
} CertificateViewerData;
static void
@@ -39,26 +46,20 @@ free_data (gpointer data, GObject *where_the_object_was)
{
CertificateViewerData *cvm = data;
+ g_list_foreach (cvm->cert_chain, (GFunc)g_object_unref, NULL);
+ g_list_free (cvm->cert_chain);
+
g_object_unref (cvm->gui);
g_free (cvm);
}
-
-GtkWidget*
-certificate_viewer_show (ECert *cert)
+static void
+fill_in_general (CertificateViewerData *cvm_data, ECert *cert)
{
- CertificateViewerData *cvm_data;
- CERTCertificate *mcert;
+ CERTCertificate *mcert = e_cert_get_internal_cert (cert);
GtkWidget *label;
const char *text;
- mcert = e_cert_get_internal_cert (cert);
-
- cvm_data = g_new0 (CertificateViewerData, 1);
- cvm_data->gui = glade_xml_new (EVOLUTION_GLADEDIR "/" GLADE_FILE_NAME, NULL, NULL);
-
- cvm_data->dialog = glade_xml_get_widget (cvm_data->gui, "certificate-viewer-dialog");
-
/* issued to */
if (e_cert_get_cn (cert)) {
label = glade_xml_get_widget (cvm_data->gui, "issued-to-cn");
@@ -114,6 +115,108 @@ certificate_viewer_show (ECert *cert)
text = e_cert_get_md5_fingerprint (cert);
label = glade_xml_get_widget (cvm_data->gui, "fingerprints-md5");
gtk_label_set_text (GTK_LABEL (label), text);
+}
+
+static void
+hierarchy_selection_changed (GtkTreeSelection *selection, CertificateViewerData *cvm_data)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+
+ if (gtk_tree_selection_get_selected (selection,
+ &model,
+ &iter)) {
+ EASN1Object *asn1_object;
+ ECert *cert;
+
+ gtk_tree_model_get (model,
+ &iter,
+ 1, &cert,
+ -1);
+
+ if (!cert)
+ return;
+
+ /* XXX show the selected fields somehow */
+ asn1_object = e_asn1_object_new_from_cert (cert);
+ }
+}
+
+static void
+fields_selection_changed (GtkTreeSelection *selection, CertificateViewerData *cvm_data)
+{
+}
+
+static void
+fill_in_details (CertificateViewerData *cvm_data, ECert *cert)
+{
+ GList *l;
+ GtkTreeIter *root = NULL;
+ GtkTreeSelection *selection;
+
+ /* 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 = glade_xml_get_widget (cvm_data->gui, "cert-hierarchy-treeview");
+ gtk_tree_view_set_model (GTK_TREE_VIEW (cvm_data->hierarchy_tree),
+ GTK_TREE_MODEL (cvm_data->hierarchy_store));
+
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (cvm_data->hierarchy_tree),
+ -1, "Cert", gtk_cell_renderer_text_new(),
+ "text", 0, NULL);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (cvm_data->hierarchy_tree));
+ g_signal_connect (selection, "changed", G_CALLBACK (hierarchy_selection_changed), cvm_data);
+
+ /* hook up all the fields tree foo */
+ cvm_data->fields_store = gtk_tree_store_new (1, G_TYPE_STRING);
+ cvm_data->fields_tree = glade_xml_get_widget (cvm_data->gui, "cert-fields-treeview");
+ gtk_tree_view_set_model (GTK_TREE_VIEW (cvm_data->fields_tree),
+ GTK_TREE_MODEL (cvm_data->fields_store));
+
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (cvm_data->fields_tree),
+ -1, "Field", gtk_cell_renderer_text_new(),
+ "text", 0, NULL);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (cvm_data->fields_tree));
+ g_signal_connect (selection, "changed", G_CALLBACK (fields_selection_changed), cvm_data);
+
+ /* hook up all the field display foo */
+ cvm_data->field_text = glade_xml_get_widget (cvm_data->gui, "cert-field-value-textview");
+
+ /* 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 char *str;
+ GtkTreeIter new_iter;
+
+ str = e_cert_get_cn (c);
+ if (!str)
+ str = e_cert_get_subject_name (c);
+
+ gtk_tree_store_insert (cvm_data->hierarchy_store, &new_iter, root, -1);
+ gtk_tree_store_set (cvm_data->hierarchy_store, &new_iter,
+ 0, str,
+ 1, c,
+ -1);
+
+ root = &new_iter;
+ }
+}
+
+GtkWidget*
+certificate_viewer_show (ECert *cert)
+{
+ CertificateViewerData *cvm_data;
+
+ cvm_data = g_new0 (CertificateViewerData, 1);
+ cvm_data->gui = glade_xml_new (EVOLUTION_GLADEDIR "/" GLADE_FILE_NAME, NULL, NULL);
+
+ cvm_data->dialog = glade_xml_get_widget (cvm_data->gui, "certificate-viewer-dialog");
+
+ fill_in_general (cvm_data, cert);
+ fill_in_details (cvm_data, cert);
g_object_weak_ref (G_OBJECT (cvm_data->dialog), free_data, cvm_data);
diff --git a/smime/gui/smime-ui.glade b/smime/gui/smime-ui.glade
index 57475c1cbc..36966f7443 100644
--- a/smime/gui/smime-ui.glade
+++ b/smime/gui/smime-ui.glade
@@ -1759,8 +1759,8 @@
</child>
</widget>
-<widget class="GtkDialog" id="dialog1">
- <property name="title" translatable="yes">dialog1</property>
+<widget class="GtkDialog" id="ca-trust-dialog">
+ <property name="title" translatable="yes">Certificate Authority Trust</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
diff --git a/smime/lib/Makefile.am b/smime/lib/Makefile.am
index d7d5b11784..69c435fb1e 100644
--- a/smime/lib/Makefile.am
+++ b/smime/lib/Makefile.am
@@ -20,6 +20,8 @@ INCLUDES = \
noinst_LTLIBRARIES = libessmime.la
libessmime_la_SOURCES = \
+ e-asn1-object.c \
+ e-asn1-object.h \
e-cert.c \
e-cert.h \
e-cert-trust.c \
diff --git a/smime/lib/e-asn1-object.c b/smime/lib/e-asn1-object.c
new file mode 100644
index 0000000000..47cf591b48
--- /dev/null
+++ b/smime/lib/e-asn1-object.c
@@ -0,0 +1,369 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* e-cert.c
+ *
+ * Copyright (C) 2003 Ximian, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Chris Toshok (toshok@ximian.com)
+ */
+
+/* The following is the mozilla license blurb, as the bodies some of
+ these functions were derived from the mozilla source. */
+
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ *
+ */
+
+#include "e-asn1-object.h"
+
+#include "secasn1.h"
+
+struct _EASN1ObjectPrivate {
+ PRUint32 tag;
+ PRUint32 type;
+ gboolean valid_container;
+
+ GList *children;
+
+ char *display_name;
+ char *value;
+
+ char *data;
+ guint data_len;
+};
+
+#define PARENT_TYPE G_TYPE_OBJECT
+static GObjectClass *parent_class;
+
+static void
+e_asn1_object_dispose (GObject *object)
+{
+}
+
+static void
+e_asn1_object_class_init (EASN1ObjectClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS(klass);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ object_class->dispose = e_asn1_object_dispose;
+}
+
+static void
+e_asn1_object_init (EASN1Object *asn1)
+{
+ asn1->priv = g_new0 (EASN1ObjectPrivate, 1);
+}
+
+GType
+e_asn1_object_get_type (void)
+{
+ static GType asn1_object_type = 0;
+
+ if (!asn1_object_type) {
+ static const GTypeInfo asn1_object_info = {
+ sizeof (EASN1ObjectClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) e_asn1_object_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (EASN1Object),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) e_asn1_object_init,
+ };
+
+ asn1_object_type = g_type_register_static (PARENT_TYPE, "EASN1Object", &asn1_object_info, 0);
+ }
+
+ return asn1_object_type;
+}
+
+
+/* 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 int
+get_integer_256 (unsigned char *data, unsigned int nb)
+{
+ int val;
+
+ switch (nb) {
+ case 1:
+ val = data[0];
+ break;
+ case 2:
+ val = (data[0] << 8) | data[1];
+ break;
+ case 3:
+ val = (data[0] << 16) | (data[1] << 8) | data[2];
+ break;
+ case 4:
+ val = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+ break;
+ default:
+ return -1;
+ }
+
+ return val;
+}
+
+/* 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 (unsigned char *data, unsigned char *end,
+ unsigned long *bytesUsed, gboolean *indefinite)
+{
+ unsigned char lbyte = *data++;
+ PRInt32 length = -1;
+
+ *indefinite = FALSE;
+ if (lbyte >= 0x80) {
+ /* Multibyte length */
+ unsigned nb = (unsigned) (lbyte & 0x7f);
+ if (nb > 4) {
+ return -1;
+ }
+ if (nb > 0) {
+
+ 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;
+ } else {
+ length = lbyte;
+ *bytesUsed = 1;
+ }
+ return length;
+}
+
+static gboolean
+build_from_der (EASN1Object *parent, char *data, char *end)
+{
+ unsigned long bytesUsed;
+ gboolean indefinite;
+ PRInt32 len;
+ PRUint32 type;
+ unsigned char code, tagnum;
+ EASN1Object *asn1object;
+
+ if (data >= end)
+ 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 int 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.
+ */
+
+ while (data < end) {
+ code = *data;
+ tagnum = code & SEC_ASN1_TAGNUM_MASK;
+
+ /*
+ * NOTE: This code does not (yet) handle the high-tag-number form!
+ */
+ if (tagnum == SEC_ASN1_HIGH_TAG_NUMBER) {
+ return FALSE;
+ }
+ data++;
+ len = get_der_item_length (data, end, &bytesUsed, &indefinite);
+ data += bytesUsed;
+ if ((len < 0) || ((data+len) > end))
+ 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 ();
+
+ asn1object->priv->type = tagnum;
+ asn1object->priv->tag = tagnum;
+
+ /*printableItem->SetData((char*)data, len);*/
+ }
+ data += len;
+
+ parent->priv->children = g_list_append (parent->priv->children, asn1object);
+ }
+
+ return TRUE;
+}
+
+EASN1Object*
+e_asn1_object_new_from_der (char *data, guint32 len)
+{
+ EASN1Object *obj = g_object_new (E_TYPE_ASN1_OBJECT, NULL);
+
+ if (!build_from_der (obj, data, data + len)) {
+ g_object_unref (obj);
+ return NULL;
+ }
+
+ return obj;
+}
+
+EASN1Object*
+e_asn1_object_new_from_cert (ECert *cert)
+{
+ char *data;
+ guint32 len;
+ EASN1Object *obj;
+
+ if (!e_cert_get_raw_der (cert, &data, &len))
+ return NULL;
+
+ obj = g_object_new (E_TYPE_ASN1_OBJECT, NULL);
+ if (!build_from_der (obj, data, data + len)) {
+ g_object_unref (obj);
+ return NULL;
+ }
+
+ return obj;
+}
+
+EASN1Object*
+e_asn1_object_new (void)
+{
+ return E_ASN1_OBJECT (g_object_new (E_TYPE_ASN1_OBJECT, NULL));
+}
+
+
+gboolean
+e_asn1_object_is_valid_container (EASN1Object *obj)
+{
+ return obj->priv->valid_container;
+}
+
+PRUint32
+e_asn1_object_get_asn1_type (EASN1Object *obj)
+{
+ return obj->priv->type;
+}
+
+PRUint32
+e_asn1_object_get_asn1_tag (EASN1Object *obj)
+{
+ return obj->priv->tag;
+}
+
+GList*
+e_asn1_object_get_children (EASN1Object *obj)
+{
+ GList *children = g_list_copy (obj->priv->children);
+
+ g_list_foreach (children, (GFunc)g_object_ref, NULL);
+
+ return children;
+}
+
+const char*
+e_asn1_object_get_display_name (EASN1Object *obj)
+{
+ return obj->priv->display_name;
+}
+
+const char*
+e_asn1_object_get_display_value (EASN1Object *obj)
+{
+ return obj->priv->value;
+}
+
+void
+e_asn1_object_get_data (EASN1Object *obj, char **data, guint32 *len)
+{
+ *data = obj->priv->data;
+ *len = obj->priv->data_len;
+}
diff --git a/smime/lib/e-asn1-object.h b/smime/lib/e-asn1-object.h
new file mode 100644
index 0000000000..ebdb7de15e
--- /dev/null
+++ b/smime/lib/e-asn1-object.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Chris Toshok <toshok@ximian.com>
+ *
+ * Copyright (C) 2003 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _E_ASN1_OBJECT_H_
+#define _E_ASN1_OBJECT_H_
+
+#include <glib-object.h>
+
+#include "e-cert.h"
+
+#include <nspr.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))
+#define E_ASN1_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_ASN1_OBJECT, EASN1ObjectClass))
+#define E_IS_ASN1_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_ASN1_OBJECT))
+#define E_IS_ASN1_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_ASN1_OBJECT))
+#define E_ASN1_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_ASN1_OBJECT, EASN1ObjectClass))
+
+typedef struct _EASN1Object EASN1Object;
+typedef struct _EASN1ObjectClass EASN1ObjectClass;
+typedef struct _EASN1ObjectPrivate EASN1ObjectPrivate;
+
+enum {
+ E_ASN1_OBJECT_TYPE_APPLICATION,
+ E_ASN1_OBJECT_TYPE_CONTEXT_SPECIFIC,
+ E_ASN1_OBJECT_TYPE_PRIVATE
+};
+
+struct _EASN1Object {
+ GObject parent;
+
+ EASN1ObjectPrivate *priv;
+};
+
+struct _EASN1ObjectClass {
+ GObjectClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_ecert_reserved0) (void);
+ void (*_ecert_reserved1) (void);
+ void (*_ecert_reserved2) (void);
+ void (*_ecert_reserved3) (void);
+ void (*_ecert_reserved4) (void);
+};
+
+EASN1Object *e_asn1_object_new_from_cert (ECert *cert);
+EASN1Object *e_asn1_object_new_from_der (char *data, guint32 len);
+EASN1Object *e_asn1_object_new (void);
+
+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);
+const char *e_asn1_object_get_display_name (EASN1Object *obj);
+const char *e_asn1_object_get_display_value (EASN1Object *obj);
+
+void e_asn1_object_get_data (EASN1Object *obj, char **data, guint32 *len);
+
+GType e_asn1_object_get_type (void);
+
+#endif /* _E_ASN1_OBJECT_H_ */
diff --git a/smime/lib/e-cert.c b/smime/lib/e-cert.c
index a8fa5879c2..2389cc29c8 100644
--- a/smime/lib/e-cert.c
+++ b/smime/lib/e-cert.c
@@ -409,6 +409,31 @@ e_cert_get_md5_fingerprint (ECert *cert)
return cert->priv->md5_fingerprint;
}
+GList*
+e_cert_get_chain (ECert *ecert)
+{
+ GList *l = NULL;
+
+ g_object_ref (ecert);
+
+ 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;
+
+ next_cert = CERT_FindCertIssuer (cert, PR_Now(), certUsageSSLClient);
+ if (!next_cert)
+ break;
+ ecert = e_cert_new (next_cert);
+ }
+
+ return l;
+}
+
gboolean
e_cert_mark_for_deletion (ECert *cert)
{
diff --git a/smime/lib/e-cert.h b/smime/lib/e-cert.h
index 4b5ec05a96..ac596b285b 100644
--- a/smime/lib/e-cert.h
+++ b/smime/lib/e-cert.h
@@ -91,6 +91,8 @@ const char* e_cert_get_serial_number (ECert *cert);
const char* e_cert_get_sha1_fingerprint (ECert *cert);
const char* e_cert_get_md5_fingerprint (ECert *cert);
+GList* e_cert_get_chain (ECert *cert);
+
gboolean e_cert_mark_for_deletion (ECert *cert);
ECertType e_cert_get_cert_type (ECert *cert);