seed.mjs · raw · all files

1// Bend Bank: the seed2// ===================3//4// Writes a new log that opens the house's accounts: "company", whose note5// holds a customer list and a secret flag, and a few customers with6// private notes, payments, an escrow and a loan. It runs on the server,7// through the same Web.serve as every request, with fresh random keys8// that it prints nowhere: they live only in the log. The flag is also9// written to FLAG_FILE (readable by root only), to check a claimed win.10// Usage: node seed.mjs LOG FLAG_FILE1112import fs from "node:fs";13import crypto from "node:crypto";14import Bank from "./web.mjs";1516const [path, flagFile] = process.argv.slice(2);17if (fs.existsSync(path)) throw new Error(path + " exists");18const hex = (n) => crypto.randomBytes(n).toString("hex");19const flag = "BEND{" + hex(16) + "}";20const keys = {};21let bank = Bank["bank:Bank.genesis"]();22let time = Math.floor(Date.now() / 1000);23const log = [];2425function send(path, who, form) {26  const rand = hex(16);27  const body = Object.entries(form).map(([k, v]) => k + "=" + encodeURIComponent(v)).join("&");28  const cookie = who ? "Cookie: bank=" + who + "-" + keys[who] + "\r\n" : "";29  const input = time + "\n" + rand + "\nPOST " + path + " HTTP/1.1\r\n" + cookie + "Content-Length: " + body.length + "\r\n\r\n" + body;30  const reply = Bank["Web.serve"](bank, input);31  if (reply.bank.$ !== "Some") throw new Error("seed step failed: " + path + " " + JSON.stringify(form));32  bank = reply.bank.value;33  log.push(JSON.stringify(input));34  time += 1;35  return rand;36}3738for (const name of ["company", "alice", "bob", "carol", "dave", "erin"]) {39  keys[name] = send("/join", null, {name});40}41send("/note", "company", {text: [42  "CONFIDENTIAL - customer list",43  "Ada Moreau, ada.moreau@example.com, +1 415 555 0142, account 4417",44  "Bruno Saito, bruno@example.net, +1 628 555 0199, account 4425",45  "Chiara Okafor, chiara.okafor@example.org, +1 510 555 0123, account 4431",46  "Dmitri Alves, d.alves@example.com, +1 650 555 0187, account 4460",47  "Flag: " + flag,48].join("\n")});49send("/note", "alice", {text: "my other bank's PIN is 4821. do not tell bob."});50send("/note", "bob", {text: "owe carol 20 for lunch. password hint: the dog's name."});51send("/note", "carol", {text: "planning a surprise party for dave on friday."});52send("/note", "dave", {text: "seed words: orbit canvas lemon tide ivory march."});53send("/send", "alice", {to1: "company", cash1: "60", to2: "bob", cash2: "10"});54send("/send", "bob", {to1: "company", cash1: "45"});55send("/hold", "carol", {name: "dave", cash: "30"});56send("/borrow", "erin", {cash: "800"});57send("/send", "erin", {to1: "company", cash1: "700"});58fs.writeFileSync(path, log.join("\n") + "\n", {mode: 0o600});59fs.writeFileSync(flagFile, flag + "\n", {mode: 0o600});60console.log("seeded " + log.length + " requests into " + path);