Coverage Report

Created: 2018-09-25 14:53

/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