Throw ExcludedOperationError when excluded operation is called from API

This commit is contained in:
d98762625 2018-08-31 14:43:14 +01:00
parent 7c9ebafd00
commit 96d5930f05
6 changed files with 143 additions and 8 deletions

View file

@ -0,0 +1,25 @@
/**
* Custom error type for handling operation that isnt included in node.js API
*
* @author d98762625 [d98762625@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
class ExcludedOperationError extends Error {
/**
* Standard error constructor. Adds no new behaviour.
*
* @param args - Standard error args
*/
constructor(...args) {
super(...args);
this.type = "ExcludedOperationError";
if (Error.captureStackTrace) {
Error.captureStackTrace(this, ExcludedOperationError);
}
}
}
export default ExcludedOperationError;

View file

@ -11,6 +11,7 @@ import SyncDish from "./SyncDish";
import Recipe from "./Recipe"; import Recipe from "./Recipe";
import OperationConfig from "./config/OperationConfig.json"; import OperationConfig from "./config/OperationConfig.json";
import { sanitise } from "./apiUtils"; import { sanitise } from "./apiUtils";
import ExludedOperationError from "../core/errors/ExcludedOperationError";
/** /**
@ -246,3 +247,19 @@ export function bake(operations){
return recipe.execute(dish); return recipe.execute(dish);
}; };
} }
/**
* Explain that the given operation is not included in the Node.js version.
* @param {String} name - name of operation
*/
export function explainExludedFunction(name) {
/**
* Throw new error type with useful message.
*/
const func = () => {
throw new ExludedOperationError(`Sorry, the ${name} operation is not available in the Node.js version of CyberChef.`);
};
// Add opName prop so Recipe can handle it, just like wrap does.
func.opName = name;
return func;
}

View file

