evolution-3.6.4/smime/lib/e-cert-db.c

No issues found

   1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
   2 /* The following is the mozilla license blurb, as the bodies some of
   3  * these functions were derived from the mozilla source. */
   4 /* e-cert-db.c
   5  *
   6  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
   7  *
   8  * The contents of this file are subject to the Mozilla Public License Version
   9  * 1.1 (the "License"); you may not use this file except in compliance with
  10  * the License. You may obtain a copy of the License at
  11  * http://www.mozilla.org/MPL/
  12  *
  13  * Software distributed under the License is distributed on an "AS IS" basis,
  14  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  15  * for the specific language governing rights and limitations under the
  16  * License.
  17  *
  18  * The Original Code is the Netscape security libraries.
  19  *
  20  * The Initial Developer of the Original Code is
  21  * Netscape Communications Corporation.
  22  * Portions created by the Initial Developer are Copyright (C) 1994-2000
  23  * the Initial Developer. All Rights Reserved.
  24  *
  25  * Alternatively, the contents of this file may be used under the terms of
  26  * either the GNU General Public License Version 2 or later (the "GPL"), or
  27  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28  * in which case the provisions of the GPL or the LGPL are applicable instead
  29  * of those above. If you wish to allow use of your version of this file only
  30  * under the terms of either the GPL or the LGPL, and not to allow others to
  31  * use your version of this file under the terms of the MPL, indicate your
  32  * decision by deleting the provisions above and replace them with the notice
  33  * and other provisions required by the GPL or the LGPL. If you do not delete
  34  * the provisions above, a recipient may use your version of this file under
  35  * the terms of any one of the MPL, the GPL or the LGPL.
  36  */
  37 
  38 /*
  39  * Author: Chris Toshok (toshok@ximian.com)
  40  *
  41  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
  42  */
  43 #ifdef HAVE_CONFIG_H
  44 #include <config.h>
  45 #endif
  46 
  47 #include <gtk/gtk.h>
  48 #include <glib/gi18n.h>
  49 #include <glib/gstdio.h>
  50 
  51 #include <camel/camel.h>        /* FIXME: this is where camel_init is defined; it shouldn't include everything else */
  52 
  53 #include <libedataserverui/libedataserverui.h>
  54 
  55 /* private NSS defines used by PSM */
  56 /* (must be declated before cert.h) */
  57 #define CERT_NewTempCertificate __CERT_NewTempCertificate
  58 #define CERT_AddTempCertToPerm __CERT_AddTempCertToPerm
  59 
  60 #include "e-cert-db.h"
  61 #include "e-cert-trust.h"
  62 #include "e-pkcs12.h"
  63 
  64 #include "gmodule.h"
  65 
  66 #include "nss.h"
  67 #include "ssl.h"
  68 #include "p12plcy.h"
  69 #include "pk11func.h"
  70 #include "nssckbi.h"
  71 #include <secerr.h>
  72 #include "secmod.h"
  73 #include "certdb.h"
  74 #include "plstr.h"
  75 #include "prprf.h"
  76 #include "prmem.h"
  77 #include "e-util/e-util.h"
  78 #include "e-util/e-util-private.h"
  79 #include <sys/types.h>
  80 #include <sys/stat.h>
  81 #include <unistd.h>
  82 
  83 enum {
  84 	PK11_PASSWD,
  85 	PK11_CHANGE_PASSWD,
  86 	CONFIRM_CA_CERT_IMPORT,
  87 	LAST_SIGNAL
  88 };
  89 
  90 static guint e_cert_db_signals[LAST_SIGNAL];
  91 
  92 G_DEFINE_TYPE (ECertDB, e_cert_db, G_TYPE_OBJECT)
  93 
  94 GQuark
  95 e_certdb_error_quark (void)
  96 {
  97 	static GQuark q = 0;
  98 	if (q == 0)
  99 		q = g_quark_from_static_string ("e-certdb-error-quark");
 100 
 101 	return q;
 102 }
 103 
 104 static const gchar *
 105 nss_error_to_string (glong errorcode)
 106 {
 107 #define cs(a,b) case a: return b;
 108 
 109 	switch (errorcode) {
 110 	cs (SEC_ERROR_IO, "An I/O error occurred during security authorization.")
 111 	cs (SEC_ERROR_LIBRARY_FAILURE, "security library failure.")
 112 	cs (SEC_ERROR_BAD_DATA, "security library: received bad data.")
 113 	cs (SEC_ERROR_OUTPUT_LEN, "security library: output length error.")
 114 	cs (SEC_ERROR_INPUT_LEN, "security library has experienced an input length error.")
 115 	cs (SEC_ERROR_INVALID_ARGS, "security library: invalid arguments.")
 116 	cs (SEC_ERROR_INVALID_ALGORITHM, "security library: invalid algorithm.")
 117 	cs (SEC_ERROR_INVALID_AVA, "security library: invalid AVA.")
 118 	cs (SEC_ERROR_INVALID_TIME, "Improperly formatted time string.")
 119 	cs (SEC_ERROR_BAD_DER, "security library: improperly formatted DER-encoded message.")
 120 	cs (SEC_ERROR_BAD_SIGNATURE, "Peer's certificate has an invalid signature.")
 121 	cs (SEC_ERROR_EXPIRED_CERTIFICATE, "Peer's Certificate has expired.")
 122 	cs (SEC_ERROR_REVOKED_CERTIFICATE, "Peer's Certificate has been revoked.")
 123 	cs (SEC_ERROR_UNKNOWN_ISSUER, "Peer's Certificate issuer is not recognized.")
 124 	cs (SEC_ERROR_BAD_KEY, "Peer's public key is invalid.")
 125 	cs (SEC_ERROR_BAD_PASSWORD, "The security password entered is incorrect.")
 126 	cs (SEC_ERROR_RETRY_PASSWORD, "New password entered incorrectly.  Please try again.")
 127 	cs (SEC_ERROR_NO_NODELOCK, "security library: no nodelock.")
 128 	cs (SEC_ERROR_BAD_DATABASE, "security library: bad database.")
 129 	cs (SEC_ERROR_NO_MEMORY, "security library: memory allocation failure.")
 130 	cs (SEC_ERROR_UNTRUSTED_ISSUER, "Peer's certificate issuer has been marked as not trusted by the user.")
 131 	cs (SEC_ERROR_UNTRUSTED_CERT, "Peer's certificate has been marked as not trusted by the user.")
 132 	cs (SEC_ERROR_DUPLICATE_CERT, "Certificate already exists in your database.")
 133 	cs (SEC_ERROR_DUPLICATE_CERT_NAME, "Downloaded certificate's name duplicates one already in your database.")
 134 	cs (SEC_ERROR_ADDING_CERT, "Error adding certificate to database.")
 135 	cs (SEC_ERROR_FILING_KEY, "Error refiling the key for this certificate.")
 136 	cs (SEC_ERROR_NO_KEY, "The private key for this certificate cannot be found in key database")
 137 	cs (SEC_ERROR_CERT_VALID, "This certificate is valid.")
 138 	cs (SEC_ERROR_CERT_NOT_VALID, "This certificate is not valid.")
 139 	cs (SEC_ERROR_CERT_NO_RESPONSE, "Cert Library: No Response")
 140 	cs (SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE, "The certificate issuer's certificate has expired.  Check your system date and time.")
 141 	cs (SEC_ERROR_CRL_EXPIRED, "The CRL for the certificate's issuer has expired.  Update it or check your system date and time.")
 142 	cs (SEC_ERROR_CRL_BAD_SIGNATURE, "The CRL for the certificate's issuer has an invalid signature.")
 143 	cs (SEC_ERROR_CRL_INVALID, "New CRL has an invalid format.")
 144 	cs (SEC_ERROR_EXTENSION_VALUE_INVALID, "Certificate extension value is invalid.")
 145 	cs (SEC_ERROR_EXTENSION_NOT_FOUND, "Certificate extension not found.")
 146 	cs (SEC_ERROR_CA_CERT_INVALID, "Issuer certificate is invalid.")
 147 	cs (SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID, "Certificate path length constraint is invalid.")
 148 	cs (SEC_ERROR_CERT_USAGES_INVALID, "Certificate usages field is invalid.")
 149 	cs (SEC_INTERNAL_ONLY, "**Internal ONLY module**")
 150 	cs (SEC_ERROR_INVALID_KEY, "The key does not support the requested operation.")
 151 	cs (SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION, "Certificate contains unknown critical extension.")
 152 	cs (SEC_ERROR_OLD_CRL, "New CRL is not later than the current one.")
 153 	cs (SEC_ERROR_NO_EMAIL_CERT, "Not encrypted or signed: you do not yet have an email certificate.")
 154 	cs (SEC_ERROR_NO_RECIPIENT_CERTS_QUERY, "Not encrypted: you do not have certificates for each of the recipients.")
 155 	cs (SEC_ERROR_NOT_A_RECIPIENT, "Cannot decrypt: you are not a recipient, or matching certificate and private key not found.")
 156 	cs (SEC_ERROR_PKCS7_KEYALG_MISMATCH, "Cannot decrypt: key encryption algorithm does not match your certificate.")
 157 	cs (SEC_ERROR_PKCS7_BAD_SIGNATURE, "Signature verification failed: no signer found, too many signers found, or improper or corrupted data.")
 158 	cs (SEC_ERROR_UNSUPPORTED_KEYALG, "Unsupported or unknown key algorithm.")
 159 	cs (SEC_ERROR_DECRYPTION_DISALLOWED, "Cannot decrypt: encrypted using a disallowed algorithm or key size.")
 160 	cs (XP_SEC_FORTEZZA_BAD_CARD, "Fortezza card has not been properly initialized.  Please remove it and return it to your issuer.")
 161 	cs (XP_SEC_FORTEZZA_NO_CARD, "No Fortezza cards Found")
 162 	cs (XP_SEC_FORTEZZA_NONE_SELECTED, "No Fortezza card selected")
 163 	cs (XP_SEC_FORTEZZA_MORE_INFO, "Please select a personality to get more info on")
 164 	cs (XP_SEC_FORTEZZA_PERSON_NOT_FOUND, "Personality not found")
 165 	cs (XP_SEC_FORTEZZA_NO_MORE_INFO, "No more information on that Personality")
 166 	cs (XP_SEC_FORTEZZA_BAD_PIN, "Invalid Pin")
 167 	cs (XP_SEC_FORTEZZA_PERSON_ERROR, "Couldn't initialize Fortezza personalities.")
 168 	cs (SEC_ERROR_NO_KRL, "No KRL for this site's certificate has been found.")
 169 	cs (SEC_ERROR_KRL_EXPIRED, "The KRL for this site's certificate has expired.")
 170 	cs (SEC_ERROR_KRL_BAD_SIGNATURE, "The KRL for this site's certificate has an invalid signature.")
 171 	cs (SEC_ERROR_REVOKED_KEY, "The key for this site's certificate has been revoked.")
 172 	cs (SEC_ERROR_KRL_INVALID, "New KRL has an invalid format.")
 173 	cs (SEC_ERROR_NEED_RANDOM, "security library: need random data.")
 174 	cs (SEC_ERROR_NO_MODULE, "security library: no security module can perform the requested operation.")
 175 	cs (SEC_ERROR_NO_TOKEN, "The security card or token does not exist, needs to be initialized, or has been removed.")
 176 	cs (SEC_ERROR_READ_ONLY, "security library: read-only database.")
 177 	cs (SEC_ERROR_NO_SLOT_SELECTED, "No slot or token was selected.")
 178 	cs (SEC_ERROR_CERT_NICKNAME_COLLISION, "A certificate with the same nickname already exists.")
 179 	cs (SEC_ERROR_KEY_NICKNAME_COLLISION, "A key with the same nickname already exists.")
 180 	cs (SEC_ERROR_SAFE_NOT_CREATED, "error while creating safe object")
 181 	cs (SEC_ERROR_BAGGAGE_NOT_CREATED, "error while creating baggage object")
 182 	cs (XP_JAVA_REMOVE_PRINCIPAL_ERROR, "Couldn't remove the principal")
 183 	cs (XP_JAVA_DELETE_PRIVILEGE_ERROR, "Couldn't delete the privilege")
 184 	cs (XP_JAVA_CERT_NOT_EXISTS_ERROR, "This principal doesn't have a certificate")
 185 	cs (SEC_ERROR_BAD_EXPORT_ALGORITHM, "Required algorithm is not allowed.")
 186 	cs (SEC_ERROR_EXPORTING_CERTIFICATES, "Error attempting to export certificates.")
 187 	cs (SEC_ERROR_IMPORTING_CERTIFICATES, "Error attempting to import certificates.")
 188 	cs (SEC_ERROR_PKCS12_DECODING_PFX, "Unable to import.  Decoding error.  File not valid.")
 189 	cs (SEC_ERROR_PKCS12_INVALID_MAC, "Unable to import.  Invalid MAC.  Incorrect password or corrupt file.")
 190 	cs (SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM, "Unable to import.  MAC algorithm not supported.")
 191 	cs (SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE, "Unable to import.  Only password integrity and privacy modes supported.")
 192 	cs (SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE, "Unable to import.  File structure is corrupt.")
 193 	cs (SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM, "Unable to import.  Encryption algorithm not supported.")
 194 	cs (SEC_ERROR_PKCS12_UNSUPPORTED_VERSION, "Unable to import.  File version not supported.")
 195 	cs (SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT, "Unable to import.  Incorrect privacy password.")
 196 	cs (SEC_ERROR_PKCS12_CERT_COLLISION, "Unable to import.  Same nickname already exists in database.")
 197 	cs (SEC_ERROR_USER_CANCELLED, "The user pressed cancel.")
 198 	cs (SEC_ERROR_PKCS12_DUPLICATE_DATA, "Not imported, already in database.")
 199 	cs (SEC_ERROR_MESSAGE_SEND_ABORTED, "Message not sent.")
 200 	cs (SEC_ERROR_INADEQUATE_KEY_USAGE, "Certificate key usage inadequate for attempted operation.")
 201 	cs (SEC_ERROR_INADEQUATE_CERT_TYPE, "Certificate type not approved for application.")
 202 	cs (SEC_ERROR_CERT_ADDR_MISMATCH, "Address in signing certificate does not match address in message headers.")
 203 	cs (SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY, "Unable to import.  Error attempting to import private key.")
 204 	cs (SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN, "Unable to import.  Error attempting to import certificate chain.")
 205 	cs (SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME, "Unable to export.  Unable to locate certificate or key by nickname.")
 206 	cs (SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY, "Unable to export.  Private Key could not be located and exported.")
 207 	cs (SEC_ERROR_PKCS12_UNABLE_TO_WRITE, "Unable to export.  Unable to write the export file.")
 208 	cs (SEC_ERROR_PKCS12_UNABLE_TO_READ, "Unable to import.  Unable to read the import file.")
 209 	cs (SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED, "Unable to export.  Key database corrupt or deleted.")
 210 	cs (SEC_ERROR_KEYGEN_FAIL, "Unable to generate public/private key pair.")
 211 	cs (SEC_ERROR_INVALID_PASSWORD, "Password entered is invalid.  Please pick a different one.")
 212 	cs (SEC_ERROR_RETRY_OLD_PASSWORD, "Old password entered incorrectly.  Please try again.")
 213 	cs (SEC_ERROR_BAD_NICKNAME, "Certificate nickname already in use.")
 214 	cs (SEC_ERROR_NOT_FORTEZZA_ISSUER, "Peer FORTEZZA chain has a non-FORTEZZA Certificate.")
 215 	cs (SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY, "A sensitive key cannot be moved to the slot where it is needed.")
 216 	cs (SEC_ERROR_JS_INVALID_MODULE_NAME, "Invalid module name.")
 217 	cs (SEC_ERROR_JS_INVALID_DLL, "Invalid module path/filename")
 218 	cs (SEC_ERROR_JS_ADD_MOD_FAILURE, "Unable to add module")
 219 	cs (SEC_ERROR_JS_DEL_MOD_FAILURE, "Unable to delete module")
 220 	cs (SEC_ERROR_OLD_KRL, "New KRL is not later than the current one.")
 221 	cs (SEC_ERROR_CKL_CONFLICT, "New CKL has different issuer than current CKL.  Delete current CKL.")
 222 	cs (SEC_ERROR_CERT_NOT_IN_NAME_SPACE, "The Certifying Authority for this certificate is not permitted to issue a certificate with this name.")
 223 	cs (SEC_ERROR_KRL_NOT_YET_VALID, "The key revocation list for this certificate is not yet valid.")
 224 	cs (SEC_ERROR_CRL_NOT_YET_VALID, "The certificate revocation list for this certificate is not yet valid.")
 225 	cs (SEC_ERROR_UNKNOWN_CERT, "The requested certificate could not be found.")
 226 	cs (SEC_ERROR_UNKNOWN_SIGNER, "The signer's certificate could not be found.")
 227 	cs (SEC_ERROR_CERT_BAD_ACCESS_LOCATION,	 "The location for the certificate status server has invalid format.")
 228 	cs (SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE, "The OCSP response cannot be fully decoded; it is of an unknown type.")
 229 	cs (SEC_ERROR_OCSP_BAD_HTTP_RESPONSE, "The OCSP server returned unexpected/invalid HTTP data.")
 230 	cs (SEC_ERROR_OCSP_MALFORMED_REQUEST, "The OCSP server found the request to be corrupted or improperly formed.")
 231 	cs (SEC_ERROR_OCSP_SERVER_ERROR, "The OCSP server experienced an internal error.")
 232 	cs (SEC_ERROR_OCSP_TRY_SERVER_LATER, "The OCSP server suggests trying again later.")
 233 	cs (SEC_ERROR_OCSP_REQUEST_NEEDS_SIG, "The OCSP server requires a signature on this request.")
 234 	cs (SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST, "The OCSP server has refused this request as unauthorized.")
 235 	cs (SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, "The OCSP server returned an unrecognizable status.")
 236 	cs (SEC_ERROR_OCSP_UNKNOWN_CERT, "The OCSP server has no status for the certificate.")
 237 	cs (SEC_ERROR_OCSP_NOT_ENABLED, "You must enable OCSP before performing this operation.")
 238 	cs (SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER, "You must set the OCSP default responder before performing this operation.")
 239 	cs (SEC_ERROR_OCSP_MALFORMED_RESPONSE, "The response from the OCSP server was corrupted or improperly formed.")
 240 	cs (SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE, "The signer of the OCSP response is not authorized to give status for this certificate.")
 241 	cs (SEC_ERROR_OCSP_FUTURE_RESPONSE, "The OCSP response is not yet valid (contains a date in the future).")
 242 	cs (SEC_ERROR_OCSP_OLD_RESPONSE, "The OCSP response contains out-of-date information.")
 243 	cs (SEC_ERROR_DIGEST_NOT_FOUND, "The CMS or PKCS #7 Digest was not found in signed message.")
 244 	cs (SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE, "The CMS or PKCS #7 Message type is unsupported.")
 245 	cs (SEC_ERROR_MODULE_STUCK, "PKCS #11 module could not be removed because it is still in use.")
 246 	cs (SEC_ERROR_BAD_TEMPLATE, "Could not decode ASN.1 data. Specified template was invalid.")
 247 	cs (SEC_ERROR_CRL_NOT_FOUND, "No matching CRL was found.")
 248 	cs (SEC_ERROR_REUSED_ISSUER_AND_SERIAL, "You are attempting to import a cert with the same issuer/serial as an existing cert, but that is not the same cert.")
 249 	cs (SEC_ERROR_BUSY, "NSS could not shutdown. Objects are still in use.")
 250 	cs (SEC_ERROR_EXTRA_INPUT, "DER-encoded message contained extra unused data.")
 251 	cs (SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE, "Unsupported elliptic curve.")
 252 	cs (SEC_ERROR_UNSUPPORTED_EC_POINT_FORM, "Unsupported elliptic curve point form.")
 253 	cs (SEC_ERROR_UNRECOGNIZED_OID, "Unrecognized Object Identifier.")
 254 	cs (SEC_ERROR_OCSP_INVALID_SIGNING_CERT, "Invalid OCSP signing certificate in OCSP response.")
 255 	cs (SEC_ERROR_REVOKED_CERTIFICATE_CRL, "Certificate is revoked in issuer's certificate revocation list.")
 256 	cs (SEC_ERROR_REVOKED_CERTIFICATE_OCSP, "Issuer's OCSP responder reports certificate is revoked.")
 257 	cs (SEC_ERROR_CRL_INVALID_VERSION, "Issuer's Certificate Revocation List has an unknown version number.")
 258 	cs (SEC_ERROR_CRL_V1_CRITICAL_EXTENSION, "Issuer's V1 Certificate Revocation List has a critical extension.")
 259 	cs (SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION, "Issuer's V2 Certificate Revocation List has an unknown critical extension.")
 260 	cs (SEC_ERROR_UNKNOWN_OBJECT_TYPE, "Unknown object type specified.")
 261 	cs (SEC_ERROR_INCOMPATIBLE_PKCS11, "PKCS #11 driver violates the spec in an incompatible way.")
 262 	cs (SEC_ERROR_NO_EVENT, "No new slot event is available at this time.")
 263 	cs (SEC_ERROR_CRL_ALREADY_EXISTS, "CRL already exists.")
 264 	cs (SEC_ERROR_NOT_INITIALIZED, "NSS is not initialized.")
 265 	cs (SEC_ERROR_TOKEN_NOT_LOGGED_IN, "The operation failed because the PKCS#11 token is not logged in.")
 266 	cs (SEC_ERROR_OCSP_RESPONDER_CERT_INVALID, "Configured OCSP responder's certificate is invalid.")
 267 	cs (SEC_ERROR_OCSP_BAD_SIGNATURE, "OCSP response has an invalid signature.")
 268 
 269 	#if defined (NSS_VMAJOR) && defined (NSS_VMINOR) && defined (NSS_VPATCH) && (NSS_VMAJOR > 3 || (NSS_VMAJOR == 3 && NSS_VMINOR > 12) || (NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH >= 2))
 270 	cs (SEC_ERROR_OUT_OF_SEARCH_LIMITS, "Cert validation search is out of search limits")
 271 	cs (SEC_ERROR_INVALID_POLICY_MAPPING, "Policy mapping contains anypolicy")
 272 	cs (SEC_ERROR_POLICY_VALIDATION_FAILED, "Cert chain fails policy validation")
 273 	cs (SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE, "Unknown location type in cert AIA extension")
 274 	cs (SEC_ERROR_BAD_HTTP_RESPONSE, "Server returned bad HTTP response")
 275 	cs (SEC_ERROR_BAD_LDAP_RESPONSE, "Server returned bad LDAP response")
 276 	cs (SEC_ERROR_FAILED_TO_ENCODE_DATA, "Failed to encode data with ASN1 encoder")
 277 	cs (SEC_ERROR_BAD_INFO_ACCESS_LOCATION, "Bad information access location in cert extension")
 278 	cs (SEC_ERROR_LIBPKIX_INTERNAL, "Libpkix internal error occured during cert validation.")
 279 	cs (SEC_ERROR_PKCS11_GENERAL_ERROR, "A PKCS #11 module returned CKR_GENERAL_ERROR, indicating that an unrecoverable error has occurred.")
 280 	cs (SEC_ERROR_PKCS11_FUNCTION_FAILED, "A PKCS #11 module returned CKR_FUNCTION_FAILED, indicating that the requested function could not be performed.  Trying the same operation again might succeed.")
 281 	cs (SEC_ERROR_PKCS11_DEVICE_ERROR, "A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot.")
 282 	#endif
 283 	}
 284 
 285 	#undef cs
 286 
 287 	return NULL;
 288 }
 289 
 290 static void
 291 set_nss_error (GError **error)
 292 {
 293 	glong err_code;
 294 	const gchar *err_str;
 295 
 296 	if (!error)
 297 		return;
 298 
 299 	g_return_if_fail (*error == NULL);
 300 
 301 	err_code = PORT_GetError ();
 302 
 303 	if (!err_code)
 304 		return;
 305 
 306 	err_str = nss_error_to_string (err_code);
 307 	if (!err_str)
 308 		return;
 309 
 310 	*error = g_error_new_literal (E_CERTDB_ERROR, err_code, err_str);
 311 }
 312 
 313 static SECStatus PR_CALLBACK
 314 collect_certs (gpointer arg,
 315                SECItem **certs,
 316                gint numcerts)
 317 {
 318 	CERTDERCerts *collectArgs;
 319 	SECItem *cert;
 320 	SECStatus rv;
 321 
 322 	collectArgs = (CERTDERCerts *) arg;
 323 
 324 	collectArgs->numcerts = numcerts;
 325 	collectArgs->rawCerts = (SECItem *) PORT_ArenaZAlloc (
 326 		collectArgs->arena, sizeof (SECItem) * numcerts);
 327 	if (collectArgs->rawCerts == NULL)
 328 		return (SECFailure);
 329 
 330 	cert = collectArgs->rawCerts;
 331 
 332 	while (numcerts--) {
 333 		rv = SECITEM_CopyItem (collectArgs->arena, cert, *certs);
 334 		if (rv == SECFailure)
 335 			return (SECFailure);
 336 		cert++;
 337 		certs++;
 338 	}
 339 
 340 	return (SECSuccess);
 341 }
 342 
 343 static CERTDERCerts *
 344 e_cert_db_get_certs_from_package (PRArenaPool *arena,
 345                                   gchar *data,
 346                                   guint32 length)
 347 {
 348 	/*nsNSSShutDownPreventionLock locker;*/
 349 	CERTDERCerts *collectArgs =
 350 		(CERTDERCerts *) PORT_ArenaZAlloc (arena, sizeof (CERTDERCerts));
 351 	SECStatus sec_rv;
 352 
 353 	if (!collectArgs)
 354 		return NULL;
 355 
 356 	collectArgs->arena = arena;
 357 	sec_rv = CERT_DecodeCertPackage (
 358 		data,
 359 					length, collect_certs,
 360 					(gpointer) collectArgs);
 361 
 362 	if (sec_rv != SECSuccess)
 363 		return NULL;
 364 
 365 	return collectArgs;
 366 }
 367 
 368 #ifdef notyet
 369 PRBool
 370 ucs2_ascii_conversion_fn (PRBool toUnicode,
 371                           guchar *inBuf,
 372                           guint inBufLen,
 373                           guchar *outBuf,
 374                           guint maxOutBufLen,
 375                           guint *outBufLen,
 376                           PRBool swapBytes)
 377 {
 378 	printf ("in ucs2_ascii_conversion_fn\n");
 379 }
 380 #endif
 381 
 382 static gchar * PR_CALLBACK
 383 pk11_password (PK11SlotInfo *slot,
 384                PRBool retry,
 385                gpointer arg)
 386 {
 387 	gchar *pwd;
 388 	gchar *nsspwd;
 389 
 390 	gboolean rv = FALSE;
 391 
 392 	g_signal_emit (
 393 		e_cert_db_peek (),
 394 		e_cert_db_signals[PK11_PASSWD], 0,
 395 		slot,
 396 		retry,
 397 		&pwd,
 398 		&rv);
 399 
 400 	if (pwd == NULL)
 401 		return NULL;
 402 
 403 	nsspwd = PORT_Strdup (pwd);
 404 	memset (pwd, 0, strlen (pwd));
 405 	g_free (pwd);
 406 	return nsspwd;
 407 }
 408 
 409 static void
 410 initialize_nss (void)
 411 {
 412 	/* Use camel_init() to initialise NSS consistently... */
 413 	camel_init (e_get_user_data_dir (), TRUE);
 414 
 415 	/* ... except for the bits we only seem to do here. FIXME */
 416 	PK11_SetPasswordFunc (pk11_password);
 417 
 418 	/* Enable ciphers for PKCS#12 */
 419 	SEC_PKCS12EnableCipher (PKCS12_RC4_40, 1);
 420 	SEC_PKCS12EnableCipher (PKCS12_RC4_128, 1);
 421 	SEC_PKCS12EnableCipher (PKCS12_RC2_CBC_40, 1);
 422 	SEC_PKCS12EnableCipher (PKCS12_RC2_CBC_128, 1);
 423 	SEC_PKCS12EnableCipher (PKCS12_DES_56, 1);
 424 	SEC_PKCS12EnableCipher (PKCS12_DES_EDE3_168, 1);
 425 	SEC_PKCS12SetPreferredCipher (PKCS12_DES_EDE3_168, 1);
 426 #ifdef notyet
 427 	PORT_SetUCS2_ASCIIConversionFunction (ucs2_ascii_conversion_fn);
 428 #endif
 429 }
 430 
 431 static void
 432 install_loadable_roots (void)
 433 {
 434 	SECMODModuleList *list = SECMOD_GetDefaultModuleList ();
 435 	SECMODListLock *lock = SECMOD_GetDefaultModuleListLock ();
 436 	SECMODModule *RootsModule = NULL;
 437 	gint i;
 438 
 439 	SECMOD_GetReadLock (lock);
 440 	while (!RootsModule && list) {
 441 		SECMODModule *module = list->module;
 442 
 443 		for (i = 0; i < module->slotCount; i++) {
 444 			PK11SlotInfo *slot = module->slots[i];
 445 			if (PK11_IsPresent (slot)) {
 446 				if (PK11_HasRootCerts (slot)) {
 447 					RootsModule = module;
 448 					break;
 449 				}
 450 			}
 451 		}
 452 
 453 		list = list->next;
 454 	}
 455 	SECMOD_ReleaseReadLock (lock);
 456 
 457 	if (RootsModule) {
 458 		/* Check version, and unload module if it is too old */
 459 		CK_INFO info;
 460 
 461 		if (PK11_GetModInfo (RootsModule, &info) != SECSuccess) {
 462 			/* Do not use this module */
 463 			RootsModule = NULL;
 464 		} else {
 465 			/* NSS_BUILTINS_LIBRARY_VERSION_MAJOR and NSS_BUILTINS_LIBRARY_VERSION_MINOR
 466 			 * define the version we expect to have.
 467 			 * Later version are fine.
 468 			 * Older versions are not ok, and we will replace with our own version.
 469 			 */
 470 			if ((info.libraryVersion.major < NSS_BUILTINS_LIBRARY_VERSION_MAJOR)
 471 			    || (info.libraryVersion.major == NSS_BUILTINS_LIBRARY_VERSION_MAJOR
 472 				&& info.libraryVersion.minor < NSS_BUILTINS_LIBRARY_VERSION_MINOR)) {
 473 				PRInt32 modType;
 474 
 475 				SECMOD_DeleteModule (RootsModule->commonName, &modType);
 476 
 477 				RootsModule = NULL;
 478 			}
 479 		}
 480 	}
 481 
 482 	if (!RootsModule) {
 483 #ifndef G_OS_WIN32
 484 		/* grovel in various places for mozilla's built-in
 485 		 * cert module.
 486 		 *
 487 		 * XXX yes this is gross.  *sigh *
 488 		*/
 489 		const gchar *paths_to_check[] = {
 490 #ifdef MOZILLA_NSS_LIB_DIR
 491 			MOZILLA_NSS_LIB_DIR,
 492 #endif
 493 			"/usr/lib",
 494 			"/usr/lib/mozilla",
 495 			"/opt/mozilla/lib",
 496 			"/opt/mozilla/lib/mozilla"
 497 		};
 498 
 499 		for (i = 0; i < G_N_ELEMENTS (paths_to_check); i++) {
 500 			gchar *dll_path = g_module_build_path (paths_to_check[i], "nssckbi");
 501 
 502 			if (g_file_test (dll_path, G_FILE_TEST_EXISTS)) {
 503 				PRInt32 modType;
 504 
 505 				/* Delete the existing module */
 506 				SECMOD_DeleteModule ("Mozilla Root Certs", &modType);
 507 
 508 				SECMOD_AddNewModule ("Mozilla Root Certs",dll_path, 0, 0);
 509 				g_free (dll_path);
 510 				break;
 511 			}
 512 
 513 			g_free (dll_path);
 514 		}
 515 #else
 516 		/* FIXME: Might be useful to look up if there is a
 517 		 * Mozilla installation on the machine and use the
 518 		 * nssckbi.dll from there.
 519 		 */
 520 #endif
 521 	}
 522 }
 523 
 524 static void
 525 e_cert_db_class_init (ECertDBClass *class)
 526 {
 527 	GObjectClass *object_class;
 528 
 529 	object_class = G_OBJECT_CLASS (class);
 530 
 531 	initialize_nss ();
 532 	/* check to see if you have a rootcert module installed */
 533 	install_loadable_roots ();
 534 
 535 	e_cert_db_signals[PK11_PASSWD] = g_signal_new (
 536 		"pk11_passwd",
 537 		G_OBJECT_CLASS_TYPE (object_class),
 538 		G_SIGNAL_RUN_LAST,
 539 		G_STRUCT_OFFSET (ECertDBClass, pk11_passwd),
 540 		NULL, NULL,
 541 		e_marshal_BOOLEAN__POINTER_BOOLEAN_POINTER,
 542 		G_TYPE_BOOLEAN, 3,
 543 		G_TYPE_POINTER, G_TYPE_BOOLEAN, G_TYPE_POINTER);
 544 
 545 	e_cert_db_signals[PK11_CHANGE_PASSWD] = g_signal_new (
 546 		"pk11_change_passwd",
 547 		G_OBJECT_CLASS_TYPE (object_class),
 548 		G_SIGNAL_RUN_LAST,
 549 		G_STRUCT_OFFSET (ECertDBClass, pk11_change_passwd),
 550 		NULL, NULL,
 551 		e_marshal_BOOLEAN__POINTER_POINTER,
 552 		G_TYPE_BOOLEAN, 2,
 553 		G_TYPE_POINTER, G_TYPE_POINTER);
 554 
 555 	e_cert_db_signals[CONFIRM_CA_CERT_IMPORT] = g_signal_new (
 556 		"confirm_ca_cert_import",
 557 		G_OBJECT_CLASS_TYPE (object_class),
 558 		G_SIGNAL_RUN_LAST,
 559 		G_STRUCT_OFFSET (ECertDBClass, confirm_ca_cert_import),
 560 		NULL, NULL,
 561 		e_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER,
 562 		G_TYPE_BOOLEAN, 4,
 563 		G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER);
 564 }
 565 
 566 static void
 567 e_cert_db_init (ECertDB *ec)
 568 {
 569 }
 570 
 571 GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
 572 static ECertDB *cert_db = NULL;
 573 
 574 ECertDB *
 575 e_cert_db_peek (void)
 576 {
 577 	g_static_mutex_lock (&init_mutex);
 578 	if (!cert_db)
 579 		cert_db = g_object_new (E_TYPE_CERT_DB, NULL);
 580 	g_static_mutex_unlock (&init_mutex);
 581 
 582 	return cert_db;
 583 }
 584 
 585 void
 586 e_cert_db_shutdown (void)
 587 {
 588 	/* XXX */
 589 }
 590 
 591 /* searching for certificates */
 592 ECert *
 593 e_cert_db_find_cert_by_nickname (ECertDB *certdb,
 594                                  const gchar *nickname,
 595                                  GError **error)
 596 {
 597 	/*  nsNSSShutDownPreventionLock locker;*/
 598 	CERTCertificate *cert = NULL;
 599 
 600 	/*PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Getting \"%s\"\n", asciiname));*/
 601 	cert = PK11_FindCertFromNickname ((gchar *) nickname, NULL);
 602 	if (!cert) {
 603 		cert = CERT_FindCertByNickname (CERT_GetDefaultCertDB (), (gchar *) nickname);
 604 	}
 605 
 606 	if (cert) {
 607 		/*    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("got it\n"));*/
 608 		ECert *ecert = e_cert_new (cert);
 609 		return ecert;
 610 	}
 611 	else {
 612 		set_nss_error (error);
 613 		return NULL;
 614 	}
 615 }
 616 
 617 #ifdef notyet
 618 ECert *
 619 e_cert_db_find_cert_by_key (ECertDB *certdb,
 620                             const gchar *db_key,
 621                             GError **error)
 622 {
 623 	/*  nsNSSShutDownPreventionLock locker;*/
 624 	SECItem keyItem = {siBuffer, NULL, 0};
 625 	SECItem *dummy;
 626 	CERTIssuerAndSN issuerSN;
 627 	gulong moduleID,slotID;
 628 	CERTCertificate *cert;
 629 
 630 	if (!db_key) {
 631 		set_nss_error (error);
 632 		return NULL;
 633 	}
 634 
 635 	dummy = NSSBase64_DecodeBuffer (
 636 		NULL, &keyItem, db_key,
 637 		(PRUint32) PL_strlen (db_key));
 638 
 639 	/* someday maybe we can speed up the search using the moduleID and slotID*/
 640 	moduleID = NS_NSS_GET_LONG (keyItem.data);
 641 	slotID = NS_NSS_GET_LONG (&keyItem.data[NS_NSS_LONG]);
 642 
 643 	/* build the issuer/SN structure*/
 644 	issuerSN.serialNumber.len = NS_NSS_GET_LONG (&keyItem.data[NS_NSS_LONG *2]);
 645 	issuerSN.derIssuer.len = NS_NSS_GET_LONG (&keyItem.data[NS_NSS_LONG *3]);
 646 	issuerSN.serialNumber.data= &keyItem.data[NS_NSS_LONG *4];
 647 	issuerSN.derIssuer.data= &keyItem.data[NS_NSS_LONG *4+
 648 					       issuerSN.serialNumber.len];
 649 
 650 	cert = CERT_FindCertByIssuerAndSN (CERT_GetDefaultCertDB (), &issuerSN);
 651 	PR_FREEIF (keyItem.data);
 652 	if (cert) {
 653 		ECert *ecert = e_cert_new (cert);
 654 		return e_cert;
 655 	}
 656 
 657 	set_nss_error (error);
 658 	return NULL;
 659 }
 660 
 661 GList *
 662 e_cert_db_get_cert_nicknames (ECertDB *certdb,
 663                               ECertType cert_type,
 664                               GError **error)
 665 {
 666 }
 667 
 668 ECert *
 669 e_cert_db_find_email_encryption_cert (ECertDB *certdb,
 670                                       const gchar *nickname,
 671                                       GError **error)
 672 {
 673 }
 674 
 675 ECert *
 676 e_cert_db_find_email_signing_cert (ECertDB *certdb,
 677                                    const gchar *nickname,
 678                                    GError **error)
 679 {
 680 }
 681 #endif
 682 
 683 ECert *
 684 e_cert_db_find_cert_by_email_address (ECertDB *certdb,
 685                                       const gchar *email,
 686                                       GError **error)
 687 {
 688 	/*  nsNSSShutDownPreventionLock locker; */
 689 	ECert *cert;
 690 	CERTCertificate *any_cert;
 691 	CERTCertList *certlist;
 692 
 693 	any_cert = CERT_FindCertByNicknameOrEmailAddr (
 694 		CERT_GetDefaultCertDB (), (gchar *) email);
 695 
 696 	if (!any_cert) {
 697 		set_nss_error (error);
 698 		return NULL;
 699 	}
 700 
 701 	/* any_cert now contains a cert with the right subject,
 702 	 * but it might not have the correct usage. */
 703 	certlist = CERT_CreateSubjectCertList (
 704 		NULL,
 705 		CERT_GetDefaultCertDB (),
 706 		&any_cert->derSubject,
 707 		PR_Now (), PR_TRUE);
 708 	if (!certlist) {
 709 		set_nss_error (error);
 710 		CERT_DestroyCertificate (any_cert);
 711 		return NULL;
 712 	}
 713 
 714 	if (SECSuccess != CERT_FilterCertListByUsage (
 715 		certlist, certUsageEmailRecipient, PR_FALSE)) {
 716 		set_nss_error (error);
 717 		CERT_DestroyCertificate (any_cert);
 718 		CERT_DestroyCertList (certlist);
 719 		return NULL;
 720 	}
 721 
 722 	if (CERT_LIST_END (CERT_LIST_HEAD (certlist), certlist)) {
 723 		set_nss_error (error);
 724 		CERT_DestroyCertificate (any_cert);
 725 		CERT_DestroyCertList (certlist);
 726 		return NULL;
 727 	}
 728 
 729 	cert = e_cert_new (CERT_DupCertificate (CERT_LIST_HEAD (certlist)->cert));
 730 
 731 	CERT_DestroyCertList (certlist);
 732 	CERT_DestroyCertificate (any_cert);
 733 
 734 	return cert;
 735 }
 736 
 737 static gboolean
 738 confirm_download_ca_cert (ECertDB *cert_db,
 739                           ECert *cert,
 740                           gboolean *trust_ssl,
 741                           gboolean *trust_email,
 742                           gboolean *trust_objsign)
 743 {
 744 	gboolean rv = FALSE;
 745 
 746 	*trust_ssl =
 747 		*trust_email =
 748 		*trust_objsign = FALSE;
 749 
 750 	g_signal_emit (
 751 		e_cert_db_peek (),
 752 		e_cert_db_signals[CONFIRM_CA_CERT_IMPORT], 0,
 753 		cert,
 754 		trust_ssl,
 755 		trust_email,
 756 		trust_objsign,
 757 		&rv);
 758 
 759 	return rv;
 760 }
 761 
 762 static gboolean
 763 handle_ca_cert_download (ECertDB *cert_db,
 764                          GList *certs,
 765                          GError **error)
 766 {
 767 	ECert *certToShow;
 768 	SECItem der;
 769 	gchar *raw_der = NULL;
 770 	CERTCertificate *tmpCert;
 771 
 772 	/* First thing we have to do is figure out which certificate
 773 	 * we're gonna present to the user.  The CA may have sent down
 774 	 * a list of certs which may or may not be a chained list of
 775 	 * certs.  Until the day we can design some solid UI for the
 776 	 * general case, we'll code to the > 90% case.  That case is
 777 	 * where a CA sends down a list that is a chain up to its root
 778 	 * in either ascending or descending order.  What we're gonna
 779 	 * do is compare the first 2 entries, if the first was signed
 780 	 * by the second, we assume the leaf cert is the first cert
 781 	 * and display it.  If the second cert was signed by the first
 782 	 * cert, then we assume the first cert is the root and the
 783 	 * last cert in the array is the leaf.  In this case we
 784 	 * display the last cert.
 785 	*/
 786 
 787 	/*  nsNSSShutDownPreventionLock locker;*/
 788 
 789 	if (certs == NULL) {
 790 		g_warning ("Didn't get any certs to import.");
 791 		return TRUE;
 792 	}
 793 	else if (certs->next == NULL) {
 794 		/* there's 1 cert */
 795 		certToShow = E_CERT (certs->data);
 796 	}
 797 	else {
 798 		/* there are multiple certs */
 799 		ECert *cert0;
 800 		ECert *cert1;
 801 		const gchar * cert0SubjectName;
 802 		const gchar * cert0IssuerName;
 803 		const gchar * cert1SubjectName;
 804 		const gchar * cert1IssuerName;
 805 
 806 		cert0 = E_CERT (certs->data);
 807 		cert1 = E_CERT (certs->next->data);
 808 
 809 		cert0IssuerName = e_cert_get_issuer_name (cert0);
 810 		cert0SubjectName = e_cert_get_subject_name (cert0);
 811 
 812 		cert1IssuerName = e_cert_get_issuer_name (cert1);
 813 		cert1SubjectName = e_cert_get_subject_name (cert1);
 814 
 815 		if (!strcmp (cert1IssuerName, cert0SubjectName)) {
 816 			/* In this case, the first cert in the list signed the second,
 817 			 * so the first cert is the root.  Let's display the last cert
 818 			 * in the list. */
 819 			certToShow = E_CERT (g_list_last (certs)->data);
 820 		}
 821 		else if (!strcmp (cert0IssuerName, cert1SubjectName)) {
 822 			/* In this case the second cert has signed the first cert.  The
 823 			 * first cert is the leaf, so let's display it. */
 824 			certToShow = cert0;
 825 		} else {
 826 			/* It's not a chain, so let's just show the first one in the
 827 			 * downloaded list. */
 828 			certToShow = cert0;
 829 		}
 830 	}
 831 
 832 	if (!certToShow) {
 833 		set_nss_error (error);
 834 		return FALSE;
 835 	}
 836 
 837 	if (!e_cert_get_raw_der (certToShow, &raw_der, &der.len)) {
 838 		set_nss_error (error);
 839 		return FALSE;
 840 	}
 841 
 842 	der.data = (guchar *) raw_der;
 843 
 844 	{
 845 		/*PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Creating temp cert\n"));*/
 846 		CERTCertDBHandle *certdb = CERT_GetDefaultCertDB ();
 847 		tmpCert = CERT_FindCertByDERCert (certdb, &der);
 848 		if (!tmpCert) {
 849 			tmpCert = CERT_NewTempCertificate (
 850 				certdb, &der,
 851 				NULL, PR_FALSE, PR_TRUE);
 852 		}
 853 		if (!tmpCert) {
 854 			g_warning ("Couldn't create cert from DER blob");
 855 			set_nss_error (error);
 856 			return FALSE;
 857 		}
 858 	}
 859 
 860 #if 0
 861 	CERTCertificateCleaner tmpCertCleaner (tmpCert);
 862 #endif
 863 
 864 	if (tmpCert->isperm) {
 865 		if (error && !*error)
 866 			*error = g_error_new_literal (E_CERTDB_ERROR, 0, _("Certificate already exists"));
 867 		return FALSE;
 868 	}
 869 	else {
 870 		gboolean trust_ssl, trust_email, trust_objsign;
 871 		gchar *nickname;
 872 		SECStatus srv;
 873 		CERTCertTrust trust;
 874 
 875 		if (!confirm_download_ca_cert (
 876 			cert_db, certToShow, &trust_ssl,
 877 			&trust_email, &trust_objsign)) {
 878 			set_nss_error (error);
 879 			return FALSE;
 880 		}
 881 
 882 		/*PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("trust is %d\n", trustBits));*/
 883 
 884 		nickname = CERT_MakeCANickname (tmpCert);
 885 
 886 		/*PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Created nick \"%s\"\n", nickname.get()));*/
 887 
 888 		e_cert_trust_init (&trust);
 889 		e_cert_trust_set_valid_ca (&trust);
 890 		e_cert_trust_add_ca_trust (
 891 			&trust,
 892 			trust_ssl,
 893 			trust_email,
 894 			trust_objsign);
 895 
 896 		srv = CERT_AddTempCertToPerm (
 897 			tmpCert,
 898 			nickname,
 899 			&trust);
 900 
 901 		/* If we aren't logged into the token, then what *should*
 902 		 * happen is the above call should fail, and we should
 903 		 * authenticate and then try again. But see NSS bug #595861.
 904 		 * With NSS 3.12.6 at least, the above call will fail, but
 905 		 * it *will* have added the cert to the database, with
 906 		 * random trust bits. We have to authenticate and then set
 907 		 * the trust bits correctly. And calling
 908 		 * CERT_AddTempCertToPerm() again doesn't work either -- it'll
 909 		 * fail even though it arguably ought to succeed (which is
 910 		 * probably another NSS bug).
 911 		 * So if we get SEC_ERROR_TOKEN_NOT_LOGGED_IN, we first try
 912 		 * CERT_ChangeCertTrust(), and if that doesn't work we hope
 913 		 * we're on a fixed version of NSS and we try calling
 914 		 * CERT_AddTempCertToPerm() again instead. */
 915 		if (srv != SECSuccess &&
 916 		    PORT_GetError () == SEC_ERROR_TOKEN_NOT_LOGGED_IN &&
 917 		    e_cert_db_login_to_slot (NULL, PK11_GetInternalKeySlot ())) {
 918 			srv = CERT_ChangeCertTrust (
 919 				CERT_GetDefaultCertDB (),
 920 				tmpCert, &trust);
 921 			if (srv != SECSuccess)
 922 				srv = CERT_AddTempCertToPerm (
 923 					tmpCert,
 924 					nickname,
 925 					&trust);
 926 		}
 927 		if (srv != SECSuccess) {
 928 			set_nss_error (error);
 929 			return FALSE;
 930 		}
 931 
 932 #if 0
 933 		/* Now it's time to add the rest of the certs we just downloaded.
 934 		 * Since we didn't prompt the user about any of these certs, we
 935 		 * won't set any trust bits for them. */
 936 		e_cert_trust_init (&trust);
 937 		e_cert_trust_set_valid_ca (&trust);
 938 		e_cert_trusts_add_ca_trust (&trust, 0, 0, 0);
 939 		for (PRUint32 i = 0; i < numCerts; i++) {
 940 			if (i == selCertIndex)
 941 				continue;
 942 
 943 			certToShow = do_QueryElementAt (x509Certs, i);
 944 			certToShow->GetRawDER (&der.len, (PRUint8 **) &der.data);
 945 
 946 			CERTCertificate *tmpCert2 =
 947 				CERT_NewTempCertificate (certdb, &der, nsnull, PR_FALSE, PR_TRUE);
 948 
 949 			if (!tmpCert2) {
 950 				NS_ASSERTION (0, "Couldn't create temp cert from DER blob\n");
 951 				continue;  /* Let's try to import the rest of 'em */
 952 			}
 953 			nickname.Adopt (CERT_MakeCANickname (tmpCert2));
 954 			CERT_AddTempCertToPerm (
 955 				tmpCert2, NS_CONST_CAST (gchar *,nickname.get ()),
 956 				defaultTrust.GetTrust ());
 957 			CERT_DestroyCertificate (tmpCert2);
 958 		}
 959 #endif
 960 		return TRUE;
 961 	}
 962 }
 963 gboolean e_cert_db_change_cert_trust (CERTCertificate *cert, CERTCertTrust *trust)
 964 {
 965 	SECStatus srv;
 966 
 967 	srv = CERT_ChangeCertTrust (
 968 		CERT_GetDefaultCertDB (),
 969 		cert, trust);
 970 	if (srv != SECSuccess &&
 971 	    PORT_GetError () == SEC_ERROR_TOKEN_NOT_LOGGED_IN &&
 972 	    e_cert_db_login_to_slot (NULL, PK11_GetInternalKeySlot ()))
 973 		srv = CERT_ChangeCertTrust (
 974 			CERT_GetDefaultCertDB (),
 975 			cert, trust);
 976 
 977 	if (srv != SECSuccess) {
 978 		glong err = PORT_GetError ();
 979 		g_warning (
 980 			"CERT_ChangeCertTrust() failed: %s\n",
 981 			nss_error_to_string (err));
 982 		return FALSE;
 983 	}
 984 	return TRUE;
 985 }
 986 
 987 /* deleting certificates */
 988 gboolean
 989 e_cert_db_delete_cert (ECertDB *certdb,
 990                        ECert *ecert)
 991 {
 992 	/*  nsNSSShutDownPreventionLock locker;
 993 	 *  nsNSSCertificate *nssCert = NS_STATIC_CAST (nsNSSCertificate *, aCert); */
 994 
 995 	CERTCertificate *cert;
 996 
 997 	if (!e_cert_mark_for_deletion (ecert)) {
 998 		return FALSE;
 999 	}
1000 
1001 	cert = e_cert_get_internal_cert (ecert);
1002 	if (cert->slot && e_cert_get_cert_type (ecert) != E_CERT_USER) {
1003 		/* To delete a cert of a slot (builtin, most likely), mark it as
1004 		 * completely untrusted.  This way we keep a copy cached in the
1005 		 * local database, and next time we try to load it off of the
1006 		 * external token/slot, we'll know not to trust it.  We don't
1007 		 * want to do that with user certs, because a user may  re-store
1008 		 * the cert onto the card again at which point we *will* want to
1009 		 * trust that cert if it chains up properly. */
1010 		CERTCertTrust trust;
1011 
1012 		e_cert_trust_init_with_values (&trust, 0, 0, 0);
1013 		return e_cert_db_change_cert_trust (cert, &trust);
1014 	}
1015 
1016 	return TRUE;
1017 }
1018 
1019 /* importing certificates */
1020 gboolean
1021 e_cert_db_import_certs (ECertDB *certdb,
1022                         gchar *data,
1023                         guint32 length,
1024                         ECertType cert_type,
1025                         GSList **imported_certs,
1026                         GError **error)
1027 {
1028 	/*nsNSSShutDownPreventionLock locker;*/
1029 	PRArenaPool *arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
1030 	GList *certs = NULL;
1031 	CERTDERCerts *certCollection = e_cert_db_get_certs_from_package (arena, data, length);
1032 	gint i;
1033 	gboolean rv;
1034 
1035 	if (!certCollection) {
1036 		set_nss_error (error);
1037 		PORT_FreeArena (arena, PR_FALSE);
1038 		return FALSE;
1039 	}
1040 
1041 	/* Now let's create some certs to work with */
1042 	for (i = 0; i < certCollection->numcerts; i++) {
1043 		SECItem *currItem = &certCollection->rawCerts[i];
1044 		ECert *cert;
1045 
1046 		cert = e_cert_new_from_der ((gchar *) currItem->data, currItem->len);
1047 		if (!cert) {
1048 			set_nss_error (error);
1049 			g_list_foreach (certs, (GFunc) g_object_unref, NULL);
1050 			g_list_free (certs);
1051 			PORT_FreeArena (arena, PR_FALSE);
1052 			return FALSE;
1053 		}
1054 		certs = g_list_append (certs, cert);
1055 	}
1056 	switch (cert_type) {
1057 	case E_CERT_CA:
1058 		rv = handle_ca_cert_download (certdb, certs, error);
1059 		if (rv && imported_certs) {
1060 			GList *l;
1061 
1062 			/* copy certificates to the caller */
1063 			*imported_certs = NULL;
1064 			for (l = certs; l; l = l->next) {
1065 				ECert *cert = l->data;
1066 
1067 				if (cert)
1068 					*imported_certs = g_slist_prepend (*imported_certs, g_object_ref (cert));
1069 			}
1070 
1071 			*imported_certs = g_slist_reverse (*imported_certs);
1072 		}
1073 		break;
1074 	default:
1075 		/* We only deal with import CA certs in this method currently.*/
1076 		set_nss_error (error);
1077 		PORT_FreeArena (arena, PR_FALSE);
1078 		rv = FALSE;
1079 	}
1080 
1081 	g_list_foreach (certs, (GFunc) g_object_unref, NULL);
1082 	g_list_free (certs);
1083 	PORT_FreeArena (arena, PR_FALSE);
1084 	return rv;
1085 }
1086 
1087 gboolean
1088 e_cert_db_import_email_cert (ECertDB *certdb,
1089                              gchar *data,
1090                              guint32 length,
1091                              GSList **imported_certs,
1092                              GError **error)
1093 {
1094 	/*nsNSSShutDownPreventionLock locker;*/
1095 	SECStatus srv = SECFailure;
1096 	gboolean rv = TRUE;
1097 	CERTCertificate * cert;
1098 	SECItem **rawCerts;
1099 	gint numcerts;
1100 	gint i;
1101 	PRArenaPool *arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
1102 	CERTDERCerts *certCollection = e_cert_db_get_certs_from_package (arena, data, length);
1103 
1104 	if (!certCollection) {
1105 		set_nss_error (error);
1106 		PORT_FreeArena (arena, PR_FALSE);
1107 		return FALSE;
1108 	}
1109 
1110 	cert = CERT_NewTempCertificate (
1111 		CERT_GetDefaultCertDB (), certCollection->rawCerts,
1112 		(gchar *) NULL, PR_FALSE, PR_TRUE);
1113 	if (!cert) {
1114 		set_nss_error (error);
1115 		rv = FALSE;
1116 		goto loser;
1117 	}
1118 	numcerts = certCollection->numcerts;
1119 	rawCerts = (SECItem **) PORT_Alloc (sizeof (SECItem *) * numcerts);
1120 	if (!rawCerts) {
1121 		set_nss_error (error);
1122 		rv = FALSE;
1123 		goto loser;
1124 	}
1125 
1126 	for (i = 0; i < numcerts; i++) {
1127 		rawCerts[i] = &certCollection->rawCerts[i];
1128 	}
1129 
1130 	srv = CERT_ImportCerts (
1131 		CERT_GetDefaultCertDB (), certUsageEmailSigner,
1132 		numcerts, rawCerts, NULL, PR_TRUE, PR_FALSE,
1133 		NULL);
1134 	if (srv != SECSuccess) {
1135 		set_nss_error (error);
1136 		rv = FALSE;
1137 		goto loser;
1138 	}
1139 	CERT_SaveSMimeProfile (cert, NULL, NULL);
1140 
1141 	if (imported_certs) {
1142 		*imported_certs = NULL;
1143 		for (i = 0; i < certCollection->numcerts; i++) {
1144 			SECItem *currItem = &certCollection->rawCerts[i];
1145 			ECert *cert;
1146 
1147 			cert = e_cert_new_from_der ((gchar *) currItem->data, currItem->len);
1148 			if (cert)
1149 				*imported_certs = g_slist_prepend (*imported_certs, cert);
1150 		}
1151 
1152 		*imported_certs = g_slist_reverse (*imported_certs);
1153 	}
1154 
1155 	PORT_Free (rawCerts);
1156  loser:
1157 	if (cert)
1158 		CERT_DestroyCertificate (cert);
1159 	if (arena)
1160 		PORT_FreeArena (arena, PR_TRUE);
1161 	return rv;
1162 }
1163 
1164 static gchar *
1165 default_nickname (CERTCertificate *cert)
1166 {
1167 	/*  nsNSSShutDownPreventionLock locker; */
1168 	gchar *username = NULL;
1169 	gchar *caname = NULL;
1170 	gchar *nickname = NULL;
1171 	gchar *tmp = NULL;
1172 	gint count;
1173 	const gchar *nickFmt = NULL;
1174 	CERTCertificate *dummycert;
1175 	PK11SlotInfo *slot = NULL;
1176 	CK_OBJECT_HANDLE keyHandle;
1177 
1178 	CERTCertDBHandle *defaultcertdb = CERT_GetDefaultCertDB ();
1179 
1180 	username = CERT_GetCommonName (&cert->subject);
1181 	if (username == NULL)
1182 		username = PL_strdup ("");
1183 
1184 	if (username == NULL)
1185 		goto loser;
1186 
1187 	caname = CERT_GetOrgName (&cert->issuer);
1188 	if (caname == NULL)
1189 		caname = PL_strdup ("");
1190 
1191 	if (caname == NULL)
1192 		goto loser;
1193 
1194 	count = 1;
1195 
1196 	nickFmt = "%1$s's %2$s ID";
1197 
1198 	nickname = PR_smprintf (nickFmt, username, caname);
1199 	/*
1200 	 * We need to see if the private key exists on a token, if it does
1201 	 * then we need to check for nicknames that already exist on the smart
1202 	 * card.
1203 	 */
1204 	slot = PK11_KeyForCertExists (cert, &keyHandle, NULL);
1205 	if (slot == NULL) {
1206 		goto loser;
1207 	}
1208 	if (!PK11_IsInternal (slot)) {
1209 		tmp = PR_smprintf ("%s:%s", PK11_GetTokenName (slot), nickname);
1210 		PR_Free (nickname);
1211 		nickname = tmp;
1212 		tmp = NULL;
1213 	}
1214 	tmp = nickname;
1215 	while (1) {
1216 		if (count > 1) {
1217 			nickname = PR_smprintf ("%s #%d", tmp, count);
1218 		}
1219 
1220 		if (nickname == NULL)
1221 			goto loser;
1222 
1223 		if (PK11_IsInternal (slot)) {
1224 			/* look up the nickname to make sure it isn't in use already */
1225 			dummycert = CERT_FindCertByNickname (defaultcertdb, nickname);
1226 
1227 		} else {
1228 			/*
1229 			 * Check the cert against others that already live on the smart
1230 			 * card.
1231 			 */
1232 			dummycert = PK11_FindCertFromNickname (nickname, NULL);
1233 			if (dummycert != NULL) {
1234 				/*
1235 				 * Make sure the subject names are different.
1236 				 */
1237 				if (CERT_CompareName (&cert->subject, &dummycert->subject) == SECEqual) {
1238 					/*
1239 					 * There is another certificate with the same nickname and
1240 					 * the same subject name on the smart card, so let's use this
1241 					 * nickname.
1242 					 */
1243 					CERT_DestroyCertificate (dummycert);
1244 					dummycert = NULL;
1245 				}
1246 			}
1247 		}
1248 		if (dummycert == NULL)
1249 			goto done;
1250 
1251 		/* found a cert, destroy it and loop */
1252 		CERT_DestroyCertificate (dummycert);
1253 		if (tmp != nickname) PR_Free (nickname);
1254 		count++;
1255 	} /* end of while (1) */
1256 
1257  loser:
1258 	if (nickname) {
1259 		PR_Free (nickname);
1260 	}
1261 	nickname = NULL;
1262  done:
1263 	if (caname) {
1264 		PR_Free (caname);
1265 	}
1266 	if (username)  {
1267 		PR_Free (username);
1268 	}
1269 	if (slot != NULL) {
1270 		PK11_FreeSlot (slot);
1271 		if (nickname != NULL) {
1272 			tmp = nickname;
1273 			nickname = strchr (tmp, ':');
1274 			if (nickname != NULL) {
1275 				nickname++;
1276 				nickname = PL_strdup (nickname);
1277 				PR_Free (tmp);
1278 				tmp = NULL;
1279 			} else {
1280 				nickname = tmp;
1281 				tmp = NULL;
1282 			}
1283 		}
1284 	}
1285 	PR_FREEIF (tmp);
1286 	return (nickname);
1287 }
1288 
1289 gboolean
1290 e_cert_db_import_user_cert (ECertDB *certdb,
1291                             gchar *data,
1292                             guint32 length,
1293                             GError **error)
1294 {
1295 	/*  nsNSSShutDownPreventionLock locker;*/
1296 	PK11SlotInfo *slot;
1297 	gchar * nickname = NULL;
1298 	gboolean rv = FALSE;
1299 	gint numCACerts;
1300 	SECItem *CACerts;
1301 	CERTDERCerts * collectArgs;
1302 	PRArenaPool *arena;
1303 	CERTCertificate * cert = NULL;
1304 
1305 	arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
1306 	if (arena == NULL) {
1307 		set_nss_error (error);
1308 		goto loser;
1309 	}
1310 
1311 	collectArgs = e_cert_db_get_certs_from_package (arena, data, length);
1312 	if (!collectArgs) {
1313 		set_nss_error (error);
1314 		goto loser;
1315 	}
1316 
1317 	cert = CERT_NewTempCertificate (
1318 		CERT_GetDefaultCertDB (), collectArgs->rawCerts,
1319 		(gchar *) NULL, PR_FALSE, PR_TRUE);
1320 	if (!cert) {
1321 		set_nss_error (error);
1322 		goto loser;
1323 	}
1324 
1325 	slot = PK11_KeyForCertExists (cert, NULL, NULL);
1326 	if (slot == NULL) {
1327 		set_nss_error (error);
1328 		goto loser;
1329 	}
1330 	PK11_FreeSlot (slot);
1331 
1332 	/* pick a nickname for the cert */
1333 	if (cert->nickname) {
1334 		/* sigh, we need a call to look up other certs with this subject and
1335 		 * identify nicknames from them. We can no longer walk down internal
1336 		 * database structures  rjr */
1337 		nickname = cert->nickname;
1338 	}
1339 	else {
1340 		nickname = default_nickname (cert);
1341 	}
1342 
1343 	/* user wants to import the cert */
1344 	slot = PK11_ImportCertForKey (cert, nickname, NULL);
1345 	if (!slot) {
1346 		set_nss_error (error);
1347 		goto loser;
1348 	}
1349 	PK11_FreeSlot (slot);
1350 	numCACerts = collectArgs->numcerts - 1;
1351 
1352 	if (numCACerts) {
1353 		CACerts = collectArgs->rawCerts + 1;
1354 		if (!CERT_ImportCAChain (CACerts, numCACerts, certUsageUserCertImport)) {
1355 			rv = TRUE;
1356 		}
1357 	}
1358 
1359  loser:
1360 	if (arena) {
1361 		PORT_FreeArena (arena, PR_FALSE);
1362 	}
1363 	if (cert) {
1364 		CERT_DestroyCertificate (cert);
1365 	}
1366 	return rv;
1367 }
1368 
1369 gboolean
1370 e_cert_db_import_server_cert (ECertDB *certdb,
1371                               gchar *data,
1372                               guint32 length,
1373                               GSList **imported_certs,
1374                               GError **error)
1375 {
1376 	/* not c&p'ing this over at the moment, as we don't have a UI
1377 	 * for server certs anyway */
1378 	return FALSE;
1379 }
1380 
1381 gboolean
1382 e_cert_db_import_certs_from_file (ECertDB *cert_db,
1383                                   const gchar *file_path,
1384                                   ECertType cert_type,
1385                                   GSList **imported_certs,
1386                                   GError **error)
1387 {
1388 	gboolean rv;
1389 	gint fd;
1390 	struct stat sb;
1391 	gchar *buf;
1392 	gint bytes_read;
1393 
1394 	switch (cert_type) {
1395 	case E_CERT_CA:
1396 	case E_CERT_CONTACT:
1397 	case E_CERT_SITE:
1398 		/* good */
1399 		break;
1400 
1401 	default:
1402 		/* not supported (yet) */
1403 		set_nss_error (error);
1404 		return FALSE;
1405 	}
1406 
1407 	fd = g_open (file_path, O_RDONLY | O_BINARY, 0);
1408 	if (fd == -1) {
1409 		set_nss_error (error);
1410 		return FALSE;
1411 	}
1412 
1413 	if (-1 == fstat (fd, &sb)) {
1414 		set_nss_error (error);
1415 		close (fd);
1416 		return FALSE;
1417 	}
1418 
1419 	buf = g_malloc (sb.st_size);
1420 	if (!buf) {
1421 		set_nss_error (error);
1422 		close (fd);
1423 		return FALSE;
1424 	}
1425 
1426 	bytes_read = read (fd, buf, sb.st_size);
1427 
1428 	close (fd);
1429 
1430 	if (bytes_read != sb.st_size) {
1431 		set_nss_error (error);
1432 		rv = FALSE;
1433 	}
1434 	else {
1435 		printf ("importing %d bytes from '%s'\n", bytes_read, file_path);
1436 
1437 		switch (cert_type) {
1438 		case E_CERT_CA:
1439 			rv = e_cert_db_import_certs (cert_db, buf, bytes_read, cert_type, imported_certs, error);
1440 			break;
1441 
1442 		case E_CERT_SITE:
1443 			rv = e_cert_db_import_server_cert (cert_db, buf, bytes_read, imported_certs, error);
1444 			break;
1445 
1446 		case E_CERT_CONTACT:
1447 			rv = e_cert_db_import_email_cert (cert_db, buf, bytes_read, imported_certs, error);
1448 			break;
1449 
1450 		default:
1451 			rv = FALSE;
1452 			break;
1453 		}
1454 	}
1455 
1456 	g_free (buf);
1457 	return rv;
1458 }
1459 
1460 gboolean
1461 e_cert_db_import_pkcs12_file (ECertDB *cert_db,
1462                               const gchar *file_path,
1463                               GError **error)
1464 {
1465 	EPKCS12 *pkcs12 = e_pkcs12_new ();
1466 	GError *e = NULL;
1467 
1468 	if (!e_pkcs12_import_from_file (pkcs12, file_path, &e)) {
1469 		g_propagate_error (error, e);
1470 		return FALSE;
1471 	}
1472 
1473 	return TRUE;
1474 }
1475 
1476 #ifdef notyet
1477 gboolean
1478 e_cert_db_export_pkcs12_file (ECertDB *cert_db,
1479                               const gchar *file_path,
1480                               GList *certs,
1481                               GError **error)
1482 {
1483 }
1484 #endif
1485 
1486 gboolean
1487 e_cert_db_login_to_slot (ECertDB *cert_db,
1488                          PK11SlotInfo *slot)
1489 {
1490 	if (PK11_NeedLogin (slot)) {
1491 		PK11_Logout (slot);
1492 
1493 		if (PK11_NeedUserInit (slot)) {
1494 			gchar *pwd;
1495 			gboolean rv = FALSE;
1496 
1497 			printf ("initializing slot password\n");
1498 
1499 			g_signal_emit (
1500 				e_cert_db_peek (),
1501 				e_cert_db_signals[PK11_CHANGE_PASSWD], 0,
1502 				NULL,
1503 				&pwd,
1504 				&rv);
1505 
1506 			if (!rv)
1507 				return FALSE;
1508 
1509 			/* the user needs to specify the initial password */
1510 			PK11_InitPin (slot, "", pwd);
1511 		}
1512 
1513 		PK11_SetPasswordFunc (pk11_password);
1514 		if (PK11_Authenticate (slot, PR_TRUE, NULL) != SECSuccess) {
1515 			printf (
1516 				"PK11_Authenticate failed (err = %d/%d)\n",
1517 				PORT_GetError (), PORT_GetError () + 0x2000);
1518 			return FALSE;
1519 		}
1520 	}
1521 
1522 	return TRUE;
1523 }