Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion openwisp_radius/api/freeradius_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ def _check_client_ip_and_return(self, request, uuid):

for ip in ip_list:
try:
if ipaddress.ip_address(client_ip) in ipaddress.ip_network(ip):
if ipaddress.ip_address(client_ip) in ipaddress.ip_network(
(ip or "").strip(), strict=False
):
return (AnonymousUser(), uuid)
except ValueError:
invalid_addr_message = _(
Expand Down
11 changes: 8 additions & 3 deletions openwisp_radius/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1338,8 +1338,11 @@ def __str__(self):
@property
def freeradius_allowed_hosts_list(self):
addresses = []
if self.freeradius_allowed_hosts:
addresses = self.freeradius_allowed_hosts.split(",")
addresses = [
(ip or "").strip()
for ip in (self.freeradius_allowed_hosts or "").split(",")
if (ip or "").strip()
]
return addresses

@property
Expand Down Expand Up @@ -1383,7 +1386,9 @@ def _clean_freeradius_allowed_hosts(self):
else:
try:
for ip_address in allowed_hosts_set:
ipaddress.ip_network(ip_address)
ip_str = (ip_address or "").strip()
if ip_str:
ipaddress.ip_network(ip_str, strict=False)
except ValueError:
raise ValidationError(
{
Expand Down
61 changes: 61 additions & 0 deletions openwisp_radius/tests/test_api/test_freeradius_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2385,6 +2385,67 @@ def test_ip_from_radsetting_valid(self):
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, _AUTH_TYPE_ACCEPT_RESPONSE)

def test_ip_from_radsetting_cidr_range_valid(self):
with mock.patch(self.freeradius_hosts_path, []):
radsetting = OrganizationRadiusSettings.objects.get(
organization=self._get_org()
)
radsetting.freeradius_allowed_hosts = "172.18.0.0/16"
radsetting.save()

with mock.patch(
"openwisp_radius.api.freeradius_views.get_client_ip",
return_value=("172.18.0.10", True),
):
response = self.client.post(reverse("radius:authorize"), self.params)

self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, _AUTH_TYPE_ACCEPT_RESPONSE)

def test_ip_from_radsetting_spaces_and_host_bits_valid(self):
org = self._get_org()
with mock.patch(self.freeradius_hosts_path, []):
radsetting = OrganizationRadiusSettings.objects.get(organization=org)

radsetting.freeradius_allowed_hosts = "127.0.0.1, 172.18.0.5/16"
radsetting.save()

self.assertEqual(
cache.get(f"ip-{org.pk}"),
["127.0.0.1", "172.18.0.5/16"],
)

with mock.patch(
"openwisp_radius.api.freeradius_views.get_client_ip",
return_value=("172.18.0.10", True),
):
response = self.client.post(reverse("radius:authorize"), self.params)

self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, _AUTH_TYPE_ACCEPT_RESPONSE)

@capture_any_output()
def test_ip_outside_cidr_range_rejected(self):
with mock.patch(self.freeradius_hosts_path, []):
radsetting = OrganizationRadiusSettings.objects.get(
organization=self._get_org()
)
radsetting.freeradius_allowed_hosts = "172.18.0.0/16"
radsetting.save()

with mock.patch(
"openwisp_radius.api.freeradius_views.get_client_ip",
return_value=("10.0.0.5", True),
):
response = self.client.post(reverse("radius:authorize"), self.params)

self.assertEqual(response.status_code, 403)
self.assertEqual(
response.data["detail"],
"Request rejected: Client IP address (10.0.0.5) is not in "
"the list of IP addresses allowed to consume the freeradius API.",
)

def test_ip_from_setting_valid(self):
response = self.client.post(reverse("radius:authorize"), self.params)
self.assertEqual(response.status_code, 200)
Expand Down
Loading