From 44084c9348c4ab87643051c7c3f4dd6af95c2646 Mon Sep 17 00:00:00 2001 From: Eivind Eklund Date: Thu, 14 Dec 2000 13:59:10 +0000 Subject: [PATCH] Add better IP, netmask and gateway checks. - IP addresses are verified as being correct dotted quad format. - Netmasks are verified as being in correct dotted quad or 0x* format, and being consecutive 1 bits followed by consecutive 0 bits. - The gateway is verified as being correct dotted quad format and being reachable through the configured IP address and netmask. --- release/sysinstall/tcpip.c | 106 +++++++++++++++++++++++++++++++----- usr.sbin/sysinstall/tcpip.c | 106 +++++++++++++++++++++++++++++++----- 2 files changed, 184 insertions(+), 28 deletions(-) diff --git a/release/sysinstall/tcpip.c b/release/sysinstall/tcpip.c index 3f725b5aa2c9..f466bfe8f9a9 100644 --- a/release/sysinstall/tcpip.c +++ b/release/sysinstall/tcpip.c @@ -116,18 +116,36 @@ feepout(char *msg) msgConfirm(msg); } -/* Very basic IP address integrity check - could be drastically improved */ +/* Verify IP address integrity */ static int -verifyIP(char *ip) +verifyIP(char *ip, unsigned long *out) { - int a, b, c, d; + long a, b, c, d; + char *endptr; - if (ip && sscanf(ip, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 && - _validByte(a) && _validByte(b) && _validByte(c) && - _validByte(d) && (d != 255)) - return 1; - else + if (ip == NULL) return 0; + a = strtol(ip, &endptr, 10); + if (*endptr++ != '.') + return 0; + b = strtol(endptr, &endptr, 10); + if (*endptr++ != '.') + return 0; + c = strtol(endptr, &endptr, 10); + if (*endptr++ != '.') + return 0; + d = strtol(endptr, &endptr, 10); + if (*endptr != '\0') + return 0; + /* Both 0 and 255 are technically valid in nets that are larger + than class C, but at least MS' TCP/IP stacks freak out if they see + them. */ + if (!_validByte(a) || !_validByte(b) || !_validByte(c) || + !_validByte(d) || (d == 0) || (d == 255)) + return 0; + if (out) + *out = (a << 24) | (b << 16) | (c << 8) | d; + return 1; } static int @@ -146,21 +164,81 @@ verifyIP6(char *ip) return 0; } +/* Verify IPv4 netmask as being well-formed as + a 0x or AAA.BBB.CCC.DDD mask */ +static int +verifyNetmask(const char *netmask, unsigned long *out) +{ + unsigned long mask; + unsigned long tmp; + char *endptr; + + if (netmask[0] == '0' && (netmask[1] == 'x' || netmask[1] == 'X')) { + /* Parse out hex mask */ + mask = strtoul(netmask, &endptr, 0); + if (*endptr != '\0') + return 0; + } else { + /* Parse out quad decimal mask */ + mask = strtoul(netmask, &endptr, 10); + if (!_validByte(mask) || *endptr++ != '.') + return 0; + tmp = strtoul(endptr, &endptr, 10); + if (!_validByte(tmp) || *endptr++ != '.') + return 0; + mask = (mask << 8) + tmp; + tmp = strtoul(endptr, &endptr, 10); + if (!_validByte(tmp) || *endptr++ != '.') + return 0; + mask = (mask << 8) + tmp; + tmp = strtoul(endptr, &endptr, 10); + if (!_validByte(tmp) || *endptr++ != '\0') + return 0; + mask = (mask << 8) + tmp; + } + /* Verify that we have a continous netmask */ + if ((((-mask & mask) - 1) | mask) != 0xffffffff) + return 0; + if (out) + *out = mask; + return 1; +} + +static int +verifyGW(char *gw, unsigned long *ip, unsigned long *mask) +{ + unsigned long parsedgw; + + if (!verifyIP(gw, &parsedgw)) + return 0; + /* Gateway needs to be within the set of IPs reachable through the + interface */ + if (ip && mask && ((parsedgw & *mask) != (*ip & *mask))) + return 0; + return 1; +} + /* Check for the settings on the screen - the per-interface stuff is moved to the main handling code now to do it on the fly - sigh */ static int verifySettings(void) { + unsigned long parsedip; + unsigned long parsednetmask; + if (!hostname[0]) feepout("Must specify a host name of some sort!"); - else if (gateway[0] && strcmp(gateway, "NO") && !verifyIP(gateway)) - feepout("Invalid gateway IPv4 address specified"); - else if (nameserver[0] && !verifyIP(nameserver) && !verifyIP6(nameserver)) + else if (nameserver[0] && !verifyIP(nameserver, NULL) && + !verifyIP6(nameserver)) feepout("Invalid name server IP address specified"); - else if (netmask[0] && (netmask[0] < '0' && netmask[0] > '3')) - feepout("Invalid netmask value"); - else if (ipaddr[0] && !verifyIP(ipaddr)) + else if (ipaddr[0] && !verifyIP(ipaddr, &parsedip)) feepout("Invalid IPv4 address"); + else if (netmask[0] && !verifyNetmask(netmask, &parsednetmask)) + feepout("Invalid netmask value"); + else if (gateway[0] && strcmp(gateway, "NO") && + !verifyGW(gateway, ipaddr[0] ? &parsedip : NULL, + netmask[0] ? &parsednetmask : NULL)) + feepout("Invalid gateway IPv4 address specified"); else return 1; return 0; diff --git a/usr.sbin/sysinstall/tcpip.c b/usr.sbin/sysinstall/tcpip.c index 3f725b5aa2c9..f466bfe8f9a9 100644 --- a/usr.sbin/sysinstall/tcpip.c +++ b/usr.sbin/sysinstall/tcpip.c @@ -116,18 +116,36 @@ feepout(char *msg) msgConfirm(msg); } -/* Very basic IP address integrity check - could be drastically improved */ +/* Verify IP address integrity */ static int -verifyIP(char *ip) +verifyIP(char *ip, unsigned long *out) { - int a, b, c, d; + long a, b, c, d; + char *endptr; - if (ip && sscanf(ip, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 && - _validByte(a) && _validByte(b) && _validByte(c) && - _validByte(d) && (d != 255)) - return 1; - else + if (ip == NULL) return 0; + a = strtol(ip, &endptr, 10); + if (*endptr++ != '.') + return 0; + b = strtol(endptr, &endptr, 10); + if (*endptr++ != '.') + return 0; + c = strtol(endptr, &endptr, 10); + if (*endptr++ != '.') + return 0; + d = strtol(endptr, &endptr, 10); + if (*endptr != '\0') + return 0; + /* Both 0 and 255 are technically valid in nets that are larger + than class C, but at least MS' TCP/IP stacks freak out if they see + them. */ + if (!_validByte(a) || !_validByte(b) || !_validByte(c) || + !_validByte(d) || (d == 0) || (d == 255)) + return 0; + if (out) + *out = (a << 24) | (b << 16) | (c << 8) | d; + return 1; } static int @@ -146,21 +164,81 @@ verifyIP6(char *ip) return 0; } +/* Verify IPv4 netmask as being well-formed as + a 0x or AAA.BBB.CCC.DDD mask */ +static int +verifyNetmask(const char *netmask, unsigned long *out) +{ + unsigned long mask; + unsigned long tmp; + char *endptr; + + if (netmask[0] == '0' && (netmask[1] == 'x' || netmask[1] == 'X')) { + /* Parse out hex mask */ + mask = strtoul(netmask, &endptr, 0); + if (*endptr != '\0') + return 0; + } else { + /* Parse out quad decimal mask */ + mask = strtoul(netmask, &endptr, 10); + if (!_validByte(mask) || *endptr++ != '.') + return 0; + tmp = strtoul(endptr, &endptr, 10); + if (!_validByte(tmp) || *endptr++ != '.') + return 0; + mask = (mask << 8) + tmp; + tmp = strtoul(endptr, &endptr, 10); + if (!_validByte(tmp) || *endptr++ != '.') + return 0; + mask = (mask << 8) + tmp; + tmp = strtoul(endptr, &endptr, 10); + if (!_validByte(tmp) || *endptr++ != '\0') + return 0; + mask = (mask << 8) + tmp; + } + /* Verify that we have a continous netmask */ + if ((((-mask & mask) - 1) | mask) != 0xffffffff) + return 0; + if (out) + *out = mask; + return 1; +} + +static int +verifyGW(char *gw, unsigned long *ip, unsigned long *mask) +{ + unsigned long parsedgw; + + if (!verifyIP(gw, &parsedgw)) + return 0; + /* Gateway needs to be within the set of IPs reachable through the + interface */ + if (ip && mask && ((parsedgw & *mask) != (*ip & *mask))) + return 0; + return 1; +} + /* Check for the settings on the screen - the per-interface stuff is moved to the main handling code now to do it on the fly - sigh */ static int verifySettings(void) { + unsigned long parsedip; + unsigned long parsednetmask; + if (!hostname[0]) feepout("Must specify a host name of some sort!"); - else if (gateway[0] && strcmp(gateway, "NO") && !verifyIP(gateway)) - feepout("Invalid gateway IPv4 address specified"); - else if (nameserver[0] && !verifyIP(nameserver) && !verifyIP6(nameserver)) + else if (nameserver[0] && !verifyIP(nameserver, NULL) && + !verifyIP6(nameserver)) feepout("Invalid name server IP address specified"); - else if (netmask[0] && (netmask[0] < '0' && netmask[0] > '3')) - feepout("Invalid netmask value"); - else if (ipaddr[0] && !verifyIP(ipaddr)) + else if (ipaddr[0] && !verifyIP(ipaddr, &parsedip)) feepout("Invalid IPv4 address"); + else if (netmask[0] && !verifyNetmask(netmask, &parsednetmask)) + feepout("Invalid netmask value"); + else if (gateway[0] && strcmp(gateway, "NO") && + !verifyGW(gateway, ipaddr[0] ? &parsedip : NULL, + netmask[0] ? &parsednetmask : NULL)) + feepout("Invalid gateway IPv4 address specified"); else return 1; return 0;