From e6a875b7e4e4b179284942878da452a8db8d9b50 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Fri, 26 Feb 2021 14:14:44 +0300 Subject: [PATCH] check if client-presented URL scheme is different from one configured in SELF_URL_PATH --- classes/errors.php | 5 +++-- classes/rpc.php | 13 ++++++++++++- js/App.js | 20 +++++++++++++++----- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/classes/errors.php b/classes/errors.php index be175418e..3599c2639 100644 --- a/classes/errors.php +++ b/classes/errors.php @@ -5,8 +5,9 @@ class Errors { const E_UNKNOWN_METHOD = "E_UNKNOWN_METHOD"; const E_UNKNOWN_PLUGIN = "E_UNKNOWN_PLUGIN"; const E_SCHEMA_MISMATCH = "E_SCHEMA_MISMATCH"; + const E_URL_SCHEME_MISMATCH = "E_URL_SCHEME_MISMATCH"; - static function to_json(string $code) { - return json_encode(["error" => ["code" => $code]]); + static function to_json(string $code, array $params = []) { + return json_encode(["error" => ["code" => $code, "params" => $params]]); } } diff --git a/classes/rpc.php b/classes/rpc.php index aaaf4f8d5..630ea50cb 100755 --- a/classes/rpc.php +++ b/classes/rpc.php @@ -168,10 +168,21 @@ class RPC extends Handler_Protected { $_SESSION["hasSandbox"] = clean($_REQUEST["hasSandbox"]) === "true"; $_SESSION["clientTzOffset"] = clean($_REQUEST["clientTzOffset"]); + $client_location = $_REQUEST["clientLocation"]; + $error = Errors::E_SUCCESS; + $error_params = []; + + $client_scheme = parse_url($client_location, PHP_URL_SCHEME); + $server_scheme = parse_url(get_self_url_prefix(), PHP_URL_SCHEME); if (get_schema_version() != SCHEMA_VERSION) { $error = Errors::E_SCHEMA_MISMATCH; + } else if ($client_scheme != $server_scheme) { + $error = Errors::E_URL_SCHEME_MISMATCH; + $error_params["client_scheme"] = $client_scheme; + $error_params["server_scheme"] = $server_scheme; + $error_params["self_url_path"] = get_self_url_prefix(); } if ($error == Errors::E_SUCCESS) { @@ -183,7 +194,7 @@ class RPC extends Handler_Protected { print json_encode($reply); } else { - print Errors::to_json($error); + print Errors::to_json($error, $error_params); } } diff --git a/js/App.js b/js/App.js index bb8da578d..895483dd7 100644 --- a/js/App.js +++ b/js/App.js @@ -418,7 +418,7 @@ const App = { if (error && error.code && error.code != App.Error.E_SUCCESS) { console.warn("handleRpcJson: fatal error", error); - this.Error.fatal(error.code); + this.Error.fatal(error.code, error.params); return false; } @@ -547,6 +547,7 @@ const App = { E_SUCCESS: "E_SUCCESS", E_UNAUTHORIZED: "E_UNAUTHORIZED", E_SCHEMA_MISMATCH: "E_SCHEMA_MISMATCH", + E_URL_SCHEME_MISMATCH: "E_URL_SCHEME_MISMATCH", fatal: function (error, params = {}) { if (error == App.Error.E_UNAUTHORIZED) { window.location.href = "index.php"; @@ -554,9 +555,14 @@ const App = { } else if (error == App.Error.E_SCHEMA_MISMATCH) { window.location.href = "public.php?op=dbupdate"; return; + } else if (error == App.Error.E_URL_SCHEME_MISMATCH) { + params.description = __("URL scheme reported by your browser (%a) doesn't match server-configured SELF_URL_PATH (%b), check X-Forwarded-Proto.") + .replace("%a", params.client_scheme) + .replace("%b", params.server_scheme); + params.info = `SELF_URL_PATH: ${params.self_url_path}\nCLIENT_LOCATION: ${document.location.href}` } - return this.report(__("Fatal error: %s").replace("%s", error), + return this.report(error, {...{title: __("Fatal error")}, ...params}); }, report: function(error, params = {}) { @@ -587,10 +593,13 @@ const App = {

${message}

-
${__('Stack trace')}
+ ${params.description ? `

${params.description}

` : ''} + + ${error.stack ? + `
${__('Stack trace')}
-
+ ` : ''} ${params && params.info ? ` @@ -650,7 +659,8 @@ const App = { op: "rpc", method: "sanityCheck", clientTzOffset: new Date().getTimezoneOffset() * 60, - hasSandbox: "sandbox" in document.createElement("iframe") + hasSandbox: "sandbox" in document.createElement("iframe"), + clientLocation: window.location.href }; xhr.json("backend.php", params, (reply) => {