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 }