On Sat, Jun 17, 2006 at 02:27:43AM +0900, James F. Hranicky wrote:
> On Friday 16 June 2006 11:51, Tanaka Akira wrote:
> > In article <200606091528.30171.jfh / cise.ufl.edu>,
> >
> >   "James F. Hranicky" <jfh / cise.ufl.edu> writes:
> > > This patch adds support for getting the uid and gid of the peer
> > > socket connected to a Unix domain socket.
> >
> > I think it's good feature.
> 
> Ok -- I think I'm going to take Sam's advice and turn it into one
> method that returns [uid, gid] .

It would be nice to get API feedback from more than 2 people though!

> I'm not sure how to get the creds of a DGRAM sock, though.

Sorry, forget I mentioned it, they come (if at all) with the extra
information from recvmsg, and it doesn't have anything to do with
getpeerid(2) or getpeerucred(2).

> > > + * Document-method: peer_uid
> > > + * call-seq: socket.peer_uid => int
> > > + *
> > > + * Returns the uid of the peer socket for Unix domain stream sockets
> >
> > real uid or effective uid?
> 
> It depends on the platform -- on FreeBSD it's euid, on Linux (I think) it's
> ruid and on Solaris it can be anything, though I stuck with ruid. 

With linux, the man pages make it look like the sender has to explicitly
set the credentials, and can set real or effective, but the kernel does
permissions checks (if non-root, won't allows the uid/gid to be set to
other than the real, effective, or saved values). Perhaps there is
a default if the caller doesn't set them.


A problem with unifying such different interfaces is any assumptions
made (such as the caller doesn't care if it gets ruid or euid from
#peer_uid) are bound to be wrong for somebody.


One other option would be to simply expose system interfaces. I.e.,

- for systems with getpeerid(), add BasicSocket#getpeerid() =>
  [euid,egid] or {:euid=>euid, :egid=>egid}

- for systems with getpeerucred(), add BasicSocket#getpeerucred() =>
  [uid,gid,euid,egid,...], or {:euid=>euid, :egid=>egid, :uid=>uid, ...}

- for linux, emulate getpeerid() by calling getsockopt(), notice that
  linux has struct ucred{pid,uid,gid}

If all three had a single method, peer_id, that returned a Hash, it
would be possible for the caller to look at the contents of the hash,
and use whatever they wanted:

  peer = socket.peer_id[:euid] || socket.peer_id[:uid]

or:

  unless peer = socket.peer_id[:euid]
    raise "effective uid unknown, abort!"
  end


I'm just throwing ideas out there. It seems that by exposing the system
interfaces in way that is as close as possible to the system/C
interfaces (but that DOESN'T involve unpacking binary structures whose
layout varies depending on the OS), the Socket APIs allow you to do
anything you could if you were coding in C. I like that about ruby's
socket support, when it works.

High level functions like #peer_id => [uid,gid] are useful, too, but
they can be implemented in terms of the low-level functions.

Anyhow, one way or another, the information returned by getpeerid(2) and
getpeerucred(2) isn't available in ruby now, and I very much support it
becoming available, thanks for putting this out there.

Sam