/src/mozilla-central/security/manager/ssl/NSSErrorsService.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 0 | #define PIPNSS_STRBUNDLE_URL "chrome://pipnss/locale/pipnss.properties" |
14 | 0 | #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 | | IsPSMError(PRErrorCode error) |
30 | 0 | { |
31 | 0 | return (error >= mozilla::pkix::ERROR_BASE && |
32 | 0 | error < mozilla::pkix::ERROR_LIMIT); |
33 | 0 | } |
34 | | |
35 | | NS_IMPL_ISUPPORTS(NSSErrorsService, nsINSSErrorsService) |
36 | | |
37 | 0 | NSSErrorsService::~NSSErrorsService() { } |
38 | | |
39 | | nsresult |
40 | | NSSErrorsService::Init() |
41 | 0 | { |
42 | 0 | nsresult rv; |
43 | 0 | nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv)); |
44 | 0 | if (NS_FAILED(rv) || !bundleService) |
45 | 0 | return NS_ERROR_FAILURE; |
46 | 0 | |
47 | 0 | bundleService->CreateBundle(PIPNSS_STRBUNDLE_URL, |
48 | 0 | getter_AddRefs(mPIPNSSBundle)); |
49 | 0 | if (!mPIPNSSBundle) |
50 | 0 | rv = NS_ERROR_FAILURE; |
51 | 0 |
|
52 | 0 | bundleService->CreateBundle(NSSERR_STRBUNDLE_URL, |
53 | 0 | getter_AddRefs(mNSSErrorsBundle)); |
54 | 0 | if (!mNSSErrorsBundle) |
55 | 0 | rv = NS_ERROR_FAILURE; |
56 | 0 |
|
57 | 0 | return rv; |
58 | 0 | } |
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 | | IsNSSErrorCode(PRErrorCode code) |
74 | 0 | { |
75 | 0 | return IS_SEC_ERROR(code) || IS_SSL_ERROR(code) || IsPSMError(code); |
76 | 0 | } |
77 | | |
78 | | nsresult |
79 | | GetXPCOMFromNSSError(PRErrorCode code) |
80 | 0 | { |
81 | 0 | if (!code) { |
82 | 0 | MOZ_CRASH("Function failed without calling PR_GetError"); |
83 | 0 | } |
84 | 0 |
|
85 | 0 | // The error codes within each module must be a 16 bit value. |
86 | 0 | // For simplicity we use the positive value of the NSS code. |
87 | 0 | return (nsresult)NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, |
88 | 0 | -1 * code); |
89 | 0 | } |
90 | | |
91 | | NS_IMETHODIMP |
92 | | NSSErrorsService::IsNSSErrorCode(int32_t aNSPRCode, bool *_retval) |
93 | 0 | { |
94 | 0 | if (!_retval) { |
95 | 0 | return NS_ERROR_INVALID_ARG; |
96 | 0 | } |
97 | 0 | |
98 | 0 | *_retval = mozilla::psm::IsNSSErrorCode(aNSPRCode); |
99 | 0 | return NS_OK; |
100 | 0 | } |
101 | | |
102 | | NS_IMETHODIMP |
103 | | NSSErrorsService::GetXPCOMFromNSSError(int32_t aNSPRCode, nsresult *aXPCOMErrorCode) |
104 | 0 | { |
105 | 0 | if (!aXPCOMErrorCode) { |
106 | 0 | return NS_ERROR_INVALID_ARG; |
107 | 0 | } |
108 | 0 | |
109 | 0 | if (!mozilla::psm::IsNSSErrorCode(aNSPRCode)) { |
110 | 0 | return NS_ERROR_INVALID_ARG; |
111 | 0 | } |
112 | 0 | |
113 | 0 | *aXPCOMErrorCode = mozilla::psm::GetXPCOMFromNSSError(aNSPRCode); |
114 | 0 |
|
115 | 0 | return NS_OK; |
116 | 0 | } |
117 | | |
118 | | NS_IMETHODIMP |
119 | | NSSErrorsService::GetErrorClass(nsresult aXPCOMErrorCode, uint32_t *aErrorClass) |
120 | 0 | { |
121 | 0 | NS_ENSURE_ARG(aErrorClass); |
122 | 0 |
|
123 | 0 | if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY || |
124 | 0 | NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) { |
125 | 0 | return NS_ERROR_FAILURE; |
126 | 0 | } |
127 | 0 | |
128 | 0 | int32_t aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); |
129 | 0 |
|
130 | 0 | if (!mozilla::psm::IsNSSErrorCode(aNSPRCode)) { |
131 | 0 | return NS_ERROR_FAILURE; |
132 | 0 | } |
133 | 0 | |
134 | 0 | if (mozilla::psm::ErrorIsOverridable(aNSPRCode)) { |
135 | 0 | *aErrorClass = ERROR_CLASS_BAD_CERT; |
136 | 0 | } else { |
137 | 0 | *aErrorClass = ERROR_CLASS_SSL_PROTOCOL; |
138 | 0 | } |
139 | 0 |
|
140 | 0 | return NS_OK; |
141 | 0 | } |
142 | | |
143 | | bool |
144 | | ErrorIsOverridable(PRErrorCode code) |
145 | | { |
146 | | switch (code) |
147 | | { |
148 | | // Overridable errors. |
149 | | case mozilla::pkix::MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED: |
150 | | case mozilla::pkix::MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY: |
151 | | case mozilla::pkix::MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME: |
152 | | case mozilla::pkix::MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE: |
153 | | case mozilla::pkix::MOZILLA_PKIX_ERROR_MITM_DETECTED: |
154 | | case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE: |
155 | | case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE: |
156 | | case mozilla::pkix::MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT: |
157 | | case mozilla::pkix::MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA: |
158 | | case SEC_ERROR_CA_CERT_INVALID: |
159 | | case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED: |
160 | | case SEC_ERROR_EXPIRED_CERTIFICATE: |
161 | | case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: |
162 | | case SEC_ERROR_INVALID_TIME: |
163 | | case SEC_ERROR_UNKNOWN_ISSUER: |
164 | | case SSL_ERROR_BAD_CERT_DOMAIN: |
165 | | return true; |
166 | | // Non-overridable errors. |
167 | | default: |
168 | | return false; |
169 | | } |
170 | | } |
171 | | |
172 | | static const char* |
173 | | getOverrideErrorStringName(PRErrorCode aErrorCode) |
174 | | { |
175 | | switch (aErrorCode) { |
176 | | case SSL_ERROR_SSL_DISABLED: |
177 | | return "PSMERR_SSL_Disabled"; |
178 | | case SSL_ERROR_SSL2_DISABLED: |
179 | | return "PSMERR_SSL2_Disabled"; |
180 | | case SEC_ERROR_REUSED_ISSUER_AND_SERIAL: |
181 | | return "PSMERR_HostReusedIssuerSerial"; |
182 | | case mozilla::pkix::MOZILLA_PKIX_ERROR_MITM_DETECTED: |
183 | | return "certErrorTrust_MitM"; |
184 | | default: |
185 | | return nullptr; |
186 | | } |
187 | | } |
188 | | |
189 | | NS_IMETHODIMP |
190 | | NSSErrorsService::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessage) |
191 | 0 | { |
192 | 0 | if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY || |
193 | 0 | NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) { |
194 | 0 | return NS_ERROR_FAILURE; |
195 | 0 | } |
196 | 0 | |
197 | 0 | int32_t aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); |
198 | 0 |
|
199 | 0 | if (!mozilla::psm::IsNSSErrorCode(aNSPRCode)) { |
200 | 0 | return NS_ERROR_FAILURE; |
201 | 0 | } |
202 | 0 | |
203 | 0 | nsCOMPtr<nsIStringBundle> theBundle = mPIPNSSBundle; |
204 | 0 | const char* idStr = getOverrideErrorStringName(aNSPRCode); |
205 | 0 |
|
206 | 0 | if (!idStr) { |
207 | 0 | idStr = PR_ErrorToName(aNSPRCode); |
208 | 0 | theBundle = mNSSErrorsBundle; |
209 | 0 | } |
210 | 0 |
|
211 | 0 | if (!idStr || !theBundle) { |
212 | 0 | return NS_ERROR_FAILURE; |
213 | 0 | } |
214 | 0 | |
215 | 0 | nsAutoString msg; |
216 | 0 | nsresult rv = theBundle->GetStringFromName(idStr, msg); |
217 | 0 | if (NS_SUCCEEDED(rv)) { |
218 | 0 | aErrorMessage = msg; |
219 | 0 | } |
220 | 0 | return rv; |
221 | 0 | } |
222 | | |
223 | | } // namespace psm |
224 | | } // namespace mozilla |