[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

ftpd and IP_PORTRANGE



I thought others might find this useful.

The enclosed patches cause ftpd to bind to high port numbers when
serving clients in passive mode.  This makes it much easier to define
sane IP packet filters on machines running ftpd.  It is accomplished
using the IP_PORTRANGE setsockopt available on *BSD systems.  It will
have no effect on systems without IP_PORTRANGE.

I've also added a `-U' flag to revert to the old behavior.  The flag
name and the semantics match the same flag on FreeBSD's ftpd.

Cheers,
-- 
Jacques Vidrine / n@nectar.com / jvidrine@verio.net / nectar@FreeBSD.org


--- appl/ftp/ftpd/ftpd.c.orig	Thu Aug 31 01:08:49 2000
+++ appl/ftp/ftpd/ftpd.c	Fri Nov  3 12:01:17 2000
@@ -68,6 +68,7 @@
 int	debug = 0;
 int	ftpd_timeout = 900;    /* timeout after 15 minutes of inactivity */
 int	maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
+int	restricted_data_ports = 1;
 int	logging;
 int	guest;
 int	dochroot;
@@ -215,6 +216,7 @@
     { NULL, 't', arg_integer, &ftpd_timeout, "initial timeout" },
     { NULL, 'T', arg_integer, &maxtimeout, "max timeout" },
     { NULL, 'u', arg_string, &umask_string, "umask for user logins" },
+    { NULL, 'U', arg_negative_flag, &restricted_data_ports, "don't use high data ports" },
     { NULL, 'd', arg_flag, &debug, "enable debugging" },
     { NULL, 'v', arg_flag, &debug, "enable debugging" },
     { "builtin-ls", 'B', arg_flag, &use_builtin_ls, "use built-in ls to list files" },
@@ -1942,6 +1944,8 @@
 	socket_set_address_and_port (pasv_addr,
 				     socket_get_address (ctrl_addr),
 				     0);
+	socket_set_portrange(pdata, restricted_data_ports, 
+	    pasv_addr->sa_family); 
 	seteuid(0);
 	if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) {
 		seteuid(pw->pw_uid);
@@ -1984,6 +1988,8 @@
 	socket_set_address_and_port (pasv_addr,
 				     socket_get_address (ctrl_addr),
 				     0);
+	socket_set_portrange(pdata, restricted_data_ports, 
+	    pasv_addr->sa_family); 
 	seteuid(0);
 	if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) {
 		seteuid(pw->pw_uid);
--- appl/ftp/ftpd/ftpd.8.orig	Tue Feb 16 14:14:08 1999
+++ appl/ftp/ftpd/ftpd.8	Fri Nov  3 12:07:47 2000
@@ -43,7 +43,7 @@
 .Sh SYNOPSIS
 .Nm ftpd
 .Op Fl a Ar authmode
-.Op Fl dilv
+.Op Fl dilvU
 .Op Fl g Ar umask
 .Op Fl p Ar port 
 .Op Fl T Ar maxtimeout
@@ -127,6 +127,13 @@
 seconds (the default is 15 minutes).
 .It Fl u
 Set the initial umask to something else than the default 027.
+.It Fl U
+In previous versions of
+.Nm ftpd ,
+when a passive mode client requested a data connection to the server, the 
+server would use data ports in the range 1024..4999.  Now, by default, the 
+server will use data ports in the range 49152..65535.  Specifying this option
+will revert to the old behavior.  
 .It Fl v
 Verbose mode.
 .El
--- lib/roken/socket.c.orig	Wed Jul 26 23:41:06 2000
+++ lib/roken/socket.c	Fri Nov  3 11:56:34 2000
@@ -222,6 +222,31 @@
 }
 
 /*
+ * Set the range of ports to use when binding with port = 0.
+ */
+void
+socket_set_portrange (int sock, int restrict, int af)
+{
+#if defined(IP_PORTRANGE)
+	if (af == AF_INET) {
+		int on = restrict ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
+		if (setsockopt (sock, IPPROTO_IP, IP_PORTRANGE, &on,
+		    sizeof(on)) < 0)
+			warn ("setsockopt IP_PORTRANGE (ignored)");
+	}
+#endif
+#if defined(IPV6_PORTRANGE)
+	if (af == AF_INET6) {
+		int on = restrict ? IPV6_PORTRANGE_HIGH : 
+		    IPV6_PORTRANGE_DEFAULT;
+		if (setsockopt (sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on,
+		    sizeof(on)) < 0)
+			warn ("setsockopt IPV6_PORTRANGE (ignored)");
+	}
+#endif
+}
+	
+/*
  * Enable debug on `sock'.
  */
 
--- lib/roken/roken-common.h.orig	Fri Nov  3 11:31:42 2000
+++ lib/roken/roken-common.h	Fri Nov  3 11:57:01 2000
@@ -276,6 +276,9 @@
 socket_set_port (struct sockaddr *sa, int port);
 
 void
+socket_set_portrange (int sock, int restrict, int af);
+
+void
 socket_set_debug (int sock);
 
 void