]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
limit src port ranges to >1024
authorAlan T. DeKok <aland@freeradius.org>
Sat, 7 Feb 2026 17:28:57 +0000 (12:28 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Sat, 7 Feb 2026 17:28:57 +0000 (12:28 -0500)
and do a few more cleanups.

src/lib/bio/fd_open.c

index 9ec486794193b9e4f34fe1869db2f5d89c2ced9a..4f63a62827ae0ccd5e737f3fcd9e4ba036007fa6 100644 (file)
@@ -736,32 +736,43 @@ static int fr_bio_fd_socket_bind(fr_bio_fd_t *my, fr_bio_fd_config_t const *cfg)
 
        fr_assert((my->info.socket.af == AF_INET) || (my->info.socket.af == AF_INET6));
 
+       /*
+        *      Ranges must be a high value.
+        */
+       if (my->info.cfg->src_port_start && (my->info.cfg->src_port_start < 1024)) {
+               fr_strerror_const("Cannot set src_port_start in the range 1..1023");
+               return -1;
+       }
+
 #ifdef HAVE_CAPABILITY_H
        /*
-        *      If we're binding to a special port as non-root, then
-        *      check capabilities.  If we're root, we already have
-        *      equivalent capabilities so we don't need to check.
+        *      Source port is in the restricted range, and we're not root, we need to set a capability.
+        *
+        *      @todo - we really need to call rad_suid_up() and rad_suid_down() here.  But those functions
+        *      are in src/lib/server/util.c, and we can't require that libfreeradius-bio is linked to
+        *      libfreeradius-server.
         */
-       if ((my->info.socket.inet.src_port < 1024) && (geteuid() != 0)) {
-               (void)fr_cap_enable(CAP_NET_BIND_SERVICE, CAP_EFFECTIVE);
+       if ((my->info.socket.inet.src_port > 0) && (my->info.socket.inet.src_port < 1024) && (geteuid() != 0));
+               (void) fr_cap_enable(CAP_NET_BIND_SERVICE, CAP_EFFECTIVE);
        }
 #endif
 
        if (fr_bio_fd_socket_bind_to_device(my, cfg) < 0) return -1;
 
        /*
-        *      Bind to the IP + interface.
+        *      Get the sockaddr for bind()
         */
        if (fr_ipaddr_to_sockaddr(&salocal, &salen, &my->info.socket.inet.src_ipaddr, my->info.socket.inet.src_port) < 0) return -1;
 
        /*
-        *      If we have a fixed source port, just use that.
+        *      We don't have a source port range, just bind to whatever source port that we're given.
         */
-       if (my->info.cfg->src_port || !my->info.cfg->src_port_start) {
+       if (!my->info.cfg->src_port_start) {
                if (bind(my->info.socket.fd, (struct sockaddr *) &salocal, salen) < 0) {
                        fr_strerror_printf("Failed binding to socket: %s", fr_syserror(errno));
                        return -1;
                }
+
        } else {
                uint16_t src_port, current, range;
                struct sockaddr_in *sin = (struct sockaddr_in *) &salocal;
@@ -816,7 +827,7 @@ static int fr_bio_fd_socket_bind(fr_bio_fd_t *my, fr_bio_fd_config_t const *cfg)
        }
 
        /*
-        *      The source IP may have changed, so get the new one.
+        *      The IP and/or port may have changed, so get the new one.
         */
 done:
        return fr_bio_fd_socket_name(my);