| const { execSync } = require("child_process"); |
| const fs = require("fs"); |
| const readline = require("readline"); |
|
|
| const username = "user"; |
| const password = "root"; |
|
|
| |
|
|
| function run(cmd) { |
| console.log(`Running: ${cmd}`); |
| try { |
| execSync(cmd, { stdio: "inherit" }); |
| } catch (err) { |
| console.error(`Error: ${cmd}`); |
| } |
| } |
|
|
| |
|
|
| const PIN_FILE = "pin.lock"; |
| const ATTEMPT_FILE = "attempts.lock"; |
|
|
| const MAX_ATTEMPTS = 3; |
| const LOCK_TIME = 5 * 60 * 1000; |
|
|
| |
|
|
| const rl = readline.createInterface({ |
| input: process.stdin, |
| output: process.stdout |
| }); |
|
|
| function ask(q) { |
| return new Promise(resolve => rl.question(q, ans => resolve(ans.trim()))); |
| } |
|
|
| |
|
|
| function generatePIN() { |
| return Math.floor(1000 + Math.random() * 9000).toString(); |
| } |
|
|
| function loadPIN() { |
| if (!fs.existsSync(PIN_FILE)) { |
| const pin = generatePIN(); |
| fs.writeFileSync(PIN_FILE, JSON.stringify({ pin }, null, 2)); |
| console.log("New PIN created:", pin); |
| return pin; |
| } |
| return JSON.parse(fs.readFileSync(PIN_FILE)).pin; |
| } |
|
|
| function loadAttempts() { |
| if (!fs.existsSync(ATTEMPT_FILE)) { |
| return { attempts: 0, lockUntil: 0 }; |
| } |
| return JSON.parse(fs.readFileSync(ATTEMPT_FILE)); |
| } |
|
|
| function saveAttempts(data) { |
| fs.writeFileSync(ATTEMPT_FILE, JSON.stringify(data, null, 2)); |
| } |
|
|
| function timeLeft(ms) { |
| const sec = Math.max(0, Math.floor(ms / 1000)); |
| return { |
| min: Math.floor(sec / 60), |
| sec: sec % 60 |
| }; |
| } |
|
|
| |
|
|
| function install() { |
| console.log("\nStarting installation...\n"); |
|
|
| run("sudo apt update -y"); |
|
|
| run("wget -q --show-progress https://dl.google.com/linux/direct/chrome-remote-desktop_current_amd64.deb"); |
|
|
| run("sudo dpkg --install chrome-remote-desktop_current_amd64.deb"); |
| run("sudo apt-get install --fix-broken -y"); |
|
|
| run("sudo systemctl disable lightdm.service"); |
|
|
| run("sudo DEBIAN_FRONTEND=noninteractive apt-get install --assume-yes -y xfce4 desktop-base dbus-x11 xscreensaver"); |
|
|
| run(`sudo bash -c 'echo "exec /etc/X11/Xsession /usr/bin/xfce4-session" > /etc/chrome-remote-desktop-session'`); |
|
|
| run(`sudo useradd -m ${username}`); |
| run(`echo "${username}:${password}" | sudo chpasswd`); |
|
|
| run(`sudo sed -i 's#/bin/sh#/bin/bash#g' /etc/passwd`); |
|
|
| run("sudo add-apt-repository ppa:mozillateam/ppa -y"); |
| run("sudo apt update -y"); |
| run("sudo apt install firefox-esr -y"); |
|
|
| console.log("\nInstallation completed successfully"); |
| } |
|
|
| |
|
|
| async function loginFlow() { |
| const pin = loadPIN(); |
| const state = loadAttempts(); |
|
|
| if (state.lockUntil && Date.now() < state.lockUntil) { |
| const t = timeLeft(state.lockUntil - Date.now()); |
| console.log(`Too many failed attempts.`); |
| console.log(`Try again in ${t.min} min ${t.sec} sec`); |
| process.exit(1); |
| } |
|
|
| let inputPin = await ask("Enter PIN: "); |
|
|
| if (inputPin === pin) { |
| console.log("PIN correct. Access granted."); |
| saveAttempts({ attempts: 0, lockUntil: 0 }); |
| rl.close(); |
|
|
| |
| install(); |
| return; |
| } |
|
|
| state.attempts += 1; |
| console.log(`Wrong PIN (${state.attempts}/${MAX_ATTEMPTS})`); |
|
|
| if (state.attempts >= MAX_ATTEMPTS) { |
| state.lockUntil = Date.now() + LOCK_TIME; |
| state.attempts = 0; |
|
|
| const t = timeLeft(LOCK_TIME); |
| console.log(`Locked for ${t.min} min ${t.sec} sec`); |
|
|
| saveAttempts(state); |
| rl.close(); |
| process.exit(1); |
| } |
|
|
| saveAttempts(state); |
| rl.close(); |
| process.exit(1); |
| } |
|
|
| |
|
|
| async function setupPINIfNeeded() { |
| if (fs.existsSync(PIN_FILE)) return; |
|
|
| console.log("First time setup: Create PIN"); |
|
|
| let pin1 = await ask("Enter new 4-digit PIN: "); |
| let pin2 = await ask("Confirm PIN: "); |
|
|
| if (pin1 !== pin2) { |
| console.log("PIN mismatch. Try again."); |
| rl.close(); |
| process.exit(1); |
| } |
|
|
| fs.writeFileSync(PIN_FILE, JSON.stringify({ pin: pin1 }, null, 2)); |
| fs.writeFileSync(ATTEMPT_FILE, JSON.stringify({ attempts: 0, lockUntil: 0 }, null, 2)); |
|
|
| console.log("PIN created successfully."); |
| } |
|
|
| |
|
|
| (async () => { |
| await setupPINIfNeeded(); |
| await loginFlow(); |
| })(); |