| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469 |
- <?php
- use function Hestiacp\quoteshellarg\quoteshellarg;
- define("NO_AUTH_REQUIRED", true);
- // Main include
- include $_SERVER["DOCUMENT_ROOT"] . "/inc/main.php";
- $TAB = "LOGIN";
- if (isset($_GET["logout"])) {
- unset($_SESSION);
- session_unset();
- session_destroy();
- header("Location: /login/");
- }
- /* ACTIONS FOR CURRENT USER SESSION */
- if (isset($_SESSION["user"])) {
- // User impersonation
- // Allow administrators to view and manipulate contents of other user accounts
- if ($_SESSION["userContext"] === "admin" && !empty($_GET["loginas"])) {
- // Ensure token is passed and matches before granting user impersonation access
- if (verify_csrf($_GET)) {
- $v_user = quoteshellarg($_GET["loginas"]);
- $v_impersonator = quoteshellarg($_SESSION["user"]);
- exec(HESTIA_CMD . "v-list-user " . $v_user . " json", $output, $return_var);
- if ($return_var == 0) {
- $data = json_decode(implode("", $output), true);
- reset($data);
- $_SESSION["look"] = key($data);
- // Log impersonation events
- exec(
- HESTIA_CMD .
- "v-log-action " .
- $v_impersonator .
- " 'Info' 'Security' 'Logged in as another user (User: $v_user)'",
- $output,
- $return_var,
- );
- exec(
- HESTIA_CMD .
- "v-log-action system 'Warning' 'Security' 'User impersonation session started (User: $v_user, Administrator: $v_impersonator)'",
- $output,
- $return_var,
- );
- // Reset account details for File Manager to impersonated user
- unset($_SESSION["_sf2_attributes"]);
- unset($_SESSION["_sf2_meta"]);
- if (!empty($_GET["edit_link"])) {
- $edit_link = urldecode($_GET["edit_link"]);
- $url = $edit_link . "&token=" . $_SESSION["token"];
- header("Location: " . $url);
- die();
- }
- header("Location: /login/");
- } else {
- # User doesn't exists
- header("Location: /");
- }
- }
- exit();
- }
- // Set view based on account properties
- if (empty($_GET["loginas"])) {
- // Default view to Users list for administrator accounts
- if ($_SESSION["userContext"] === "admin" && !isset($_SESSION["look"])) {
- header("Location: /list/user/");
- exit();
- }
- // Obtain account properties
- $v_user = quoteshellarg(
- $_SESSION[
- $_SESSION["userContext"] === "admin" && $_SESSION["look"] !== "" ? "look" : "user"
- ],
- );
- exec(HESTIA_CMD . "v-list-user " . $v_user . " json", $output, $return_var);
- $data = json_decode(implode("", $output), true);
- unset($output);
- // Determine package features and land user at the first available page
- if ($data[$user_plain]["WEB_DOMAINS"] !== "0") {
- header("Location: /list/web/");
- } elseif ($data[$user_plain]["DNS_DOMAINS"] !== "0") {
- header("Location: /list/dns/");
- } elseif ($data[$user_plain]["MAIL_DOMAINS"] !== "0") {
- header("Location: /list/mail/");
- } elseif ($data[$user_plain]["DATABASES"] !== "0") {
- header("Location: /list/db/");
- } elseif ($data[$user_plain]["CRON_JOBS"] !== "0") {
- header("Location: /list/cron/");
- } elseif ($data[$user_plain]["BACKUPS"] !== "0") {
- header("Location: /list/backup/");
- } else {
- header("Location: /error/");
- }
- exit();
- }
- // Do not allow non-administrators to access account impersonation
- if ($_SESSION["userContext"] !== "admin" && !empty($_GET["loginas"])) {
- header("Location: /login/");
- exit();
- }
- exit();
- }
- function authenticate_user($user, $password, $twofa = "") {
- unset($_SESSION["login"]);
- if (verify_csrf($_POST, true)) {
- $v_user = quoteshellarg($user);
- $ip = $_SERVER["REMOTE_ADDR"];
- $user_agent = $_SERVER["HTTP_USER_AGENT"];
- if (
- !empty($_SERVER["HTTP_CF_CONNECTING_IP"]) &&
- filter_var(
- $_SERVER["HTTP_CF_CONNECTING_IP"],
- FILTER_VALIDATE_IP,
- FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6,
- )
- ) {
- $ip = $_SERVER["HTTP_CF_CONNECTING_IP"];
- }
- // Handling IPv4-mapped IPv6 address
- if (strpos($ip, ":") === 0 && strpos($ip, ".") > 0) {
- $ip = substr($ip, strrpos($ip, ":") + 1); // Strip IPv4 Compatibility notation
- }
- $v_ip = quoteshellarg($ip);
- $v_user_agent = quoteshellarg($user_agent);
- // Get user's salt
- $output = "";
- exec(
- HESTIA_CMD . "v-get-user-salt " . $v_user . " " . $v_ip . " json",
- $output,
- $return_var,
- );
- $pam = json_decode(implode("", $output), true);
- unset($output);
- if ($return_var > 0) {
- sleep(2);
- if ($return_var == 5) {
- $error = _("Account has been suspended");
- } elseif ($return_var == 1) {
- $error = _("Unsupported hash method");
- } else {
- $error = _("Invalid username or password");
- }
- return $error;
- } else {
- $salt = $pam[$user]["SALT"];
- $method = $pam[$user]["METHOD"];
- if ($method == "md5") {
- $hash = crypt($password, '$1$' . $salt . '$');
- }
- if ($method == "sha-512") {
- $hash = crypt($password, '$6$rounds=5000$' . $salt . '$');
- $hash = str_replace('$rounds=5000', "", $hash);
- }
- if ($method == "yescrypt") {
- $fp = tmpfile();
- $v_password = stream_get_meta_data($fp)["uri"];
- fwrite($fp, $password . "\n");
- exec(
- HESTIA_CMD .
- "v-check-user-password " .
- $v_user .
- " " .
- quoteshellarg($v_password) .
- " " .
- $v_ip .
- " yes",
- $output,
- $return_var,
- );
- $hash = $output[0];
- fclose($fp);
- unset($output, $fp, $v_password);
- }
- if ($method == "des") {
- $hash = crypt($password, $salt);
- }
- // Send hash via tmp file
- $v_hash = exec("mktemp -p /tmp");
- $fp = fopen($v_hash, "w");
- fwrite($fp, $hash . "\n");
- fclose($fp);
- // Check user hash
- exec(
- HESTIA_CMD . "v-check-user-hash " . $v_user . " " . $v_hash . " " . $v_ip,
- $output,
- $return_var,
- );
- unset($output);
- // Remove tmp file
- unlink($v_hash);
- // Check API answer
- if ($return_var > 0) {
- sleep(2);
- $error = _("Invalid username or password");
- $v_session_id = quoteshellarg($_POST["token"]);
- exec(
- HESTIA_CMD .
- "v-log-user-login " .
- $v_user .
- " " .
- $v_ip .
- " failed " .
- $v_session_id .
- " " .
- $v_user_agent,
- $output,
- $return_var,
- );
- return $error;
- } else {
- // Get user specific parameters
- exec(HESTIA_CMD . "v-list-user " . $v_user . " json", $output, $return_var);
- $data = json_decode(implode("", $output), true);
- unset($output);
- if ($data[$user]["LOGIN_DISABLED"] === "yes") {
- sleep(2);
- $error = _("Invalid username or password");
- $v_session_id = quoteshellarg($_POST["token"]);
- exec(
- HESTIA_CMD .
- "v-log-user-login " .
- $v_user .
- " " .
- $v_ip .
- " failed " .
- $v_session_id .
- " " .
- $v_user_agent .
- ' yes "Login disabled for this user"',
- $output,
- $return_var,
- );
- return $error;
- }
- if ($data[$user]["LOGIN_USE_IPLIST"] === "yes") {
- $v_login_user_allowed_ips = explode(",", $data[$user]["LOGIN_ALLOW_IPS"]);
- $v_login_user_allowed_ips = array_map("trim", $v_login_user_allowed_ips);
- if (!in_array($ip, $v_login_user_allowed_ips, true)) {
- sleep(2);
- $error = _("Invalid username or password");
- $v_session_id = quoteshellarg($_POST["token"]);
- exec(
- HESTIA_CMD .
- "v-log-user-login " .
- $v_user .
- " " .
- $v_ip .
- " failed " .
- $v_session_id .
- " " .
- $v_user_agent .
- ' yes "IP address not in allowed list"',
- $output,
- $return_var,
- );
- return $error;
- }
- }
- if ($data[$user]["TWOFA"] != "") {
- if (empty($twofa)) {
- $_SESSION["login"]["username"] = $user;
- $_SESSION["login"]["password"] = $password;
- return false;
- } else {
- $v_twofa = quoteshellarg($twofa);
- exec(
- HESTIA_CMD . "v-check-user-2fa " . $v_user . " " . $v_twofa,
- $output,
- $return_var,
- );
- unset($output);
- if ($return_var > 0) {
- sleep(2);
- $error = _("Invalid or missing 2FA token");
- $_SESSION["login"]["username"] = $user;
- $_SESSION["login"]["password"] = $password;
- $v_session_id = quoteshellarg($_POST["token"]);
- if (isset($_SESSION["failed_twofa"])) {
- //allow a few failed attemps before start of logging.
- if ($_SESSION["failed_twofa"] > 2) {
- exec(
- HESTIA_CMD .
- "v-log-user-login " .
- $v_user .
- " " .
- $v_ip .
- " failed " .
- $v_session_id .
- " " .
- $v_user_agent .
- ' yes "Invalid or missing 2FA token"',
- $output,
- $return_var,
- );
- }
- $_SESSION["failed_twofa"]++;
- } else {
- $_SESSION["failed_twofa"] = 1;
- }
- unset($_POST["twofa"]);
- return $error;
- }
- }
- }
- // Define session user
- $_SESSION["user"] = key($data);
- $v_user = $_SESSION["user"];
- //log successfull login attempt
- $v_session_id = quoteshellarg($_POST["token"]);
- exec(
- HESTIA_CMD .
- "v-log-user-login " .
- $v_user .
- " " .
- $v_ip .
- " success " .
- $v_session_id .
- " " .
- $v_user_agent,
- $output,
- $return_var,
- );
- $_SESSION["LAST_ACTIVITY"] = time();
- // Define user role / context
- $_SESSION["userContext"] = $data[$user]["ROLE"];
- // Set active user theme on login
- $_SESSION["userTheme"] = $data[$user]["THEME"];
- if ($_SESSION["POLICY_USER_CHANGE_THEME"] !== "yes") {
- unset($_SESSION["userTheme"]);
- }
- $_SESSION["userSortOrder"] = !empty($data[$user]["PREF_UI_SORT"])
- ? $data[$user]["PREF_UI_SORT"]
- : "name";
- // Define language
- $output = "";
- exec(HESTIA_CMD . "v-list-sys-languages json", $output, $return_var);
- $languages = json_decode(implode("", $output), true);
- $_SESSION["language"] = in_array($data[$v_user]["LANGUAGE"], $languages)
- ? $data[$user]["LANGUAGE"]
- : "en";
- // Regenerate session id to prevent session fixation
- session_regenerate_id(true);
- // Redirect request to control panel interface
- if (!empty($_SESSION["request_uri"])) {
- header("Location: " . $_SESSION["request_uri"]);
- unset($_SESSION["request_uri"]);
- exit();
- } else {
- if ($_SESSION["userContext"] === "admin") {
- header("Location: /list/user/");
- } else {
- if ($data[$user]["WEB_DOMAINS"] != "0") {
- header("Location: /list/web/");
- } elseif ($data[$user]["DNS_DOMAINS"] != "0") {
- header("Location: /list/dns/");
- } elseif ($data[$user]["MAIL_DOMAINS"] != "0") {
- header("Location: /list/mail/");
- } elseif ($data[$user]["DATABASES"] != "0") {
- header("Location: /list/db/");
- } elseif ($data[$user]["CRON_JOBS"] != "0") {
- header("Location: /list/cron/");
- } elseif ($data[$user]["BACKUPS"] != "0") {
- header("Location: /list/backup/");
- } else {
- header("Location: /error/");
- }
- }
- exit();
- }
- }
- }
- } else {
- unset($_POST);
- unset($_GET);
- unset($_SESSION);
- // Delete old session and start a new one
- session_write_close();
- session_unset();
- session_destroy();
- session_start();
- return false;
- }
- }
- if (empty($_POST["user"])) {
- $user = "";
- } else {
- if (preg_match('/^[[:alnum:]][-|\.|_[:alnum:]]{0,28}[[:alnum:]]$/', $_POST["user"])) {
- $_SESSION["login"]["username"] = $_POST["user"];
- } else {
- $user = "";
- }
- }
- if (
- !empty($_SESSION["login"]["username"]) &&
- !empty($_SESSION["login"]["password"]) &&
- !empty($_POST["twofa"])
- ) {
- $error = authenticate_user(
- $_SESSION["login"]["username"],
- $_SESSION["login"]["password"],
- $_POST["twofa"],
- );
- unset($_POST);
- } elseif (!empty($_SESSION["login"]["username"]) && !empty($_POST["password"])) {
- $error = authenticate_user($_SESSION["login"]["username"], $_POST["password"]);
- unset($_POST);
- }
- // Check system configuration
- load_hestia_config();
- // Detect language
- if (empty($_SESSION["language"])) {
- $output = "";
- exec(HESTIA_CMD . "v-list-sys-config json", $output, $return_var);
- $config = json_decode(implode("", $output), true);
- $lang = $config["config"]["LANGUAGE"];
- $output = "";
- exec(HESTIA_CMD . "v-list-sys-languages json", $output, $return_var);
- $languages = json_decode(implode("", $output), true);
- $_SESSION["language"] = in_array($lang, $languages) ? $lang : "en";
- }
- // Generate CSRF token
- $token = bin2hex(random_bytes(16));
- $_SESSION["token"] = $token;
- require_once "../templates/header.php";
- if (!empty($_SESSION["login"]["password"])) {
- require_once "../templates/pages/login/login_2.php";
- } elseif (empty($_SESSION["login"]["username"])) {
- require_once "../templates/pages/login/login" .
- ($_SESSION["LOGIN_STYLE"] != "old" ? "" : "_a") .
- ".php";
- } elseif (empty($_POST["password"])) {
- require_once "../templates/pages/login/login_1.php";
- } else {
- require_once "../templates/pages/login/login" .
- ($_SESSION["LOGIN_STYLE"] != "old" ? "" : "_a") .
- ".php";
- }
- require_once "../templates/includes/login-footer.php";
|