Daring to challenge the will of the almighty Leviam00se, Roger Espel Llima
: >I'm testing Unix-domain datagram sockets for an implementation
: >of local RPC, and the following question arose:
: >Given that a server has received a call (via recvfrom()), how can it
: >retrieve the Unix credentials of the client?
: >I'd like at least the effective uid and gid, but the pid and real
: >uid/gid would be nice too.
: >My current approach is to use the st_uid/st_gid fields of the
: >'struct stat' of the client's sun_path, which I got from recvfrom().
: >(Since the application is RPC and not message passing, I require the
: >client to bind() to a valid return address before calling the server.)
: >Is this the best way to do it?
: >Unfortunately, this doesn't give me the caller's pid, and I'm not
: >100% certain of it's accuracy -- i.e., can the client lie?
The st_uid/st_gid members of struct stat show you the owner and group
of the file that was opened. Unfortunately, this does not give you
absolute proof of the client process' idendity since it could have
opened a file for reading that was owned by someone else. (I agonized
over something similar to this not too long ago; I was able to find
problems with every suggestion someone gave me. Finally I had to hack
the kernel to get what I wanted.)
: If you're using RPC (as in, Sun's RPC over XDR, rfc1057), you *could*
: use authentification over RPC. It comes in various flavors: AUTH_NULL
: (no auth), AUTH_UNIX (which sucks; the client can lie), and AUTH_DES
: (which is fairly secure, but requires the clients to have generated keys
: for themselves, and may not be available on all systems).
It also requires DES. :) Plus it too has some problems: in an RPC
message that uses AUTH_DES, you have a small block of data containing
credentials and the verifier, and then you have the actual contents
of the RPC. The problem is that the cred/verifier data is not tied
to the RPC itself in any particular way. There is an expiration window
to attempt to avoid replay (after the window expires, you have to
recompute the verifier) but the window is usually on the order of a
couple of minutes. What this means is that if I can intercept an RPC
with a valid credential/verifier block, I can strip the creds and
verifier from the message, attatch it to one of my own, then send it
out the server. The server will know that the verifier is correct, but
then it just arbitrarily trusts the rest of the message. Ideally the
verifier should contain an encrypted checksum of the RPC, but unfortunately
that's not how it works.
: >(I'm using Unix-domain sockets because I also need to be able to pass
: >open file descriptors around. The only viable alternatives I know of
: >are less widely available (SVR4 Streams, Solaris Doors, and Linux
: >SCM_CREDENTIALS control messages).)
: I'd go for SCM_CREDENTIALS/SCM_CRED whenever they're available.
FreeBSD also supports SCM_CREDS with its sendmsg()/recvmsg() system
calls, as does BSD/OS (though in a slightly different manner).
I know of the trick with streams/TLI where you can use t_getinfo()
to learn the identify of the process on the other end of a TLI endpoint,
though offhand I don't remember the code to do it.
: Otherwise, you could come up with some scheme like:
: . have a special 1777 directory used only for auth
: . have the client create a file there, mode 600
: . pass the file's fd (through the Unix domain socket) to the server
: . fstat(), then unlink.
This is similar to some of the suggestions I got when I was looking into
this sort of thing. This is kind a of long way to go, and if you look
at it long enough you'll eventually find a problem with it. At the very
least, this is a terrible kludge and introduces more work (extra syscalls)
that you really shouldn't have to do.
: That loses on systems that let people give away their files, though.
See? I told you you'd find something wrong with it. :)
-Bill Paul (212) 854-6020 | System Manager, Master of Unix-Fu
"Now, that's "Open" as used in the sentence "Open your wallet", right?"