* [MOD] Detect hostname and protocol when accesing through reverse proxy. Thanks to @aeimer for contribution.

This commit is contained in:
nuxsmin
2017-09-18 00:26:17 +02:00
parent 21e37e644d
commit 825db82dc2
6 changed files with 101 additions and 111 deletions

View File

@@ -41,6 +41,7 @@ use SP\Log\Log;
use SP\Mgmt\Profiles\Profile;
use SP\Storage\DBUtil;
use SP\Util\Checks;
use SP\Util\HttpUtil;
use SP\Util\Json;
use SP\Util\Util;
use SP\Core\Crypt\Session as CryptSession;
@@ -64,15 +65,10 @@ class Init
*/
public static $WEBROOT = '';
/**
* @var string The sysPass root path for http requests (e.g. syspass/)
*/
public static $WEBURI = '';
/**
* @var string The full URL to reach sysPass (e.g. https://sub.example.com/syspass/)
*/
public static $WEBBASE = '';
public static $WEBURI = '';
/**
* @var bool True if sysPass has been updated. Only for notices.
@@ -168,7 +164,7 @@ class Init
}
// Comprobar si es necesario cambiar a HTTPS
self::checkHttps();
HttpUtil::checkHttps();
// Comprobar si es necesario inicialización
if (self::$checkInitSourceInclude ||
@@ -360,61 +356,16 @@ class Init
self::$WEBROOT = '/' . self::$WEBROOT;
}
self::$WEBBASE = self::retrieveWebBase();
self::$WEBURI .= self::$WEBBASE . self::$WEBROOT;
self::$WEBURI = HttpUtil::getHttpHost() . self::$WEBROOT;
}
private static function retrieveWebBase() {
// Check in style of RFC 7239
$reProto = '/proto=.+(,|$)/i';
$reHost = '/host=.+(,|$)/i';
if (
isset($_SERVER['Forwarded']) &&
preg_match($reProto, $_SERVER['HTTP_FORWARDED'], $matchesProto) &&
preg_match($reHost, $_SERVER['HTTP_FORWARDED'], $matchesHost)
) {
// Removes proto= and host=
$protocol = str_replace('proto=', '', strtolower($matchesProto[0]));
$host = str_replace('host=', '', strtolower($matchesHost[0]));
// Removes possible `"`-chars
$protocol = str_replace('"', '', $protocol);
$host = str_replace('"', '', $host);
// Check if prtocol and host are not empty
if (strlen($protocol) > 0 && strlen($host) > 0) {
return $protocol . '://' . $host;
}
}
// Check (deprecated) de facto standard
if (
isset($_SERVER['HTTP_X_FORWARDED_FOR']) &&
isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
) {
// This only could be http or https
$protocol = str_replace('"', '', trim($_SERVER['HTTP_X_FORWARDED_PROTO']));
// This may be example.com or sub.example.com/syspass
$host = str_replace('"', '', trim($_SERVER['HTTP_X_FORWARDED_FOR']));
// Check if protocol and host are not empty
if (strlen($protocol) > 0 && strlen($host) > 0) {
return $protocol . '://' . $host;
}
}
// We got called directly
$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
return $protocol . $_SERVER['HTTP_HOST'];
}
/**
* Devuelve un error utilizando la plantilla de error o en formato JSON
*
* @param string $message con la descripción del error
* @param string $hint opcional, con una ayuda sobre el error
* @param bool $headers
* @param string $hint opcional, con una ayuda sobre el error
* @param bool $headers
*/
public static function initError($message, $hint = '', $headers = false)
{
@@ -573,18 +524,6 @@ class Init
&& is_object(Session::getUserPreferences()));
}
/**
* Comprobar y forzar (si es necesario) la conexión HTTPS
*/
private static function checkHttps()
{
if (Checks::forceHttpsIsEnabled() && !Checks::httpsEnabled()) {
$port = ((int)$_SERVER['SERVER_PORT'] !== 443) ? ':' . $_SERVER['SERVER_PORT'] : '';
$fullUrl = 'https://' . $_SERVER['SERVER_NAME'] . $port . $_SERVER['REQUEST_URI'];
header('Location: ' . $fullUrl);
}
}
/**
* Comprueba que la aplicación esté instalada
* Esta función comprueba si la aplicación está instalada. Si no lo está, redirige al instalador.

View File

@@ -0,0 +1,91 @@
<?php
/**
* sysPass
*
* @author nuxsmin
* @link http://syspass.org
* @copyright 2012-2017, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Util;
/**
* Class HttpUtil
*
* @package SP\Util
*/
class HttpUtil
{
/**
* Comprobar y forzar (si es necesario) la conexión HTTPS
*/
public static function checkHttps()
{
if (Checks::forceHttpsIsEnabled() && !Checks::httpsEnabled()) {
$port = ((int)$_SERVER['SERVER_PORT'] !== 443) ? ':' . $_SERVER['SERVER_PORT'] : '';
$host = str_replace('http', 'https', self::getHttpHost());
header('Location: ' . $host . $port . $_SERVER['REQUEST_URI']);
}
}
/**
* Returns the URI used by the browser and checks for the protocol used
*
* @see https://tools.ietf.org/html/rfc7239#section-7.5
* @return string
*/
public static function getHttpHost()
{
// Check in style of RFC 7239
if (isset($_SERVER['HTTP_FORWARDED'])
&& preg_match('/proto=(\w+);/i', $_SERVER['HTTP_FORWARDED'], $matchesProto)
&& preg_match('/host=(\w+);/i', $_SERVER['HTTP_FORWARDED'], $matchesHost)
) {
// Removes possible `"`-chars
$protocol = strtolower($matchesProto[0]);
$host = strtolower($matchesHost[0]);
// Check if prtocol and host are not empty
if (strlen($protocol) > 0 && strlen($host) > 0) {
return $protocol . '://' . $host;
}
}
// Check (deprecated) de facto standard
if (isset($_SERVER['HTTP_X_FORWARDED_HOST'], $_SERVER['HTTP_X_FORWARDED_PROTO'])) {
// This only could be http or https
$protocol = str_replace('"', '', trim($_SERVER['HTTP_X_FORWARDED_PROTO']));
// This may be example.com or sub.example.com/syspass
$host = str_replace('"', '', trim($_SERVER['HTTP_X_FORWARDED_HOST']));
// Check if protocol and host are not empty
if (strlen($protocol) > 0 && strlen($host) > 0) {
return $protocol . '://' . $host;
}
}
// We got called directly
if (Checks::httpsEnabled()) {
return 'https://' . $_SERVER['HTTP_HOST'];
}
return 'http://' . $_SERVER['HTTP_HOST'];
}
}

