Files
palemoon27/security/manager/ssl/nsCertPicker.cpp
T
roytam1 81d61fa324 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1265036 - Use NS_ABORT_OOM() if try_realloc() fails. r=billm (c30f4f83d5)
- Bug 1263292 - Handle calling realloc(0) (r=jld) (f292859ee9)
- Bug 1256366 - Remove linear and exponential stats collection from histogram.cc. r=gfritzsche (f9a1c869a1)
- Bug 1263953 - Reduce the growth rate of Pickle. r=wmccloskey (6eb5228490)
- Bug 1233275 - Copy environment for IPC using NSPR. r=jld (2004db748e)
- Bug 1261094 - Improve how MessageChannel::mInterruptStack is used in IPC code, r=jld (56e2c114a4)
- Bug 1246931: Include dbus.h in DBus IPC headers, r=shuang (43e797c2d8)
- Bug 1264887: Make DBus helpers available on desktop builds, r=shuang (58bff1f640)
- Bug 1268130, part 1 - Reimplement ByteLengthIsValid using CheckedInt. r=froydnj (6018e22ae0)
- Bug 1268130, part 2 - Make ByteLengthIsValid failures fatal in release builds. r=froydnj (f9d934a498)
- Bug 1269365, part 1 - Swap fallible and infallible TArray ParamTraits. r=froydnj (ad423bc04d)
- Bug 1269365, part 2 - Make ParamTraits<nsTArray<E>>::Read use infallible allocation. r=froydnj (9b902a5bc4)
- Bug 1269365, part 3 - Use infallible array allocation in implementSpecialArrayPickling. r=froydnj (592fe648d3)
- Bug 1264820 - Measure IPC reply size in telemetry (r=mccr8) (62c54d3141)
- Bug 1268938 - Use the name of the original message in Send for reply telemetry. r=billm (a2de5c6a91)
- Bug 1266954: Remove temporary |ScopedClose| from PDU receive code, r=jacheng (cb06315c33)
- Bug 1142109 - Fix IPDL tests (r=dvander) (df3f0cda32)
- Bug 1177013 - Fix IPDL tests for not allowing CPOWs during sync (r=dvander) (5da0a8a4c9)
- Bug 1261307: Convert RIL sockets to |UniquePtr|, r=nfroyd (08609783b3)
- Bug 1253622 - Move the mozilla-trace.h generation into moz.build; r=ted (f01dc418bc)
- Bug 1267318 ignore cert expiration for mozilla-signed packages, r=dkeeler (7a1ddd6090)
- Bug 1029173 - Clean up nsDataSignatureVerifier. r=keeler (f9602341ea)
- bug 1267463 - add a more nuanced subject common name fallback option for prerelease channels r=Cykesiopka,jcj (9b55320c9b)
- Bug 1253108 - Enable ESLint "strict" rule for PSM. r=keeler (54802bdc38)
- Bug 1255425 - part 1 - clearly delineate steps when outputting HSTS preload list; r=keeler (79f73189c8)
- Bug 1251801 - Fully implement nsNSSShutDownObject and obviate manual NSS resource management. r=keeler (af32315d3f)
- Bug 1251801 - Improve handling of PK11_* function error codes. r=keeler (9f2c8ac64b)
- Fix unified-build bustage from bug 1264706. r=bustage (11bc0417c7)
- Bug 1265164 - Always use nsCOMPtrs with getNSSDialogs(). r=keeler (ce5a703972)
2024-09-03 10:19:02 +08:00

