Skip to content

Commit

Permalink
Add a hack to detect distrust of Let's Encrypt
Browse files Browse the repository at this point in the history
Many older devices do not support the Let's Encrypt CA, for various
reasons.  This causes connection issues for sites using Let's Encrypt to
support HTTPS connections.  This commit adds a hack that can be enabled
with a switch in callbacks.js to try to detect when the user's browser
does not trust the certificate and permit the user to connect to an
insecure endpoint instead.

Unfortunately, the AJAX API does not allow to distinguish between *why*
a request fails, so the best we can do is detect that the HTTPS request
failed, try to make a request over plain HTTP, and if it works, assume
the HTTPS request failed due to a certificate error.  It's not 100%
foolproof since the HTTPS endpoint could just be down for some reason,
but it should work well enough in most cases.

Closes #602
  • Loading branch information
calzoneman committed Jul 17, 2016
1 parent aaa21aa commit 6e416fe
Showing 1 changed file with 71 additions and 11 deletions.
82 changes: 71 additions & 11 deletions www/js/callbacks.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Callbacks = {
return;
$("<div/>")
.addClass("server-msg-disconnect")
.text("Disconnected from server. Attempting reconnection...")
.text("Disconnected from server.")
.appendTo($("#messagebuffer"));
scrollChat();
},
Expand Down Expand Up @@ -1123,29 +1123,89 @@ function ioServerConnect(socketConfig) {
window.socket = io(chosenServer.url, opts);
}

(function () {
if (typeof io === "undefined") {
var script = document.getElementById("socketio-js");
var source = "unknown";
if (script) {
source = script.src;
}
var USING_LETS_ENCRYPT = false;

function initSocketIO(socketConfig) {
function genericConnectionError() {
var message = "The socket.io library could not be loaded from <code>" +
source + "</code>. Ensure that it is not being blocked " +
"by a script blocking extension or firewall and try again.";
makeAlert("Error", message, "alert-danger")
.appendTo($("#announcements"));
Callbacks.disconnect();
}

if (typeof io === "undefined") {
var script = document.getElementById("socketio-js");
var source = "unknown";
if (script) {
source = script.src;
}

if (/^https/.test(source) && location.protocol === "http:"
&& USING_LETS_ENCRYPT) {
checkLetsEncrypt(socketConfig, genericConnectionError);
return;
}

genericConnectionError();
return;
}

ioServerConnect(socketConfig);
setupCallbacks();
}

function checkLetsEncrypt(socketConfig, nonLetsEncryptError) {
var servers = socketConfig.servers.filter(function (server) {
return !server.secure && !server.ipv6Only
});

if (servers.length === 0) {
nonLetsEncryptError();
return;
}

$.ajax({
url: servers[0].url + "/socket.io/socket.io.js",
dataType: "script",
timeout: 10000
}).done(function () {
var message = "Your browser cannot connect securely because it does " +
"not support the newer Let's Encrypt certificate " +
"authority. Click below to acknowledge and continue " +
"connecting over an unencrypted connection. See " +
"<a href=\"https://community.letsencrypt.org/t/which-browsers-and-operating-systems-support-lets-encrypt/4394\" target=\"_blank\">here</a> " +
"for more details.";
var connectionAlert = makeAlert("Error", message, "alert-danger")
.appendTo($("#announcements"));

var button = document.createElement("button");
button.className = "btn btn-default";
button.textContent = "Connect Anyways";

var alertBox = connectionAlert.find(".alert")[0];
alertBox.appendChild(document.createElement("hr"));
alertBox.appendChild(button);

button.onclick = function connectAnyways() {
ioServerConnect({
servers: servers
});
setupCallbacks();
};
}).error(function () {
nonLetsEncryptError();
});
}

(function () {
$.getJSON("/socketconfig/" + CHANNEL.name + ".json")
.done(function (socketConfig) {
ioServerConnect(socketConfig);
setupCallbacks();
initSocketIO(socketConfig);
}).fail(function () {
makeAlert("Error", "Failed to retrieve socket.io configuration",
makeAlert("Error", "Failed to retrieve socket.io configuration. " +
"Please try again in a few minutes.",
"alert-danger")
.appendTo($("#announcements"));
Callbacks.disconnect();
Expand Down

0 comments on commit 6e416fe

Please sign in to comment.