Restrict the CIDR values to what dnsmasq and the API accepts

The check is not 100% accurate, as it allows > 32 sized CIDRs
for IPv4 addresses, but it is good enough for the frontend checks.

Signed-off-by: Mcat12 <newtoncat12@yahoo.com>
This commit is contained in:
Mcat12
2019-07-06 18:07:33 -07:00
parent 4e86f5126a
commit eb70e87be1
5 changed files with 121 additions and 7 deletions
+1 -1
View File
@@ -382,7 +382,7 @@ function getDNSInfo() {
.word()
.toLowerCase()
.split(" ", 2)[0],
cidr: faker.random.number({ min: 1, max: 32 })
cidr: faker.random.arrayElement([8, 16, 24, 32])
}
};
}
@@ -23,6 +23,7 @@ export interface ConditionalForwardingSettingsProps {
settings: ConditionalForwardingObject;
onUpdate: (settings: ConditionalForwardingObject) => void;
isRouterIpValid: boolean;
isCidrValid: boolean;
isDomainValid: boolean;
t: i18next.TFunction;
}
@@ -31,6 +32,7 @@ const ConditionalForwardingSettings = ({
settings,
onUpdate,
isRouterIpValid,
isCidrValid,
isDomainValid,
t
}: ConditionalForwardingSettingsProps) => (
@@ -67,12 +69,17 @@ const ConditionalForwardingSettings = ({
<Input
id="cidr"
disabled={!settings.enabled}
value={settings.cidr}
value={settings.cidr === -1 ? "" : settings.cidr}
invalid={!isCidrValid}
onChange={e => {
const cidr = parseInt(e.target.value);
let cidr = parseInt(e.target.value);
// Only allow numbers
if (isNaN(cidr)) {
if (e.target.value.length === 0) {
// Use -1 as an internal representation of the empty string.
// It will show the form as invalid and make the text field
// function as the user expects it to.
cidr = -1;
} else if (isNaN(cidr)) {
return;
}
+19 -2
View File
@@ -23,7 +23,13 @@ import ConditionalForwardingSettings, {
} from "./ConditionalForwardingSettings";
import DnsOptionSettings, { DnsOptionsObject } from "./DnsOptionSettings";
import Alert, { AlertType } from "../common/Alert";
import { isValidHostname, isValidIpv4, isValidIpv6 } from "../../util/validate";
import {
isValidHostname,
isValidIpv4,
isValidIpv4Cidr,
isValidIpv6,
isValidIpv6Cidr
} from "../../util/validate";
export interface DNSInfoState {
alertMessage: string;
@@ -195,6 +201,11 @@ class DNSInfo extends Component<WithTranslation, DNSInfoState> {
address => isValidIpv4(address) || isValidIpv6(address)
);
const isCidrValid = this.isCFSettingValid(
this.state.conditionalForwarding.cidr.toString(),
cidr => isValidIpv4Cidr(cidr) || isValidIpv6Cidr(cidr)
);
const isDomainValid = this.isCFSettingValid(
this.state.conditionalForwarding.domain,
isValidHostname
@@ -226,6 +237,7 @@ class DNSInfo extends Component<WithTranslation, DNSInfoState> {
settings={this.state.conditionalForwarding}
onUpdate={this.handleConditionalForwardingUpdate}
isRouterIpValid={isRouterIpValid}
isCidrValid={isCidrValid}
isDomainValid={isDomainValid}
t={t}
/>
@@ -239,7 +251,12 @@ class DNSInfo extends Component<WithTranslation, DNSInfoState> {
</FormGroup>
<Button
type="submit"
disabled={this.state.processing || !isRouterIpValid || !isDomainValid}
disabled={
this.state.processing ||
!isRouterIpValid ||
!isCidrValid ||
!isDomainValid
}
>
{t("Apply")}
</Button>
+70
View File
@@ -12,8 +12,10 @@ import {
isPositiveNumber,
isValidDomain,
isValidIpv4,
isValidIpv4Cidr,
isValidIpv4OptionalPort,
isValidIpv6,
isValidIpv6Cidr,
isValidIpv6OptionalPort,
isValidRegex
} from "../validate";
@@ -230,6 +232,40 @@ describe("Testing the validation functions", () => {
});
});
describe("isValidIpv4Cidr", () => {
it("passes 8", () => {
expect(isValidIpv4Cidr("8")).toBe(true);
});
it("passes 16", () => {
expect(isValidIpv4Cidr("16")).toBe(true);
});
it("passes 24", () => {
expect(isValidIpv4Cidr("24")).toBe(true);
});
it("passes 32", () => {
expect(isValidIpv4Cidr("32")).toBe(true);
});
it("fails -1", () => {
expect(isValidIpv4Cidr("-1")).toBe(false);
});
it("fails 0", () => {
expect(isValidIpv4Cidr("0")).toBe(false);
});
it("fails 28", () => {
expect(isValidIpv4Cidr("28")).toBe(false);
});
it("fails 40", () => {
expect(isValidIpv4Cidr("40")).toBe(false);
});
});
describe("isValidIpv6", () => {
it("passes 1fff:0:a88:85a3::ac1f", () => {
expect(isValidIpv6("1fff:0:a88:85a3::ac1f")).toBe(true);
@@ -291,4 +327,38 @@ describe("Testing the validation functions", () => {
expect(isValidIpv6OptionalPort("[::1]")).toBe(false);
});
});
describe("isValidIpv6Cidr", () => {
it("passes 8", () => {
expect(isValidIpv6Cidr("8")).toBe(true);
});
it("passes 64", () => {
expect(isValidIpv6Cidr("64")).toBe(true);
});
it("passes 56", () => {
expect(isValidIpv6Cidr("56")).toBe(true);
});
it("passes 128", () => {
expect(isValidIpv6Cidr("128")).toBe(true);
});
it("fails -1", () => {
expect(isValidIpv6Cidr("-1")).toBe(false);
});
it("fails 0", () => {
expect(isValidIpv6Cidr("0")).toBe(false);
});
it("fails 63", () => {
expect(isValidIpv6Cidr("63")).toBe(false);
});
it("fails 150", () => {
expect(isValidIpv6Cidr("150")).toBe(false);
});
});
});
+20
View File
@@ -95,6 +95,15 @@ export function isValidIpv4OptionalPort(address: string): boolean {
);
}
/**
* Check if the string is a valid IPv4 CIDR number which dnsmasq accepts
*
* @param cidr The string to check
*/
export function isValidIpv4Cidr(cidr: string): boolean {
return ["8", "16", "24", "32"].includes(cidr);
}
/**
* Check if the string is a valid IPv6 address. This function does not do a
* thorough check of the IPv6 address; the backend will check it in detail.
@@ -118,3 +127,14 @@ export function isValidIpv6(address: string): boolean {
export function isValidIpv6OptionalPort(address: string): boolean {
return /^(\[[a-fA-F0-9:]+]:\d+|[a-fA-F0-9:]+)$/.test(address);
}
/**
* Check if the string is a valid IPv6 CIDR number which dnsmasq accepts
*
* @param cidr The string to check
*/
export function isValidIpv6Cidr(cidr: string): boolean {
const cidrNum = parseInt(cidr);
return !isNaN(cidrNum) && cidrNum > 0 && cidrNum <= 128 && cidrNum % 4 === 0;
}