Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 8 May 2004 17:23:54 +0400
From:      Yar Tikhiy <yar@comp.chem.msu.su>
To:        "Bjoern A. Zeeb" <bzeeb-lists@lists.zabbadoz.net>
Cc:        net@freebsd.org
Subject:   Re: bin/65928: [PATCH] stock ftpd uses superuser credentials for active mode sockets
Message-ID:  <20040508132354.GB44214@comp.chem.msu.su>
In-Reply-To: <Pine.BSF.4.53.0405080636010.66978@e0-0.zab2.int.zabbadoz.net>
References:  <20040508034514.GA937@grosbein.pp.ru> <Pine.BSF.4.53.0405080636010.66978@e0-0.zab2.int.zabbadoz.net>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sat, May 08, 2004 at 06:40:41AM +0000, Bjoern A. Zeeb wrote:
> 
> > When an active IPv4 TCP connection between
> > localIP:localport and remoteIP1:remoteport1 exists,
> > it is not possible for local non-root user to create outgoing
> > TCP connection from localIP:localport to remoteIP2:remoteport2.
> >
> > Why? It prevents http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/65928
> > from resolving.
> 
> to do it with other wording:
> 
> if in active mode data is send to remote, the server uses ftp-data
> as port (which is 20 [ftp(21)-1]) and you are running into creating
> a socket in the privileged port range:
> net.inet.ip.portrange.reservedlow to net.inet.ip.portrange.reservedhigh
> which "only may be opened by root-owned processes" [ip(4)].

Not exactly.  The right to bind a socket to a priviliged port is
verified against the process credentials, with suser() and at a
different point in the code.  Eugene is talking about socket
credentials, so_cred, and their use in preventing port stealth.
It's a different thing, it applies to any port number.  The code
in question is in file sys/netinet/in_pcb.c, function in_pcbbind():

        if (so->so_cred->cr_uid != 0 &&
            !IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
                t = in_pcblookup_local(inp->inp_pcbinfo,
                    sin->sin_addr, lport,
                    prison ? 0 :  INPLOOKUP_WILDCARD);
                if (t &&
        ...

My investigation shows that the problem is somewhat tangled.  On
the one hand, it has to do with the way in_pcblookup_local() is
invoked to check for possible port stealth.  The function takes the
last on/off argument "wild_okay" instructing it whether to consider
connected sockets along with unconnected ones.  This argument is
set to 1 by the code in question unless we're in jail.  Consequently,
the function can match established connections.

On the other hand, "wild_okay" can't just be set to constant 0 there
because in this case in_pcblookup_local() would not match connections
with the local wildcard address.  Perhaps, yet another "if" needs to
be added to check if the existing inpcb found is not connected yet.
Another point to note here is that for a UDP inpcb having the foreign
address set to something different from INADDR_ANY doesn't mean the
inpcb is actually connected.

-- 
Yar



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040508132354.GB44214>