]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
mask off ipv4 prefix bits, to be in compliance with RFC8044 Section 3.11
authorAlan T. DeKok <aland@freeradius.org>
Thu, 12 Feb 2026 01:53:43 +0000 (20:53 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 12 Feb 2026 01:53:43 +0000 (20:53 -0500)
this shouldn't strictly be necessary, as the value-boxes should
already enforce this.  But layers of protection aren't bad.

src/protocols/radius/encode.c

index bc57a464fb9fb44f6a087a1cf301109863a60327..f9d8ef6346dfc7bbdd0576ea01bff4e53d71ac44 100644 (file)
@@ -466,12 +466,31 @@ static ssize_t encode_value(fr_dbuff_t *dbuff,
                break;
 
        /*
-        *      Common encoder doesn't add reserved byte
+        *      Common encoder doesn't add reserved byte, so we add one here to be compliant with RFC 8044
+        *      Section 3.11.
         */
        case FR_TYPE_IPV4_PREFIX:
        ipv4_prefix:
-               FR_DBUFF_IN_BYTES_RETURN(&value_dbuff, 0x00, vp->vp_ip.prefix);
-               FR_DBUFF_IN_MEMCPY_RETURN(&value_dbuff, (uint8_t const *)&vp->vp_ipv4addr, sizeof(vp->vp_ipv4addr));
+               if (!vp->vp_ipv4addr) {
+                       /*
+                        *      If the ipaddr is all zeros, then the prefix length MUST be set to 32.
+                        */
+                       FR_DBUFF_IN_BYTES_RETURN(&value_dbuff, 0x00, 0x20);
+               } else {
+                       uint32_t ipaddr = vp->vp_ipv4addr;
+
+                       FR_DBUFF_IN_BYTES_RETURN(&value_dbuff, 0x00, vp->vp_ip.prefix);
+
+                       if (vp->vp_ip.prefix == 0) {
+                               ipaddr = 0;
+
+                       } else if (vp->vp_ip.prefix < 32) {
+                               ipaddr &= htonl(~((1UL << (32 - vp->vp_ip.prefix)) - 1));
+
+                       } /* else leave ipaddr alone */
+
+                       FR_DBUFF_IN_MEMCPY_RETURN(&value_dbuff, (uint8_t const *) &ipaddr, sizeof(ipaddr));
+               }
                break;
 
        /*