1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/manager/ssl/src/nsNSSCertificate.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1900 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsNSSCertificate.h" 1.10 + 1.11 +#include "prmem.h" 1.12 +#include "prerror.h" 1.13 +#include "prprf.h" 1.14 +#include "CertVerifier.h" 1.15 +#include "ExtendedValidation.h" 1.16 +#include "pkix/pkixtypes.h" 1.17 +#include "nsNSSComponent.h" // for PIPNSS string bundle calls. 1.18 +#include "nsNSSCleaner.h" 1.19 +#include "nsCOMPtr.h" 1.20 +#include "nsIMutableArray.h" 1.21 +#include "nsNSSCertValidity.h" 1.22 +#include "nsPKCS12Blob.h" 1.23 +#include "nsPK11TokenDB.h" 1.24 +#include "nsIX509Cert.h" 1.25 +#include "nsIX509Cert3.h" 1.26 +#include "nsISMimeCert.h" 1.27 +#include "nsNSSASN1Object.h" 1.28 +#include "nsString.h" 1.29 +#include "nsXPIDLString.h" 1.30 +#include "nsReadableUtils.h" 1.31 +#include "nsIURI.h" 1.32 +#include "nsCRT.h" 1.33 +#include "nsUsageArrayHelper.h" 1.34 +#include "nsICertificateDialogs.h" 1.35 +#include "nsNSSCertHelper.h" 1.36 +#include "nsISupportsPrimitives.h" 1.37 +#include "nsUnicharUtils.h" 1.38 +#include "nsThreadUtils.h" 1.39 +#include "nsCertVerificationThread.h" 1.40 +#include "nsIObjectOutputStream.h" 1.41 +#include "nsIObjectInputStream.h" 1.42 +#include "nsIProgrammingLanguage.h" 1.43 +#include "nsXULAppAPI.h" 1.44 +#include "ScopedNSSTypes.h" 1.45 +#include "nsProxyRelease.h" 1.46 +#include "mozilla/Base64.h" 1.47 + 1.48 +#include "nspr.h" 1.49 +#include "certdb.h" 1.50 +#include "secerr.h" 1.51 +#include "nssb64.h" 1.52 +#include "secasn1.h" 1.53 +#include "secder.h" 1.54 +#include "ssl.h" 1.55 +#include "ocsp.h" 1.56 +#include "plbase64.h" 1.57 + 1.58 +using namespace mozilla; 1.59 +using namespace mozilla::psm; 1.60 + 1.61 +#ifdef PR_LOGGING 1.62 +extern PRLogModuleInfo* gPIPNSSLog; 1.63 +#endif 1.64 + 1.65 +NSSCleanupAutoPtrClass_WithParam(PLArenaPool, PORT_FreeArena, FalseParam, false) 1.66 + 1.67 +// This is being stored in an uint32_t that can otherwise 1.68 +// only take values from nsIX509Cert's list of cert types. 1.69 +// As nsIX509Cert is frozen, we choose a value not contained 1.70 +// in the list to mean not yet initialized. 1.71 +#define CERT_TYPE_NOT_YET_INITIALIZED (1 << 30) 1.72 + 1.73 +NS_IMPL_ISUPPORTS(nsNSSCertificate, 1.74 + nsIX509Cert, 1.75 + nsIX509Cert2, 1.76 + nsIX509Cert3, 1.77 + nsIIdentityInfo, 1.78 + nsISMimeCert, 1.79 + nsISerializable, 1.80 + nsIClassInfo) 1.81 + 1.82 +/*static*/ nsNSSCertificate* 1.83 +nsNSSCertificate::Create(CERTCertificate* cert, SECOidTag* evOidPolicy) 1.84 +{ 1.85 + if (GeckoProcessType_Default != XRE_GetProcessType()) { 1.86 + NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!"); 1.87 + return nullptr; 1.88 + } 1.89 + if (cert) 1.90 + return new nsNSSCertificate(cert, evOidPolicy); 1.91 + else 1.92 + return new nsNSSCertificate(); 1.93 +} 1.94 + 1.95 +nsNSSCertificate* 1.96 +nsNSSCertificate::ConstructFromDER(char* certDER, int derLen) 1.97 +{ 1.98 + // On non-chrome process prevent instantiation 1.99 + if (GeckoProcessType_Default != XRE_GetProcessType()) 1.100 + return nullptr; 1.101 + 1.102 + nsNSSCertificate* newObject = nsNSSCertificate::Create(); 1.103 + if (newObject && !newObject->InitFromDER(certDER, derLen)) { 1.104 + delete newObject; 1.105 + newObject = nullptr; 1.106 + } 1.107 + 1.108 + return newObject; 1.109 +} 1.110 + 1.111 +bool 1.112 +nsNSSCertificate::InitFromDER(char* certDER, int derLen) 1.113 +{ 1.114 + nsNSSShutDownPreventionLock locker; 1.115 + if (isAlreadyShutDown()) 1.116 + return false; 1.117 + 1.118 + if (!certDER || !derLen) 1.119 + return false; 1.120 + 1.121 + CERTCertificate* aCert = CERT_DecodeCertFromPackage(certDER, derLen); 1.122 + 1.123 + if (!aCert) 1.124 + return false; 1.125 + 1.126 + if (!aCert->dbhandle) 1.127 + { 1.128 + aCert->dbhandle = CERT_GetDefaultCertDB(); 1.129 + } 1.130 + 1.131 + mCert = aCert; 1.132 + return true; 1.133 +} 1.134 + 1.135 +nsNSSCertificate::nsNSSCertificate(CERTCertificate* cert, 1.136 + SECOidTag* evOidPolicy) 1.137 + : mCert(nullptr) 1.138 + , mPermDelete(false) 1.139 + , mCertType(CERT_TYPE_NOT_YET_INITIALIZED) 1.140 + , mCachedEVStatus(ev_status_unknown) 1.141 +{ 1.142 +#if defined(DEBUG) 1.143 + if (GeckoProcessType_Default != XRE_GetProcessType()) 1.144 + NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!"); 1.145 +#endif 1.146 + 1.147 + nsNSSShutDownPreventionLock locker; 1.148 + if (isAlreadyShutDown()) 1.149 + return; 1.150 + 1.151 + if (cert) { 1.152 + mCert = CERT_DupCertificate(cert); 1.153 + if (evOidPolicy) { 1.154 + if (*evOidPolicy == SEC_OID_UNKNOWN) { 1.155 + mCachedEVStatus = ev_status_invalid; 1.156 + } 1.157 + else { 1.158 + mCachedEVStatus = ev_status_valid; 1.159 + } 1.160 + mCachedEVOidTag = *evOidPolicy; 1.161 + } 1.162 + } 1.163 +} 1.164 + 1.165 +nsNSSCertificate::nsNSSCertificate() : 1.166 + mCert(nullptr), 1.167 + mPermDelete(false), 1.168 + mCertType(CERT_TYPE_NOT_YET_INITIALIZED), 1.169 + mCachedEVStatus(ev_status_unknown) 1.170 +{ 1.171 + if (GeckoProcessType_Default != XRE_GetProcessType()) 1.172 + NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!"); 1.173 +} 1.174 + 1.175 +nsNSSCertificate::~nsNSSCertificate() 1.176 +{ 1.177 + nsNSSShutDownPreventionLock locker; 1.178 + if (isAlreadyShutDown()) { 1.179 + return; 1.180 + } 1.181 + destructorSafeDestroyNSSReference(); 1.182 + shutdown(calledFromObject); 1.183 +} 1.184 + 1.185 +void nsNSSCertificate::virtualDestroyNSSReference() 1.186 +{ 1.187 + destructorSafeDestroyNSSReference(); 1.188 +} 1.189 + 1.190 +void nsNSSCertificate::destructorSafeDestroyNSSReference() 1.191 +{ 1.192 + if (mPermDelete) { 1.193 + if (mCertType == nsNSSCertificate::USER_CERT) { 1.194 + nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext(); 1.195 + PK11_DeleteTokenCertAndKey(mCert.get(), cxt); 1.196 + } else if (!PK11_IsReadOnly(mCert->slot)) { 1.197 + // If the list of built-ins does contain a non-removable 1.198 + // copy of this certificate, our call will not remove 1.199 + // the certificate permanently, but rather remove all trust. 1.200 + SEC_DeletePermCertificate(mCert.get()); 1.201 + } 1.202 + } 1.203 + 1.204 + mCert = nullptr; 1.205 +} 1.206 + 1.207 +nsresult 1.208 +nsNSSCertificate::GetCertType(uint32_t* aCertType) 1.209 +{ 1.210 + if (mCertType == CERT_TYPE_NOT_YET_INITIALIZED) { 1.211 + // only determine cert type once and cache it 1.212 + mCertType = getCertType(mCert.get()); 1.213 + } 1.214 + *aCertType = mCertType; 1.215 + return NS_OK; 1.216 +} 1.217 + 1.218 +NS_IMETHODIMP 1.219 +nsNSSCertificate::GetIsSelfSigned(bool* aIsSelfSigned) 1.220 +{ 1.221 + NS_ENSURE_ARG(aIsSelfSigned); 1.222 + 1.223 + nsNSSShutDownPreventionLock locker; 1.224 + if (isAlreadyShutDown()) 1.225 + return NS_ERROR_NOT_AVAILABLE; 1.226 + 1.227 + *aIsSelfSigned = mCert->isRoot; 1.228 + return NS_OK; 1.229 +} 1.230 + 1.231 +nsresult 1.232 +nsNSSCertificate::MarkForPermDeletion() 1.233 +{ 1.234 + nsNSSShutDownPreventionLock locker; 1.235 + if (isAlreadyShutDown()) 1.236 + return NS_ERROR_NOT_AVAILABLE; 1.237 + 1.238 + // make sure user is logged in to the token 1.239 + nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext(); 1.240 + 1.241 + if (PK11_NeedLogin(mCert->slot) 1.242 + && !PK11_NeedUserInit(mCert->slot) 1.243 + && !PK11_IsInternal(mCert->slot)) 1.244 + { 1.245 + if (SECSuccess != PK11_Authenticate(mCert->slot, true, ctx)) 1.246 + { 1.247 + return NS_ERROR_FAILURE; 1.248 + } 1.249 + } 1.250 + 1.251 + mPermDelete = true; 1.252 + return NS_OK; 1.253 +} 1.254 + 1.255 +nsresult 1.256 +GetKeyUsagesString(CERTCertificate* cert, nsINSSComponent* nssComponent, 1.257 + nsString& text) 1.258 +{ 1.259 + text.Truncate(); 1.260 + 1.261 + SECItem keyUsageItem; 1.262 + keyUsageItem.data = nullptr; 1.263 + 1.264 + SECStatus srv; 1.265 + 1.266 + // There is no extension, v1 or v2 certificate 1.267 + if (!cert->extensions) 1.268 + return NS_OK; 1.269 + 1.270 + 1.271 + srv = CERT_FindKeyUsageExtension(cert, &keyUsageItem); 1.272 + if (srv == SECFailure) { 1.273 + if (PORT_GetError () == SEC_ERROR_EXTENSION_NOT_FOUND) 1.274 + return NS_OK; 1.275 + else 1.276 + return NS_ERROR_FAILURE; 1.277 + } 1.278 + 1.279 + unsigned char keyUsage = keyUsageItem.data[0]; 1.280 + nsAutoString local; 1.281 + nsresult rv; 1.282 + const char16_t comma = ','; 1.283 + 1.284 + if (keyUsage & KU_DIGITAL_SIGNATURE) { 1.285 + rv = nssComponent->GetPIPNSSBundleString("CertDumpKUSign", local); 1.286 + if (NS_SUCCEEDED(rv)) { 1.287 + if (!text.IsEmpty()) text.Append(comma); 1.288 + text.Append(local.get()); 1.289 + } 1.290 + } 1.291 + if (keyUsage & KU_NON_REPUDIATION) { 1.292 + rv = nssComponent->GetPIPNSSBundleString("CertDumpKUNonRep", local); 1.293 + if (NS_SUCCEEDED(rv)) { 1.294 + if (!text.IsEmpty()) text.Append(comma); 1.295 + text.Append(local.get()); 1.296 + } 1.297 + } 1.298 + if (keyUsage & KU_KEY_ENCIPHERMENT) { 1.299 + rv = nssComponent->GetPIPNSSBundleString("CertDumpKUEnc", local); 1.300 + if (NS_SUCCEEDED(rv)) { 1.301 + if (!text.IsEmpty()) text.Append(comma); 1.302 + text.Append(local.get()); 1.303 + } 1.304 + } 1.305 + if (keyUsage & KU_DATA_ENCIPHERMENT) { 1.306 + rv = nssComponent->GetPIPNSSBundleString("CertDumpKUDEnc", local); 1.307 + if (NS_SUCCEEDED(rv)) { 1.308 + if (!text.IsEmpty()) text.Append(comma); 1.309 + text.Append(local.get()); 1.310 + } 1.311 + } 1.312 + if (keyUsage & KU_KEY_AGREEMENT) { 1.313 + rv = nssComponent->GetPIPNSSBundleString("CertDumpKUKA", local); 1.314 + if (NS_SUCCEEDED(rv)) { 1.315 + if (!text.IsEmpty()) text.Append(comma); 1.316 + text.Append(local.get()); 1.317 + } 1.318 + } 1.319 + if (keyUsage & KU_KEY_CERT_SIGN) { 1.320 + rv = nssComponent->GetPIPNSSBundleString("CertDumpKUCertSign", local); 1.321 + if (NS_SUCCEEDED(rv)) { 1.322 + if (!text.IsEmpty()) text.Append(comma); 1.323 + text.Append(local.get()); 1.324 + } 1.325 + } 1.326 + if (keyUsage & KU_CRL_SIGN) { 1.327 + rv = nssComponent->GetPIPNSSBundleString("CertDumpKUCRLSign", local); 1.328 + if (NS_SUCCEEDED(rv)) { 1.329 + if (!text.IsEmpty()) text.Append(comma); 1.330 + text.Append(local.get()); 1.331 + } 1.332 + } 1.333 + 1.334 + PORT_Free (keyUsageItem.data); 1.335 + return NS_OK; 1.336 +} 1.337 + 1.338 +nsresult 1.339 +nsNSSCertificate::FormatUIStrings(const nsAutoString& nickname, 1.340 + nsAutoString& nickWithSerial, 1.341 + nsAutoString& details) 1.342 +{ 1.343 + static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); 1.344 + 1.345 + if (!NS_IsMainThread()) { 1.346 + NS_ERROR("nsNSSCertificate::FormatUIStrings called off the main thread"); 1.347 + return NS_ERROR_NOT_SAME_THREAD; 1.348 + } 1.349 + 1.350 + nsresult rv = NS_OK; 1.351 + 1.352 + nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv)); 1.353 + 1.354 + if (NS_FAILED(rv) || !nssComponent) { 1.355 + return NS_ERROR_FAILURE; 1.356 + } 1.357 + 1.358 + nsAutoString info; 1.359 + nsAutoString temp1; 1.360 + 1.361 + nickWithSerial.Append(nickname); 1.362 + 1.363 + if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoIssuedFor", info))) { 1.364 + details.Append(info); 1.365 + details.Append(char16_t(' ')); 1.366 + if (NS_SUCCEEDED(GetSubjectName(temp1)) && !temp1.IsEmpty()) { 1.367 + details.Append(temp1); 1.368 + } 1.369 + details.Append(char16_t('\n')); 1.370 + } 1.371 + 1.372 + if (NS_SUCCEEDED(GetSerialNumber(temp1)) && !temp1.IsEmpty()) { 1.373 + details.AppendLiteral(" "); 1.374 + if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertDumpSerialNo", info))) { 1.375 + details.Append(info); 1.376 + details.AppendLiteral(": "); 1.377 + } 1.378 + details.Append(temp1); 1.379 + 1.380 + nickWithSerial.AppendLiteral(" ["); 1.381 + nickWithSerial.Append(temp1); 1.382 + nickWithSerial.Append(char16_t(']')); 1.383 + 1.384 + details.Append(char16_t('\n')); 1.385 + } 1.386 + 1.387 + nsCOMPtr<nsIX509CertValidity> validity; 1.388 + rv = GetValidity(getter_AddRefs(validity)); 1.389 + if (NS_SUCCEEDED(rv) && validity) { 1.390 + details.AppendLiteral(" "); 1.391 + if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoValid", info))) { 1.392 + details.Append(info); 1.393 + } 1.394 + 1.395 + if (NS_SUCCEEDED(validity->GetNotBeforeLocalTime(temp1)) && !temp1.IsEmpty()) { 1.396 + details.Append(char16_t(' ')); 1.397 + if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoFrom", info))) { 1.398 + details.Append(info); 1.399 + details.Append(char16_t(' ')); 1.400 + } 1.401 + details.Append(temp1); 1.402 + } 1.403 + 1.404 + if (NS_SUCCEEDED(validity->GetNotAfterLocalTime(temp1)) && !temp1.IsEmpty()) { 1.405 + details.Append(char16_t(' ')); 1.406 + if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoTo", info))) { 1.407 + details.Append(info); 1.408 + details.Append(char16_t(' ')); 1.409 + } 1.410 + details.Append(temp1); 1.411 + } 1.412 + 1.413 + details.Append(char16_t('\n')); 1.414 + } 1.415 + 1.416 + if (NS_SUCCEEDED(GetKeyUsagesString(mCert.get(), nssComponent, temp1)) && 1.417 + !temp1.IsEmpty()) { 1.418 + details.AppendLiteral(" "); 1.419 + if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertDumpKeyUsage", info))) { 1.420 + details.Append(info); 1.421 + details.AppendLiteral(": "); 1.422 + } 1.423 + details.Append(temp1); 1.424 + details.Append(char16_t('\n')); 1.425 + } 1.426 + 1.427 + nsAutoString firstEmail; 1.428 + const char* aWalkAddr; 1.429 + for (aWalkAddr = CERT_GetFirstEmailAddress(mCert.get()) 1.430 + ; 1.431 + aWalkAddr 1.432 + ; 1.433 + aWalkAddr = CERT_GetNextEmailAddress(mCert.get(), aWalkAddr)) 1.434 + { 1.435 + NS_ConvertUTF8toUTF16 email(aWalkAddr); 1.436 + if (email.IsEmpty()) 1.437 + continue; 1.438 + 1.439 + if (firstEmail.IsEmpty()) { 1.440 + // If the first email address from the subject DN is also present 1.441 + // in the subjectAltName extension, GetEmailAddresses() will return 1.442 + // it twice (as received from NSS). Remember the first address so that 1.443 + // we can filter out duplicates later on. 1.444 + firstEmail = email; 1.445 + 1.446 + details.AppendLiteral(" "); 1.447 + if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoEmail", info))) { 1.448 + details.Append(info); 1.449 + details.AppendLiteral(": "); 1.450 + } 1.451 + details.Append(email); 1.452 + } 1.453 + else { 1.454 + // Append current address if it's different from the first one. 1.455 + if (!firstEmail.Equals(email)) { 1.456 + details.AppendLiteral(", "); 1.457 + details.Append(email); 1.458 + } 1.459 + } 1.460 + } 1.461 + 1.462 + if (!firstEmail.IsEmpty()) { 1.463 + // We got at least one email address, so we want a newline 1.464 + details.Append(char16_t('\n')); 1.465 + } 1.466 + 1.467 + if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoIssuedBy", info))) { 1.468 + details.Append(info); 1.469 + details.Append(char16_t(' ')); 1.470 + 1.471 + if (NS_SUCCEEDED(GetIssuerName(temp1)) && !temp1.IsEmpty()) { 1.472 + details.Append(temp1); 1.473 + } 1.474 + 1.475 + details.Append(char16_t('\n')); 1.476 + } 1.477 + 1.478 + if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoStoredIn", info))) { 1.479 + details.Append(info); 1.480 + details.Append(char16_t(' ')); 1.481 + 1.482 + if (NS_SUCCEEDED(GetTokenName(temp1)) && !temp1.IsEmpty()) { 1.483 + details.Append(temp1); 1.484 + } 1.485 + } 1.486 + 1.487 + // the above produces the following output: 1.488 + // 1.489 + // Issued to: $subjectName 1.490 + // Serial number: $serialNumber 1.491 + // Valid from: $starting_date to $expiration_date 1.492 + // Certificate Key usage: $usages 1.493 + // Email: $address(es) 1.494 + // Issued by: $issuerName 1.495 + // Stored in: $token 1.496 + 1.497 + return rv; 1.498 +} 1.499 + 1.500 +NS_IMETHODIMP 1.501 +nsNSSCertificate::GetDbKey(char** aDbKey) 1.502 +{ 1.503 + nsNSSShutDownPreventionLock locker; 1.504 + if (isAlreadyShutDown()) 1.505 + return NS_ERROR_NOT_AVAILABLE; 1.506 + 1.507 + SECItem key; 1.508 + 1.509 + NS_ENSURE_ARG(aDbKey); 1.510 + *aDbKey = nullptr; 1.511 + key.len = NS_NSS_LONG*4+mCert->serialNumber.len+mCert->derIssuer.len; 1.512 + key.data = (unsigned char*) nsMemory::Alloc(key.len); 1.513 + if (!key.data) 1.514 + return NS_ERROR_OUT_OF_MEMORY; 1.515 + NS_NSS_PUT_LONG(0,key.data); // later put moduleID 1.516 + NS_NSS_PUT_LONG(0,&key.data[NS_NSS_LONG]); // later put slotID 1.517 + NS_NSS_PUT_LONG(mCert->serialNumber.len,&key.data[NS_NSS_LONG*2]); 1.518 + NS_NSS_PUT_LONG(mCert->derIssuer.len,&key.data[NS_NSS_LONG*3]); 1.519 + memcpy(&key.data[NS_NSS_LONG*4], mCert->serialNumber.data, 1.520 + mCert->serialNumber.len); 1.521 + memcpy(&key.data[NS_NSS_LONG*4+mCert->serialNumber.len], 1.522 + mCert->derIssuer.data, mCert->derIssuer.len); 1.523 + 1.524 + *aDbKey = NSSBase64_EncodeItem(nullptr, nullptr, 0, &key); 1.525 + nsMemory::Free(key.data); // SECItem is a 'c' type without a destrutor 1.526 + return (*aDbKey) ? NS_OK : NS_ERROR_FAILURE; 1.527 +} 1.528 + 1.529 +NS_IMETHODIMP 1.530 +nsNSSCertificate::GetWindowTitle(char** aWindowTitle) 1.531 +{ 1.532 + nsNSSShutDownPreventionLock locker; 1.533 + if (isAlreadyShutDown()) 1.534 + return NS_ERROR_NOT_AVAILABLE; 1.535 + 1.536 + NS_ENSURE_ARG(aWindowTitle); 1.537 + if (mCert) { 1.538 + if (mCert->nickname) { 1.539 + *aWindowTitle = PL_strdup(mCert->nickname); 1.540 + } else { 1.541 + *aWindowTitle = CERT_GetCommonName(&mCert->subject); 1.542 + if (!*aWindowTitle) { 1.543 + if (mCert->subjectName) { 1.544 + *aWindowTitle = PL_strdup(mCert->subjectName); 1.545 + } else if (mCert->emailAddr) { 1.546 + *aWindowTitle = PL_strdup(mCert->emailAddr); 1.547 + } else { 1.548 + *aWindowTitle = PL_strdup(""); 1.549 + } 1.550 + } 1.551 + } 1.552 + } else { 1.553 + NS_ERROR("Somehow got nullptr for mCertificate in nsNSSCertificate."); 1.554 + *aWindowTitle = nullptr; 1.555 + } 1.556 + return NS_OK; 1.557 +} 1.558 + 1.559 +NS_IMETHODIMP 1.560 +nsNSSCertificate::GetNickname(nsAString& aNickname) 1.561 +{ 1.562 + static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); 1.563 + 1.564 + nsNSSShutDownPreventionLock locker; 1.565 + if (isAlreadyShutDown()) 1.566 + return NS_ERROR_NOT_AVAILABLE; 1.567 + 1.568 + if (mCert->nickname) { 1.569 + CopyUTF8toUTF16(mCert->nickname, aNickname); 1.570 + } else { 1.571 + nsresult rv; 1.572 + nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv)); 1.573 + if (NS_FAILED(rv) || !nssComponent) { 1.574 + return NS_ERROR_FAILURE; 1.575 + } 1.576 + nssComponent->GetPIPNSSBundleString("CertNoNickname", aNickname); 1.577 + } 1.578 + return NS_OK; 1.579 +} 1.580 + 1.581 +NS_IMETHODIMP 1.582 +nsNSSCertificate::GetEmailAddress(nsAString& aEmailAddress) 1.583 +{ 1.584 + static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); 1.585 + 1.586 + nsNSSShutDownPreventionLock locker; 1.587 + if (isAlreadyShutDown()) 1.588 + return NS_ERROR_NOT_AVAILABLE; 1.589 + 1.590 + if (mCert->emailAddr) { 1.591 + CopyUTF8toUTF16(mCert->emailAddr, aEmailAddress); 1.592 + } else { 1.593 + nsresult rv; 1.594 + nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv)); 1.595 + if (NS_FAILED(rv) || !nssComponent) { 1.596 + return NS_ERROR_FAILURE; 1.597 + } 1.598 + nssComponent->GetPIPNSSBundleString("CertNoEmailAddress", aEmailAddress); 1.599 + } 1.600 + return NS_OK; 1.601 +} 1.602 + 1.603 +NS_IMETHODIMP 1.604 +nsNSSCertificate::GetEmailAddresses(uint32_t* aLength, char16_t*** aAddresses) 1.605 +{ 1.606 + nsNSSShutDownPreventionLock locker; 1.607 + if (isAlreadyShutDown()) 1.608 + return NS_ERROR_NOT_AVAILABLE; 1.609 + 1.610 + NS_ENSURE_ARG(aLength); 1.611 + NS_ENSURE_ARG(aAddresses); 1.612 + 1.613 + *aLength = 0; 1.614 + 1.615 + const char* aAddr; 1.616 + for (aAddr = CERT_GetFirstEmailAddress(mCert.get()) 1.617 + ; 1.618 + aAddr 1.619 + ; 1.620 + aAddr = CERT_GetNextEmailAddress(mCert.get(), aAddr)) 1.621 + { 1.622 + ++(*aLength); 1.623 + } 1.624 + 1.625 + *aAddresses = (char16_t**) nsMemory::Alloc(sizeof(char16_t*) * (*aLength)); 1.626 + if (!*aAddresses) 1.627 + return NS_ERROR_OUT_OF_MEMORY; 1.628 + 1.629 + uint32_t iAddr; 1.630 + for (aAddr = CERT_GetFirstEmailAddress(mCert.get()), iAddr = 0 1.631 + ; 1.632 + aAddr 1.633 + ; 1.634 + aAddr = CERT_GetNextEmailAddress(mCert.get(), aAddr), ++iAddr) 1.635 + { 1.636 + (*aAddresses)[iAddr] = ToNewUnicode(NS_ConvertUTF8toUTF16(aAddr)); 1.637 + } 1.638 + 1.639 + return NS_OK; 1.640 +} 1.641 + 1.642 +NS_IMETHODIMP 1.643 +nsNSSCertificate::ContainsEmailAddress(const nsAString& aEmailAddress, 1.644 + bool* result) 1.645 +{ 1.646 + nsNSSShutDownPreventionLock locker; 1.647 + if (isAlreadyShutDown()) 1.648 + return NS_ERROR_NOT_AVAILABLE; 1.649 + 1.650 + NS_ENSURE_ARG(result); 1.651 + *result = false; 1.652 + 1.653 + const char* aAddr = nullptr; 1.654 + for (aAddr = CERT_GetFirstEmailAddress(mCert.get()) 1.655 + ; 1.656 + aAddr 1.657 + ; 1.658 + aAddr = CERT_GetNextEmailAddress(mCert.get(), aAddr)) 1.659 + { 1.660 + NS_ConvertUTF8toUTF16 certAddr(aAddr); 1.661 + ToLowerCase(certAddr); 1.662 + 1.663 + nsAutoString testAddr(aEmailAddress); 1.664 + ToLowerCase(testAddr); 1.665 + 1.666 + if (certAddr == testAddr) 1.667 + { 1.668 + *result = true; 1.669 + break; 1.670 + } 1.671 + 1.672 + } 1.673 + 1.674 + return NS_OK; 1.675 +} 1.676 + 1.677 +NS_IMETHODIMP 1.678 +nsNSSCertificate::GetCommonName(nsAString& aCommonName) 1.679 +{ 1.680 + nsNSSShutDownPreventionLock locker; 1.681 + if (isAlreadyShutDown()) 1.682 + return NS_ERROR_NOT_AVAILABLE; 1.683 + 1.684 + aCommonName.Truncate(); 1.685 + if (mCert) { 1.686 + char* commonName = CERT_GetCommonName(&mCert->subject); 1.687 + if (commonName) { 1.688 + aCommonName = NS_ConvertUTF8toUTF16(commonName); 1.689 + PORT_Free(commonName); 1.690 + } 1.691 + } 1.692 + return NS_OK; 1.693 +} 1.694 + 1.695 +NS_IMETHODIMP 1.696 +nsNSSCertificate::GetOrganization(nsAString& aOrganization) 1.697 +{ 1.698 + nsNSSShutDownPreventionLock locker; 1.699 + if (isAlreadyShutDown()) 1.700 + return NS_ERROR_NOT_AVAILABLE; 1.701 + 1.702 + aOrganization.Truncate(); 1.703 + if (mCert) { 1.704 + char* organization = CERT_GetOrgName(&mCert->subject); 1.705 + if (organization) { 1.706 + aOrganization = NS_ConvertUTF8toUTF16(organization); 1.707 + PORT_Free(organization); 1.708 + } 1.709 + } 1.710 + return NS_OK; 1.711 +} 1.712 + 1.713 +NS_IMETHODIMP 1.714 +nsNSSCertificate::GetIssuerCommonName(nsAString& aCommonName) 1.715 +{ 1.716 + nsNSSShutDownPreventionLock locker; 1.717 + if (isAlreadyShutDown()) 1.718 + return NS_ERROR_NOT_AVAILABLE; 1.719 + 1.720 + aCommonName.Truncate(); 1.721 + if (mCert) { 1.722 + char* commonName = CERT_GetCommonName(&mCert->issuer); 1.723 + if (commonName) { 1.724 + aCommonName = NS_ConvertUTF8toUTF16(commonName); 1.725 + PORT_Free(commonName); 1.726 + } 1.727 + } 1.728 + return NS_OK; 1.729 +} 1.730 + 1.731 +NS_IMETHODIMP 1.732 +nsNSSCertificate::GetIssuerOrganization(nsAString& aOrganization) 1.733 +{ 1.734 + nsNSSShutDownPreventionLock locker; 1.735 + if (isAlreadyShutDown()) 1.736 + return NS_ERROR_NOT_AVAILABLE; 1.737 + 1.738 + aOrganization.Truncate(); 1.739 + if (mCert) { 1.740 + char* organization = CERT_GetOrgName(&mCert->issuer); 1.741 + if (organization) { 1.742 + aOrganization = NS_ConvertUTF8toUTF16(organization); 1.743 + PORT_Free(organization); 1.744 + } else { 1.745 + return GetIssuerCommonName(aOrganization); 1.746 + } 1.747 + } 1.748 + return NS_OK; 1.749 +} 1.750 + 1.751 +NS_IMETHODIMP 1.752 +nsNSSCertificate::GetIssuerOrganizationUnit(nsAString& aOrganizationUnit) 1.753 +{ 1.754 + nsNSSShutDownPreventionLock locker; 1.755 + if (isAlreadyShutDown()) 1.756 + return NS_ERROR_NOT_AVAILABLE; 1.757 + 1.758 + aOrganizationUnit.Truncate(); 1.759 + if (mCert) { 1.760 + char* organizationUnit = CERT_GetOrgUnitName(&mCert->issuer); 1.761 + if (organizationUnit) { 1.762 + aOrganizationUnit = NS_ConvertUTF8toUTF16(organizationUnit); 1.763 + PORT_Free(organizationUnit); 1.764 + } 1.765 + } 1.766 + return NS_OK; 1.767 +} 1.768 + 1.769 +NS_IMETHODIMP 1.770 +nsNSSCertificate::GetIssuer(nsIX509Cert** aIssuer) 1.771 +{ 1.772 + nsNSSShutDownPreventionLock locker; 1.773 + if (isAlreadyShutDown()) 1.774 + return NS_ERROR_NOT_AVAILABLE; 1.775 + 1.776 + NS_ENSURE_ARG(aIssuer); 1.777 + *aIssuer = nullptr; 1.778 + 1.779 + nsCOMPtr<nsIArray> chain; 1.780 + nsresult rv; 1.781 + rv = GetChain(getter_AddRefs(chain)); 1.782 + NS_ENSURE_SUCCESS(rv, rv); 1.783 + uint32_t length; 1.784 + if (!chain || NS_FAILED(chain->GetLength(&length)) || length == 0) { 1.785 + return NS_ERROR_UNEXPECTED; 1.786 + } 1.787 + if (length == 1) { // No known issuer 1.788 + return NS_OK; 1.789 + } 1.790 + nsCOMPtr<nsIX509Cert> cert; 1.791 + chain->QueryElementAt(1, NS_GET_IID(nsIX509Cert), getter_AddRefs(cert)); 1.792 + if (!cert) { 1.793 + return NS_ERROR_UNEXPECTED; 1.794 + } 1.795 + *aIssuer = cert; 1.796 + NS_ADDREF(*aIssuer); 1.797 + return NS_OK; 1.798 +} 1.799 + 1.800 +NS_IMETHODIMP 1.801 +nsNSSCertificate::GetOrganizationalUnit(nsAString& aOrganizationalUnit) 1.802 +{ 1.803 + nsNSSShutDownPreventionLock locker; 1.804 + if (isAlreadyShutDown()) 1.805 + return NS_ERROR_NOT_AVAILABLE; 1.806 + 1.807 + aOrganizationalUnit.Truncate(); 1.808 + if (mCert) { 1.809 + char* orgunit = CERT_GetOrgUnitName(&mCert->subject); 1.810 + if (orgunit) { 1.811 + aOrganizationalUnit = NS_ConvertUTF8toUTF16(orgunit); 1.812 + PORT_Free(orgunit); 1.813 + } 1.814 + } 1.815 + return NS_OK; 1.816 +} 1.817 + 1.818 +NS_IMETHODIMP 1.819 +nsNSSCertificate::GetChain(nsIArray** _rvChain) 1.820 +{ 1.821 + nsNSSShutDownPreventionLock locker; 1.822 + if (isAlreadyShutDown()) 1.823 + return NS_ERROR_NOT_AVAILABLE; 1.824 + 1.825 + NS_ENSURE_ARG(_rvChain); 1.826 + nsresult rv; 1.827 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Getting chain for \"%s\"\n", mCert->nickname)); 1.828 + 1.829 + ::mozilla::pkix::ScopedCERTCertList nssChain; 1.830 + RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier()); 1.831 + NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED); 1.832 + 1.833 + // We want to test all usages, but we start with server because most of the 1.834 + // time Firefox users care about server certs. 1.835 + certVerifier->VerifyCert(mCert.get(), 1.836 + certificateUsageSSLServer, PR_Now(), 1.837 + nullptr, /*XXX fixme*/ 1.838 + nullptr, /* hostname */ 1.839 + CertVerifier::FLAG_LOCAL_ONLY, 1.840 + nullptr, /* stapledOCSPResponse */ 1.841 + &nssChain); 1.842 + // This is the whitelist of all non-SSLServer usages that are supported by 1.843 + // verifycert. 1.844 + const int otherUsagesToTest = certificateUsageSSLClient | 1.845 + certificateUsageSSLCA | 1.846 + certificateUsageEmailSigner | 1.847 + certificateUsageEmailRecipient | 1.848 + certificateUsageObjectSigner | 1.849 + certificateUsageStatusResponder; 1.850 + for (int usage = certificateUsageSSLClient; 1.851 + usage < certificateUsageAnyCA && !nssChain; 1.852 + usage = usage << 1) { 1.853 + if ((usage & otherUsagesToTest) == 0) { 1.854 + continue; 1.855 + } 1.856 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, 1.857 + ("pipnss: PKIX attempting chain(%d) for '%s'\n", 1.858 + usage, mCert->nickname)); 1.859 + certVerifier->VerifyCert(mCert.get(), 1.860 + usage, PR_Now(), 1.861 + nullptr, /*XXX fixme*/ 1.862 + nullptr, /*hostname*/ 1.863 + CertVerifier::FLAG_LOCAL_ONLY, 1.864 + nullptr, /* stapledOCSPResponse */ 1.865 + &nssChain); 1.866 + } 1.867 + 1.868 + if (!nssChain) { 1.869 + // There is not verified path for the chain, howeever we still want to 1.870 + // present to the user as much of a possible chain as possible, in the case 1.871 + // where there was a problem with the cert or the issuers. 1.872 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, 1.873 + ("pipnss: getchain :CertVerify failed to get chain for '%s'\n", 1.874 + mCert->nickname)); 1.875 + nssChain = CERT_GetCertChainFromCert(mCert.get(), PR_Now(), 1.876 + certUsageSSLClient); 1.877 + } 1.878 + 1.879 + if (!nssChain) { 1.880 + return NS_ERROR_FAILURE; 1.881 + } 1.882 + 1.883 + // enumerate the chain for scripting purposes 1.884 + nsCOMPtr<nsIMutableArray> array = 1.885 + do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); 1.886 + if (NS_FAILED(rv)) { 1.887 + goto done; 1.888 + } 1.889 + CERTCertListNode* node; 1.890 + for (node = CERT_LIST_HEAD(nssChain.get()); 1.891 + !CERT_LIST_END(node, nssChain.get()); 1.892 + node = CERT_LIST_NEXT(node)) { 1.893 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, 1.894 + ("adding %s to chain\n", node->cert->nickname)); 1.895 + nsCOMPtr<nsIX509Cert> cert = nsNSSCertificate::Create(node->cert); 1.896 + array->AppendElement(cert, false); 1.897 + } 1.898 + *_rvChain = array; 1.899 + NS_IF_ADDREF(*_rvChain); 1.900 + rv = NS_OK; 1.901 +done: 1.902 + return rv; 1.903 +} 1.904 + 1.905 +NS_IMETHODIMP 1.906 +nsNSSCertificate::GetAllTokenNames(uint32_t* aLength, char16_t*** aTokenNames) 1.907 +{ 1.908 + nsNSSShutDownPreventionLock locker; 1.909 + if (isAlreadyShutDown()) 1.910 + return NS_ERROR_NOT_AVAILABLE; 1.911 + 1.912 + NS_ENSURE_ARG(aLength); 1.913 + NS_ENSURE_ARG(aTokenNames); 1.914 + *aLength = 0; 1.915 + *aTokenNames = nullptr; 1.916 + 1.917 + // Get the slots from NSS 1.918 + ScopedPK11SlotList slots; 1.919 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Getting slots for \"%s\"\n", mCert->nickname)); 1.920 + slots = PK11_GetAllSlotsForCert(mCert.get(), nullptr); 1.921 + if (!slots) { 1.922 + if (PORT_GetError() == SEC_ERROR_NO_TOKEN) 1.923 + return NS_OK; // List of slots is empty, return empty array 1.924 + else 1.925 + return NS_ERROR_FAILURE; 1.926 + } 1.927 + 1.928 + // read the token names from slots 1.929 + PK11SlotListElement* le; 1.930 + 1.931 + for (le = slots->head; le; le = le->next) { 1.932 + ++(*aLength); 1.933 + } 1.934 + 1.935 + *aTokenNames = (char16_t**) nsMemory::Alloc(sizeof(char16_t*) * (*aLength)); 1.936 + if (!*aTokenNames) { 1.937 + *aLength = 0; 1.938 + return NS_ERROR_OUT_OF_MEMORY; 1.939 + } 1.940 + 1.941 + uint32_t iToken; 1.942 + for (le = slots->head, iToken = 0; le; le = le->next, ++iToken) { 1.943 + char* token = PK11_GetTokenName(le->slot); 1.944 + (*aTokenNames)[iToken] = ToNewUnicode(NS_ConvertUTF8toUTF16(token)); 1.945 + if (!(*aTokenNames)[iToken]) { 1.946 + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(iToken, *aTokenNames); 1.947 + *aLength = 0; 1.948 + *aTokenNames = nullptr; 1.949 + return NS_ERROR_OUT_OF_MEMORY; 1.950 + } 1.951 + } 1.952 + 1.953 + return NS_OK; 1.954 +} 1.955 + 1.956 +NS_IMETHODIMP 1.957 +nsNSSCertificate::GetSubjectName(nsAString& _subjectName) 1.958 +{ 1.959 + nsNSSShutDownPreventionLock locker; 1.960 + if (isAlreadyShutDown()) 1.961 + return NS_ERROR_NOT_AVAILABLE; 1.962 + 1.963 + _subjectName.Truncate(); 1.964 + if (mCert->subjectName) { 1.965 + _subjectName = NS_ConvertUTF8toUTF16(mCert->subjectName); 1.966 + return NS_OK; 1.967 + } 1.968 + return NS_ERROR_FAILURE; 1.969 +} 1.970 + 1.971 +NS_IMETHODIMP 1.972 +nsNSSCertificate::GetIssuerName(nsAString& _issuerName) 1.973 +{ 1.974 + nsNSSShutDownPreventionLock locker; 1.975 + if (isAlreadyShutDown()) 1.976 + return NS_ERROR_NOT_AVAILABLE; 1.977 + 1.978 + _issuerName.Truncate(); 1.979 + if (mCert->issuerName) { 1.980 + _issuerName = NS_ConvertUTF8toUTF16(mCert->issuerName); 1.981 + return NS_OK; 1.982 + } 1.983 + return NS_ERROR_FAILURE; 1.984 +} 1.985 + 1.986 +NS_IMETHODIMP 1.987 +nsNSSCertificate::GetSerialNumber(nsAString& _serialNumber) 1.988 +{ 1.989 + nsNSSShutDownPreventionLock locker; 1.990 + if (isAlreadyShutDown()) 1.991 + return NS_ERROR_NOT_AVAILABLE; 1.992 + 1.993 + _serialNumber.Truncate(); 1.994 + char* tmpstr = CERT_Hexify(&mCert->serialNumber, 1); 1.995 + if (tmpstr) { 1.996 + _serialNumber = NS_ConvertASCIItoUTF16(tmpstr); 1.997 + PORT_Free(tmpstr); 1.998 + return NS_OK; 1.999 + } 1.1000 + return NS_ERROR_FAILURE; 1.1001 +} 1.1002 + 1.1003 +NS_IMETHODIMP 1.1004 +nsNSSCertificate::GetSha1Fingerprint(nsAString& _sha1Fingerprint) 1.1005 +{ 1.1006 + nsNSSShutDownPreventionLock locker; 1.1007 + if (isAlreadyShutDown()) 1.1008 + return NS_ERROR_NOT_AVAILABLE; 1.1009 + 1.1010 + _sha1Fingerprint.Truncate(); 1.1011 + unsigned char fingerprint[20]; 1.1012 + SECItem fpItem; 1.1013 + memset(fingerprint, 0, sizeof fingerprint); 1.1014 + PK11_HashBuf(SEC_OID_SHA1, fingerprint, 1.1015 + mCert->derCert.data, mCert->derCert.len); 1.1016 + fpItem.data = fingerprint; 1.1017 + fpItem.len = SHA1_LENGTH; 1.1018 + char* fpStr = CERT_Hexify(&fpItem, 1); 1.1019 + if (fpStr) { 1.1020 + _sha1Fingerprint = NS_ConvertASCIItoUTF16(fpStr); 1.1021 + PORT_Free(fpStr); 1.1022 + return NS_OK; 1.1023 + } 1.1024 + return NS_ERROR_FAILURE; 1.1025 +} 1.1026 + 1.1027 +NS_IMETHODIMP 1.1028 +nsNSSCertificate::GetMd5Fingerprint(nsAString& _md5Fingerprint) 1.1029 +{ 1.1030 + nsNSSShutDownPreventionLock locker; 1.1031 + if (isAlreadyShutDown()) 1.1032 + return NS_ERROR_NOT_AVAILABLE; 1.1033 + 1.1034 + _md5Fingerprint.Truncate(); 1.1035 + unsigned char fingerprint[20]; 1.1036 + SECItem fpItem; 1.1037 + memset(fingerprint, 0, sizeof fingerprint); 1.1038 + PK11_HashBuf(SEC_OID_MD5, fingerprint, 1.1039 + mCert->derCert.data, mCert->derCert.len); 1.1040 + fpItem.data = fingerprint; 1.1041 + fpItem.len = MD5_LENGTH; 1.1042 + char* fpStr = CERT_Hexify(&fpItem, 1); 1.1043 + if (fpStr) { 1.1044 + _md5Fingerprint = NS_ConvertASCIItoUTF16(fpStr); 1.1045 + PORT_Free(fpStr); 1.1046 + return NS_OK; 1.1047 + } 1.1048 + return NS_ERROR_FAILURE; 1.1049 +} 1.1050 + 1.1051 +NS_IMETHODIMP 1.1052 +nsNSSCertificate::GetTokenName(nsAString& aTokenName) 1.1053 +{ 1.1054 + static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); 1.1055 + 1.1056 + nsNSSShutDownPreventionLock locker; 1.1057 + if (isAlreadyShutDown()) 1.1058 + return NS_ERROR_NOT_AVAILABLE; 1.1059 + 1.1060 + aTokenName.Truncate(); 1.1061 + if (mCert) { 1.1062 + // HACK alert 1.1063 + // When the trust of a builtin cert is modified, NSS copies it into the 1.1064 + // cert db. At this point, it is now "managed" by the user, and should 1.1065 + // not be listed with the builtins. However, in the collection code 1.1066 + // used by PK11_ListCerts, the cert is found in the temp db, where it 1.1067 + // has been loaded from the token. Though the trust is correct (grabbed 1.1068 + // from the cert db), the source is wrong. I believe this is a safe 1.1069 + // way to work around this. 1.1070 + if (mCert->slot) { 1.1071 + char* token = PK11_GetTokenName(mCert->slot); 1.1072 + if (token) { 1.1073 + aTokenName = NS_ConvertUTF8toUTF16(token); 1.1074 + } 1.1075 + } else { 1.1076 + nsresult rv; 1.1077 + nsAutoString tok; 1.1078 + nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv)); 1.1079 + if (NS_FAILED(rv)) return rv; 1.1080 + rv = nssComponent->GetPIPNSSBundleString("InternalToken", tok); 1.1081 + if (NS_SUCCEEDED(rv)) 1.1082 + aTokenName = tok; 1.1083 + } 1.1084 + } 1.1085 + return NS_OK; 1.1086 +} 1.1087 + 1.1088 +NS_IMETHODIMP 1.1089 +nsNSSCertificate::GetSha256SubjectPublicKeyInfoDigest(nsACString& aSha256SPKIDigest) 1.1090 +{ 1.1091 + nsNSSShutDownPreventionLock locker; 1.1092 + if (isAlreadyShutDown()) { 1.1093 + return NS_ERROR_NOT_AVAILABLE; 1.1094 + } 1.1095 + 1.1096 + aSha256SPKIDigest.Truncate(); 1.1097 + Digest digest; 1.1098 + nsresult rv = digest.DigestBuf(SEC_OID_SHA256, mCert->derPublicKey.data, 1.1099 + mCert->derPublicKey.len); 1.1100 + if (NS_WARN_IF(NS_FAILED(rv))) { 1.1101 + return rv; 1.1102 + } 1.1103 + rv = Base64Encode(nsDependentCSubstring( 1.1104 + reinterpret_cast<const char*> (digest.get().data), 1.1105 + digest.get().len), 1.1106 + aSha256SPKIDigest); 1.1107 + if (NS_WARN_IF(NS_FAILED(rv))) { 1.1108 + return rv; 1.1109 + } 1.1110 + return NS_OK; 1.1111 +} 1.1112 + 1.1113 +NS_IMETHODIMP 1.1114 +nsNSSCertificate::GetRawDER(uint32_t* aLength, uint8_t** aArray) 1.1115 +{ 1.1116 + nsNSSShutDownPreventionLock locker; 1.1117 + if (isAlreadyShutDown()) 1.1118 + return NS_ERROR_NOT_AVAILABLE; 1.1119 + 1.1120 + if (mCert) { 1.1121 + *aArray = (uint8_t*)nsMemory::Alloc(mCert->derCert.len); 1.1122 + if (*aArray) { 1.1123 + memcpy(*aArray, mCert->derCert.data, mCert->derCert.len); 1.1124 + *aLength = mCert->derCert.len; 1.1125 + return NS_OK; 1.1126 + } 1.1127 + } 1.1128 + *aLength = 0; 1.1129 + return NS_ERROR_FAILURE; 1.1130 +} 1.1131 + 1.1132 +NS_IMETHODIMP 1.1133 +nsNSSCertificate::ExportAsCMS(uint32_t chainMode, 1.1134 + uint32_t* aLength, uint8_t** aArray) 1.1135 +{ 1.1136 + NS_ENSURE_ARG(aLength); 1.1137 + NS_ENSURE_ARG(aArray); 1.1138 + 1.1139 + nsNSSShutDownPreventionLock locker; 1.1140 + if (isAlreadyShutDown()) 1.1141 + return NS_ERROR_NOT_AVAILABLE; 1.1142 + 1.1143 + if (!mCert) 1.1144 + return NS_ERROR_FAILURE; 1.1145 + 1.1146 + switch (chainMode) { 1.1147 + case nsIX509Cert3::CMS_CHAIN_MODE_CertOnly: 1.1148 + case nsIX509Cert3::CMS_CHAIN_MODE_CertChain: 1.1149 + case nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot: 1.1150 + break; 1.1151 + default: 1.1152 + return NS_ERROR_INVALID_ARG; 1.1153 + }; 1.1154 + 1.1155 + PLArenaPool* arena = PORT_NewArena(1024); 1.1156 + PLArenaPoolCleanerFalseParam arenaCleaner(arena); 1.1157 + if (!arena) { 1.1158 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, 1.1159 + ("nsNSSCertificate::ExportAsCMS - out of memory\n")); 1.1160 + return NS_ERROR_OUT_OF_MEMORY; 1.1161 + } 1.1162 + 1.1163 + ScopedNSSCMSMessage cmsg(NSS_CMSMessage_Create(nullptr)); 1.1164 + if (!cmsg) { 1.1165 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, 1.1166 + ("nsNSSCertificate::ExportAsCMS - can't create CMS message\n")); 1.1167 + return NS_ERROR_OUT_OF_MEMORY; 1.1168 + } 1.1169 + 1.1170 + // first, create SignedData with the certificate only (no chain) 1.1171 + ScopedNSSCMSSignedData sigd( 1.1172 + NSS_CMSSignedData_CreateCertsOnly(cmsg, mCert.get(), false)); 1.1173 + if (!sigd) { 1.1174 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, 1.1175 + ("nsNSSCertificate::ExportAsCMS - can't create SignedData\n")); 1.1176 + return NS_ERROR_FAILURE; 1.1177 + } 1.1178 + 1.1179 + // Calling NSS_CMSSignedData_CreateCertsOnly() will not allow us 1.1180 + // to specify the inclusion of the root, but CERT_CertChainFromCert() does. 1.1181 + // Since CERT_CertChainFromCert() also includes the certificate itself, 1.1182 + // we have to start at the issuing cert (to avoid duplicate certs 1.1183 + // in the SignedData). 1.1184 + if (chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChain || 1.1185 + chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot) { 1.1186 + ScopedCERTCertificate issuerCert( 1.1187 + CERT_FindCertIssuer(mCert.get(), PR_Now(), certUsageAnyCA)); 1.1188 + // the issuerCert of a self signed root is the cert itself, 1.1189 + // so make sure we're not adding duplicates, again 1.1190 + if (issuerCert && issuerCert != mCert.get()) { 1.1191 + bool includeRoot = 1.1192 + (chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot); 1.1193 + ScopedCERTCertificateList certChain( 1.1194 + CERT_CertChainFromCert(issuerCert, certUsageAnyCA, includeRoot)); 1.1195 + if (certChain) { 1.1196 + if (NSS_CMSSignedData_AddCertList(sigd, certChain) == SECSuccess) { 1.1197 + certChain.forget(); 1.1198 + } 1.1199 + else { 1.1200 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, 1.1201 + ("nsNSSCertificate::ExportAsCMS - can't add chain\n")); 1.1202 + return NS_ERROR_FAILURE; 1.1203 + } 1.1204 + } 1.1205 + else { 1.1206 + // try to add the issuerCert, at least 1.1207 + if (NSS_CMSSignedData_AddCertificate(sigd, issuerCert) 1.1208 + == SECSuccess) { 1.1209 + issuerCert.forget(); 1.1210 + } 1.1211 + else { 1.1212 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, 1.1213 + ("nsNSSCertificate::ExportAsCMS - can't add issuer cert\n")); 1.1214 + return NS_ERROR_FAILURE; 1.1215 + } 1.1216 + } 1.1217 + } 1.1218 + } 1.1219 + 1.1220 + NSSCMSContentInfo* cinfo = NSS_CMSMessage_GetContentInfo(cmsg); 1.1221 + if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd) 1.1222 + == SECSuccess) { 1.1223 + sigd.forget(); 1.1224 + } 1.1225 + else { 1.1226 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, 1.1227 + ("nsNSSCertificate::ExportAsCMS - can't attach SignedData\n")); 1.1228 + return NS_ERROR_FAILURE; 1.1229 + } 1.1230 + 1.1231 + SECItem certP7 = { siBuffer, nullptr, 0 }; 1.1232 + NSSCMSEncoderContext* ecx = NSS_CMSEncoder_Start(cmsg, nullptr, nullptr, 1.1233 + &certP7, arena, nullptr, 1.1234 + nullptr, nullptr, nullptr, 1.1235 + nullptr, nullptr); 1.1236 + if (!ecx) { 1.1237 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, 1.1238 + ("nsNSSCertificate::ExportAsCMS - can't create encoder context\n")); 1.1239 + return NS_ERROR_FAILURE; 1.1240 + } 1.1241 + 1.1242 + if (NSS_CMSEncoder_Finish(ecx) != SECSuccess) { 1.1243 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, 1.1244 + ("nsNSSCertificate::ExportAsCMS - failed to add encoded data\n")); 1.1245 + return NS_ERROR_FAILURE; 1.1246 + } 1.1247 + 1.1248 + *aArray = (uint8_t*)nsMemory::Alloc(certP7.len); 1.1249 + if (!*aArray) 1.1250 + return NS_ERROR_OUT_OF_MEMORY; 1.1251 + 1.1252 + memcpy(*aArray, certP7.data, certP7.len); 1.1253 + *aLength = certP7.len; 1.1254 + return NS_OK; 1.1255 +} 1.1256 + 1.1257 +CERTCertificate* 1.1258 +nsNSSCertificate::GetCert() 1.1259 +{ 1.1260 + nsNSSShutDownPreventionLock locker; 1.1261 + if (isAlreadyShutDown()) 1.1262 + return nullptr; 1.1263 + 1.1264 + return (mCert) ? CERT_DupCertificate(mCert.get()) : nullptr; 1.1265 +} 1.1266 + 1.1267 +NS_IMETHODIMP 1.1268 +nsNSSCertificate::GetValidity(nsIX509CertValidity** aValidity) 1.1269 +{ 1.1270 + nsNSSShutDownPreventionLock locker; 1.1271 + if (isAlreadyShutDown()) 1.1272 + return NS_ERROR_NOT_AVAILABLE; 1.1273 + 1.1274 + NS_ENSURE_ARG(aValidity); 1.1275 + nsX509CertValidity* validity = new nsX509CertValidity(mCert.get()); 1.1276 + 1.1277 + NS_ADDREF(validity); 1.1278 + *aValidity = static_cast<nsIX509CertValidity*>(validity); 1.1279 + return NS_OK; 1.1280 +} 1.1281 + 1.1282 +NS_IMETHODIMP 1.1283 +nsNSSCertificate::GetUsagesArray(bool localOnly, 1.1284 + uint32_t* _verified, 1.1285 + uint32_t* _count, 1.1286 + char16_t*** _usages) 1.1287 +{ 1.1288 + nsNSSShutDownPreventionLock locker; 1.1289 + if (isAlreadyShutDown()) 1.1290 + return NS_ERROR_NOT_AVAILABLE; 1.1291 + 1.1292 + nsresult rv; 1.1293 + const int max_usages = 13; 1.1294 + char16_t* tmpUsages[max_usages]; 1.1295 + const char* suffix = ""; 1.1296 + uint32_t tmpCount; 1.1297 + nsUsageArrayHelper uah(mCert.get()); 1.1298 + rv = uah.GetUsagesArray(suffix, localOnly, max_usages, _verified, &tmpCount, 1.1299 + tmpUsages); 1.1300 + NS_ENSURE_SUCCESS(rv,rv); 1.1301 + if (tmpCount > 0) { 1.1302 + *_usages = (char16_t**) nsMemory::Alloc(sizeof(char16_t*) * tmpCount); 1.1303 + if (!*_usages) 1.1304 + return NS_ERROR_OUT_OF_MEMORY; 1.1305 + for (uint32_t i=0; i<tmpCount; i++) { 1.1306 + (*_usages)[i] = tmpUsages[i]; 1.1307 + } 1.1308 + *_count = tmpCount; 1.1309 + return NS_OK; 1.1310 + } 1.1311 + *_usages = (char16_t**) nsMemory::Alloc(sizeof(char16_t*)); 1.1312 + if (!*_usages) 1.1313 + return NS_ERROR_OUT_OF_MEMORY; 1.1314 + *_count = 0; 1.1315 + return NS_OK; 1.1316 +} 1.1317 + 1.1318 +NS_IMETHODIMP 1.1319 +nsNSSCertificate::RequestUsagesArrayAsync( 1.1320 + nsICertVerificationListener* aResultListener) 1.1321 +{ 1.1322 + NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD); 1.1323 + 1.1324 + if (!aResultListener) 1.1325 + return NS_ERROR_FAILURE; 1.1326 + 1.1327 + nsCertVerificationJob* job = new nsCertVerificationJob; 1.1328 + 1.1329 + job->mCert = this; 1.1330 + job->mListener = 1.1331 + new nsMainThreadPtrHolder<nsICertVerificationListener>(aResultListener); 1.1332 + 1.1333 + nsresult rv = nsCertVerificationThread::addJob(job); 1.1334 + if (NS_FAILED(rv)) 1.1335 + delete job; 1.1336 + 1.1337 + return rv; 1.1338 +} 1.1339 + 1.1340 +NS_IMETHODIMP 1.1341 +nsNSSCertificate::GetUsagesString(bool localOnly, uint32_t* _verified, 1.1342 + nsAString& _usages) 1.1343 +{ 1.1344 + nsNSSShutDownPreventionLock locker; 1.1345 + if (isAlreadyShutDown()) 1.1346 + return NS_ERROR_NOT_AVAILABLE; 1.1347 + 1.1348 + nsresult rv; 1.1349 + const int max_usages = 13; 1.1350 + char16_t* tmpUsages[max_usages]; 1.1351 + const char* suffix = "_p"; 1.1352 + uint32_t tmpCount; 1.1353 + nsUsageArrayHelper uah(mCert.get()); 1.1354 + rv = uah.GetUsagesArray(suffix, localOnly, max_usages, _verified, &tmpCount, 1.1355 + tmpUsages); 1.1356 + NS_ENSURE_SUCCESS(rv,rv); 1.1357 + _usages.Truncate(); 1.1358 + for (uint32_t i=0; i<tmpCount; i++) { 1.1359 + if (i>0) _usages.AppendLiteral(","); 1.1360 + _usages.Append(tmpUsages[i]); 1.1361 + nsMemory::Free(tmpUsages[i]); 1.1362 + } 1.1363 + return NS_OK; 1.1364 +} 1.1365 + 1.1366 +#if defined(DEBUG_javi) || defined(DEBUG_jgmyers) 1.1367 +void 1.1368 +DumpASN1Object(nsIASN1Object* object, unsigned int level) 1.1369 +{ 1.1370 + nsAutoString dispNameU, dispValU; 1.1371 + unsigned int i; 1.1372 + nsCOMPtr<nsIMutableArray> asn1Objects; 1.1373 + nsCOMPtr<nsISupports> isupports; 1.1374 + nsCOMPtr<nsIASN1Object> currObject; 1.1375 + bool processObjects; 1.1376 + uint32_t numObjects; 1.1377 + 1.1378 + for (i=0; i<level; i++) 1.1379 + printf (" "); 1.1380 + 1.1381 + object->GetDisplayName(dispNameU); 1.1382 + nsCOMPtr<nsIASN1Sequence> sequence(do_QueryInterface(object)); 1.1383 + if (sequence) { 1.1384 + printf ("%s ", NS_ConvertUTF16toUTF8(dispNameU).get()); 1.1385 + sequence->GetIsValidContainer(&processObjects); 1.1386 + if (processObjects) { 1.1387 + printf("\n"); 1.1388 + sequence->GetASN1Objects(getter_AddRefs(asn1Objects)); 1.1389 + asn1Objects->GetLength(&numObjects); 1.1390 + for (i=0; i<numObjects;i++) { 1.1391 + asn1Objects->QueryElementAt(i, NS_GET_IID(nsISupports), 1.1392 + getter_AddRefs(currObject)); 1.1393 + DumpASN1Object(currObject, level+1); 1.1394 + } 1.1395 + } else { 1.1396 + object->GetDisplayValue(dispValU); 1.1397 + printf("= %s\n", NS_ConvertUTF16toUTF8(dispValU).get()); 1.1398 + } 1.1399 + } else { 1.1400 + object->GetDisplayValue(dispValU); 1.1401 + printf("%s = %s\n",NS_ConvertUTF16toUTF8(dispNameU).get(), 1.1402 + NS_ConvertUTF16toUTF8(dispValU).get()); 1.1403 + } 1.1404 +} 1.1405 +#endif 1.1406 + 1.1407 +NS_IMETHODIMP 1.1408 +nsNSSCertificate::GetASN1Structure(nsIASN1Object** aASN1Structure) 1.1409 +{ 1.1410 + nsNSSShutDownPreventionLock locker; 1.1411 + nsresult rv = NS_OK; 1.1412 + NS_ENSURE_ARG_POINTER(aASN1Structure); 1.1413 + // First create the recursive structure os ASN1Objects 1.1414 + // which tells us the layout of the cert. 1.1415 + rv = CreateASN1Struct(aASN1Structure); 1.1416 + if (NS_FAILED(rv)) { 1.1417 + return rv; 1.1418 + } 1.1419 +#ifdef DEBUG_javi 1.1420 + DumpASN1Object(*aASN1Structure, 0); 1.1421 +#endif 1.1422 + return rv; 1.1423 +} 1.1424 + 1.1425 +NS_IMETHODIMP 1.1426 +nsNSSCertificate::Equals(nsIX509Cert* other, bool* result) 1.1427 +{ 1.1428 + nsNSSShutDownPreventionLock locker; 1.1429 + if (isAlreadyShutDown()) 1.1430 + return NS_ERROR_NOT_AVAILABLE; 1.1431 + 1.1432 + NS_ENSURE_ARG(other); 1.1433 + NS_ENSURE_ARG(result); 1.1434 + 1.1435 + nsCOMPtr<nsIX509Cert2> other2 = do_QueryInterface(other); 1.1436 + if (!other2) 1.1437 + return NS_ERROR_FAILURE; 1.1438 + 1.1439 + ScopedCERTCertificate cert(other2->GetCert()); 1.1440 + *result = (mCert.get() == cert.get()); 1.1441 + return NS_OK; 1.1442 +} 1.1443 + 1.1444 +NS_IMETHODIMP 1.1445 +nsNSSCertificate::SaveSMimeProfile() 1.1446 +{ 1.1447 + nsNSSShutDownPreventionLock locker; 1.1448 + if (isAlreadyShutDown()) 1.1449 + return NS_ERROR_NOT_AVAILABLE; 1.1450 + 1.1451 + if (SECSuccess != CERT_SaveSMimeProfile(mCert.get(), nullptr, nullptr)) 1.1452 + return NS_ERROR_FAILURE; 1.1453 + else 1.1454 + return NS_OK; 1.1455 +} 1.1456 + 1.1457 +#ifndef MOZ_NO_EV_CERTS 1.1458 + 1.1459 +nsresult 1.1460 +nsNSSCertificate::hasValidEVOidTag(SECOidTag& resultOidTag, bool& validEV) 1.1461 +{ 1.1462 + nsNSSShutDownPreventionLock locker; 1.1463 + if (isAlreadyShutDown()) 1.1464 + return NS_ERROR_NOT_AVAILABLE; 1.1465 + 1.1466 + EnsureIdentityInfoLoaded(); 1.1467 + 1.1468 + RefPtr<mozilla::psm::SharedCertVerifier> 1.1469 + certVerifier(mozilla::psm::GetDefaultCertVerifier()); 1.1470 + NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED); 1.1471 + 1.1472 + validEV = false; 1.1473 + resultOidTag = SEC_OID_UNKNOWN; 1.1474 + 1.1475 + uint32_t flags = mozilla::psm::CertVerifier::FLAG_LOCAL_ONLY | 1.1476 + mozilla::psm::CertVerifier::FLAG_MUST_BE_EV; 1.1477 + SECStatus rv = certVerifier->VerifyCert(mCert.get(), 1.1478 + certificateUsageSSLServer, PR_Now(), 1.1479 + nullptr /* XXX pinarg */, 1.1480 + nullptr /* hostname */, 1.1481 + flags, nullptr /* stapledOCSPResponse */ , nullptr, &resultOidTag); 1.1482 + 1.1483 + if (rv != SECSuccess) { 1.1484 + resultOidTag = SEC_OID_UNKNOWN; 1.1485 + } 1.1486 + if (resultOidTag != SEC_OID_UNKNOWN) { 1.1487 + validEV = true; 1.1488 + } 1.1489 + return NS_OK; 1.1490 +} 1.1491 + 1.1492 +nsresult 1.1493 +nsNSSCertificate::getValidEVOidTag(SECOidTag& resultOidTag, bool& validEV) 1.1494 +{ 1.1495 + if (mCachedEVStatus != ev_status_unknown) { 1.1496 + validEV = (mCachedEVStatus == ev_status_valid); 1.1497 + if (validEV) { 1.1498 + resultOidTag = mCachedEVOidTag; 1.1499 + } 1.1500 + return NS_OK; 1.1501 + } 1.1502 + 1.1503 + nsresult rv = hasValidEVOidTag(resultOidTag, validEV); 1.1504 + if (NS_SUCCEEDED(rv)) { 1.1505 + if (validEV) { 1.1506 + mCachedEVOidTag = resultOidTag; 1.1507 + } 1.1508 + mCachedEVStatus = validEV ? ev_status_valid : ev_status_invalid; 1.1509 + } 1.1510 + return rv; 1.1511 +} 1.1512 + 1.1513 +#endif // MOZ_NO_EV_CERTS 1.1514 + 1.1515 +NS_IMETHODIMP 1.1516 +nsNSSCertificate::GetIsExtendedValidation(bool* aIsEV) 1.1517 +{ 1.1518 +#ifdef MOZ_NO_EV_CERTS 1.1519 + *aIsEV = false; 1.1520 + return NS_OK; 1.1521 +#else 1.1522 + nsNSSShutDownPreventionLock locker; 1.1523 + if (isAlreadyShutDown()) { 1.1524 + return NS_ERROR_NOT_AVAILABLE; 1.1525 + } 1.1526 + 1.1527 + NS_ENSURE_ARG(aIsEV); 1.1528 + *aIsEV = false; 1.1529 + 1.1530 + if (mCachedEVStatus != ev_status_unknown) { 1.1531 + *aIsEV = (mCachedEVStatus == ev_status_valid); 1.1532 + return NS_OK; 1.1533 + } 1.1534 + 1.1535 + SECOidTag oid_tag; 1.1536 + return getValidEVOidTag(oid_tag, *aIsEV); 1.1537 +#endif 1.1538 +} 1.1539 + 1.1540 +NS_IMETHODIMP 1.1541 +nsNSSCertificate::GetValidEVPolicyOid(nsACString& outDottedOid) 1.1542 +{ 1.1543 + outDottedOid.Truncate(); 1.1544 + 1.1545 +#ifndef MOZ_NO_EV_CERTS 1.1546 + nsNSSShutDownPreventionLock locker; 1.1547 + if (isAlreadyShutDown()) { 1.1548 + return NS_ERROR_NOT_AVAILABLE; 1.1549 + } 1.1550 + 1.1551 + SECOidTag oid_tag; 1.1552 + bool valid; 1.1553 + nsresult rv = getValidEVOidTag(oid_tag, valid); 1.1554 + if (NS_FAILED(rv)) { 1.1555 + return rv; 1.1556 + } 1.1557 + 1.1558 + if (valid) { 1.1559 + SECOidData* oid_data = SECOID_FindOIDByTag(oid_tag); 1.1560 + if (!oid_data) { 1.1561 + return NS_ERROR_FAILURE; 1.1562 + } 1.1563 + 1.1564 + char* oid_str = CERT_GetOidString(&oid_data->oid); 1.1565 + if (!oid_str) { 1.1566 + return NS_ERROR_FAILURE; 1.1567 + } 1.1568 + 1.1569 + outDottedOid.Assign(oid_str); 1.1570 + PR_smprintf_free(oid_str); 1.1571 + } 1.1572 +#endif 1.1573 + 1.1574 + return NS_OK; 1.1575 +} 1.1576 + 1.1577 +NS_IMPL_ISUPPORTS(nsNSSCertList, nsIX509CertList) 1.1578 + 1.1579 +nsNSSCertList::nsNSSCertList(mozilla::pkix::ScopedCERTCertList& certList, 1.1580 + const nsNSSShutDownPreventionLock& proofOfLock) 1.1581 +{ 1.1582 + if (certList) { 1.1583 + mCertList = certList.release(); 1.1584 + } else { 1.1585 + mCertList = CERT_NewCertList(); 1.1586 + } 1.1587 +} 1.1588 + 1.1589 +nsNSSCertList::nsNSSCertList() 1.1590 +{ 1.1591 + mCertList = CERT_NewCertList(); 1.1592 +} 1.1593 + 1.1594 +nsNSSCertList::~nsNSSCertList() 1.1595 +{ 1.1596 + nsNSSShutDownPreventionLock locker; 1.1597 + if (isAlreadyShutDown()) { 1.1598 + return; 1.1599 + } 1.1600 + destructorSafeDestroyNSSReference(); 1.1601 + shutdown(calledFromObject); 1.1602 +} 1.1603 + 1.1604 +void nsNSSCertList::virtualDestroyNSSReference() 1.1605 +{ 1.1606 + destructorSafeDestroyNSSReference(); 1.1607 +} 1.1608 + 1.1609 +void nsNSSCertList::destructorSafeDestroyNSSReference() 1.1610 +{ 1.1611 + if (mCertList) { 1.1612 + mCertList = nullptr; 1.1613 + } 1.1614 +} 1.1615 + 1.1616 +NS_IMETHODIMP 1.1617 +nsNSSCertList::AddCert(nsIX509Cert* aCert) 1.1618 +{ 1.1619 + nsNSSShutDownPreventionLock locker; 1.1620 + if (isAlreadyShutDown()) { 1.1621 + return NS_ERROR_NOT_AVAILABLE; 1.1622 + } 1.1623 + nsCOMPtr<nsIX509Cert2> nssCert = do_QueryInterface(aCert); 1.1624 + CERTCertificate* cert; 1.1625 + 1.1626 + cert = nssCert->GetCert(); 1.1627 + if (!cert) { 1.1628 + NS_ERROR("Somehow got nullptr for mCertificate in nsNSSCertificate."); 1.1629 + return NS_ERROR_FAILURE; 1.1630 + } 1.1631 + 1.1632 + if (!mCertList) { 1.1633 + NS_ERROR("Somehow got nullptr for mCertList in nsNSSCertList."); 1.1634 + return NS_ERROR_FAILURE; 1.1635 + } 1.1636 + // XXX: check return value! 1.1637 + CERT_AddCertToListTail(mCertList.get(), cert); 1.1638 + return NS_OK; 1.1639 +} 1.1640 + 1.1641 +NS_IMETHODIMP 1.1642 +nsNSSCertList::DeleteCert(nsIX509Cert* aCert) 1.1643 +{ 1.1644 + nsNSSShutDownPreventionLock locker; 1.1645 + if (isAlreadyShutDown()) { 1.1646 + return NS_ERROR_NOT_AVAILABLE; 1.1647 + } 1.1648 + nsCOMPtr<nsIX509Cert2> nssCert = do_QueryInterface(aCert); 1.1649 + CERTCertificate* cert = nssCert->GetCert(); 1.1650 + CERTCertListNode* node; 1.1651 + 1.1652 + if (!cert) { 1.1653 + NS_ERROR("Somehow got nullptr for mCertificate in nsNSSCertificate."); 1.1654 + return NS_ERROR_FAILURE; 1.1655 + } 1.1656 + 1.1657 + if (!mCertList) { 1.1658 + NS_ERROR("Somehow got nullptr for mCertList in nsNSSCertList."); 1.1659 + return NS_ERROR_FAILURE; 1.1660 + } 1.1661 + 1.1662 + for (node = CERT_LIST_HEAD(mCertList.get()); 1.1663 + !CERT_LIST_END(node, mCertList.get()); node = CERT_LIST_NEXT(node)) { 1.1664 + if (node->cert == cert) { 1.1665 + CERT_RemoveCertListNode(node); 1.1666 + return NS_OK; 1.1667 + } 1.1668 + } 1.1669 + return NS_OK; // XXX Should we fail if we couldn't find it? 1.1670 +} 1.1671 + 1.1672 +CERTCertList* 1.1673 +nsNSSCertList::DupCertList(CERTCertList* aCertList, 1.1674 + const nsNSSShutDownPreventionLock& /*proofOfLock*/) 1.1675 +{ 1.1676 + if (!aCertList) 1.1677 + return nullptr; 1.1678 + 1.1679 + CERTCertList* newList = CERT_NewCertList(); 1.1680 + 1.1681 + if (!newList) { 1.1682 + return nullptr; 1.1683 + } 1.1684 + 1.1685 + CERTCertListNode* node; 1.1686 + for (node = CERT_LIST_HEAD(aCertList); !CERT_LIST_END(node, aCertList); 1.1687 + node = CERT_LIST_NEXT(node)) { 1.1688 + CERTCertificate* cert = CERT_DupCertificate(node->cert); 1.1689 + CERT_AddCertToListTail(newList, cert); 1.1690 + } 1.1691 + return newList; 1.1692 +} 1.1693 + 1.1694 +void* 1.1695 +nsNSSCertList::GetRawCertList() 1.1696 +{ 1.1697 + // This function should only be called after adquiring a 1.1698 + // nsNSSShutDownPreventionLock 1.1699 + return mCertList.get(); 1.1700 +} 1.1701 + 1.1702 +NS_IMETHODIMP 1.1703 +nsNSSCertList::GetEnumerator(nsISimpleEnumerator** _retval) 1.1704 +{ 1.1705 + nsNSSShutDownPreventionLock locker; 1.1706 + if (isAlreadyShutDown()) { 1.1707 + return NS_ERROR_NOT_AVAILABLE; 1.1708 + } 1.1709 + nsCOMPtr<nsISimpleEnumerator> enumerator = 1.1710 + new nsNSSCertListEnumerator(mCertList.get(), locker); 1.1711 + 1.1712 + *_retval = enumerator; 1.1713 + NS_ADDREF(*_retval); 1.1714 + return NS_OK; 1.1715 +} 1.1716 + 1.1717 +NS_IMPL_ISUPPORTS(nsNSSCertListEnumerator, nsISimpleEnumerator) 1.1718 + 1.1719 +nsNSSCertListEnumerator::nsNSSCertListEnumerator( 1.1720 + CERTCertList* certList, const nsNSSShutDownPreventionLock& proofOfLock) 1.1721 +{ 1.1722 + mCertList = nsNSSCertList::DupCertList(certList, proofOfLock); 1.1723 +} 1.1724 + 1.1725 +nsNSSCertListEnumerator::~nsNSSCertListEnumerator() 1.1726 +{ 1.1727 + nsNSSShutDownPreventionLock locker; 1.1728 + if (isAlreadyShutDown()) { 1.1729 + return; 1.1730 + } 1.1731 + destructorSafeDestroyNSSReference(); 1.1732 + shutdown(calledFromObject); 1.1733 +} 1.1734 + 1.1735 +void nsNSSCertListEnumerator::virtualDestroyNSSReference() 1.1736 +{ 1.1737 + destructorSafeDestroyNSSReference(); 1.1738 +} 1.1739 + 1.1740 +void nsNSSCertListEnumerator::destructorSafeDestroyNSSReference() 1.1741 +{ 1.1742 + if (mCertList) { 1.1743 + mCertList = nullptr; 1.1744 + } 1.1745 +} 1.1746 + 1.1747 +NS_IMETHODIMP 1.1748 +nsNSSCertListEnumerator::HasMoreElements(bool* _retval) 1.1749 +{ 1.1750 + nsNSSShutDownPreventionLock locker; 1.1751 + if (isAlreadyShutDown()) { 1.1752 + return NS_ERROR_NOT_AVAILABLE; 1.1753 + } 1.1754 + 1.1755 + NS_ENSURE_TRUE(mCertList, NS_ERROR_FAILURE); 1.1756 + 1.1757 + *_retval = !CERT_LIST_EMPTY(mCertList); 1.1758 + return NS_OK; 1.1759 +} 1.1760 + 1.1761 +NS_IMETHODIMP 1.1762 +nsNSSCertListEnumerator::GetNext(nsISupports** _retval) 1.1763 +{ 1.1764 + nsNSSShutDownPreventionLock locker; 1.1765 + if (isAlreadyShutDown()) { 1.1766 + return NS_ERROR_NOT_AVAILABLE; 1.1767 + } 1.1768 + 1.1769 + NS_ENSURE_TRUE(mCertList, NS_ERROR_FAILURE); 1.1770 + 1.1771 + CERTCertListNode* node = CERT_LIST_HEAD(mCertList); 1.1772 + if (CERT_LIST_END(node, mCertList)) { 1.1773 + return NS_ERROR_FAILURE; 1.1774 + } 1.1775 + 1.1776 + nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(node->cert); 1.1777 + if (!nssCert) { 1.1778 + return NS_ERROR_OUT_OF_MEMORY; 1.1779 + } 1.1780 + 1.1781 + *_retval = nssCert; 1.1782 + NS_ADDREF(*_retval); 1.1783 + 1.1784 + CERT_RemoveCertListNode(node); 1.1785 + return NS_OK; 1.1786 +} 1.1787 + 1.1788 +// NB: This serialization must match that of nsNSSCertificateFakeTransport. 1.1789 +NS_IMETHODIMP 1.1790 +nsNSSCertificate::Write(nsIObjectOutputStream* aStream) 1.1791 +{ 1.1792 + NS_ENSURE_STATE(mCert); 1.1793 + nsresult rv = aStream->Write32(static_cast<uint32_t>(mCachedEVStatus)); 1.1794 + if (NS_FAILED(rv)) { 1.1795 + return rv; 1.1796 + } 1.1797 + rv = aStream->Write32(mCert->derCert.len); 1.1798 + if (NS_FAILED(rv)) { 1.1799 + return rv; 1.1800 + } 1.1801 + return aStream->WriteByteArray(mCert->derCert.data, mCert->derCert.len); 1.1802 +} 1.1803 + 1.1804 +NS_IMETHODIMP 1.1805 +nsNSSCertificate::Read(nsIObjectInputStream* aStream) 1.1806 +{ 1.1807 + NS_ENSURE_STATE(!mCert); 1.1808 + 1.1809 + uint32_t cachedEVStatus; 1.1810 + nsresult rv = aStream->Read32(&cachedEVStatus); 1.1811 + if (NS_FAILED(rv)) { 1.1812 + return rv; 1.1813 + } 1.1814 + if (cachedEVStatus == static_cast<uint32_t>(ev_status_unknown)) { 1.1815 + mCachedEVStatus = ev_status_unknown; 1.1816 + } else if (cachedEVStatus == static_cast<uint32_t>(ev_status_valid)) { 1.1817 + mCachedEVStatus = ev_status_valid; 1.1818 + } else if (cachedEVStatus == static_cast<uint32_t>(ev_status_invalid)) { 1.1819 + mCachedEVStatus = ev_status_invalid; 1.1820 + } else { 1.1821 + return NS_ERROR_UNEXPECTED; 1.1822 + } 1.1823 + 1.1824 + uint32_t len; 1.1825 + rv = aStream->Read32(&len); 1.1826 + if (NS_FAILED(rv)) { 1.1827 + return rv; 1.1828 + } 1.1829 + 1.1830 + nsXPIDLCString str; 1.1831 + rv = aStream->ReadBytes(len, getter_Copies(str)); 1.1832 + if (NS_FAILED(rv)) { 1.1833 + return rv; 1.1834 + } 1.1835 + 1.1836 + if (!InitFromDER(const_cast<char*>(str.get()), len)) { 1.1837 + return NS_ERROR_UNEXPECTED; 1.1838 + } 1.1839 + 1.1840 + return NS_OK; 1.1841 +} 1.1842 + 1.1843 +NS_IMETHODIMP 1.1844 +nsNSSCertificate::GetInterfaces(uint32_t* count, nsIID*** array) 1.1845 +{ 1.1846 + *count = 0; 1.1847 + *array = nullptr; 1.1848 + return NS_OK; 1.1849 +} 1.1850 + 1.1851 +NS_IMETHODIMP 1.1852 +nsNSSCertificate::GetHelperForLanguage(uint32_t language, 1.1853 + nsISupports** _retval) 1.1854 +{ 1.1855 + *_retval = nullptr; 1.1856 + return NS_OK; 1.1857 +} 1.1858 + 1.1859 +NS_IMETHODIMP 1.1860 +nsNSSCertificate::GetContractID(char** aContractID) 1.1861 +{ 1.1862 + *aContractID = nullptr; 1.1863 + return NS_OK; 1.1864 +} 1.1865 + 1.1866 +NS_IMETHODIMP 1.1867 +nsNSSCertificate::GetClassDescription(char** aClassDescription) 1.1868 +{ 1.1869 + *aClassDescription = nullptr; 1.1870 + return NS_OK; 1.1871 +} 1.1872 + 1.1873 +NS_IMETHODIMP 1.1874 +nsNSSCertificate::GetClassID(nsCID** aClassID) 1.1875 +{ 1.1876 + *aClassID = (nsCID*) nsMemory::Alloc(sizeof(nsCID)); 1.1877 + if (!*aClassID) 1.1878 + return NS_ERROR_OUT_OF_MEMORY; 1.1879 + return GetClassIDNoAlloc(*aClassID); 1.1880 +} 1.1881 + 1.1882 +NS_IMETHODIMP 1.1883 +nsNSSCertificate::GetImplementationLanguage(uint32_t* aImplementationLanguage) 1.1884 +{ 1.1885 + *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS; 1.1886 + return NS_OK; 1.1887 +} 1.1888 + 1.1889 +NS_IMETHODIMP 1.1890 +nsNSSCertificate::GetFlags(uint32_t* aFlags) 1.1891 +{ 1.1892 + *aFlags = nsIClassInfo::THREADSAFE; 1.1893 + return NS_OK; 1.1894 +} 1.1895 + 1.1896 +NS_IMETHODIMP 1.1897 +nsNSSCertificate::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) 1.1898 +{ 1.1899 + static NS_DEFINE_CID(kNSSCertificateCID, NS_X509CERT_CID); 1.1900 + 1.1901 + *aClassIDNoAlloc = kNSSCertificateCID; 1.1902 + return NS_OK; 1.1903 +}