diff options
author | Chris Toshok <toshok@ximian.com> | 2003-11-12 10:07:25 +0800 |
---|---|---|
committer | Chris Toshok <toshok@src.gnome.org> | 2003-11-12 10:07:25 +0800 |
commit | 4e1bce59fa373fd302b994d495427109c9fff121 (patch) | |
tree | 0769e76165203f6ee8395589441a5053074e3ea5 /smime/lib/e-cert-db.c | |
parent | 747e7843d135ca6640db787819b2664fe97afdad (diff) | |
download | gsoc2013-evolution-4e1bce59fa373fd302b994d495427109c9fff121.tar.gz gsoc2013-evolution-4e1bce59fa373fd302b994d495427109c9fff121.tar.zst gsoc2013-evolution-4e1bce59fa373fd302b994d495427109c9fff121.zip |
don't init NSS here. it's done in e_cert_db_peek.
2003-11-11 Chris Toshok <toshok@ximian.com>
* tests/import-cert.c (main): don't init NSS here. it's done in
e_cert_db_peek.
* lib/Makefile.am (libessmime_la_SOURCES): add e-cert-db.[ch]
* gui/smime-ui.glade: set the initial sensitivity of the buttons
here, and add the beginnings of the CA import dialog (where you
assign trust levels to it.)
* gui/certificate-manager.c (handle_selection_changed):
sensitize/desensitize all the various buttons correctly when the
GtkTreeView's selection changes.
(yourcerts_selection_changed): new, selection change handler for
the Your Certs tab.
(initialize_yourcerts_ui): hook up the tree selection, and add a
model column for the ECert.
(contactcerts_selection_changed): new, selection change handler
for the Contact Certs tab.
(initialize_contactcerts_ui): hook up the tree selection, and add
a model column for the ECert.
(import_ca): new function.
(delete_ca): new function.
(authoritycerts_selection_changed): new, selection change handler
for the Authority Certs tab.
(create_authoritycerts_treemodel): new function for creating the
authority cert tree model. the other tabs will eventually use a
separate function for this too, as unload_certs gets fleshed out.
(initialize_authoritycerts_ui): hook up the tree selection, and
add import/delete buttons.
(destroy_key): dtor for the keys in our hashes.
(destroy_value): dtor for the values in our hashes.
(unload_certs): new function. basically destroy/recreate the
model and hash for the particular cert type/tab.
(load_certs): use e_cert_get_cert_type.
(populate_ui): use unload_certs as well as load_certs.
(certificate_manager_config_control_new): call e_cert_db_peek
,which will initialize all of NSS. hook up all the widgets from
libglade.
* lib/e-cert.h: add prototypes for all the new methods, and add
the ECertType enum.
* lib/e-cert.c (e_cert_dispose): handle deletion from the DB here.
(e_cert_new_from_der): new function.
(e_cert_get_internal_cert): new function.
(e_cert_get_raw_der): new function.
(e_cert_get_issuer_name): new
(e_cert_get_subject_name): new
(e_cert_mark_for_deletion): new
(e_cert_get_cert_type): new.
(e_cert_is_ca_cert): nuke.
* lib/e-cert-db.[ch]: new, partly implemented, derived from
mozilla's nsNSSCertificateDB code.
svn path=/trunk/; revision=23292
Diffstat (limited to 'smime/lib/e-cert-db.c')
-rw-r--r-- | smime/lib/e-cert-db.c | 822 |
1 files changed, 822 insertions, 0 deletions
diff --git a/smime/lib/e-cert-db.c b/smime/lib/e-cert-db.c new file mode 100644 index 0000000000..8e98124a14 --- /dev/null +++ b/smime/lib/e-cert-db.c @@ -0,0 +1,822 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* e-cert-db.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 of most + 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-cert-db.h" + +#include "nss.h" +#include "pk11func.h" +#include "certdb.h" +#include <e-util/e-dialog-utils.h> +#include <gtk/gtkmessagedialog.h> +#include <libgnome/gnome-i18n.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +struct _ECertDBPrivate { +}; + +#define PARENT_TYPE G_TYPE_OBJECT +static GObjectClass *parent_class; + +static CERTDERCerts* e_cert_db_get_certs_from_package (PRArenaPool *arena, char *data, guint32 length); + + + +static void +e_cert_db_dispose (GObject *object) +{ + ECertDB *ec = E_CERT_DB (object); + + if (!ec->priv) + return; + + /* XXX free instance specific data */ + + g_free (ec->priv); + ec->priv = NULL; + + if (G_OBJECT_CLASS (parent_class)->dispose) + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +e_cert_db_class_init (ECertDBClass *klass) +{ + GObjectClass *object_class; + char *evolution_dir_path; + gboolean success; + + object_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + object_class->dispose = e_cert_db_dispose; + + evolution_dir_path = g_build_path ("/", g_get_home_dir (), ".evolution", NULL); + + /* we initialize NSS here to make sure it only happens once */ + success = (SECSuccess == NSS_InitReadWrite (evolution_dir_path)); + if (!success) { + success = (SECSuccess == NSS_Init (evolution_dir_path)); + if (success) + g_warning ("opening cert databases read-only"); + } + if (!success) { + success = (SECSuccess == NSS_NoDB_Init (evolution_dir_path)); + if (success) + g_warning ("initializing security library without cert databases."); + } + g_free (evolution_dir_path); + + if (!success) { + g_warning ("Failed all methods for initializing NSS"); + } +} + +static void +e_cert_db_init (ECertDB *ec) +{ + ec->priv = g_new0 (ECertDBPrivate, 1); +} + +GType +e_cert_db_get_type (void) +{ + static GType cert_type = 0; + + if (!cert_type) { + static const GTypeInfo cert_info = { + sizeof (ECertDBClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) e_cert_db_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (ECertDB), + 0, /* n_preallocs */ + (GInstanceInitFunc) e_cert_db_init, + }; + + cert_type = g_type_register_static (PARENT_TYPE, "ECertDB", &cert_info, 0); + } + + return cert_type; +} + + + +GStaticMutex init_mutex = G_STATIC_MUTEX_INIT; +static ECertDB *cert_db = NULL; + +ECertDB* +e_cert_db_peek (void) +{ + g_static_mutex_lock (&init_mutex); + if (!cert_db) + cert_db = g_object_new (E_TYPE_CERT_DB, NULL); + g_static_mutex_unlock (&init_mutex); + + return cert_db; +} + +void +e_cert_db_shutdown (void) +{ + /* XXX */ +} + +/* searching for certificates */ +ECert* +e_cert_db_find_cert_by_nickname (ECertDB *certdb, + const char *nickname, + GError **error) +{ + // nsNSSShutDownPreventionLock locker; + CERTCertificate *cert = NULL; + + //PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Getting \"%s\"\n", asciiname)); +#if 0 + // what it should be, but for now... + if (aToken) { + cert = PK11_FindCertFromNickname(asciiname, NULL); + } else { + cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), asciiname); + } +#endif + cert = PK11_FindCertFromNickname((char*)nickname, NULL); + if (!cert) { + cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), (char*)nickname); + } + + + if (cert) { + // PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("got it\n")); + ECert *ecert = e_cert_new (cert); + return ecert; + } + else { + /* XXX gerror */ + return NULL; + } +} + +ECert* +e_cert_db_find_cert_by_key (ECertDB *certdb, + const char *db_key, + GError **error) +{ +#if 0 + // nsNSSShutDownPreventionLock locker; + SECItem keyItem = {siBuffer, NULL, 0}; + SECItem *dummy; + CERTIssuerAndSN issuerSN; + unsigned long moduleID,slotID; + CERTCertificate *cert; + + if (!db_key) { + /* XXX gerror */ + return NULL; + } + + dummy = NSSBase64_DecodeBuffer(NULL, &keyItem, db_key, + (PRUint32)PL_strlen(db_key)); + + // someday maybe we can speed up the search using the moduleID and slotID + moduleID = NS_NSS_GET_LONG(keyItem.data); + slotID = NS_NSS_GET_LONG(&keyItem.data[NS_NSS_LONG]); + + // build the issuer/SN structure + issuerSN.serialNumber.len = NS_NSS_GET_LONG(&keyItem.data[NS_NSS_LONG*2]); + issuerSN.derIssuer.len = NS_NSS_GET_LONG(&keyItem.data[NS_NSS_LONG*3]); + issuerSN.serialNumber.data= &keyItem.data[NS_NSS_LONG*4]; + issuerSN.derIssuer.data= &keyItem.data[NS_NSS_LONG*4+ + issuerSN.serialNumber.len]; + + cert = CERT_FindCertByIssuerAndSN(CERT_GetDefaultCertDB(), &issuerSN); + PR_FREEIF(keyItem.data); + if (cert) { + ECert *ecert = e_cert_new (cert); + return e_cert; + } + + /* XXX gerror */ + return NULL; +#endif +} + +GList* +e_cert_db_get_cert_nicknames (ECertDB *certdb, + ECertType cert_type, + GError **error) +{ +} + +ECert* +e_cert_db_find_email_encryption_cert (ECertDB *certdb, + const char *nickname, + GError **error) +{ +} + +ECert* +e_cert_db_find_email_signing_cert (ECertDB *certdb, + const char *nickname, + GError **error) +{ +} + +ECert* +e_cert_db_find_cert_by_email_address (ECertDB *certdb, + const char *email, + GError **error) +{ + /* nsNSSShutDownPreventionLock locker; */ + ECert *cert; + CERTCertificate *any_cert = CERT_FindCertByNicknameOrEmailAddr(CERT_GetDefaultCertDB(), + (char*)email); + CERTCertList *certlist; + + if (!any_cert) { + /* XXX gerror */ + return NULL; + } + + /* any_cert now contains a cert with the right subject, but it might not have the correct usage */ + certlist = CERT_CreateSubjectCertList(NULL, + CERT_GetDefaultCertDB(), + &any_cert->derSubject, + PR_Now(), PR_TRUE); + if (!certlist) { + /* XXX gerror */ + /* XXX free any_cert */ + return NULL; + } + + if (SECSuccess != CERT_FilterCertListByUsage(certlist, certUsageEmailRecipient, PR_FALSE)) { + /* XXX gerror */ + /* XXX free any_cert */ + /* XXX free certlist */ + return NULL; + } + + if (CERT_LIST_END(CERT_LIST_HEAD(certlist), certlist)) { + /* XXX gerror */ + /* XXX free any_cert */ + /* XXX free certlist */ + return NULL; + } + + cert = e_cert_new (CERT_LIST_HEAD(certlist)->cert); + + return cert; +} + +static gboolean +_confirm_download_ca_cert (ECert *cert, guint32 *trustBits, gboolean *allow) +{ + /* right now just allow it and set the trustBits to 0 */ + *trustBits = 0; + *allow = TRUE; + return TRUE; +} + +static gboolean +handle_ca_cert_download(GList *certs, GError **error) +{ + ECert *certToShow; + SECItem der; + CERTCertificate *tmpCert; + + /* First thing we have to do is figure out which certificate + we're gonna present to the user. The CA may have sent down + a list of certs which may or may not be a chained list of + certs. Until the day we can design some solid UI for the + general case, we'll code to the > 90% case. That case is + where a CA sends down a list that is a chain up to its root + in either ascending or descending order. What we're gonna + do is compare the first 2 entries, if the first was signed + by the second, we assume the leaf cert is the first cert + and display it. If the second cert was signed by the first + cert, then we assume the first cert is the root and the + last cert in the array is the leaf. In this case we + display the last cert. + */ + + /* nsNSSShutDownPreventionLock locker;*/ + + if (certs == NULL) { + g_warning ("Didn't get any certs to import."); + return TRUE; + } + else if (certs->next == NULL) { + /* there's 1 cert */ + certToShow = E_CERT (certs->data); + } + else { + /* there are multiple certs */ + ECert *cert0; + ECert *cert1; + const char* cert0SubjectName; + const char* cert0IssuerName; + const char* cert1SubjectName; + const char* cert1IssuerName; + + cert0 = E_CERT (certs->data); + cert1 = E_CERT (certs->next->data); + + cert0IssuerName = e_cert_get_issuer_name (cert0); + cert0SubjectName = e_cert_get_subject_name (cert0); + + cert1IssuerName = e_cert_get_issuer_name (cert1); + cert1SubjectName = e_cert_get_subject_name (cert1); + + if (!strcmp(cert1IssuerName, cert0SubjectName)) { + /* In this case, the first cert in the list signed the second, + so the first cert is the root. Let's display the last cert + in the list. */ + certToShow = E_CERT (g_list_last (certs)->data); + } + else if (!strcmp(cert0IssuerName, cert1SubjectName)) { + /* In this case the second cert has signed the first cert. The + first cert is the leaf, so let's display it. */ + certToShow = cert0; + } else { + /* It's not a chain, so let's just show the first one in the + downloaded list. */ + certToShow = cert0; + } + } + + if (!certToShow) { + /* XXX gerror */ + return FALSE; + } + + if (!e_cert_get_raw_der (certToShow, (char**)&der.data, &der.len)) { + /* XXX gerror */ + return FALSE; + } + + { + /*PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Creating temp cert\n"));*/ + CERTCertDBHandle *certdb = CERT_GetDefaultCertDB(); + tmpCert = CERT_FindCertByDERCert(certdb, &der); + if (!tmpCert) { + tmpCert = CERT_NewTempCertificate(certdb, &der, + NULL, PR_FALSE, PR_TRUE); + } + if (!tmpCert) { + g_warning ("Couldn't create cert from DER blob"); + return FALSE; + } + } + +#if 0 + CERTCertificateCleaner tmpCertCleaner(tmpCert); +#endif + + if (tmpCert->isperm) { + e_notice (NULL, GTK_MESSAGE_WARNING, _("Certificate already exists")); + /* XXX gerror */ + return FALSE; + } + else { + guint32 trustBits; + gboolean allow; + char *nickname; + SECStatus srv; + + if (!_confirm_download_ca_cert (certToShow, &trustBits, &allow)) { + /* XXX gerror */ + return FALSE; + } + + if (!allow) { + /* XXX gerror */ + return FALSE; + } + + //PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("trust is %d\n", trustBits)); + + nickname = CERT_MakeCANickname(tmpCert); + + //PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Created nick \"%s\"\n", nickname.get())); + +#if 0 + nsNSSCertTrust trust; + trust.SetValidCA(); + trust.AddCATrust(trustBits & nsIX509CertDB::TRUSTED_SSL, + trustBits & nsIX509CertDB::TRUSTED_EMAIL, + trustBits & nsIX509CertDB::TRUSTED_OBJSIGN); +#endif + + srv = CERT_AddTempCertToPerm(tmpCert, + nickname, + /*XXX trust.GetTrust()*/ 0); + + if (srv != SECSuccess) { + /* XXX gerror */ + return FALSE; + } + +#if 0 + /* Now it's time to add the rest of the certs we just downloaded. + Since we didn't prompt the user about any of these certs, we + won't set any trust bits for them. */ + nsNSSCertTrust defaultTrust; + defaultTrust.SetValidCA(); + defaultTrust.AddCATrust(0,0,0); + for (PRUint32 i=0; i<numCerts; i++) { + if (i == selCertIndex) + continue; + + certToShow = do_QueryElementAt(x509Certs, i); + certToShow->GetRawDER(&der.len, (PRUint8 **)&der.data); + + CERTCertificate *tmpCert2 = + CERT_NewTempCertificate(certdb, &der, nsnull, PR_FALSE, PR_TRUE); + + if (!tmpCert2) { + NS_ASSERTION(0, "Couldn't create temp cert from DER blob\n"); + continue; // Let's try to import the rest of 'em + } + nickname.Adopt(CERT_MakeCANickname(tmpCert2)); + CERT_AddTempCertToPerm(tmpCert2, NS_CONST_CAST(char*,nickname.get()), + defaultTrust.GetTrust()); + CERT_DestroyCertificate(tmpCert2); + } +#endif + return TRUE; + } +} + +/* deleting certificates */ +gboolean +e_cert_db_delete_cert (ECertDB *certdb, + ECert *ecert) +{ + // nsNSSShutDownPreventionLock locker; + // nsNSSCertificate *nssCert = NS_STATIC_CAST(nsNSSCertificate*, aCert); + + CERTCertificate *cert; + SECStatus srv = SECSuccess; + if (!e_cert_mark_for_deletion (ecert)) { + return FALSE; + } + + cert = e_cert_get_internal_cert (ecert); + if (cert->slot && e_cert_get_cert_type (ecert) != E_CERT_USER) { + /* To delete a cert of a slot (builtin, most likely), mark it as + completely untrusted. This way we keep a copy cached in the + local database, and next time we try to load it off of the + external token/slot, we'll know not to trust it. We don't + want to do that with user certs, because a user may re-store + the cert onto the card again at which point we *will* want to + trust that cert if it chains up properly. */ +#if 0 + nsNSSCertTrust trust(0, 0, 0); + srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), + cert, trust.GetTrust()); +#endif + } + +#if 0 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("cert deleted: %d", srv)); +#endif + return (srv) ? FALSE : TRUE; +} + +/* importing certificates */ +gboolean +e_cert_db_import_certs (ECertDB *certdb, + char *data, guint32 length, + ECertType cert_type, + GError **error) +{ + /*nsNSSShutDownPreventionLock locker;*/ + PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + GList *certs = NULL; + CERTDERCerts *certCollection = e_cert_db_get_certs_from_package (arena, data, length); + int i; + gboolean rv; + + if (!certCollection) { + /* XXX gerror */ + PORT_FreeArena(arena, PR_FALSE); + return FALSE; + } + + /* Now let's create some certs to work with */ + for (i=0; i<certCollection->numcerts; i++) { + SECItem *currItem = &certCollection->rawCerts[i]; + ECert *cert; + + cert = e_cert_new_from_der ((char*)currItem->data, currItem->len); + if (!cert) { + /* XXX gerror */ + g_list_foreach (certs, (GFunc)g_object_unref, NULL); + g_list_free (certs); + PORT_FreeArena(arena, PR_FALSE); + return FALSE; + } + certs = g_list_append (certs, cert); + } + switch (cert_type) { + case E_CERT_CA: + rv = handle_ca_cert_download(certs, error); + break; + default: + // We only deal with import CA certs in this method currently. + /* XXX gerror */ + PORT_FreeArena(arena, PR_FALSE); + rv = FALSE; + } + + g_list_foreach (certs, (GFunc)g_object_unref, NULL); + g_list_free (certs); + PORT_FreeArena(arena, PR_FALSE); + return rv; +} + +gboolean +e_cert_db_import_email_cert (ECertDB *certdb, + char *data, guint32 length, + GError **error) +{ +} + +gboolean +e_cert_db_import_user_cert (ECertDB *certdb, + char *data, guint32 length, + GError **error) +{ +#if 0 + /* nsNSSShutDownPreventionLock locker;*/ + PK11SlotInfo *slot; + char * nickname = NULL; + gboolean rv = FALSE; + int numCACerts; + SECItem *CACerts; + CERTDERCerts * collectArgs; + CERTCertificate * cert=NULL; + + collectArgs = e_cert_db_get_certs_from_package(data, length); + if (!collectArgs) { + goto loser; + } + + cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), collectArgs->rawCerts, + (char *)NULL, PR_FALSE, PR_TRUE); + if (!cert) { + goto loser; + } + + slot = PK11_KeyForCertExists(cert, NULL, NULL); + if ( slot == NULL ) { + goto loser; + } + PK11_FreeSlot(slot); + + /* pick a nickname for the cert */ + if (cert->nickname) { + /* sigh, we need a call to look up other certs with this subject and + * identify nicknames from them. We can no longer walk down internal + * database structures rjr */ + nickname = cert->nickname; + } + else { + g_assert_not_reached (); + /* nickname = default_nickname(cert, NULL); */ + } + + /* user wants to import the cert */ + slot = PK11_ImportCertForKey(cert, nickname, NULL); + if (!slot) { + goto loser; + } + PK11_FreeSlot(slot); + numCACerts = collectArgs->numcerts - 1; + + if (numCACerts) { + CACerts = collectArgs->rawCerts+1; + if ( ! CERT_ImportCAChain(CACerts, numCACerts, certUsageUserCertImport) ) { + rv = TRUE; + } + } + + loser: + if ( cert ) { + CERT_DestroyCertificate(cert); + } + return rv; +#endif +} + +gboolean +e_cert_db_import_server_cert (ECertDB *certdb, + char *data, guint32 length, + GError **error) +{ +} + +gboolean +e_cert_db_import_certs_from_file (ECertDB *cert_db, + const char *file_path, + ECertType cert_type, + GError **error) +{ + gboolean rv; + int fd; + struct stat sb; + char *buf; + int bytes_read; + + switch (cert_type) { + case E_CERT_CA: + case E_CERT_CONTACT: + case E_CERT_SITE: + /* good */ + break; + + default: + /* not supported (yet) */ + /* XXX gerror */ + return FALSE; + } + + fd = open (file_path, O_RDONLY); + if (fd == -1) { + /* XXX gerror */ + return FALSE; + } + + if (-1 == fstat (fd, &sb)) { + /* XXX gerror */ + close (fd); + return FALSE; + } + + buf = g_malloc (sb.st_size); + if (!buf) { + /* XXX gerror */ + close (fd); + return FALSE; + } + + bytes_read = read (fd, buf, sb.st_size); + + close (fd); + + if (bytes_read != sb.st_size) { + /* XXX gerror */ + rv = FALSE; + } + else { + printf ("importing %d bytes from `%s'\n", bytes_read, file_path); + + switch (cert_type) { + case E_CERT_CA: + rv = e_cert_db_import_certs (cert_db, buf, bytes_read, cert_type, error); + break; + + case E_CERT_SITE: + rv = e_cert_db_import_server_cert (cert_db, buf, bytes_read, error); + break; + + case E_CERT_CONTACT: + rv = e_cert_db_import_email_cert (cert_db, buf, bytes_read, error); + break; + + default: + rv = FALSE; + break; + } + } + + g_free (buf); + return rv; +} + +gboolean +e_cert_db_import_pkcs12_file (ECertDB *cert_db, + const char *file_path, + GError **error) +{ +} + +gboolean +e_cert_db_export_pkcs12_file (ECertDB *cert_db, + const char *file_path, + GList *certs, + GError **error) +{ +} + + + +static SECStatus PR_CALLBACK +collect_certs(void *arg, SECItem **certs, int numcerts) +{ + CERTDERCerts *collectArgs; + SECItem *cert; + SECStatus rv; + + collectArgs = (CERTDERCerts *)arg; + + collectArgs->numcerts = numcerts; + collectArgs->rawCerts = (SECItem *) PORT_ArenaZAlloc(collectArgs->arena, sizeof(SECItem) * numcerts); + if ( collectArgs->rawCerts == NULL ) + return(SECFailure); + + cert = collectArgs->rawCerts; + + while ( numcerts-- ) { + rv = SECITEM_CopyItem(collectArgs->arena, cert, *certs); + if ( rv == SECFailure ) + return(SECFailure); + cert++; + certs++; + } + + return (SECSuccess); +} + +static CERTDERCerts* +e_cert_db_get_certs_from_package (PRArenaPool *arena, + char *data, + guint32 length) +{ + /*nsNSSShutDownPreventionLock locker;*/ + CERTDERCerts *collectArgs = + (CERTDERCerts *)PORT_ArenaZAlloc(arena, sizeof(CERTDERCerts)); + SECStatus sec_rv; + + if (!collectArgs) + return NULL; + + collectArgs->arena = arena; + sec_rv = CERT_DecodeCertPackage(data, + length, collect_certs, + (void *)collectArgs); + + if (sec_rv != SECSuccess) + return NULL; + + return collectArgs; +} |