@aikidosec/firewall
Version:
Zen by Aikido is an embedded Web Application Firewall that autonomously protects Node.js apps against common and critical attacks
144 lines (143 loc) • 4.58 kB
JavaScript
"use strict";
// Based on https://github.com/demskie/netparser
// MIT License - Copyright (c) 2019 alex
Object.defineProperty(exports, "__esModule", { value: true });
exports.Network = void 0;
const parse = require("./parse");
const Address_1 = require("./Address");
const BEFORE = -1;
const EQUALS = 0;
const AFTER = 1;
class Network {
constructor(network) {
this.addr = new Address_1.Address();
this.netbits = -1;
if (network) {
const net = parse.network(network);
if (net) {
this.addr.setBytes(net.bytes);
this.netbits = net.cidr;
}
}
}
destroy() {
if (!this.addr.isValid()) {
this.addr.destroy();
}
this.netbits = -1;
return this;
}
cidr() {
if (this.isValid()) {
return this.netbits;
}
return Number.NaN;
}
isValid() {
return this.addr.isValid() && this.netbits !== -1;
}
duplicate() {
const network = new Network();
if (this.isValid()) {
network.addr.setBytes(this.addr.bytes().slice());
network.netbits = this.netbits;
}
return network;
}
next() {
this.addr.increase(this.netbits);
return this;
}
setCIDR(cidr) {
if (!this.addr.isValid()) {
this.destroy();
}
else {
cidr = Math.floor(cidr);
if (cidr >= 0 && cidr <= this.addr.bytes().length * 8) {
this.netbits = cidr;
}
else {
this.destroy();
}
}
return this;
}
compare(network) {
// check that both networks are valid
if (!this.isValid() || !network.isValid())
return null;
// compare addresses
const cmp = this.addr.compare(network.addr);
if (cmp !== EQUALS)
return cmp;
// compare subnet mask length
if (this.netbits < network.netbits)
return BEFORE;
if (this.netbits > network.netbits)
return AFTER;
// otherwise they must be equal
return EQUALS;
}
contains(network) {
// check that both networks are valid
if (!this.isValid() || !network.isValid())
return false;
// ensure that both IPs are of the same type
if (this.addr.bytes().length !== network.addr.bytes().length)
return false;
// handle edge cases
if (this.netbits === 0)
return true;
if (network.netbits === 0)
return false;
// our base address should be less than or equal to the other base address
if (this.addr.compare(network.addr) === AFTER)
return false;
// get the next network address for both
const next = this.duplicate().next();
const otherNext = network.duplicate().next();
// handle edge case where our next network address overflows
if (!next.isValid())
return true;
// our address should be more than or equal to the other address
if (next.addr.compare(otherNext.addr) === BEFORE)
return false;
// must be a child subnet
return true;
}
adjacent(network) {
// check that both networks are valid
if (!this.isValid() || !network.isValid())
return false;
// ensure that both IPs are of the same type
if (this.addr.bytes().length !== network.addr.bytes().length)
return false;
// handle edge cases
if (this.netbits === 0 || network.netbits == 0)
return true;
const cmp = this.addr.compare(network.addr);
if (cmp === EQUALS)
return false;
// ensure that alpha addr contains the baseAddress that comes first
let alpha, bravo;
if (cmp === BEFORE) {
alpha = this.duplicate().next();
bravo = network;
}
else {
alpha = network.duplicate().next();
// eslint-disable-next-line @typescript-eslint/no-this-alias
bravo = this;
}
// if alpha overflows then an adjacency is not possible
if (!alpha.isValid())
return false;
// alpha addr should equal bravo for them to be perfectly adjacent
if (alpha.addr.compare(bravo.addr) === EQUALS)
return true;
// otherwise we aren't adjacent
return false;
}
}
exports.Network = Network;