Subject: passive() and seteuid(0)

From: Michael Douglass <[email-masked]>
Date: Sun, 16 Nov 1997 14:06:25 -0600

Okay, I was perusing the wu-ftpd source (beta 15) today.  I was specifically
looking at the passive() function; wanting to impose limits on the ports
that it binds the new socket to so that we can open a firewall with a
limited range of ports--then I stumbled upon the code doing the binding:

    pasv_addr = ctrl_addr;
    pasv_addr.sin_port = 0;
    delay_signaling(); /* we can't allow any signals while euid==0: kinch */
    (void) seteuid((uid_t) 0);          /* XXX: not needed if > 1024 */
    if (bind(pdata, (struct sockaddr *) &pasv_addr, sizeof(pasv_addr)) < 0) {
        (void) seteuid((uid_t) pw->pw_uid);
        enable_signaling(); /* we can allow signals once again: kinch */
        goto pasv_error;
    }
    (void) seteuid((uid_t) pw->pw_uid);
    enable_signaling(); /* we can allow signals once again: kinch */
 
I can't figure out why we are gaining root permissions before calling this
bind() command...  We are not binding to a priveledged port in this code
segment, why do we need root perms?

-- 
Michael Douglass
Texas Networking, Inc.

 "The past is a foreign country; they do things differently there."
      L. P. Hartley, British author. The Go-Between, Prologue (1953).

---

From: "Roger A. Hanke" <[email-masked]>
Date: Mon, 17 Nov 1997 10:18:15 -0500

Pedro Melo has already completed a pasv port patch and submitted it to
Stan. A number of us have been using it for awhile. You just define the
range of ports you want the server to return, so you can only open up
your firewall for that range. Sounded as if you have the same need as
many of us. Please take a look at his patch and lets pick one version and
try to get it in the base product. I have included the last patch email 
I had from Pedro at the end of this mail.
	Roger Hanke

----------
From: 	Michael Douglass[SMTP:[email-masked]]
Reply To: 	[email-masked]
Sent: 	Sunday, November 16, 1997 3:06 PM
To: 	[email-masked]
Subject: 	passive() and seteuid(0)

    pasv_addr = ctrl_addr;
    pasv_addr.sin_port = 0;

-- 
Michael Douglass
Texas Networking, Inc.

----------------------------------------------------------------------------------
Hi!

Some time ago I made a patch for beta12 that allows you to restrict the
port ranges used by passive mode ftp. 

This is helpfull for people who dont want to open just a part of their port
space in their firewall.

So far, the pacth is compile time only. You cannot specify in the  config
file the port range to use. You have to change the values of PASSIVE_BASE
and PASSIVE_SPAN in the patched ftpd.c and recompile... For ex, if you want
to open ports 4000 to 5000, use PASSIVE_BASE 4000 and PASSIVE_SPAN 1000

Apply to the ftpd.c in the src directory...

I've been working with this patch for a coupple of month now, no problems.

*** ftpd.c.orig	Fri Mar 21 02:15:09 1997
--- ftpd.c	Fri Mar 21 02:19:00 1997
***************
*** 394,399 ****
--- 394,401 ----
      struct sockaddr_in *virtual_ptr;
  #endif
  
+     srandom(getpid());
+ 
  #ifdef AUX
      setcompat(COMPAT_POSIX | COMPAT_BSDSETUGID);
  #endif
***************
*** 3246,3251 ****
--- 3248,3256 ----
   * response by Jon Postel in a telephone conversation with Rick Adams on
25
   * Jan 89. */
  
+ #define PASSIVE_BASE 3000
+ #define PASSIVE_SPAN 500
+ 
  void
  #ifdef __STDC__
  passive(void)
***************
*** 3253,3259 ****
  passive()
  #endif
  {
!     int len;
      register char *p,
       *a;
  
--- 3258,3264 ----
  passive()
  #endif
  {
!     int len, bind_error;
      register char *p,
       *a;
  
***************
*** 3268,3281 ****
          return;
      }
      pasv_addr = ctrl_addr;
!     pasv_addr.sin_port = 0;
      delay_signaling(); /* we can't allow any signals while euid==0: kinch
*/
      (void) seteuid((uid_t) 0);		/* XXX: not needed if >
1024 */
!     if (bind(pdata, (struct sockaddr *) &pasv_addr, sizeof(pasv_addr)) <
0) {
!         (void) seteuid((uid_t) pw->pw_uid);
!         enable_signaling(); /* we can allow signals once again: kinch */
!         goto pasv_error;
      }
      (void) seteuid((uid_t) pw->pw_uid);
      enable_signaling(); /* we can allow signals once again: kinch */
      len = sizeof(pasv_addr);
--- 3273,3293 ----
          return;
      }
      pasv_addr = ctrl_addr;
! 
      delay_signaling(); /* we can't allow any signals while euid==0: kinch
*/
      (void) seteuid((uid_t) 0);		/* XXX: not needed if >
1024 */
!     do {
!         pasv_addr.sin_port = PASSIVE_BASE + random() % PASSIVE_SPAN;
!         if (log_commands) syslog(LOG_DEBUG, "PASV trying %d",
pasv_addr.sin_port);
!         bind_error = bind(pdata, (struct sockaddr *) &pasv_addr,
sizeof(pasv_addr));
!     } while(errno==EADDRINUSE);
!     if (bind_error < 0) {
!               (void) seteuid((uid_t) pw->pw_uid);
!               enable_signaling(); /* we can allow signals once again:
kinch */
!               goto pasv_error;
      }
+     if (log_commands) syslog(LOG_DEBUG, "PASV got %d",
pasv_addr.sin_port);
+ 
      (void) seteuid((uid_t) pw->pw_uid);
      enable_signaling(); /* we can allow signals once again: kinch */
      len = sizeof(pasv_addr);
--
************** Pedro Melo ([email-masked]) BOFH ******************
*   TELENET, Servicos de Telecomunicacoes, SA - Tel +351 1 3139190   *
* finger [email-masked] or search key servers for PGP key *
*           It's management's job to support the geniuses,           *
*                      not to tell them what to do                   *
**********************************************************************