forked from mirrors/gecko-dev
Bug 1721220 - Add BAD_STS_CERT error r=geckoview-reviewers,nika,agi,owlish
Differential Revision: https://phabricator.services.mozilla.com/D146234
This commit is contained in:
parent
0cf67ce1eb
commit
803a4e8449
10 changed files with 83 additions and 8 deletions
|
|
@ -119,6 +119,7 @@ https://sub2.test1.example.com:443 privileged
|
||||||
https://sub2.test2.example.com:443 privileged
|
https://sub2.test2.example.com:443 privileged
|
||||||
https://example.net:443 privileged
|
https://example.net:443 privileged
|
||||||
https://nocert.example.com:443 privileged,nocert
|
https://nocert.example.com:443 privileged,nocert
|
||||||
|
https://nocert.example.org:443 privileged,nocert
|
||||||
https://self-signed.example.com:443 privileged,cert=selfsigned
|
https://self-signed.example.com:443 privileged,cert=selfsigned
|
||||||
https://untrusted.example.com:443 privileged,cert=untrusted
|
https://untrusted.example.com:443 privileged,cert=untrusted
|
||||||
https://expired.example.com:443 privileged,cert=expired
|
https://expired.example.com:443 privileged,cert=expired
|
||||||
|
|
|
||||||
|
|
@ -3561,6 +3561,7 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
||||||
const char* errorDescriptionID = nullptr;
|
const char* errorDescriptionID = nullptr;
|
||||||
AutoTArray<nsString, 3> formatStrs;
|
AutoTArray<nsString, 3> formatStrs;
|
||||||
bool addHostPort = false;
|
bool addHostPort = false;
|
||||||
|
bool isBadStsCertError = false;
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
nsAutoString messageStr;
|
nsAutoString messageStr;
|
||||||
nsAutoCString cssClass;
|
nsAutoCString cssClass;
|
||||||
|
|
@ -3710,6 +3711,7 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
||||||
// In the future we should differentiate between an HSTS host and a
|
// In the future we should differentiate between an HSTS host and a
|
||||||
// pinned host and display a more informative message to the user.
|
// pinned host and display a more informative message to the user.
|
||||||
if (isStsHost || isPinnedHost) {
|
if (isStsHost || isPinnedHost) {
|
||||||
|
isBadStsCertError = true;
|
||||||
cssClass.AssignLiteral("badStsCert");
|
cssClass.AssignLiteral("badStsCert");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3870,19 +3872,21 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult delegateErrorCode = aError;
|
||||||
// If the HTTPS-Only Mode upgraded this request and the upgrade might have
|
// If the HTTPS-Only Mode upgraded this request and the upgrade might have
|
||||||
// caused this error, we replace the error-page with about:httpsonlyerror
|
// caused this error, we replace the error-page with about:httpsonlyerror
|
||||||
bool isHttpsOnlyError =
|
if (nsHTTPSOnlyUtils::CouldBeHttpsOnlyError(aFailedChannel, aError)) {
|
||||||
nsHTTPSOnlyUtils::CouldBeHttpsOnlyError(aFailedChannel, aError);
|
|
||||||
if (isHttpsOnlyError) {
|
|
||||||
errorPage.AssignLiteral("httpsonlyerror");
|
errorPage.AssignLiteral("httpsonlyerror");
|
||||||
|
delegateErrorCode = NS_ERROR_HTTPS_ONLY;
|
||||||
|
} else if (isBadStsCertError) {
|
||||||
|
delegateErrorCode = NS_ERROR_BAD_HSTS_CERT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nsCOMPtr<nsILoadURIDelegate> loadURIDelegate = GetLoadURIDelegate()) {
|
if (nsCOMPtr<nsILoadURIDelegate> loadURIDelegate = GetLoadURIDelegate()) {
|
||||||
nsresult code = isHttpsOnlyError ? NS_ERROR_HTTPS_ONLY : aError;
|
|
||||||
nsCOMPtr<nsIURI> errorPageURI;
|
nsCOMPtr<nsIURI> errorPageURI;
|
||||||
rv = loadURIDelegate->HandleLoadError(aURI, code, NS_ERROR_GET_MODULE(code),
|
rv = loadURIDelegate->HandleLoadError(
|
||||||
getter_AddRefs(errorPageURI));
|
aURI, delegateErrorCode, NS_ERROR_GET_MODULE(delegateErrorCode),
|
||||||
|
getter_AddRefs(errorPageURI));
|
||||||
// If the docshell is going away there's no point in showing an error page.
|
// If the docshell is going away there's no point in showing an error page.
|
||||||
if (NS_FAILED(rv) || mIsBeingDestroyed) {
|
if (NS_FAILED(rv) || mIsBeingDestroyed) {
|
||||||
*aDisplayedErrorPage = false;
|
*aDisplayedErrorPage = false;
|
||||||
|
|
|
||||||
|
|
@ -2376,6 +2376,7 @@ package org.mozilla.geckoview {
|
||||||
@AnyThread public class WebRequestError extends Exception {
|
@AnyThread public class WebRequestError extends Exception {
|
||||||
ctor public WebRequestError(int, int);
|
ctor public WebRequestError(int, int);
|
||||||
ctor public WebRequestError(int, int, X509Certificate);
|
ctor public WebRequestError(int, int, X509Certificate);
|
||||||
|
field public static final int ERROR_BAD_HSTS_CERT = 179;
|
||||||
field public static final int ERROR_CATEGORY_CONTENT = 4;
|
field public static final int ERROR_CATEGORY_CONTENT = 4;
|
||||||
field public static final int ERROR_CATEGORY_NETWORK = 3;
|
field public static final int ERROR_CATEGORY_NETWORK = 3;
|
||||||
field public static final int ERROR_CATEGORY_PROXY = 6;
|
field public static final int ERROR_CATEGORY_PROXY = 6;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
function handleRequest(request, response) {
|
||||||
|
response.setHeader(
|
||||||
|
"Strict-Transport-Security",
|
||||||
|
"max-age=60; includeSubDomains"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -625,6 +625,51 @@ class NavigationDelegateTest : BaseSessionTest() {
|
||||||
sessionRule.runtime.settings.setAllowInsecureConnections(GeckoRuntimeSettings.ALLOW_ALL)
|
sessionRule.runtime.settings.setAllowInsecureConnections(GeckoRuntimeSettings.ALLOW_ALL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test fun loadHSTSBadCert() {
|
||||||
|
// TODO: Bug 1673954
|
||||||
|
assumeThat(sessionRule.env.isFission, equalTo(false))
|
||||||
|
|
||||||
|
val httpsFirstPref = "dom.security.https_first"
|
||||||
|
assertThat("https pref should be false", sessionRule.getPrefs(httpsFirstPref)[0] as Boolean, equalTo(false))
|
||||||
|
|
||||||
|
// load secure url with hsts header
|
||||||
|
val uri = "https://example.org/tests/junit/hsts_header.sjs"
|
||||||
|
mainSession.loadUri(uri)
|
||||||
|
mainSession.waitForPageStop()
|
||||||
|
|
||||||
|
// load insecure subdomain url to see if it gets upgraded to https
|
||||||
|
val http_uri = "http://test1.example.org/"
|
||||||
|
val https_uri = "https://test1.example.org/"
|
||||||
|
|
||||||
|
mainSession.loadUri(http_uri)
|
||||||
|
mainSession.waitForPageStop()
|
||||||
|
|
||||||
|
mainSession.forCallbacksDuringWait(object : NavigationDelegate {
|
||||||
|
@AssertCalled(count = 2)
|
||||||
|
override fun onLoadRequest(session: GeckoSession,
|
||||||
|
request: LoadRequest):
|
||||||
|
GeckoResult<AllowOrDeny>? {
|
||||||
|
assertThat("URI should be HTTP then redirected to HTTPS",
|
||||||
|
request.uri, equalTo(forEachCall(http_uri, https_uri)))
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// load subdomain that will trigger the cert error
|
||||||
|
val no_cert_uri = "https://nocert.example.org/"
|
||||||
|
mainSession.loadUri(no_cert_uri)
|
||||||
|
mainSession.waitForPageStop()
|
||||||
|
|
||||||
|
mainSession.forCallbacksDuringWait(object : NavigationDelegate {
|
||||||
|
@AssertCalled(count = 1)
|
||||||
|
override fun onLoadError(session: GeckoSession, uri: String?, error: WebRequestError): GeckoResult<String>? {
|
||||||
|
assertThat("categories should match", error.category, equalTo(WebRequestError.ERROR_CATEGORY_NETWORK))
|
||||||
|
assertThat("codes should match", error.code, equalTo(WebRequestError.ERROR_BAD_HSTS_CERT))
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
@Ignore // Disabled for bug 1619344.
|
@Ignore // Disabled for bug 1619344.
|
||||||
@Test fun loadUnknownProtocol() {
|
@Test fun loadUnknownProtocol() {
|
||||||
testLoadEarlyError(UNKNOWN_PROTOCOL_URI,
|
testLoadEarlyError(UNKNOWN_PROTOCOL_URI,
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,8 @@ public class WebRequestError extends Exception {
|
||||||
ERROR_UNSAFE_CONTENT_TYPE,
|
ERROR_UNSAFE_CONTENT_TYPE,
|
||||||
ERROR_CORRUPTED_CONTENT,
|
ERROR_CORRUPTED_CONTENT,
|
||||||
ERROR_DATA_URI_TOO_LONG,
|
ERROR_DATA_URI_TOO_LONG,
|
||||||
ERROR_HTTPS_ONLY
|
ERROR_HTTPS_ONLY,
|
||||||
|
ERROR_BAD_HSTS_CERT
|
||||||
})
|
})
|
||||||
public @interface Error {}
|
public @interface Error {}
|
||||||
|
|
||||||
|
|
@ -134,6 +135,12 @@ public class WebRequestError extends Exception {
|
||||||
*/
|
*/
|
||||||
public static final int ERROR_HTTPS_ONLY = 0xA3;
|
public static final int ERROR_HTTPS_ONLY = 0xA3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A certificate validation error occurred when connecting to a site that does not allow error
|
||||||
|
* overrides.
|
||||||
|
*/
|
||||||
|
public static final int ERROR_BAD_HSTS_CERT = 0xB3;
|
||||||
|
|
||||||
// Content
|
// Content
|
||||||
/** A content type was returned which was deemed unsafe. */
|
/** A content type was returned which was deemed unsafe. */
|
||||||
public static final int ERROR_UNSAFE_CONTENT_TYPE = 0x24;
|
public static final int ERROR_UNSAFE_CONTENT_TYPE = 0x24;
|
||||||
|
|
@ -326,6 +333,9 @@ public class WebRequestError extends Exception {
|
||||||
if (geckoError == XPCOMError.NS_ERROR_HTTPS_ONLY) {
|
if (geckoError == XPCOMError.NS_ERROR_HTTPS_ONLY) {
|
||||||
return ERROR_HTTPS_ONLY;
|
return ERROR_HTTPS_ONLY;
|
||||||
}
|
}
|
||||||
|
if (geckoError == XPCOMError.NS_ERROR_BAD_HSTS_CERT) {
|
||||||
|
return ERROR_BAD_HSTS_CERT;
|
||||||
|
}
|
||||||
if (geckoError == XPCOMError.NS_ERROR_OFFLINE) {
|
if (geckoError == XPCOMError.NS_ERROR_OFFLINE) {
|
||||||
return ERROR_OFFLINE;
|
return ERROR_OFFLINE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ exclude: true
|
||||||
([bug 1758800]({{bugzilla}}1758800))
|
([bug 1758800]({{bugzilla}}1758800))
|
||||||
- Deprecated [`GeckoSession.autofill`][102.18], use [`Autofill.Session.autofill`][102.19] instead.
|
- Deprecated [`GeckoSession.autofill`][102.18], use [`Autofill.Session.autofill`][102.19] instead.
|
||||||
([bug 1770010]({{bugzilla}}1770010))
|
([bug 1770010]({{bugzilla}}1770010))
|
||||||
|
- Added [`WebRequestError.ERROR_BAD_HSTS_CERT`][102.20] error code to notify the app of a connection to a site that does not allow error overrides.
|
||||||
|
([bug 1721220]({{bugzilla}}1721220))
|
||||||
|
|
||||||
[102.1]: {{javadoc_uri}}/GeckoSession.PromptDelegate.DateTimePrompt.html#stepValue
|
[102.1]: {{javadoc_uri}}/GeckoSession.PromptDelegate.DateTimePrompt.html#stepValue
|
||||||
[102.2]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date#step
|
[102.2]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date#step
|
||||||
|
|
@ -50,6 +52,7 @@ exclude: true
|
||||||
[102.17]: {{javadoc_uri}}/GeckoSession.PromptDelegate.PromptInstanceDelegate.html#onPromptUpdate(org.mozilla.geckoview.GeckoSession.PromptDelegate.BasePrompt)
|
[102.17]: {{javadoc_uri}}/GeckoSession.PromptDelegate.PromptInstanceDelegate.html#onPromptUpdate(org.mozilla.geckoview.GeckoSession.PromptDelegate.BasePrompt)
|
||||||
[102.18]: {{javadoc_uri}}/GeckoSession.html#autofill(android.util.SparseArray)
|
[102.18]: {{javadoc_uri}}/GeckoSession.html#autofill(android.util.SparseArray)
|
||||||
[102.19]: {{javadoc_uri}}/Autofill.Session.html#autofill(android.util.SparseArray)
|
[102.19]: {{javadoc_uri}}/Autofill.Session.html#autofill(android.util.SparseArray)
|
||||||
|
[102.20]: {{javadoc_uri}}/WebRequestError.html#ERROR_BAD_HSTS_CERT
|
||||||
|
|
||||||
## v101
|
## v101
|
||||||
- Added [`GeckoDisplay.surfaceChanged`][101.1] function taking new type [`GeckoDisplay.SurfaceInfo`][101.2].
|
- Added [`GeckoDisplay.surfaceChanged`][101.1] function taking new type [`GeckoDisplay.SurfaceInfo`][101.2].
|
||||||
|
|
@ -1204,4 +1207,4 @@ to allow adding gecko profiler markers.
|
||||||
[65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport(android.content.Context,android.os.Bundle,java.lang.String)
|
[65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport(android.content.Context,android.os.Bundle,java.lang.String)
|
||||||
[65.25]: {{javadoc_uri}}/GeckoResult.html
|
[65.25]: {{javadoc_uri}}/GeckoResult.html
|
||||||
|
|
||||||
[api-version]: dc9516b62971d881de4059eae2ea1b88a1ebb3d1
|
[api-version]: d06ece1a8d568d3c62ee1f6786f4ffe13476b29f
|
||||||
|
|
|
||||||
|
|
@ -2161,6 +2161,8 @@ public class GeckoViewActivity extends AppCompatActivity
|
||||||
return "ERROR_CORRUPTED_CONTENT";
|
return "ERROR_CORRUPTED_CONTENT";
|
||||||
case WebRequestError.ERROR_HTTPS_ONLY:
|
case WebRequestError.ERROR_HTTPS_ONLY:
|
||||||
return "ERROR_HTTPS_ONLY";
|
return "ERROR_HTTPS_ONLY";
|
||||||
|
case WebRequestError.ERROR_BAD_HSTS_CERT:
|
||||||
|
return "ERROR_BAD_HSTS_CERT";
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ TEST_HARNESS_FILES.testing.mochitest.tests.junit += [
|
||||||
"geckoview/src/androidTest/assets/www/forms_iframe.html",
|
"geckoview/src/androidTest/assets/www/forms_iframe.html",
|
||||||
"geckoview/src/androidTest/assets/www/forms_xorigin.html",
|
"geckoview/src/androidTest/assets/www/forms_xorigin.html",
|
||||||
"geckoview/src/androidTest/assets/www/hello.html",
|
"geckoview/src/androidTest/assets/www/hello.html",
|
||||||
|
"geckoview/src/androidTest/assets/www/hsts_header.sjs",
|
||||||
"geckoview/src/androidTest/assets/www/iframe_http_only.html",
|
"geckoview/src/androidTest/assets/www/iframe_http_only.html",
|
||||||
"geckoview/src/androidTest/assets/www/simple_redirect.sjs",
|
"geckoview/src/androidTest/assets/www/simple_redirect.sjs",
|
||||||
"geckoview/src/androidTest/assets/www/update_manifest.json",
|
"geckoview/src/androidTest/assets/www/update_manifest.json",
|
||||||
|
|
|
||||||
|
|
@ -343,6 +343,8 @@ with modules["NETWORK"]:
|
||||||
# A connection to a non local address is refused because
|
# A connection to a non local address is refused because
|
||||||
# xpc::AreNonLocalConnectionsDisabled() returns true.
|
# xpc::AreNonLocalConnectionsDisabled() returns true.
|
||||||
errors["NS_ERROR_NON_LOCAL_CONNECTION_REFUSED"] = FAILURE(88)
|
errors["NS_ERROR_NON_LOCAL_CONNECTION_REFUSED"] = FAILURE(88)
|
||||||
|
# Connection to a sts host without a hsts header.
|
||||||
|
errors["NS_ERROR_BAD_HSTS_CERT"] = FAILURE(89)
|
||||||
|
|
||||||
# XXX really need to better rationalize these error codes. are consumers of
|
# XXX really need to better rationalize these error codes. are consumers of
|
||||||
# necko really expected to know how to discern the meaning of these??
|
# necko really expected to know how to discern the meaning of these??
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue