[comp.unix.wizards] Authenticating Unix Domain sockets.

peter@prefect.Berkeley.EDU (Peter Moore) (01/29/91)

What I would like is a guaranteed way of finding out the uid of a process
that just connected to me using local (same machine) IPC.  I have vague memory
of special ioctl or connect argument that would give me the uid of the
connecting process when using Unix domain sockets.  But I have RTFM
(actually greped the man pages) and haven't found any sign of such a beast.

Normally I would have chalked this up to youthful hallucinations , but
I also didn't find the magic method to pass open file descriptors over
Unix domain sockets, and I KNOW that used to be in at least 4.3 BSD Unix.

So, does anyone know of such a beast?  Authentication of IPC of any
sort on almost any Unix would be of interest.
 

	Peter Moore
	Objectivity Inc.
	peter@objy.com

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (01/30/91)

In article <1991Jan29.063539.2169@objy.com> peter@objy.com writes:
: What I would like is a guaranteed way of finding out the uid of a process
: that just connected to me using local (same machine) IPC.

What do you mean by "the" uid?  Given that the other end of a socket may
be open multiple times by multiple processes, there's no guarantee of
uniqueness.

To answer your question, apart from using a secure protocol or grodying
about in the kernel like fuser or ofiles, there isn't a way.

Larry Wall
lwall@jpl-devvax.jpl.nasa.gov

gsf@ulysses.att.com (Glenn S. Fowler) (01/30/91)

In article <11225@jpl-devvax.JPL.NASA.GOV> lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) writes:
>In article <1991Jan29.063539.2169@objy.com> peter@objy.com writes:
>: What I would like is a guaranteed way of finding out the uid of a process
>: that just connected to me using local (same machine) IPC.
>What do you mean by "the" uid?  Given that the other end of a socket may
>be open multiple times by multiple processes, there's no guarantee of
>uniqueness.

accept() on a unix domain socket returns an fd to 1/2 of a unique r/w
stream of which the other 1/2 is returned by connect() (presumably in
another proc)

so there are only two processes in question, the accept()-process A and
the connect()-process C

the problem is to authenticate the uid of C within A

you can set up a handshake where C must pass an fd that only the owner
of the corresponding file F could have opened -- A will then fstat(fd)
and check it against stat(F), along with checks verifying that only C
could have opened F

the access rights array of send(2) and recv(2) are used to send fd's

I would also be interested in an ioctl() to get the uid of C from A

note that the streams ioctl I_RECVFD (the other side of I_SENDFD)
provides uid,gid authentication

Glenn Fowler    (908)-582-2195    AT&T Bell Laboratories, Murray Hill, NJ
uucp: {att,ucbvax}!ulysses!gsf              internet: gsf@ulysses.att.com

viktor@shearson.com (Viktor Dukhovni) (01/31/91)

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) writes:

>In article <1991Jan29.063539.2169@objy.com> peter@objy.com writes:
>: What I would like is a guaranteed way of finding out the uid of a process
>: that just connected to me using local (same machine) IPC.

>What do you mean by "the" uid?  Given that the other end of a socket may
>be open multiple times by multiple processes, there's no guarantee of
>uniqueness.

	Actually this is wrong!  With a SOCK_STREAM socket,  
or using the "fromaddr" argument of recvfrom() the peer address
can be examined using getpeername or directly respectively.

	Since UNIX sockets must be bound explicitly,  and must not
exit prior to creation,  the effecttive user id of the remote process
is the same as the owner of the the remote socket in the file space.

	Just 
	
	struct sockaddr_un fromaddr;
	int len=sizeof(fromaddr);
	uid_t uid;

	bzero(fromaddr,len);

	geetpeername(s,(struct sockaddr *)&fromaddr,&len);
	if ( ((struct sockaddr *)&fromaddr)->sa_family != AF_UNIX ) {
		/* Bitch about impossible connection */
		exit(1);
	}

	stat( fromaddr.sun_path, &st );
	uid = st.st_uid;

	...

Works for me.  Your mileage may vary.

-- 
-- 
        Viktor Dukhovni <viktor@shearson.com>       : ARPA
                <...!uunet!shearson.com!viktor>     : UUCP
        388 Greenwich St., 11th floor, NY, NY 10013 : US-Post

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (01/31/91)

In article <1991Jan30.213227.19055@shearson.com> viktor@shearson.com (Viktor Dukhovni) writes:
: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) writes:
: 
: >In article <1991Jan29.063539.2169@objy.com> peter@objy.com writes:
: >: What I would like is a guaranteed way of finding out the uid of a process
: >: that just connected to me using local (same machine) IPC.
: 
: >What do you mean by "the" uid?  Given that the other end of a socket may
: >be open multiple times by multiple processes, there's no guarantee of
: >uniqueness.
: 
: 	Actually this is wrong!  With a SOCK_STREAM socket,  
: or using the "fromaddr" argument of recvfrom() the peer address
: can be examined using getpeername or directly respectively.
: 
: 	Since UNIX sockets must be bound explicitly,  and must not
: exit prior to creation,  the effecttive user id of the remote process
: is the same as the owner of the the remote socket in the file space.

Oh, come now.  This is comp.unix.wizards.  Surely you've heard of fork()
and setuid().  I can easily make your socket hooked to 10 processes, not
one of which has the uid of the socket in the file space.  One of the
first tricks in the book is to fork the client so that you have separate
processes reading and writing the socket.

And we're ignoring totally the possibility that the file you are stat()ing
may not be the file you thought you were stat()ing.  At a miminum, change
your code to use fstat().

On top of which, the file is owned by the process that creates it, which is
going to be the server, not the client.  No good for finding out who just
connected to you.

: 	Just 
: 	
: 	struct sockaddr_un fromaddr;
: 	int len=sizeof(fromaddr);
: 	uid_t uid;
: 
: 	bzero(fromaddr,len);
: 
: 	geetpeername(s,(struct sockaddr *)&fromaddr,&len);
: 	if ( ((struct sockaddr *)&fromaddr)->sa_family != AF_UNIX ) {
: 		/* Bitch about impossible connection */
: 		exit(1);
: 	}
: 
: 	stat( fromaddr.sun_path, &st );
: 	uid = st.st_uid;
: 
: 	...
: 
: Works for me.  Your mileage may vary.

It certainly does.

Larry