Of all the gin joints in all the towns in all the world, Theo de Raadt had to walk into mine and say: > Regarding: > > > -pmap_set : it is called when a rpc program wants to register itself in the > > portmapper list (rpcinfo -p returns this list). > > > > -pmap_unset : same as above but it's used to unregister a rpc program. > > Again, Wietse' portmapper fixed almost all the holes related to pset/punset > > rpc calls. > > > > However, due to a restriction in the protocol, all the security problems > > cannot be fixed easily. When a rpc program (such as rpc.mountd) wants to > > un/register itself on the portmapper list, it sends an udp || tcp packet to > > the portmapper (port 111) using the pmap_set or pmap_unset respectively. [...] There's really only one way to completely fix this problem with portmap, and that is simply not to use TCP or UDP. Instead, you need to use a local-only transport, such as an AF_LOCAL socket. It's actually very easy to do this: I took copies of the TCP transport client and server modules from the FreeBSD RPC library and converted them to use AF_LOCAL stream sockets instead of AF_INET. Additionally, if you use an AF_LOCAL socket in conjunction with SCM_CREDS credential transfers, you can provide a much more secure mechanism for preventing local users from setting/unsetting mappings that don't belong to them. As you say, this does require changes to libc, so it's not something to be undertaken lightly and it would be difficult to manage with commercial systems for which you don't have the source code. With TI-RPC, you already have a special loopback transport available which provides similar functionality. However TI-RPC is based on TLI, and none of the BSD-based systems or Linux have support for TLI or STREAMS (yet) so they use the older RPC 4.0 instead, which only supports TCP and UDP. I had a choice between trying to implement all of the necessary support code to make TI-RPC work in FreeBSD or add an additional transport to the existing RPC library. Lacking the time and understanding needed to do the former, I instead chose the latter. The advantage to using an AF_LOCAL socket is that right away the server can tell if it's handling a remote or local request by checking the family type of the socket in its transport handle. TCP or UDP sockets will be AF_INET instead of AF_LOCAL. Procedures that really care about enforcing access can choose to deny connections from AF_INET sockets, which will lock out any non-local process. Also, by using SCM_CREDS, the portmapper can check which local user is sending the request (and can be relatively sure of the information since it's provided by the kernel, not the caller, and is thus harder to spoof). This means that if user A registers a service, the portmapper can insure that only user A (or root) can unregister it later. Right now, access checks are performed in rpcinfo, which is a bad idea (access checks should be in the server, not the client). You still need to allow UDP/TCP access to some of the proceedures since remote hosts have to be able to reference the port/program number mappings and use the callit routine, but restricting the set/unset procedures by only allowing AF_LOCAL connections insures that no remote process can ever fiddle with the mapping tables. I had plans to do this for FreeBSD and actually added code to libc to test for an AF_LOCAL socket special file and use that if it's present, rolling over to the old mechanism if it isn't. However I still need to modify portmap itself, which is a little tricky because I want to store the EUID of the caller that registers a service for access checks later, and the structure used to store the mappings doesn't have room for this. Unfortunately, this structure is set in stone in the portmap protocol specification. Before I was able to get very far on this, I got sidetracked by other things. My main reason for creating this extra transport and adding the SCM_CREDS support to the kernel was for the Secure RPC keyserv program, which, in RPC 4.0, also uses a terrible kludge not too different from the mess in portmap to enforce access restrictions to its secret key tables. Keyserv normally relies on the bletcherous keyenvoy program, which the client has to invoke in order to talk to the key server. The problem here is that a client can't use Secure RPC credentials and verifiers until the user does a keylogin to load his secret key into the local keyserv, but keyserv also needs to use an authentication mechanism to make sure that another user can't spoof a request to steal the user's secret key once it's been loaded. TI-RPC uses the loopback transport and a special TLI routine called t_getinto() to do this, which does away with the need for the keyenvoy program. However FreeBSD doesn't have TLI/STREAMS, so I had to improvise. -Bill -- ============================================================================= -Bill Paul (212) 854-6020 | System Manager, Master of Unix-Fu Work: wpaulat_private | Center for Telecommunications Research Home: wpaulat_private | Columbia University, New York City ============================================================================= "Mulder, toads just fell from the sky!" "I guess their parachutes didn't open." =============================================================================
This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:23:28 PDT