bin/65928: [PATCH] stock ftpd uses superuser credentials for active mode sockets

Eugene Grosbein eugen at grosbein.pp.ru
Sat Apr 24 05:40:08 PDT 2004


>Number:         65928
>Category:       bin
>Synopsis:       [PATCH] stock ftpd uses superuser credentials for active mode sockets
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Apr 24 05:40:07 PDT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Eugene Grosbein
>Release:        FreeBSD 4.10-BETA i386
>Organization:
Svyaz Service JSC
>Environment:
System: FreeBSD grosbein.pp.ru 4.10-BETA FreeBSD 4.10-BETA #0: Sun Apr 11 15:43:04 KRAST 2004 eu at grosbein.pp.ru:/usr/local/obj/usr/local/src/sys/DADV i386

>Description:
		ftpd(8) has to switch euid to 0 when it needs to bind(2)
		a socket to a port 'ftp-data' for active mode transfer.
		Now uses seteuid/socket/bind/... sequence. So the socket
		belongs to the superuser and data flow is matched
		by rules similar to:

		ipfw add count tcp from me 20 to any uid root

		The sequence socket/seteuid/bind results in another situation:
		the socket belongs to the authenticated user and
		data flow is matched by rules similar to:

		ipfw add count tcp from me 20 to any uid ftp

		That's much better. That makes it possible to engage
		all the power of system credential control.
		Ftp traffic can be shaped using dummynet per-user,
		for example. It can be easily accounted or blocked, too.
		The same for ordinary user's traffic.
		
>How-To-Repeat:

		Use rules like this:

ipfw add 1 count tcp from 127.0.0.1 ftp-data to any uid root out
ipfw add 2 count tcp from 127.0.0.1 ftp-data to any uid ftp out

		Connect to local ftpd, turn passive mode off and do 'ls'.
		Then see ipfw rules counters.

>Fix:

		Apply next patch:

--- ftpd.c.orig	Fri Apr 23 20:42:47 2004
+++ ftpd.c	Fri Apr 23 20:43:23 2004
@@ -1792,7 +1792,6 @@
 
 	if (data >= 0)
 		return (fdopen(data, mode));
-	(void) seteuid((uid_t)0);
 
 	s = socket(data_dest.su_family, SOCK_STREAM, 0);
 	if (s < 0)
@@ -1802,6 +1801,7 @@
 	/* anchor socket to avoid multi-homing problems */
 	data_source = ctrl_addr;
 	data_source.su_port = htons(dataport);
+	(void) seteuid((uid_t)0);
 	for (tries = 1; ; tries++) {
 		if (bind(s, (struct sockaddr *)&data_source,
 		    data_source.su_len) >= 0)


Eugene Grosbein
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list