mirror of
https://github.com/dkmstr/openuds.git
synced 2025-10-08 19:34:11 +03:00
182 lines
6.2 KiB
Python
182 lines
6.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
#
|
|
# Copyright (c) 2012 Virtual Cable S.L.
|
|
# All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without modification,
|
|
# are permitted provided that the following conditions are met:
|
|
#
|
|
# * Redistributions of source code must retain the above copyright notice,
|
|
# this list of conditions and the following disclaimer.
|
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
# this list of conditions and the following disclaimer in the documentation
|
|
# and/or other materials provided with the distribution.
|
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
|
# may be used to endorse or promote products derived from this software
|
|
# without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
'''
|
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
|
'''
|
|
from __future__ import unicode_literals
|
|
import re
|
|
|
|
# Test patters for networks
|
|
reCIDR = re.compile(r'^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/([0-9]{1,2})$')
|
|
reMask = re.compile(r'^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})netmask([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$')
|
|
re1Asterisk = re.compile(r'^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.\*$')
|
|
re2Asterisk = re.compile(r'^([0-9]{1,3})\.([0-9]{1,3})\.\*\.?\*?$')
|
|
re3Asterisk = re.compile(r'^([0-9]{1,3})\.\*\.?\*?\.?\*?$')
|
|
reRange = re.compile(r'^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})-([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$')
|
|
reHost = re.compile(r'^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$')
|
|
|
|
|
|
def ipToLong(ip):
|
|
'''
|
|
convert decimal dotted quad string to long integer
|
|
'''
|
|
try:
|
|
hexn = ''.join(["%02X" % long(i) for i in ip.split('.')])
|
|
return long(hexn, 16)
|
|
except:
|
|
return 0 # Invalid values will map to "0.0.0.0" --> 0
|
|
|
|
|
|
def longToIp(n):
|
|
'''
|
|
convert long int to dotted quad string
|
|
'''
|
|
try:
|
|
d = 1 << 24
|
|
q = []
|
|
while d > 0:
|
|
m, n = divmod(n, d)
|
|
q.append(str(m)) # As m is an integer, this works on py2 and p3 correctly
|
|
d >>= 8
|
|
|
|
return '.'.join(q)
|
|
except:
|
|
return '0.0.0.0' # Invalid values will map to "0.0.0.0"
|
|
|
|
|
|
def networksFromString(strNets, allowMultipleNetworks=True):
|
|
'''
|
|
Parses the network from strings in this forms:
|
|
- A.* (or A.*.* or A.*.*.*)
|
|
- A.B.* (or A.B.*.* )
|
|
- A.B.C.* (i.e. 192.168.0.*)
|
|
- A.B.C.D/N (i.e. 192.168.0.0/24)
|
|
- A.B.C.D netmask X.X.X.X (i.e. 192.168.0.0 netmask 255.255.255.0)
|
|
- A.B.C.D - E.F.G.D (i.e. 192-168.0.0-192.168.0.255)
|
|
- A.B.C.D
|
|
If allowMultipleNetworks is True, it allows ',' and ';' separators (and, ofc, more than 1 network)
|
|
Returns a list of networks tuples in the form [(start1, end1), (start2, end2) ...]
|
|
'''
|
|
|
|
inputString = strNets
|
|
|
|
def check(*args):
|
|
for n in args:
|
|
if int(n) < 0 or int(n) > 255:
|
|
raise Exception()
|
|
|
|
def toNum(*args):
|
|
start = 256 * 256 * 256
|
|
val = 0
|
|
for n in args:
|
|
val += start * int(n)
|
|
start >>= 8
|
|
return val
|
|
|
|
def maskFromBits(nBits):
|
|
v = 0
|
|
for n in range(nBits):
|
|
v |= 1 << (31 - n)
|
|
return v
|
|
|
|
if allowMultipleNetworks is True:
|
|
res = []
|
|
for strNet in re.split('[;,]', strNets):
|
|
if strNet != '':
|
|
res.append(networksFromString(strNet, False))
|
|
return res
|
|
|
|
strNets = strNets.replace(' ', '')
|
|
|
|
if strNets == '*':
|
|
return (0, 4294967295)
|
|
|
|
try:
|
|
# Test patterns
|
|
m = reCIDR.match(strNets)
|
|
if m is not None:
|
|
check(*m.groups())
|
|
bits = int(m.group(5))
|
|
if bits < 0 | bits > 32:
|
|
raise Exception()
|
|
val = toNum(*m.groups())
|
|
bits = maskFromBits(bits)
|
|
noBits = ~bits & 0xffffffff
|
|
return (val & bits, val | noBits)
|
|
|
|
m = reMask.match(strNets)
|
|
if m is not None:
|
|
check(*m.groups())
|
|
val = toNum(*(m.groups()[0:4]))
|
|
bits = toNum(*(m.groups()[4:8]))
|
|
noBits = ~bits & 0xffffffff
|
|
return (val & bits, val | noBits)
|
|
|
|
m = reRange.match(strNets)
|
|
if m is not None:
|
|
check(*m.groups())
|
|
val = toNum(*(m.groups()[0:4]))
|
|
val2 = toNum(*(m.groups()[4:8]))
|
|
if val2 < val:
|
|
raise Exception()
|
|
return (val, val2)
|
|
|
|
m = reHost.match(strNets)
|
|
if m is not None:
|
|
check(*m.groups())
|
|
val = toNum(*m.groups())
|
|
return (val, val)
|
|
|
|
for v in ((re1Asterisk, 3), (re2Asterisk, 2), (re3Asterisk, 1)):
|
|
m = v[0].match(strNets)
|
|
if m is not None:
|
|
check(*m.groups())
|
|
val = toNum(*(m.groups()[0:v[1] + 1]))
|
|
bits = maskFromBits(v[1] * 8)
|
|
noBits = ~bits & 0xffffffff
|
|
return (val & bits, val | noBits)
|
|
|
|
# No pattern recognized, invalid network
|
|
raise Exception()
|
|
except:
|
|
raise ValueError(inputString)
|
|
|
|
|
|
def ipInNetwork(ip, network):
|
|
if isinstance(ip, unicode) or isinstance(ip, str):
|
|
ip = ipToLong(ip)
|
|
if isinstance(network, unicode) or isinstance(network, str):
|
|
network = networksFromString(network)
|
|
|
|
for net in network:
|
|
if ip >= net[0] and ip <= net[1]:
|
|
return True
|
|
return False
|