1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is the Netscape security libraries.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 2000
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Ian McGreer <mcgreer@netscape.com>
24 : * Javier Delgadillo <javi@netscape.com>
25 : * Kai Engert <kengert@redhat.com>
26 : * Jesper Kristensen <mail@jesperkristensen.dk>
27 : *
28 : * Alternatively, the contents of this file may be used under the terms of
29 : * either the GNU General Public License Version 2 or later (the "GPL"), or
30 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 : * in which case the provisions of the GPL or the LGPL are applicable instead
32 : * of those above. If you wish to allow use of your version of this file only
33 : * under the terms of either the GPL or the LGPL, and not to allow others to
34 : * use your version of this file under the terms of the MPL, indicate your
35 : * decision by deleting the provisions above and replace them with the notice
36 : * and other provisions required by the GPL or the LGPL. If you do not delete
37 : * the provisions above, a recipient may use your version of this file under
38 : * the terms of any one of the MPL, the GPL or the LGPL.
39 : *
40 : * ***** END LICENSE BLOCK ***** */
41 :
42 : #include "prmem.h"
43 : #include "prerror.h"
44 : #include "prprf.h"
45 :
46 : #include "nsNSSComponent.h" // for PIPNSS string bundle calls.
47 : #include "nsNSSCleaner.h"
48 : #include "nsCOMPtr.h"
49 : #include "nsIMutableArray.h"
50 : #include "nsNSSCertificate.h"
51 : #include "nsNSSCertValidity.h"
52 : #include "nsPKCS12Blob.h"
53 : #include "nsPK11TokenDB.h"
54 : #include "nsIX509Cert.h"
55 : #include "nsIX509Cert3.h"
56 : #include "nsISMimeCert.h"
57 : #include "nsNSSASN1Object.h"
58 : #include "nsString.h"
59 : #include "nsXPIDLString.h"
60 : #include "nsReadableUtils.h"
61 : #include "nsIURI.h"
62 : #include "nsCRT.h"
63 : #include "nsUsageArrayHelper.h"
64 : #include "nsICertificateDialogs.h"
65 : #include "nsNSSCertHelper.h"
66 : #include "nsISupportsPrimitives.h"
67 : #include "nsUnicharUtils.h"
68 : #include "nsThreadUtils.h"
69 : #include "nsCertVerificationThread.h"
70 : #include "nsIObjectOutputStream.h"
71 : #include "nsIObjectInputStream.h"
72 : #include "nsIProgrammingLanguage.h"
73 :
74 : #include "nsXULAppAPI.h"
75 :
76 : #include "nspr.h"
77 : extern "C" {
78 : #include "pk11func.h"
79 : #include "certdb.h"
80 : #include "cert.h"
81 : #include "secerr.h"
82 : #include "nssb64.h"
83 : #include "secasn1.h"
84 : #include "secder.h"
85 : }
86 : #include "ssl.h"
87 : #include "ocsp.h"
88 : #include "plbase64.h"
89 : #include "cms.h"
90 : #include "cert.h"
91 :
92 : #ifdef PR_LOGGING
93 : extern PRLogModuleInfo* gPIPNSSLog;
94 : #endif
95 :
96 : static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
97 :
98 0 : NSSCleanupAutoPtrClass(CERTCertificateList, CERT_DestroyCertificateList)
99 0 : NSSCleanupAutoPtrClass(CERTCertificate, CERT_DestroyCertificate)
100 0 : NSSCleanupAutoPtrClass(NSSCMSMessage, NSS_CMSMessage_Destroy)
101 0 : NSSCleanupAutoPtrClass_WithParam(PLArenaPool, PORT_FreeArena, FalseParam, false)
102 0 : NSSCleanupAutoPtrClass(NSSCMSSignedData, NSS_CMSSignedData_Destroy)
103 0 : NSSCleanupAutoPtrClass(PK11SlotList, PK11_FreeSlotList)
104 :
105 : // This is being stored in an PRUint32 that can otherwise
106 : // only take values from nsIX509Cert's list of cert types.
107 : // As nsIX509Cert is frozen, we choose a value not contained
108 : // in the list to mean not yet initialized.
109 : #define CERT_TYPE_NOT_YET_INITIALIZED (1 << 30)
110 :
111 : /* nsNSSCertificate */
112 :
113 80 : NS_IMPL_THREADSAFE_ISUPPORTS7(nsNSSCertificate, nsIX509Cert,
114 : nsIX509Cert2,
115 : nsIX509Cert3,
116 : nsIIdentityInfo,
117 : nsISMimeCert,
118 : nsISerializable,
119 : nsIClassInfo)
120 :
121 : /* static */
122 : nsNSSCertificate*
123 8 : nsNSSCertificate::Create(CERTCertificate *cert)
124 : {
125 8 : if (GeckoProcessType_Default != XRE_GetProcessType()) {
126 0 : NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!");
127 0 : return nsnull;
128 : }
129 8 : if (cert)
130 8 : return new nsNSSCertificate(cert);
131 : else
132 0 : return new nsNSSCertificate();
133 : }
134 :
135 : nsNSSCertificate*
136 0 : nsNSSCertificate::ConstructFromDER(char *certDER, int derLen)
137 : {
138 : // On non-chrome process prevent instantiation
139 0 : if (GeckoProcessType_Default != XRE_GetProcessType())
140 0 : return nsnull;
141 :
142 0 : nsNSSCertificate* newObject = nsNSSCertificate::Create();
143 0 : if (newObject && !newObject->InitFromDER(certDER, derLen)) {
144 0 : delete newObject;
145 0 : newObject = nsnull;
146 : }
147 :
148 0 : return newObject;
149 : }
150 :
151 : bool
152 0 : nsNSSCertificate::InitFromDER(char *certDER, int derLen)
153 : {
154 0 : nsNSSShutDownPreventionLock locker;
155 0 : if (isAlreadyShutDown())
156 0 : return false;
157 :
158 0 : if (!certDER || !derLen)
159 0 : return false;
160 :
161 0 : CERTCertificate *aCert = CERT_DecodeCertFromPackage(certDER, derLen);
162 :
163 0 : if (!aCert)
164 0 : return false;
165 :
166 0 : if(aCert->dbhandle == nsnull)
167 : {
168 0 : aCert->dbhandle = CERT_GetDefaultCertDB();
169 : }
170 :
171 0 : mCert = aCert;
172 0 : return true;
173 : }
174 :
175 176 : nsNSSCertificate::nsNSSCertificate(CERTCertificate *cert) :
176 : mCert(nsnull),
177 : mPermDelete(false),
178 : mCertType(CERT_TYPE_NOT_YET_INITIALIZED),
179 176 : mCachedEVStatus(ev_status_unknown)
180 : {
181 : #if defined(DEBUG)
182 176 : if (GeckoProcessType_Default != XRE_GetProcessType())
183 0 : NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!");
184 : #endif
185 :
186 352 : nsNSSShutDownPreventionLock locker;
187 176 : if (isAlreadyShutDown())
188 : return;
189 :
190 176 : if (cert)
191 176 : mCert = CERT_DupCertificate(cert);
192 : }
193 :
194 0 : nsNSSCertificate::nsNSSCertificate() :
195 : mCert(nsnull),
196 : mPermDelete(false),
197 : mCertType(CERT_TYPE_NOT_YET_INITIALIZED),
198 0 : mCachedEVStatus(ev_status_unknown)
199 : {
200 0 : if (GeckoProcessType_Default != XRE_GetProcessType())
201 0 : NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!");
202 0 : }
203 :
204 360 : nsNSSCertificate::~nsNSSCertificate()
205 : {
206 352 : nsNSSShutDownPreventionLock locker;
207 176 : if (isAlreadyShutDown())
208 : return;
209 :
210 172 : destructorSafeDestroyNSSReference();
211 348 : shutdown(calledFromObject);
212 368 : }
213 :
214 4 : void nsNSSCertificate::virtualDestroyNSSReference()
215 : {
216 4 : destructorSafeDestroyNSSReference();
217 4 : }
218 :
219 176 : void nsNSSCertificate::destructorSafeDestroyNSSReference()
220 : {
221 176 : if (isAlreadyShutDown())
222 0 : return;
223 :
224 176 : if (mPermDelete) {
225 0 : if (mCertType == nsNSSCertificate::USER_CERT) {
226 0 : nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext();
227 0 : PK11_DeleteTokenCertAndKey(mCert, cxt);
228 0 : } else if (!PK11_IsReadOnly(mCert->slot)) {
229 : // If the list of built-ins does contain a non-removable
230 : // copy of this certificate, our call will not remove
231 : // the certificate permanently, but rather remove all trust.
232 0 : SEC_DeletePermCertificate(mCert);
233 : }
234 : }
235 :
236 176 : if (mCert) {
237 176 : CERT_DestroyCertificate(mCert);
238 176 : mCert = nsnull;
239 : }
240 : }
241 :
242 : nsresult
243 0 : nsNSSCertificate::GetCertType(PRUint32 *aCertType)
244 : {
245 0 : if (mCertType == CERT_TYPE_NOT_YET_INITIALIZED) {
246 : // only determine cert type once and cache it
247 0 : mCertType = getCertType(mCert);
248 : }
249 0 : *aCertType = mCertType;
250 0 : return NS_OK;
251 : }
252 :
253 : NS_IMETHODIMP
254 0 : nsNSSCertificate::GetIsSelfSigned(bool *aIsSelfSigned)
255 : {
256 0 : NS_ENSURE_ARG(aIsSelfSigned);
257 :
258 0 : nsNSSShutDownPreventionLock locker;
259 0 : if (isAlreadyShutDown())
260 0 : return NS_ERROR_NOT_AVAILABLE;
261 :
262 0 : *aIsSelfSigned = mCert->isRoot;
263 0 : return NS_OK;
264 : }
265 :
266 : nsresult
267 0 : nsNSSCertificate::MarkForPermDeletion()
268 : {
269 0 : nsNSSShutDownPreventionLock locker;
270 0 : if (isAlreadyShutDown())
271 0 : return NS_ERROR_NOT_AVAILABLE;
272 :
273 : // make sure user is logged in to the token
274 0 : nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
275 :
276 0 : if (PK11_NeedLogin(mCert->slot)
277 0 : && !PK11_NeedUserInit(mCert->slot)
278 0 : && !PK11_IsInternal(mCert->slot))
279 : {
280 0 : if (SECSuccess != PK11_Authenticate(mCert->slot, true, ctx))
281 : {
282 0 : return NS_ERROR_FAILURE;
283 : }
284 : }
285 :
286 0 : mPermDelete = true;
287 0 : return NS_OK;
288 : }
289 :
290 : nsresult
291 0 : GetKeyUsagesString(CERTCertificate *cert, nsINSSComponent *nssComponent,
292 : nsString &text)
293 : {
294 0 : text.Truncate();
295 :
296 : SECItem keyUsageItem;
297 0 : keyUsageItem.data = NULL;
298 :
299 : SECStatus srv;
300 :
301 : /* There is no extension, v1 or v2 certificate */
302 0 : if (!cert->extensions)
303 0 : return NS_OK;
304 :
305 :
306 0 : srv = CERT_FindKeyUsageExtension(cert, &keyUsageItem);
307 0 : if (srv == SECFailure) {
308 0 : if (PORT_GetError () == SEC_ERROR_EXTENSION_NOT_FOUND)
309 0 : return NS_OK;
310 : else
311 0 : return NS_ERROR_FAILURE;
312 : }
313 :
314 0 : unsigned char keyUsage = keyUsageItem.data[0];
315 0 : nsAutoString local;
316 : nsresult rv;
317 0 : const PRUnichar *comma = NS_LITERAL_STRING(",").get();
318 :
319 0 : if (keyUsage & KU_DIGITAL_SIGNATURE) {
320 0 : rv = nssComponent->GetPIPNSSBundleString("CertDumpKUSign", local);
321 0 : if (NS_SUCCEEDED(rv)) {
322 0 : if (!text.IsEmpty()) text.Append(comma);
323 0 : text.Append(local.get());
324 : }
325 : }
326 0 : if (keyUsage & KU_NON_REPUDIATION) {
327 0 : rv = nssComponent->GetPIPNSSBundleString("CertDumpKUNonRep", local);
328 0 : if (NS_SUCCEEDED(rv)) {
329 0 : if (!text.IsEmpty()) text.Append(comma);
330 0 : text.Append(local.get());
331 : }
332 : }
333 0 : if (keyUsage & KU_KEY_ENCIPHERMENT) {
334 0 : rv = nssComponent->GetPIPNSSBundleString("CertDumpKUEnc", local);
335 0 : if (NS_SUCCEEDED(rv)) {
336 0 : if (!text.IsEmpty()) text.Append(comma);
337 0 : text.Append(local.get());
338 : }
339 : }
340 0 : if (keyUsage & KU_DATA_ENCIPHERMENT) {
341 0 : rv = nssComponent->GetPIPNSSBundleString("CertDumpKUDEnc", local);
342 0 : if (NS_SUCCEEDED(rv)) {
343 0 : if (!text.IsEmpty()) text.Append(comma);
344 0 : text.Append(local.get());
345 : }
346 : }
347 0 : if (keyUsage & KU_KEY_AGREEMENT) {
348 0 : rv = nssComponent->GetPIPNSSBundleString("CertDumpKUKA", local);
349 0 : if (NS_SUCCEEDED(rv)) {
350 0 : if (!text.IsEmpty()) text.Append(comma);
351 0 : text.Append(local.get());
352 : }
353 : }
354 0 : if (keyUsage & KU_KEY_CERT_SIGN) {
355 0 : rv = nssComponent->GetPIPNSSBundleString("CertDumpKUCertSign", local);
356 0 : if (NS_SUCCEEDED(rv)) {
357 0 : if (!text.IsEmpty()) text.Append(comma);
358 0 : text.Append(local.get());
359 : }
360 : }
361 0 : if (keyUsage & KU_CRL_SIGN) {
362 0 : rv = nssComponent->GetPIPNSSBundleString("CertDumpKUCRLSign", local);
363 0 : if (NS_SUCCEEDED(rv)) {
364 0 : if (!text.IsEmpty()) text.Append(comma);
365 0 : text.Append(local.get());
366 : }
367 : }
368 :
369 0 : PORT_Free (keyUsageItem.data);
370 0 : return NS_OK;
371 : }
372 :
373 : nsresult
374 0 : nsNSSCertificate::FormatUIStrings(const nsAutoString &nickname, nsAutoString &nickWithSerial, nsAutoString &details)
375 : {
376 0 : if (!NS_IsMainThread()) {
377 0 : NS_ERROR("nsNSSCertificate::FormatUIStrings called off the main thread");
378 0 : return NS_ERROR_NOT_SAME_THREAD;
379 : }
380 :
381 0 : nsresult rv = NS_OK;
382 :
383 0 : nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
384 :
385 0 : if (NS_FAILED(rv) || !nssComponent) {
386 0 : return NS_ERROR_FAILURE;
387 : }
388 :
389 0 : nsAutoString info;
390 0 : nsAutoString temp1;
391 :
392 0 : nickWithSerial.Append(nickname);
393 :
394 0 : if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoIssuedFor", info))) {
395 0 : details.Append(info);
396 0 : details.Append(PRUnichar(' '));
397 0 : if (NS_SUCCEEDED(GetSubjectName(temp1)) && !temp1.IsEmpty()) {
398 0 : details.Append(temp1);
399 : }
400 0 : details.Append(PRUnichar('\n'));
401 : }
402 :
403 0 : if (NS_SUCCEEDED(GetSerialNumber(temp1)) && !temp1.IsEmpty()) {
404 0 : details.AppendLiteral(" ");
405 0 : if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertDumpSerialNo", info))) {
406 0 : details.Append(info);
407 0 : details.AppendLiteral(": ");
408 : }
409 0 : details.Append(temp1);
410 :
411 0 : nickWithSerial.AppendLiteral(" [");
412 0 : nickWithSerial.Append(temp1);
413 0 : nickWithSerial.Append(PRUnichar(']'));
414 :
415 0 : details.Append(PRUnichar('\n'));
416 : }
417 :
418 0 : nsCOMPtr<nsIX509CertValidity> validity;
419 0 : rv = GetValidity(getter_AddRefs(validity));
420 0 : if (NS_SUCCEEDED(rv) && validity) {
421 0 : details.AppendLiteral(" ");
422 0 : if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoValid", info))) {
423 0 : details.Append(info);
424 : }
425 :
426 0 : if (NS_SUCCEEDED(validity->GetNotBeforeLocalTime(temp1)) && !temp1.IsEmpty()) {
427 0 : details.Append(PRUnichar(' '));
428 0 : if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoFrom", info))) {
429 0 : details.Append(info);
430 0 : details.Append(PRUnichar(' '));
431 : }
432 0 : details.Append(temp1);
433 : }
434 :
435 0 : if (NS_SUCCEEDED(validity->GetNotAfterLocalTime(temp1)) && !temp1.IsEmpty()) {
436 0 : details.Append(PRUnichar(' '));
437 0 : if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoTo", info))) {
438 0 : details.Append(info);
439 0 : details.Append(PRUnichar(' '));
440 : }
441 0 : details.Append(temp1);
442 : }
443 :
444 0 : details.Append(PRUnichar('\n'));
445 : }
446 :
447 0 : if (NS_SUCCEEDED(GetKeyUsagesString(mCert, nssComponent, temp1)) && !temp1.IsEmpty()) {
448 0 : details.AppendLiteral(" ");
449 0 : if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertDumpKeyUsage", info))) {
450 0 : details.Append(info);
451 0 : details.AppendLiteral(": ");
452 : }
453 0 : details.Append(temp1);
454 0 : details.Append(PRUnichar('\n'));
455 : }
456 :
457 0 : nsAutoString firstEmail;
458 : const char *aWalkAddr;
459 0 : for (aWalkAddr = CERT_GetFirstEmailAddress(mCert)
460 0 : ;
461 : aWalkAddr
462 : ;
463 0 : aWalkAddr = CERT_GetNextEmailAddress(mCert, aWalkAddr))
464 : {
465 0 : NS_ConvertUTF8toUTF16 email(aWalkAddr);
466 0 : if (email.IsEmpty())
467 0 : continue;
468 :
469 0 : if (firstEmail.IsEmpty()) {
470 : /*
471 : * If the first email address from the subject DN is also present
472 : * in the subjectAltName extension, GetEmailAddresses() will return
473 : * it twice (as received from NSS). Remember the first address so that
474 : * we can filter out duplicates later on.
475 : */
476 0 : firstEmail = email;
477 :
478 0 : details.AppendLiteral(" ");
479 0 : if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoEmail", info))) {
480 0 : details.Append(info);
481 0 : details.AppendLiteral(": ");
482 : }
483 0 : details.Append(email);
484 : }
485 : else {
486 : // Append current address if it's different from the first one.
487 0 : if (!firstEmail.Equals(email)) {
488 0 : details.AppendLiteral(", ");
489 0 : details.Append(email);
490 : }
491 : }
492 : }
493 :
494 0 : if (!firstEmail.IsEmpty()) {
495 : // We got at least one email address, so we want a newline
496 0 : details.Append(PRUnichar('\n'));
497 : }
498 :
499 0 : if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoIssuedBy", info))) {
500 0 : details.Append(info);
501 0 : details.Append(PRUnichar(' '));
502 :
503 0 : if (NS_SUCCEEDED(GetIssuerName(temp1)) && !temp1.IsEmpty()) {
504 0 : details.Append(temp1);
505 : }
506 :
507 0 : details.Append(PRUnichar('\n'));
508 : }
509 :
510 0 : if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoStoredIn", info))) {
511 0 : details.Append(info);
512 0 : details.Append(PRUnichar(' '));
513 :
514 0 : if (NS_SUCCEEDED(GetTokenName(temp1)) && !temp1.IsEmpty()) {
515 0 : details.Append(temp1);
516 : }
517 : }
518 :
519 : /*
520 : the above produces the following output:
521 :
522 : Issued to: $subjectName
523 : Serial number: $serialNumber
524 : Valid from: $starting_date to $expiration_date
525 : Certificate Key usage: $usages
526 : Email: $address(es)
527 : Issued by: $issuerName
528 : Stored in: $token
529 : */
530 :
531 0 : return rv;
532 : }
533 :
534 :
535 : /* readonly attribute string dbKey; */
536 : NS_IMETHODIMP
537 0 : nsNSSCertificate::GetDbKey(char * *aDbKey)
538 : {
539 0 : nsNSSShutDownPreventionLock locker;
540 0 : if (isAlreadyShutDown())
541 0 : return NS_ERROR_NOT_AVAILABLE;
542 :
543 : SECItem key;
544 :
545 0 : NS_ENSURE_ARG(aDbKey);
546 0 : *aDbKey = nsnull;
547 0 : key.len = NS_NSS_LONG*4+mCert->serialNumber.len+mCert->derIssuer.len;
548 0 : key.data = (unsigned char *)nsMemory::Alloc(key.len);
549 0 : if (!key.data)
550 0 : return NS_ERROR_OUT_OF_MEMORY;
551 0 : NS_NSS_PUT_LONG(0,key.data); // later put moduleID
552 0 : NS_NSS_PUT_LONG(0,&key.data[NS_NSS_LONG]); // later put slotID
553 0 : NS_NSS_PUT_LONG(mCert->serialNumber.len,&key.data[NS_NSS_LONG*2]);
554 0 : NS_NSS_PUT_LONG(mCert->derIssuer.len,&key.data[NS_NSS_LONG*3]);
555 0 : memcpy(&key.data[NS_NSS_LONG*4], mCert->serialNumber.data,
556 0 : mCert->serialNumber.len);
557 0 : memcpy(&key.data[NS_NSS_LONG*4+mCert->serialNumber.len],
558 0 : mCert->derIssuer.data, mCert->derIssuer.len);
559 :
560 0 : *aDbKey = NSSBase64_EncodeItem(nsnull, nsnull, 0, &key);
561 0 : nsMemory::Free(key.data); // SECItem is a 'c' type without a destrutor
562 0 : return (*aDbKey) ? NS_OK : NS_ERROR_FAILURE;
563 : }
564 :
565 : /* readonly attribute string windowTitle; */
566 : NS_IMETHODIMP
567 0 : nsNSSCertificate::GetWindowTitle(char * *aWindowTitle)
568 : {
569 0 : nsNSSShutDownPreventionLock locker;
570 0 : if (isAlreadyShutDown())
571 0 : return NS_ERROR_NOT_AVAILABLE;
572 :
573 0 : NS_ENSURE_ARG(aWindowTitle);
574 0 : if (mCert) {
575 0 : if (mCert->nickname) {
576 0 : *aWindowTitle = PL_strdup(mCert->nickname);
577 : } else {
578 0 : *aWindowTitle = CERT_GetCommonName(&mCert->subject);
579 0 : if (!*aWindowTitle) {
580 0 : if (mCert->subjectName) {
581 0 : *aWindowTitle = PL_strdup(mCert->subjectName);
582 0 : } else if (mCert->emailAddr) {
583 0 : *aWindowTitle = PL_strdup(mCert->emailAddr);
584 : } else {
585 0 : *aWindowTitle = PL_strdup("");
586 : }
587 : }
588 : }
589 : } else {
590 0 : NS_ERROR("Somehow got nsnull for mCertificate in nsNSSCertificate.");
591 0 : *aWindowTitle = nsnull;
592 : }
593 0 : return NS_OK;
594 : }
595 :
596 : NS_IMETHODIMP
597 0 : nsNSSCertificate::GetNickname(nsAString &aNickname)
598 : {
599 0 : nsNSSShutDownPreventionLock locker;
600 0 : if (isAlreadyShutDown())
601 0 : return NS_ERROR_NOT_AVAILABLE;
602 :
603 0 : if (mCert->nickname) {
604 0 : CopyUTF8toUTF16(mCert->nickname, aNickname);
605 : } else {
606 : nsresult rv;
607 0 : nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
608 0 : if (NS_FAILED(rv) || !nssComponent) {
609 0 : return NS_ERROR_FAILURE;
610 : }
611 0 : nssComponent->GetPIPNSSBundleString("CertNoNickname", aNickname);
612 : }
613 0 : return NS_OK;
614 : }
615 :
616 : NS_IMETHODIMP
617 0 : nsNSSCertificate::GetEmailAddress(nsAString &aEmailAddress)
618 : {
619 0 : nsNSSShutDownPreventionLock locker;
620 0 : if (isAlreadyShutDown())
621 0 : return NS_ERROR_NOT_AVAILABLE;
622 :
623 0 : if (mCert->emailAddr) {
624 0 : CopyUTF8toUTF16(mCert->emailAddr, aEmailAddress);
625 : } else {
626 : nsresult rv;
627 0 : nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
628 0 : if (NS_FAILED(rv) || !nssComponent) {
629 0 : return NS_ERROR_FAILURE;
630 : }
631 0 : nssComponent->GetPIPNSSBundleString("CertNoEmailAddress", aEmailAddress);
632 : }
633 0 : return NS_OK;
634 : }
635 :
636 : NS_IMETHODIMP
637 0 : nsNSSCertificate::GetEmailAddresses(PRUint32 *aLength, PRUnichar*** aAddresses)
638 : {
639 0 : nsNSSShutDownPreventionLock locker;
640 0 : if (isAlreadyShutDown())
641 0 : return NS_ERROR_NOT_AVAILABLE;
642 :
643 0 : NS_ENSURE_ARG(aLength);
644 0 : NS_ENSURE_ARG(aAddresses);
645 :
646 0 : *aLength = 0;
647 :
648 : const char *aAddr;
649 0 : for (aAddr = CERT_GetFirstEmailAddress(mCert)
650 0 : ;
651 : aAddr
652 : ;
653 0 : aAddr = CERT_GetNextEmailAddress(mCert, aAddr))
654 : {
655 0 : ++(*aLength);
656 : }
657 :
658 0 : *aAddresses = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *) * (*aLength));
659 0 : if (!*aAddresses)
660 0 : return NS_ERROR_OUT_OF_MEMORY;
661 :
662 : PRUint32 iAddr;
663 0 : for (aAddr = CERT_GetFirstEmailAddress(mCert), iAddr = 0
664 0 : ;
665 : aAddr
666 : ;
667 0 : aAddr = CERT_GetNextEmailAddress(mCert, aAddr), ++iAddr)
668 : {
669 0 : (*aAddresses)[iAddr] = ToNewUnicode(NS_ConvertUTF8toUTF16(aAddr));
670 : }
671 :
672 0 : return NS_OK;
673 : }
674 :
675 : NS_IMETHODIMP
676 0 : nsNSSCertificate::ContainsEmailAddress(const nsAString &aEmailAddress, bool *result)
677 : {
678 0 : nsNSSShutDownPreventionLock locker;
679 0 : if (isAlreadyShutDown())
680 0 : return NS_ERROR_NOT_AVAILABLE;
681 :
682 0 : NS_ENSURE_ARG(result);
683 0 : *result = false;
684 :
685 0 : const char *aAddr = nsnull;
686 0 : for (aAddr = CERT_GetFirstEmailAddress(mCert)
687 0 : ;
688 : aAddr
689 : ;
690 0 : aAddr = CERT_GetNextEmailAddress(mCert, aAddr))
691 : {
692 0 : NS_ConvertUTF8toUTF16 certAddr(aAddr);
693 0 : ToLowerCase(certAddr);
694 :
695 0 : nsAutoString testAddr(aEmailAddress);
696 0 : ToLowerCase(testAddr);
697 :
698 0 : if (certAddr == testAddr)
699 : {
700 0 : *result = true;
701 : break;
702 : }
703 :
704 : }
705 :
706 0 : return NS_OK;
707 : }
708 :
709 : NS_IMETHODIMP
710 0 : nsNSSCertificate::GetCommonName(nsAString &aCommonName)
711 : {
712 0 : nsNSSShutDownPreventionLock locker;
713 0 : if (isAlreadyShutDown())
714 0 : return NS_ERROR_NOT_AVAILABLE;
715 :
716 0 : aCommonName.Truncate();
717 0 : if (mCert) {
718 0 : char *commonName = CERT_GetCommonName(&mCert->subject);
719 0 : if (commonName) {
720 0 : aCommonName = NS_ConvertUTF8toUTF16(commonName);
721 0 : PORT_Free(commonName);
722 : } /*else {
723 : *aCommonName = ToNewUnicode(NS_LITERAL_STRING("<not set>")),
724 : }*/
725 : }
726 0 : return NS_OK;
727 : }
728 :
729 : NS_IMETHODIMP
730 0 : nsNSSCertificate::GetOrganization(nsAString &aOrganization)
731 : {
732 0 : nsNSSShutDownPreventionLock locker;
733 0 : if (isAlreadyShutDown())
734 0 : return NS_ERROR_NOT_AVAILABLE;
735 :
736 0 : aOrganization.Truncate();
737 0 : if (mCert) {
738 0 : char *organization = CERT_GetOrgName(&mCert->subject);
739 0 : if (organization) {
740 0 : aOrganization = NS_ConvertUTF8toUTF16(organization);
741 0 : PORT_Free(organization);
742 : } /*else {
743 : *aOrganization = ToNewUnicode(NS_LITERAL_STRING("<not set>")),
744 : }*/
745 : }
746 0 : return NS_OK;
747 : }
748 :
749 : NS_IMETHODIMP
750 0 : nsNSSCertificate::GetIssuerCommonName(nsAString &aCommonName)
751 : {
752 0 : nsNSSShutDownPreventionLock locker;
753 0 : if (isAlreadyShutDown())
754 0 : return NS_ERROR_NOT_AVAILABLE;
755 :
756 0 : aCommonName.Truncate();
757 0 : if (mCert) {
758 0 : char *commonName = CERT_GetCommonName(&mCert->issuer);
759 0 : if (commonName) {
760 0 : aCommonName = NS_ConvertUTF8toUTF16(commonName);
761 0 : PORT_Free(commonName);
762 : }
763 : }
764 0 : return NS_OK;
765 : }
766 :
767 : NS_IMETHODIMP
768 0 : nsNSSCertificate::GetIssuerOrganization(nsAString &aOrganization)
769 : {
770 0 : nsNSSShutDownPreventionLock locker;
771 0 : if (isAlreadyShutDown())
772 0 : return NS_ERROR_NOT_AVAILABLE;
773 :
774 0 : aOrganization.Truncate();
775 0 : if (mCert) {
776 0 : char *organization = CERT_GetOrgName(&mCert->issuer);
777 0 : if (organization) {
778 0 : aOrganization = NS_ConvertUTF8toUTF16(organization);
779 0 : PORT_Free(organization);
780 : } else {
781 0 : return GetIssuerCommonName(aOrganization);
782 : }
783 : }
784 0 : return NS_OK;
785 : }
786 :
787 : NS_IMETHODIMP
788 0 : nsNSSCertificate::GetIssuerOrganizationUnit(nsAString &aOrganizationUnit)
789 : {
790 0 : nsNSSShutDownPreventionLock locker;
791 0 : if (isAlreadyShutDown())
792 0 : return NS_ERROR_NOT_AVAILABLE;
793 :
794 0 : aOrganizationUnit.Truncate();
795 0 : if (mCert) {
796 0 : char *organizationUnit = CERT_GetOrgUnitName(&mCert->issuer);
797 0 : if (organizationUnit) {
798 0 : aOrganizationUnit = NS_ConvertUTF8toUTF16(organizationUnit);
799 0 : PORT_Free(organizationUnit);
800 : }
801 : }
802 0 : return NS_OK;
803 : }
804 :
805 : /* readonly attribute nsIX509Cert issuer; */
806 : NS_IMETHODIMP
807 0 : nsNSSCertificate::GetIssuer(nsIX509Cert * *aIssuer)
808 : {
809 0 : nsNSSShutDownPreventionLock locker;
810 0 : if (isAlreadyShutDown())
811 0 : return NS_ERROR_NOT_AVAILABLE;
812 :
813 0 : NS_ENSURE_ARG(aIssuer);
814 0 : *aIssuer = nsnull;
815 : CERTCertificate *issuer;
816 0 : issuer = CERT_FindCertIssuer(mCert, PR_Now(), certUsageSSLClient);
817 0 : if (issuer) {
818 0 : nsCOMPtr<nsIX509Cert> cert = nsNSSCertificate::Create(issuer);
819 0 : if (cert) {
820 0 : *aIssuer = cert;
821 0 : NS_ADDREF(*aIssuer);
822 : }
823 0 : CERT_DestroyCertificate(issuer);
824 : }
825 0 : return NS_OK;
826 : }
827 :
828 : NS_IMETHODIMP
829 0 : nsNSSCertificate::GetOrganizationalUnit(nsAString &aOrganizationalUnit)
830 : {
831 0 : nsNSSShutDownPreventionLock locker;
832 0 : if (isAlreadyShutDown())
833 0 : return NS_ERROR_NOT_AVAILABLE;
834 :
835 0 : aOrganizationalUnit.Truncate();
836 0 : if (mCert) {
837 0 : char *orgunit = CERT_GetOrgUnitName(&mCert->subject);
838 0 : if (orgunit) {
839 0 : aOrganizationalUnit = NS_ConvertUTF8toUTF16(orgunit);
840 0 : PORT_Free(orgunit);
841 : } /*else {
842 : *aOrganizationalUnit = ToNewUnicode(NS_LITERAL_STRING("<not set>")),
843 : }*/
844 : }
845 0 : return NS_OK;
846 : }
847 :
848 : /*
849 : * nsIEnumerator getChain();
850 : */
851 : NS_IMETHODIMP
852 0 : nsNSSCertificate::GetChain(nsIArray **_rvChain)
853 : {
854 0 : nsNSSShutDownPreventionLock locker;
855 0 : if (isAlreadyShutDown())
856 0 : return NS_ERROR_NOT_AVAILABLE;
857 :
858 0 : NS_ENSURE_ARG(_rvChain);
859 : nsresult rv;
860 : /* Get the cert chain from NSS */
861 0 : CERTCertList *nssChain = NULL;
862 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Getting chain for \"%s\"\n", mCert->nickname));
863 0 : nssChain = CERT_GetCertChainFromCert(mCert, PR_Now(), certUsageSSLClient);
864 0 : if (!nssChain)
865 0 : return NS_ERROR_FAILURE;
866 : /* enumerate the chain for scripting purposes */
867 : nsCOMPtr<nsIMutableArray> array =
868 0 : do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
869 0 : if (NS_FAILED(rv)) {
870 0 : goto done;
871 : }
872 : CERTCertListNode *node;
873 0 : for (node = CERT_LIST_HEAD(nssChain);
874 0 : !CERT_LIST_END(node, nssChain);
875 : node = CERT_LIST_NEXT(node)) {
876 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("adding %s to chain\n", node->cert->nickname));
877 0 : nsCOMPtr<nsIX509Cert> cert = nsNSSCertificate::Create(node->cert);
878 0 : array->AppendElement(cert, false);
879 : }
880 0 : *_rvChain = array;
881 0 : NS_IF_ADDREF(*_rvChain);
882 0 : rv = NS_OK;
883 : done:
884 0 : if (nssChain)
885 0 : CERT_DestroyCertList(nssChain);
886 0 : return rv;
887 : }
888 :
889 : NS_IMETHODIMP
890 0 : nsNSSCertificate::GetAllTokenNames(PRUint32 *aLength, PRUnichar*** aTokenNames)
891 : {
892 0 : nsNSSShutDownPreventionLock locker;
893 0 : if (isAlreadyShutDown())
894 0 : return NS_ERROR_NOT_AVAILABLE;
895 :
896 0 : NS_ENSURE_ARG(aLength);
897 0 : NS_ENSURE_ARG(aTokenNames);
898 0 : *aLength = 0;
899 0 : *aTokenNames = NULL;
900 :
901 : /* Get the slots from NSS */
902 0 : PK11SlotList *slots = NULL;
903 0 : PK11SlotListCleaner slotCleaner(slots);
904 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Getting slots for \"%s\"\n", mCert->nickname));
905 0 : slots = PK11_GetAllSlotsForCert(mCert, NULL);
906 0 : if (!slots) {
907 0 : if (PORT_GetError() == SEC_ERROR_NO_TOKEN)
908 0 : return NS_OK; // List of slots is empty, return empty array
909 : else
910 0 : return NS_ERROR_FAILURE;
911 : }
912 :
913 : /* read the token names from slots */
914 : PK11SlotListElement *le;
915 :
916 0 : for (le = slots->head; le; le = le->next) {
917 0 : ++(*aLength);
918 : }
919 :
920 0 : *aTokenNames = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *) * (*aLength));
921 0 : if (!*aTokenNames) {
922 0 : *aLength = 0;
923 0 : return NS_ERROR_OUT_OF_MEMORY;
924 : }
925 :
926 : PRUint32 iToken;
927 0 : for (le = slots->head, iToken = 0; le; le = le->next, ++iToken) {
928 0 : char *token = PK11_GetTokenName(le->slot);
929 0 : (*aTokenNames)[iToken] = ToNewUnicode(NS_ConvertUTF8toUTF16(token));
930 0 : if (!(*aTokenNames)[iToken]) {
931 0 : NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(iToken, *aTokenNames);
932 0 : *aLength = 0;
933 0 : *aTokenNames = NULL;
934 0 : return NS_ERROR_OUT_OF_MEMORY;
935 : }
936 : }
937 :
938 0 : return NS_OK;
939 : }
940 :
941 : NS_IMETHODIMP
942 0 : nsNSSCertificate::GetSubjectName(nsAString &_subjectName)
943 : {
944 0 : nsNSSShutDownPreventionLock locker;
945 0 : if (isAlreadyShutDown())
946 0 : return NS_ERROR_NOT_AVAILABLE;
947 :
948 0 : _subjectName.Truncate();
949 0 : if (mCert->subjectName) {
950 0 : _subjectName = NS_ConvertUTF8toUTF16(mCert->subjectName);
951 0 : return NS_OK;
952 : }
953 0 : return NS_ERROR_FAILURE;
954 : }
955 :
956 : NS_IMETHODIMP
957 0 : nsNSSCertificate::GetIssuerName(nsAString &_issuerName)
958 : {
959 0 : nsNSSShutDownPreventionLock locker;
960 0 : if (isAlreadyShutDown())
961 0 : return NS_ERROR_NOT_AVAILABLE;
962 :
963 0 : _issuerName.Truncate();
964 0 : if (mCert->issuerName) {
965 0 : _issuerName = NS_ConvertUTF8toUTF16(mCert->issuerName);
966 0 : return NS_OK;
967 : }
968 0 : return NS_ERROR_FAILURE;
969 : }
970 :
971 : NS_IMETHODIMP
972 0 : nsNSSCertificate::GetSerialNumber(nsAString &_serialNumber)
973 : {
974 0 : nsNSSShutDownPreventionLock locker;
975 0 : if (isAlreadyShutDown())
976 0 : return NS_ERROR_NOT_AVAILABLE;
977 :
978 0 : _serialNumber.Truncate();
979 0 : char *tmpstr = CERT_Hexify(&mCert->serialNumber, 1);
980 0 : if (tmpstr) {
981 0 : _serialNumber = NS_ConvertASCIItoUTF16(tmpstr);
982 0 : PORT_Free(tmpstr);
983 0 : return NS_OK;
984 : }
985 0 : return NS_ERROR_FAILURE;
986 : }
987 :
988 : NS_IMETHODIMP
989 168 : nsNSSCertificate::GetSha1Fingerprint(nsAString &_sha1Fingerprint)
990 : {
991 336 : nsNSSShutDownPreventionLock locker;
992 168 : if (isAlreadyShutDown())
993 0 : return NS_ERROR_NOT_AVAILABLE;
994 :
995 168 : _sha1Fingerprint.Truncate();
996 : unsigned char fingerprint[20];
997 : SECItem fpItem;
998 168 : memset(fingerprint, 0, sizeof fingerprint);
999 : PK11_HashBuf(SEC_OID_SHA1, fingerprint,
1000 168 : mCert->derCert.data, mCert->derCert.len);
1001 168 : fpItem.data = fingerprint;
1002 168 : fpItem.len = SHA1_LENGTH;
1003 168 : char *fpStr = CERT_Hexify(&fpItem, 1);
1004 168 : if (fpStr) {
1005 168 : _sha1Fingerprint = NS_ConvertASCIItoUTF16(fpStr);
1006 168 : PORT_Free(fpStr);
1007 168 : return NS_OK;
1008 : }
1009 0 : return NS_ERROR_FAILURE;
1010 : }
1011 :
1012 : NS_IMETHODIMP
1013 0 : nsNSSCertificate::GetMd5Fingerprint(nsAString &_md5Fingerprint)
1014 : {
1015 0 : nsNSSShutDownPreventionLock locker;
1016 0 : if (isAlreadyShutDown())
1017 0 : return NS_ERROR_NOT_AVAILABLE;
1018 :
1019 0 : _md5Fingerprint.Truncate();
1020 : unsigned char fingerprint[20];
1021 : SECItem fpItem;
1022 0 : memset(fingerprint, 0, sizeof fingerprint);
1023 : PK11_HashBuf(SEC_OID_MD5, fingerprint,
1024 0 : mCert->derCert.data, mCert->derCert.len);
1025 0 : fpItem.data = fingerprint;
1026 0 : fpItem.len = MD5_LENGTH;
1027 0 : char *fpStr = CERT_Hexify(&fpItem, 1);
1028 0 : if (fpStr) {
1029 0 : _md5Fingerprint = NS_ConvertASCIItoUTF16(fpStr);
1030 0 : PORT_Free(fpStr);
1031 0 : return NS_OK;
1032 : }
1033 0 : return NS_ERROR_FAILURE;
1034 : }
1035 :
1036 : NS_IMETHODIMP
1037 0 : nsNSSCertificate::GetTokenName(nsAString &aTokenName)
1038 : {
1039 0 : nsNSSShutDownPreventionLock locker;
1040 0 : if (isAlreadyShutDown())
1041 0 : return NS_ERROR_NOT_AVAILABLE;
1042 :
1043 0 : aTokenName.Truncate();
1044 0 : if (mCert) {
1045 : // HACK alert
1046 : // When the trust of a builtin cert is modified, NSS copies it into the
1047 : // cert db. At this point, it is now "managed" by the user, and should
1048 : // not be listed with the builtins. However, in the collection code
1049 : // used by PK11_ListCerts, the cert is found in the temp db, where it
1050 : // has been loaded from the token. Though the trust is correct (grabbed
1051 : // from the cert db), the source is wrong. I believe this is a safe
1052 : // way to work around this.
1053 0 : if (mCert->slot) {
1054 0 : char *token = PK11_GetTokenName(mCert->slot);
1055 0 : if (token) {
1056 0 : aTokenName = NS_ConvertUTF8toUTF16(token);
1057 : }
1058 : } else {
1059 : nsresult rv;
1060 0 : nsAutoString tok;
1061 0 : nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
1062 0 : if (NS_FAILED(rv)) return rv;
1063 0 : rv = nssComponent->GetPIPNSSBundleString("InternalToken", tok);
1064 0 : if (NS_SUCCEEDED(rv))
1065 0 : aTokenName = tok;
1066 : }
1067 : }
1068 0 : return NS_OK;
1069 : }
1070 :
1071 : NS_IMETHODIMP
1072 0 : nsNSSCertificate::GetRawDER(PRUint32 *aLength, PRUint8 **aArray)
1073 : {
1074 0 : nsNSSShutDownPreventionLock locker;
1075 0 : if (isAlreadyShutDown())
1076 0 : return NS_ERROR_NOT_AVAILABLE;
1077 :
1078 0 : if (mCert) {
1079 0 : *aArray = (PRUint8*)nsMemory::Alloc(mCert->derCert.len);
1080 0 : if (*aArray) {
1081 0 : memcpy(*aArray, mCert->derCert.data, mCert->derCert.len);
1082 0 : *aLength = mCert->derCert.len;
1083 0 : return NS_OK;
1084 : }
1085 : }
1086 0 : *aLength = 0;
1087 0 : return NS_ERROR_FAILURE;
1088 : }
1089 :
1090 : NS_IMETHODIMP
1091 0 : nsNSSCertificate::ExportAsCMS(PRUint32 chainMode,
1092 : PRUint32 *aLength, PRUint8 **aArray)
1093 : {
1094 0 : NS_ENSURE_ARG(aLength);
1095 0 : NS_ENSURE_ARG(aArray);
1096 :
1097 0 : nsNSSShutDownPreventionLock locker;
1098 0 : if (isAlreadyShutDown())
1099 0 : return NS_ERROR_NOT_AVAILABLE;
1100 :
1101 0 : if (!mCert)
1102 0 : return NS_ERROR_FAILURE;
1103 :
1104 0 : switch (chainMode) {
1105 : case nsIX509Cert3::CMS_CHAIN_MODE_CertOnly:
1106 : case nsIX509Cert3::CMS_CHAIN_MODE_CertChain:
1107 : case nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot:
1108 : break;
1109 : default:
1110 0 : return NS_ERROR_INVALID_ARG;
1111 : };
1112 :
1113 0 : PLArenaPool *arena = PORT_NewArena(1024);
1114 0 : PLArenaPoolCleanerFalseParam arenaCleaner(arena);
1115 0 : if (!arena) {
1116 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
1117 : ("nsNSSCertificate::ExportAsCMS - out of memory\n"));
1118 0 : return NS_ERROR_OUT_OF_MEMORY;
1119 : }
1120 :
1121 0 : NSSCMSMessage *cmsg = NSS_CMSMessage_Create(nsnull);
1122 0 : NSSCMSMessageCleaner cmsgCleaner(cmsg);
1123 0 : if (!cmsg) {
1124 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
1125 : ("nsNSSCertificate::ExportAsCMS - can't create CMS message\n"));
1126 0 : return NS_ERROR_OUT_OF_MEMORY;
1127 : }
1128 :
1129 : /*
1130 : * first, create SignedData with the certificate only (no chain)
1131 : */
1132 0 : NSSCMSSignedData *sigd = NSS_CMSSignedData_CreateCertsOnly(cmsg, mCert, false);
1133 0 : NSSCMSSignedDataCleaner sigdCleaner(sigd);
1134 0 : if (!sigd) {
1135 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
1136 : ("nsNSSCertificate::ExportAsCMS - can't create SignedData\n"));
1137 0 : return NS_ERROR_FAILURE;
1138 : }
1139 :
1140 : /*
1141 : * Calling NSS_CMSSignedData_CreateCertsOnly() will not allow us
1142 : * to specify the inclusion of the root, but CERT_CertChainFromCert() does.
1143 : * Since CERT_CertChainFromCert() also includes the certificate itself,
1144 : * we have to start at the issuing cert (to avoid duplicate certs
1145 : * in the SignedData).
1146 : */
1147 0 : if (chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChain ||
1148 : chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot) {
1149 0 : CERTCertificate *issuerCert = CERT_FindCertIssuer(mCert, PR_Now(), certUsageAnyCA);
1150 0 : CERTCertificateCleaner issuerCertCleaner(issuerCert);
1151 : /*
1152 : * the issuerCert of a self signed root is the cert itself,
1153 : * so make sure we're not adding duplicates, again
1154 : */
1155 0 : if (issuerCert && issuerCert != mCert) {
1156 : bool includeRoot =
1157 0 : (chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot);
1158 0 : CERTCertificateList *certChain = CERT_CertChainFromCert(issuerCert, certUsageAnyCA, includeRoot);
1159 0 : CERTCertificateListCleaner certChainCleaner(certChain);
1160 0 : if (certChain) {
1161 0 : if (NSS_CMSSignedData_AddCertList(sigd, certChain) == SECSuccess) {
1162 0 : certChainCleaner.detach();
1163 : }
1164 : else {
1165 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
1166 : ("nsNSSCertificate::ExportAsCMS - can't add chain\n"));
1167 0 : return NS_ERROR_FAILURE;
1168 : }
1169 : }
1170 : else {
1171 : /* try to add the issuerCert, at least */
1172 0 : if (NSS_CMSSignedData_AddCertificate(sigd, issuerCert)
1173 : == SECSuccess) {
1174 0 : issuerCertCleaner.detach();
1175 : }
1176 : else {
1177 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
1178 : ("nsNSSCertificate::ExportAsCMS - can't add issuer cert\n"));
1179 0 : return NS_ERROR_FAILURE;
1180 : }
1181 : }
1182 : }
1183 : }
1184 :
1185 0 : NSSCMSContentInfo *cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
1186 0 : if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd)
1187 : == SECSuccess) {
1188 0 : sigdCleaner.detach();
1189 : }
1190 : else {
1191 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
1192 : ("nsNSSCertificate::ExportAsCMS - can't attach SignedData\n"));
1193 0 : return NS_ERROR_FAILURE;
1194 : }
1195 :
1196 0 : SECItem certP7 = { siBuffer, nsnull, 0 };
1197 : NSSCMSEncoderContext *ecx = NSS_CMSEncoder_Start(cmsg, nsnull, nsnull, &certP7, arena,
1198 : nsnull, nsnull, nsnull, nsnull, nsnull,
1199 0 : nsnull);
1200 0 : if (!ecx) {
1201 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
1202 : ("nsNSSCertificate::ExportAsCMS - can't create encoder context\n"));
1203 0 : return NS_ERROR_FAILURE;
1204 : }
1205 :
1206 0 : if (NSS_CMSEncoder_Finish(ecx) != SECSuccess) {
1207 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
1208 : ("nsNSSCertificate::ExportAsCMS - failed to add encoded data\n"));
1209 0 : return NS_ERROR_FAILURE;
1210 : }
1211 :
1212 0 : *aArray = (PRUint8*)nsMemory::Alloc(certP7.len);
1213 0 : if (!*aArray)
1214 0 : return NS_ERROR_OUT_OF_MEMORY;
1215 :
1216 0 : memcpy(*aArray, certP7.data, certP7.len);
1217 0 : *aLength = certP7.len;
1218 0 : return NS_OK;
1219 : }
1220 :
1221 : CERTCertificate *
1222 0 : nsNSSCertificate::GetCert()
1223 : {
1224 0 : nsNSSShutDownPreventionLock locker;
1225 0 : if (isAlreadyShutDown())
1226 0 : return nsnull;
1227 :
1228 0 : return (mCert) ? CERT_DupCertificate(mCert) : nsnull;
1229 : }
1230 :
1231 : NS_IMETHODIMP
1232 0 : nsNSSCertificate::GetValidity(nsIX509CertValidity **aValidity)
1233 : {
1234 0 : nsNSSShutDownPreventionLock locker;
1235 0 : if (isAlreadyShutDown())
1236 0 : return NS_ERROR_NOT_AVAILABLE;
1237 :
1238 0 : NS_ENSURE_ARG(aValidity);
1239 0 : nsX509CertValidity *validity = new nsX509CertValidity(mCert);
1240 0 : if (nsnull == validity)
1241 0 : return NS_ERROR_OUT_OF_MEMORY;
1242 :
1243 0 : NS_ADDREF(validity);
1244 0 : *aValidity = static_cast<nsIX509CertValidity*>(validity);
1245 0 : return NS_OK;
1246 : }
1247 :
1248 : NS_IMETHODIMP
1249 0 : nsNSSCertificate::VerifyForUsage(PRUint32 usage, PRUint32 *verificationResult)
1250 : {
1251 0 : nsNSSShutDownPreventionLock locker;
1252 0 : if (isAlreadyShutDown())
1253 0 : return NS_ERROR_NOT_AVAILABLE;
1254 :
1255 0 : NS_ENSURE_ARG(verificationResult);
1256 :
1257 : nsresult nsrv;
1258 0 : nsCOMPtr<nsINSSComponent> inss = do_GetService(kNSSComponentCID, &nsrv);
1259 0 : if (!inss)
1260 0 : return nsrv;
1261 0 : nsRefPtr<nsCERTValInParamWrapper> survivingParams;
1262 0 : nsrv = inss->GetDefaultCERTValInParam(survivingParams);
1263 0 : if (NS_FAILED(nsrv))
1264 0 : return nsrv;
1265 :
1266 : SECCertificateUsage nss_usage;
1267 :
1268 0 : switch (usage)
1269 : {
1270 : case CERT_USAGE_SSLClient:
1271 0 : nss_usage = certificateUsageSSLClient;
1272 0 : break;
1273 :
1274 : case CERT_USAGE_SSLServer:
1275 0 : nss_usage = certificateUsageSSLServer;
1276 0 : break;
1277 :
1278 : case CERT_USAGE_SSLServerWithStepUp:
1279 0 : nss_usage = certificateUsageSSLServerWithStepUp;
1280 0 : break;
1281 :
1282 : case CERT_USAGE_SSLCA:
1283 0 : nss_usage = certificateUsageSSLCA;
1284 0 : break;
1285 :
1286 : case CERT_USAGE_EmailSigner:
1287 0 : nss_usage = certificateUsageEmailSigner;
1288 0 : break;
1289 :
1290 : case CERT_USAGE_EmailRecipient:
1291 0 : nss_usage = certificateUsageEmailRecipient;
1292 0 : break;
1293 :
1294 : case CERT_USAGE_ObjectSigner:
1295 0 : nss_usage = certificateUsageObjectSigner;
1296 0 : break;
1297 :
1298 : case CERT_USAGE_UserCertImport:
1299 0 : nss_usage = certificateUsageUserCertImport;
1300 0 : break;
1301 :
1302 : case CERT_USAGE_VerifyCA:
1303 0 : nss_usage = certificateUsageVerifyCA;
1304 0 : break;
1305 :
1306 : case CERT_USAGE_ProtectedObjectSigner:
1307 0 : nss_usage = certificateUsageProtectedObjectSigner;
1308 0 : break;
1309 :
1310 : case CERT_USAGE_StatusResponder:
1311 0 : nss_usage = certificateUsageStatusResponder;
1312 0 : break;
1313 :
1314 : case CERT_USAGE_AnyCA:
1315 0 : nss_usage = certificateUsageAnyCA;
1316 0 : break;
1317 :
1318 : default:
1319 0 : return NS_ERROR_FAILURE;
1320 : }
1321 :
1322 : SECStatus verify_result;
1323 0 : if (!nsNSSComponent::globalConstFlagUsePKIXVerification) {
1324 0 : CERTCertDBHandle *defaultcertdb = CERT_GetDefaultCertDB();
1325 : verify_result = CERT_VerifyCertificateNow(defaultcertdb, mCert, true,
1326 0 : nss_usage, NULL, NULL);
1327 : }
1328 : else {
1329 : CERTValOutParam cvout[1];
1330 0 : cvout[0].type = cert_po_end;
1331 : verify_result = CERT_PKIXVerifyCert(mCert, nss_usage,
1332 : survivingParams->GetRawPointerForNSS(),
1333 0 : cvout, NULL);
1334 : }
1335 :
1336 0 : if (verify_result == SECSuccess)
1337 : {
1338 0 : *verificationResult = VERIFIED_OK;
1339 : }
1340 : else
1341 : {
1342 0 : int err = PR_GetError();
1343 :
1344 : // this list was cloned from verifyFailed
1345 :
1346 0 : switch (err)
1347 : {
1348 : case SEC_ERROR_INADEQUATE_KEY_USAGE:
1349 : case SEC_ERROR_INADEQUATE_CERT_TYPE:
1350 0 : *verificationResult = USAGE_NOT_ALLOWED;
1351 0 : break;
1352 :
1353 : case SEC_ERROR_REVOKED_CERTIFICATE:
1354 0 : *verificationResult = CERT_REVOKED;
1355 0 : break;
1356 :
1357 : case SEC_ERROR_EXPIRED_CERTIFICATE:
1358 0 : *verificationResult = CERT_EXPIRED;
1359 0 : break;
1360 :
1361 : case SEC_ERROR_UNTRUSTED_CERT:
1362 0 : *verificationResult = CERT_NOT_TRUSTED;
1363 0 : break;
1364 :
1365 : case SEC_ERROR_UNTRUSTED_ISSUER:
1366 0 : *verificationResult = ISSUER_NOT_TRUSTED;
1367 0 : break;
1368 :
1369 : case SEC_ERROR_UNKNOWN_ISSUER:
1370 0 : *verificationResult = ISSUER_UNKNOWN;
1371 0 : break;
1372 :
1373 : case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
1374 0 : *verificationResult = INVALID_CA;
1375 0 : break;
1376 :
1377 : case SEC_ERROR_CERT_USAGES_INVALID:
1378 : default:
1379 0 : *verificationResult = NOT_VERIFIED_UNKNOWN;
1380 0 : break;
1381 : }
1382 : }
1383 :
1384 0 : return NS_OK;
1385 : }
1386 :
1387 :
1388 : NS_IMETHODIMP
1389 0 : nsNSSCertificate::GetUsagesArray(bool localOnly,
1390 : PRUint32 *_verified,
1391 : PRUint32 *_count,
1392 : PRUnichar ***_usages)
1393 : {
1394 0 : nsNSSShutDownPreventionLock locker;
1395 0 : if (isAlreadyShutDown())
1396 0 : return NS_ERROR_NOT_AVAILABLE;
1397 :
1398 : nsresult rv;
1399 0 : const int max_usages = 13;
1400 : PRUnichar *tmpUsages[max_usages];
1401 0 : const char *suffix = "";
1402 : PRUint32 tmpCount;
1403 0 : nsUsageArrayHelper uah(mCert);
1404 0 : rv = uah.GetUsagesArray(suffix, localOnly, max_usages, _verified, &tmpCount, tmpUsages);
1405 0 : NS_ENSURE_SUCCESS(rv,rv);
1406 0 : if (tmpCount > 0) {
1407 0 : *_usages = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *) * tmpCount);
1408 0 : if (!*_usages)
1409 0 : return NS_ERROR_OUT_OF_MEMORY;
1410 0 : for (PRUint32 i=0; i<tmpCount; i++) {
1411 0 : (*_usages)[i] = tmpUsages[i];
1412 : }
1413 0 : *_count = tmpCount;
1414 0 : return NS_OK;
1415 : }
1416 0 : *_usages = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *));
1417 0 : if (!*_usages)
1418 0 : return NS_ERROR_OUT_OF_MEMORY;
1419 0 : *_count = 0;
1420 0 : return NS_OK;
1421 : }
1422 :
1423 : NS_IMETHODIMP
1424 0 : nsNSSCertificate::RequestUsagesArrayAsync(nsICertVerificationListener *aResultListener)
1425 : {
1426 0 : if (!aResultListener)
1427 0 : return NS_ERROR_FAILURE;
1428 :
1429 0 : nsCertVerificationJob *job = new nsCertVerificationJob;
1430 0 : if (!job)
1431 0 : return NS_ERROR_OUT_OF_MEMORY;
1432 :
1433 0 : job->mCert = this;
1434 0 : job->mListener = aResultListener;
1435 :
1436 0 : nsresult rv = nsCertVerificationThread::addJob(job);
1437 0 : if (NS_FAILED(rv))
1438 0 : delete job;
1439 :
1440 0 : return rv;
1441 : }
1442 :
1443 : NS_IMETHODIMP
1444 0 : nsNSSCertificate::GetUsagesString(bool localOnly,
1445 : PRUint32 *_verified,
1446 : nsAString &_usages)
1447 : {
1448 0 : nsNSSShutDownPreventionLock locker;
1449 0 : if (isAlreadyShutDown())
1450 0 : return NS_ERROR_NOT_AVAILABLE;
1451 :
1452 : nsresult rv;
1453 0 : const int max_usages = 13;
1454 : PRUnichar *tmpUsages[max_usages];
1455 0 : const char *suffix = "_p";
1456 : PRUint32 tmpCount;
1457 0 : nsUsageArrayHelper uah(mCert);
1458 0 : rv = uah.GetUsagesArray(suffix, localOnly, max_usages, _verified, &tmpCount, tmpUsages);
1459 0 : NS_ENSURE_SUCCESS(rv,rv);
1460 0 : _usages.Truncate();
1461 0 : for (PRUint32 i=0; i<tmpCount; i++) {
1462 0 : if (i>0) _usages.AppendLiteral(",");
1463 0 : _usages.Append(tmpUsages[i]);
1464 0 : nsMemory::Free(tmpUsages[i]);
1465 : }
1466 0 : return NS_OK;
1467 : }
1468 :
1469 : #if defined(DEBUG_javi) || defined(DEBUG_jgmyers)
1470 : void
1471 : DumpASN1Object(nsIASN1Object *object, unsigned int level)
1472 : {
1473 : nsAutoString dispNameU, dispValU;
1474 : unsigned int i;
1475 : nsCOMPtr<nsIMutableArray> asn1Objects;
1476 : nsCOMPtr<nsISupports> isupports;
1477 : nsCOMPtr<nsIASN1Object> currObject;
1478 : bool processObjects;
1479 : PRUint32 numObjects;
1480 :
1481 : for (i=0; i<level; i++)
1482 : printf (" ");
1483 :
1484 : object->GetDisplayName(dispNameU);
1485 : nsCOMPtr<nsIASN1Sequence> sequence(do_QueryInterface(object));
1486 : if (sequence) {
1487 : printf ("%s ", NS_ConvertUTF16toUTF8(dispNameU).get());
1488 : sequence->GetIsValidContainer(&processObjects);
1489 : if (processObjects) {
1490 : printf("\n");
1491 : sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
1492 : asn1Objects->GetLength(&numObjects);
1493 : for (i=0; i<numObjects;i++) {
1494 : asn1Objects->QueryElementAt(i, NS_GET_IID(nsISupports), getter_AddRefs(currObject));
1495 : DumpASN1Object(currObject, level+1);
1496 : }
1497 : } else {
1498 : object->GetDisplayValue(dispValU);
1499 : printf("= %s\n", NS_ConvertUTF16toUTF8(dispValU).get());
1500 : }
1501 : } else {
1502 : object->GetDisplayValue(dispValU);
1503 : printf("%s = %s\n",NS_ConvertUTF16toUTF8(dispNameU).get(),
1504 : NS_ConvertUTF16toUTF8(dispValU).get());
1505 : }
1506 : }
1507 : #endif
1508 :
1509 : /* readonly attribute nsIASN1Object ASN1Structure; */
1510 : NS_IMETHODIMP
1511 0 : nsNSSCertificate::GetASN1Structure(nsIASN1Object * *aASN1Structure)
1512 : {
1513 0 : nsNSSShutDownPreventionLock locker;
1514 0 : nsresult rv = NS_OK;
1515 0 : NS_ENSURE_ARG_POINTER(aASN1Structure);
1516 0 : if (mASN1Structure == nsnull) {
1517 : // First create the recursive structure os ASN1Objects
1518 : // which tells us the layout of the cert.
1519 0 : rv = CreateASN1Struct();
1520 0 : if (NS_FAILED(rv)) {
1521 0 : return rv;
1522 : }
1523 : #ifdef DEBUG_javi
1524 : DumpASN1Object(mASN1Structure, 0);
1525 : #endif
1526 : }
1527 0 : *aASN1Structure = mASN1Structure;
1528 0 : NS_IF_ADDREF(*aASN1Structure);
1529 0 : return rv;
1530 : }
1531 :
1532 : NS_IMETHODIMP
1533 0 : nsNSSCertificate::Equals(nsIX509Cert *other, bool *result)
1534 : {
1535 0 : nsNSSShutDownPreventionLock locker;
1536 0 : if (isAlreadyShutDown())
1537 0 : return NS_ERROR_NOT_AVAILABLE;
1538 :
1539 0 : NS_ENSURE_ARG(other);
1540 0 : NS_ENSURE_ARG(result);
1541 :
1542 0 : nsCOMPtr<nsIX509Cert2> other2 = do_QueryInterface(other);
1543 0 : if (!other2)
1544 0 : return NS_ERROR_FAILURE;
1545 :
1546 0 : CERTCertificate *cert = other2->GetCert();
1547 0 : *result = (mCert == cert);
1548 0 : if (cert) {
1549 0 : CERT_DestroyCertificate(cert);
1550 : }
1551 0 : return NS_OK;
1552 : }
1553 :
1554 : NS_IMETHODIMP
1555 0 : nsNSSCertificate::SaveSMimeProfile()
1556 : {
1557 0 : nsNSSShutDownPreventionLock locker;
1558 0 : if (isAlreadyShutDown())
1559 0 : return NS_ERROR_NOT_AVAILABLE;
1560 :
1561 0 : if (SECSuccess != CERT_SaveSMimeProfile(mCert, nsnull, nsnull))
1562 0 : return NS_ERROR_FAILURE;
1563 : else
1564 0 : return NS_OK;
1565 : }
1566 :
1567 :
1568 4 : char* nsNSSCertificate::defaultServerNickname(CERTCertificate* cert)
1569 : {
1570 8 : nsNSSShutDownPreventionLock locker;
1571 4 : char* nickname = nsnull;
1572 : int count;
1573 : bool conflict;
1574 4 : char* servername = nsnull;
1575 :
1576 4 : servername = CERT_GetCommonName(&cert->subject);
1577 4 : if (!servername) {
1578 : // Certs without common names are strange, but they do exist...
1579 : // Let's try to use another string for the nickname
1580 0 : servername = CERT_GetOrgUnitName(&cert->subject);
1581 0 : if (!servername) {
1582 0 : servername = CERT_GetOrgName(&cert->subject);
1583 0 : if (!servername) {
1584 0 : servername = CERT_GetLocalityName(&cert->subject);
1585 0 : if (!servername) {
1586 0 : servername = CERT_GetStateName(&cert->subject);
1587 0 : if (!servername) {
1588 0 : servername = CERT_GetCountryName(&cert->subject);
1589 0 : if (!servername) {
1590 : // We tried hard, there is nothing more we can do.
1591 : // A cert without any names doesn't really make sense.
1592 0 : return nsnull;
1593 : }
1594 : }
1595 : }
1596 : }
1597 : }
1598 : }
1599 :
1600 4 : count = 1;
1601 0 : while (1) {
1602 4 : if (count == 1) {
1603 4 : nickname = PR_smprintf("%s", servername);
1604 : }
1605 : else {
1606 0 : nickname = PR_smprintf("%s #%d", servername, count);
1607 : }
1608 4 : if (nickname == NULL) {
1609 0 : break;
1610 : }
1611 :
1612 : conflict = SEC_CertNicknameConflict(nickname, &cert->derSubject,
1613 4 : cert->dbhandle);
1614 4 : if (!conflict) {
1615 4 : break;
1616 : }
1617 0 : PR_Free(nickname);
1618 0 : count++;
1619 : }
1620 4 : PR_FREEIF(servername);
1621 4 : return nickname;
1622 : }
1623 :
1624 0 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsNSSCertList, nsIX509CertList)
1625 :
1626 0 : nsNSSCertList::nsNSSCertList(CERTCertList *certList, bool adopt)
1627 : {
1628 0 : if (certList) {
1629 0 : if (adopt) {
1630 0 : mCertList = certList;
1631 : } else {
1632 0 : mCertList = DupCertList(certList);
1633 : }
1634 : } else {
1635 0 : mCertList = CERT_NewCertList();
1636 : }
1637 0 : }
1638 :
1639 0 : nsNSSCertList::~nsNSSCertList()
1640 : {
1641 0 : if (mCertList) {
1642 0 : CERT_DestroyCertList(mCertList);
1643 : }
1644 0 : }
1645 :
1646 : /* void addCert (in nsIX509Cert cert); */
1647 : NS_IMETHODIMP
1648 0 : nsNSSCertList::AddCert(nsIX509Cert *aCert)
1649 : {
1650 : /* This should be a query interface, but currently this his how the
1651 : * rest of PSM is working */
1652 0 : nsCOMPtr<nsIX509Cert2> nssCert = do_QueryInterface(aCert);
1653 : CERTCertificate *cert;
1654 :
1655 0 : cert = nssCert->GetCert();
1656 0 : if (cert == nsnull) {
1657 0 : NS_ERROR("Somehow got nsnull for mCertificate in nsNSSCertificate.");
1658 0 : return NS_ERROR_FAILURE;
1659 : }
1660 :
1661 0 : if (mCertList == nsnull) {
1662 0 : NS_ERROR("Somehow got nsnull for mCertList in nsNSSCertList.");
1663 0 : return NS_ERROR_FAILURE;
1664 : }
1665 0 : CERT_AddCertToListTail(mCertList,cert);
1666 0 : return NS_OK;
1667 : }
1668 :
1669 : /* void deleteCert (in nsIX509Cert cert); */
1670 : NS_IMETHODIMP
1671 0 : nsNSSCertList::DeleteCert(nsIX509Cert *aCert)
1672 : {
1673 : /* This should be a query interface, but currently this his how the
1674 : * rest of PSM is working */
1675 0 : nsCOMPtr<nsIX509Cert2> nssCert = do_QueryInterface(aCert);
1676 0 : CERTCertificate *cert = nssCert->GetCert();
1677 : CERTCertListNode *node;
1678 :
1679 0 : if (cert == nsnull) {
1680 0 : NS_ERROR("Somehow got nsnull for mCertificate in nsNSSCertificate.");
1681 0 : return NS_ERROR_FAILURE;
1682 : }
1683 :
1684 0 : if (mCertList == nsnull) {
1685 0 : NS_ERROR("Somehow got nsnull for mCertList in nsNSSCertList.");
1686 0 : return NS_ERROR_FAILURE;
1687 : }
1688 :
1689 0 : for (node = CERT_LIST_HEAD(mCertList); !CERT_LIST_END(node,mCertList);
1690 : node = CERT_LIST_NEXT(node)) {
1691 0 : if (node->cert == cert) {
1692 0 : CERT_RemoveCertListNode(node);
1693 0 : return NS_OK;
1694 : }
1695 : }
1696 0 : return NS_OK; /* should we fail if we couldn't find it? */
1697 : }
1698 :
1699 : CERTCertList *
1700 0 : nsNSSCertList::DupCertList(CERTCertList *aCertList)
1701 : {
1702 0 : if (!aCertList)
1703 0 : return nsnull;
1704 :
1705 0 : CERTCertList *newList = CERT_NewCertList();
1706 :
1707 0 : if (newList == nsnull) {
1708 0 : return nsnull;
1709 : }
1710 :
1711 : CERTCertListNode *node;
1712 0 : for (node = CERT_LIST_HEAD(aCertList); !CERT_LIST_END(node, aCertList);
1713 : node = CERT_LIST_NEXT(node)) {
1714 0 : CERTCertificate *cert = CERT_DupCertificate(node->cert);
1715 0 : CERT_AddCertToListTail(newList, cert);
1716 : }
1717 0 : return newList;
1718 : }
1719 :
1720 : void *
1721 0 : nsNSSCertList::GetRawCertList()
1722 : {
1723 0 : return mCertList;
1724 : }
1725 :
1726 : /* nsISimpleEnumerator getEnumerator (); */
1727 : NS_IMETHODIMP
1728 0 : nsNSSCertList::GetEnumerator(nsISimpleEnumerator **_retval)
1729 : {
1730 0 : nsCOMPtr<nsISimpleEnumerator> enumerator = new nsNSSCertListEnumerator(mCertList);
1731 0 : if (!enumerator) {
1732 0 : return NS_ERROR_OUT_OF_MEMORY;
1733 : }
1734 :
1735 0 : *_retval = enumerator;
1736 0 : NS_ADDREF(*_retval);
1737 0 : return NS_OK;
1738 : }
1739 :
1740 0 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsNSSCertListEnumerator,
1741 : nsISimpleEnumerator)
1742 :
1743 0 : nsNSSCertListEnumerator::nsNSSCertListEnumerator(CERTCertList *certList)
1744 : {
1745 0 : mCertList = nsNSSCertList::DupCertList(certList);
1746 0 : }
1747 :
1748 0 : nsNSSCertListEnumerator::~nsNSSCertListEnumerator()
1749 : {
1750 0 : if (mCertList) {
1751 0 : CERT_DestroyCertList(mCertList);
1752 : }
1753 0 : }
1754 :
1755 : /* boolean hasMoreElements (); */
1756 : NS_IMETHODIMP
1757 0 : nsNSSCertListEnumerator::HasMoreElements(bool *_retval)
1758 : {
1759 0 : NS_ENSURE_TRUE(mCertList, NS_ERROR_FAILURE);
1760 :
1761 0 : *_retval = !CERT_LIST_EMPTY(mCertList);
1762 0 : return NS_OK;
1763 : }
1764 :
1765 : /* nsISupports getNext(); */
1766 : NS_IMETHODIMP
1767 0 : nsNSSCertListEnumerator::GetNext(nsISupports **_retval)
1768 : {
1769 0 : NS_ENSURE_TRUE(mCertList, NS_ERROR_FAILURE);
1770 :
1771 0 : CERTCertListNode *node = CERT_LIST_HEAD(mCertList);
1772 0 : if (CERT_LIST_END(node, mCertList)) {
1773 0 : return NS_ERROR_FAILURE;
1774 : }
1775 :
1776 0 : nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(node->cert);
1777 0 : if (!nssCert) {
1778 0 : return NS_ERROR_OUT_OF_MEMORY;
1779 : }
1780 :
1781 0 : *_retval = nssCert;
1782 0 : NS_ADDREF(*_retval);
1783 :
1784 0 : CERT_RemoveCertListNode(node);
1785 0 : return NS_OK;
1786 : }
1787 :
1788 : NS_IMETHODIMP
1789 8 : nsNSSCertificate::Write(nsIObjectOutputStream* aStream)
1790 : {
1791 8 : NS_ENSURE_STATE(mCert);
1792 8 : nsresult rv = aStream->Write32(mCert->derCert.len);
1793 8 : if (NS_FAILED(rv)) {
1794 0 : return rv;
1795 : }
1796 :
1797 8 : return aStream->WriteByteArray(mCert->derCert.data, mCert->derCert.len);
1798 : }
1799 :
1800 : NS_IMETHODIMP
1801 0 : nsNSSCertificate::Read(nsIObjectInputStream* aStream)
1802 : {
1803 0 : NS_ENSURE_STATE(!mCert);
1804 :
1805 : PRUint32 len;
1806 0 : nsresult rv = aStream->Read32(&len);
1807 0 : if (NS_FAILED(rv)) {
1808 0 : return rv;
1809 : }
1810 :
1811 0 : nsXPIDLCString str;
1812 0 : rv = aStream->ReadBytes(len, getter_Copies(str));
1813 0 : if (NS_FAILED(rv)) {
1814 0 : return rv;
1815 : }
1816 :
1817 0 : if (!InitFromDER(const_cast<char*>(str.get()), len)) {
1818 0 : return NS_ERROR_UNEXPECTED;
1819 : }
1820 :
1821 0 : return NS_OK;
1822 : }
1823 :
1824 : NS_IMETHODIMP
1825 0 : nsNSSCertificate::GetInterfaces(PRUint32 *count, nsIID * **array)
1826 : {
1827 0 : *count = 0;
1828 0 : *array = nsnull;
1829 0 : return NS_OK;
1830 : }
1831 :
1832 : NS_IMETHODIMP
1833 0 : nsNSSCertificate::GetHelperForLanguage(PRUint32 language, nsISupports **_retval)
1834 : {
1835 0 : *_retval = nsnull;
1836 0 : return NS_OK;
1837 : }
1838 :
1839 : NS_IMETHODIMP
1840 0 : nsNSSCertificate::GetContractID(char * *aContractID)
1841 : {
1842 0 : *aContractID = nsnull;
1843 0 : return NS_OK;
1844 : }
1845 :
1846 : NS_IMETHODIMP
1847 0 : nsNSSCertificate::GetClassDescription(char * *aClassDescription)
1848 : {
1849 0 : *aClassDescription = nsnull;
1850 0 : return NS_OK;
1851 : }
1852 :
1853 : NS_IMETHODIMP
1854 0 : nsNSSCertificate::GetClassID(nsCID * *aClassID)
1855 : {
1856 0 : *aClassID = (nsCID*) nsMemory::Alloc(sizeof(nsCID));
1857 0 : if (!*aClassID)
1858 0 : return NS_ERROR_OUT_OF_MEMORY;
1859 0 : return GetClassIDNoAlloc(*aClassID);
1860 : }
1861 :
1862 : NS_IMETHODIMP
1863 0 : nsNSSCertificate::GetImplementationLanguage(PRUint32 *aImplementationLanguage)
1864 : {
1865 0 : *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
1866 0 : return NS_OK;
1867 : }
1868 :
1869 : NS_IMETHODIMP
1870 0 : nsNSSCertificate::GetFlags(PRUint32 *aFlags)
1871 : {
1872 0 : *aFlags = nsIClassInfo::THREADSAFE;
1873 0 : return NS_OK;
1874 : }
1875 :
1876 : static NS_DEFINE_CID(kNSSCertificateCID, NS_X509CERT_CID);
1877 :
1878 : NS_IMETHODIMP
1879 4 : nsNSSCertificate::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
1880 : {
1881 4 : *aClassIDNoAlloc = kNSSCertificateCID;
1882 4 : return NS_OK;
1883 : }
|