summaryrefslogtreecommitdiffstats
path: root/netman.py
diff options
context:
space:
mode:
authorEdward A. James <eajames@us.ibm.com>2016-07-15 09:11:18 -0500
committerPatrick Williams <patrick@stwcx.xyz>2016-08-02 19:48:34 +0000
commit75757c08579200677391f5319aee68cafcae0bf1 (patch)
tree5e30048c1b774a4d77089432cd4170f8303e512c /netman.py
parentc69c3d30fd7d5fd04ba990788b6d75b19f275fc8 (diff)
downloadphosphor-networkd-75757c08579200677391f5319aee68cafcae0bf1.tar.gz
phosphor-networkd-75757c08579200677391f5319aee68cafcae0bf1.zip
networking: ip address validation
- check user-provided ip address before assigning to network device to prevent invalid addresses or addresses in disallowed ranges (bad addresses will cause networking failures on the system) Resolves openbmc/openbmc#202. Change-Id: I03826a0b9c947dad5ececd5af5269d3daf6afed8 Signed-off-by: Edward A. James <eajames@us.ibm.com>
Diffstat (limited to 'netman.py')
-rwxr-xr-xnetman.py80
1 files changed, 55 insertions, 25 deletions
diff --git a/netman.py b/netman.py
index 90cb022..34f63e5 100755
--- a/netman.py
+++ b/netman.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python
from subprocess import call, Popen, PIPE
+from IPy import IP
import sys
import subprocess
import dbus
@@ -82,29 +83,56 @@ class NetMan (dbus.service.Object):
if re.compile(macre).search(mac) : return True
else: return False
- def _isvalidip(self, family, ipaddr):
- if family == socket.AF_INET:
- try:
- socket.inet_pton(socket.AF_INET, ipaddr)
- except AttributeError: # no inet_pton here, sorry
- try:
- socket.inet_aton(ipaddr)
- except socket.error:
- return False
- return ipaddr.count('.') == 3
- except socket.error: # not a valid address
- return False
+ def _isvalidipv4(self, ipstr, netmask):
+ ip_parts = ipstr.split(".")
+ if len(ip_parts) != 4:
+ return "Malformed"
+
+ first, second, third, fourth = [int(part) for part in ip_parts]
+ if first == 0 and second == 0 and third == 0 and fourth == 0:
+ return "Invalid" # "this" network disallowed
+ if first == 169 and second == 254:
+ return "Link Local"
+ if first >= 224:
+ return "Invalid" # class D multicast and class E disallowed
+ if first == 192 and second == 88 and third == 99:
+ return "Invalid" # ipv6 relay
+
+ # check validity against netmask
+ if netmask != '0':
+ ip_bin = (first << 24) + (second << 16) + (third << 8) + fourth
+ mask_parts = netmask.split(".")
+ if len(mask_parts) == 4: # long form netmask
+ mask_bin = (int(mask_parts[0]) << 24) + (int(mask_parts[1]) << 16) + (int(mask_parts[2]) << 8) + int(mask_parts[3])
+ elif netmask.count(".") == 0: # short form netmask
+ mask_bin = 0xffffffff ^ (1 << 32 - int(netmask)) - 1
+ else:
+ return "Malformed" # bad netmask
+
+ if ip_bin & ~mask_bin == 0:
+ return "Invalid" # disallowed by this netmask
+ if ip_bin | mask_bin == 0xFFFFFFFF:
+ return "Invalid" # disallowed by this netmask
+
+ return "Valid"
+
+
+ def _isvalidip(self, ipaddr, netmask = '0'):
+ try:
+ ip = IP(ipaddr)
+ except ValueError:
+ return "Malformed"
- return True
+ ipstr = ip.strNormal(0)
+ ipstr_masked = ip.strNormal(2)
+ if ipstr_masked.count("/") != 0 and netmask == '0':
+ netmask = ipstr_masked.split("/")[1]
- elif family == socket.AF_INET6:
- try:
- socket.inet_pton(socket.AF_INET6, ipaddr)
- except socket.error: # not a valid address
- return False
- return True
+ if ip.version() == 4: # additional checks for ipv4
+ return self._isvalidipv4(ipstr, netmask)
+ # TODO: check ipv6 openbmc/openbmc#496
- else: return False
+ return "Valid"
def _getAddr (self, target, device):
netprov = network_providers [self.provider]
@@ -165,12 +193,13 @@ class NetMan (dbus.service.Object):
@dbus.service.method(DBUS_NAME, "ssss", "x")
def SetAddress4 (self, device, ipaddr, netmask, gateway):
if not self._isvaliddev (device) : raise ValueError, "Invalid Device"
- if not self._isvalidip (socket.AF_INET, ipaddr) : raise ValueError, "Malformed IP Address"
- if not self._isvalidip (socket.AF_INET, gateway) : raise ValueError, "Malformed GW Address"
if not self._isvalidmask (netmask) : raise ValueError, "Invalid Mask"
-
prefixLen = getPrefixLen (netmask)
if prefixLen == 0: raise ValueError, "Invalid Mask"
+ valid = self._isvalidip (ipaddr, netmask)
+ if valid != "Valid": raise ValueError, valid + " IP Address"
+ valid = self._isvalidip (gateway)
+ if valid != "Valid": raise ValueError, valid + " IP Address"
confFile = "/etc/systemd/network/00-bmc-" + device + ".network"
@@ -254,12 +283,13 @@ class NetMan (dbus.service.Object):
file_opened = False
if len(dns_entry) > 0:
for dns in dns_entry:
- if not self._isvalidip (socket.AF_INET, dns):
+ valid = self._isvalidip (dns)
+ if valid != "Valid":
if dns == "DHCP_AUTO=":
#This DNS is supplied by DHCP.
dhcp_auto = True
else:
- print "Malformed DNS Address [" + dns + "]"
+ print valid + " DNS Address [" + dns + "]"
fail_msg = fail_msg + '[' + dns + ']'
else:
#Only over write on a first valid input
OpenPOWER on IntegriCloud