server Tag
This commit is contained in:
parent
8accb3fd2f
commit
60069c86af
10 changed files with 183 additions and 110 deletions
|
@ -1,7 +1,6 @@
|
|||
import { eq, select, update } from "dblang";
|
||||
import { outbagURLshort } from "../../server/outbagURL.js";
|
||||
import { PERMISSIONS } from "../../server/permissions.js";
|
||||
import { oConf } from "../../sys/config.js";
|
||||
import { selfTag } from "../../sys/config.js";
|
||||
import { sha256, sign } from "../../sys/crypto.js";
|
||||
import { accounts, db } from "../../sys/db.js";
|
||||
import { getSettings, SETTINGS } from "../../sys/settings.js";
|
||||
|
@ -30,8 +29,8 @@ export const createSignature = {
|
|||
publicKey: "string"
|
||||
},
|
||||
func: async (client: Client, data: any, aws: (code: string, data: any) => void) => {
|
||||
const server = await outbagURLshort(oConf.get("System", "URL") + ":" + oConf.get("System", "PORTexposed"));
|
||||
const tag = client.name + "@" + server + "-" + data.publicKey;
|
||||
const server = selfTag;
|
||||
const tag = `${client.name}@${server.host}:${server.port}-${data.publicKey}`;
|
||||
var signature = await sign(tag, await getSettings(SETTINGS.privateKey));
|
||||
aws("ok", signature);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { select, count, alias, insert, remove, le, update, minus, eq, and } from "dblang";
|
||||
import { outbagURLshort } from "../../server/outbagURL.js";
|
||||
import { outbagURLfromTag } from "../../server/outbagURL.js";
|
||||
import { PERMISSIONS } from "../../server/permissions.js";
|
||||
import { getRemote } from "../../server/serverCerts.js";
|
||||
import { oConf } from "../../sys/config.js";
|
||||
import { localhostTag, oConf } from "../../sys/config.js";
|
||||
import { sha256, verify } from "../../sys/crypto.js";
|
||||
import { accounts, db, signupOTA as signupOTATable } from "../../sys/db.js";
|
||||
import { get64, uts } from "../../sys/tools.js";
|
||||
|
@ -50,7 +50,7 @@ export const signup: Act = {
|
|||
client.state = STATE.client;
|
||||
client.accID = accID;
|
||||
client.name = data.name;
|
||||
client.server = "localhost";
|
||||
client.server = localhostTag;
|
||||
}
|
||||
} else {
|
||||
client.suspect();
|
||||
|
@ -92,7 +92,7 @@ export const signupOTA = {
|
|||
client.state = STATE.client;
|
||||
client.accID = accID;
|
||||
client.name = data.name;
|
||||
client.server = "localhost";
|
||||
client.server = localhostTag;
|
||||
}
|
||||
} else {
|
||||
client.suspect();
|
||||
|
@ -126,7 +126,7 @@ export const signin = {
|
|||
client.state = STATE.client;
|
||||
client.accID = accID;
|
||||
client.name = data.name;
|
||||
client.server = "localhost";
|
||||
client.server = localhostTag;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -141,9 +141,9 @@ export const remote1 = {
|
|||
sign: "string",
|
||||
},
|
||||
func: async (client: Client, data: any, aws: (code: string, data: any) => void) => {
|
||||
data.server = await outbagURLshort(data.server);
|
||||
let server = await outbagURLfromTag(data.server);
|
||||
try {
|
||||
var cert = await getRemote(data.server);
|
||||
var cert = await getRemote(server);
|
||||
var tagAcert = data.name + "@" + data.server + "-" + data.key;
|
||||
if (!(await verify(tagAcert, data.sign, cert))) {
|
||||
client.suspect();
|
||||
|
@ -152,7 +152,7 @@ export const remote1 = {
|
|||
}
|
||||
|
||||
client.name = data.name;
|
||||
client.server = data.server;
|
||||
client.server = server;
|
||||
client.challenge = get64(64);
|
||||
client.state = STATE.remoteP;
|
||||
client.remoteKey = data.key;
|
||||
|
|
|
@ -10,15 +10,24 @@ import { sha256 } from "../sys/crypto.js";
|
|||
import { get64, uts } from "../sys/tools.js";
|
||||
import { addShutdownTask } from "nman";
|
||||
import { suspectRequest } from "../sys/bruteforce.js";
|
||||
import { localhostTag } from "../sys/config.js";
|
||||
|
||||
let acts = importActs as { [key: string]: Act };
|
||||
|
||||
let tempTokens: { [key: string]: postClient } = {};
|
||||
|
||||
let activePost = false;
|
||||
export const activatePost = () => { activePost = true; };
|
||||
|
||||
export const addPostMethods = (server: express.Express) => {
|
||||
for (const act in acts) {
|
||||
let methode = acts[act];
|
||||
server.post("/api/" + act, async (req: suspectRequest, res) => {
|
||||
if (!activePost) {
|
||||
res.status(500);
|
||||
res.send("not active");
|
||||
return;
|
||||
}
|
||||
debug("POST", "reveived:", req.body);
|
||||
const aws = (state: string, data: any) => {
|
||||
res.status(state == "error" ? 400 : 200);
|
||||
|
@ -29,7 +38,7 @@ export const addPostMethods = (server: express.Express) => {
|
|||
try {
|
||||
let auth = authorization.parse(req.headers["authorization"] ?? "");
|
||||
if (auth.scheme == "outbagServer") {
|
||||
|
||||
|
||||
} else if (auth.token != null && typeof auth.token == "string") {
|
||||
if (tempTokens[auth.token] != null) {
|
||||
client = tempTokens[auth.token];
|
||||
|
@ -41,7 +50,7 @@ export const addPostMethods = (server: express.Express) => {
|
|||
} else if (auth?.params?.name != null && auth?.params?.accountKey != null && typeof auth?.params?.name == "string" && typeof auth?.params?.accountKey == "string") {
|
||||
client = new postClient(req.ip);
|
||||
client.name = auth?.params?.name;
|
||||
client.server = "localhost";
|
||||
client.server = localhostTag;
|
||||
let accountKey = auth?.params?.accountKey;
|
||||
|
||||
let query = await select([accounts.accID, accounts.accountKey, accounts.accountKeySalt], accounts)
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
import { and, eq, naturalJoin, select, update } from "dblang";
|
||||
import { accounts, db, roomMembers, rooms } from "../sys/db.js";
|
||||
import { addBruteforcePotantial } from "../sys/bruteforce.js";
|
||||
import { outbagServer } from "../server/outbagURL.js";
|
||||
|
||||
export const STATE = {
|
||||
no: 0b00001,
|
||||
no: 0b00001,
|
||||
remoteP: 0b00010,
|
||||
remote: 0b00100,
|
||||
client: 0b01000,
|
||||
server: 0b10000,
|
||||
remote: 0b00100,
|
||||
client: 0b01000,
|
||||
server: 0b10000,
|
||||
};
|
||||
|
||||
export const MODE = {
|
||||
ws: 0b01,
|
||||
ws: 0b01,
|
||||
post: 0b10,
|
||||
both: 0b11,
|
||||
};
|
||||
|
@ -27,7 +28,7 @@ export type Act = {
|
|||
|
||||
export class Client {
|
||||
name: string = "";
|
||||
server: string = "";
|
||||
server: outbagServer;
|
||||
ip: string = "";
|
||||
state: number = STATE.no;
|
||||
|
||||
|
@ -36,6 +37,7 @@ export class Client {
|
|||
remoteKey: string = "";
|
||||
|
||||
constructor(ip: string) {
|
||||
this.server = new outbagServer("", "", "", "");
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
|
@ -49,7 +51,7 @@ export class Client {
|
|||
.where(and(
|
||||
eq(rooms.name, name),
|
||||
eq(roomMembers.name, this.name),
|
||||
eq(roomMembers.server, this.server)
|
||||
eq(roomMembers.server, this.server.tag)
|
||||
))
|
||||
.query(db);
|
||||
if (query.length == 0) return -1;
|
||||
|
@ -62,7 +64,7 @@ export class Client {
|
|||
eq(rooms.name, name),
|
||||
eq(roomMembers.admin, true),
|
||||
eq(roomMembers.name, this.name),
|
||||
eq(roomMembers.server, this.server)
|
||||
eq(roomMembers.server, this.server.tag)
|
||||
))
|
||||
.query(db);
|
||||
if (query.length == 0) return -1;
|
||||
|
|
|
@ -7,9 +7,12 @@ import * as importActs from "./acts.js"
|
|||
|
||||
let acts = importActs as { [key: string]: Act };
|
||||
|
||||
let activeWS = false;
|
||||
export const activatePost = () => { activeWS = true; };
|
||||
|
||||
export const wsOnConnection = (socket: ws.WebSocket, req: http.IncomingMessage) => {
|
||||
let ip = req.socket.remoteAddress;
|
||||
if (bruteforcecheck(ip ?? "")) return void socket.close();
|
||||
if (!activeWS || bruteforcecheck(ip ?? "")) return void socket.close();
|
||||
new wsClient(socket, req);
|
||||
}
|
||||
|
||||
|
|
17
src/main.ts
17
src/main.ts
|
@ -8,15 +8,15 @@ import nman from "nman";
|
|||
import cors from "cors";
|
||||
import { WebSocketServer } from "ws";
|
||||
import { Command } from "commander";
|
||||
import { oConf } from "./sys/config.js";
|
||||
import { generateTag, oConf } from "./sys/config.js";
|
||||
import { error, log } from "./sys/log.js";
|
||||
import { connectToDB } from "./sys/db.js";
|
||||
import bruteforce, { suspectRequest } from "./sys/bruteforce.js";
|
||||
import bruteforce from "./sys/bruteforce.js";
|
||||
import { fullSetup, partiellSetup } from "./setup/config.js";
|
||||
import { addGetMethods } from "./api/get.js";
|
||||
import { addPostMethods } from "./api/post.js";
|
||||
import { wsOnConnection } from "./api/ws.js";
|
||||
import { startUpdateCerts } from "./server/serverCerts.js";
|
||||
import { startUpdateCert } from "./server/serverCerts.js";
|
||||
|
||||
|
||||
const config = {
|
||||
|
@ -52,6 +52,8 @@ program
|
|||
|
||||
program.parse();
|
||||
|
||||
const activeRequest = false;
|
||||
|
||||
var serverclose = { close: (d: () => void) => d() };
|
||||
nman.addShutdownTask(() => new Promise(async (res, rej) => {
|
||||
//await closeWebSocket();
|
||||
|
@ -96,6 +98,9 @@ async function startServer() {
|
|||
}
|
||||
|
||||
|
||||
function complete_loaded() {
|
||||
startUpdateCerts();
|
||||
}
|
||||
async function complete_loaded() {
|
||||
startUpdateCert();
|
||||
let succ = await generateTag();
|
||||
if(!succ) error("System", "Could not resolve own Server Tag. Remote-Auth will not work! Check if the Server is reachable and the config ist correct!");
|
||||
|
||||
}
|
|
@ -1,59 +1,55 @@
|
|||
const WELL_KNOWN_PATH = "/.well-known/outbag/server";
|
||||
const DEFAULT_PORT = 7223;
|
||||
const DEFAULT_PORT = "7223";
|
||||
|
||||
export const outbagURL = (url: string, prefix = "https") => new Promise((res, rej) => {
|
||||
const fetchWellknown = async (uri: URL) => {
|
||||
uri = new URL(uri);
|
||||
let resp = await fetch(uri);
|
||||
let json = await resp.json();
|
||||
if (json.path == null || json.port == null) throw new Error("NotAValidWellKnown");
|
||||
return { host: uri.hostname, path: json.path as string, port: json.port as string };
|
||||
};
|
||||
|
||||
export const outbagURLfromTag = async (tag: string) => {
|
||||
let uri: URL;
|
||||
try {
|
||||
uri = new URL("/", url);
|
||||
uri = new URL("/", tag);
|
||||
uri.protocol = "https";
|
||||
} catch (_) {
|
||||
uri = new URL("https://" + url);
|
||||
uri = new URL("https://" + tag);
|
||||
}
|
||||
uri.pathname = WELL_KNOWN_PATH;
|
||||
fetch(uri)
|
||||
.then(resp => resp.json())
|
||||
.then(({ path = "/", port = 7223 }) => {
|
||||
uri.pathname = path;
|
||||
uri.port = port;
|
||||
uri.protocol = prefix;
|
||||
res(uri.toString());
|
||||
})
|
||||
.catch(_ => {
|
||||
if (uri.port == '') {
|
||||
uri.port = DEFAULT_PORT + "";
|
||||
outbagURL(uri.toString(), prefix)
|
||||
.then(url => res(url))
|
||||
.catch(_ => rej());
|
||||
} else {
|
||||
rej();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
export const outbagURLshort = (url: string) => new Promise((res, rej) => {
|
||||
let uri: URL;
|
||||
let isMain = uri.port == '';
|
||||
try {
|
||||
uri = new URL("/", url);
|
||||
uri.protocol = "https";
|
||||
let { host, path, port } = await fetchWellknown(uri);
|
||||
return new outbagServer(isMain ? host : host + ":" + port, host, path, port);
|
||||
} catch (_) {
|
||||
uri = new URL("https://" + url);
|
||||
if (isMain) {
|
||||
try {
|
||||
uri.port = DEFAULT_PORT;
|
||||
let { host, path, port } = await fetchWellknown(uri);
|
||||
return new outbagServer(isMain ? host : host + ":" + port, host, path, port);
|
||||
} catch (_) { }
|
||||
}
|
||||
throw new Error("InvalidOutbagServer");
|
||||
}
|
||||
uri.pathname = WELL_KNOWN_PATH;
|
||||
fetch(uri)
|
||||
.then(resp => resp.json())
|
||||
.then(({ path = "/", port = 7223 }) => {
|
||||
uri.pathname = path;
|
||||
uri.port = port;
|
||||
res(uri.hostname + ":" + uri.port);
|
||||
})
|
||||
.catch(_ => {
|
||||
if (uri.port == '') {
|
||||
uri.port = DEFAULT_PORT + "";
|
||||
outbagURLshort(uri.toString())
|
||||
.then(url => res(url))
|
||||
.catch(_ => rej());
|
||||
} else {
|
||||
rej();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export class outbagServer {
|
||||
host: string;
|
||||
port: string;
|
||||
path: string;
|
||||
tag: string;
|
||||
constructor(tag: string, host: string, path: string, port: string) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
if (!path.startsWith("/")) this.path = "/" + path;
|
||||
else this.path = path;
|
||||
this.tag = tag;
|
||||
}
|
||||
get httpsURL() {
|
||||
return `https://${this.host}:${this.port}${this.path}/`;
|
||||
}
|
||||
get wsURL() {
|
||||
return `wss://${this.host}:${this.port}${this.path}/`;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import { outbagURL, outbagURLshort } from "./outbagURL.js";
|
||||
import { db, serverCerts } from "../sys/db.js"
|
||||
import { eq, insert, select, update } from "dblang";
|
||||
import { error, log } from "../sys/log.js";
|
||||
import { outbagServer } from "./outbagURL.js";
|
||||
import { debug, log } from "../sys/log.js";
|
||||
import { uts } from "../sys/tools.js";
|
||||
import { getSettings, setSettings, SETTINGS } from "../sys/settings.js"
|
||||
import { generateSigningKey } from "../sys/crypto.js"
|
||||
import { oConf } from "../sys/config.js";
|
||||
import nman from "nman";
|
||||
import nman, { addShutdownTask } from "nman";
|
||||
import { insert } from "dblang";
|
||||
import { db, servers } from "../sys/db.js";
|
||||
|
||||
export const startUpdateCerts = () => {
|
||||
export const startUpdateCert = () => {
|
||||
const update = async () => {
|
||||
var exp = parseInt(await getSettings(SETTINGS.certExpires));
|
||||
if (uts() - 60 >= (exp || 0)) {
|
||||
|
@ -27,26 +27,25 @@ export const startUpdateCerts = () => {
|
|||
}, 100);
|
||||
}
|
||||
|
||||
async function updateRemote(url: string, pKey: string = ""): Promise<boolean | string> {
|
||||
var urlP = await outbagURL(url);
|
||||
/*async function updateRemote(server: outbagServer): Promise<boolean> {
|
||||
return new Promise((res, rej) => {
|
||||
fetch(urlP + "api/server/publicKey")
|
||||
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(serverCerts.url, serverCerts.publicKey, serverCerts.expires)
|
||||
.add(url, publicKey, expires)
|
||||
await insert(servers.url, servers.publicKey, servers.expires)
|
||||
.add(server.tag, publicKey, expires)
|
||||
.query(db);
|
||||
} catch (error) {
|
||||
await update(serverCerts)
|
||||
.set(serverCerts.publicKey, publicKey)
|
||||
.set(serverCerts.expires, expires)
|
||||
.where(eq(serverCerts.url, url))
|
||||
await update(servers)
|
||||
.set(servers.publicKey, publicKey)
|
||||
.set(servers.expires, expires)
|
||||
.where(eq(servers.url, server.tag))
|
||||
.query(db);
|
||||
}
|
||||
res(publicKey);
|
||||
res(true);
|
||||
} else {
|
||||
if (publicKey.length > 0) {
|
||||
res(publicKey);
|
||||
|
@ -57,20 +56,53 @@ async function updateRemote(url: string, pKey: string = ""): Promise<boolean | s
|
|||
})
|
||||
.catch((e) => {
|
||||
error("serverCert", "fetch error:", e);
|
||||
if (pKey.length > 0) {
|
||||
res(pKey);
|
||||
return;
|
||||
}
|
||||
res(false);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const getRemote = async (url: string) => {
|
||||
let query = await select([serverCerts.publicKey, serverCerts.expires], serverCerts)
|
||||
.where(eq(serverCerts.url, url))
|
||||
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);
|
||||
if (query.length == 0 || query[0][serverCerts.expires] < uts() - 60)
|
||||
return await updateRemote(url, query[0][serverCerts.publicKey]);
|
||||
return query[0][serverCerts.publicKey];
|
||||
return query[0][servers.publicKey];
|
||||
};*/
|
||||
const deleteafter = 60 * 60;
|
||||
|
||||
const certList: { [key: string]: { exp: number, cert: string } } = {};
|
||||
|
||||
var certListCleaner = setInterval(async () => {
|
||||
var utst = uts();
|
||||
let keys = Object.keys(certList);
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
if (utst >= certList[keys[i]].exp) {
|
||||
debug("Certificate List", "remove Cert: ", keys[i]);
|
||||
delete certList[keys[i]];
|
||||
}
|
||||
}
|
||||
}, 1000 * 60);
|
||||
addShutdownTask(() => clearInterval(certListCleaner), 5000);
|
||||
|
||||
const updateCert = async (server: outbagServer) => {
|
||||
try {
|
||||
let resp = await fetch(server.httpsURL + "api/server/publicKey")
|
||||
let json = await resp.json();
|
||||
let { publicKey, expires } = json;
|
||||
certList[server.tag] = { exp: Math.min(expires, deleteafter), cert: publicKey };
|
||||
try {
|
||||
await insert(servers.tag)
|
||||
.add(server.tag)
|
||||
.query(db);
|
||||
} catch (error) {}
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const getRemote = async (server: outbagServer) => {
|
||||
if (certList[server.tag] == null || certList[server.tag].exp >= uts()) await updateCert(server);
|
||||
if (certList[server.tag] != null) return certList[server.tag].cert;
|
||||
else throw new Error("Cert Error");
|
||||
};
|
|
@ -1,4 +1,5 @@
|
|||
import juml from "juml";
|
||||
import { outbagServer, outbagURLfromTag } from "../server/outbagURL.js";
|
||||
|
||||
const conf_struct = {
|
||||
System: {
|
||||
|
@ -29,4 +30,31 @@ const conf_struct = {
|
|||
}
|
||||
};
|
||||
|
||||
export const oConf = new juml(conf_struct);
|
||||
export const oConf = new juml(conf_struct);
|
||||
|
||||
export let localhostTag: outbagServer = new outbagServer(
|
||||
"localhost",
|
||||
oConf.get("System", "URL")+"",
|
||||
oConf.get("System", "PATHexposed")+"",
|
||||
oConf.get("System", "PORTexposed")+"",
|
||||
);
|
||||
|
||||
export let selfTag: outbagServer = localhostTag;
|
||||
|
||||
export const generateTag = async () => {
|
||||
try {
|
||||
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 != serverHostPort){
|
||||
selfTag = serverHostPort;
|
||||
}else selfTag = mainServerHost;
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
|
@ -67,12 +67,11 @@ settings.addAttributes({
|
|||
data: { type: TEXT },
|
||||
})
|
||||
|
||||
export const serverCerts = db.newTable("serverCerts");
|
||||
serverCerts.addAttributes({
|
||||
serverCertID: { type: INT, primaryKey: true, autoIncrement: true },
|
||||
url: { type: TEXT },
|
||||
publicKey: { type: TEXT },
|
||||
expires: { type: BIGINT },
|
||||
export const servers = db.newTable("servers");
|
||||
servers.addAttributes({
|
||||
tag: { type: VARCHAR(255), primaryKey: true },
|
||||
//publicKey: { type: TEXT },
|
||||
//expires: { type: BIGINT },
|
||||
token: { type: TEXT, notNull: false },
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue