From 70953f3194154d5122ef8482762f307aa212c645 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 18 May 2023 08:09:18 +0000 Subject: [PATCH] mitigate some vulnerabilities in disk attach, handle errors in getDiskInfo as result of nonexistent disk --- main.js | 27 +++++++++++++++++++++------ pve.js | 29 +++++++++++++++++++---------- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/main.js b/main.js index 699e46c..772763e 100644 --- a/main.js +++ b/main.js @@ -25,7 +25,7 @@ app.get("/api/echo", (req, res) => { }); app.get("/api/auth", async (req, res) => { - let auth = await checkAuth(req.cookies); + let auth = await checkAuth(req.cookies, res); if (!auth) { return; } res.status(200).send({ auth: true }); }); @@ -115,10 +115,20 @@ app.post("/api/instance/disk/attach", async (req, res) => { let vmpath = `/nodes/${req.body.node}/${req.body.type}/${req.body.vmid}`; let auth = await checkAuth(req.cookies, res, vmpath); if (!auth) { return; } + // get current config and check if unused disk exists + let config = await requestPVE(`${vmpath}/config`, "GET", req.cookies, null, null); + if (!config.data.data[`unused${req.body.source}`]) { + res.status(403).send({ error: `requested disk unused${req.body.source} does not exist` }); + res.end(); + return; + } + let sourceDisk = config.data.data[`unused${req.body.source}`]; + // setup action using source disk info from vm config let action = {}; - action[req.body.disk] = req.body.data; + action[req.body.disk] = sourceDisk; action = JSON.stringify(action); let method = req.body.type === "qemu" ? "POST" : "PUT"; + // commit action let result = await requestPVE(`${vmpath}/config`, method, req.cookies, action, pveAPIToken); await handleResponse(req.body.node, result, res); }); @@ -179,7 +189,7 @@ app.post("/api/instance/disk/move", async (req, res) => { res.end(); return; } - + // create action let action = { storage: req.body.storage, delete: req.body.delete }; if (req.body.type === "qemu") { action.disk = req.body.disk @@ -189,6 +199,7 @@ app.post("/api/instance/disk/move", async (req, res) => { } action = JSON.stringify(action); let route = req.body.type === "qemu" ? "move_disk" : "move_volume"; + // commit action let result = await requestPVE(`${vmpath}/${route}`, "POST", req.cookies, action, pveAPIToken); await handleResponse(req.body.node, result, res); }); @@ -204,6 +215,7 @@ app.post("/api/instance/disk/delete", async (req, res) => { res.end(); return; } + // create action let action = JSON.stringify({ delete: req.body.disk }); let method = req.body.type === "qemu" ? "POST" : "PUT"; // commit action @@ -227,6 +239,7 @@ app.post("/api/instance/disk/create", async (req, res) => { return; } } + // setup action let action = {}; if (req.body.disk.includes("ide") && req.body.iso) { action[req.body.disk] = `${req.body.iso},media=cdrom`; @@ -262,11 +275,12 @@ app.post("/api/instance/network", async (req, res) => { res.end(); return; } - // commit action + // setup action let action = {}; action[`net${req.body.netid}`] = currentNetworkConfig.replace(`rate=${currentNetworkRate}`, `rate=${req.body.rate}`); action = JSON.stringify(action); let method = req.body.type === "qemu" ? "POST" : "PUT"; + // commit action let result = await requestPVE(`${vmpath}/config`, method, req.cookies, action, pveAPIToken); await handleResponse(req.body.node, result, res); }); @@ -288,9 +302,10 @@ app.post("/api/instance/resources", async (req, res) => { res.end(); return; } - // commit action + // setup action let action = JSON.stringify({ cores: req.body.cores, memory: req.body.memory }); let method = req.body.type === "qemu" ? "POST" : "PUT"; + // commit action let result = await requestPVE(`${vmpath}/config`, method, req.cookies, action, pveAPIToken); await handleResponse(req.body.node, result, res); }); @@ -349,8 +364,8 @@ app.post("/api/instance", async (req, res) => { res.end(); return; } - // commit action action = JSON.stringify(action); + // commit action let result = await requestPVE(`/nodes/${req.body.node}/${req.body.type}`, "POST", req.cookies, action, pveAPIToken); await handleResponse(req.body.node, result, res); }); diff --git a/pve.js b/pve.js index f31d877..b2fc377 100644 --- a/pve.js +++ b/pve.js @@ -56,13 +56,18 @@ export async function handleResponse(node, result, res) { let upid = result.data.data; while (true) { let taskStatus = await requestPVE(`/nodes/${node}/tasks/${upid}/status`, "GET", null, null, pveAPIToken); + let taskLog = await requestPVE(`/nodes/${node}/tasks/${upid}/log`, "GET", null, null, pveAPIToken); if (taskStatus.data.data.status === "stopped" && taskStatus.data.data.exitstatus === "OK") { - res.status(200).send(taskStatus.data.data); + let result = taskStatus.data.data; + result.log = taskLog.data.data; + res.status(200).send(result); res.end(); return; } else if (taskStatus.data.data.status === "stopped") { - res.status(500).send(taskStatus.data.data); + let result = taskStatus.data.data; + result.log = taskLog.data.data; + res.status(500).send(result); res.end(); return; } @@ -73,8 +78,7 @@ export async function handleResponse(node, result, res) { } else { res.status(result.status).send(result.data); - res.end(); - return; + res.end(); } } @@ -112,10 +116,15 @@ export async function getUsedResources(req, resourceMeta) { } export async function getDiskInfo(node, type, vmid, disk) { - let config = await requestPVE(`/nodes/${node}/${type}/${vmid}/config`, "GET", null, null, pveAPIToken); - let storageID = config.data.data[disk].split(":")[0]; - let volID = config.data.data[disk].split(",")[0]; - let volInfo = await requestPVE(`/nodes/${node}/storage/${storageID}/content/${volID}`, "GET", null, null, pveAPIToken); - volInfo.data.data.storage = storageID; - return volInfo.data.data; + try { + let config = await requestPVE(`/nodes/${node}/${type}/${vmid}/config`, "GET", null, null, pveAPIToken); + let storageID = config.data.data[disk].split(":")[0]; + let volID = config.data.data[disk].split(",")[0]; + let volInfo = await requestPVE(`/nodes/${node}/storage/${storageID}/content/${volID}`, "GET", null, null, pveAPIToken); + volInfo.data.data.storage = storageID; + return volInfo.data.data; + } + catch { + return null; + } } \ No newline at end of file