From aa37fa8b4c36f7b8a60c41b994f909c033e2e625 Mon Sep 17 00:00:00 2001 From: nilsteampassnet Date: Mon, 25 Nov 2024 20:36:20 +0100 Subject: [PATCH 1/5] WIP fix installation process --- includes/config/include.php | 2 +- install/install.queries.php | 44 ++++++++++++++++++++++++------------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/includes/config/include.php b/includes/config/include.php index 7bb2d84a7..f22b8c133 100755 --- a/includes/config/include.php +++ b/includes/config/include.php @@ -28,7 +28,7 @@ define('TP_VERSION', '3.1.2'); define("UPGRADE_MIN_DATE", "1732264740"); -define('TP_VERSION_MINOR', '167'); +define('TP_VERSION_MINOR', '168'); define('TP_TOOL_NAME', 'Teampass'); define('TP_ONE_DAY_SECONDS', 86400); define('TP_ONE_WEEK_SECONDS', 604800); diff --git a/install/install.queries.php b/install/install.queries.php index 5c9e2d843..c518aafad 100755 --- a/install/install.queries.php +++ b/install/install.queries.php @@ -25,6 +25,7 @@ * @license GPL-3.0 * @see https://www.teampass.net */ +require '../vendor/autoload.php'; use TiBeN\CrontabManager\CrontabJob; use TiBeN\CrontabManager\CrontabAdapter; use TiBeN\CrontabManager\CrontabRepository; @@ -53,9 +54,28 @@ } } +include_once '../includes/config/settings.php'; + +// +if (defined('SECUREPATH') === false || defined('SECUREFILE') === false) { + define('SECUREFILE', generateRandomKey()); + define('SECUREPATH', __DIR__.'/../includes/config'); + + // 1- generate saltkey + $key = Key::createNewRandomKey(); + $new_salt = $key->saveToAsciiSafeString(); + + // 2- store key in file + file_put_contents( + SECUREPATH.'/'.SECUREFILE, + $new_salt + ); +} + // Load functions require_once __DIR__.'/../sources/main.functions.php'; + // init loadClasses('DB'); $session = SessionManager::getSession(); @@ -1429,10 +1449,8 @@ function encryptFollowingDefuse($message, $ascii_key) if ($inputData['activity'] === 'file') { if ($inputData['task'] === 'settings.php') { // first is to create teampass-seckey.txt - // 0- check if exists - $filesecure = generateRandomKey(); - define('SECUREFILE', $filesecure); - $filename_seckey = $securePath . '/' . $filesecure; + // MOVE FILE TO DESTINATION PATH + $filename_seckey = $securePath . '/' . SECUREFILE; if (file_exists($filename_seckey)) { if (!copy($filename_seckey, $filename_seckey . '.' . date('Y_m_d', mktime(0, 0, 0, (int) date('m'), (int) date('d'), (int) date('y'))))) { @@ -1441,18 +1459,14 @@ function encryptFollowingDefuse($message, $ascii_key) } else { unlink($filename); } + } else { + // Move file + if (!copy(__DIR__.'/../includes/config/'.SECUREFILE, $filename_seckey)) { + echo '[{"error" : "File `'.__DIR__.'/../includes/config/'.SECUREFILE.'` could not be copied to `'.$filename_seckey.'`. Please check the path and the rights", "result":"", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; + break; + } } - // 1- generate saltkey - $key = Key::createNewRandomKey(); - $new_salt = $key->saveToAsciiSafeString(); - - // 2- store key in file - file_put_contents( - $filename_seckey, - $new_salt - ); - // Now create settings file $filename = '../includes/config/settings.php'; @@ -1498,7 +1512,7 @@ function encryptFollowingDefuse($message, $ascii_key) MYSQLI_OPT_CONNECT_TIMEOUT => 10 )); define("SECUREPATH", "' . $securePath . '"); -define("SECUREFILE", "' . $filesecure. '"); +define("SECUREFILE", "' . SECUREFILE. '"); if (isset($_SESSION[\'settings\'][\'timezone\']) === true) { date_default_timezone_set($_SESSION[\'settings\'][\'timezone\']); From b7ad2801aa4f60d78cfcb6cdd33abb9719f909bd Mon Sep 17 00:00:00 2001 From: nilsteampassnet Date: Mon, 25 Nov 2024 21:05:55 +0100 Subject: [PATCH 2/5] Reworked the way SECUREPATH and SECUREFILE are generated and added s=to settings.php --- includes/config/include.php | 2 +- includes/config/settings.sample.php | 2 -- install/install.queries.php | 19 ++++++++++++++++--- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/includes/config/include.php b/includes/config/include.php index f22b8c133..4a4d6ce69 100755 --- a/includes/config/include.php +++ b/includes/config/include.php @@ -28,7 +28,7 @@ define('TP_VERSION', '3.1.2'); define("UPGRADE_MIN_DATE", "1732264740"); -define('TP_VERSION_MINOR', '168'); +define('TP_VERSION_MINOR', '169'); define('TP_TOOL_NAME', 'Teampass'); define('TP_ONE_DAY_SECONDS', 86400); define('TP_ONE_WEEK_SECONDS', 604800); diff --git a/includes/config/settings.sample.php b/includes/config/settings.sample.php index 940f5cf3d..742852bc7 100755 --- a/includes/config/settings.sample.php +++ b/includes/config/settings.sample.php @@ -19,8 +19,6 @@ define("DB_CONNECT_OPTIONS", array( MYSQLI_OPT_CONNECT_TIMEOUT => 10 )); -define("SECUREPATH", ""); -define("SECUREFILE", ""); define("IKEY", ""); define("SKEY", ""); define("HOST", ""); diff --git a/install/install.queries.php b/install/install.queries.php index c518aafad..5468fa465 100755 --- a/install/install.queries.php +++ b/install/install.queries.php @@ -54,12 +54,18 @@ } } + +// Load settings include_once '../includes/config/settings.php'; -// -if (defined('SECUREPATH') === false || defined('SECUREFILE') === false) { - define('SECUREFILE', generateRandomKey()); +// Check if SECUREPATH and SECUREFILE are defined +if (defined('SECUREPATH') === false) { define('SECUREPATH', __DIR__.'/../includes/config'); + error_log("TEST1"); +} +if (defined('SECUREFILE') === false) { + define('SECUREFILE', generateRandomKey()); + error_log("TEST2"); // 1- generate saltkey $key = Key::createNewRandomKey(); @@ -70,6 +76,13 @@ SECUREPATH.'/'.SECUREFILE, $new_salt ); + + //3 - add to settings + $newLine = ' +define("SECUREPATH", "' . SECUREPATH. '"); +define("SECUREFILE", "' . SECUREFILE. '"); +'; + file_put_contents('../includes/config/settings.php', $newLine, FILE_APPEND); } // Load functions From 9441c8dab84edca7855008af5e057740221c43d4 Mon Sep 17 00:00:00 2001 From: nilsteampassnet Date: Wed, 27 Nov 2024 08:31:19 +0100 Subject: [PATCH 3/5] Changed the way to initialize SECUREPATH et SECUREFILE Handled issue with session encrypted. TODO: install steps check --- includes/config/include.php | 2 +- install/install.queries.php | 160 ++++++++++++++++-------------------- 2 files changed, 73 insertions(+), 89 deletions(-) diff --git a/includes/config/include.php b/includes/config/include.php index 4a4d6ce69..a6c039116 100755 --- a/includes/config/include.php +++ b/includes/config/include.php @@ -28,7 +28,7 @@ define('TP_VERSION', '3.1.2'); define("UPGRADE_MIN_DATE", "1732264740"); -define('TP_VERSION_MINOR', '169'); +define('TP_VERSION_MINOR', '170'); define('TP_TOOL_NAME', 'Teampass'); define('TP_ONE_DAY_SECONDS', 86400); define('TP_ONE_WEEK_SECONDS', 604800); diff --git a/install/install.queries.php b/install/install.queries.php index 5468fa465..d4322fa18 100755 --- a/install/install.queries.php +++ b/install/install.queries.php @@ -85,6 +85,11 @@ file_put_contents('../includes/config/settings.php', $newLine, FILE_APPEND); } +if (session_status() === PHP_SESSION_ACTIVE) { + session_unset(); + session_destroy(); +} + // Load functions require_once __DIR__.'/../sources/main.functions.php'; @@ -218,26 +223,54 @@ function encryptFollowingDefuse($message, $ascii_key) $session_abspath ); +// Prepare variables +$session_abspath = rtrim($inputData['data']['absolute_path'], '/'); +$session_url_path = rtrim($inputData['data']['url_path'], '/'); +$session_sk_path = rtrim($inputData['data']['sk_path'], '/'); + if (null !== $inputData['type']) { switch ($inputData['type']) { - case 'step_2': - $abspath = str_replace('\\', '/', $inputData['data']['absolute_path']); - if (substr($abspath, strlen($abspath) - 1) == '/') { - $abspath = substr($abspath, 0, strlen($abspath) - 1); - } - $session_abspath = $abspath; - $session_url_path = $inputData['data']['url_path']; - + case 'step_2': + // Check FOLDERS if (isset($inputData['activity']) && $inputData['activity'] === 'folder') { - $targetPath = $abspath . '/' . $inputData['task'] . '/'; - if (is_writable($targetPath) === true) { + // Handle specific case of "secure path" + if ($inputData['task'] === 'secure') { + // Is SK path a folder? + if (!is_dir($session_sk_path)) { + echo '[{"error" : " Path ' . $session_sk_path . ' is not a folder!", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; + break; + } + + // Is SK path writable? + if (is_writable($session_sk_path) === false) { + echo '[{"error" : " Path ' . $session_sk_path . ' is not writable!", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; + break; + } + + // Handle the SK file to correct folder + $filename_seckey = $session_sk_path . '/' . SECUREFILE; + + if (!file_exists($filename_seckey)) { + // Move file + if (!copy(__DIR__.'/../includes/config/'.SECUREFILE, $filename_seckey)) { + echo '[{"error" : "File `'.__DIR__.'/../includes/config/'.SECUREFILE.'` could not be copied to `'.$filename_seckey.'`. Please check the path and the rights", "result":"", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; + break; + } + } echo '[{"error" : "", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; } else { - echo '[{"error" : " Path ' . $targetPath . ' is not writable!", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; + $targetPath = $session_abspath . '/' . $inputData['task'] . '/'; + error_log("PATH: ".$targetPath); + if (is_writable($targetPath) === true) { + echo '[{"error" : "", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; + } else { + echo '[{"error" : " Path ' . $targetPath . ' is not writable!", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; + } } break; } + // Check EXTENSIONS if (isset($inputData['activity']) && $inputData['activity'] === 'extension') { if (extension_loaded($inputData['task'])) { echo '[{"error" : "", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; @@ -247,6 +280,7 @@ function encryptFollowingDefuse($message, $ascii_key) break; } + // Check FUNCTION if (isset($inputData['activity']) && $inputData['activity'] === 'function') { if (function_exists($inputData['task'])) { echo '[{"error" : "", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; @@ -256,6 +290,7 @@ function encryptFollowingDefuse($message, $ascii_key) break; } + // Check VERSIONS if (isset($inputData['activity']) && $inputData['activity'] === 'version') { if (version_compare(phpversion(), MIN_PHP_VERSION, '>=')) { echo '[{"error" : "", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; @@ -265,6 +300,7 @@ function encryptFollowingDefuse($message, $ascii_key) break; } + // Check INI if (isset($inputData['activity']) && $inputData['activity'] === 'ini') { if (ini_get($inputData['task']) >= 30) { echo '[{"error" : "", "index" : "' . $inputData['index'] . '"}]'; @@ -276,12 +312,7 @@ function encryptFollowingDefuse($message, $ascii_key) break; - case 'step_3': - $post_abspath = str_replace('\\', '/', $inputData['data']['absolute_path']); - if (substr($abspath, strlen($post_abspath) - 1) == '/') { - $post_abspath = substr($post_abspath, 0, strlen($post_abspath) - 1); - } - + case 'step_3': // launch try { $dbTmp = mysqli_connect( @@ -323,17 +354,14 @@ function encryptFollowingDefuse($message, $ascii_key) } // For other queries with `url_path` and `absolute_path` - $escapedUrlPath = mysqli_real_escape_string($dbTmp, empty($post_urlpath) ? $inputData['db']['url_path'] : $post_urlpath); - $escapedAbsPath = mysqli_real_escape_string($dbTmp, empty($post_abspath) ? $inputData['data']['absolute_path'] : $post_abspath); - $tmp = mysqli_num_rows(mysqli_query($dbTmp, "SELECT * FROM `_install` WHERE `key` = 'url_path'")); if (intval($tmp) === 0) { - mysqli_query($dbTmp, "INSERT INTO `_install` (`key`, `value`) VALUES ('url_path', '" . $escapedUrlPath . "');"); + mysqli_query($dbTmp, "INSERT INTO `_install` (`key`, `value`) VALUES ('url_path', '" . $session_url_path . "');"); } $tmp = mysqli_num_rows(mysqli_query($dbTmp, "SELECT * FROM `_install` WHERE `key` = 'absolute_path'")); if (intval($tmp) === 0) { - mysqli_query($dbTmp, "INSERT INTO `_install` (`key`, `value`) VALUES ('absolute_path', '" . $escapedAbsPath . "');"); + mysqli_query($dbTmp, "INSERT INTO `_install` (`key`, `value`) VALUES ('absolute_path', '" . $session_abspath . "');"); } echo '[{"error" : "", "result" : "Connection is successful", "multiple" : ""}]'; @@ -344,14 +372,7 @@ function encryptFollowingDefuse($message, $ascii_key) break; case 'step_4': - $dbTmp = mysqli_connect( - $inputData['db']['db_host'], - $inputData['db']['db_login'], - $inputData['db']['db_pw'], - $inputData['db']['db_bdd'], - $inputData['db']['db_port'] - ); - + // prepare data foreach ($inputData['data'] as $key => $value) { $escapedKey = mysqli_real_escape_string($dbTmp, $key); @@ -359,40 +380,25 @@ function encryptFollowingDefuse($message, $ascii_key) $inputData['data'][$escapedKey] = $escapedValue; } - // check skpath - if (empty($inputData['data']['sk_path'])) { - $inputData['data']['sk_path'] = $session_abspath . '/includes'; - } else { - $inputData['data']['sk_path'] = str_replace('\', '/', $inputData['data']['sk_path']); - } - if (substr($inputData['data']['sk_path'], strlen($inputData['data']['sk_path']) - 1) == '/' || substr($inputData['data']['sk_path'], strlen($inputData['data']['sk_path']) - 1) == '"') { - $inputData['data']['sk_path'] = substr($inputData['data']['sk_path'], 0, strlen($inputData['data']['sk_path']) - 1); - } - if (is_dir($inputData['data']['sk_path'])) { - if (is_writable($inputData['data']['sk_path'])) { - // store all variables in SESSION - foreach ($inputData['data'] as $key => $value) { - $superGlobal->put($key, $value, 'SESSION'); - - // Use mysqli_real_escape_string to escape keys and values - $escapedKey = mysqli_real_escape_string($dbTmp, $key); - $escapedValue = mysqli_real_escape_string($dbTmp, $value); + // store all variables in SESSION + foreach ($inputData['data'] as $key => $value) { + $superGlobal->put($key, $value, 'SESSION'); + + // Use mysqli_real_escape_string to escape keys and values + $escapedKey = mysqli_real_escape_string($dbTmp, $key); + $escapedValue = mysqli_real_escape_string($dbTmp, $value); - $tmp = mysqli_num_rows(mysqli_query($dbTmp, "SELECT * FROM `_install` WHERE `key` = '" . $escapedKey . "'")); - if (intval($tmp) === 0) { - mysqli_query($dbTmp, "INSERT INTO `_install` (`key`, `value`) VALUES ('" . $escapedKey . "', '" . $escapedValue . "');"); - } else { - mysqli_query($dbTmp, "UPDATE `_install` SET `value` = '" . $escapedValue . "' WHERE `key` = '" . $escapedKey . "';"); - } - } - echo '[{"error" : "", "result" : "Information stored", "multiple" : ""}]'; + $tmp = mysqli_num_rows(mysqli_query($dbTmp, "SELECT * FROM `_install` WHERE `key` = '" . $escapedKey . "'")); + if (intval($tmp) === 0) { + mysqli_query($dbTmp, "INSERT INTO `_install` (`key`, `value`) VALUES ('" . $escapedKey . "', '" . $escapedValue . "');"); } else { - echo '[{"error" : "The Directory must be writable!", "result" : "Information stored", "multiple" : ""}]'; + mysqli_query($dbTmp, "UPDATE `_install` SET `value` = '" . $escapedValue . "' WHERE `key` = '" . $escapedKey . "';"); } - } else { - echo '[{"error" : "' . $inputData['data']['sk_path'] . ' is not a Directory!", "result" : "Information stored", "multiple" : ""}]'; } mysqli_close($dbTmp); + + echo '[{"error" : "", "result" : "Information stored", "multiple" : ""}]'; + break; case 'step_5': @@ -1449,37 +1455,10 @@ function encryptFollowingDefuse($message, $ascii_key) } // launch - if (empty($var['sk_path'])) { - $securePath = $var['absolute_path']; - } else { - //ensure $var['sk_path'] has no trailing slash - $var['sk_path'] = rtrim(str_replace('\/', '//', $var['sk_path']), '/\\'); - $securePath = $var['sk_path']; - } - $events = ''; if ($inputData['activity'] === 'file') { if ($inputData['task'] === 'settings.php') { - // first is to create teampass-seckey.txt - // MOVE FILE TO DESTINATION PATH - $filename_seckey = $securePath . '/' . SECUREFILE; - - if (file_exists($filename_seckey)) { - if (!copy($filename_seckey, $filename_seckey . '.' . date('Y_m_d', mktime(0, 0, 0, (int) date('m'), (int) date('d'), (int) date('y'))))) { - echo '[{"error" : "File `'.$filename_seckey.'` already exists and cannot be renamed. Please do it by yourself and click on button Launch.", "result":"", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; - break; - } else { - unlink($filename); - } - } else { - // Move file - if (!copy(__DIR__.'/../includes/config/'.SECUREFILE, $filename_seckey)) { - echo '[{"error" : "File `'.__DIR__.'/../includes/config/'.SECUREFILE.'` could not be copied to `'.$filename_seckey.'`. Please check the path and the rights", "result":"", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; - break; - } - } - // Now create settings file $filename = '../includes/config/settings.php'; @@ -1491,7 +1470,12 @@ function encryptFollowingDefuse($message, $ascii_key) unlink($filename); } } - //echo ">". $inputData['db']['db_pw']." -- ".$new_salt." ;; "; + + // + if (file_exists(__DIR__.'/../includes/config/'.SECUREFILE)) { + unlink(__DIR__.'/../includes/config/'.SECUREFILE); + } + // Encrypt the DB password $encrypted_text = encryptFollowingDefuse( $inputData['db']['db_pw'], @@ -1524,7 +1508,7 @@ function encryptFollowingDefuse($message, $ascii_key) define("DB_CONNECT_OPTIONS", array( MYSQLI_OPT_CONNECT_TIMEOUT => 10 )); -define("SECUREPATH", "' . $securePath . '"); +define("SECUREPATH", "' . $session_sk_path . '"); define("SECUREFILE", "' . SECUREFILE. '"); if (isset($_SESSION[\'settings\'][\'timezone\']) === true) { From 99eb56042f788be8bfd4bc5d1153334ddf261915 Mon Sep 17 00:00:00 2001 From: nilsteampassnet Date: Thu, 28 Nov 2024 22:30:21 +0100 Subject: [PATCH 4/5] Fixed the installation from scratch. --- includes/config/include.php | 2 +- install/install.js | 66 ++++++++------ install/install.php | 38 ++++++-- install/install.queries.php | 172 +++++++++++++++++++++++++----------- 4 files changed, 188 insertions(+), 90 deletions(-) diff --git a/includes/config/include.php b/includes/config/include.php index a6c039116..c7e5e9fb9 100755 --- a/includes/config/include.php +++ b/includes/config/include.php @@ -28,7 +28,7 @@ define('TP_VERSION', '3.1.2'); define("UPGRADE_MIN_DATE", "1732264740"); -define('TP_VERSION_MINOR', '170'); +define('TP_VERSION_MINOR', '171'); define('TP_TOOL_NAME', 'Teampass'); define('TP_ONE_DAY_SECONDS', 86400); define('TP_ONE_WEEK_SECONDS', 604800); diff --git a/install/install.js b/install/install.js index 5cded9af0..557a99b56 100755 --- a/install/install.js +++ b/install/install.js @@ -26,14 +26,6 @@ $(function() { alert("Paste option is disabled !!"); e.preventDefault(); }); - - /* - * Removing automatic action - // Auto start - if ($("#step").val() == 5) { - $('#but_launch').trigger('click'); - } - */ }); function aesEncrypt(text) @@ -47,7 +39,9 @@ var global_error_on_query = false, dbInfo = "", index = "", multiple = "", - jsonValues = ""; + jsonValues = "", + skFile = ""; +let progressNotification; function checkPage() { @@ -57,26 +51,25 @@ function checkPage() index = ""; tasks = []; dbInfo = []; + skFile = []; multiple = ""; tsk = ""; $("#step_error").addClass("hidden").html(""); $("#res_"+step).html(""); - alertify - .message('Working on it... ', 0) - .dismissOthers(); - + if (step === "2") { // STEP 2 - if ($("#url_path").val() === "" || $("#absolute_path").val() === "") { + if ($("#url_path").val() === "" || $("#absolute_path").val() === "" || $("#sk_path").val() === "") { error = "Fields need to be filled in!"; } else { - jsonValues = {"absolute_path":$("#absolute_path").val(), "url_path":$("#url_path").val()}; + jsonValues = {"absolute_path":sanitizeString($("#absolute_path").val()), "url_path":sanitizeString($("#url_path").val()), "sk_path":sanitizeString($("#sk_path").val())}; dataToUse = JSON.stringify(jsonValues); - tasks = ["folder*install", "folder*includes", "folder*includes/config", "folder*includes/avatars", "folder*includes/libraries/csrfp/libs", "folder*includes/libraries/csrfp/js", "folder*includes/libraries/csrfp/log", "extension*mbstring", "extension*openssl", "extension*bcmath", "extension*iconv", "extension*gd", "extension*xml", "extension*curl", "version*php", "ini*max_execution_time", "extension*gmp", "folder*files", "folder*upload"]; + tasks = ["folder*install", "folder*includes", "folder*includes/config", "folder*includes/avatars", "folder*includes/libraries/csrfp/libs", "folder*includes/libraries/csrfp/js", "folder*includes/libraries/csrfp/log", "extension*mbstring", "extension*openssl", "extension*bcmath", "extension*iconv", "extension*gd", "extension*xml", "extension*curl", "version*php", "ini*max_execution_time", "extension*gmp", "folder*files", "folder*upload", "folder*secure"]; multiple = true; $("#hid_absolute_path").val($("#absolute_path").val()); $("#hid_url_path").val($("#url_path").val()); + $("#hid_sk_path").val($("#sk_path").val()); } } else if (step === "3") { // STEP 3 @@ -130,7 +123,7 @@ function checkPage() } $("#hid_db_pre").val($("#tbl_prefix").val()); - jsonValues = {"tbl_prefix":sanitizeString($("#tbl_prefix").val()), "sk_path":sanitizeString($("#sk_path").val()), "admin_pwd":sanitizeString($("#admin_pwd").val()), "admin_email":sanitizeString($("#admin_email").val()), "send_stats":""}; + jsonValues = {"tbl_prefix":sanitizeString($("#tbl_prefix").val()), "admin_pwd":sanitizeString($("#admin_pwd").val()), "admin_email":sanitizeString($("#admin_email").val()), "send_stats":""}; dataToUse = JSON.stringify(jsonValues); tasks = ["misc*preparation"]; multiple = ""; @@ -139,11 +132,12 @@ function checkPage() dataToUse = ""; tasks = ["table*utf8", "table*api", "table*automatic_del", "table*cache", "table*cache_tree", "table*categories", "table*categories_folders", "table*categories_items", "table*defuse_passwords", "table*emails", "table*export", "table*files", "table*items", "table*items_change", "table*items_edition", "table*items_otp", "table*kb", "table*kb_categories", "table*kb_items", "table*ldap_groups_roles", "table*languages", "table*log_items", "table*log_system", "table*misc", "table*nested_tree", "table*notification", "table*otv", "table*background_tasks", "table*background_subtasks", "table*background_tasks_logs", "table*restriction_to_roles", "table*rights", "table*roles_title", "table*roles_values", "table*sharekeys_fields", "table*sharekeys_files", "table*sharekeys_items", "table*sharekeys_logs", "table*sharekeys_suggestions", "table*suggestion", "table*tags", "table*templates", "table*tokens", "table*users", "table*auth_failures"]; multiple = true; + $('#step5_wip').removeClass('hidden'); } else if (step === "6") { // STEP 6 jsonValues = {"url_path":sanitizeString($("#hid_url_path").val())}; dataToUse = JSON.stringify(jsonValues); - tasks = ["install*init", "file*security", "file*settings.php", "file*csrfp-token", "install*cleanup", "install*cronJob"]; + tasks = [ "file*settings.php","install*init", "file*security", "file*settings.php", "file*csrfp-token", "install*cleanup", "install*cronJob"]; multiple = true; } @@ -152,9 +146,13 @@ function checkPage() global_error_on_query = false; index = 0; dbInfo = {"db_host" : $("#hid_db_host").val(), "db_bdd" : $("#hid_db_bdd").val(), "db_login" : $("#hid_db_login").val(), "db_pw" : $("#hid_db_pwd").val(), "db_port" : $("#hid_db_port").val(), "db_pre" : $("#hid_db_pre").val()}; + skFile = {"sk_path" : $("#hid_sk_path").val(), "sk_filename" : $("#hid_sk_filename").val(), "sk_key" : $("#hid_sk_key").val()}; $("#step_res").val("true"); $("#pop_db").html(""); + + progressNotification = alertify.message(' Processing tasks...', 0); // Timeout = 0 means persistent + var promise = tasks.slice(1) .reduce( @@ -167,12 +165,15 @@ function checkPage() promise.then(function(){ // do something when all requests are ready // all requests are complete + $('.progress').addClass('hidden'); if ($("#step_res").val() === "false" || global_error_on_query === true) { + progressNotification.dismiss(); alertify .error('At least one task has failed! Please correct and relaunch.', 0) .dismissOthers(); return false; } else { + progressNotification.dismiss(); alertify .success('Done.
Click next to continue', 1) .dismissOthers(); @@ -190,11 +191,16 @@ function checkPage() .addClass("hidden"); } } + }); } else if (error === "" && multiple === "") { + + progressNotification = alertify.message(' Processing tasks...', 0); + tsk = tasks[0].split("*"); dbInfo = {"db_host" : $("#hid_db_host").val(), "db_bdd" : $("#hid_db_bdd").val(), "db_login" : $("#hid_db_login").val(), "db_pw" : $("#hid_db_pwd").val(), "db_port" : $("#hid_db_port").val()}; + skFile = {"sk_path" : $("#hid_sk_path").val(), "sk_filename" : $("#hid_sk_filename").val(), "sk_key" : $("#hid_sk_key").val()}; dataToUse = { type: "step_"+step, @@ -202,6 +208,7 @@ function checkPage() activity: aesEncrypt(tsk[0]), task: aesEncrypt(tsk[1]), db: aesEncrypt(JSON.stringify(dbInfo)), + skFile: aesEncrypt(JSON.stringify(skFile)), index: index, multiple: multiple, info: tsk[0]+"-"+tsk[1], @@ -236,7 +243,9 @@ function checkPage() } }); } else { - $("#step_error").removeClass("hidden").html(error); + alertify + .error('' + error + '
Please correct and relaunch.', 10) + .dismissOthers(); } } @@ -246,9 +255,8 @@ function checkPage() */ function doGetJson(task) { - console.log("\n\n--- PREPARATION---\n"+step+"\n"+dataToUse+"\n"+dbInfo+"\n"+index+"\n"+multiple+"\n"+task+"\n-------\n") tsk = task.split("*"); - + return $.ajax({ url: "install.queries.php", type : "POST", @@ -260,22 +268,22 @@ function doGetJson(task) activity: aesEncrypt(tsk[0]), task: aesEncrypt(tsk[1]), db: aesEncrypt(JSON.stringify(dbInfo)), + skFile: aesEncrypt(JSON.stringify(skFile)), index: index, multiple: multiple, info: tsk[0]+"-"+tsk[1] } }) .complete(function(data) { - console.log("\n\n--- RECEPTION---\n"+JSON.stringify(data, null, 2)+"\n-------\n") if (data.responseText === "") { alertify .error('[ERROR] Answer from server is empty.', 10) .dismissOthers(); } else { data = $.parseJSON(data.responseText); - console.log("RETOUR:"); - console.log(data) + if (data[0].error === "") { + progressNotification.setContent(` Task ${tsk[1]} completed successfully.`); if (step === "5") { if (data[0].activity === "table") { $("#pop_db").append("
  • Table "+data[0].task+" created
  • "); @@ -293,12 +301,18 @@ function doGetJson(task) .dismissOthers(); } } else { - $("#res"+step+"_check"+data[0].index).html('' + data[0].error + "
    "); + progressNotification.setContent(` Task ${tsk[1]} failed: ${data[0].error}`); // Considere only a warning on GMP extension - if (data[0].index !== "16") { + if (step !== "5" && data[0].index !== "16") { global_error_on_query = true; } + + if (step === "5") { + if (data[0].activity === "table" && data[0].error.includes("Duplicate key name") === false) { + global_error_on_query = true; + } + } } } index++; diff --git a/install/install.php b/install/install.php index aac58a26c..ef8b11c5d 100755 --- a/install/install.php +++ b/install/install.php @@ -102,6 +102,21 @@ if (empty($post_sk_path) === true) { $post_sk_path = filter_input(INPUT_POST, 'hid_sk_path', FILTER_SANITIZE_FULL_SPECIAL_CHARS); } + if (empty($post_sk_filename) === true) { + $post_sk_filename = filter_input(INPUT_POST, 'hid_sk_filename', FILTER_SANITIZE_FULL_SPECIAL_CHARS); + } + if (empty($post_sk_key) === true) { + $post_sk_key= filter_input(INPUT_POST, 'hid_sk_key', FILTER_SANITIZE_FULL_SPECIAL_CHARS); + } + + if (isset($_COOKIE['PHPSESSID'])) { + setcookie('PHPSESSID', '', time() - 10, '/', '', false, true); + } + if (session_status() === PHP_SESSION_ACTIVE) { + session_unset(); + session_destroy(); + } + // Get some data include "../includes/config/include.php"; @@ -133,6 +148,8 @@ + +
    @@ -191,6 +208,13 @@
    +
    + + + For security reasons, the secure path shall be defined outside the WWW folder of your server (example: /var/teampass/). It will host an encryption key used for several Teampass features. + + +
    @@ -206,7 +230,8 @@
      -
    • File "/includes/config/settings.php is available" 
    • +
    • Secure folder is available 
    • +
    • File "/includes/config/settings.php is available 
    • Directory "/install/" is writable 
    • Directory "/includes/" is writable 
    • Directory "/includes/config/" is writable 
    • @@ -297,14 +322,6 @@
    -
    - - - - The SaltKey is stored in a file called teampass-seckey.txt and hashed for security purpose. For security reasons, this file should be stored in a folder outside the WWW folder of your server (example: /var/teampass/). This key will be used to encrypt data when sharing information with users without any Teampass account. If this field remains empty, this file will be stored in folder /includes/. - -
    -
    @@ -342,6 +359,9 @@
      + '; diff --git a/install/install.queries.php b/install/install.queries.php index d4322fa18..06287424b 100755 --- a/install/install.queries.php +++ b/install/install.queries.php @@ -42,6 +42,7 @@ use Encryption\Crypt\aesctr; // Do initial test +// Ensure that the file settings.php exists if (file_exists('../includes/config/settings.php') === false) { $settings_sample = 'includes/config/settings.sample.php'; $settings = 'includes/config/settings.php'; @@ -52,20 +53,9 @@ 'Then click START button.", "index" : "99", "multiple" : "' . $inputData['multiple'] . '"}]'; exit(); } -} - - -// Load settings -include_once '../includes/config/settings.php'; -// Check if SECUREPATH and SECUREFILE are defined -if (defined('SECUREPATH') === false) { - define('SECUREPATH', __DIR__.'/../includes/config'); - error_log("TEST1"); -} -if (defined('SECUREFILE') === false) { - define('SECUREFILE', generateRandomKey()); - error_log("TEST2"); + $SECUREPATH = __DIR__.'/../includes/config'; + $SECUREFILE = generateRandomKey(); // 1- generate saltkey $key = Key::createNewRandomKey(); @@ -73,18 +63,25 @@ // 2- store key in file file_put_contents( - SECUREPATH.'/'.SECUREFILE, + $SECUREPATH.'/'.$SECUREFILE, $new_salt ); //3 - add to settings $newLine = ' -define("SECUREPATH", "' . SECUREPATH. '"); -define("SECUREFILE", "' . SECUREFILE. '"); +define("SECUREPATH", "' . $SECUREPATH. '"); +define("SECUREFILE", "' . $SECUREFILE. '"); '; file_put_contents('../includes/config/settings.php', $newLine, FILE_APPEND); } +// Load settings +include_once '../includes/config/settings.php'; + +// Reset SESSION +if (isset($_COOKIE['PHPSESSID'])) { + setcookie('PHPSESSID', '', time() - 10, '/', '', false, true); +} if (session_status() === PHP_SESSION_ACTIVE) { session_unset(); session_destroy(); @@ -93,7 +90,6 @@ // Load functions require_once __DIR__.'/../sources/main.functions.php'; - // init loadClasses('DB'); $session = SessionManager::getSession(); @@ -116,9 +112,6 @@ $session_db_encoding = 'utf8'; define('MIN_PHP_VERSION', 8.1); -$superGlobal = new SuperGlobal(); -$lang = new Language(); - /** * Generates a random key. */ @@ -189,12 +182,13 @@ function encryptFollowingDefuse($message, $ascii_key) 'index' => filter_input(INPUT_POST, 'index', FILTER_SANITIZE_NUMBER_INT), 'multiple' => filter_input(INPUT_POST, 'multiple', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'db' => filter_input(INPUT_POST, 'db', FILTER_SANITIZE_FULL_SPECIAL_CHARS), + 'skFile' => filter_input(INPUT_POST, 'skFile', FILTER_SANITIZE_FULL_SPECIAL_CHARS), ]; // Decrypt POST values require_once 'libs/aesctr.php'; foreach ($postValues as $key => $value) { - if ($key === 'data' || $key === 'activity' || $key === 'task' || $key === 'db') { + if ($key === 'data' || $key === 'activity' || $key === 'task' || $key === 'db' || $key === 'skFile') { $postValues[$key] = aesctr::decrypt($value, 'cpm', 128); } } @@ -207,6 +201,7 @@ function encryptFollowingDefuse($message, $ascii_key) 'index' => isset($postValues['index']) === true ? (int) $postValues['index'] : 0, 'multiple' => isset($postValues['multiple']) === true ? $postValues['multiple'] : '', 'db' => isset($postValues['db']) === true ? $postValues['db'] : '', + 'skFile' => isset($postValues['skFile']) === true ? $postValues['skFile'] : '', ]; $filters = [ 'type' => 'trim|escape', @@ -216,6 +211,7 @@ function encryptFollowingDefuse($message, $ascii_key) 'index' => 'cast:integer', 'multiple' => 'trim|escape', 'db' => 'cast:array', + 'skFile' => 'cast:array', ]; $inputData = dataSanitizer( $inputData['data'], @@ -226,7 +222,9 @@ function encryptFollowingDefuse($message, $ascii_key) // Prepare variables $session_abspath = rtrim($inputData['data']['absolute_path'], '/'); $session_url_path = rtrim($inputData['data']['url_path'], '/'); -$session_sk_path = rtrim($inputData['data']['sk_path'], '/'); +$session_sk_path = rtrim($inputData['skFile']['sk_path'], '/'); +$session_sk_filename = $inputData['skFile']['sk_filename']; +$session_sk_key = $inputData['skFile']['sk_key']; if (null !== $inputData['type']) { switch ($inputData['type']) { @@ -257,10 +255,10 @@ function encryptFollowingDefuse($message, $ascii_key) break; } } + define('SECUREPATH', $session_sk_path); echo '[{"error" : "", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; } else { $targetPath = $session_abspath . '/' . $inputData['task'] . '/'; - error_log("PATH: ".$targetPath); if (is_writable($targetPath) === true) { echo '[{"error" : "", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; } else { @@ -371,7 +369,20 @@ function encryptFollowingDefuse($message, $ascii_key) mysqli_close($dbTmp); break; - case 'step_4': + case 'step_4': + // launch + try { + $dbTmp = mysqli_connect( + $inputData['db']['db_host'], + $inputData['db']['db_login'], + $inputData['db']['db_pw'], + $inputData['db']['db_bdd'], + $inputData['db']['db_port'] + ); + } catch (Exception $e) { + echo '[{"error" : "Cannot connect to Database - '.$e->getMessage().'"}]'; + break; + } // prepare data foreach ($inputData['data'] as $key => $value) { @@ -457,12 +468,27 @@ function encryptFollowingDefuse($message, $ascii_key) INDEX idx_object_user (`object_id`, `user_id`) ) CHARSET=utf8;' ); - $mysqli_result = mysqli_query( - $dbTmp, - 'ALTER TABLE `' . $var['tbl_prefix'] . 'sharekeys_items` - ADD KEY `object_id_idx` (`object_id`), - ADD KEY `user_id_idx` (`user_id`);' - ); + + // Requête pour vérifier si les clés existent + $keyCheckQuery = " + SELECT COUNT(1) as key_exists + FROM information_schema.STATISTICS + WHERE table_schema = DATABASE() + AND table_name = '" . $var['tbl_prefix'] . "sharekeys_items' + AND index_name IN ('object_id_idx', 'user_id_idx') + "; + $result = mysqli_query($dbTmp, $keyCheckQuery); + if ($result) { + $row = mysqli_fetch_assoc($result); + if ($row['key_exists'] == 0) { + // Les clés n'existent pas, exécutez la requête ALTER TABLE + $alterQuery = " + ALTER TABLE `" . $var['tbl_prefix'] . "sharekeys_items` + ADD KEY `object_id_idx` (`object_id`), + ADD KEY `user_id_idx` (`user_id`); + "; + } + } } elseif ($inputData['task'] === 'sharekeys_logs') { $mysqli_result = mysqli_query( $dbTmp, @@ -474,12 +500,26 @@ function encryptFollowingDefuse($message, $ascii_key) PRIMARY KEY (`increment_id`) ) CHARSET=utf8;' ); - $mysqli_result = mysqli_query( - $dbTmp, - 'ALTER TABLE `' . $var['tbl_prefix'] . 'sharekeys_logs` - ADD KEY `object_id_idx` (`object_id`), - ADD KEY `user_id_idx` (`user_id`);' - ); + // Requête pour vérifier si les clés existent + $keyCheckQuery = " + SELECT COUNT(1) as key_exists + FROM information_schema.STATISTICS + WHERE table_schema = DATABASE() + AND table_name = '" . $var['tbl_prefix'] . "sharekeys_logs' + AND index_name IN ('object_id_idx', 'user_id_idx') + "; + $result = mysqli_query($dbTmp, $keyCheckQuery); + if ($result) { + $row = mysqli_fetch_assoc($result); + if ($row['key_exists'] == 0) { + // Les clés n'existent pas, exécutez la requête ALTER TABLE + $alterQuery = " + ALTER TABLE `" . $var['tbl_prefix'] . "sharekeys_logs` + ADD KEY `object_id_idx` (`object_id`), + ADD KEY `user_id_idx` (`user_id`); + "; + } + } } elseif ($inputData['task'] === 'sharekeys_fields') { $mysqli_result = mysqli_query( $dbTmp, @@ -1342,11 +1382,26 @@ function encryptFollowingDefuse($message, $ascii_key) PRIMARY KEY (`increment_id`) ) CHARSET=utf8;" ); - $mysqli_result = mysqli_query( - $dbTmp, - 'ALTER TABLE `' . $var['tbl_prefix'] . 'background_subtasks` - ADD KEY `task_id_idx` (`task_id`);' - ); + + // Requête pour vérifier si les clés existent + $keyCheckQuery = " + SELECT COUNT(1) as key_exists + FROM information_schema.STATISTICS + WHERE table_schema = DATABASE() + AND table_name = '" . $var['tbl_prefix'] . "background_subtasks' + AND index_name IN ('task_id_idx') + "; + $result = mysqli_query($dbTmp, $keyCheckQuery); + if ($result) { + $row = mysqli_fetch_assoc($result); + if ($row['key_exists'] == 0) { + // Les clés n'existent pas, exécutez la requête ALTER TABLE + $alterQuery = " + ALTER TABLE `" . $var['tbl_prefix'] . "background_subtasks` + ADD KEY `task_id_idx` (`task_id`); + "; + } + } } else if ($inputData['task'] === 'background_tasks') { $mysqli_result = mysqli_query( $dbTmp, @@ -1462,24 +1517,18 @@ function encryptFollowingDefuse($message, $ascii_key) // Now create settings file $filename = '../includes/config/settings.php'; - if (file_exists($filename)) { - if (!copy($filename, $filename . '.' . date('Y_m_d', mktime(0, 0, 0, (int) date('m'), (int) date('d'), (int) date('y'))))) { - echo '[{"error" : "Setting.php file already exists and cannot be renamed. Please do it by yourself and click on button Launch.", "result":"", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; - break; - } else { - unlink($filename); - } + if (!copy($filename, $filename . '.' . date('Y_m_d', mktime(0, 0, 0, (int) date('m'), (int) date('d'), (int) date('y')))."_".time())) { + echo '[{"error" : "Setting.php file already exists and cannot be renamed. Please do it by yourself and click on button Launch.", "result":"", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; + break; } - // - if (file_exists(__DIR__.'/../includes/config/'.SECUREFILE)) { - unlink(__DIR__.'/../includes/config/'.SECUREFILE); - } + // get key + $encryptionKey = file_get_contents(SECUREPATH . "/" . SECUREFILE); // Encrypt the DB password $encrypted_text = encryptFollowingDefuse( $inputData['db']['db_pw'], - $new_salt + $encryptionKey )['string']; // Open and write Settings file @@ -1519,6 +1568,11 @@ function encryptFollowingDefuse($message, $ascii_key) ); fclose($file_handler); + // NOw remove old file + if (file_exists(__DIR__.'/../includes/config/'.SECUREFILE)) { + unlink(__DIR__.'/../includes/config/'.SECUREFILE); + } + // Create TP USER require_once '../includes/config/include.php'; $tmp = mysqli_num_rows(mysqli_query($dbTmp, "SELECT * FROM `" . $var['tbl_prefix'] . "users` WHERE id = '" . TP_USER_ID . "'")); @@ -1527,7 +1581,7 @@ function encryptFollowingDefuse($message, $ascii_key) $pwd = GenerateCryptKey(25, true, true, true, true); $encrypted_pwd = cryption( $pwd, - $new_salt, + $encryptionKey, 'encrypt' )['string']; @@ -1540,6 +1594,16 @@ function encryptFollowingDefuse($message, $ascii_key) ); } + // Destroy session without writing to disk + // Requested to reset CONST values + if (isset($_COOKIE['PHPSESSID'])) { + setcookie('PHPSESSID', '', time() - 10, '/', '', false, true); + } + if (session_status() === PHP_SESSION_ACTIVE) { + session_unset(); + session_destroy(); + } + if ($result === false) { echo '[{"error" : "Setting.php file could not be created. Please check the path and the rights", "result":"", "index" : "' . $inputData['index'] . '", "multiple" : "' . $inputData['multiple'] . '"}]'; } else { From d69de4e4b966a323058a4a330bfa782205aedfde Mon Sep 17 00:00:00 2001 From: nilsteampassnet Date: Thu, 28 Nov 2024 22:38:21 +0100 Subject: [PATCH 5/5] Fixed comments review --- includes/config/include.php | 2 +- install/install.queries.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/includes/config/include.php b/includes/config/include.php index c7e5e9fb9..c69326da2 100755 --- a/includes/config/include.php +++ b/includes/config/include.php @@ -28,7 +28,7 @@ define('TP_VERSION', '3.1.2'); define("UPGRADE_MIN_DATE", "1732264740"); -define('TP_VERSION_MINOR', '171'); +define('TP_VERSION_MINOR', '172'); define('TP_TOOL_NAME', 'Teampass'); define('TP_ONE_DAY_SECONDS', 86400); define('TP_ONE_WEEK_SECONDS', 604800); diff --git a/install/install.queries.php b/install/install.queries.php index 06287424b..fda222154 100755 --- a/install/install.queries.php +++ b/install/install.queries.php @@ -354,12 +354,12 @@ function encryptFollowingDefuse($message, $ascii_key) // For other queries with `url_path` and `absolute_path` $tmp = mysqli_num_rows(mysqli_query($dbTmp, "SELECT * FROM `_install` WHERE `key` = 'url_path'")); if (intval($tmp) === 0) { - mysqli_query($dbTmp, "INSERT INTO `_install` (`key`, `value`) VALUES ('url_path', '" . $session_url_path . "');"); + mysqli_query($dbTmp, "INSERT INTO `_install` (`key`, `value`) VALUES ('url_path', '" . mysqli_real_escape_string($dbTmp, $session_url_path) . "');"); } $tmp = mysqli_num_rows(mysqli_query($dbTmp, "SELECT * FROM `_install` WHERE `key` = 'absolute_path'")); if (intval($tmp) === 0) { - mysqli_query($dbTmp, "INSERT INTO `_install` (`key`, `value`) VALUES ('absolute_path', '" . $session_abspath . "');"); + mysqli_query($dbTmp, "INSERT INTO `_install` (`key`, `value`) VALUES ('absolute_path', '" . mysqli_real_escape_string($dbTmp, $session_abspath) . "');"); } echo '[{"error" : "", "result" : "Connection is successful", "multiple" : ""}]'; @@ -1557,7 +1557,7 @@ function encryptFollowingDefuse($message, $ascii_key) define("DB_CONNECT_OPTIONS", array( MYSQLI_OPT_CONNECT_TIMEOUT => 10 )); -define("SECUREPATH", "' . $session_sk_path . '"); +define("SECUREPATH", "' . str_replace('"', '', $session_sk_path) . '"); define("SECUREFILE", "' . SECUREFILE. '"); if (isset($_SESSION[\'settings\'][\'timezone\']) === true) {