remote test & lots of fixes

This commit is contained in:
jusax23 2023-03-10 16:28:24 +01:00
parent 7b26048288
commit e2b931d6c5
Signed by: jusax23
GPG key ID: 499E2AA870C1CD41
16 changed files with 211 additions and 143 deletions

View file

@ -15,7 +15,8 @@ pipeline:
commands: commands:
- apk add openssl - apk add openssl
- sh genSelfSignedCert.sh - sh genSelfSignedCert.sh
- node tests/tester.js ci - node tests/ws.js ci
- node tests/post.js ci
buildBin: buildBin:
image: node:18 image: node:18
commands: commands:

View file

@ -1,8 +1,8 @@
import { eq, select, update } from "dblang"; import { eq, select, update } from "dblang";
import { PERMISSIONS } from "../../server/permissions.js"; import { PERMISSIONS } from "../../server/permissions.js";
import { selfTag } from "../../sys/config.js";
import { sha256, sign } from "../../sys/crypto.js"; import { sha256, sign } from "../../sys/crypto.js";
import { accounts, db } from "../../sys/db.js"; import { accounts, db } from "../../sys/db.js";
import { selfTag } from "../../sys/selfTag.js";
import { getSettings, SETTINGS } from "../../sys/settings.js"; import { getSettings, SETTINGS } from "../../sys/settings.js";
import { get64 } from "../../sys/tools.js"; import { get64 } from "../../sys/tools.js";
import { Client, STATE } from "../user.js"; import { Client, STATE } from "../user.js";

View file

