Line data Source code
1 : /* This Source Code Form is subject to the terms of the Mozilla Public
2 : * License, v. 2.0. If a copy of the MPL was not distributed with this
3 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 :
5 : #include "NSSErrorsService.h"
6 :
7 : #include "nsNSSComponent.h"
8 : #include "nsServiceManagerUtils.h"
9 : #include "pkix/pkixnss.h"
10 : #include "secerr.h"
11 : #include "sslerr.h"
12 :
13 : #define PIPNSS_STRBUNDLE_URL "chrome://pipnss/locale/pipnss.properties"
14 : #define NSSERR_STRBUNDLE_URL "chrome://pipnss/locale/nsserrors.properties"
15 :
16 : namespace mozilla {
17 : namespace psm {
18 :
19 : static_assert(mozilla::pkix::ERROR_BASE ==
20 : nsINSSErrorsService::MOZILLA_PKIX_ERROR_BASE,
21 : "MOZILLA_PKIX_ERROR_BASE and "
22 : "nsINSSErrorsService::MOZILLA_PKIX_ERROR_BASE do not match.");
23 : static_assert(mozilla::pkix::ERROR_LIMIT ==
24 : nsINSSErrorsService::MOZILLA_PKIX_ERROR_LIMIT,
25 : "MOZILLA_PKIX_ERROR_LIMIT and "
26 : "nsINSSErrorsService::MOZILLA_PKIX_ERROR_LIMIT do not match.");
27 :
28 : static bool
29 6 : IsPSMError(PRErrorCode error)
30 : {
31 6 : return (error >= mozilla::pkix::ERROR_BASE &&
32 6 : error < mozilla::pkix::ERROR_LIMIT);
33 : }
34 :
35 9 : NS_IMPL_ISUPPORTS(NSSErrorsService, nsINSSErrorsService)
36 :
37 0 : NSSErrorsService::~NSSErrorsService() { }
38 :
39 : nsresult
40 1 : NSSErrorsService::Init()
41 : {
42 : nsresult rv;
43 2 : nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
44 1 : if (NS_FAILED(rv) || !bundleService)
45 0 : return NS_ERROR_FAILURE;
46 :
47 2 : bundleService->CreateBundle(PIPNSS_STRBUNDLE_URL,
48 2 : getter_AddRefs(mPIPNSSBundle));
49 1 : if (!mPIPNSSBundle)
50 0 : rv = NS_ERROR_FAILURE;
51 :
52 2 : bundleService->CreateBundle(NSSERR_STRBUNDLE_URL,
53 2 : getter_AddRefs(mNSSErrorsBundle));
54 1 : if (!mNSSErrorsBundle)
55 0 : rv = NS_ERROR_FAILURE;
56 :
57 1 : return rv;
58 : }
59 :
60 : #define EXPECTED_SEC_ERROR_BASE (-0x2000)
61 : #define EXPECTED_SSL_ERROR_BASE (-0x3000)
62 :
63 : #if SEC_ERROR_BASE != EXPECTED_SEC_ERROR_BASE || SSL_ERROR_BASE != EXPECTED_SSL_ERROR_BASE
64 : #error "Unexpected change of error code numbers in lib NSS, please adjust the mapping code"
65 : /*
66 : * Please ensure the NSS error codes are mapped into the positive range 0x1000 to 0xf000
67 : * Search for NS_ERROR_MODULE_SECURITY to ensure there are no conflicts.
68 : * The current code also assumes that NSS library error codes are negative.
69 : */
70 : #endif
71 :
72 : bool
73 6 : IsNSSErrorCode(PRErrorCode code)
74 : {
75 6 : return IS_SEC_ERROR(code) || IS_SSL_ERROR(code) || IsPSMError(code);
76 : }
77 :
78 : nsresult
79 3 : GetXPCOMFromNSSError(PRErrorCode code)
80 : {
81 3 : if (!code) {
82 0 : MOZ_CRASH("Function failed without calling PR_GetError");
83 : }
84 :
85 : // The error codes within each module must be a 16 bit value.
86 : // For simplicity we use the positive value of the NSS code.
87 3 : return (nsresult)NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY,
88 : -1 * code);
89 : }
90 :
91 : NS_IMETHODIMP
92 0 : NSSErrorsService::IsNSSErrorCode(int32_t aNSPRCode, bool *_retval)
93 : {
94 0 : if (!_retval) {
95 0 : return NS_ERROR_INVALID_ARG;
96 : }
97 :
98 0 : *_retval = mozilla::psm::IsNSSErrorCode(aNSPRCode);
99 0 : return NS_OK;
100 : }
101 :
102 : NS_IMETHODIMP
103 0 : NSSErrorsService::GetXPCOMFromNSSError(int32_t aNSPRCode, nsresult *aXPCOMErrorCode)
104 : {
105 0 : if (!aXPCOMErrorCode) {
106 0 : return NS_ERROR_INVALID_ARG;
107 : }
108 :
109 0 : if (!mozilla::psm::IsNSSErrorCode(aNSPRCode)) {
110 0 : return NS_ERROR_INVALID_ARG;
111 : }
112 :
113 0 : *aXPCOMErrorCode = mozilla::psm::GetXPCOMFromNSSError(aNSPRCode);
114 :
115 0 : return NS_OK;
116 : }
117 :
118 : NS_IMETHODIMP
119 2 : NSSErrorsService::GetErrorClass(nsresult aXPCOMErrorCode, uint32_t *aErrorClass)
120 : {
121 2 : NS_ENSURE_ARG(aErrorClass);
122 :
123 2 : if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY ||
124 0 : NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) {
125 2 : return NS_ERROR_FAILURE;
126 : }
127 :
128 0 : int32_t aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode);
129 :
130 0 : if (!mozilla::psm::IsNSSErrorCode(aNSPRCode)) {
131 0 : return NS_ERROR_FAILURE;
132 : }
133 :
134 0 : if (mozilla::psm::ErrorIsOverridable(aNSPRCode)) {
135 0 : *aErrorClass = ERROR_CLASS_BAD_CERT;
136 : } else {
137 0 : *aErrorClass = ERROR_CLASS_SSL_PROTOCOL;
138 : }
139 :
140 0 : return NS_OK;
141 : }
142 :
143 : bool
144 0 : ErrorIsOverridable(PRErrorCode code)
145 : {
146 0 : switch (code)
147 : {
148 : // Overridable errors.
149 : case mozilla::pkix::MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY:
150 : case mozilla::pkix::MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME:
151 : case mozilla::pkix::MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE:
152 : case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE:
153 : case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE:
154 : case mozilla::pkix::MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA:
155 : case SEC_ERROR_CA_CERT_INVALID:
156 : case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
157 : case SEC_ERROR_EXPIRED_CERTIFICATE:
158 : case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
159 : case SEC_ERROR_INVALID_TIME:
160 : case SEC_ERROR_UNKNOWN_ISSUER:
161 : case SSL_ERROR_BAD_CERT_DOMAIN:
162 0 : return true;
163 : // Non-overridable errors.
164 : default:
165 0 : return false;
166 : }
167 : }
168 :
169 : NS_IMETHODIMP
170 0 : NSSErrorsService::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessage)
171 : {
172 0 : if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY ||
173 0 : NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) {
174 0 : return NS_ERROR_FAILURE;
175 : }
176 :
177 0 : int32_t aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode);
178 :
179 0 : if (!mozilla::psm::IsNSSErrorCode(aNSPRCode)) {
180 0 : return NS_ERROR_FAILURE;
181 : }
182 :
183 0 : nsCOMPtr<nsIStringBundle> theBundle = mPIPNSSBundle;
184 0 : const char *id_str = nsNSSErrors::getOverrideErrorStringName(aNSPRCode);
185 :
186 0 : if (!id_str) {
187 0 : id_str = nsNSSErrors::getDefaultErrorStringName(aNSPRCode);
188 0 : theBundle = mNSSErrorsBundle;
189 : }
190 :
191 0 : if (!id_str || !theBundle) {
192 0 : return NS_ERROR_FAILURE;
193 : }
194 :
195 0 : nsAutoString msg;
196 : nsresult rv =
197 0 : theBundle->GetStringFromName(NS_ConvertASCIItoUTF16(id_str).get(),
198 0 : getter_Copies(msg));
199 0 : if (NS_SUCCEEDED(rv)) {
200 0 : aErrorMessage = msg;
201 : }
202 0 : return rv;
203 : }
204 :
205 : } // namespace psm
206 : } // namespace mozilla
|