##// END OF EJS Templates
IP restrictions now also enabled for IPv6
marcink -
r3345:dc2c1fc9 default
parent child Browse files
Show More
@@ -34,6 +34,7 b' from decorator import decorator'
34 from pylons import config, url, request
34 from pylons import config, url, request
35 from pylons.controllers.util import abort, redirect
35 from pylons.controllers.util import abort, redirect
36 from pylons.i18n.translation import _
36 from pylons.i18n.translation import _
37 from sqlalchemy.orm.exc import ObjectDeletedError
37
38
38 from rhodecode import __platform__, is_windows, is_unix
39 from rhodecode import __platform__, is_windows, is_unix
39 from rhodecode.model.meta import Session
40 from rhodecode.model.meta import Session
@@ -447,8 +448,13 b' class AuthUser(object):'
447 user_ips = user_ips.options(FromCache("sql_cache_short",
448 user_ips = user_ips.options(FromCache("sql_cache_short",
448 "get_user_ips_%s" % user_id))
449 "get_user_ips_%s" % user_id))
449 for ip in user_ips:
450 for ip in user_ips:
450 _set.add(ip.ip_addr)
451 try:
451 return _set or set(['0.0.0.0/0'])
452 _set.add(ip.ip_addr)
453 except ObjectDeletedError:
454 # since we use heavy caching sometimes it happens that we get
455 # deleted objects here, we just skip them
456 pass
457 return _set or set(['0.0.0.0/0', '::/0'])
452
458
453
459
454 def set_available_permissions(config):
460 def set_available_permissions(config):
@@ -990,6 +996,13 b' def check_ip_access(source_ip, allowed_i'
990 log.debug('checking if ip:%s is subnet of %s' % (source_ip, allowed_ips))
996 log.debug('checking if ip:%s is subnet of %s' % (source_ip, allowed_ips))
991 if isinstance(allowed_ips, (tuple, list, set)):
997 if isinstance(allowed_ips, (tuple, list, set)):
992 for ip in allowed_ips:
998 for ip in allowed_ips:
993 if ipaddr.IPAddress(source_ip) in ipaddr.IPNetwork(ip):
999 try:
994 return True
1000 if ipaddr.IPAddress(source_ip) in ipaddr.IPNetwork(ip):
1001 return True
1002 # for any case we cannot determine the IP, don't crash just
1003 # skip it and log as error, we want to say forbidden still when
1004 # sending bad IP
1005 except Exception:
1006 log.error(traceback.format_exc())
1007 continue
995 return False
1008 return False
@@ -562,7 +562,7 b' class UserIpMap(Base, BaseModel):'
562 @classmethod
562 @classmethod
563 def _get_ip_range(cls, ip_addr):
563 def _get_ip_range(cls, ip_addr):
564 from rhodecode.lib import ipaddr
564 from rhodecode.lib import ipaddr
565 net = ipaddr.IPv4Network(ip_addr)
565 net = ipaddr.IPNetwork(address=ip_addr)
566 return [str(net.network), str(net.broadcast)]
566 return [str(net.network), str(net.broadcast)]
567
567
568 def __json__(self):
568 def __json__(self):
@@ -14,6 +14,7 b' from formencode.validators import ('
14 NotEmpty, IPAddress, CIDR
14 NotEmpty, IPAddress, CIDR
15 )
15 )
16 from rhodecode.lib.compat import OrderedSet
16 from rhodecode.lib.compat import OrderedSet
17 from rhodecode.lib import ipaddr
17 from rhodecode.lib.utils import repo_name_slug
18 from rhodecode.lib.utils import repo_name_slug
18 from rhodecode.model.db import RepoGroup, Repository, UsersGroup, User,\
19 from rhodecode.model.db import RepoGroup, Repository, UsersGroup, User,\
19 ChangesetStatus
20 ChangesetStatus
@@ -711,35 +712,31 b' def NotReviewedRevisions(repo_id):'
711 def ValidIp():
712 def ValidIp():
712 class _validator(CIDR):
713 class _validator(CIDR):
713 messages = dict(
714 messages = dict(
714 badFormat=_('Please enter a valid IP address (a.b.c.d)'),
715 badFormat=_('Please enter a valid IPv4 or IpV6 address'),
715 illegalOctets=_('The octets must be within the range of 0-255'
716 ' (not %(octet)r)'),
717 illegalBits=_('The network size (bits) must be within the range'
716 illegalBits=_('The network size (bits) must be within the range'
718 ' of 0-32 (not %(bits)r)'))
717 ' of 0-32 (not %(bits)r)'))
719
718
719 def to_python(self, value, state):
720 v = super(_validator, self).to_python(value, state)
721 v = v.strip()
722 net = ipaddr.IPNetwork(address=v)
723 if isinstance(net, ipaddr.IPv4Network):
724 #if IPv4 doesn't end with a mask, add /32
725 if '/' not in value:
726 v += '/32'
727 if isinstance(net, ipaddr.IPv6Network):
728 #if IPv6 doesn't end with a mask, add /128
729 if '/' not in value:
730 v += '/128'
731 return v
732
720 def validate_python(self, value, state):
733 def validate_python(self, value, state):
721 try:
734 try:
722 # Split into octets and bits
735 addr = value.strip()
723 if '/' in value: # a.b.c.d/e
736 #this raises an ValueError if address is not IpV4 or IpV6
724 addr, bits = value.split('/')
737 ipaddr.IPNetwork(address=addr)
725 else: # a.b.c.d
726 addr, bits = value, 32
727 # Use IPAddress validator to validate the IP part
728 IPAddress.validate_python(self, addr, state)
729 # Bits (netmask) correct?
730 if not 0 <= int(bits) <= 32:
731 raise formencode.Invalid(
732 self.message('illegalBits', state, bits=bits),
733 value, state)
734 # Splitting faild: wrong syntax
735 except ValueError:
738 except ValueError:
736 raise formencode.Invalid(self.message('badFormat', state),
739 raise formencode.Invalid(self.message('badFormat', state),
737 value, state)
740 value, state)
738
741
739 def to_python(self, value, state):
740 v = super(_validator, self).to_python(value, state)
741 #if IP doesn't end with a mask, add /32
742 if '/' not in value:
743 v += '/32'
744 return v
745 return _validator
742 return _validator
General Comments 0
You need to be logged in to leave comments. Login now