diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /security/manager/ssl/NSSErrorsService.cpp | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/manager/ssl/NSSErrorsService.cpp')
-rw-r--r-- | security/manager/ssl/NSSErrorsService.cpp | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/security/manager/ssl/NSSErrorsService.cpp b/security/manager/ssl/NSSErrorsService.cpp new file mode 100644 index 0000000000..06c0b1e790 --- /dev/null +++ b/security/manager/ssl/NSSErrorsService.cpp @@ -0,0 +1,212 @@ +/* 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 "NSSErrorsService.h" + +#include "nsIStringBundle.h" +#include "nsNSSComponent.h" +#include "nsServiceManagerUtils.h" +#include "mozpkix/pkixnss.h" +#include "secerr.h" +#include "sslerr.h" + +#define PIPNSS_STRBUNDLE_URL "chrome://pipnss/locale/pipnss.properties" +#define NSSERR_STRBUNDLE_URL "chrome://pipnss/locale/nsserrors.properties" + +namespace mozilla { +namespace psm { + +static_assert(mozilla::pkix::ERROR_BASE == + nsINSSErrorsService::MOZILLA_PKIX_ERROR_BASE, + "MOZILLA_PKIX_ERROR_BASE and " + "nsINSSErrorsService::MOZILLA_PKIX_ERROR_BASE do not match."); +static_assert(mozilla::pkix::ERROR_LIMIT == + nsINSSErrorsService::MOZILLA_PKIX_ERROR_LIMIT, + "MOZILLA_PKIX_ERROR_LIMIT and " + "nsINSSErrorsService::MOZILLA_PKIX_ERROR_LIMIT do not match."); + +static bool IsPSMError(PRErrorCode error) { + return (error >= mozilla::pkix::ERROR_BASE && + error < mozilla::pkix::ERROR_LIMIT); +} + +NS_IMPL_ISUPPORTS(NSSErrorsService, nsINSSErrorsService) + +NSSErrorsService::~NSSErrorsService() = default; + +nsresult NSSErrorsService::Init() { + nsresult rv; + nsCOMPtr<nsIStringBundleService> bundleService( + do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv)); + if (NS_FAILED(rv) || !bundleService) return NS_ERROR_FAILURE; + + bundleService->CreateBundle(PIPNSS_STRBUNDLE_URL, + getter_AddRefs(mPIPNSSBundle)); + if (!mPIPNSSBundle) rv = NS_ERROR_FAILURE; + + bundleService->CreateBundle(NSSERR_STRBUNDLE_URL, + getter_AddRefs(mNSSErrorsBundle)); + if (!mNSSErrorsBundle) rv = NS_ERROR_FAILURE; + + return rv; +} + +#define EXPECTED_SEC_ERROR_BASE (-0x2000) +#define EXPECTED_SSL_ERROR_BASE (-0x3000) + +#if SEC_ERROR_BASE != EXPECTED_SEC_ERROR_BASE || \ + SSL_ERROR_BASE != EXPECTED_SSL_ERROR_BASE +# error \ + "Unexpected change of error code numbers in lib NSS, please adjust the mapping code" +/* + * Please ensure the NSS error codes are mapped into the positive range 0x1000 + * to 0xf000 Search for NS_ERROR_MODULE_SECURITY to ensure there are no + * conflicts. The current code also assumes that NSS library error codes are + * negative. + */ +#endif + +bool IsNSSErrorCode(PRErrorCode code) { + return IS_SEC_ERROR(code) || IS_SSL_ERROR(code) || IsPSMError(code); +} + +nsresult GetXPCOMFromNSSError(PRErrorCode code) { + if (!code) { + MOZ_CRASH("Function failed without calling PR_GetError"); + } + + // The error codes within each module must be a 16 bit value. + // For simplicity we use the positive value of the NSS code. + return (nsresult)NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, + -1 * code); +} + +NS_IMETHODIMP +NSSErrorsService::IsNSSErrorCode(int32_t aNSPRCode, bool* _retval) { + if (!_retval) { + return NS_ERROR_INVALID_ARG; + } + + *_retval = mozilla::psm::IsNSSErrorCode(aNSPRCode); + return NS_OK; +} + +NS_IMETHODIMP +NSSErrorsService::GetXPCOMFromNSSError(int32_t aNSPRCode, + nsresult* aXPCOMErrorCode) { + if (!aXPCOMErrorCode) { + return NS_ERROR_INVALID_ARG; + } + + if (!mozilla::psm::IsNSSErrorCode(aNSPRCode)) { + return NS_ERROR_INVALID_ARG; + } + + *aXPCOMErrorCode = mozilla::psm::GetXPCOMFromNSSError(aNSPRCode); + + return NS_OK; +} + +NS_IMETHODIMP +NSSErrorsService::GetErrorClass(nsresult aXPCOMErrorCode, + uint32_t* aErrorClass) { + NS_ENSURE_ARG(aErrorClass); + + if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY || + NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) { + return NS_ERROR_FAILURE; + } + + int32_t aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); + + if (!mozilla::psm::IsNSSErrorCode(aNSPRCode)) { + return NS_ERROR_FAILURE; + } + + if (mozilla::psm::ErrorIsOverridable(aNSPRCode)) { + *aErrorClass = ERROR_CLASS_BAD_CERT; + } else { + *aErrorClass = ERROR_CLASS_SSL_PROTOCOL; + } + + return NS_OK; +} + +bool ErrorIsOverridable(PRErrorCode code) { + switch (code) { + // Overridable errors. + case mozilla::pkix::MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED: + case mozilla::pkix::MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY: + case mozilla::pkix::MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME: + case mozilla::pkix::MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE: + case mozilla::pkix::MOZILLA_PKIX_ERROR_MITM_DETECTED: + case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE: + case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE: + case mozilla::pkix::MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT: + case mozilla::pkix::MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA: + case SEC_ERROR_CA_CERT_INVALID: + case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED: + case SEC_ERROR_EXPIRED_CERTIFICATE: + case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: + case SEC_ERROR_INVALID_TIME: + case SEC_ERROR_UNKNOWN_ISSUER: + case SSL_ERROR_BAD_CERT_DOMAIN: + return true; + // Non-overridable errors. + default: + return false; + } +} + +static const char* getOverrideErrorStringName(PRErrorCode aErrorCode) { + switch (aErrorCode) { + case SSL_ERROR_SSL_DISABLED: + return "PSMERR_SSL_Disabled"; + case SSL_ERROR_SSL2_DISABLED: + return "PSMERR_SSL2_Disabled"; + case SEC_ERROR_REUSED_ISSUER_AND_SERIAL: + return "PSMERR_HostReusedIssuerSerial"; + case mozilla::pkix::MOZILLA_PKIX_ERROR_MITM_DETECTED: + return "certErrorTrust_MitM"; + default: + return nullptr; + } +} + +NS_IMETHODIMP +NSSErrorsService::GetErrorMessage(nsresult aXPCOMErrorCode, + nsAString& aErrorMessage) { + if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY || + NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) { + return NS_ERROR_FAILURE; + } + + int32_t aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); + + if (!mozilla::psm::IsNSSErrorCode(aNSPRCode)) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr<nsIStringBundle> theBundle = mPIPNSSBundle; + const char* idStr = getOverrideErrorStringName(aNSPRCode); + + if (!idStr) { + idStr = PR_ErrorToName(aNSPRCode); + theBundle = mNSSErrorsBundle; + } + + if (!idStr || !theBundle) { + return NS_ERROR_FAILURE; + } + + nsAutoString msg; + nsresult rv = theBundle->GetStringFromName(idStr, msg); + if (NS_SUCCEEDED(rv)) { + aErrorMessage = msg; + } + return rv; +} + +} // namespace psm +} // namespace mozilla |