1
0
mirror of https://github.com/samba-team/samba.git synced 2025-07-31 20:22:15 +03:00

samldb: ensure subnets have proper net ranges

A subnet name needs to be a valid CIDR address range -- that's the
ones that look like 10.9.8.0/22, where the number after the /
determines how many bits are in the address suffix. It can be IPv4 or
IPv6. There are a few odd constraints (see MS-ADTS v20150630
6.1.1.2.2.2.1 "Subnet Object") -- for example, with IPv4, the implied
bit mask can't equal the address. That is, you can't have a subnet
named "255.255.255.0/24" in a Windows subnet. This rule does not apply
to IPv6.

Windows and Samba both make some ensure that subnets have a unique
valid name, though unfortunately Windows 2008R2 is rather slack when
it comes to IPv6. We follow Windows 2012R2, which roughly follows
RFC5952 -- with one caveat: Windows will allow an address like
"::ffff:0:1:2", which translates to the IPv4 address "0.1.0.2" using
the SIIT translation scheme, and which inet_ntop() would render as
"::ffff:0:0.1.0.2". In the Samba implementation we use an inet_pton()/
inet_ntop() round-trip to establish canonicality, so these addresses
fail. Windows wisely does not allow the SIIT style addresses (the
acronym is widely agreed to be off-by-one in the second letter), and
it will regard "::ffff:0:1:2" as simply "::ffff:0:1:2" and allow it.
We would like to do that too.

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
Douglas Bagnall
2015-09-23 15:10:56 +12:00
committed by Andrew Bartlett
parent cbb93977cd
commit 906a53f442
3 changed files with 580 additions and 0 deletions

View File

