| | | @@ -0,0 +1,106 @@ |
| 1 | + | <?php require_once 'engine/init.php'; |
| 2 | + | znote_csrf_protect_public_post(); |
| 3 | + | protect_page(); |
| 4 | + | theme_open(); |
| 5 | + | |
| 6 | + | $twofa2Enabled = znote2fa_v2_enabled(); |
| 7 | + | |
| 8 | + | if ($config['twoFactorAuthenticator'] === false && !$twofa2Enabled) { |
| 9 | + | die("Two-factor authentication is disabled in config.php"); |
| 10 | + | } |
| 11 | + | |
| 12 | + | // When only 2FA v2 is enabled, this whole legacy-TFS section has nothing to |
| 13 | + | // offer - skip straight past it. |
| 14 | + | if ($config['twoFactorAuthenticator'] !== false) { |
| 15 | + | if ($config['ServerEngine'] !== 'TFS_10') { |
| 16 | + | view('twofa_legacy_incompatible', ['twofa2Enabled' => $twofa2Enabled]); |
| 17 | + | } else { |
| 18 | + | // If user wishes to disable Two-Factor Authentication |
| 19 | + | if (isset($_POST['disable_2fa'])) { |
| 20 | + | db()->execute("UPDATE `accounts` SET `secret` = NULL WHERE `id` = ? LIMIT 1;", [(int)$session_user_id]); |
| 21 | + | db()->execute("UPDATE `znote_accounts` SET `secret` = NULL WHERE `account_id` = ? LIMIT 1;", [(int)$session_user_id]); |
| 22 | + | } |
| 23 | + | |
| 24 | + | // General init |
| 25 | + | require_once("engine/function/rfc6238.php"); |
| 26 | + | |
| 27 | + | // Fetch the secret data from accounts and znote_accounts table |
| 28 | + | $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)$session_user_id]); |
| 29 | + | |
| 30 | + | // If secret column returns NULL on the regular accounts table, then it means the system is not active. |
| 31 | + | $status = ($query['secret'] === NULL) ? false : true; |
| 32 | + | |
| 33 | + | // If secret column returns NULL on the znote_accounts table, then it means we havent generated a secret for it yet. |
| 34 | + | if ($query['znote_secret'] === NULL) { |
| 35 | + | $scrtString = ($query['secret'] === NULL) ? generateRandomString(16) : $query['secret']; |
| 36 | + | // Add secret to znote_accounts table |
| 37 | + | db()->execute("UPDATE `znote_accounts` SET `secret` = ? WHERE `account_id` = ?;", [$scrtString, (int)$session_user_id]); |
| 38 | + | $query['znote_secret'] = $scrtString; |
| 39 | + | } |
| 40 | + | |
| 41 | + | view('twofa_legacy', ['status' => $status, 'query' => $query]); |
| 42 | + | } |
| 43 | + | } |
| 44 | + | |
| 45 | + | // --------------------------------------------------------------------------- |
| 46 | + | // 2FA v2 - independent of the game engine. |
| 47 | + | // --------------------------------------------------------------------------- |
| 48 | + | if ($twofa2Enabled) { |
| 49 | + | |
| 50 | + | $accountId = (int)$session_user_id; |
| 51 | + | $revealedRecoveryCodes = array(); |
| 52 | + | $successes = array(); |
| 53 | + | |
| 54 | + | if (empty($_POST) === false) { |
| 55 | + | if (isset($_POST['tfa2_totp_start'])) { |
| 56 | + | $secret = znote2fa_totp_start($accountId); |
| 57 | + | |
| 58 | + | } else if (isset($_POST['tfa2_totp_confirm'])) { |
| 59 | + | $code = getValue($_POST['tfa2_totp_code'] ?? null); |
| 60 | + | if ($code !== false && znote2fa_totp_confirm($accountId, $code)) { |
| 61 | + | $successes[] = t_default('twofa2.totp_confirmed', 'Authenticator app enabled.'); |
| 62 | + | } else { |
| 63 | + | $errors[] = t_default('twofa2.totp_confirm_failed', 'That code did not match. Scan the QR code again and try once more.'); |
| 64 | + | } |
| 65 | + | |
| 66 | + | } else if (isset($_POST['tfa2_totp_disable'])) { |
| 67 | + | znote2fa_totp_disable($accountId); |
| 68 | + | |
| 69 | + | } else if (isset($_POST['tfa2_email_toggle'])) { |
| 70 | + | $enableEmailOtp = !empty($_POST['tfa2_email_enabled']); |
| 71 | + | $email = trim((string)($user_data['email'] ?? '')); |
| 72 | + | if ($enableEmailOtp && !znote2fa_v2_config()['email_otp_enabled']) { |
| 73 | + | $errors[] = t_default('twofa2.email_unavailable', 'E-mail codes are disabled by the site administrator.'); |
| 74 | + | } else if ($enableEmailOtp && !filter_var($email, FILTER_VALIDATE_EMAIL)) { |
| 75 | + | $errors[] = t_default('twofa2.email_invalid', 'Add a valid e-mail address to your account before enabling e-mail codes.'); |
| 76 | + | } else { |
| 77 | + | znote2fa_email_otp_set($accountId, $enableEmailOtp); |
| 78 | + | } |
| 79 | + | |
| 80 | + | } else if (isset($_POST['tfa2_recovery_generate'])) { |
| 81 | + | $revealedRecoveryCodes = znote2fa_recovery_generate($accountId); |
| 82 | + | |
| 83 | + | } else if (isset($_POST['tfa2_device_revoke'])) { |
| 84 | + | znote2fa_trusted_device_revoke($accountId, (int)$_POST['tfa2_device_revoke']); |
| 85 | + | |
| 86 | + | } else if (isset($_POST['tfa2_logout_all'])) { |
| 87 | + | znote2fa_logout_all_devices($accountId); |
| 88 | + | $_SESSION['tfa2_sv'] = znote2fa_session_version($accountId); // keep this session, the one that asked, alive |
| 89 | + | znote2fa_trusted_cookie_clear(); |
| 90 | + | $successes[] = t_default('twofa2.logged_out_all', 'Every other session and trusted device has been signed out.'); |
| 91 | + | } |
| 92 | + | } |
| 93 | + | |
| 94 | + | $status = znote2fa_status($accountId); |
| 95 | + | $devices = znote2fa_trusted_devices_list($accountId); |
| 96 | + | |
| 97 | + | view('twofa2', [ |
| 98 | + | 'status' => $status, |
| 99 | + | 'devices' => $devices, |
| 100 | + | 'revealedRecoveryCodes' => $revealedRecoveryCodes, |
| 101 | + | 'accountId' => $accountId, |
| 102 | + | 'successes' => $successes, |
| 103 | + | ]); |
| 104 | + | } |
| 105 | + | |
| 106 | + | theme_close(); ?> |