From e2b931d6c5879ad5a5d138b8bfdf290a5435e123 Mon Sep 17 00:00:00 2001 From: jusax23 Date: Fri, 10 Mar 2023 16:28:24 +0100 Subject: [PATCH] remote test & lots of fixes --- .woodpecker.yml | 3 +- src/api/acts/client.ts | 2 +- src/api/acts/login.ts | 12 ++++-- src/api/post.ts | 4 +- src/main.ts | 7 ++-- src/server/outbagURL.ts | 4 +- src/server/serverCerts.ts | 45 +--------------------- src/sys/config.ts | 40 +------------------ src/sys/log.ts | 1 - src/sys/selfTag.ts | 39 +++++++++++++++++++ tests/post.js | 2 +- tests/tester.js | 6 +-- tests/tests/ws.js | 81 +++++++++++++++++++++++++++++++++++++++ tests/ws.js | 75 +++++++++++++++++++++++++++++++----- tests/ws/login.js | 32 ---------------- tests/ws/ws.js | 1 - 16 files changed, 211 insertions(+), 143 deletions(-) create mode 100644 src/sys/selfTag.ts create mode 100644 tests/tests/ws.js delete mode 100644 tests/ws/login.js delete mode 100644 tests/ws/ws.js diff --git a/.woodpecker.yml b/.woodpecker.yml index d8b01ed..f6d38ed 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -15,7 +15,8 @@ pipeline: commands: - apk add openssl - sh genSelfSignedCert.sh - - node tests/tester.js ci + - node tests/ws.js ci + - node tests/post.js ci buildBin: image: node:18 commands: diff --git a/src/api/acts/client.ts b/src/api/acts/client.ts index b2144f3..25b535b 100644 --- a/src/api/acts/client.ts +++ b/src/api/acts/client.ts @@ -1,8 +1,8 @@ import { eq, select, update } from "dblang"; import { PERMISSIONS } from "../../server/permissions.js"; -import { selfTag } from "../../sys/config.js"; import { sha256, sign } from "../../sys/crypto.js"; import { accounts, db } from "../../sys/db.js"; +import { selfTag } from "../../sys/selfTag.js"; import { getSettings, SETTINGS } from "../../sys/settings.js"; import { get64 } from "../../sys/tools.js"; import { Client, STATE } from "../user.js"; diff --git a/src/api/acts/login.ts b/src/api/acts/login.ts index 88debc5..caa2c98 100644 --- a/src/api/acts/login.ts +++ b/src/api/acts/login.ts @@ -5,6 +5,7 @@ import { getRemote } from "../../server/serverCerts.js"; import { oConf } from "../../sys/config.js"; import { sha256, verify } from "../../sys/crypto.js"; import { accounts, db, signupOTA as signupOTATable } from "../../sys/db.js"; +import { selfTag } from "../../sys/selfTag.js"; import { get64, uts } from "../../sys/tools.js"; import { addTempToken, postClient } from "../post.js"; import { Act, Client, STATE } from "../user.js"; @@ -56,7 +57,7 @@ export const signup: Act = { client.state = STATE.client; client.accID = accID; client.name = data.name; - client.server = new outbagServer(data.server, oConf.get("System", "URL") + "", oConf.get("System", "PATHexposed") + "", oConf.get("System", "PORTexposed") + ""); + client.server = new outbagServer(data.server, selfTag.host, selfTag.path, selfTag.port); } } else { client.suspect(); @@ -109,7 +110,7 @@ export const signupOTA = { client.state = STATE.client; client.accID = accID; client.name = data.name; - client.server = new outbagServer(data.server, oConf.get("System", "URL") + "", oConf.get("System", "PATHexposed") + "", oConf.get("System", "PORTexposed") + ""); + client.server = new outbagServer(data.server, selfTag.host, selfTag.path, selfTag.port); } } else { client.suspect(); @@ -148,7 +149,7 @@ export const signin = { client.state = STATE.client; client.accID = accID; client.name = data.name; - client.server = new outbagServer(data.server, oConf.get("System", "URL") + "", oConf.get("System", "PATHexposed") + "", oConf.get("System", "PORTexposed") + ""); + client.server = new outbagServer(data.server, selfTag.host, selfTag.path, selfTag.port); } } }; @@ -163,12 +164,14 @@ export const remote1 = { sign: "string", }, func: async (client: Client, data: any, aws: (code: string, data: any) => void) => { - let server = await outbagURLfromTag(data.server); try { + let server = await outbagURLfromTag(data.server); var cert = await getRemote(server); + console.log(server, cert); var tagAcert = `${data.name}@${server.host}:${server.port}-${data.publicKey}`; if (!(await verify(tagAcert, data.sign, cert))) { client.suspect(); + console.log("verify"); aws("error", "signature"); return; } @@ -180,6 +183,7 @@ export const remote1 = { client.remoteKey = data.publicKey; aws("ok", client.challenge); } catch (e) { + console.log(e); client.suspect(); aws("error", "signature"); } diff --git a/src/api/post.ts b/src/api/post.ts index f891bd8..376bd81 100644 --- a/src/api/post.ts +++ b/src/api/post.ts @@ -11,7 +11,7 @@ import { get64, uts } from "../sys/tools.js"; import { addShutdownTask } from "nman"; import { suspectRequest } from "../sys/bruteforce.js"; import { checkSelfTag, outbagServer } from "../server/outbagURL.js"; -import { oConf, selfTag } from "../sys/config.js"; +import { selfTag } from "../sys/selfTag.js"; let acts = importActs as { [key: string]: Act }; @@ -56,7 +56,7 @@ export const addPostMethods = (server: express.Express) => { aws("error", "data"); return; } - client.client.server = new outbagServer(serverTag, selfTag.host, selfTag.path, selfTag.port);; + client.client.server = new outbagServer(serverTag, selfTag.host, selfTag.path, selfTag.port); let accountKey = auth?.params?.accountKey; let query = await select([accounts.accID, accounts.accountKey, accounts.accountKeySalt], accounts) diff --git a/src/main.ts b/src/main.ts index 7dd7cca..2731ea2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,7 +8,8 @@ import nman from "nman"; import cors from "cors"; import { WebSocketServer } from "ws"; import { Command } from "commander"; -import { generateTag, oConf } from "./sys/config.js"; +import { oConf } from "./sys/config.js"; +import { generateTag } from "./sys/selfTag.js" import { error, log } from "./sys/log.js"; import { connectToDB } from "./sys/db.js"; import bruteforce from "./sys/bruteforce.js"; @@ -37,7 +38,7 @@ program .action(({ config, debug, setup }) => { let dofullSetup = false; global.debug = debug != null; - if(global.debug){ + if (global.debug) { process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0"; } if (config) { @@ -103,7 +104,7 @@ async function startServer() { async function complete_loaded() { - startUpdateCert(); + await startUpdateCert(); await wait(500); let succ = await generateTag(); if (!succ) error("Outbag", "Could not check own Server Tag. Remote-Auth may not work! Check if the Server is reachable and the config ist correct!"); diff --git a/src/server/outbagURL.ts b/src/server/outbagURL.ts index 23a779a..6756778 100644 --- a/src/server/outbagURL.ts +++ b/src/server/outbagURL.ts @@ -1,4 +1,4 @@ -import { oConf } from "../sys/config.js"; +import { selfTag } from "../sys/selfTag.js"; const WELL_KNOWN_PATH = "/.well-known/outbag/server"; const DEFAULT_PORT = "7223"; @@ -57,5 +57,5 @@ export class outbagServer { }; export const checkSelfTag = (tag: string) => { - return tag == oConf.get("System", "URL") || tag == oConf.get("System", "URL") + ":" + oConf.get("System", "PORTexposed") + return tag == selfTag.host || tag == selfTag.host + ":" + selfTag.port; } \ No newline at end of file diff --git a/src/server/serverCerts.ts b/src/server/serverCerts.ts index 1fb34a1..f568713 100644 --- a/src/server/serverCerts.ts +++ b/src/server/serverCerts.ts @@ -8,7 +8,7 @@ import nman, { addShutdownTask } from "nman"; import { insert } from "dblang"; import { db, servers } from "../sys/db.js"; -export const startUpdateCert = () => { +export const startUpdateCert = async () => { const update = async () => { var exp = parseInt(await getSettings(SETTINGS.certExpires)); if (uts() - 60 >= (exp || 0)) { @@ -20,54 +20,13 @@ export const startUpdateCert = () => { } }; let intervalId = setInterval(update, 1000 * 60); - update(); + await update(); nman.addShutdownTask(() => { clearInterval(intervalId); }, 100); } -/*async function updateRemote(server: outbagServer): Promise { - return new Promise((res, rej) => { - fetch(server.httpsURL + "api/server/publicKey") - .then(d => d.json()) - .then(async json => { - let { publicKey, expires } = json; - if (typeof publicKey == "string" && typeof expires == "string") { - try { - await insert(servers.url, servers.publicKey, servers.expires) - .add(server.tag, publicKey, expires) - .query(db); - } catch (error) { - await update(servers) - .set(servers.publicKey, publicKey) - .set(servers.expires, expires) - .where(eq(servers.url, server.tag)) - .query(db); - } - res(true); - } else { - if (publicKey.length > 0) { - res(publicKey); - return; - } - res(false); - } - }) - .catch((e) => { - error("serverCert", "fetch error:", e); - res(false); - }); - }); -}; - -export const getRemote = async (server: outbagServer) => { - await updateRemote(server); - let query = await select([servers.publicKey, servers.expires], servers) - .where(eq(servers.url, server.tag)) - .query(db); - return query[0][servers.publicKey]; -};*/ const deleteafter = 60 * 60; const certList: { [key: string]: { exp: number, cert: string } } = {}; diff --git a/src/sys/config.ts b/src/sys/config.ts index 381a2a4..843084c 100644 --- a/src/sys/config.ts +++ b/src/sys/config.ts @@ -1,6 +1,4 @@ import juml from "juml"; -import { outbagServer, outbagURLfromTag } from "../server/outbagURL.js"; -import { debug } from "./log.js"; const conf_struct = { System: { @@ -31,40 +29,4 @@ const conf_struct = { } }; -export const oConf = new juml(conf_struct); - -export let selfTag: outbagServer = new outbagServer( - "localhost", - oConf.get("System", "URL") + "", - oConf.get("System", "PATHexposed") + "", - oConf.get("System", "PORTexposed") + "", -); - -export const generateTag = async () => { - try { - selfTag = new outbagServer( - "localhost", - oConf.get("System", "URL") + "", - oConf.get("System", "PATHexposed") + "", - oConf.get("System", "PORTexposed") + "", - ); - let initselfTag = selfTag; - let mainServerHost: outbagServer | null = null; - try { - mainServerHost = await outbagURLfromTag(oConf.get("System", "URL")); - } catch (error) { } - let serverHostPort = await outbagURLfromTag( - oConf.get("System", "URL") + ":" + oConf.get("System", "PORTexposed")); - if (mainServerHost == null || mainServerHost.tag != serverHostPort.tag) { - selfTag = serverHostPort; - } else selfTag = mainServerHost; - if (initselfTag.httpsURL != selfTag.httpsURL) { - console.log(initselfTag, initselfTag.httpsURL, selfTag.httpsURL); - debug("Outbag", "Not matching Server host, port, path and expected server link."); - return false; - } - return true; - } catch (error) { - return false; - } -}; \ No newline at end of file +export const oConf = new juml(conf_struct); \ No newline at end of file diff --git a/src/sys/log.ts b/src/sys/log.ts index 5833b8e..2d15479 100644 --- a/src/sys/log.ts +++ b/src/sys/log.ts @@ -33,7 +33,6 @@ export const warn = (name: string, ...args: any[]) => { }; export const error = (name: string, ...args: any[]) => { - args = consorArgs(args); console.error( "\x1b[33m%s\x1b[0m" + "\x1b[1m\x1b[41m%s\x1b[0m\x1b[41m", diff --git a/src/sys/selfTag.ts b/src/sys/selfTag.ts new file mode 100644 index 0000000..96f2787 --- /dev/null +++ b/src/sys/selfTag.ts @@ -0,0 +1,39 @@ +import { outbagServer, outbagURLfromTag } from "../server/outbagURL.js"; +import {oConf} from "./config.js" +import { debug } from "./log.js"; + +export let selfTag: outbagServer = new outbagServer( + "localhost", + oConf.get("System", "URL") + "", + oConf.get("System", "PATHexposed") + "", + oConf.get("System", "PORTexposed") + "", +); + +export const generateTag = async () => { + try { + selfTag = new outbagServer( + "localhost", + oConf.get("System", "URL") + "", + oConf.get("System", "PATHexposed") + "", + oConf.get("System", "PORTexposed") + "", + ); + let initselfTag = selfTag; + let mainServerHost: outbagServer | null = null; + try { + mainServerHost = await outbagURLfromTag(oConf.get("System", "URL")); + } catch (error) { } + let serverHostPort = await outbagURLfromTag( + oConf.get("System", "URL") + ":" + oConf.get("System", "PORTexposed")); + if (mainServerHost == null || mainServerHost.tag != serverHostPort.tag) { + selfTag = serverHostPort; + } else selfTag = mainServerHost; + if (initselfTag.httpsURL != selfTag.httpsURL) { + console.log(initselfTag, initselfTag.httpsURL, selfTag.httpsURL); + debug("Outbag", "Not matching Server host, port, path and expected server link."); + return false; + } + return true; + } catch (error) { + return false; + } +}; \ No newline at end of file diff --git a/tests/post.js b/tests/post.js index 4a6ee4d..0b99f1a 100644 --- a/tests/post.js +++ b/tests/post.js @@ -1,3 +1,3 @@ -export async function postTester(){ +async function postTester(){ } \ No newline at end of file diff --git a/tests/tester.js b/tests/tester.js index 2d018af..3575adc 100644 --- a/tests/tester.js +++ b/tests/tester.js @@ -10,12 +10,12 @@ process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0; ls.stdout.on('data', (data) => { process.stdout.write(data); - if(data.includes("Listening...")) test(); + if (data.includes("Listening...")) test(); }); ls.stderr.on('data', (data) => { console.error(`stderr: ${data}`); - + }); ls.on('close', (code) => { @@ -30,7 +30,7 @@ function kill() { let startet = false; async function test() { - if(startet) return; + if (startet) return; startet = true; console.log("Start testing"); let url = "localhost:7224"; diff --git a/tests/tests/ws.js b/tests/tests/ws.js new file mode 100644 index 0000000..f4f8b61 --- /dev/null +++ b/tests/tests/ws.js @@ -0,0 +1,81 @@ +import { generateSigningKey, sign } from '../../dist/sys/crypto.js'; + +let name1 = "testUser1"; +let name2 = "testUser2"; +let name3 = "testUser3"; +let accountKey = "123456789"; + +let { privateKey, publicKey } = await generateSigningKey(); + +const list = [ + ["signup", async (handler, req, newHandler) => { + await req(handler, "signup", { + name: name1, + server: "localhost:7224", + accountKey + }, "ok", ""); + await req(handler, "signup", { + name: name1, + server: "localhost:7224", + accountKey + }, "error", "wrongstate"); + await req(await newHandler(), "signup", { + name: name1, + server: "localhost:7224", + accountKey + }, "error", "existence"); + await req(await newHandler(), "signup", { + name: name2, + server: "localhost:7224", + accountKey + }, "ok", ""); + await req(await newHandler(), "signup", { + name: name3, + server: "localhost:7224", + accountKey + }, "error", "config"); + }], ["remote", async (handler, req, newHandler) => { + await req(handler, "signin", { + name: name1, + server: "localhost:7224", + accountKey + }, "ok", ""); + let signature = await req(handler, "createSignature", { + publicKey + }, "ok", null); + let falseSignature = await sign("lol", privateKey); + let h2 = await newHandler(); + await req(h2, "remote1", { + name: name1, + server: "localhost:7223", + publicKey, + sign: signature + }, "error", "signature"); + await req(h2, "remote1", { + name: name1, + server: "localhost:7223", + publicKey, + sign: falseSignature + }, "error", "signature"); + let challenge = await req(h2, "remote1", { + name: name1, + server: "localhost:7224", + publicKey, + sign: signature + }, "ok", null); + await req(h2, "remote1", { + name: name1, + server: "localhost:7224", + publicKey, + sign: signature + }, "error", "wrongstate"); + await req(h2, "remote2", { + sign: await sign(challenge + "lol", privateKey) + }, "error", "signature"); + await req(h2, "remote2", { + sign: await sign(challenge, privateKey) + }, "ok", ""); + }] +]; + +export default list; \ No newline at end of file diff --git a/tests/ws.js b/tests/ws.js index c291972..310773e 100644 --- a/tests/ws.js +++ b/tests/ws.js @@ -1,7 +1,28 @@ import WebSocket from 'ws'; -import { generateSigningKey, sign } from '../dist/sys/crypto.js'; import { uts, wait } from '../dist/sys/tools.js'; -import * as ws from "./ws/ws.js" +import ws from "./tests/ws.js" +import { spawn } from "child_process"; +import { oConf } from "../dist/sys/config.js" +import mariadb from "mariadb"; + +let inCI = process.argv.includes("ci"); + +oConf.connect(inCI ? 'test.juml' : 'testLocal.juml'); + +const connection = await mariadb.createConnection({ + host: oConf.get("Database", "host"), + port: oConf.get("Database", "port"), + user: oConf.get("Database", "user"), + password: oConf.get("Database", "password"), + database: oConf.get("Database", "database"), + multipleStatements: true +}); +await wait(100); + +let req = await connection.query("SELECT table_name as n FROM information_schema.tables WHERE table_schema = ?;", [oConf.get("Database", "database")]); +let sql = [...req].map(d => "DROP TABLE IF EXISTS `" + d.n + "`;").join(""); +if (sql.length > 5) await connection.query("SET FOREIGN_KEY_CHECKS = 0;" + sql + "SET FOREIGN_KEY_CHECKS = 1;", []); +connection.close(); function conn(url) { const ws = new WebSocket(url); @@ -78,7 +99,7 @@ function shallowEqual(object1, object2) { -export async function wsTester(url, kill) { +async function wsTester(url) { async function test(conn, act, data, expState, expData) { console.log("Testing Act:", act, "with Data:", data); let resp = await conn.req(act, data); @@ -93,7 +114,7 @@ export async function wsTester(url, kill) { kill(); process.exit(1); } - } else { + } else if (expData != null) { if (expData != resp.data) { console.error(`Expected data: '${expData}', but got: '${resp.data}'`); kill(); @@ -103,14 +124,14 @@ export async function wsTester(url, kill) { return resp.data; } - for (const k in ws) { - console.log(`Testing '${k}':`); + for (let i = 0; i < ws.length; i++) { + const currTest = ws[i]; + console.log(`Testing '${currTest[0]}':`); const handler = [new conn(url)]; await wait(100); - const currTest = ws[k]; let resp = true; try { - resp = await currTest(handler[0], test, async ()=>{ + resp = await currTest[1](handler[0], test, async () => { let h = new conn(url); await wait(100); handler.push(h); @@ -121,8 +142,8 @@ export async function wsTester(url, kill) { kill(); process.exit(1); } - - handler.forEach(h=>h.close()); + + handler.forEach(h => h.close()); if (resp === false) { console.log("Test respond with error indication!"); kill(); @@ -130,3 +151,37 @@ export async function wsTester(url, kill) { } } } + + +const ls = spawn('node', ['.', '-c', inCI ? 'test.juml' : 'testLocal.juml', '-d']); + +process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0; + +ls.stdout.on('data', (data) => { + process.stdout.write(data); + if (data.includes("Listening...")) test(); +}); + +ls.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); +}); + +ls.on('close', (code) => { + console.log(`child process exited with code ${code}`); + process.exit(code); +}); + +function kill() { + ls.kill('SIGINT'); +} + +let startet = false; + +async function test() { + if (startet) return; + startet = true; + console.log("Start testing"); + await wsTester("wss://localhost:7224/"); + kill(); + process.exit(0); +} \ No newline at end of file diff --git a/tests/ws/login.js b/tests/ws/login.js deleted file mode 100644 index 3bf661a..0000000 --- a/tests/ws/login.js +++ /dev/null @@ -1,32 +0,0 @@ -let name1 = "testUser1"; -let name2 = "testUser2"; -let name3 = "testUser3"; -let accountKey = "123456789"; - -export const signup = async (handler, req, newHandler) => { - await req(handler, "signup", { - name: name1, - server: "localhost:7224", - accountKey - }, "ok", ""); - await req(handler, "signup", { - name: name1, - server: "localhost:7224", - accountKey - }, "error", "wrongstate"); - await req(await newHandler(), "signup", { - name: name1, - server: "localhost:7224", - accountKey - }, "error", "existence"); - await req(await newHandler(), "signup", { - name: name2, - server: "localhost:7224", - accountKey - }, "ok", ""); - await req(await newHandler(), "signup", { - name: name2, - server: "localhost:7224", - accountKey - }, "error", "config"); -}; \ No newline at end of file diff --git a/tests/ws/ws.js b/tests/ws/ws.js deleted file mode 100644 index 94d9888..0000000 --- a/tests/ws/ws.js +++ /dev/null @@ -1 +0,0 @@ -export * from "./login.js"; \ No newline at end of file