View File

@@ -386,8 +386,8 @@ class Util
*/
public static function getVersion($retBuild = false, $normalized = false)
{
$build = 17090102;
$version = [2, 1, 14];
$build = 17091801;
$version = [2, 1, 15];
if ($normalized === true) {
return [implode('', $version), $build];

View File

@@ -1,40 +0,0 @@
.alertify-log-error {
color: #ecf0f1;
background: #f44336 !important;
background: rgba(244, 67, 54, .9) !important;
border: 1px solid #f44336
}
.alertify-log-success {
color: #ecf0f1;
background: #009688;
background: rgba(0, 150, 136, .9) !important;
border: 1px solid #009688
}
.alertify-button-cancel, .alertify-button-cancel:active, .alertify-button-cancel:focus, .alertify-button-cancel:hover {
color: #fff;
background: #f44336 !important;
background: rgba(244, 67, 54, .7) !important;
}
.alertify-button-cancel:active, .alertify-button-cancel:focus, .alertify-button-cancel:hover {
color: #fff;
background: #f44336 !important;
background: rgba(244, 67, 54, .9) !important;
border-color: #f44336;
}
.alertify-button-ok, .alertify-button-ok:active, .alertify-button-ok:focus, .alertify-button-ok:hover {
color: #fff;
background: #009688;
background: rgba(0, 150, 136, .9) !important;
border-color: #009688;
}
.alertify-button-ok:active, .alertify-button-ok:focus, .alertify-button-ok:hover {
color: #fff;
background: #009688;
background: rgba(0, 150, 136, .7) !important;
border-color: #009688;
}

File diff suppressed because one or more lines are too long

2
js/app-main.min.js vendored
View File

@@ -1,4 +1,4 @@
var $jscomp={scope:{}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(b,f,g){if(g.get||g.set)throw new TypeError("ES3 does not support getters and setters.");b!=Array.prototype&&b!=Object.prototype&&(b[f]=g.value)};$jscomp.getGlobal=function(b){return"undefined"!=typeof window&&window===b?b:"undefined"!=typeof global&&null!=global?global:b};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_";
var $jscomp={scope:{}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(b,f,g){if(g.get||g.set)throw new TypeError("ES3 does not support getters and setters.");b!=Array.prototype&&b!=Object.prototype&&(b[f]=g.value)};$jscomp.getGlobal=function(b){return"undefined"!=typeof window&&window===b?b:"undefined"!=typeof global?global:b};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_";
$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.symbolCounter_=0;$jscomp.Symbol=function(b){return $jscomp.SYMBOL_PREFIX+(b||"")+$jscomp.symbolCounter_++};
$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var b=$jscomp.global.Symbol.iterator;b||(b=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[b]&&$jscomp.defineProperty(Array.prototype,b,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(b){var f=0;return $jscomp.iteratorPrototype(function(){return f<b.length?{done:!1,value:b[f++]}:{done:!0}})};
$jscomp.iteratorPrototype=function(b){$jscomp.initSymbolIterator();b={next:b};b[$jscomp.global.Symbol.iterator]=function(){return this};return b};$jscomp.array=$jscomp.array||{};$jscomp.iteratorFromArray=function(b,f){$jscomp.initSymbolIterator();b instanceof String&&(b+="");var g=0,e={next:function(){if(g<b.length){var l=g++;return{value:f(l,b[l]),done:!1}}e.next=function(){return{done:!0,value:void 0}};return e.next()}};e[Symbol.iterator]=function(){return e};return e};