customRoutes/publishcve.js (136 lines of code) (raw):
const express = require('express');
const protected = express.Router();
const conf = require('../config/conf');
const csurf = require('csurf');
var request = require('request');
const email = require('./email.js');
const asf = require('../custom/asf.js');
var csrfProtection = csurf();
var textUtil = require('../public/js/util.js');
// We have to duplicate this from custom/cve5/asfpreload.js
global.getProductListNoVendor = function getProductListNoVendor(c) {
var lines = [];
for (var affected of c.containers.cna.affected) {
lines.push(affected.product);
}
return lines.join(", ");
}
// Is the PMC allowed to do a live CVE.org push?
// Currently only if you are in security group or if you're listed in the config,
// or if the config allows all (*) but you're not listed as an exception
function allowedtopushlive(pmcsiamin, specificpmc) {
if (pmcsiamin.includes(conf.admingroupname)) {
return true;
}
if (!pmcsiamin.includes(specificpmc)) {
return false; // they're messing with the form
}
return false;
// This isn't implemented yet
//
if (conf.pmcstrustedascna.includes("*")) {
if (conf.pmcstrustedascna.includes("-"+specificpmc)) {
return false;
}
return true;
}
if (conf.pmcstrustedascna.includes(specificpmc)) {
return true;
}
return false;
}
function getCveIdState(cveid, cb) {
var opt = {
'method' : 'GET',
'url': conf.cveapiurl+'/cve-id/'+ cveid,
'json': true,
'headers': conf.cveapiheaders,
};
try {
request(opt, (error, response, body) => {
if (error) {
console.warn(error);
cb("");
} else {
cb(body.state);
}
});
} catch (error) {
console.warn(error);
cb("");
}
}
function publishCve(cveid, isupdate, container, cb) {
var opt = {
'method' : 'POST',
'url': conf.cveapiurl+'/cve/'+ cveid +"/cna",
'json': {"cnaContainer": container},
'headers': conf.cveapiheaders,
};
if (isupdate) {
opt['method'] = "PUT";
}
try {
request(opt, (error, response, body) => {
if (error) {
console.warn(error);
cb(error);
} else if (body.error) {
console.warn(body.error);
cb(body.message);
} else {
console.log(body.message);
cb();
}
});
} catch (error) {
console.warn(error);
cb(error);
}
}
protected.post('/', csrfProtection, async function(req,res) {
var q = {};
var opts = {"idpath":"body.cveMetadata.cveId"};
console.log("publishcve", req.body.cve);
q[opts.idpath] = req.body.cve;
let Document = res.locals.docs.cve5.Document;
var doc = await Document.findOne(q);
if (!doc) {
res.json({"body": req.body.cve+" not found"});
res.end();
return;
}
// We now have a loaded document for the given CVE ID
var cvepmcowner = doc.body.CNA_private.owner;
if (!allowedtopushlive(req.user.pmcs,cvepmcowner)) {
res.json({"body":"Sorry the PMC "+cvepmcowner+" has no push rights"});
res.end();
return true;
}
// We now know that the user trying to push it is allowed to do so
j = textUtil.reduceJSON(doc.body);
// We now have the document the same as the CVE-JSON tab had
if (doc.body.CNA_private.state != "PUBLIC" && doc.body.CNA_private.state != "READY" ) {
res.json({"body":req.body.cve+" is not in state PUBLIC or READY"});
res.end();
return true;
}
// We now have something we're allowed to push
// portal.js does a getCveId(j.cveMetadata.cveId) and looks at the state so we know if
// we're doing a first push or an update push
var lateststate = await new Promise( res => { getCveIdState(req.body.cve, res)})
//console.log("According to cve.org "+req.body.cve+" is state "+lateststate);
if (j.cveMetadata.state == "PUBLISHED") {
var isupdate = (lateststate != "RESERVED")
var result = await new Promise( res => { publishCve(j.cveMetadata.cveId, isupdate, j.containers.cna, res)})
if (!result) {
res.json({"body":"Push to cve.org success."});
var s2 = email.sendemail({"to":"security@apache.org",
"subject":j.cveMetadata.cveId+" was pushed to cve.org",
"text":"push by "+req.user.username+" success",
}).then( (x) => { console.log("sent CVE push mail "+x);});
} else {
res.json({"body":"Push to cve.org failed. "+result});
var s2 = email.sendemail({"to":"security@apache.org",
"subject":j.cveMetadata.cveId+" failed push to cve.org",
"text":"push by "+req.user.username+" failed "+result,
}).then( (x) => { console.log("sent CVE push failed mail "+x);});
}
res.end();
return true;
} else { // Rejected
res.json({"body":"Push is authorised for you, but 'reject cve' not yet implemented."});
res.end();
return true;
}
});
module.exports = {
protected: protected
};