0) { znote2fa_trusted_device_issue($accountId); } header('Location: myaccount.php'); exit(); } $errors[] = t_default('twofa2.wrong_code', 'That code is not valid. It may have expired, or you may have mistyped it.'); } } if (isset($_SESSION['tfa2_pending']['id'])) { $pendingStatus = znote2fa_status((int)$_SESSION['tfa2_pending']['id']); if (empty($_POST['tfa2_email_sent']) && $pendingStatus['email_otp_enabled'] && !$pendingStatus['totp_enabled']) { $pendingUser = user_data((int)$_SESSION['tfa2_pending']['id'], 'email', 'name'); if (is_array($pendingUser) && !empty($pendingUser['email'])) { if (!znote2fa_email_send_code((int)$_SESSION['tfa2_pending']['id'], (string)$pendingUser['email'], (string)($pendingUser['name'] ?? ''))) { $errors[] = t_default('twofa2.email_delivery_failed', 'The verification e-mail could not be sent. Try again later or use a recovery code.'); } } else { $errors[] = t_default('twofa2.email_missing', 'This account has no valid e-mail address. Use a recovery code or contact an administrator.'); } } view('login_2fa'); theme_close(); exit(); } if (empty($_POST) === false && !isset($_POST['tfa2_code'])) { if ($config['log_ip']) { znote_visitor_insert_detailed_data(5); } $username = $_POST['username']; $password = $_POST['password']; $loginGuardIp = znote_login_guard_ip(); $loginGuardLockedFor = znote_login_guard_lockout_remaining($loginGuardIp); if ($loginGuardLockedFor > 0) { $errors[] = t('login.too_many_attempts', ['minutes' => (int)ceil($loginGuardLockedFor / 60)]); } else if (empty($username) || empty($password)) { $errors[] = t('login.empty_fields'); } else if (strlen($username) > 32 || strlen($password) > 64) { $errors[] = t('login.too_long'); } else if (user_exist($username) === false) { znote_login_guard_record($loginGuardIp, (string)$username, false); $errors[] = t('login.not_found'); } /*else if (user_activated($username) === false) { $errors[] = t('login.not_activated'); } */else if (!Token::isValid($_POST['token'] ?? null)) { $errors[] = t('login.token_invalid'); } else { // Starting login. Delegated to the server adapter, which knows whether // this engine identifies an account by name or id and which password // scheme it uses (see engine/adapter/). $login = znote_server_adapter()->login($username, $password); if ($login === false) { znote_login_guard_record($loginGuardIp, (string)$username, false); $errors[] = t('login.wrong_combo'); } else { znote_login_guard_record($loginGuardIp, (string)$username, true); // Check if user have access to login $status = false; if ($config['mailserver']['register']) { $authenticate = db()->fetchOne( "SELECT `id` FROM `znote_accounts` WHERE `account_id` = ? AND `active` = 1 LIMIT 1;", [(int)$login] ); if ($authenticate !== false) { $status = true; } else { $errors[] = t('login.not_activated'); } } else $status = true; if ($status) { // Regular login success, now lets check authentication token code if (znote_server_adapter()->supportsLegacyTwoFactor() && $config['twoFactorAuthenticator']) { require_once("engine/function/rfc6238.php"); // Two factor authentication code / token $authcode = (isset($_POST['authcode'])) ? getValue($_POST['authcode'] ?? null) : false; // Load secret values from db $query = db()->fetchOne( "SELECT `a`.`secret` AS `secret`, `za`.`secret` AS `znote_secret` FROM `accounts` AS `a` INNER JOIN `znote_accounts` AS `za` ON `a`.`id` = `za`.`account_id` WHERE `a`.`id` = ? LIMIT 1;", [(int)$login] ); if ($query === false) { $errors[] = t('login.failed_title'); $status = false; // If account table HAS a secret, we need to validate it } else if ($query['secret'] !== NULL) { // Validate the secret first to make sure all is good. if (TokenAuth6238::verify($query['secret'], $authcode) !== true) { $errors[] = t('login.2fa_wrong'); $errors[] = t('login.2fa_hint'); $status = false; } } else { // secret from accounts table is null/not set. Perhaps we can activate it: if ($query['znote_secret'] !== NULL && $authcode !== false && !empty($authcode)) { // Validate the secret first to make sure all is good. if (TokenAuth6238::verify($query['znote_secret'], $authcode)) { // Success, enable the 2FA system db()->execute( "UPDATE `accounts` SET `secret` = ? WHERE `id` = ?;", [$query['znote_secret'], (int)$login] ); } else { $errors[] = t('login.2fa_activate_failed'); $errors[] = t('login.2fa_wrong'); $errors[] = t('login.2fa_hint'); $status = false; } } } } // End tfs 1.0+ with 2FA auth if ($status) { if (!znote_session_regenerate()) { $errors[] = t('login.failed_title'); $status = false; } } if ($status) { $loginNameRow = user_data($login, 'id', 'name'); $isAdminAccount = has_admin_panel_access(is_array($loginNameRow) ? $loginNameRow : array()); if (znote2fa_required((int)$login, $isAdminAccount) && !znote2fa_trusted_device_check((int)$login)) { $_SESSION['tfa2_pending'] = array('id' => (int)$login, 'until' => time() + 300); header('Location: login.php'); exit(); } setSession('user_id', $login); $_SESSION['tfa2_sv'] = znote2fa_session_version((int)$login); Token::generate(); // if IP is not set (etc acc created before Znote AAC was in use) $znote_data = user_znote_account_data($login, 'ip'); if ($znote_data['ip'] == 0) { $update_data = array( 'ip' => getIPLong(), ); user_update_znote_account($update_data); } // Send them to myaccount.php header('Location: myaccount.php'); exit(); } } } } } if (empty($errors) === false) { header("HTTP/1.1 401 Not Found"); } if (empty($_POST) === true || empty($errors) === false) { view('login_form'); } theme_close(); ?>