src/Scanner.js
const fs = require("fs");
const MD = require("./Markdown.js");
const FORMAT = {
code: 0x1,
list: 0x2
}
function RuleResult(config){
this.description = null;
this.verdict = null;
this.format = null;
this.data = null;
this.match = false;
this.header = null;
for(let i in config) this[i]=config[i];
return this;
}
RuleResult.prototype.toMarkdown = function(){
let out ="";
if(this.description !== null) out += "\n"+this.description+"\n";
switch(this.format){
case FORMAT.code:
out += MD.code(this.data);
break;
case FORMAT.list:
out += MD.table(this.header,this.data.getData());
break;
case FORMAT.raw:
out += this.data;
break;
}
if(this.verdict !== null){
out += "#### Verdict \n"+this.verdict+"\n";
}
return out;
}
/**
* Represente le couple regle/resultat
* @param {*} config
*/
function Match(config){
this.result = null;
this.rule = null;
for(let i in config) this[i]=config[i];
return this;
}
Match.prototype.toMarkdown = function(){
let out="";
out += "## "+this.rule.name+"\n"+this.rule.description+"\n";
if(this.result !== null)
out += this.result.toMarkdown();
else
out += "Not match founds";
return out;
}
/**
* Represente une regle
* @param {*} config
*/
function Rule(config){
this.enable = true;
this.name = null;
this.description = null;
this.ruleset = null;
this.pattern = null;
this.header = null;
this.type = null;
for(let i in config) this[i]=config[i];
return this;
}
Rule.prototype.run = function(context){
if(this.pattern instanceof Function){
return new Match({
result: this.pattern(context),
rule: this
});
}else{
return null;
}
}
/**
* Un scanner regroupe un ensemble de regles regroupees en categories
* et faisant partageant un meme objectif (identifier la surface d'attaque,
* les mechanismes, ..)
* @param {*} config
*/
function Scanner(config){
this.name = null;
this.context = null
this.description = null;
this.analyzer = null;
this.rules = {};
this.matches = [];
for(let i in config) this[i]=config[i];
return this;
}
Scanner.prototype.addRule = function(category,rule){
if(this.rules[category]==null){
this.rules[category] = {};
}
this.rules[category][rule.name] = rule;
};
Scanner.prototype.scan = function(force){
let match = null;
for(let cat in this.rules){
for(let name in this.rules[cat]){
if((this.rules[cat][name] instanceof Rule)
&& this.rules[cat][name].enable){
match = this.rules[cat][name].run(this.context);
if(this.rules[cat][name].hasMatch(match)){
this.matches.push(match);
}
}
}
}
};
Scanner.prototype.publish = function(path){
let filepath = path;
if(filepath == null)
filepath=this.context.workspace.getTimestampedFilePath(this.name+"_report",".md");
let fd = fs.openSync(filepath,'w+');
for(let i in this.matches){
fs.writeSync(fd, this.matches[i].toMarkdown());
}
fs.closeSync(fd);
return filepath;
};
module.exports = {
FORMAT: FORMAT,
RuleResult: RuleResult,
Scanner: Scanner,
Rule: Rule,
Match: Match
}