Abstract:
Add calls to UNIXSocket to pass around the UNIX credentials (i.e. pid,
uid and gid).
Problem:
There is no way, that I know of, within Ruby to find out which process
is connected at the other end of a UNIX socket.
Ex:
[gus@comp unix_credentials]$ irb
irb(main):001:0> require ‘socket’
=> true
irb(main):002:0> s = UNIXServer.new(‘unixtest’)
=> #UNIXServer:unixtest
irb(main):003:0> t = s.accept
=> #UNIXSocket:0x4396d330
irb(main):004:0> t.peeraddr
=> [“AF_UNIX”, “”] # Doesn’t tell you anything!
Proposal:
I propose the addition of two methods, send_credentials and
recv_credentils to pass through a UNIX socket the process id, user id
and group id.
Analysis:
The Linux system provide a mechanism to send UNIX credentials as
ancilary data (the same way as you can pass file descriptors,
implemented in Ruby as send_io). Other UNIX implementation I believe
offer similar mechanism.
One difference with just sending this data directly through the UNIX
socket (for example as a Mashalled array containing the pid, uid and
gid) is that the system does some checks on the values send (unless you
are root and are allowed to lie).
Implementation:
The attached patch implements it. It has been tested on Linux 2.4 only.
It is heavily inspired by the implementation of send_io. Usage example:
The Linux system provide a mechanism to send UNIX credentials as
ancilary data (the same way as you can pass file descriptors,
implemented in Ruby as send_io). Other UNIX implementation I believe
offer similar mechanism.
I surveyed the feature sometime ago.
Unfortunately it is not so portable.
SCM_CREDS and getpeerid.
There are 2 kind of interfaces.
SCM_CREDS: a client must send a credential explicitly.
getpeerid: a client doesn’t need to send a credential.
getpeerid
As far as I know, following system has getpeerid or similar.
This works fine too:
class UNIXSocket
def getpeercredentials
getsockopt(Socket::SOL_SOCKET, Socket::SO_PEERCRED).unpack(“i3”)
end
end
No need for C code. Tested on Linux. A web search tells me that the
SO_PEERCRED option is supported on the BSD family as well. The closest
thing to a BSD machine I have is a MacOS X box, which doesn’t support
it. Can anybody try this piece of code on *BSD?
There seems to be a similar mechanism as the Linux one to pass this
information as ancillary data and *BSD, with the SCM_CREDS cmsg type
and struct cmsgcred. But once again, Apple is failing on me: the
definition of struct cmsgcred is surrounded by #ifndefAPPLE … #endif.
The advantage of sending ancillary data compared to getsockopt is that
you can send you euid and egid instead of uid and gid.
Guillaume.
···
Le 18 mai 04, à 23:20, Yukihiro Matsumoto a écrit :
I like the idea. But I don’t want to merge it if it’s Linux
specific. Any idea?
So, should we implement a UNIXSocket#getpeerid method, using getpeerid()
or SO_PEERCRED, depending on what’s available? The way of doing things
with getpeerid seems more natural than SCM_CREDS.
The Linux system provide a mechanism to send UNIX credentials as
ancilary data (the same way as you can pass file descriptors,
implemented in Ruby as send_io). Other UNIX implementation I believe
offer similar mechanism.
I surveyed the feature sometime ago.
Unfortunately it is not so portable.
SCM_CREDS and getpeerid.
There are 2 kind of interfaces.
SCM_CREDS: a client must send a credential explicitly.
getpeerid: a client doesn’t need to send a credential.
getpeerid
As far as I know, following system has getpeerid or similar.