Help testing if a variable contains an IPv4
David Herselman
dhe at syrex.co
Sat Jun 12 19:11:52 CEST 2021
Hi Alan,
Many thanks, the following now works as expected:
(1) Calling-Station-Id = "oxidized.syrex.co.za"
(1) update request {
(1) Tmp-IP-Address-0 := &Calling-Station-Id -> 41.0.0.5
(1) } # update request = noop
(1) if ((&Client-Shortname == "isp_core") && !(&User-Name == "revisioncfg" && &Tmp-IP-Address-0 && <ipv4prefix>&Tmp-IP-Address-0 < 41.0.0.0/29)) {
(1) EXPAND &Client-Shortname
(1) --> isp_core
(1) if ((&Client-Shortname == "isp_core") && !(&User-Name == "revisioncfg" && &Tmp-IP-Address-0 && <ipv4prefix>&Tmp-IP-Address-0 < 41.0.0.0/29)) -> FALSE
(32) Calling-Station-Id = "197.91.242.47"
(32) update request {
(32) Tmp-IP-Address-0 := &Calling-Station-Id -> 197.91.242.47
(32) } # update request = noop
(32) if ((&Client-Shortname == "isp_core") && !(&User-Name == " revisioncfg" && &Tmp-IP-Address-0 && <ipv4prefix>&Tmp-IP-Address-0 < 41.0.0.0/29)) {
(32) EXPAND &Client-Shortname
(32) --> isp_core
(32) if ((&Client-Shortname == "isp_core") && !(&User-Name == " revisioncfg" && &Tmp-IP-Address-0 && <ipv4prefix>&Tmp-IP-Address-0 < 41.0.0.0/29)) -> TRUE
What it however does allow is for someone to set a DNS PTR record for their source IP as a hostname that would resolve to an IP in the 41.0.0.0/29 subnet. I presume I should limit validation to numeric values only by first validating Calling-Station-Id =~ /^\d{1,3}(\.\d{1,3}){3}$/ ?
Regards
David Herselman
-----Original Message-----
From: Freeradius-Users <freeradius-users-bounces+dhe=syrex.co at lists.freeradius.org> On Behalf Of Alan DeKok
Sent: Saturday, 12 June 2021 3:06 PM
To: FreeRadius users mailing list <freeradius-users at lists.freeradius.org>
Subject: Re: Help testing if a variable contains an IPv4
On Jun 12, 2021, at 8:55 AM, David Herselman via Freeradius-Users <freeradius-users at lists.freeradius.org> wrote:
> I'm trying to allow non MFA logins from configuration revisioning systems where the target device doesn't support SSH key based authentication. I started constructing an unlang check using '<ipv4prefix>' and hit some quirks.
>
> Most of our devices include the calling station's source IP in their request, whilst a few send the reverse DNS lookup strings. How do I test if a variable matches the structure of an IPv4 IP?
It depends.
In RADIUS, attributes have a data type. Some are type "string", and others are type "ipaddr". The first one can contain an ASCII string which represents the *printed* form on an IP address. But it's not an IP address.
In contrast, the "ipaddr" data type is a 32-bit IPv4 address.
> My problem appears to be that '<ipv4prefix>&String < 41.0.0.0/29' returns true, for example:
Because an ASCII string isn't a 32-bit IPv4 address.
> (0) Calling-Station-Id = "oxidized.syrex.co.za"
> (0) if (&Client-Shortname == "core_routers") && !(&User-Name == "revisioncfg" && &Calling-Station-Id && <ipv4prefix>&Calling-Station-Id < 41.0.0.0/29) {
That won't work. What you're asking is for it to do a DNS lookup (generally a bad idea, too), and then compare the resulting IP address to the prefix.
What's actually happening is that it's casting the first 32-bits of the string to an IP address, and then checking that.
The solution is to copy the Calling-Station-ID to an attribute of type "ipaddr" first. e.g. Tmp-IP-Address-0. Then, compare that address to the prefix:
update request {
Tmp-IP-Address-0 := &Calling-Station-Id
}
if (<ipv4prefix>&Tmp-IP-Address-0 < 41.0.0.0/29) {
...
}
Alan DeKok.
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
More information about the Freeradius-Users
mailing list