@ -183,5 +183,293 @@ class SimpleSubnetTests(SitesBaseTests):
self.assertRaises(subnets.SubnetNotFound,
subnets.delete_subnet, self.ldb, basedn, cidr)
def test_create_bad_ranges(self):
"""These CIDR ranges all have something wrong with them, and they
should all fail."""
basedn = self.ldb.get_config_basedn()
cidrs = [
# IPv4
# insufficient zeros
"10.11.12.0/14",
"110.0.0.0/6",
"1.0.0.0/0",
"10.11.13.1/24",
"1.2.3.4/29",
"10.11.12.0/21",
# out of range mask
"110.0.0.0/33",
"110.0.0.0/-1",
"4.0.0.0/111",
# out of range address
"310.0.0.0/24",
"10.0.0.256/32",
"1.1.-20.0/24",
# badly formed
"1.0.0.0/1e",
"1.0.0.0/24.0",
"1.0.0.0/1/1",
"1.0.0.0",
"1.c.0.0/24",
"1.2.0.0.0/27",
"1.23.0/24",
"1.23.0.-7/24",
"1.-23.0.7/24",
"1.23.-0.7/24",
"1.23.0.0/0x10",
# IPv6 insufficient zeros -- this could be a subtle one
# due to the vagaries of endianness in the 16 bit groups.
"aaaa:bbbb:cccc:dddd:eeee:ffff:2222:1100/119",
"aaaa:bbbb::/31",
"a:b::/31",
"c000::/1",
"a::b00/119",
"1::1/127",
"1::2/126",
"1::100/119",
"1::8000/112",
# out of range mask
"a:b::/130",
"a:b::/-1",
"::/129",
# An IPv4 address can't be exactly the bitmask (MS ADTS)
"128.0.0.0/1",
"192.0.0.0/2",
"255.192.0.0/10",
"255.255.255.0/24",
"255.255.255.255/32",
"0.0.0.0/0",
# The address can't have leading zeros (not RFC 4632, but MS ADTS)
"00.1.2.0/24",
"003.1.2.0/24",
"022.1.0.0/16",
"00000000000000000000000003.1.2.0/24",
"09876::abfc/126",
"0aaaa:bbbb::/32",
"009876::abfc/126",
"000a:bbbb::/32",
# How about extraneous zeros later on
"3.01.2.0/24",
"3.1.2.00/24",
"22.001.0.0/16",
"3.01.02.0/24",
"100a:0bbb:0023::/48",
"100a::0023/128",
# Windows doesn't like the zero IPv4 address
"0.0.0.0/8",
# or the zero mask on IPv6
"::/0",
# various violations of RFC5952
"0:0:0:0:0:0:0:0/8",
"0::0/0",
"::0:0/48",
"::0:4/128",
"0::/8",
"0::4f/128",
"0::42:0:0:0:0/64",
"4f::0/48",
# badly formed -- mostly the wrong arrangement of colons
"a::b::0/120",
"a::abcdf:0/120",
"a::g:0/120",
"::0::3/48",
"2001:3::110::3/118",
"aaaa:bbbb:cccc:dddd:eeee:ffff:2222:1111:0000/128",
"a:::5:0/120",
# non-canonical representations (vs RFC 5952)
# "2001:0:c633:63::1:0/120" is correct
"2001:0:c633:63:0:0:1:0/120",
"2001::c633:63:0:0:1:0/120",
"2001:0:c633:63:0:0:1::/120",
# "10:0:0:42::/64" is correct
"10::42:0:0:0:0/64",
"10:0:0:42:0:0:0:0/64",
# "1::4:5:0:0:8/127" is correct
"1:0:0:4:5:0:0:8/127",
"1:0:0:4:5::8/127",
# "2001:db8:0:1:1:1:1:1/128" is correct
"2001:db8::1:1:1:1:1/128",
# IP4 embedded - rejected
"a::10.0.0.0/120",
"a::10.9.8.7/128",
"::ffff:0:0/96", #this one fails on WIN2012r2
# completely wrong
None,
"bob",
3.1415,
False,
"10.11.16.0/24\x00hidden bytes past a zero",
self,
]
failures = []
for cidr in cidrs:
try:
subnets.create_subnet(self.ldb, basedn, cidr, self.sitename)
except subnets.SubnetInvalid:
print >> sys.stderr, "%s fails properly" % (cidr,)
continue
# we are here because it succeeded when it shouldn't have.
print >> sys.stderr, "CIDR %s fails to fail" % (cidr,)
failures.append(cidr)
subnets.delete_subnet(self.ldb, basedn, cidr)
if failures:
print "These bad subnet names were accepted:"
for cidr in failures:
print " %s" % cidr
self.fail()
def test_create_good_ranges(self):
"""All of these CIDRs are good, and the subnet creation should
succeed."""
basedn = self.ldb.get_config_basedn()
cidrs = [
# IPv4
"10.11.12.0/24",
"10.11.12.0/23",
"10.11.12.0/25",
"110.0.0.0/7",
"1.0.0.0/32",
"10.11.13.0/32",
"10.11.13.1/32",
"99.0.97.0/24",
"1.2.3.4/30",
"10.11.12.0/22",
"0.12.13.0/24",
# IPv6
"aaaa:bbbb:cccc:dddd:eeee:ffff:2222:1100/120",
"aaaa:bbbb:cccc:dddd:eeee:ffff:2222:11f0/124",
"aaaa:bbbb:cccc:dddd:eeee:ffff:2222:11fc/126",
# don't forget upper case
"FFFF:FFFF:FFFF:FFFF:ABCD:EfFF:FFFF:FFeF/128",
"9876::ab00/120",
"9876::abf0/124",
"9876::abfc/126",
"aaaa:bbbb::/32",
"aaaa:bbba::/31",
"aaaa:ba00::/23",
"aaaa:bb00::/24",
"aaaa:bb00::/77",
"::/48",
"a:b::/32",
"c000::/2",
"a::b00/120",
"1::2/127",
# this pattern of address suffix == mask is forbidden with
# IPv4 but OK for IPv6.
"8000::/1",
"c000::/2",
"ffff:ffff:ffc0::/42",
"FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF/128",
# leading zeros are forbidden, but implicit IPv6 zeros
# (via "::") are OK.
"::1000/116",
"::8000/113",
# taken to the logical conclusion, "::/0" should be OK, but no.
"::/48",
# Try some reserved ranges, which it might be reasonable
# to exclude, but which are not excluded in practice.
"129.0.0.0/16",
"129.255.0.0/16",
"100.64.0.0/10",
"127.0.0.0/8",
"127.0.0.0/24",
"169.254.0.0/16",
"169.254.1.0/24",
"192.0.0.0/24",
"192.0.2.0/24",
"198.18.0.0/15",
"198.51.100.0/24",
"203.0.113.0/24",
"224.0.0.0/4",
"130.129.0.0/16",
"130.255.0.0/16",
"192.12.0.0/24",
"223.255.255.0/24",
"240.255.255.0/24",
"224.0.0.0/8",
"::/96",
"100::/64",
"2001:10::/28",
"fec0::/10",
"ff00::/8",
"::1/128",
"2001:db8::/32",
"2001:10::/28",
"2002::/24",
"2002:a00::/24",
"2002:7f00::/24",
"2002:a9fe::/32",
"2002:ac10::/28",
"2002:c000::/40",
"2002:c000:200::/40",
"2002:c0a8::/32",
"2002:c612::/31",
"2002:c633:6400::/40",
"2002:cb00:7100::/40",
"2002:e000::/20",
"2002:f000::/20",
"2002:ffff:ffff::/48",
"2001::/40",
"2001:0:a00::/40",
"2001:0:7f00::/40",
"2001:0:a9fe::/48",
"2001:0:ac10::/44",
"2001:0:c000::/56",
"2001:0:c000:200::/56",
"2001:0:c0a8::/48",
"2001:0:c612::/47",
"2001:0:c633:6400::/56",
"2001:0:cb00:7100::/56",
"2001:0:e000::/36",
"2001:0:f000::/36",
"2001:0:ffff:ffff::/64",
# non-RFC-5952 versions of these are tested in create_bad_ranges
"2001:0:c633:63::1:0/120",
"10:0:0:42::/64",
"1::4:5:0:0:8/127",
"2001:db8:0:1:1:1:1:1/128",
]
failures = []
for cidr in cidrs:
try:
subnets.create_subnet(self.ldb, basedn, cidr, self.sitename)
except subnets.SubnetInvalid, e:
print e
failures.append(cidr)
continue
ret = self.ldb.search(base=basedn, scope=SCOPE_SUBTREE,
expression=('(&(objectclass=subnet)(cn=%s))' %
cidr))
if len(ret) != 1:
print "%s was not created" % cidr
failures.append(cidr)
continue
subnets.delete_subnet(self.ldb, basedn, cidr)
if failures:
print "These good subnet names were not accepted:"
for cidr in failures:
print " %s" % cidr
self.fail()
TestProgram(module=__name__, opts=subunitopts)