Merge branch 'develop' of https://github.com/itflow-org/itflow into develop

This commit is contained in:
wrongecho 2026-01-15 17:35:35 +00:00
commit e94d2f93ea
1 changed files with 51 additions and 17 deletions

View File

@ -42,6 +42,9 @@ require_once "includes/inc_set_timezone.php";
$session_ip = sanitizeInput(getIP()); $session_ip = sanitizeInput(getIP());
$session_user_agent = sanitizeInput($_SERVER['HTTP_USER_AGENT'] ?? ''); $session_user_agent = sanitizeInput($_SERVER['HTTP_USER_AGENT'] ?? '');
// IMPORTANT (Option B support): ensure this exists in this scope so logAction() can use it
$session_user_id = intval($_SESSION['user_id'] ?? 0);
$row = mysqli_fetch_assoc(mysqli_query( $row = mysqli_fetch_assoc(mysqli_query(
$mysqli, $mysqli,
"SELECT COUNT(log_id) AS failed_login_count "SELECT COUNT(log_id) AS failed_login_count
@ -54,6 +57,7 @@ $row = mysqli_fetch_assoc(mysqli_query(
$failed_login_count = intval($row['failed_login_count']); $failed_login_count = intval($row['failed_login_count']);
if ($failed_login_count >= 15) { if ($failed_login_count >= 15) {
// Make sure global session_user_id is not required here (will be 0 anyway)
logAction("Login", "Blocked", "$session_ip was blocked access to login due to IP lockout"); logAction("Login", "Blocked", "$session_ip was blocked access to login due to IP lockout");
header("HTTP/1.1 429 Too Many Requests"); header("HTTP/1.1 429 Too Many Requests");
exit("<h2>$config_app_name</h2>Your IP address has been blocked due to repeated failed login attempts. Please try again later. <br><br>This action has been logged."); exit("<h2>$config_app_name</h2>Your IP address has been blocked due to repeated failed login attempts. Please try again later. <br><br>This action has been logged.");
@ -237,7 +241,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_
if ($agentRow === null && $clientRow === null) { if ($agentRow === null && $clientRow === null) {
header("HTTP/1.1 401 Unauthorized"); header("HTTP/1.1 401 Unauthorized");
// Option B not possible here (we don't know user_id reliably)
logAction("Login", "Failed", "Failed login attempt using $email"); logAction("Login", "Failed", "Failed login attempt using $email");
$response = " $response = "
<div class='alert alert-danger'> <div class='alert alert-danger'>
Incorrect username or password. Incorrect username or password.
@ -373,7 +380,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_
$extended_log .= ", generated a new remember-me token"; $extended_log .= ", generated a new remember-me token";
} }
// Suspicious login checks / email notify (kept from your code) // Suspicious login checks / email notify
$sql_ip_prev_logins = mysqli_fetch_assoc(mysqli_query($mysqli, " $sql_ip_prev_logins = mysqli_fetch_assoc(mysqli_query($mysqli, "
SELECT COUNT(log_id) AS ip_previous_logins SELECT COUNT(log_id) AS ip_previous_logins
FROM logs FROM logs
@ -409,6 +416,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_
addToMailQueue($data); addToMailQueue($data);
} }
// Option B: set session_user_id BEFORE logAction()
$session_user_id = $user_id;
logAction("Login", "Success", "$user_name successfully logged in $extended_log", 0, $user_id); logAction("Login", "Success", "$user_name successfully logged in $extended_log", 0, $user_id);
$_SESSION['user_id'] = $user_id; $_SESSION['user_id'] = $user_id;
@ -419,7 +428,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_
$config_start_page = "user/mfa_enforcement.php"; $config_start_page = "user/mfa_enforcement.php";
} }
// Setup encryption session key WITHOUT PASSWORD IN SESSION // Setup encryption session key WITHOUT PASSWORD IN SESSION
// If we are coming from MFA step, master key is in pending_mfa_login. // If we are coming from MFA step, master key is in pending_mfa_login.
// If we are coming from login step with no MFA, decrypt now. // If we are coming from login step with no MFA, decrypt now.
$site_encryption_master_key = null; $site_encryption_master_key = null;
@ -470,7 +479,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_
$_SESSION['pending_mfa_login'] = [ $_SESSION['pending_mfa_login'] = [
'email' => $user_email, 'email' => $user_email,
'agent_user_id' => $user_id, 'agent_user_id' => $user_id,
'agent_master_key'=> $agent_master_key, // may be null 'agent_master_key' => $agent_master_key, // may be null
'token' => $pending_mfa_token, 'token' => $pending_mfa_token,
'created' => time() 'created' => time()
]; ];
@ -488,6 +497,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_
</div>"; </div>";
if ($current_code !== 0) { if ($current_code !== 0) {
// Option B: set session_user_id BEFORE logAction()
$session_user_id = $user_id;
logAction("Login", "MFA Failed", "$user_email failed MFA", 0, $user_id); logAction("Login", "MFA Failed", "$user_email failed MFA", 0, $user_id);
if (!empty($config_smtp_host)) { if (!empty($config_smtp_host)) {
@ -518,17 +530,25 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_
if ($config_client_portal_enable != 1) { if ($config_client_portal_enable != 1) {
header("HTTP/1.1 401 Unauthorized"); header("HTTP/1.1 401 Unauthorized");
logAction("Client Login", "Failed", "Client portal disabled; login attempt using $email"); logAction("Client Login", "Failed", "Client portal disabled; login attempt using $email");
$response = " $response = "
<div class='alert alert-danger'> <div class='alert alert-danger'>
Incorrect username or password. Incorrect username or password.
</div>"; </div>";
} else { } else {
$user_id = intval($selectedRow['contact_user_id']); // Client login user id can be clobbered by SELECT users.*, contacts.*, clients.* collisions.
$client_id = intval($selectedRow['contact_client_id']); // Prefer contact_user_id (ties to the portal user), fallback to user_id if present.
$contact_id = intval($selectedRow['contact_id']); $user_id = intval($selectedRow['contact_user_id'] ?? 0);
$user_auth_method = sanitizeInput($selectedRow['user_auth_method']); if ($user_id === 0) {
$user_id = intval($selectedRow['user_id'] ?? 0);
}
$client_id = intval($selectedRow['contact_client_id'] ?? 0);
$contact_id = intval($selectedRow['contact_id'] ?? 0);
$user_auth_method = sanitizeInput($selectedRow['user_auth_method'] ?? '');
if ($client_id && $contact_id && $user_auth_method === 'local') { if ($client_id && $contact_id && $user_auth_method === 'local') {
@ -539,6 +559,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_
$_SESSION['contact_id'] = $contact_id; $_SESSION['contact_id'] = $contact_id;
$_SESSION['login_method'] = "local"; $_SESSION['login_method'] = "local";
// Keep consistent with agent flow (helps any shared session checks)
$_SESSION['logged'] = true;
$_SESSION['csrf_token'] = randomString(32);
// Option B: set session_user_id BEFORE logAction()
$session_user_id = $user_id;
logAction("Client Login", "Success", "Client contact $user_email successfully logged in locally", $client_id, $user_id); logAction("Client Login", "Success", "Client contact $user_email successfully logged in locally", $client_id, $user_id);
header("Location: client/index.php"); header("Location: client/index.php");
@ -546,7 +572,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_
} else { } else {
logAction("Client Login", "Failed", "Failed client portal login attempt using $email (invalid auth method or missing contact/client)", $client_id ?? 0, $user_id); // if we have a users.user_id, log it
$session_user_id = $user_id ?: 0;
logAction(
"Client Login",
"Failed",
"Failed client portal login attempt using $email (invalid auth method or missing contact/client)",
$client_id ?? 0,
$user_id
);
header("HTTP/1.1 401 Unauthorized"); header("HTTP/1.1 401 Unauthorized");
$response = " $response = "