From 1a64deeb894dc95e2645a75771732c6cc53a79ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isma=C3=ABl=20Bouya?= Date: Wed, 4 Oct 2023 01:35:06 +0200 Subject: Squash changes containing private information There were a lot of changes since the previous commit, but a lot of them contained personnal information about users. All thos changes got stashed into a single commit (history is kept in a different place) and private information was moved in a separate private repository --- overlays/shaarli/shaarli_ldap.patch | 425 ------------------------------------ 1 file changed, 425 deletions(-) delete mode 100644 overlays/shaarli/shaarli_ldap.patch (limited to 'overlays/shaarli/shaarli_ldap.patch') diff --git a/overlays/shaarli/shaarli_ldap.patch b/overlays/shaarli/shaarli_ldap.patch deleted file mode 100644 index e66a54f..0000000 --- a/overlays/shaarli/shaarli_ldap.patch +++ /dev/null @@ -1,425 +0,0 @@ -commit a19c24edc1057bd411821f9e3e7d1d309d38b1bb -Author: Ismaël Bouya -Date: Sun Feb 3 20:58:18 2019 +0100 - - Add ldap connection - -diff --git a/.htaccess b/.htaccess -index 4c00427..5acd708 100644 ---- a/.htaccess -+++ b/.htaccess -@@ -6,10 +6,23 @@ RewriteEngine On - # Prevent accessing subdirectories not managed by SCM - RewriteRule ^(.git|doxygen|vendor) - [F] - -+RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$ -+RewriteRule ^(.*) - [E=BASE:%1] -+ -+RewriteCond %{ENV:REDIRECT_BASE} (.+) -+RewriteRule .* - [E=BASE:%1] -+ - # Forward the "Authorization" HTTP header - RewriteCond %{HTTP:Authorization} ^(.*) - RewriteRule .* - [e=HTTP_AUTHORIZATION:%1] - -+RewriteCond %{REQUEST_FILENAME} !-f -+RewriteCond %{REQUEST_FILENAME} !-d -+RewriteRule ^((?!api/)[^/]*)/?(.*)$ $2?%{QUERY_STRING} [E=USERSPACE:$1] -+ -+RewriteCond %{ENV:REDIRECT_USERSPACE} (.+) -+RewriteRule .* - [E=USERSPACE:%1] -+ - # REST API - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d -diff --git a/application/ApplicationUtils.php b/application/ApplicationUtils.php -index 911873a..f21a1ef 100644 ---- a/application/ApplicationUtils.php -+++ b/application/ApplicationUtils.php -@@ -191,6 +191,9 @@ public static function checkResourcePermissions($conf) - $conf->get('resource.page_cache'), - $conf->get('resource.raintpl_tmp'), - ) as $path) { -+ if (! is_dir($path)) { -+ mkdir($path, 0755, true); -+ } - if (! is_readable(realpath($path))) { - $errors[] = '"'.$path.'" '. t('directory is not readable'); - } -diff --git a/application/config/ConfigManager.php b/application/config/ConfigManager.php -index 32aaea4..99efc15 100644 ---- a/application/config/ConfigManager.php -+++ b/application/config/ConfigManager.php -@@ -21,6 +21,11 @@ class ConfigManager - - public static $DEFAULT_PLUGINS = array('qrcode'); - -+ /** -+ * @var string User space. -+ */ -+ protected $userSpace; -+ - /** - * @var string Config folder. - */ -@@ -41,12 +46,36 @@ class ConfigManager - * - * @param string $configFile Configuration file path without extension. - */ -- public function __construct($configFile = 'data/config') -+ public function __construct($configFile = null, $userSpace = null) - { -- $this->configFile = $configFile; -+ $this->userSpace = $this->findLDAPUser($userSpace); -+ if ($configFile !== null) { -+ $this->configFile = $configFile; -+ } else { -+ $this->configFile = ($this->userSpace === null) ? 'data/config' : 'data/' . $this->userSpace . '/config'; -+ } - $this->initialize(); - } - -+ public function findLDAPUser($login, $password = null) { -+ $connect = ldap_connect(getenv('SHAARLI_LDAP_HOST')); -+ ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3); -+ if (!$connect || !ldap_bind($connect, getenv('SHAARLI_LDAP_DN'), getenv('SHAARLI_LDAP_PASSWORD'))) { -+ return false; -+ } -+ -+ $search_query = str_replace('%login%', ldap_escape($login), getenv('SHAARLI_LDAP_FILTER')); -+ -+ $search = ldap_search($connect, getenv('SHAARLI_LDAP_BASE'), $search_query); -+ $info = ldap_get_entries($connect, $search); -+ -+ if (ldap_count_entries($connect, $search) == 1 && (is_null($password) || ldap_bind($connect, $info[0]["dn"], $password))) { -+ return $login; -+ } else { -+ return null; -+ } -+ } -+ - /** - * Reset the ConfigManager instance. - */ -@@ -269,6 +298,16 @@ public function getConfigFileExt() - return $this->configFile . $this->configIO->getExtension(); - } - -+ /** -+ * Get the current userspace. -+ * -+ * @return mixed User space. -+ */ -+ public function getUserSpace() -+ { -+ return $this->userSpace; -+ } -+ - /** - * Recursive function which find asked setting in the loaded config. - * -@@ -342,19 +381,31 @@ protected static function removeConfig($settings, &$conf) - */ - protected function setDefaultValues() - { -- $this->setEmpty('resource.data_dir', 'data'); -- $this->setEmpty('resource.config', 'data/config.php'); -- $this->setEmpty('resource.datastore', 'data/datastore.php'); -- $this->setEmpty('resource.ban_file', 'data/ipbans.php'); -- $this->setEmpty('resource.updates', 'data/updates.txt'); -- $this->setEmpty('resource.log', 'data/log.txt'); -- $this->setEmpty('resource.update_check', 'data/lastupdatecheck.txt'); -- $this->setEmpty('resource.history', 'data/history.php'); -+ if ($this->userSpace === null) { -+ $data = 'data'; -+ $tmp = 'tmp'; -+ $cache = 'cache'; -+ $pagecache = 'pagecache'; -+ } else { -+ $data = 'data/' . ($this->userSpace); -+ $tmp = 'tmp/' . ($this->userSpace); -+ $cache = 'cache/' . ($this->userSpace); -+ $pagecache = 'pagecache/' . ($this->userSpace); -+ } -+ -+ $this->setEmpty('resource.data_dir', $data); -+ $this->setEmpty('resource.config', $data . '/config.php'); -+ $this->setEmpty('resource.datastore', $data . '/datastore.php'); -+ $this->setEmpty('resource.ban_file', $data . '/ipbans.php'); -+ $this->setEmpty('resource.updates', $data . '/updates.txt'); -+ $this->setEmpty('resource.log', $data . '/log.txt'); -+ $this->setEmpty('resource.update_check', $data . '/lastupdatecheck.txt'); -+ $this->setEmpty('resource.history', $data . '/history.php'); - $this->setEmpty('resource.raintpl_tpl', 'tpl/'); - $this->setEmpty('resource.theme', 'default'); -- $this->setEmpty('resource.raintpl_tmp', 'tmp/'); -- $this->setEmpty('resource.thumbnails_cache', 'cache'); -- $this->setEmpty('resource.page_cache', 'pagecache'); -+ $this->setEmpty('resource.raintpl_tmp', $tmp); -+ $this->setEmpty('resource.thumbnails_cache', $cache); -+ $this->setEmpty('resource.page_cache', $pagecache); - - $this->setEmpty('security.ban_after', 4); - $this->setEmpty('security.ban_duration', 1800); -diff --git a/application/security/LoginManager.php b/application/security/LoginManager.php -index d6784d6..bdfaca7 100644 ---- a/application/security/LoginManager.php -+++ b/application/security/LoginManager.php -@@ -32,6 +32,9 @@ class LoginManager - /** @var string User sign-in token depending on remote IP and credentials */ - protected $staySignedInToken = ''; - -+ protected $lastErrorReason = ''; -+ protected $lastErrorIsBanishable = false; -+ - /** - * Constructor - * -@@ -83,7 +86,7 @@ public function getStaySignedInToken() - */ - public function checkLoginState($cookie, $clientIpId) - { -- if (! $this->configManager->exists('credentials.login')) { -+ if (! $this->configManager->exists('credentials.login') || (isset($_SESSION['username']) && $_SESSION['username'] && $this->configManager->get('credentials.login') !== $_SESSION['username'])) { - // Shaarli is not configured yet - $this->isLoggedIn = false; - return; -@@ -133,20 +136,40 @@ public function isLoggedIn() - */ - public function checkCredentials($remoteIp, $clientIpId, $login, $password) - { -- $hash = sha1($password . $login . $this->configManager->get('credentials.salt')); -+ $this->lastErrorIsBanishable = false; -+ -+ if ($this->configManager->getUserSpace() !== null && $this->configManager->getUserSpace() !== $login) { -+ logm($this->configManager->get('resource.log'), -+ $remoteIp, -+ 'Trying to login to wrong user space'); -+ $this->lastErrorReason = 'You’re trying to access the wrong account.'; -+ return false; -+ } - -- if ($login != $this->configManager->get('credentials.login') -- || $hash != $this->configManager->get('credentials.hash') -- ) { -+ logm($this->configManager->get('resource.log'), -+ $remoteIp, -+ 'Trying LDAP connection'); -+ $result = $this->configManager->findLDAPUser($login, $password); -+ if ($result === false) { - logm( - $this->configManager->get('resource.log'), - $remoteIp, -- 'Login failed for user ' . $login -+ 'Impossible to connect to LDAP' - ); -+ $this->lastErrorReason = 'Server error.'; -+ return false; -+ } else if (is_null($result)) { -+ logm( -+ $this->configManager->get('resource.log'), -+ $remoteIp, -+ 'Login failed for user ' . $login -+ ); -+ $this->lastErrorIsBanishable = true; -+ $this->lastErrorReason = 'Wrong login/password.'; - return false; - } - -- $this->sessionManager->storeLoginInfo($clientIpId); -+ $this->sessionManager->storeLoginInfo($clientIpId, $login); - logm( - $this->configManager->get('resource.log'), - $remoteIp, -@@ -187,6 +210,10 @@ protected function writeBanFile() - */ - public function handleFailedLogin($server) - { -+ if (!$this->lastErrorIsBanishable) { -+ return $this->lastErrorReason ?: 'Error during login.'; -+ }; -+ - $ip = $server['REMOTE_ADDR']; - $trusted = $this->configManager->get('security.trusted_proxies', []); - -@@ -215,6 +242,7 @@ public function handleFailedLogin($server) - ); - } - $this->writeBanFile(); -+ return $this->lastErrorReason ?: 'Error during login.'; - } - - /** -diff --git a/application/security/SessionManager.php b/application/security/SessionManager.php -index b8b8ab8..5eb4aac 100644 ---- a/application/security/SessionManager.php -+++ b/application/security/SessionManager.php -@@ -111,10 +111,10 @@ public static function checkId($sessionId) - * - * @param string $clientIpId Client IP address identifier - */ -- public function storeLoginInfo($clientIpId) -+ public function storeLoginInfo($clientIpId, $login = null) - { - $this->session['ip'] = $clientIpId; -- $this->session['username'] = $this->conf->get('credentials.login'); -+ $this->session['username'] = $login ?: $this->conf->get('credentials.login'); - $this->extendTimeValidityBy(self::$SHORT_TIMEOUT); - } - -diff --git a/index.php b/index.php -index 4b86a3e..58ae2dd 100644 ---- a/index.php -+++ b/index.php -@@ -121,7 +121,32 @@ - $_COOKIE['shaarli'] = session_id(); - } - --$conf = new ConfigManager(); -+$folderBase = getenv("BASE"); -+ -+if (getenv("USERSPACE")) { -+ if (isset($_GET["do"]) && $_GET["do"] == "login") { -+ header("Location: $folderBase/?do=login"); -+ exit; -+ } -+ $userspace = preg_replace("/[^-_A-Za-z0-9]/", '', getenv("USERSPACE")); -+} else if (isset($_SESSION["username"]) && $_SESSION["username"]) { -+ header("Location: " . $folderBase . "/" . $_SESSION["username"] . "?"); -+ exit; -+} else if (!isset($_GET["do"]) || $_GET["do"] != "login") { -+ header("Location: $folderBase/?do=login"); -+ exit; -+} -+ -+if (!isset($userspace) && isset($_POST["login"])) { -+ $userspace = preg_replace("/[^-_A-Za-z0-9]/", '', $_POST["login"]); -+ error_log("debugImmae: setting userspace from POST: " . $userspace); -+} -+ -+if (isset($userspace)) { -+ $conf = new ConfigManager(null, $userspace); -+} else { -+ $conf = new ConfigManager(); -+} - $sessionManager = new SessionManager($_SESSION, $conf); - $loginManager = new LoginManager($GLOBALS, $conf, $sessionManager); - $loginManager->generateStaySignedInToken($_SERVER['REMOTE_ADDR']); -@@ -175,7 +200,7 @@ - } - - // Display the installation form if no existing config is found -- install($conf, $sessionManager, $loginManager); -+ install($conf, $sessionManager, $loginManager, $userspace); - } - - $loginManager->checkLoginState($_COOKIE, $clientIpId); -@@ -205,6 +230,7 @@ function isLoggedIn() - && $loginManager->checkCredentials($_SERVER['REMOTE_ADDR'], $clientIpId, $_POST['login'], $_POST['password']) - ) { - $loginManager->handleSuccessfulLogin($_SERVER); -+ $userspace = $_POST['login']; - - $cookiedir = ''; - if (dirname($_SERVER['SCRIPT_NAME']) != '/') { -@@ -241,25 +267,25 @@ function isLoggedIn() - $uri .= '&'.$param.'='.urlencode($_GET[$param]); - } - } -- header('Location: '. $uri); -+ header('Location: '. $userspace . $uri); - exit; - } - - if (isset($_GET['edit_link'])) { -- header('Location: ?edit_link='. escape($_GET['edit_link'])); -+ header('Location: ' . $userspace . '?edit_link='. escape($_GET['edit_link'])); - exit; - } - - if (isset($_POST['returnurl'])) { - // Prevent loops over login screen. - if (strpos($_POST['returnurl'], 'do=login') === false) { -- header('Location: '. generateLocation($_POST['returnurl'], $_SERVER['HTTP_HOST'])); -+ header('Location: ' . generateLocation($_POST['returnurl'], $_SERVER['HTTP_HOST'])); - exit; - } - } -- header('Location: ?'); exit; -+ header('Location: '. $userspace . '?'); exit; - } else { -- $loginManager->handleFailedLogin($_SERVER); -+ $errorReason = $loginManager->handleFailedLogin($_SERVER); - $redir = '&username='. urlencode($_POST['login']); - if (isset($_GET['post'])) { - $redir .= '&post=' . urlencode($_GET['post']); -@@ -270,7 +296,7 @@ function isLoggedIn() - } - } - // Redirect to login screen. -- echo ''; -+ echo ''; - exit; - } - } -@@ -1719,7 +1745,7 @@ function buildLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager) - * @param SessionManager $sessionManager SessionManager instance - * @param LoginManager $loginManager LoginManager instance - */ --function install($conf, $sessionManager, $loginManager) { -+function install($conf, $sessionManager, $loginManager, $userspace) { - // On free.fr host, make sure the /sessions directory exists, otherwise login will not work. - if (endsWith($_SERVER['HTTP_HOST'],'.free.fr') && !is_dir($_SERVER['DOCUMENT_ROOT'].'/sessions')) mkdir($_SERVER['DOCUMENT_ROOT'].'/sessions',0705); - -@@ -1755,7 +1781,7 @@ function install($conf, $sessionManager, $loginManager) { - } - - -- if (!empty($_POST['setlogin']) && !empty($_POST['setpassword'])) -+ if (true) - { - $tz = 'UTC'; - if (!empty($_POST['continent']) && !empty($_POST['city']) -@@ -1764,15 +1790,15 @@ function install($conf, $sessionManager, $loginManager) { - $tz = $_POST['continent'].'/'.$_POST['city']; - } - $conf->set('general.timezone', $tz); -- $login = $_POST['setlogin']; -- $conf->set('credentials.login', $login); -+ $conf->set('credentials.login', $userspace); - $salt = sha1(uniqid('', true) .'_'. mt_rand()); - $conf->set('credentials.salt', $salt); -- $conf->set('credentials.hash', sha1($_POST['setpassword'] . $login . $salt)); -+ $hash = sha1(uniqid('', true) .'_'. mt_rand()); -+ $conf->set('credentials.hash', $hash); - if (!empty($_POST['title'])) { - $conf->set('general.title', escape($_POST['title'])); - } else { -- $conf->set('general.title', 'Shared links on '.escape(index_url($_SERVER))); -+ $conf->set('general.title', ucwords(str_replace("_", " ", $userspace))); - } - $conf->set('translation.language', escape($_POST['language'])); - $conf->set('updates.check_updates', !empty($_POST['updateCheck'])); -@@ -1841,7 +1867,12 @@ function install($conf, $sessionManager, $loginManager) { - $app = new \Slim\App($container); - - // REST API routes --$app->group('/api/v1', function() { -+if (isset($userspace)) { -+ $mountpoint = '/' . $userspace . '/api/v1'; -+} else { -+ $mountpoint = '/api/v1'; -+} -+$app->group($mountpoint, function() { - $this->get('/info', '\Shaarli\Api\Controllers\Info:getInfo')->setName('getInfo'); - $this->get('/links', '\Shaarli\Api\Controllers\Links:getLinks')->setName('getLinks'); - $this->get('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:getLink')->setName('getLink'); -@@ -1860,7 +1891,7 @@ function install($conf, $sessionManager, $loginManager) { - $response = $app->run(true); - // Hack to make Slim and Shaarli router work together: - // If a Slim route isn't found and NOT API call, we call renderPage(). --if ($response->getStatusCode() == 404 && strpos($_SERVER['REQUEST_URI'], '/api/v1') === false) { -+if ($response->getStatusCode() == 404 && strpos($_SERVER['REQUEST_URI'], $mountpoint) === false) { - // We use UTF-8 for proper international characters handling. - header('Content-Type: text/html; charset=utf-8'); - renderPage($conf, $pluginManager, $linkDb, $history, $sessionManager, $loginManager); -- cgit v1.2.3