213 lines
6.4 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsCertPicker.h"
#include "ScopedNSSTypes.h"
#include "cert.h"
#include "mozilla/RefPtr.h"
#include "nsCOMPtr.h"
#include "nsICertPickDialogs.h"
#include "nsIInterfaceRequestor.h"
#include "nsIServiceManager.h"
#include "nsMemory.h"
#include "nsNSSCertHelper.h"
#include "nsNSSCertificate.h"
#include "nsNSSComponent.h"
#include "nsNSSHelper.h"
#include "nsNSSShutDown.h"
#include "nsReadableUtils.h"
#include "nsString.h"
#include "pkix/pkixtypes.h"
using namespace mozilla;
NS_IMPL_ISUPPORTS(nsCertPicker, nsIUserCertPicker)
nsCertPicker::nsCertPicker()
{
}
nsCertPicker::~nsCertPicker()
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return;
}
shutdown(calledFromObject);
}
NS_IMETHODIMP nsCertPicker::PickByUsage(nsIInterfaceRequestor *ctx,
const char16_t *selectedNickname,
int32_t certUsage,
bool allowInvalid,
bool allowDuplicateNicknames,
const nsAString &emailAddress,
bool *canceled,
nsIX509Cert **_retval)
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return NS_ERROR_NOT_AVAILABLE;
}
int32_t selectedIndex = -1;
bool selectionFound = false;
char16_t **certNicknameList = nullptr;
char16_t **certDetailsList = nullptr;
CERTCertListNode* node = nullptr;
nsresult rv = NS_OK;
{
// Iterate over all certs. This assures that user is logged in to all hardware tokens.
nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
ScopedCERTCertList allcerts(PK11_ListCerts(PK11CertListUnique, ctx));
}
/* find all user certs that are valid for the specified usage */
/* note that we are allowing expired certs in this list */
ScopedCERTCertList certList(
CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(),
(SECCertUsage)certUsage,
!allowDuplicateNicknames,
!allowInvalid,
ctx));
if (!certList) {
return NS_ERROR_NOT_AVAILABLE;
}
/* if a (non-empty) emailAddress argument is supplied to PickByUsage, */
/* remove non-matching certificates from the candidate list */
if (!emailAddress.IsEmpty()) {
node = CERT_LIST_HEAD(certList);
while (!CERT_LIST_END(node, certList)) {
/* if the cert has at least one e-mail address, check if suitable */
if (CERT_GetFirstEmailAddress(node->cert)) {
RefPtr<nsNSSCertificate> tempCert(nsNSSCertificate::Create(node->cert));
bool match = false;
rv = tempCert->ContainsEmailAddress(emailAddress, &match);
if (NS_FAILED(rv)) {
return rv;
}
if (!match) {
/* doesn't contain the specified address, so remove from the list */
CERTCertListNode* freenode = node;
node = CERT_LIST_NEXT(node);
CERT_RemoveCertListNode(freenode);
continue;
}
}
node = CERT_LIST_NEXT(node);
}
}
UniqueCERTCertNicknames nicknames(
getNSSCertNicknamesFromCertList(certList.get()));
if (!nicknames) {
return NS_ERROR_NOT_AVAILABLE;
}
certNicknameList = (char16_t **)moz_xmalloc(sizeof(char16_t *) * nicknames->numnicknames);
certDetailsList = (char16_t **)moz_xmalloc(sizeof(char16_t *) * nicknames->numnicknames);
if (!certNicknameList || !certDetailsList) {
free(certNicknameList);
free(certDetailsList);
return NS_ERROR_OUT_OF_MEMORY;
}
int32_t CertsToUse;
for (CertsToUse = 0, node = CERT_LIST_HEAD(certList.get());
!CERT_LIST_END(node, certList.get()) &&
CertsToUse < nicknames->numnicknames;
node = CERT_LIST_NEXT(node)
)
{
RefPtr<nsNSSCertificate> tempCert(nsNSSCertificate::Create(node->cert));
if (tempCert) {
nsAutoString i_nickname(NS_ConvertUTF8toUTF16(nicknames->nicknames[CertsToUse]));
nsAutoString nickWithSerial;
nsAutoString details;
if (!selectionFound) {
/* for the case when selectedNickname refers to a bare nickname */
if (i_nickname == nsDependentString(selectedNickname)) {
selectedIndex = CertsToUse;
selectionFound = true;
}
}
if (NS_SUCCEEDED(tempCert->FormatUIStrings(i_nickname, nickWithSerial, details))) {
certNicknameList[CertsToUse] = ToNewUnicode(nickWithSerial);
certDetailsList[CertsToUse] = ToNewUnicode(details);
if (!selectionFound) {
/* for the case when selectedNickname refers to nickname + serial */
if (nickWithSerial == nsDependentString(selectedNickname)) {
selectedIndex = CertsToUse;
selectionFound = true;
}
}
}
else {
certNicknameList[CertsToUse] = nullptr;
certDetailsList[CertsToUse] = nullptr;
}
++CertsToUse;
}
}
if (CertsToUse) {
nsCOMPtr<nsICertPickDialogs> dialogs;
rv = getNSSDialogs(getter_AddRefs(dialogs), NS_GET_IID(nsICertPickDialogs),
NS_CERTPICKDIALOGS_CONTRACTID);
if (NS_SUCCEEDED(rv)) {
// Show the cert picker dialog and get the index of the selected cert.
rv = dialogs->PickCertificate(ctx, (const char16_t**)certNicknameList,
(const char16_t**)certDetailsList,
CertsToUse, &selectedIndex, canceled);
}
}
int32_t i;
for (i = 0; i < CertsToUse; ++i) {
free(certNicknameList[i]);
free(certDetailsList[i]);
}
free(certNicknameList);
free(certDetailsList);
if (!CertsToUse) {
return NS_ERROR_NOT_AVAILABLE;
}
if (NS_SUCCEEDED(rv) && !*canceled) {
for (i = 0, node = CERT_LIST_HEAD(certList);
!CERT_LIST_END(node, certList);
++i, node = CERT_LIST_NEXT(node)) {
if (i == selectedIndex) {
RefPtr<nsNSSCertificate> cert = nsNSSCertificate::Create(node->cert);
if (!cert) {
rv = NS_ERROR_OUT_OF_MEMORY;
break;
}
cert.forget(_retval);
break;
}
}
}
return rv;
}