@ -5,6 +5,7 @@ import { getRemote } from "../../server/serverCerts.js";
import { oConf } from "../../sys/config.js"; import { oConf } from "../../sys/config.js";
import { sha256, verify } from "../../sys/crypto.js"; import { sha256, verify } from "../../sys/crypto.js";
import { accounts, db, signupOTA as signupOTATable } from "../../sys/db.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 { get64, uts } from "../../sys/tools.js";
import { addTempToken, postClient } from "../post.js"; import { addTempToken, postClient } from "../post.js";
import { Act, Client, STATE } from "../user.js"; import { Act, Client, STATE } from "../user.js";
@ -56,7 +57,7 @@ export const signup: Act = {
client.state = STATE.client; client.state = STATE.client;
client.accID = accID; client.accID = accID;
client.name = data.name; 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 { } else {
client.suspect(); client.suspect();
@ -109,7 +110,7 @@ export const signupOTA = {
client.state = STATE.client; client.state = STATE.client;
client.accID = accID; client.accID = accID;
client.name = data.name; 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 { } else {
client.suspect(); client.suspect();
@ -148,7 +149,7 @@ export const signin = {
client.state = STATE.client; client.state = STATE.client;
client.accID = accID; client.accID = accID;
client.name = data.name; 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", sign: "string",
}, },
func: async (client: Client, data: any, aws: (code: string, data: any) => void) => { func: async (client: Client, data: any, aws: (code: string, data: any) => void) => {
let server = await outbagURLfromTag(data.server);
try { try {
let server = await outbagURLfromTag(data.server);
var cert = await getRemote(server); var cert = await getRemote(server);
console.log(server, cert);
var tagAcert = `${data.name}@${server.host}:${server.port}-${data.publicKey}`; var tagAcert = `${data.name}@${server.host}:${server.port}-${data.publicKey}`;
if (!(await verify(tagAcert, data.sign, cert))) { if (!(await verify(tagAcert, data.sign, cert))) {
client.suspect(); client.suspect();
console.log("verify");
aws("error", "signature"); aws("error", "signature");
return; return;
} }
@ -180,6 +183,7 @@ export const remote1 = {
client.remoteKey = data.publicKey; client.remoteKey = data.publicKey;
aws("ok", client.challenge); aws("ok", client.challenge);
} catch (e) { } catch (e) {
console.log(e);
client.suspect(); client.suspect();
aws("error", "signature"); aws("error", "signature");
} }

View file

@ -11,7 +11,7 @@ import { get64, uts } from "../sys/tools.js";
import { addShutdownTask } from "nman"; import { addShutdownTask } from "nman";
import { suspectRequest } from "../sys/bruteforce.js"; import { suspectRequest } from "../sys/bruteforce.js";
import { checkSelfTag, outbagServer } from "../server/outbagURL.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 }; let acts = importActs as { [key: string]: Act };
@ -56,7 +56,7 @@ export const addPostMethods = (server: express.Express) => {
aws("error", "data"); aws("error", "data");
return; 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 accountKey = auth?.params?.accountKey;
let query = await select([accounts.accID, accounts.accountKey, accounts.accountKeySalt], accounts) let query = await select([accounts.accID, accounts.accountKey, accounts.accountKeySalt], accounts)

View file

@ -8,7 +8,8 @@ import nman from "nman";
import cors from "cors"; import cors from "cors";
import { WebSocketServer } from "ws"; import { WebSocketServer } from "ws";
import { Command } from "commander"; 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 { error, log } from "./sys/log.js";
import { connectToDB } from "./sys/db.js"; import { connectToDB } from "./sys/db.js";
import bruteforce from "./sys/bruteforce.js"; import bruteforce from "./sys/bruteforce.js";
@ -37,7 +38,7 @@ program
.action(({ config, debug, setup }) => { .action(({ config, debug, setup }) => {
let dofullSetup = false; let dofullSetup = false;
global.debug = debug != null; global.debug = debug != null;
if(global.debug){ if (global.debug) {
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0"; process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0";
} }
if (config) { if (config) {
@ -103,7 +104,7 @@ async function startServer() {
async function complete_loaded() { async function complete_loaded() {
startUpdateCert(); await startUpdateCert();
await wait(500); await wait(500);
let succ = await generateTag(); 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!"); 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!");

View file

@ -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 WELL_KNOWN_PATH = "/.well-known/outbag/server";
const DEFAULT_PORT = "7223"; const DEFAULT_PORT = "7223";
@ -57,5 +57,5 @@ export class outbagServer {
}; };
export const checkSelfTag = (tag: string) => { 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;
} }

View file

@ -8,7 +8,7 @@ import nman, { addShutdownTask } from "nman";
import { insert } from "dblang"; import { insert } from "dblang";
import { db, servers } from "../sys/db.js"; import { db, servers } from "../sys/db.js";
export const startUpdateCert = () => { export const startUpdateCert = async () => {
const update = async () => { const update = async () => {
var exp = parseInt(await getSettings(SETTINGS.certExpires)); var exp = parseInt(await getSettings(SETTINGS.certExpires));
if (uts() - 60 >= (exp || 0)) { if (uts() - 60 >= (exp || 0)) {
@ -20,54 +20,13 @@ export const startUpdateCert = () => {
} }
}; };
let intervalId = setInterval(update, 1000 * 60); let intervalId = setInterval(update, 1000 * 60);
update(); await update();
nman.addShutdownTask(() => { nman.addShutdownTask(() => {
clearInterval(intervalId); clearInterval(intervalId);
}, 100); }, 100);
} }
/*async function updateRemote(server: outbagServer): Promise<boolean> {
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 deleteafter = 60 * 60;
const certList: { [key: string]: { exp: number, cert: string } } = {}; const certList: { [key: string]: { exp: number, cert: string } } = {};

View file

@ -1,6 +1,4 @@
import juml from "juml"; import juml from "juml";
import { outbagServer, outbagURLfromTag } from "../server/outbagURL.js";
import { debug } from "./log.js";
const conf_struct = { const conf_struct = {
System: { System: {
@ -32,39 +30,3 @@ const conf_struct = {
}; };
export const oConf = new juml(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;
}
};

View file

@ -33,7 +33,6 @@ export const warn = (name: string, ...args: any[]) => {
}; };
export const error = (name: string, ...args: any[]) => { export const error = (name: string, ...args: any[]) => {
args = consorArgs(args);
console.error( console.error(
"\x1b[33m%s\x1b[0m" + "\x1b[33m%s\x1b[0m" +
"\x1b[1m\x1b[41m%s\x1b[0m\x1b[41m", "\x1b[1m\x1b[41m%s\x1b[0m\x1b[41m",

39
src/sys/selfTag.ts Normal file
View file

@ -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;
}
};

View file

@ -1,3 +1,3 @@
export async function postTester(){ async function postTester(){
} }

View file

@ -10,7 +10,7 @@ process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
ls.stdout.on('data', (data) => { ls.stdout.on('data', (data) => {
process.stdout.write(data); process.stdout.write(data);
if(data.includes("Listening...")) test(); if (data.includes("Listening...")) test();
}); });
ls.stderr.on('data', (data) => { ls.stderr.on('data', (data) => {
@ -30,7 +30,7 @@ function kill() {
let startet = false; let startet = false;
async function test() { async function test() {
if(startet) return; if (startet) return;
startet = true; startet = true;
console.log("Start testing"); console.log("Start testing");
let url = "localhost:7224"; let url = "localhost:7224";

81
tests/tests/ws.js Normal file
View file

@ -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;

View file

@ -1,7 +1,28 @@
import WebSocket from 'ws'; import WebSocket from 'ws';
import { generateSigningKey, sign } from '../dist/sys/crypto.js';
import { uts, wait } from '../dist/sys/tools.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) { function conn(url) {
const ws = new WebSocket(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) { async function test(conn, act, data, expState, expData) {
console.log("Testing Act:", act, "with Data:", data); console.log("Testing Act:", act, "with Data:", data);
let resp = await conn.req(act, data); let resp = await conn.req(act, data);
@ -93,7 +114,7 @@ export async function wsTester(url, kill) {
kill(); kill();
process.exit(1); process.exit(1);
} }
} else { } else if (expData != null) {
if (expData != resp.data) { if (expData != resp.data) {
console.error(`Expected data: '${expData}', but got: '${resp.data}'`); console.error(`Expected data: '${expData}', but got: '${resp.data}'`);
kill(); kill();
@ -103,14 +124,14 @@ export async function wsTester(url, kill) {
return resp.data; return resp.data;
} }
for (const k in ws) { for (let i = 0; i < ws.length; i++) {
console.log(`Testing '${k}':`); const currTest = ws[i];
console.log(`Testing '${currTest[0]}':`);
const handler = [new conn(url)]; const handler = [new conn(url)];
await wait(100); await wait(100);
const currTest = ws[k];
let resp = true; let resp = true;
try { try {
resp = await currTest(handler[0], test, async ()=>{ resp = await currTest[1](handler[0], test, async () => {
let h = new conn(url); let h = new conn(url);
await wait(100); await wait(100);
handler.push(h); handler.push(h);
@ -122,7 +143,7 @@ export async function wsTester(url, kill) {
process.exit(1); process.exit(1);
} }
handler.forEach(h=>h.close()); handler.forEach(h => h.close());
if (resp === false) { if (resp === false) {
console.log("Test respond with error indication!"); console.log("Test respond with error indication!");
kill(); 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);
}

View file

@ -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");
};

View file

@ -1 +0,0 @@
export * from "./login.js";