Skip to content

Commit

Permalink
Add invalid certificate bypass to ssl error pages (#2530)
Browse files Browse the repository at this point in the history
* wip

* Add support for bypassing the SSL certificate exceptions

* Leave only the temporary option when bypassing
  • Loading branch information
keianhzo authored and bluemarvin committed Jan 1, 2020
1 parent 986175f commit e9e6260
Show file tree
Hide file tree
Showing 6 changed files with 273 additions and 220 deletions.
Expand Up @@ -52,7 +52,7 @@ object EngineProvider {
runtime = GeckoRuntime.create(context, builder.build())
for (extension in WEB_EXTENSIONS) {
val path = "resource://android/assets/web_extensions/$extension/"
runtime!!.registerWebExtension(WebExtension(path))
runtime!!.registerWebExtension(WebExtension(path, runtime!!.webExtensionController))
}


Expand Down
Expand Up @@ -966,7 +966,7 @@ public GeckoResult<GeckoSession> onNewSession(@NonNull GeckoSession aSession, @N
public GeckoResult<String> onLoadError(@NonNull GeckoSession session, String uri, @NonNull WebRequestError error) {
Log.d(LOGTAG, "Session onLoadError: " + uri);

return GeckoResult.fromValue(InternalPages.createErrorPageDataURI(mContext, uri, error.category, error.code));
return GeckoResult.fromValue(InternalPages.createErrorPageDataURI(mContext, uri, error.code));
}

// Progress Listener
Expand Down
196 changes: 91 additions & 105 deletions app/src/common/shared/org/mozilla/vrbrowser/utils/InternalPages.java
Expand Up @@ -16,110 +16,84 @@

public class InternalPages {

private static ErrorType fromGeckoErrorToErrorType(int category, int error) {
switch(category) {
case WebRequestError.ERROR_CATEGORY_UNKNOWN: {
return ErrorType.UNKNOWN;
private static ErrorType fromGeckoErrorToErrorType(int error) {
switch(error) {
case WebRequestError.ERROR_SECURITY_SSL: {
return ErrorType.ERROR_SECURITY_SSL;
}
case WebRequestError.ERROR_SECURITY_BAD_CERT: {
return ErrorType.ERROR_SECURITY_BAD_CERT;
}
case WebRequestError.ERROR_NET_INTERRUPT: {
return ErrorType.ERROR_NET_INTERRUPT;
}
case WebRequestError.ERROR_NET_TIMEOUT: {
return ErrorType.ERROR_NET_TIMEOUT;
}
case WebRequestError.ERROR_CONNECTION_REFUSED: {
return ErrorType.ERROR_CONNECTION_REFUSED;
}
case WebRequestError.ERROR_UNKNOWN_SOCKET_TYPE: {
return ErrorType.ERROR_UNKNOWN_SOCKET_TYPE;
}
case WebRequestError.ERROR_REDIRECT_LOOP: {
return ErrorType.ERROR_REDIRECT_LOOP;
}
case WebRequestError.ERROR_OFFLINE: {
return ErrorType.ERROR_OFFLINE;
}
case WebRequestError.ERROR_PORT_BLOCKED: {
return ErrorType.ERROR_PORT_BLOCKED;
}
case WebRequestError.ERROR_NET_RESET: {
return ErrorType.ERROR_NET_RESET;
}
case WebRequestError.ERROR_UNSAFE_CONTENT_TYPE: {
return ErrorType.ERROR_UNSAFE_CONTENT_TYPE;
}
case WebRequestError.ERROR_CORRUPTED_CONTENT: {
return ErrorType.ERROR_CORRUPTED_CONTENT;
}
case WebRequestError.ERROR_CONTENT_CRASHED: {
return ErrorType.ERROR_CONTENT_CRASHED;
}
case WebRequestError.ERROR_INVALID_CONTENT_ENCODING: {
return ErrorType.ERROR_INVALID_CONTENT_ENCODING;
}
case WebRequestError.ERROR_CATEGORY_SECURITY: {
switch (error) {
case WebRequestError.ERROR_SECURITY_SSL: {
return ErrorType.ERROR_SECURITY_SSL;
}
case WebRequestError.ERROR_SECURITY_BAD_CERT: {
return ErrorType.ERROR_SECURITY_BAD_CERT;
}
}
}
case WebRequestError.ERROR_CATEGORY_NETWORK: {
switch (error) {
case WebRequestError.ERROR_NET_INTERRUPT: {
return ErrorType.ERROR_NET_INTERRUPT;
}
case WebRequestError.ERROR_NET_TIMEOUT: {
return ErrorType.ERROR_NET_TIMEOUT;
}
case WebRequestError.ERROR_CONNECTION_REFUSED: {
return ErrorType.ERROR_CONNECTION_REFUSED;
}
case WebRequestError.ERROR_UNKNOWN_SOCKET_TYPE: {
return ErrorType.ERROR_UNKNOWN_SOCKET_TYPE;
}
case WebRequestError.ERROR_REDIRECT_LOOP: {
return ErrorType.ERROR_REDIRECT_LOOP;
}
case WebRequestError.ERROR_OFFLINE: {
return ErrorType.ERROR_OFFLINE;
}
case WebRequestError.ERROR_PORT_BLOCKED: {
return ErrorType.ERROR_PORT_BLOCKED;
}
case WebRequestError.ERROR_NET_RESET: {
return ErrorType.ERROR_NET_RESET;
}
}
}
case WebRequestError.ERROR_CATEGORY_CONTENT: {
switch (error) {
case WebRequestError.ERROR_UNSAFE_CONTENT_TYPE: {
return ErrorType.ERROR_UNSAFE_CONTENT_TYPE;
}
case WebRequestError.ERROR_CORRUPTED_CONTENT: {
return ErrorType.ERROR_CORRUPTED_CONTENT;
}
case WebRequestError.ERROR_CONTENT_CRASHED: {
return ErrorType.ERROR_CONTENT_CRASHED;
}
case WebRequestError.ERROR_INVALID_CONTENT_ENCODING: {
return ErrorType.ERROR_INVALID_CONTENT_ENCODING;
}
}
}
case WebRequestError.ERROR_CATEGORY_URI: {
switch (error) {
case WebRequestError.ERROR_UNKNOWN_HOST: {
return ErrorType.ERROR_UNKNOWN_HOST;
}
case WebRequestError.ERROR_MALFORMED_URI: {
return ErrorType.ERROR_MALFORMED_URI;
}
case WebRequestError.ERROR_UNKNOWN_PROTOCOL: {
return ErrorType.ERROR_UNKNOWN_PROTOCOL;
}
case WebRequestError.ERROR_FILE_NOT_FOUND: {
return ErrorType.ERROR_FILE_NOT_FOUND;
}
case WebRequestError.ERROR_FILE_ACCESS_DENIED: {
return ErrorType.ERROR_FILE_ACCESS_DENIED;
}
}
}
case WebRequestError.ERROR_CATEGORY_PROXY: {
switch (error) {
case WebRequestError.ERROR_PROXY_CONNECTION_REFUSED: {
return ErrorType.ERROR_CONNECTION_REFUSED;
}
case WebRequestError.ERROR_UNKNOWN_PROXY_HOST: {
return ErrorType.ERROR_UNKNOWN_PROXY_HOST;
}
}
}
case WebRequestError.ERROR_CATEGORY_SAFEBROWSING: {
switch (error) {
case WebRequestError.ERROR_SAFEBROWSING_MALWARE_URI: {
return ErrorType.ERROR_SAFEBROWSING_MALWARE_URI;
}
case WebRequestError.ERROR_SAFEBROWSING_UNWANTED_URI: {
return ErrorType.ERROR_SAFEBROWSING_UNWANTED_URI;
}
case WebRequestError.ERROR_SAFEBROWSING_HARMFUL_URI: {
return ErrorType.ERROR_SAFEBROWSING_HARMFUL_URI;
}
case WebRequestError.ERROR_SAFEBROWSING_PHISHING_URI: {
return ErrorType.ERROR_SAFEBROWSING_PHISHING_URI;
}
}
case WebRequestError.ERROR_UNKNOWN_HOST: {
return ErrorType.ERROR_UNKNOWN_HOST;
}
case WebRequestError.ERROR_MALFORMED_URI: {
return ErrorType.ERROR_MALFORMED_URI;
}
case WebRequestError.ERROR_UNKNOWN_PROTOCOL: {
return ErrorType.ERROR_UNKNOWN_PROTOCOL;
}
case WebRequestError.ERROR_FILE_NOT_FOUND: {
return ErrorType.ERROR_FILE_NOT_FOUND;
}
case WebRequestError.ERROR_FILE_ACCESS_DENIED: {
return ErrorType.ERROR_FILE_ACCESS_DENIED;
}
case WebRequestError.ERROR_PROXY_CONNECTION_REFUSED: {
return ErrorType.ERROR_PROXY_CONNECTION_REFUSED;
}
case WebRequestError.ERROR_UNKNOWN_PROXY_HOST: {
return ErrorType.ERROR_UNKNOWN_PROXY_HOST;
}
case WebRequestError.ERROR_SAFEBROWSING_MALWARE_URI: {
return ErrorType.ERROR_SAFEBROWSING_MALWARE_URI;
}
case WebRequestError.ERROR_SAFEBROWSING_UNWANTED_URI: {
return ErrorType.ERROR_SAFEBROWSING_UNWANTED_URI;
}
case WebRequestError.ERROR_SAFEBROWSING_HARMFUL_URI: {
return ErrorType.ERROR_SAFEBROWSING_HARMFUL_URI;
}
case WebRequestError.ERROR_SAFEBROWSING_PHISHING_URI: {
return ErrorType.ERROR_SAFEBROWSING_PHISHING_URI;
}
case WebRequestError.ERROR_CATEGORY_UNKNOWN:
default: {
return ErrorType.UNKNOWN;
}
Expand All @@ -142,16 +116,28 @@ public static PageResources create(int html, int css) {

public static String createErrorPageDataURI(Context context,
String uri,
int errorCategory,
int errorType) {
// TODO: browser-error pages component needs to accept a uri parameter
String html = ErrorPages.INSTANCE.createErrorPage(
context,
fromGeckoErrorToErrorType(errorCategory, errorType),
fromGeckoErrorToErrorType(errorType),
uri,
R.raw.error_pages,
R.raw.error_style);

boolean showSSLAdvanced;
switch (errorType) {
case WebRequestError.ERROR_SECURITY_SSL:
case WebRequestError.ERROR_SECURITY_BAD_CERT:
showSSLAdvanced = true;
break;
default:
showSSLAdvanced = false;
}

html = html
.replace("%url%", uri)
.replace("%advancedSSLStyle%", showSSLAdvanced ? "block" : "none");

return "data:text/html;base64," + Base64.encodeToString(html.getBytes(), Base64.NO_WRAP);
}

Expand Down
67 changes: 59 additions & 8 deletions app/src/main/res/raw/error_pages.html
@@ -1,28 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<!-- 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/. -->
<html class="error">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width; user-scalable=false;" />
<title>%pageTitle%</title>
<style>%css%</style>
<script type="text/javascript">
var advancedVisible = false;
function toggleAdvanced() {
if (advancedVisible) {
document.getElementById('badCertAdvancedPanel').style.display='none';

} else {
document.getElementById('badCertAdvancedPanel').style.display='block';
}

advancedVisible = !advancedVisible;
}
function acceptAndContinue(temporary) {
document.addCertException(temporary).then(() => {
location.reload();
},
err => {
console.error("Unexpected error: " + err)
}
);
}
</script>
</head>
<body>

<body id="errorPage" dir="auto">
<!-- PAGE CONTAINER (for styling purposes only) -->
<div id="errorPageContainer">

<!-- Error Title -->
<div id="errorTitle">
<h1 class="errorTitleText">%messageShort%</h1>
<h1 id="et_dnsNotFound" class="errorTitleText">%messageShort%</h1>
</div>

<!-- LONG CONTENT (the section most likely to require scrolling) -->
<div id="errorLongContent">
<!-- Long Description -->
<div id="errorLongDesc">%messageLong%</div>

<!-- Short Description -->
<div id="errorShortDesc">
%messageLong%
</div>

</div>

<!-- Retry Button -->
<br/>
<button id="errorTryAgain" onclick="window.location.reload();">%button%</button>
<button id="errorTryAgain" onclick="window.location.reload()">%button%</button>

<!-- Advanced Button -->
<button id="advancedButton" class="buttonSecondary" onclick="toggleAdvanced()" style="display: %advancedSSLStyle%;">Advanced...</button>

<div id="advancedPanelContainer">
<div id="badCertAdvancedPanel" class="advanced-panel" style="display: none;">
<p id="badCertTechnicalInfo">
<label>Someone could be trying to impersonate the site and you should not continue.</label>

<label>Websites prove their identity via certificates. Firefox does not trust <b>%url%</b> because its certificate issuer is unknown, the certificate is self-signed, or the server is not sending the correct intermediate certificates.</label>
</p>
<div id="advancedPanelButtonContainer" class="button-container">
<button id="advancedPanelReturnButton" onClick="window.history.back()" class="button">Go Back (Recommended)</button>
</div>
<div id="advancedPanelButtonContainer" class="button-container">
<button id="button" class="buttonSecondary" onClick="acceptAndContinue(true)">Accept the Risk and Continue</button>
</div>
</div>
</div>
</div>
</body>
</html>

0 comments on commit e9e6260

Please sign in to comment.