1 : /* ***** BEGIN LICENSE BLOCK *****
2 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 : *
4 : * The contents of this file are subject to the Mozilla Public License Version
5 : * 1.1 (the "License"); you may not use this file except in compliance with
6 : * the License. You may obtain a copy of the License at
7 : * http://www.mozilla.org/MPL/
8 : *
9 : * Software distributed under the License is distributed on an "AS IS" basis,
10 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 : * for the specific language governing rights and limitations under the
12 : * License.
13 : *
14 : * The Original Code is the Netscape security libraries.
15 : *
16 : * The Initial Developer of the Original Code is
17 : * Netscape Communications Corporation.
18 : * Portions created by the Initial Developer are Copyright (C) 2000
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Ian McGreer <mcgreer@netscape.com>
23 : * Javier Delgadillo <javi@netscape.com>
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 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "nsNSSComponent.h"
40 : #include "nsNSSCertificateDB.h"
41 : #include "nsCOMPtr.h"
42 : #include "nsNSSCertificate.h"
43 : #include "nsNSSHelper.h"
44 : #include "nsNSSCertHelper.h"
45 : #include "nsNSSCertCache.h"
46 : #include "nsCRT.h"
47 : #include "nsICertificateDialogs.h"
48 : #include "nsNSSCertTrust.h"
49 : #include "nsILocalFile.h"
50 : #include "nsPKCS12Blob.h"
51 : #include "nsPK11TokenDB.h"
52 : #include "nsOCSPResponder.h"
53 : #include "nsReadableUtils.h"
54 : #include "nsIMutableArray.h"
55 : #include "nsArrayUtils.h"
56 : #include "nsNSSShutDown.h"
57 : #include "nsIPrefService.h"
58 : #include "nsIPrefBranch.h"
59 : #include "nsComponentManagerUtils.h"
60 : #include "nsIPrompt.h"
61 : #include "nsThreadUtils.h"
62 :
63 : #include "nspr.h"
64 : extern "C" {
65 : #include "pk11func.h"
66 : #include "certdb.h"
67 : #include "cert.h"
68 : #include "secerr.h"
69 : #include "nssb64.h"
70 : #include "secasn1.h"
71 : #include "secder.h"
72 : }
73 : #include "ssl.h"
74 : #include "ocsp.h"
75 : #include "plbase64.h"
76 :
77 : #ifdef PR_LOGGING
78 : extern PRLogModuleInfo* gPIPNSSLog;
79 : #endif
80 :
81 : #include "nsNSSCleaner.h"
82 0 : NSSCleanupAutoPtrClass(CERTCertificate, CERT_DestroyCertificate)
83 0 : NSSCleanupAutoPtrClass(CERTCertList, CERT_DestroyCertList)
84 0 : NSSCleanupAutoPtrClass(CERTCertificateList, CERT_DestroyCertificateList)
85 0 : NSSCleanupAutoPtrClass(PK11SlotInfo, PK11_FreeSlot)
86 :
87 : static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
88 :
89 :
90 36 : NS_IMPL_THREADSAFE_ISUPPORTS2(nsNSSCertificateDB, nsIX509CertDB, nsIX509CertDB2)
91 :
92 4 : nsNSSCertificateDB::nsNSSCertificateDB()
93 : {
94 4 : }
95 :
96 8 : nsNSSCertificateDB::~nsNSSCertificateDB()
97 : {
98 16 : }
99 :
100 : NS_IMETHODIMP
101 0 : nsNSSCertificateDB::FindCertByNickname(nsISupports *aToken,
102 : const nsAString &nickname,
103 : nsIX509Cert **_rvCert)
104 : {
105 0 : nsNSSShutDownPreventionLock locker;
106 0 : CERTCertificate *cert = NULL;
107 0 : char *asciiname = NULL;
108 0 : NS_ConvertUTF16toUTF8 aUtf8Nickname(nickname);
109 0 : asciiname = const_cast<char*>(aUtf8Nickname.get());
110 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Getting \"%s\"\n", asciiname));
111 : #if 0
112 : // what it should be, but for now...
113 : if (aToken) {
114 : cert = PK11_FindCertFromNickname(asciiname, NULL);
115 : } else {
116 : cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), asciiname);
117 : }
118 : #endif
119 0 : cert = PK11_FindCertFromNickname(asciiname, NULL);
120 0 : if (!cert) {
121 0 : cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), asciiname);
122 : }
123 0 : if (cert) {
124 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("got it\n"));
125 0 : nsCOMPtr<nsIX509Cert> pCert = nsNSSCertificate::Create(cert);
126 0 : CERT_DestroyCertificate(cert);
127 0 : if (pCert) {
128 0 : *_rvCert = pCert;
129 0 : NS_ADDREF(*_rvCert);
130 0 : return NS_OK;
131 : }
132 : }
133 0 : *_rvCert = nsnull;
134 0 : return NS_ERROR_FAILURE;
135 : }
136 :
137 : NS_IMETHODIMP
138 0 : nsNSSCertificateDB::FindCertByDBKey(const char *aDBkey, nsISupports *aToken,
139 : nsIX509Cert **_cert)
140 : {
141 0 : nsNSSShutDownPreventionLock locker;
142 0 : SECItem keyItem = {siBuffer, nsnull, 0};
143 : SECItem *dummy;
144 : CERTIssuerAndSN issuerSN;
145 : //unsigned long moduleID,slotID;
146 0 : *_cert = nsnull;
147 0 : if (!aDBkey || !*aDBkey)
148 0 : return NS_ERROR_INVALID_ARG;
149 :
150 : dummy = NSSBase64_DecodeBuffer(nsnull, &keyItem, aDBkey,
151 0 : (PRUint32)PL_strlen(aDBkey));
152 0 : if (!dummy || keyItem.len < NS_NSS_LONG*4) {
153 0 : PR_FREEIF(keyItem.data);
154 0 : return NS_ERROR_INVALID_ARG;
155 : }
156 :
157 : CERTCertificate *cert;
158 : // someday maybe we can speed up the search using the moduleID and slotID
159 : // moduleID = NS_NSS_GET_LONG(keyItem.data);
160 : // slotID = NS_NSS_GET_LONG(&keyItem.data[NS_NSS_LONG]);
161 :
162 : // build the issuer/SN structure
163 0 : issuerSN.serialNumber.len = NS_NSS_GET_LONG(&keyItem.data[NS_NSS_LONG*2]);
164 0 : issuerSN.derIssuer.len = NS_NSS_GET_LONG(&keyItem.data[NS_NSS_LONG*3]);
165 0 : if (issuerSN.serialNumber.len == 0 || issuerSN.derIssuer.len == 0
166 : || issuerSN.serialNumber.len + issuerSN.derIssuer.len
167 : != keyItem.len - NS_NSS_LONG*4) {
168 0 : PR_FREEIF(keyItem.data);
169 0 : return NS_ERROR_INVALID_ARG;
170 : }
171 0 : issuerSN.serialNumber.data= &keyItem.data[NS_NSS_LONG*4];
172 : issuerSN.derIssuer.data= &keyItem.data[NS_NSS_LONG*4+
173 0 : issuerSN.serialNumber.len];
174 :
175 0 : cert = CERT_FindCertByIssuerAndSN(CERT_GetDefaultCertDB(), &issuerSN);
176 0 : PR_FREEIF(keyItem.data);
177 0 : if (cert) {
178 0 : nsNSSCertificate *nssCert = nsNSSCertificate::Create(cert);
179 0 : CERT_DestroyCertificate(cert);
180 0 : if (nssCert == nsnull)
181 0 : return NS_ERROR_OUT_OF_MEMORY;
182 0 : NS_ADDREF(nssCert);
183 0 : *_cert = static_cast<nsIX509Cert*>(nssCert);
184 : }
185 0 : return NS_OK;
186 : }
187 :
188 : NS_IMETHODIMP
189 0 : nsNSSCertificateDB::FindCertNicknames(nsISupports *aToken,
190 : PRUint32 aType,
191 : PRUint32 *_count,
192 : PRUnichar ***_certNames)
193 : {
194 0 : nsNSSShutDownPreventionLock locker;
195 0 : nsresult rv = NS_ERROR_FAILURE;
196 : /*
197 : * obtain the cert list from NSS
198 : */
199 0 : CERTCertList *certList = NULL;
200 : PK11CertListType pk11type;
201 : #if 0
202 : // this would seem right, but it didn't work...
203 : // oh, I know why - bonks out on internal slot certs
204 : if (aType == nsIX509Cert::USER_CERT)
205 : pk11type = PK11CertListUser;
206 : else
207 : #endif
208 0 : pk11type = PK11CertListUnique;
209 0 : certList = PK11_ListCerts(pk11type, NULL);
210 0 : if (!certList)
211 0 : goto cleanup;
212 : /*
213 : * get list of cert names from list of certs
214 : * XXX also cull the list (NSS only distinguishes based on user/non-user
215 : */
216 0 : getCertNames(certList, aType, _count, _certNames);
217 0 : rv = NS_OK;
218 : /*
219 : * finish up
220 : */
221 : cleanup:
222 0 : if (certList)
223 0 : CERT_DestroyCertList(certList);
224 0 : return rv;
225 : }
226 :
227 : SECStatus PR_CALLBACK
228 0 : collect_certs(void *arg, SECItem **certs, int numcerts)
229 : {
230 : CERTDERCerts *collectArgs;
231 : SECItem *cert;
232 : SECStatus rv;
233 :
234 0 : collectArgs = (CERTDERCerts *)arg;
235 :
236 0 : collectArgs->numcerts = numcerts;
237 : collectArgs->rawCerts = (SECItem *) PORT_ArenaZAlloc(collectArgs->arena,
238 0 : sizeof(SECItem) * numcerts);
239 0 : if ( collectArgs->rawCerts == NULL )
240 0 : return(SECFailure);
241 :
242 0 : cert = collectArgs->rawCerts;
243 :
244 0 : while ( numcerts-- ) {
245 0 : rv = SECITEM_CopyItem(collectArgs->arena, cert, *certs);
246 0 : if ( rv == SECFailure )
247 0 : return(SECFailure);
248 0 : cert++;
249 0 : certs++;
250 : }
251 :
252 0 : return (SECSuccess);
253 : }
254 :
255 : CERTDERCerts*
256 0 : nsNSSCertificateDB::getCertsFromPackage(PRArenaPool *arena, PRUint8 *data,
257 : PRUint32 length)
258 : {
259 0 : nsNSSShutDownPreventionLock locker;
260 : CERTDERCerts *collectArgs =
261 0 : (CERTDERCerts *)PORT_ArenaZAlloc(arena, sizeof(CERTDERCerts));
262 0 : if ( collectArgs == nsnull )
263 0 : return nsnull;
264 :
265 0 : collectArgs->arena = arena;
266 : SECStatus sec_rv = CERT_DecodeCertPackage(reinterpret_cast<char *>(data),
267 : length, collect_certs,
268 0 : (void *)collectArgs);
269 0 : if (sec_rv != SECSuccess)
270 0 : return nsnull;
271 :
272 0 : return collectArgs;
273 : }
274 :
275 : nsresult
276 0 : nsNSSCertificateDB::handleCACertDownload(nsIArray *x509Certs,
277 : nsIInterfaceRequestor *ctx)
278 : {
279 : // First thing we have to do is figure out which certificate we're
280 : // gonna present to the user. The CA may have sent down a list of
281 : // certs which may or may not be a chained list of certs. Until
282 : // the day we can design some solid UI for the general case, we'll
283 : // code to the > 90% case. That case is where a CA sends down a
284 : // list that is a hierarchy whose root is either the first or
285 : // the last cert. What we're gonna do is compare the first
286 : // 2 entries, if the second was signed by the first, we assume
287 : // the root cert is the first cert and display it. Otherwise,
288 : // we compare the last 2 entries, if the second to last cert was
289 : // signed by the last cert, then we assume the last cert is the
290 : // root and display it.
291 :
292 0 : nsNSSShutDownPreventionLock locker;
293 :
294 : PRUint32 numCerts;
295 :
296 0 : x509Certs->GetLength(&numCerts);
297 0 : NS_ASSERTION(numCerts > 0, "Didn't get any certs to import.");
298 0 : if (numCerts == 0)
299 0 : return NS_OK; // Nothing to import, so nothing to do.
300 :
301 0 : nsCOMPtr<nsIX509Cert> certToShow;
302 0 : nsCOMPtr<nsISupports> isupports;
303 : PRUint32 selCertIndex;
304 0 : if (numCerts == 1) {
305 : // There's only one cert, so let's show it.
306 0 : selCertIndex = 0;
307 0 : certToShow = do_QueryElementAt(x509Certs, selCertIndex);
308 : } else {
309 0 : nsCOMPtr<nsIX509Cert> cert0; // first cert
310 0 : nsCOMPtr<nsIX509Cert> cert1; // second cert
311 0 : nsCOMPtr<nsIX509Cert> certn_2; // second to last cert
312 0 : nsCOMPtr<nsIX509Cert> certn_1; // last cert
313 :
314 0 : cert0 = do_QueryElementAt(x509Certs, 0);
315 0 : cert1 = do_QueryElementAt(x509Certs, 1);
316 0 : certn_2 = do_QueryElementAt(x509Certs, numCerts-2);
317 0 : certn_1 = do_QueryElementAt(x509Certs, numCerts-1);
318 :
319 0 : nsXPIDLString cert0SubjectName;
320 0 : nsXPIDLString cert1IssuerName;
321 0 : nsXPIDLString certn_2IssuerName;
322 0 : nsXPIDLString certn_1SubjectName;
323 :
324 0 : cert0->GetSubjectName(cert0SubjectName);
325 0 : cert1->GetIssuerName(cert1IssuerName);
326 0 : certn_2->GetIssuerName(certn_2IssuerName);
327 0 : certn_1->GetSubjectName(certn_1SubjectName);
328 :
329 0 : if (cert1IssuerName.Equals(cert0SubjectName)) {
330 : // In this case, the first cert in the list signed the second,
331 : // so the first cert is the root. Let's display it.
332 0 : selCertIndex = 0;
333 0 : certToShow = cert0;
334 : } else
335 0 : if (certn_2IssuerName.Equals(certn_1SubjectName)) {
336 : // In this case the last cert has signed the second to last cert.
337 : // The last cert is the root, so let's display it.
338 0 : selCertIndex = numCerts-1;
339 0 : certToShow = certn_1;
340 : } else {
341 : // It's not a chain, so let's just show the first one in the
342 : // downloaded list.
343 0 : selCertIndex = 0;
344 0 : certToShow = cert0;
345 : }
346 : }
347 :
348 0 : if (!certToShow)
349 0 : return NS_ERROR_FAILURE;
350 :
351 0 : nsCOMPtr<nsICertificateDialogs> dialogs;
352 0 : nsresult rv = ::getNSSDialogs(getter_AddRefs(dialogs),
353 : NS_GET_IID(nsICertificateDialogs),
354 0 : NS_CERTIFICATEDIALOGS_CONTRACTID);
355 :
356 0 : if (NS_FAILED(rv))
357 0 : return rv;
358 :
359 : SECItem der;
360 0 : rv=certToShow->GetRawDER(&der.len, (PRUint8 **)&der.data);
361 :
362 0 : if (NS_FAILED(rv))
363 0 : return rv;
364 :
365 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Creating temp cert\n"));
366 : CERTCertificate *tmpCert;
367 0 : CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
368 0 : tmpCert = CERT_FindCertByDERCert(certdb, &der);
369 0 : if (!tmpCert) {
370 : tmpCert = CERT_NewTempCertificate(certdb, &der,
371 0 : nsnull, false, true);
372 : }
373 0 : nsMemory::Free(der.data);
374 0 : der.data = nsnull;
375 0 : der.len = 0;
376 :
377 0 : if (!tmpCert) {
378 0 : NS_ERROR("Couldn't create cert from DER blob");
379 0 : return NS_ERROR_FAILURE;
380 : }
381 :
382 0 : CERTCertificateCleaner tmpCertCleaner(tmpCert);
383 :
384 0 : if (!CERT_IsCACert(tmpCert, NULL)) {
385 0 : DisplayCertificateAlert(ctx, "NotACACert", certToShow);
386 0 : return NS_ERROR_FAILURE;
387 : }
388 :
389 0 : if (tmpCert->isperm) {
390 0 : DisplayCertificateAlert(ctx, "CaCertExists", certToShow);
391 0 : return NS_ERROR_FAILURE;
392 : }
393 :
394 : PRUint32 trustBits;
395 : bool allows;
396 0 : rv = dialogs->ConfirmDownloadCACert(ctx, certToShow, &trustBits, &allows);
397 0 : if (NS_FAILED(rv))
398 0 : return rv;
399 :
400 0 : if (!allows)
401 0 : return NS_ERROR_NOT_AVAILABLE;
402 :
403 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("trust is %d\n", trustBits));
404 0 : nsXPIDLCString nickname;
405 0 : nickname.Adopt(CERT_MakeCANickname(tmpCert));
406 :
407 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Created nick \"%s\"\n", nickname.get()));
408 :
409 0 : nsNSSCertTrust trust;
410 0 : trust.SetValidCA();
411 : trust.AddCATrust(!!(trustBits & nsIX509CertDB::TRUSTED_SSL),
412 : !!(trustBits & nsIX509CertDB::TRUSTED_EMAIL),
413 0 : !!(trustBits & nsIX509CertDB::TRUSTED_OBJSIGN));
414 :
415 : SECStatus srv = CERT_AddTempCertToPerm(tmpCert,
416 0 : const_cast<char*>(nickname.get()),
417 0 : trust.GetTrust());
418 :
419 0 : if (srv != SECSuccess)
420 0 : return NS_ERROR_FAILURE;
421 :
422 : // Import additional delivered certificates that can be verified.
423 :
424 : // build a CertList for filtering
425 0 : CERTCertList *certList = CERT_NewCertList();
426 0 : if (certList == NULL) {
427 0 : return NS_ERROR_FAILURE;
428 : }
429 :
430 0 : CERTCertListCleaner listCleaner(certList);
431 :
432 : // get all remaining certs into temp store
433 :
434 0 : for (PRUint32 i=0; i<numCerts; i++) {
435 0 : if (i == selCertIndex) {
436 : // we already processed that one
437 0 : continue;
438 : }
439 :
440 0 : certToShow = do_QueryElementAt(x509Certs, i);
441 0 : certToShow->GetRawDER(&der.len, (PRUint8 **)&der.data);
442 :
443 : CERTCertificate *tmpCert2 =
444 0 : CERT_NewTempCertificate(certdb, &der, nsnull, false, true);
445 :
446 0 : nsMemory::Free(der.data);
447 0 : der.data = nsnull;
448 0 : der.len = 0;
449 :
450 0 : if (!tmpCert2) {
451 0 : NS_ERROR("Couldn't create temp cert from DER blob");
452 0 : continue; // Let's try to import the rest of 'em
453 : }
454 :
455 0 : CERT_AddCertToListTail(certList, tmpCert2);
456 : }
457 :
458 0 : return ImportValidCACertsInList(certList, ctx);
459 : }
460 :
461 : /*
462 : * [noscript] void importCertificates(in charPtr data, in unsigned long length,
463 : * in unsigned long type,
464 : * in nsIInterfaceRequestor ctx);
465 : */
466 : NS_IMETHODIMP
467 0 : nsNSSCertificateDB::ImportCertificates(PRUint8 * data, PRUint32 length,
468 : PRUint32 type,
469 : nsIInterfaceRequestor *ctx)
470 :
471 : {
472 0 : nsNSSShutDownPreventionLock locker;
473 : nsresult nsrv;
474 :
475 0 : PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
476 0 : if (!arena)
477 0 : return NS_ERROR_OUT_OF_MEMORY;
478 :
479 0 : CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length);
480 0 : if (!certCollection) {
481 0 : PORT_FreeArena(arena, false);
482 0 : return NS_ERROR_FAILURE;
483 : }
484 : nsCOMPtr<nsIMutableArray> array =
485 0 : do_CreateInstance(NS_ARRAY_CONTRACTID, &nsrv);
486 0 : if (NS_FAILED(nsrv)) {
487 0 : PORT_FreeArena(arena, false);
488 0 : return nsrv;
489 : }
490 :
491 : // Now let's create some certs to work with
492 0 : nsCOMPtr<nsIX509Cert> x509Cert;
493 : nsNSSCertificate *nssCert;
494 : SECItem *currItem;
495 0 : for (int i=0; i<certCollection->numcerts; i++) {
496 0 : currItem = &certCollection->rawCerts[i];
497 0 : nssCert = nsNSSCertificate::ConstructFromDER((char*)currItem->data, currItem->len);
498 0 : if (!nssCert)
499 0 : return NS_ERROR_FAILURE;
500 0 : x509Cert = do_QueryInterface((nsIX509Cert*)nssCert);
501 0 : array->AppendElement(x509Cert, false);
502 : }
503 0 : switch (type) {
504 : case nsIX509Cert::CA_CERT:
505 0 : nsrv = handleCACertDownload(array, ctx);
506 0 : break;
507 : default:
508 : // We only deal with import CA certs in this method currently.
509 0 : nsrv = NS_ERROR_FAILURE;
510 0 : break;
511 : }
512 0 : PORT_FreeArena(arena, false);
513 0 : return nsrv;
514 : }
515 :
516 :
517 : /*
518 : * [noscript] void importEmailCertificates(in charPtr data, in unsigned long length,
519 : * in nsIInterfaceRequestor ctx);
520 : */
521 : NS_IMETHODIMP
522 0 : nsNSSCertificateDB::ImportEmailCertificate(PRUint8 * data, PRUint32 length,
523 : nsIInterfaceRequestor *ctx)
524 :
525 : {
526 0 : nsNSSShutDownPreventionLock locker;
527 0 : SECStatus srv = SECFailure;
528 0 : nsresult nsrv = NS_OK;
529 : CERTCertDBHandle *certdb;
530 0 : CERTCertificate **certArray = NULL;
531 0 : CERTCertList *certList = NULL;
532 : CERTCertListNode *node;
533 : PRTime now;
534 : SECCertUsage certusage;
535 : SECCertificateUsage certificateusage;
536 : SECItem **rawArray;
537 : int numcerts;
538 : int i;
539 : CERTValOutParam cvout[1];
540 0 : cvout[0].type = cert_po_end;
541 :
542 0 : nsCOMPtr<nsINSSComponent> inss = do_GetService(kNSSComponentCID, &nsrv);
543 0 : if (!inss)
544 0 : return nsrv;
545 0 : nsRefPtr<nsCERTValInParamWrapper> survivingParams;
546 0 : nsrv = inss->GetDefaultCERTValInParam(survivingParams);
547 0 : if (NS_FAILED(nsrv))
548 0 : return nsrv;
549 :
550 0 : PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
551 0 : if (!arena)
552 0 : return NS_ERROR_OUT_OF_MEMORY;
553 :
554 0 : CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length);
555 0 : if (!certCollection) {
556 0 : PORT_FreeArena(arena, false);
557 0 : return NS_ERROR_FAILURE;
558 : }
559 :
560 0 : certdb = CERT_GetDefaultCertDB();
561 0 : certusage = certUsageEmailRecipient;
562 0 : certificateusage = certificateUsageEmailRecipient;
563 :
564 0 : numcerts = certCollection->numcerts;
565 :
566 0 : rawArray = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts);
567 0 : if ( !rawArray ) {
568 0 : nsrv = NS_ERROR_FAILURE;
569 0 : goto loser;
570 : }
571 :
572 0 : for (i=0; i < numcerts; i++) {
573 0 : rawArray[i] = &certCollection->rawCerts[i];
574 : }
575 :
576 : srv = CERT_ImportCerts(certdb, certusage, numcerts, rawArray,
577 0 : &certArray, false, false, NULL);
578 :
579 0 : PORT_Free(rawArray);
580 0 : rawArray = NULL;
581 :
582 0 : if (srv != SECSuccess) {
583 0 : nsrv = NS_ERROR_FAILURE;
584 0 : goto loser;
585 : }
586 :
587 : // build a CertList for filtering
588 0 : certList = CERT_NewCertList();
589 0 : if (certList == NULL) {
590 0 : nsrv = NS_ERROR_FAILURE;
591 0 : goto loser;
592 : }
593 0 : for (i=0; i < numcerts; i++) {
594 0 : CERTCertificate *cert = certArray[i];
595 0 : if (cert)
596 0 : cert = CERT_DupCertificate(cert);
597 0 : if (cert)
598 0 : CERT_AddCertToListTail(certList, cert);
599 : }
600 :
601 : /* go down the remaining list of certs and verify that they have
602 : * valid chains, then import them.
603 : */
604 0 : now = PR_Now();
605 :
606 0 : for (node = CERT_LIST_HEAD(certList);
607 0 : !CERT_LIST_END(node,certList);
608 : node = CERT_LIST_NEXT(node)) {
609 :
610 0 : bool alert_and_skip = false;
611 :
612 0 : if (!node->cert) {
613 0 : continue;
614 : }
615 :
616 0 : if (!nsNSSComponent::globalConstFlagUsePKIXVerification) {
617 0 : if (CERT_VerifyCert(certdb, node->cert,
618 0 : true, certusage, now, ctx, NULL) != SECSuccess) {
619 0 : alert_and_skip = true;
620 : }
621 : }
622 : else {
623 0 : if (CERT_PKIXVerifyCert(node->cert, certificateusage,
624 : survivingParams->GetRawPointerForNSS(),
625 0 : cvout, ctx)
626 : != SECSuccess) {
627 0 : alert_and_skip = true;
628 : }
629 : }
630 :
631 0 : CERTCertificateList *certChain = nsnull;
632 0 : CERTCertificateListCleaner chainCleaner(certChain);
633 :
634 0 : if (!alert_and_skip) {
635 0 : certChain = CERT_CertChainFromCert(node->cert, certusage, false);
636 0 : if (!certChain) {
637 0 : alert_and_skip = true;
638 : }
639 : }
640 :
641 0 : if (alert_and_skip) {
642 0 : nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(node->cert);
643 0 : DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow);
644 0 : continue;
645 : }
646 :
647 : /*
648 : * CertChain returns an array of SECItems, import expects an array of
649 : * SECItem pointers. Create the SECItem Pointers from the array of
650 : * SECItems.
651 : */
652 0 : rawArray = (SECItem **) PORT_Alloc(certChain->len * sizeof(SECItem *));
653 0 : if (!rawArray) {
654 0 : continue;
655 : }
656 0 : for (i=0; i < certChain->len; i++) {
657 0 : rawArray[i] = &certChain->certs[i];
658 : }
659 : CERT_ImportCerts(certdb, certusage, certChain->len,
660 0 : rawArray, NULL, true, false, NULL);
661 :
662 0 : CERT_SaveSMimeProfile(node->cert, NULL, NULL);
663 :
664 0 : PORT_Free(rawArray);
665 : }
666 :
667 : loser:
668 0 : if (certArray) {
669 0 : CERT_DestroyCertArray(certArray, numcerts);
670 : }
671 0 : if (certList) {
672 0 : CERT_DestroyCertList(certList);
673 : }
674 0 : if (arena)
675 0 : PORT_FreeArena(arena, true);
676 0 : return nsrv;
677 : }
678 :
679 : NS_IMETHODIMP
680 0 : nsNSSCertificateDB::ImportServerCertificate(PRUint8 * data, PRUint32 length,
681 : nsIInterfaceRequestor *ctx)
682 :
683 : {
684 0 : nsNSSShutDownPreventionLock locker;
685 0 : SECStatus srv = SECFailure;
686 0 : nsresult nsrv = NS_OK;
687 : CERTCertificate * cert;
688 0 : SECItem **rawCerts = nsnull;
689 : int numcerts;
690 : int i;
691 0 : nsNSSCertTrust trust;
692 0 : char *serverNickname = nsnull;
693 :
694 0 : PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
695 0 : if (!arena)
696 0 : return NS_ERROR_OUT_OF_MEMORY;
697 :
698 0 : CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length);
699 0 : if (!certCollection) {
700 0 : PORT_FreeArena(arena, false);
701 0 : return NS_ERROR_FAILURE;
702 : }
703 : cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), certCollection->rawCerts,
704 0 : (char *)NULL, false, true);
705 0 : if (!cert) {
706 0 : nsrv = NS_ERROR_FAILURE;
707 0 : goto loser;
708 : }
709 0 : numcerts = certCollection->numcerts;
710 0 : rawCerts = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts);
711 0 : if ( !rawCerts ) {
712 0 : nsrv = NS_ERROR_FAILURE;
713 0 : goto loser;
714 : }
715 :
716 0 : for ( i = 0; i < numcerts; i++ ) {
717 0 : rawCerts[i] = &certCollection->rawCerts[i];
718 : }
719 :
720 0 : serverNickname = nsNSSCertificate::defaultServerNickname(cert);
721 : srv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageSSLServer,
722 : numcerts, rawCerts, NULL, true, false,
723 0 : serverNickname);
724 0 : PR_FREEIF(serverNickname);
725 0 : if ( srv != SECSuccess ) {
726 0 : nsrv = NS_ERROR_FAILURE;
727 0 : goto loser;
728 : }
729 :
730 0 : trust.SetValidServerPeer();
731 0 : srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, trust.GetTrust());
732 0 : if ( srv != SECSuccess ) {
733 0 : nsrv = NS_ERROR_FAILURE;
734 0 : goto loser;
735 : }
736 : loser:
737 0 : PORT_Free(rawCerts);
738 0 : if (cert)
739 0 : CERT_DestroyCertificate(cert);
740 0 : if (arena)
741 0 : PORT_FreeArena(arena, true);
742 0 : return nsrv;
743 : }
744 :
745 : nsresult
746 0 : nsNSSCertificateDB::ImportValidCACerts(int numCACerts, SECItem *CACerts, nsIInterfaceRequestor *ctx)
747 : {
748 0 : CERTCertList *certList = NULL;
749 : SECItem **rawArray;
750 :
751 : // build a CertList for filtering
752 0 : certList = CERT_NewCertList();
753 0 : if (certList == NULL) {
754 0 : return NS_ERROR_FAILURE;
755 : }
756 :
757 0 : CERTCertListCleaner listCleaner(certList);
758 :
759 : // get all certs into temp store
760 0 : SECStatus srv = SECFailure;
761 0 : CERTCertificate **certArray = NULL;
762 :
763 0 : rawArray = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numCACerts);
764 0 : if ( !rawArray ) {
765 0 : return NS_ERROR_FAILURE;
766 : }
767 :
768 0 : for (int i=0; i < numCACerts; i++) {
769 0 : rawArray[i] = &CACerts[i];
770 : }
771 :
772 : srv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageAnyCA, numCACerts, rawArray,
773 0 : &certArray, false, true, NULL);
774 :
775 0 : PORT_Free(rawArray);
776 0 : rawArray = NULL;
777 :
778 0 : if (srv != SECSuccess) {
779 0 : return NS_ERROR_FAILURE;
780 : }
781 :
782 0 : for (int i2=0; i2 < numCACerts; i2++) {
783 0 : CERTCertificate *cacert = certArray[i2];
784 0 : if (cacert)
785 0 : cacert = CERT_DupCertificate(cacert);
786 0 : if (cacert)
787 0 : CERT_AddCertToListTail(certList, cacert);
788 : }
789 :
790 0 : CERT_DestroyCertArray(certArray, numCACerts);
791 :
792 0 : return ImportValidCACertsInList(certList, ctx);
793 : }
794 :
795 : nsresult
796 0 : nsNSSCertificateDB::ImportValidCACertsInList(CERTCertList *certList, nsIInterfaceRequestor *ctx)
797 : {
798 : SECItem **rawArray;
799 : nsresult nsrv;
800 0 : nsCOMPtr<nsINSSComponent> inss = do_GetService(kNSSComponentCID, &nsrv);
801 0 : if (!inss)
802 0 : return nsrv;
803 0 : nsRefPtr<nsCERTValInParamWrapper> survivingParams;
804 0 : nsrv = inss->GetDefaultCERTValInParam(survivingParams);
805 0 : if (NS_FAILED(nsrv))
806 0 : return nsrv;
807 :
808 : /* filter out the certs we don't want */
809 0 : SECStatus srv = CERT_FilterCertListByUsage(certList, certUsageAnyCA, true);
810 0 : if (srv != SECSuccess) {
811 0 : return NS_ERROR_FAILURE;
812 : }
813 :
814 : /* go down the remaining list of certs and verify that they have
815 : * valid chains, if yes, then import.
816 : */
817 : CERTCertListNode *node;
818 : CERTValOutParam cvout[1];
819 0 : cvout[0].type = cert_po_end;
820 :
821 0 : for (node = CERT_LIST_HEAD(certList);
822 0 : !CERT_LIST_END(node,certList);
823 : node = CERT_LIST_NEXT(node)) {
824 :
825 0 : bool alert_and_skip = false;
826 :
827 0 : if (!nsNSSComponent::globalConstFlagUsePKIXVerification) {
828 0 : if (CERT_VerifyCert(CERT_GetDefaultCertDB(), node->cert,
829 0 : true, certUsageVerifyCA, PR_Now(), ctx, NULL) != SECSuccess) {
830 0 : alert_and_skip = true;
831 : }
832 : }
833 : else {
834 0 : if (CERT_PKIXVerifyCert(node->cert, certificateUsageVerifyCA,
835 : survivingParams->GetRawPointerForNSS(),
836 0 : cvout, ctx)
837 : != SECSuccess) {
838 0 : alert_and_skip = true;
839 : }
840 : }
841 :
842 0 : CERTCertificateList *certChain = nsnull;
843 0 : CERTCertificateListCleaner chainCleaner(certChain);
844 :
845 0 : if (!alert_and_skip) {
846 0 : certChain = CERT_CertChainFromCert(node->cert, certUsageAnyCA, false);
847 0 : if (!certChain) {
848 0 : alert_and_skip = true;
849 : }
850 : }
851 :
852 0 : if (alert_and_skip) {
853 0 : nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(node->cert);
854 0 : DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow);
855 0 : continue;
856 : }
857 :
858 : /*
859 : * CertChain returns an array of SECItems, import expects an array of
860 : * SECItem pointers. Create the SECItem Pointers from the array of
861 : * SECItems.
862 : */
863 0 : rawArray = (SECItem **) PORT_Alloc(certChain->len * sizeof(SECItem *));
864 0 : if (!rawArray) {
865 0 : continue;
866 : }
867 0 : for (int i=0; i < certChain->len; i++) {
868 0 : rawArray[i] = &certChain->certs[i];
869 : }
870 : CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageAnyCA, certChain->len,
871 0 : rawArray, NULL, true, true, NULL);
872 :
873 0 : PORT_Free(rawArray);
874 : }
875 :
876 0 : return NS_OK;
877 : }
878 :
879 0 : void nsNSSCertificateDB::DisplayCertificateAlert(nsIInterfaceRequestor *ctx,
880 : const char *stringID,
881 : nsIX509Cert *certToShow)
882 : {
883 0 : if (!NS_IsMainThread()) {
884 0 : NS_ERROR("nsNSSCertificateDB::DisplayCertificateAlert called off the main thread");
885 0 : return;
886 : }
887 :
888 0 : nsPSMUITracker tracker;
889 0 : if (!tracker.isUIForbidden()) {
890 :
891 0 : nsCOMPtr<nsIInterfaceRequestor> my_ctx = ctx;
892 0 : if (!my_ctx)
893 0 : my_ctx = new PipUIContext();
894 :
895 : // This shall be replaced by embedding ovverridable prompts
896 : // as discussed in bug 310446, and should make use of certToShow.
897 :
898 : nsresult rv;
899 0 : nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
900 0 : if (NS_SUCCEEDED(rv)) {
901 0 : nsAutoString tmpMessage;
902 0 : nssComponent->GetPIPNSSBundleString(stringID, tmpMessage);
903 :
904 0 : nsCOMPtr<nsIPrompt> prompt (do_GetInterface(my_ctx));
905 0 : if (!prompt)
906 : return;
907 :
908 0 : prompt->Alert(nsnull, tmpMessage.get());
909 : }
910 : }
911 : }
912 :
913 :
914 : NS_IMETHODIMP
915 0 : nsNSSCertificateDB::ImportUserCertificate(PRUint8 *data, PRUint32 length, nsIInterfaceRequestor *ctx)
916 : {
917 0 : if (!NS_IsMainThread()) {
918 0 : NS_ERROR("nsNSSCertificateDB::ImportUserCertificate called off the main thread");
919 0 : return NS_ERROR_NOT_SAME_THREAD;
920 : }
921 :
922 0 : nsNSSShutDownPreventionLock locker;
923 : PK11SlotInfo *slot;
924 0 : nsCAutoString nickname;
925 0 : nsresult rv = NS_ERROR_FAILURE;
926 : int numCACerts;
927 : SECItem *CACerts;
928 : CERTDERCerts * collectArgs;
929 : PRArenaPool *arena;
930 0 : CERTCertificate * cert=NULL;
931 :
932 0 : arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
933 0 : if ( arena == NULL ) {
934 0 : goto loser;
935 : }
936 :
937 0 : collectArgs = getCertsFromPackage(arena, data, length);
938 0 : if (!collectArgs) {
939 0 : goto loser;
940 : }
941 :
942 : cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), collectArgs->rawCerts,
943 0 : (char *)NULL, false, true);
944 0 : if (!cert) {
945 0 : goto loser;
946 : }
947 :
948 0 : slot = PK11_KeyForCertExists(cert, NULL, ctx);
949 0 : if ( slot == NULL ) {
950 0 : nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(cert);
951 0 : DisplayCertificateAlert(ctx, "UserCertIgnoredNoPrivateKey", certToShow);
952 : goto loser;
953 : }
954 0 : PK11_FreeSlot(slot);
955 :
956 : /* pick a nickname for the cert */
957 0 : if (cert->nickname) {
958 : /* sigh, we need a call to look up other certs with this subject and
959 : * identify nicknames from them. We can no longer walk down internal
960 : * database structures rjr */
961 0 : nickname = cert->nickname;
962 : }
963 : else {
964 0 : get_default_nickname(cert, ctx, nickname);
965 : }
966 :
967 : /* user wants to import the cert */
968 : {
969 0 : char *cast_const_away = const_cast<char*>(nickname.get());
970 0 : slot = PK11_ImportCertForKey(cert, cast_const_away, ctx);
971 : }
972 0 : if (!slot) {
973 0 : goto loser;
974 : }
975 0 : PK11_FreeSlot(slot);
976 :
977 : {
978 0 : nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(cert);
979 0 : DisplayCertificateAlert(ctx, "UserCertImported", certToShow);
980 : }
981 0 : rv = NS_OK;
982 :
983 0 : numCACerts = collectArgs->numcerts - 1;
984 0 : if (numCACerts) {
985 0 : CACerts = collectArgs->rawCerts+1;
986 0 : rv = ImportValidCACerts(numCACerts, CACerts, ctx);
987 : }
988 :
989 : loser:
990 0 : if (arena) {
991 0 : PORT_FreeArena(arena, false);
992 : }
993 0 : if ( cert ) {
994 0 : CERT_DestroyCertificate(cert);
995 : }
996 0 : return rv;
997 : }
998 :
999 : /*
1000 : * void deleteCertificate(in nsIX509Cert aCert);
1001 : */
1002 : NS_IMETHODIMP
1003 0 : nsNSSCertificateDB::DeleteCertificate(nsIX509Cert *aCert)
1004 : {
1005 0 : nsNSSShutDownPreventionLock locker;
1006 0 : nsCOMPtr<nsIX509Cert2> nssCert = do_QueryInterface(aCert);
1007 0 : CERTCertificate *cert = nssCert->GetCert();
1008 0 : if (!cert) return NS_ERROR_FAILURE;
1009 0 : CERTCertificateCleaner certCleaner(cert);
1010 0 : SECStatus srv = SECSuccess;
1011 :
1012 : PRUint32 certType;
1013 0 : nssCert->GetCertType(&certType);
1014 0 : if (NS_FAILED(nssCert->MarkForPermDeletion()))
1015 : {
1016 0 : return NS_ERROR_FAILURE;
1017 : }
1018 :
1019 0 : if (cert->slot && certType != nsIX509Cert::USER_CERT) {
1020 : // To delete a cert of a slot (builtin, most likely), mark it as
1021 : // completely untrusted. This way we keep a copy cached in the
1022 : // local database, and next time we try to load it off of the
1023 : // external token/slot, we'll know not to trust it. We don't
1024 : // want to do that with user certs, because a user may re-store
1025 : // the cert onto the card again at which point we *will* want to
1026 : // trust that cert if it chains up properly.
1027 0 : nsNSSCertTrust trust(0, 0, 0);
1028 : srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
1029 0 : cert, trust.GetTrust());
1030 : }
1031 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("cert deleted: %d", srv));
1032 0 : return (srv) ? NS_ERROR_FAILURE : NS_OK;
1033 : }
1034 :
1035 : /*
1036 : * void setCertTrust(in nsIX509Cert cert,
1037 : * in unsigned long type,
1038 : * in unsigned long trust);
1039 : */
1040 : NS_IMETHODIMP
1041 0 : nsNSSCertificateDB::SetCertTrust(nsIX509Cert *cert,
1042 : PRUint32 type,
1043 : PRUint32 trusted)
1044 : {
1045 0 : nsNSSShutDownPreventionLock locker;
1046 : SECStatus srv;
1047 0 : nsNSSCertTrust trust;
1048 0 : nsCOMPtr<nsIX509Cert2> pipCert = do_QueryInterface(cert);
1049 0 : if (!pipCert)
1050 0 : return NS_ERROR_FAILURE;
1051 0 : CERTCertificate *nsscert = pipCert->GetCert();
1052 0 : CERTCertificateCleaner certCleaner(nsscert);
1053 0 : if (type == nsIX509Cert::CA_CERT) {
1054 : // always start with untrusted and move up
1055 0 : trust.SetValidCA();
1056 : trust.AddCATrust(!!(trusted & nsIX509CertDB::TRUSTED_SSL),
1057 : !!(trusted & nsIX509CertDB::TRUSTED_EMAIL),
1058 0 : !!(trusted & nsIX509CertDB::TRUSTED_OBJSIGN));
1059 : srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
1060 : nsscert,
1061 0 : trust.GetTrust());
1062 0 : } else if (type == nsIX509Cert::SERVER_CERT) {
1063 : // always start with untrusted and move up
1064 0 : trust.SetValidPeer();
1065 0 : trust.AddPeerTrust(trusted & nsIX509CertDB::TRUSTED_SSL, 0, 0);
1066 : srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
1067 : nsscert,
1068 0 : trust.GetTrust());
1069 0 : } else if (type == nsIX509Cert::EMAIL_CERT) {
1070 : // always start with untrusted and move up
1071 0 : trust.SetValidPeer();
1072 0 : trust.AddPeerTrust(0, !!(trusted & nsIX509CertDB::TRUSTED_EMAIL), 0);
1073 : srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
1074 : nsscert,
1075 0 : trust.GetTrust());
1076 : } else {
1077 : // ignore user certs
1078 0 : return NS_OK;
1079 : }
1080 0 : return (srv) ? NS_ERROR_FAILURE : NS_OK;
1081 : }
1082 :
1083 : NS_IMETHODIMP
1084 0 : nsNSSCertificateDB::IsCertTrusted(nsIX509Cert *cert,
1085 : PRUint32 certType,
1086 : PRUint32 trustType,
1087 : bool *_isTrusted)
1088 : {
1089 0 : NS_ENSURE_ARG_POINTER(_isTrusted);
1090 0 : *_isTrusted = false;
1091 :
1092 0 : nsNSSShutDownPreventionLock locker;
1093 : SECStatus srv;
1094 0 : nsCOMPtr<nsIX509Cert2> pipCert = do_QueryInterface(cert);
1095 0 : CERTCertificate *nsscert = pipCert->GetCert();
1096 : CERTCertTrust nsstrust;
1097 0 : srv = CERT_GetCertTrust(nsscert, &nsstrust);
1098 0 : if (srv != SECSuccess)
1099 0 : return NS_ERROR_FAILURE;
1100 :
1101 0 : nsNSSCertTrust trust(&nsstrust);
1102 0 : CERT_DestroyCertificate(nsscert);
1103 0 : if (certType == nsIX509Cert::CA_CERT) {
1104 0 : if (trustType & nsIX509CertDB::TRUSTED_SSL) {
1105 0 : *_isTrusted = trust.HasTrustedCA(true, false, false);
1106 0 : } else if (trustType & nsIX509CertDB::TRUSTED_EMAIL) {
1107 0 : *_isTrusted = trust.HasTrustedCA(false, true, false);
1108 0 : } else if (trustType & nsIX509CertDB::TRUSTED_OBJSIGN) {
1109 0 : *_isTrusted = trust.HasTrustedCA(false, false, true);
1110 : } else {
1111 0 : return NS_ERROR_FAILURE;
1112 : }
1113 0 : } else if (certType == nsIX509Cert::SERVER_CERT) {
1114 0 : if (trustType & nsIX509CertDB::TRUSTED_SSL) {
1115 0 : *_isTrusted = trust.HasTrustedPeer(true, false, false);
1116 0 : } else if (trustType & nsIX509CertDB::TRUSTED_EMAIL) {
1117 0 : *_isTrusted = trust.HasTrustedPeer(false, true, false);
1118 0 : } else if (trustType & nsIX509CertDB::TRUSTED_OBJSIGN) {
1119 0 : *_isTrusted = trust.HasTrustedPeer(false, false, true);
1120 : } else {
1121 0 : return NS_ERROR_FAILURE;
1122 : }
1123 0 : } else if (certType == nsIX509Cert::EMAIL_CERT) {
1124 0 : if (trustType & nsIX509CertDB::TRUSTED_SSL) {
1125 0 : *_isTrusted = trust.HasTrustedPeer(true, false, false);
1126 0 : } else if (trustType & nsIX509CertDB::TRUSTED_EMAIL) {
1127 0 : *_isTrusted = trust.HasTrustedPeer(false, true, false);
1128 0 : } else if (trustType & nsIX509CertDB::TRUSTED_OBJSIGN) {
1129 0 : *_isTrusted = trust.HasTrustedPeer(false, false, true);
1130 : } else {
1131 0 : return NS_ERROR_FAILURE;
1132 : }
1133 : } /* user: ignore */
1134 0 : return NS_OK;
1135 : }
1136 :
1137 :
1138 : NS_IMETHODIMP
1139 0 : nsNSSCertificateDB::ImportCertsFromFile(nsISupports *aToken,
1140 : nsILocalFile *aFile,
1141 : PRUint32 aType)
1142 : {
1143 0 : NS_ENSURE_ARG(aFile);
1144 0 : switch (aType) {
1145 : case nsIX509Cert::CA_CERT:
1146 : case nsIX509Cert::EMAIL_CERT:
1147 : case nsIX509Cert::SERVER_CERT:
1148 : // good
1149 : break;
1150 :
1151 : default:
1152 : // not supported (yet)
1153 0 : return NS_ERROR_FAILURE;
1154 : }
1155 :
1156 : nsresult rv;
1157 0 : PRFileDesc *fd = nsnull;
1158 :
1159 0 : rv = aFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
1160 :
1161 0 : if (NS_FAILED(rv))
1162 0 : return rv;
1163 :
1164 0 : if (!fd)
1165 0 : return NS_ERROR_FAILURE;
1166 :
1167 : PRFileInfo file_info;
1168 0 : if (PR_SUCCESS != PR_GetOpenFileInfo(fd, &file_info))
1169 0 : return NS_ERROR_FAILURE;
1170 :
1171 0 : unsigned char *buf = new unsigned char[file_info.size];
1172 0 : if (!buf)
1173 0 : return NS_ERROR_OUT_OF_MEMORY;
1174 :
1175 0 : PRInt32 bytes_obtained = PR_Read(fd, buf, file_info.size);
1176 0 : PR_Close(fd);
1177 :
1178 0 : if (bytes_obtained != file_info.size)
1179 0 : rv = NS_ERROR_FAILURE;
1180 : else {
1181 0 : nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext();
1182 :
1183 0 : switch (aType) {
1184 : case nsIX509Cert::CA_CERT:
1185 0 : rv = ImportCertificates(buf, bytes_obtained, aType, cxt);
1186 0 : break;
1187 :
1188 : case nsIX509Cert::SERVER_CERT:
1189 0 : rv = ImportServerCertificate(buf, bytes_obtained, cxt);
1190 0 : break;
1191 :
1192 : case nsIX509Cert::EMAIL_CERT:
1193 0 : rv = ImportEmailCertificate(buf, bytes_obtained, cxt);
1194 0 : break;
1195 :
1196 : default:
1197 0 : break;
1198 : }
1199 : }
1200 :
1201 0 : delete [] buf;
1202 0 : return rv;
1203 : }
1204 :
1205 : NS_IMETHODIMP
1206 0 : nsNSSCertificateDB::ImportPKCS12File(nsISupports *aToken,
1207 : nsILocalFile *aFile)
1208 : {
1209 0 : NS_ENSURE_ARG(aFile);
1210 0 : nsPKCS12Blob blob;
1211 0 : nsCOMPtr<nsIPK11Token> token = do_QueryInterface(aToken);
1212 0 : if (token) {
1213 0 : blob.SetToken(token);
1214 : }
1215 0 : return blob.ImportFromFile(aFile);
1216 : }
1217 :
1218 : NS_IMETHODIMP
1219 0 : nsNSSCertificateDB::ExportPKCS12File(nsISupports *aToken,
1220 : nsILocalFile *aFile,
1221 : PRUint32 count,
1222 : nsIX509Cert **certs)
1223 : //const PRUnichar **aCertNames)
1224 : {
1225 0 : nsNSSShutDownPreventionLock locker;
1226 0 : NS_ENSURE_ARG(aFile);
1227 0 : nsPKCS12Blob blob;
1228 0 : if (count == 0) return NS_OK;
1229 0 : nsCOMPtr<nsIPK11Token> localRef;
1230 0 : if (!aToken) {
1231 0 : PK11SlotInfo *keySlot = PK11_GetInternalKeySlot();
1232 0 : NS_ASSERTION(keySlot,"Failed to get the internal key slot");
1233 0 : localRef = new nsPK11Token(keySlot);
1234 0 : PK11_FreeSlot(keySlot);
1235 : }
1236 : else {
1237 0 : localRef = do_QueryInterface(aToken);
1238 : }
1239 0 : blob.SetToken(localRef);
1240 : //blob.LoadCerts(aCertNames, count);
1241 : //return blob.ExportToFile(aFile);
1242 0 : return blob.ExportToFile(aFile, certs, count);
1243 : }
1244 :
1245 :
1246 : static SECStatus PR_CALLBACK
1247 0 : GetOCSPResponders (CERTCertificate *aCert,
1248 : SECItem *aDBKey,
1249 : void *aArg)
1250 : {
1251 0 : nsIMutableArray *array = static_cast<nsIMutableArray*>(aArg);
1252 0 : PRUnichar* nn = nsnull;
1253 0 : PRUnichar* url = nsnull;
1254 0 : char *serviceURL = nsnull;
1255 0 : char *nickname = nsnull;
1256 : PRUint32 i, count;
1257 :
1258 : // Are we interested in this cert //
1259 0 : if (!nsOCSPResponder::IncludeCert(aCert)) {
1260 0 : return SECSuccess;
1261 : }
1262 :
1263 : // Get the AIA and nickname //
1264 0 : serviceURL = CERT_GetOCSPAuthorityInfoAccessLocation(aCert);
1265 0 : if (serviceURL) {
1266 0 : url = ToNewUnicode(NS_ConvertUTF8toUTF16(serviceURL));
1267 0 : PORT_Free(serviceURL);
1268 : }
1269 :
1270 0 : nickname = aCert->nickname;
1271 0 : nn = ToNewUnicode(NS_ConvertUTF8toUTF16(nickname));
1272 :
1273 0 : nsCOMPtr<nsIOCSPResponder> new_entry = new nsOCSPResponder(nn, url);
1274 0 : nsMemory::Free(nn);
1275 0 : nsMemory::Free(url);
1276 :
1277 : // Sort the items according to nickname //
1278 0 : array->GetLength(&count);
1279 0 : for (i=0; i < count; ++i) {
1280 0 : nsCOMPtr<nsIOCSPResponder> entry = do_QueryElementAt(array, i);
1281 0 : if (nsOCSPResponder::CompareEntries(new_entry, entry) < 0) {
1282 0 : array->InsertElementAt(new_entry, i, false);
1283 : break;
1284 : }
1285 : }
1286 0 : if (i == count) {
1287 0 : array->AppendElement(new_entry, false);
1288 : }
1289 0 : return SECSuccess;
1290 : }
1291 :
1292 :
1293 :
1294 : /*
1295 : * getOCSPResponders
1296 : *
1297 : * Export a set of certs and keys from the database to a PKCS#12 file.
1298 : */
1299 : NS_IMETHODIMP
1300 0 : nsNSSCertificateDB::GetOCSPResponders(nsIArray ** aResponders)
1301 : {
1302 0 : nsNSSShutDownPreventionLock locker;
1303 : SECStatus sec_rv;
1304 : nsCOMPtr<nsIMutableArray> respondersArray =
1305 0 : do_CreateInstance(NS_ARRAY_CONTRACTID);
1306 0 : if (!respondersArray) {
1307 0 : return NS_ERROR_OUT_OF_MEMORY;
1308 : }
1309 :
1310 : sec_rv = PK11_TraverseSlotCerts(::GetOCSPResponders,
1311 : respondersArray,
1312 0 : nsnull);
1313 0 : if (sec_rv != SECSuccess) {
1314 0 : goto loser;
1315 : }
1316 :
1317 0 : *aResponders = respondersArray;
1318 0 : NS_IF_ADDREF(*aResponders);
1319 0 : return NS_OK;
1320 : loser:
1321 0 : return NS_ERROR_FAILURE;
1322 : }
1323 :
1324 : /*
1325 : * NSS Helper Routines (private to nsNSSCertificateDB)
1326 : */
1327 :
1328 : #define DELIM '\001'
1329 :
1330 : /*
1331 : * GetSortedNameList
1332 : *
1333 : * Converts a CERTCertList to a list of certificate names
1334 : */
1335 : void
1336 0 : nsNSSCertificateDB::getCertNames(CERTCertList *certList,
1337 : PRUint32 type,
1338 : PRUint32 *_count,
1339 : PRUnichar ***_certNames)
1340 : {
1341 0 : nsNSSShutDownPreventionLock locker;
1342 : CERTCertListNode *node;
1343 0 : PRUint32 numcerts = 0, i=0;
1344 0 : PRUnichar **tmpArray = NULL;
1345 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("List of certs %d:\n", type));
1346 0 : for (node = CERT_LIST_HEAD(certList);
1347 0 : !CERT_LIST_END(node, certList);
1348 : node = CERT_LIST_NEXT(node)) {
1349 0 : if (getCertType(node->cert) == type) {
1350 0 : numcerts++;
1351 : }
1352 : }
1353 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("num certs: %d\n", numcerts));
1354 0 : int nc = (numcerts == 0) ? 1 : numcerts;
1355 0 : tmpArray = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *) * nc);
1356 0 : if (numcerts == 0) goto finish;
1357 0 : for (node = CERT_LIST_HEAD(certList);
1358 0 : !CERT_LIST_END(node, certList);
1359 : node = CERT_LIST_NEXT(node)) {
1360 0 : if (getCertType(node->cert) == type) {
1361 0 : nsNSSCertificate pipCert(node->cert);
1362 0 : char *dbkey = NULL;
1363 0 : char *namestr = NULL;
1364 0 : nsAutoString certstr;
1365 0 : pipCert.GetDbKey(&dbkey);
1366 0 : nsAutoString keystr = NS_ConvertASCIItoUTF16(dbkey);
1367 0 : PR_FREEIF(dbkey);
1368 0 : if (type == nsIX509Cert::EMAIL_CERT) {
1369 0 : namestr = node->cert->emailAddr;
1370 : } else {
1371 0 : namestr = node->cert->nickname;
1372 0 : if (namestr) {
1373 0 : char *sc = strchr(namestr, ':');
1374 0 : if (sc) *sc = DELIM;
1375 : }
1376 : }
1377 0 : nsAutoString certname = NS_ConvertASCIItoUTF16(namestr ? namestr : "");
1378 0 : certstr.Append(PRUnichar(DELIM));
1379 0 : certstr += certname;
1380 0 : certstr.Append(PRUnichar(DELIM));
1381 0 : certstr += keystr;
1382 0 : tmpArray[i++] = ToNewUnicode(certstr);
1383 : }
1384 : }
1385 : finish:
1386 0 : *_count = numcerts;
1387 0 : *_certNames = tmpArray;
1388 0 : }
1389 :
1390 : /* somewhat follows logic of cert_list_include_cert from PSM 1.x */
1391 :
1392 :
1393 : NS_IMETHODIMP
1394 4 : nsNSSCertificateDB::GetIsOcspOn(bool *aOcspOn)
1395 : {
1396 8 : nsCOMPtr<nsIPrefBranch> pref = do_GetService(NS_PREFSERVICE_CONTRACTID);
1397 :
1398 : PRInt32 ocspEnabled;
1399 4 : pref->GetIntPref("security.OCSP.enabled", &ocspEnabled);
1400 4 : *aOcspOn = ( ocspEnabled == 0 ) ? false : true;
1401 4 : return NS_OK;
1402 : }
1403 :
1404 : /* nsIX509Cert getDefaultEmailEncryptionCert (); */
1405 : NS_IMETHODIMP
1406 0 : nsNSSCertificateDB::FindEmailEncryptionCert(const nsAString &aNickname, nsIX509Cert **_retval)
1407 : {
1408 0 : if (!_retval)
1409 0 : return NS_ERROR_FAILURE;
1410 :
1411 0 : *_retval = 0;
1412 :
1413 0 : if (aNickname.IsEmpty())
1414 0 : return NS_OK;
1415 :
1416 0 : nsNSSShutDownPreventionLock locker;
1417 0 : nsresult rv = NS_OK;
1418 0 : CERTCertificate *cert = 0;
1419 0 : nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
1420 0 : nsNSSCertificate *nssCert = nsnull;
1421 0 : char *asciiname = NULL;
1422 0 : NS_ConvertUTF16toUTF8 aUtf8Nickname(aNickname);
1423 0 : asciiname = const_cast<char*>(aUtf8Nickname.get());
1424 :
1425 : /* Find a good cert in the user's database */
1426 : cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(), asciiname,
1427 0 : certUsageEmailRecipient, true, ctx);
1428 :
1429 0 : if (!cert) { goto loser; }
1430 :
1431 0 : nssCert = nsNSSCertificate::Create(cert);
1432 0 : if (nssCert == nsnull) {
1433 0 : rv = NS_ERROR_OUT_OF_MEMORY;
1434 : }
1435 0 : NS_ADDREF(nssCert);
1436 :
1437 0 : *_retval = static_cast<nsIX509Cert*>(nssCert);
1438 :
1439 : loser:
1440 0 : if (cert) CERT_DestroyCertificate(cert);
1441 0 : return rv;
1442 : }
1443 :
1444 : /* nsIX509Cert getDefaultEmailSigningCert (); */
1445 : NS_IMETHODIMP
1446 0 : nsNSSCertificateDB::FindEmailSigningCert(const nsAString &aNickname, nsIX509Cert **_retval)
1447 : {
1448 0 : if (!_retval)
1449 0 : return NS_ERROR_FAILURE;
1450 :
1451 0 : *_retval = 0;
1452 :
1453 0 : if (aNickname.IsEmpty())
1454 0 : return NS_OK;
1455 :
1456 0 : nsNSSShutDownPreventionLock locker;
1457 0 : nsresult rv = NS_OK;
1458 0 : CERTCertificate *cert = 0;
1459 0 : nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
1460 0 : nsNSSCertificate *nssCert = nsnull;
1461 0 : char *asciiname = NULL;
1462 0 : NS_ConvertUTF16toUTF8 aUtf8Nickname(aNickname);
1463 0 : asciiname = const_cast<char*>(aUtf8Nickname.get());
1464 :
1465 : /* Find a good cert in the user's database */
1466 : cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(), asciiname,
1467 0 : certUsageEmailSigner, true, ctx);
1468 :
1469 0 : if (!cert) { goto loser; }
1470 :
1471 0 : nssCert = nsNSSCertificate::Create(cert);
1472 0 : if (nssCert == nsnull) {
1473 0 : rv = NS_ERROR_OUT_OF_MEMORY;
1474 : }
1475 0 : NS_ADDREF(nssCert);
1476 :
1477 0 : *_retval = static_cast<nsIX509Cert*>(nssCert);
1478 :
1479 : loser:
1480 0 : if (cert) CERT_DestroyCertificate(cert);
1481 0 : return rv;
1482 : }
1483 :
1484 : NS_IMETHODIMP
1485 0 : nsNSSCertificateDB::FindCertByEmailAddress(nsISupports *aToken, const char *aEmailAddress, nsIX509Cert **_retval)
1486 : {
1487 0 : nsNSSShutDownPreventionLock locker;
1488 :
1489 0 : nsCOMPtr<nsINSSComponent> inss;
1490 0 : nsRefPtr<nsCERTValInParamWrapper> survivingParams;
1491 : nsresult nsrv;
1492 :
1493 0 : if (nsNSSComponent::globalConstFlagUsePKIXVerification) {
1494 0 : inss = do_GetService(kNSSComponentCID, &nsrv);
1495 0 : if (!inss)
1496 0 : return nsrv;
1497 0 : nsrv = inss->GetDefaultCERTValInParam(survivingParams);
1498 0 : if (NS_FAILED(nsrv))
1499 0 : return nsrv;
1500 : }
1501 :
1502 0 : CERTCertList *certlist = PK11_FindCertsFromEmailAddress(aEmailAddress, nsnull);
1503 0 : if (!certlist)
1504 0 : return NS_ERROR_FAILURE;
1505 :
1506 : // certlist now contains certificates with the right email address,
1507 : // but they might not have the correct usage or might even be invalid
1508 :
1509 0 : CERTCertListCleaner listCleaner(certlist);
1510 :
1511 0 : if (CERT_LIST_END(CERT_LIST_HEAD(certlist), certlist))
1512 0 : return NS_ERROR_FAILURE; // no certs found
1513 :
1514 : CERTCertListNode *node;
1515 : // search for a valid certificate
1516 0 : for (node = CERT_LIST_HEAD(certlist);
1517 0 : !CERT_LIST_END(node, certlist);
1518 : node = CERT_LIST_NEXT(node)) {
1519 :
1520 0 : if (!nsNSSComponent::globalConstFlagUsePKIXVerification) {
1521 0 : if (CERT_VerifyCert(CERT_GetDefaultCertDB(), node->cert,
1522 0 : true, certUsageEmailRecipient, PR_Now(), nsnull, nsnull) == SECSuccess) {
1523 : // found a valid certificate
1524 0 : break;
1525 : }
1526 : }
1527 : else {
1528 : CERTValOutParam cvout[1];
1529 0 : cvout[0].type = cert_po_end;
1530 0 : if (CERT_PKIXVerifyCert(node->cert, certificateUsageEmailRecipient,
1531 : survivingParams->GetRawPointerForNSS(),
1532 0 : cvout, nsnull)
1533 : == SECSuccess) {
1534 : // found a valid certificate
1535 0 : break;
1536 : }
1537 : }
1538 : }
1539 :
1540 0 : if (CERT_LIST_END(node, certlist)) {
1541 : // no valid cert found
1542 0 : return NS_ERROR_FAILURE;
1543 : }
1544 :
1545 : // node now contains the first valid certificate with correct usage
1546 0 : nsNSSCertificate *nssCert = nsNSSCertificate::Create(node->cert);
1547 0 : if (!nssCert)
1548 0 : return NS_ERROR_OUT_OF_MEMORY;
1549 :
1550 0 : NS_ADDREF(nssCert);
1551 0 : *_retval = static_cast<nsIX509Cert*>(nssCert);
1552 0 : return NS_OK;
1553 : }
1554 :
1555 : /* nsIX509Cert constructX509FromBase64 (in string base64); */
1556 : NS_IMETHODIMP
1557 0 : nsNSSCertificateDB::ConstructX509FromBase64(const char *base64,
1558 : nsIX509Cert **_retval)
1559 : {
1560 0 : NS_ENSURE_ARG_POINTER(_retval);
1561 :
1562 : // sure would be nice to have a smart pointer class for PL_ allocations
1563 : // unfortunately, we cannot distinguish out-of-memory from bad-input here
1564 0 : PRUint32 len = PL_strlen(base64);
1565 0 : char *certDER = PL_Base64Decode(base64, len, NULL);
1566 0 : if (!certDER)
1567 0 : return NS_ERROR_ILLEGAL_VALUE;
1568 0 : if (!*certDER) {
1569 0 : PL_strfree(certDER);
1570 0 : return NS_ERROR_ILLEGAL_VALUE;
1571 : }
1572 :
1573 : // If we get to this point, we know we had well-formed base64 input;
1574 : // therefore the input string cannot have been less than two
1575 : // characters long. Compute the unpadded length of the decoded data.
1576 0 : PRUint32 lengthDER = (len * 3) / 4;
1577 0 : if (base64[len-1] == '=') {
1578 0 : lengthDER--;
1579 0 : if (base64[len-2] == '=')
1580 0 : lengthDER--;
1581 : }
1582 :
1583 0 : nsNSSShutDownPreventionLock locker;
1584 : SECItem secitem_cert;
1585 0 : secitem_cert.type = siDERCertBuffer;
1586 0 : secitem_cert.data = (unsigned char*)certDER;
1587 0 : secitem_cert.len = lengthDER;
1588 :
1589 : CERTCertificate *cert =
1590 : CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &secitem_cert,
1591 0 : nsnull, false, true);
1592 0 : PL_strfree(certDER);
1593 :
1594 0 : if (!cert)
1595 0 : return (PORT_GetError() == SEC_ERROR_NO_MEMORY)
1596 0 : ? NS_ERROR_OUT_OF_MEMORY : NS_ERROR_FAILURE;
1597 :
1598 0 : nsNSSCertificate *nsNSS = nsNSSCertificate::Create(cert);
1599 0 : CERT_DestroyCertificate(cert);
1600 :
1601 0 : if (!nsNSS)
1602 0 : return NS_ERROR_OUT_OF_MEMORY;
1603 :
1604 0 : return CallQueryInterface(nsNSS, _retval);
1605 : }
1606 :
1607 : void
1608 0 : nsNSSCertificateDB::get_default_nickname(CERTCertificate *cert,
1609 : nsIInterfaceRequestor* ctx,
1610 : nsCString &nickname)
1611 : {
1612 0 : nickname.Truncate();
1613 :
1614 0 : nsNSSShutDownPreventionLock locker;
1615 : nsresult rv;
1616 : CK_OBJECT_HANDLE keyHandle;
1617 :
1618 0 : CERTCertDBHandle *defaultcertdb = CERT_GetDefaultCertDB();
1619 0 : nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
1620 0 : if (NS_FAILED(rv))
1621 : return;
1622 :
1623 0 : nsCAutoString username;
1624 0 : char *temp_un = CERT_GetCommonName(&cert->subject);
1625 0 : if (temp_un) {
1626 0 : username = temp_un;
1627 0 : PORT_Free(temp_un);
1628 0 : temp_un = nsnull;
1629 : }
1630 :
1631 0 : nsCAutoString caname;
1632 0 : char *temp_ca = CERT_GetOrgName(&cert->issuer);
1633 0 : if (temp_ca) {
1634 0 : caname = temp_ca;
1635 0 : PORT_Free(temp_ca);
1636 0 : temp_ca = nsnull;
1637 : }
1638 :
1639 0 : nsAutoString tmpNickFmt;
1640 0 : nssComponent->GetPIPNSSBundleString("nick_template", tmpNickFmt);
1641 0 : NS_ConvertUTF16toUTF8 nickFmt(tmpNickFmt);
1642 :
1643 0 : nsCAutoString baseName;
1644 0 : char *temp_nn = PR_smprintf(nickFmt.get(), username.get(), caname.get());
1645 0 : if (!temp_nn) {
1646 : return;
1647 : } else {
1648 0 : baseName = temp_nn;
1649 0 : PR_smprintf_free(temp_nn);
1650 0 : temp_nn = nsnull;
1651 : }
1652 :
1653 0 : nickname = baseName;
1654 :
1655 : /*
1656 : * We need to see if the private key exists on a token, if it does
1657 : * then we need to check for nicknames that already exist on the smart
1658 : * card.
1659 : */
1660 0 : PK11SlotInfo *slot = PK11_KeyForCertExists(cert, &keyHandle, ctx);
1661 0 : PK11SlotInfoCleaner slotCleaner(slot);
1662 0 : if (!slot)
1663 : return;
1664 :
1665 0 : if (!PK11_IsInternal(slot)) {
1666 0 : char *tmp = PR_smprintf("%s:%s", PK11_GetTokenName(slot), baseName.get());
1667 0 : if (!tmp) {
1668 0 : nickname.Truncate();
1669 : return;
1670 : }
1671 0 : baseName = tmp;
1672 0 : PR_smprintf_free(tmp);
1673 :
1674 0 : nickname = baseName;
1675 : }
1676 :
1677 0 : int count = 1;
1678 0 : while (true) {
1679 0 : if ( count > 1 ) {
1680 0 : char *tmp = PR_smprintf("%s #%d", baseName.get(), count);
1681 0 : if (!tmp) {
1682 0 : nickname.Truncate();
1683 : return;
1684 : }
1685 0 : nickname = tmp;
1686 0 : PR_smprintf_free(tmp);
1687 : }
1688 :
1689 0 : CERTCertificate *dummycert = nsnull;
1690 0 : CERTCertificateCleaner dummycertCleaner(dummycert);
1691 :
1692 0 : if (PK11_IsInternal(slot)) {
1693 : /* look up the nickname to make sure it isn't in use already */
1694 0 : dummycert = CERT_FindCertByNickname(defaultcertdb, nickname.get());
1695 :
1696 : } else {
1697 : /*
1698 : * Check the cert against others that already live on the smart
1699 : * card.
1700 : */
1701 0 : dummycert = PK11_FindCertFromNickname(nickname.get(), ctx);
1702 0 : if (dummycert != NULL) {
1703 : /*
1704 : * Make sure the subject names are different.
1705 : */
1706 0 : if (CERT_CompareName(&cert->subject, &dummycert->subject) == SECEqual)
1707 : {
1708 : /*
1709 : * There is another certificate with the same nickname and
1710 : * the same subject name on the smart card, so let's use this
1711 : * nickname.
1712 : */
1713 0 : CERT_DestroyCertificate(dummycert);
1714 0 : dummycert = NULL;
1715 : }
1716 : }
1717 : }
1718 0 : if (!dummycert)
1719 : break;
1720 :
1721 0 : count++;
1722 : }
1723 : }
1724 :
1725 0 : NS_IMETHODIMP nsNSSCertificateDB::AddCertFromBase64(const char *aBase64, const char *aTrust, const char *aName)
1726 : {
1727 0 : NS_ENSURE_ARG_POINTER(aBase64);
1728 0 : nsCOMPtr <nsIX509Cert> newCert;
1729 :
1730 0 : nsNSSCertTrust trust;
1731 :
1732 : // need to calculate the trust bits from the aTrust string.
1733 0 : nsresult rv = CERT_DecodeTrustString(trust.GetTrust(), /* this is const, but not declared that way */(char *) aTrust);
1734 0 : NS_ENSURE_SUCCESS(rv, rv); // if bad trust passed in, return error.
1735 :
1736 :
1737 0 : rv = ConstructX509FromBase64(aBase64, getter_AddRefs(newCert));
1738 0 : NS_ENSURE_SUCCESS(rv, rv);
1739 :
1740 : SECItem der;
1741 0 : rv = newCert->GetRawDER(&der.len, (PRUint8 **)&der.data);
1742 0 : NS_ENSURE_SUCCESS(rv, rv);
1743 :
1744 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Creating temp cert\n"));
1745 : CERTCertificate *tmpCert;
1746 0 : CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
1747 0 : tmpCert = CERT_FindCertByDERCert(certdb, &der);
1748 0 : if (!tmpCert)
1749 : tmpCert = CERT_NewTempCertificate(certdb, &der,
1750 0 : nsnull, false, true);
1751 0 : nsMemory::Free(der.data);
1752 0 : der.data = nsnull;
1753 0 : der.len = 0;
1754 :
1755 0 : if (!tmpCert) {
1756 0 : NS_ERROR("Couldn't create cert from DER blob");
1757 0 : return NS_ERROR_FAILURE;
1758 : }
1759 :
1760 0 : if (tmpCert->isperm) {
1761 0 : CERT_DestroyCertificate(tmpCert);
1762 0 : return NS_OK;
1763 : }
1764 :
1765 0 : CERTCertificateCleaner tmpCertCleaner(tmpCert);
1766 :
1767 0 : nsXPIDLCString nickname;
1768 0 : nickname.Adopt(CERT_MakeCANickname(tmpCert));
1769 :
1770 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Created nick \"%s\"\n", nickname.get()));
1771 :
1772 : SECStatus srv = CERT_AddTempCertToPerm(tmpCert,
1773 0 : const_cast<char*>(nickname.get()),
1774 0 : trust.GetTrust());
1775 :
1776 :
1777 0 : return (srv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
1778 : }
1779 :
1780 : NS_IMETHODIMP
1781 0 : nsNSSCertificateDB::GetCerts(nsIX509CertList **_retval)
1782 : {
1783 : CERTCertList *certList;
1784 :
1785 0 : nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
1786 0 : nsCOMPtr<nsIX509CertList> nssCertList;
1787 0 : certList = PK11_ListCerts(PK11CertListUnique, ctx);
1788 :
1789 : // nsNSSCertList 1) adopts certList, and 2) handles the NULL case fine.
1790 : // (returns an empty list)
1791 0 : nssCertList = new nsNSSCertList(certList, true);
1792 0 : if (!nssCertList) { return NS_ERROR_OUT_OF_MEMORY; }
1793 :
1794 0 : *_retval = nssCertList;
1795 0 : NS_ADDREF(*_retval);
1796 0 : return NS_OK;
1797 : }
|