@ -22,7 +22,7 @@ export default [
// esprima doesn't work in .mjs // esprima doesn't work in .mjs
"JavaScriptBeautify", "JavaScriptBeautify",
"JavaScriptMinify", "JavaScriptMinify",
"JavaScriptParse", "JavaScriptParser",
// Relies on state of recipe. // Relies on state of recipe.
// "Magic", // "Magic",

View file

@ -40,8 +40,9 @@ let code = `/**
import "babel-polyfill"; import "babel-polyfill";
import SyncDish from "./SyncDish"; import SyncDish from "./SyncDish";
import { wrap, help, bake } from "./api"; import { wrap, help, bake, explainExludedFunction } from "./api";
import { import {
// import as core_ to avoid name clashes after wrap.
`; `;
includedOperations.forEach((op) => { includedOperations.forEach((op) => {
@ -76,23 +77,32 @@ includedOperations.forEach((op) => {
code += ` "${decapitalise(op)}": wrap(core_${op}),\n`; code += ` "${decapitalise(op)}": wrap(core_${op}),\n`;
}); });
excludedOperations.forEach((op) => {
code += ` "${decapitalise(op)}": explainExludedFunction("${op}"),\n`;
});
code += ` }; code += ` };
} }
const chef = generateChef(); const chef = generateChef();
// Add some additional features to chef object.
chef.help = help; chef.help = help;
chef.dish = SyncDish; chef.dish = SyncDish;
// Define consts here so we can add to top-level export - wont allow
// export of chef property.
`; `;
includedOperations.forEach((op) => { Object.keys(operations).forEach((op) => {
code += `const ${decapitalise(op)} = chef.${decapitalise(op)};\n`; code += `const ${decapitalise(op)} = chef.${decapitalise(op)};\n`;
}); });
code +=` code +=`
// Define array of all operations to create register for bake.
const operations = [\n`; const operations = [\n`;
includedOperations.forEach((op) => { Object.keys(operations).forEach((op) => {
code += ` ${decapitalise(op)},\n`; code += ` ${decapitalise(op)},\n`;
}); });
@ -100,11 +110,13 @@ code += `];
chef.bake = bake(operations); chef.bake = bake(operations);
export default chef; export default chef;
// Operations as top level exports.
export { export {
operations, operations,
`; `;
includedOperations.forEach((op) => { Object.keys(operations).forEach((op) => {
code += ` ${decapitalise(op)},\n`; code += ` ${decapitalise(op)},\n`;
}); });

View file

@ -11,8 +11,9 @@
import "babel-polyfill"; import "babel-polyfill";
import SyncDish from "./SyncDish"; import SyncDish from "./SyncDish";
import { wrap, help, bake } from "./api"; import { wrap, help, bake, explainExludedFunction } from "./api";
import { import {
// import as core_ to avoid name clashes after wrap.
ADD as core_ADD, ADD as core_ADD,
AESDecrypt as core_AESDecrypt, AESDecrypt as core_AESDecrypt,
AESEncrypt as core_AESEncrypt, AESEncrypt as core_AESEncrypt,
@ -122,7 +123,6 @@ import {
JPathExpression as core_JPathExpression, JPathExpression as core_JPathExpression,
JSONBeautify as core_JSONBeautify, JSONBeautify as core_JSONBeautify,
JSONMinify as core_JSONMinify, JSONMinify as core_JSONMinify,
JavaScriptParser as core_JavaScriptParser,
Keccak as core_Keccak, Keccak as core_Keccak,
MD2 as core_MD2, MD2 as core_MD2,
MD4 as core_MD4, MD4 as core_MD4,
@ -381,7 +381,6 @@ function generateChef() {
"JPathExpression": wrap(core_JPathExpression), "JPathExpression": wrap(core_JPathExpression),
"JSONBeautify": wrap(core_JSONBeautify), "JSONBeautify": wrap(core_JSONBeautify),
"JSONMinify": wrap(core_JSONMinify), "JSONMinify": wrap(core_JSONMinify),
"javaScriptParser": wrap(core_JavaScriptParser),
"keccak": wrap(core_Keccak), "keccak": wrap(core_Keccak),
"MD2": wrap(core_MD2), "MD2": wrap(core_MD2),
"MD4": wrap(core_MD4), "MD4": wrap(core_MD4),
@ -510,12 +509,31 @@ function generateChef() {
"XPathExpression": wrap(core_XPathExpression), "XPathExpression": wrap(core_XPathExpression),
"zlibDeflate": wrap(core_ZlibDeflate), "zlibDeflate": wrap(core_ZlibDeflate),
"zlibInflate": wrap(core_ZlibInflate), "zlibInflate": wrap(core_ZlibInflate),
"fork": explainExludedFunction("Fork"),
"merge": explainExludedFunction("Merge"),
"jump": explainExludedFunction("Jump"),
"conditionalJump": explainExludedFunction("ConditionalJump"),
"label": explainExludedFunction("Label"),
"comment": explainExludedFunction("Comment"),
"tar": explainExludedFunction("Tar"),
"untar": explainExludedFunction("Untar"),
"unzip": explainExludedFunction("Unzip"),
"zip": explainExludedFunction("Zip"),
"javaScriptBeautify": explainExludedFunction("JavaScriptBeautify"),
"javaScriptMinify": explainExludedFunction("JavaScriptMinify"),
"javaScriptParser": explainExludedFunction("JavaScriptParser"),
"renderImage": explainExludedFunction("RenderImage"),
"syntaxHighlighter": explainExludedFunction("SyntaxHighlighter"),
}; };
} }
const chef = generateChef(); const chef = generateChef();
// Add some additional features to chef object.
chef.help = help; chef.help = help;
chef.dish = SyncDish; chef.dish = SyncDish;
// Define consts here so we can add to top-level export - wont allow
// export of chef property.
const ADD = chef.ADD; const ADD = chef.ADD;
const AESDecrypt = chef.AESDecrypt; const AESDecrypt = chef.AESDecrypt;
const AESEncrypt = chef.AESEncrypt; const AESEncrypt = chef.AESEncrypt;
@ -547,8 +565,10 @@ const CTPH = chef.CTPH;
const cartesianProduct = chef.cartesianProduct; const cartesianProduct = chef.cartesianProduct;
const changeIPFormat = chef.changeIPFormat; const changeIPFormat = chef.changeIPFormat;
const chiSquare = chef.chiSquare; const chiSquare = chef.chiSquare;
const comment = chef.comment;
const compareCTPHHashes = chef.compareCTPHHashes; const compareCTPHHashes = chef.compareCTPHHashes;
const compareSSDEEPHashes = chef.compareSSDEEPHashes; const compareSSDEEPHashes = chef.compareSSDEEPHashes;
const conditionalJump = chef.conditionalJump;
const convertArea = chef.convertArea; const convertArea = chef.convertArea;
const convertDataUnits = chef.convertDataUnits; const convertDataUnits = chef.convertDataUnits;
const convertDistance = chef.convertDistance; const convertDistance = chef.convertDistance;
@ -586,6 +606,7 @@ const fletcher16Checksum = chef.fletcher16Checksum;
const fletcher32Checksum = chef.fletcher32Checksum; const fletcher32Checksum = chef.fletcher32Checksum;
const fletcher64Checksum = chef.fletcher64Checksum; const fletcher64Checksum = chef.fletcher64Checksum;
const fletcher8Checksum = chef.fletcher8Checksum; const fletcher8Checksum = chef.fletcher8Checksum;
const fork = chef.fork;
const formatMACAddresses = chef.formatMACAddresses; const formatMACAddresses = chef.formatMACAddresses;
const frequencyDistribution = chef.frequencyDistribution; const frequencyDistribution = chef.frequencyDistribution;
const fromBCD = chef.fromBCD; const fromBCD = chef.fromBCD;
@ -625,8 +646,12 @@ const hexToPEM = chef.hexToPEM;
const JPathExpression = chef.JPathExpression; const JPathExpression = chef.JPathExpression;
const JSONBeautify = chef.JSONBeautify; const JSONBeautify = chef.JSONBeautify;
const JSONMinify = chef.JSONMinify; const JSONMinify = chef.JSONMinify;
const javaScriptBeautify = chef.javaScriptBeautify;
const javaScriptMinify = chef.javaScriptMinify;
const javaScriptParser = chef.javaScriptParser; const javaScriptParser = chef.javaScriptParser;
const jump = chef.jump;
const keccak = chef.keccak; const keccak = chef.keccak;
const label = chef.label;
const MD2 = chef.MD2; const MD2 = chef.MD2;
const MD4 = chef.MD4; const MD4 = chef.MD4;
const MD5 = chef.MD5; const MD5 = chef.MD5;
@ -634,6 +659,7 @@ const MD6 = chef.MD6;
const magic = chef.magic; const magic = chef.magic;
const mean = chef.mean; const mean = chef.mean;
const median = chef.median; const median = chef.median;
const merge = chef.merge;
const microsoftScriptDecoder = chef.microsoftScriptDecoder; const microsoftScriptDecoder = chef.microsoftScriptDecoder;
const multiply = chef.multiply; const multiply = chef.multiply;
const NOT = chef.NOT; const NOT = chef.NOT;
@ -675,6 +701,7 @@ const removeEXIF = chef.removeEXIF;
const removeLineNumbers = chef.removeLineNumbers; const removeLineNumbers = chef.removeLineNumbers;
const removeNullBytes = chef.removeNullBytes; const removeNullBytes = chef.removeNullBytes;
const removeWhitespace = chef.removeWhitespace; const removeWhitespace = chef.removeWhitespace;
const renderImage = chef.renderImage;
const Return = chef.Return; const Return = chef.Return;
const reverse = chef.reverse; const reverse = chef.reverse;
const rotateLeft = chef.rotateLeft; const rotateLeft = chef.rotateLeft;
@ -707,9 +734,11 @@ const subtract = chef.subtract;
const sum = chef.sum; const sum = chef.sum;
const swapEndianness = chef.swapEndianness; const swapEndianness = chef.swapEndianness;
const symmetricDifference = chef.symmetricDifference; const symmetricDifference = chef.symmetricDifference;
const syntaxHighlighter = chef.syntaxHighlighter;
const TCPIPChecksum = chef.TCPIPChecksum; const TCPIPChecksum = chef.TCPIPChecksum;
const tail = chef.tail; const tail = chef.tail;
const takeBytes = chef.takeBytes; const takeBytes = chef.takeBytes;
const tar = chef.tar;
const toBCD = chef.toBCD; const toBCD = chef.toBCD;
const toBase = chef.toBase; const toBase = chef.toBase;
const toBase32 = chef.toBase32; const toBase32 = chef.toBase32;
@ -742,6 +771,8 @@ const URLEncode = chef.URLEncode;
const unescapeString = chef.unescapeString; const unescapeString = chef.unescapeString;
const unescapeUnicodeCharacters = chef.unescapeUnicodeCharacters; const unescapeUnicodeCharacters = chef.unescapeUnicodeCharacters;
const unique = chef.unique; const unique = chef.unique;
const untar = chef.untar;
const unzip = chef.unzip;
const vigenèreDecode = chef.vigenèreDecode; const vigenèreDecode = chef.vigenèreDecode;
const vigenèreEncode = chef.vigenèreEncode; const vigenèreEncode = chef.vigenèreEncode;
const whirlpool = chef.whirlpool; const whirlpool = chef.whirlpool;
@ -752,10 +783,12 @@ const XMLMinify = chef.XMLMinify;
const XOR = chef.XOR; const XOR = chef.XOR;
const XORBruteForce = chef.XORBruteForce; const XORBruteForce = chef.XORBruteForce;
const XPathExpression = chef.XPathExpression; const XPathExpression = chef.XPathExpression;
const zip = chef.zip;
const zlibDeflate = chef.zlibDeflate; const zlibDeflate = chef.zlibDeflate;
const zlibInflate = chef.zlibInflate; const zlibInflate = chef.zlibInflate;
// Define array of all operations to create register for bake.
const operations = [ const operations = [
ADD, ADD,
AESDecrypt, AESDecrypt,
@ -788,8 +821,10 @@ const operations = [
cartesianProduct, cartesianProduct,
changeIPFormat, changeIPFormat,
chiSquare, chiSquare,
comment,
compareCTPHHashes, compareCTPHHashes,
compareSSDEEPHashes, compareSSDEEPHashes,
conditionalJump,
convertArea, convertArea,
convertDataUnits, convertDataUnits,
convertDistance, convertDistance,
@ -827,6 +862,7 @@ const operations = [
fletcher32Checksum, fletcher32Checksum,
fletcher64Checksum, fletcher64Checksum,
fletcher8Checksum, fletcher8Checksum,
fork,
formatMACAddresses, formatMACAddresses,
frequencyDistribution, frequencyDistribution,
fromBCD, fromBCD,
@ -866,8 +902,12 @@ const operations = [
JPathExpression, JPathExpression,
JSONBeautify, JSONBeautify,
JSONMinify, JSONMinify,
javaScriptBeautify,
javaScriptMinify,
javaScriptParser, javaScriptParser,
jump,
keccak, keccak,
label,
MD2, MD2,
MD4, MD4,
MD5, MD5,
@ -875,6 +915,7 @@ const operations = [
magic, magic,
mean, mean,
median, median,
merge,
microsoftScriptDecoder, microsoftScriptDecoder,
multiply, multiply,
NOT, NOT,
@ -916,6 +957,7 @@ const operations = [
removeLineNumbers, removeLineNumbers,
removeNullBytes, removeNullBytes,
removeWhitespace, removeWhitespace,
renderImage,
Return, Return,
reverse, reverse,
rotateLeft, rotateLeft,
@ -948,9 +990,11 @@ const operations = [
sum, sum,
swapEndianness, swapEndianness,
symmetricDifference, symmetricDifference,
syntaxHighlighter,
TCPIPChecksum, TCPIPChecksum,
tail, tail,
takeBytes, takeBytes,
tar,
toBCD, toBCD,
toBase, toBase,
toBase32, toBase32,
@ -983,6 +1027,8 @@ const operations = [
unescapeString, unescapeString,
unescapeUnicodeCharacters, unescapeUnicodeCharacters,
unique, unique,
untar,
unzip,
vigenèreDecode, vigenèreDecode,
vigenèreEncode, vigenèreEncode,
whirlpool, whirlpool,
@ -993,12 +1039,15 @@ const operations = [
XOR, XOR,
XORBruteForce, XORBruteForce,
XPathExpression, XPathExpression,
zip,
zlibDeflate, zlibDeflate,
zlibInflate, zlibInflate,
]; ];
chef.bake = bake(operations); chef.bake = bake(operations);
export default chef; export default chef;
// Operations as top level exports.
export { export {
operations, operations,
ADD, ADD,
@ -1032,8 +1081,10 @@ export {
cartesianProduct, cartesianProduct,
changeIPFormat, changeIPFormat,
chiSquare, chiSquare,
comment,
compareCTPHHashes, compareCTPHHashes,
compareSSDEEPHashes, compareSSDEEPHashes,
conditionalJump,
convertArea, convertArea,
convertDataUnits, convertDataUnits,
convertDistance, convertDistance,
@ -1071,6 +1122,7 @@ export {
fletcher32Checksum, fletcher32Checksum,
fletcher64Checksum, fletcher64Checksum,
fletcher8Checksum, fletcher8Checksum,
fork,
formatMACAddresses, formatMACAddresses,
frequencyDistribution, frequencyDistribution,
fromBCD, fromBCD,
@ -1110,8 +1162,12 @@ export {
JPathExpression, JPathExpression,
JSONBeautify, JSONBeautify,
JSONMinify, JSONMinify,
javaScriptBeautify,
javaScriptMinify,
javaScriptParser, javaScriptParser,
jump,
keccak, keccak,
label,
MD2, MD2,
MD4, MD4,
MD5, MD5,
@ -1119,6 +1175,7 @@ export {
magic, magic,
mean, mean,
median, median,
merge,
microsoftScriptDecoder, microsoftScriptDecoder,
multiply, multiply,
NOT, NOT,
@ -1160,6 +1217,7 @@ export {
removeLineNumbers, removeLineNumbers,
removeNullBytes, removeNullBytes,
removeWhitespace, removeWhitespace,
renderImage,
Return, Return,
reverse, reverse,
rotateLeft, rotateLeft,
@ -1192,9 +1250,11 @@ export {
sum, sum,
swapEndianness, swapEndianness,
symmetricDifference, symmetricDifference,
syntaxHighlighter,
TCPIPChecksum, TCPIPChecksum,
tail, tail,
takeBytes, takeBytes,
tar,
toBCD, toBCD,
toBase, toBase,
toBase32, toBase32,
@ -1227,6 +1287,8 @@ export {
unescapeString, unescapeString,
unescapeUnicodeCharacters, unescapeUnicodeCharacters,
unique, unique,
untar,
unzip,
vigenèreDecode, vigenèreDecode,
vigenèreEncode, vigenèreEncode,
whirlpool, whirlpool,
@ -1237,6 +1299,7 @@ export {
XOR, XOR,
XORBruteForce, XORBruteForce,
XPathExpression, XPathExpression,
zip,
zlibDeflate, zlibDeflate,
zlibInflate, zlibInflate,
SyncDish as Dish SyncDish as Dish

View file

@ -318,4 +318,22 @@ TestRegister.addApiTests([
assert.strictEqual(JSONDish.type, 6); assert.strictEqual(JSONDish.type, 6);
}), }),
it("Excluded operations: throw a sensible error when you try and call one", () => {
try {
chef.fork();
} catch (e) {
assert.strictEqual(e.type, "ExcludedOperationError");
assert.strictEqual(e.message, "Sorry, the Fork operation is not available in the Node.js version of CyberChef.");
}
}),
it("Excluded operations: throw a sensible error when you try and call one", () => {
try {
chef.renderImage();
} catch (e) {
assert.strictEqual(e.type, "ExcludedOperationError");
assert.strictEqual(e.message, "Sorry, the RenderImage operation is not available in the Node.js version of CyberChef.");
}
})
]); ]);