const route = require("express").Router(); const { setMasterPassword, setPassword, getPassword, getPasswords, getMasterHash, sharePW, sharePWRequests, acceptsharepw, storeEncryptedPWshare, getPassManUsers } = require("../arangodb"); const { verifyToken } = require("../checkToken"); const { addRouteToScope } = require("../scopes"); const { randomBytes, createHash } = require("crypto"); const { addHupTask } = require("../huphandler"); const { writeFile, readFile, existsSync, unlink } = require("fs"); addRouteToScope("/pwman/master", "pwman") addRouteToScope("/pwman/password", "pwman") addRouteToScope("/pwman", "pwman") addRouteToScope("/pwman/checkmaster", "pwman") addRouteToScope("/pwman/pwid", "pwman") addRouteToScope("/pwman/pwid/all", "pwman") addRouteToScope("/pwman/nonce", "pwman"); addRouteToScope("/pwman/sharepw", "pwman"); addRouteToScope("/pwman/sharingpws", "pwman"); addRouteToScope("/pwman/acceptpw", "pwman"); addRouteToScope("/pwman/encryptedpwtoshare", "pwman"); addRouteToScope("/pwman/pwmanusers", "pwman"); const nonce = []; if (existsSync("./.nonce")) { readFile("./.nonce", (err, data) => { if (!err) { nonce.splice(0, 0, ...JSON.parse(data.toString())) unlink("./.nonce", (err) => { console.log(err) }) } }) } route.post("/master", verifyToken, (req, res) => { setMasterPassword(req.tokendata.id, req.body.salt, req.body.hash).then(() => { res.end() }, ({ response }) => { res.status(response.body.code).json(response.body.errorMessage) }) }) route.post("/password", verifyToken, (req, res) => { // console.log(req.tokendata.id + "storing password") const nonceEntry = nonce.find(({ id }) => id == req.tokendata.id) if (nonceEntry) { nonce.splice(nonce.indexOf(nonceEntry), 1) getMasterHash(req.tokendata.id).then((hash)=>{ if (req.body.hash == createHash("sha256").update(hash + nonceEntry.randomSequence.toString("base64")).digest("base64")) { setPassword(req.tokendata.id, req.body.salt, req.body.crypt, req.body.id).then(() => { res.end() }, ({ response }) => { res.status(response.body.code).json(response.body.errorMessage) }) } else { res.status(401).json("no match for hash") } }) } else { res.status(409).json("you need to request nonce data before performing this operation") } }) route.post("/checkmaster", verifyToken, (req, res) => { // console.log(req.tokendata.id + "checking master key") const nonceEntry = nonce.find(({ id }) => id == req.tokendata.id) if (nonceEntry) { nonce.splice(nonce.indexOf(nonceEntry), 1) getMasterHash(req.tokendata.id).then((hash) => { if (req.body.hash == createHash("sha256").update(hash + nonceEntry.randomSequence.toString("base64")).digest("base64")) { res.end() } else { res.status(401).json("no match for hash") } }) } else { res.status(409).json("you need to request nonce data before performing this operation") } }) route.get("/nonce", verifyToken, (req, res) => { // console.log(req.tokendata.id + "requesting nonce") const randomSequence = randomBytes(16); nonce.splice(nonce.findIndex(({id})=>id==req.tokendata.id),1 ,{ randomSequence, id: req.tokendata.id }) res.write(randomSequence) res.end() }) route.post("/sharepw", verifyToken, (req, res)=>{ sharePW(req.tokendata.id, req.body.target_id, req.body.target_pw_id, req.body.temp_pub).then(()=>{ res.end() }, ({ error, message})=>{ res.status(error).json(message) }) }) route.get("/sharingpws", verifyToken, (req, res)=>{ sharePWRequests(req.tokendata.id).then((requests)=>{ res.json(requests) }, ({ error, message})=>{ res.status(error).json(message) }) }) route.post("/acceptpw", verifyToken, (req, res)=>{ acceptsharepw(req.tokendata.id, req.body.target_pw_id, req.body.sharer_id, req.body.temp_pub).then(()=>{ res.end() }, ({ error, message})=>{ res.status(error).json(message) }) }) route.post("/encryptedpwtoshare", verifyToken, (req, res)=>{ storeEncryptedPWshare(req.tokendata.id, req.body.target_id, req.body.target_pw_id, req.body.encrypted_pw, req.body.iv).then(()=>{ res.end() }, ({ error, message})=>{ res.status(error).json(message) }) }) route.get("/pwmanusers", verifyToken, (req, res)=>{ getPassManUsers().then((users)=>{ res.json(users.filter(({id})=>id!=req.tokendata.id)) }, ({ error, message})=>{ res.status(error).json(message) }) }) route.get("/pwid", verifyToken, (req, res) => { // console.log(req.tokendata.id + "requesting passwords") if (req.query.id && req.query.id != "all") { const nonceEntry = nonce.find(({ id }) => req.tokendata.id == id); if (nonceEntry) { nonce.splice(nonce.indexOf(nonceEntry), 1) getPassword(req.tokendata.id, req.query.id, req.query.hash, nonceEntry.randomSequence.toString("base64")).then((pass) => { res.json(pass) }, ({ error, message, response }) => { res.status(error || response.body.code).json(message || response.body.errorMessage) }) } else { res.status(409).json("you need to request nonce data before performing this operation") } } else { getPasswords(req.tokendata.id).then((passwords) => { res.json(passwords) }, ({ response }) => { res.status(response.body.code).json(response.body.errorMessage) }) } }) addHupTask("nonce", () => new Promise((res) => { writeFile("./.nonce", JSON.stringify(nonce), (err) => { if (err) { res(err) } else { res() } }) })) module.exports = route