Discussion:
getpeereid() or equivalent
(too old to reply)
Arne H. Juul
2007-07-30 12:50:09 UTC
Permalink
I'm trying to port some code that on FreeBSD uses the getpeereid()
system call, to get the user and group IDs of a peer connected on a
UNIX-domain socket.

Question 1: has anybody considered porting this functionality
from FreeBSD to NetBSD? it seems like a simple but useful system
call to have. (snippet from the FreeBSD man page at the bottom).

Question 2: it looks like it's possible to do the same using
setsockopt with LOCAL_CREDS, but I'm not at all sure if I have
understood the documentation correctly. My first try that
actually compiles looks like this:

+#elif defined(__NetBSD__)
+ uid_t puid = 0xffffffff;
+ gid_t pgid = 0xffffffff;
+
+ int opt = 1;
+ if (setsockopt(s, 0, LOCAL_CREDS, &opt, sizeof(opt)) < 0) {
+ ::close(s);
+ continue;
+ }
+ char ctl[128];
+ struct msghdr msg;
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = NULL;
+ msg.msg_iovlen = 0;
+ msg.msg_control = ctl;
+ msg.msg_controllen = sizeof(ctl);
+ msg.msg_flags = 0;
+
+ len = recvmsg(s, &msg, 0);
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+ if (cmsg != NULL
+ && cmsg->cmsg_level == SOL_SOCKET
+ && cmsg->cmsg_type == SCM_CREDS
+ && cmsg->cmsg_len >= CMSG_LEN(SOCKCREDSIZE(0)))
+ {
+ struct sockcred *creds = (struct sockcred *)CMSG_DATA(cmsg);
+ puid = creds->sc_uid;
+ pgid = creds->sc_gid;
+ } else {
+ ::close(s);
+ continue;
+ }

so does anybody see some obvious problems with this code?
And does anybody have some example code or small test programs that
does this the correct way that I could borrow code from, that would be
even better...

Here's the (much simpler to use) FreBSD call:

SYNOPSIS
#include <sys/types.h>
#include <unistd.h>

int getpeereid(int s, uid_t *euid, gid_t *egid);

DESCRIPTION
The getpeereid() function returns the effective user and group IDs of the
peer connected to a UNIX-domain socket. The argument s must be a
UNIX-domain socket (unix(4)) of type SOCK_STREAM on which either
connect(2) or listen(2) have been called. The effective used ID is
placed in euid, and the effective group ID in egid.

The credentials returned to the listen(2) caller are those of its peer at
the time it called connect(2); the credentials returned to the connect(2)
caller are those of its peer at the time it called listen(2). This mech-
anism is reliable; there is no way for either side to influence the cre-
dentials returned to its peer except by calling the appropriate system
call (i.e., either connect(2) or listen(2)) under different effective
credentials.


Thanks in advance,

- Arne H. J.

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Matthias Scheler
2007-07-31 13:44:23 UTC
Permalink
Post by Arne H. Juul
I'm trying to port some code that on FreeBSD uses the getpeereid()
system call, to get the user and group IDs of a peer connected on a
UNIX-domain socket.
Is it really only supported for UNIX-domain sockets? Solaris 10 also
supports it for loopback TCP/IP connections.

Kind regards
--
Matthias Scheler http://zhadum.org.uk/

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Daniel Carosone
2007-07-31 23:59:36 UTC
Permalink
Post by Arne H. Juul
I'm trying to port some code that on FreeBSD uses the getpeereid()
system call, to get the user and group IDs of a peer connected on a
UNIX-domain socket.
You want getsockopt and the SO_PEERCRED option. AFAICT, this is the
'conventional' way of getting this functionality across (at least)
Linux and *BSD - the FreeBSD syscall seems to be an extra. (Is it
really a syscall, or a convenient library wrapper around getsockopt?)

For usage examples, see postgresql or ssh code.

--
Dan.
Jason Thorpe
2007-08-01 04:21:28 UTC
Permalink
Post by Daniel Carosone
Post by Arne H. Juul
I'm trying to port some code that on FreeBSD uses the getpeereid()
system call, to get the user and group IDs of a peer connected on a
UNIX-domain socket.
You want getsockopt and the SO_PEERCRED option. AFAICT, this is the
'conventional' way of getting this functionality across (at least)
Linux and *BSD - the FreeBSD syscall seems to be an extra. (Is it
really a syscall, or a convenient library wrapper around getsockopt?)
The latter, I believe. If we have the sockopt, might as well have the
API call as well.
Post by Daniel Carosone
For usage examples, see postgresql or ssh code.
--
Dan.
-- thorpej


--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Arne H. Juul
2007-08-01 09:27:17 UTC
Permalink
Post by Daniel Carosone
You want getsockopt and the SO_PEERCRED option. AFAICT, this is the
'conventional' way of getting this functionality across (at least)
Linux and *BSD - the FreeBSD syscall seems to be an extra. (Is it
really a syscall, or a convenient library wrapper around getsockopt?)
The latter, I believe. If we have the sockopt, might as well have the API
call as well.
you're both right in that - the FreeBSD getpeereid() is just a wrapper
around getsockopt with their LOCAL_PEERCRED option. But my NetBSD
-current machine has neither SO_PEERCRED nor LOCAL_PEERCRED defined
anywhere:

blackbox:~:$ uname -s -r
NetBSD 4.99.25
blackbox:~:$ grep -r SO_PEERCRED /usr/include/
blackbox:~:$ grep -r LOCAL_PEERCRED /usr/include/
blackbox:~:$ grep -r LOCAL_CREDS /usr/include/
/usr/include/sys/un.h:#define LOCAL_CREDS 0x0001 /* pass
credentials to receiver */

only the LOCAL_CREDS that I mentioned in my first mail is defined.
Post by Daniel Carosone
For usage examples, see postgresql or ssh code.
the ssh code looks really bad to me when SO_PEERCRED is undefined.

- Arne H. J.

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Jason Thorpe
2007-08-01 17:56:11 UTC
Permalink
Post by Arne H. Juul
Post by Jason Thorpe
Post by Daniel Carosone
You want getsockopt and the SO_PEERCRED option. AFAICT, this is the
'conventional' way of getting this functionality across (at least)
Linux and *BSD - the FreeBSD syscall seems to be an extra. (Is it
really a syscall, or a convenient library wrapper around
getsockopt?)
The latter, I believe. If we have the sockopt, might as well have
the API call as well.
you're both right in that - the FreeBSD getpeereid() is just a wrapper
around getsockopt with their LOCAL_PEERCRED option. But my NetBSD
-current machine has neither SO_PEERCRED nor LOCAL_PEERCRED defined
Right, we don't implement that socket option yet. We'd need to do
that first.
Post by Arne H. Juul
blackbox:~:$ uname -s -r
NetBSD 4.99.25
blackbox:~:$ grep -r SO_PEERCRED /usr/include/
blackbox:~:$ grep -r LOCAL_PEERCRED /usr/include/
blackbox:~:$ grep -r LOCAL_CREDS /usr/include/
/usr/include/sys/un.h:#define LOCAL_CREDS 0x0001 /* pass
credentials to receiver */
only the LOCAL_CREDS that I mentioned in my first mail is defined.
Post by Jason Thorpe
Post by Daniel Carosone
For usage examples, see postgresql or ssh code.
the ssh code looks really bad to me when SO_PEERCRED is undefined.
- Arne H. J.
-- thorpej


--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Daniel Carosone
2007-08-01 11:28:43 UTC
Permalink
Post by Arne H. Juul
blackbox:~:$ grep -r SO_PEERCRED /usr/include/
blackbox:~:$ grep -r LOCAL_PEERCRED /usr/include/
blackbox:~:$ grep -r LOCAL_CREDS /usr/include/
/usr/include/sys/un.h:#define LOCAL_CREDS 0x0001 /* pass
credentials to receiver */
only the LOCAL_CREDS that I mentioned in my first mail is defined.
Yeah. Despite my flaky memory, and my quick check to confirm the name
in the postgresql doc, this must be what pg is using on netbsd - since
I know it works and I use it many times each day.
Post by Arne H. Juul
Post by Daniel Carosone
For usage examples, see postgresql or ssh code.
the ssh code looks really bad to me when SO_PEERCRED is undefined.
It really does, at least for a general-purpose function, but I guess
it depends how the callers use the result.

--
Dan.
Arne H. Juul
2007-08-05 17:32:38 UTC
Permalink
First, thanks for answers and pointers - I've found the code in postgresql
that uses LOCAL_CREDS, and there the other end of the connection needs to
actively send a control message, so I don't think that's a workable
solution for the code I'm working on.
Right, we don't implement that socket option yet. We'd need to do that
first.
After looking at SO_PEERCRED on linux I would guess implementing that
exactly is a bit bothersome - it's a very linuxish API (also known as
a hack).
But the functionality is easy to replicate in NetBSD, especially after
looking at how FreeBSD and OpenBSD does this.

Here's a patch implementing a LOCAL_PEEREID option for getsockopt().

- Arne H. J.

Index: sys/sys/un.h
===================================================================
RCS file: /usr/cvs/src/sys/sys/un.h,v
retrieving revision 1.39
diff -u -r1.39 un.h
--- sys/sys/un.h 23 Jul 2006 22:06:14 -0000 1.39
+++ sys/sys/un.h 5 Aug 2007 17:06:50 -0000
@@ -57,8 +57,18 @@
#if defined(_NETBSD_SOURCE)
#define LOCAL_CREDS 0x0001 /* pass credentials to receiver */
#define LOCAL_CONNWAIT 0x0002 /* connects block until accepted */
+#define LOCAL_PEEREID 0x0003 /* get peer identification */
#endif

+/*
+ * data automatically stored inside connect() for use by LOCAL_PEERCRED
+ */
+struct unpcbid {
+ pid_t unp_pid; /* process id */
+ uid_t unp_euid; /* effective user id */
+ gid_t unp_egid; /* effective group id */
+};
+
#ifdef _KERNEL
struct unpcb;
struct socket;
Index: sys/sys/unpcb.h
===================================================================
RCS file: /usr/cvs/src/sys/sys/unpcb.h,v
retrieving revision 1.14
diff -u -r1.14 unpcb.h
--- sys/sys/unpcb.h 11 Dec 2005 12:25:21 -0000 1.14
+++ sys/sys/unpcb.h 5 Aug 2007 16:51:44 -0000
@@ -78,11 +78,26 @@
int unp_mbcnt; /* copy of rcv.sb_mbcnt */
struct timespec unp_ctime; /* holds creation time */
int unp_flags; /* misc flags; see below*/
+ struct unpcbid unp_connid; /* id and eids of peer */
};

-/* unp_flags */
+/*
+ * Flags in unp_flags.
+ *
+ * UNP_EIDSVALID - indicates that the unp_connid member is filled in
+ * and is really the effective ids of the connected peer. This is used
+ * to determine whether the contents should be sent to the user or
+ * not.
+ *
+ * UNP_EIDSBIND - indicates that the unp_connid member is filled
+ * in, but does *not* contain the effective ids of the connected peer
+ * (there may not even be a peer). This is set in unp_listen() when
+ * it fills in unp_connid for later consumption by unp_connect().
+ */
#define UNP_WANTCRED 0x0001 /* credentials wanted */
#define UNP_CONNWAIT 0x0002 /* connect blocks until accepted */
+#define UNP_EIDSVALID 0x0004 /* unp_connid contains valid data */
+#define UNP_EIDSBIND 0x0008 /* unp_connid was set by a bind */

#define sotounpcb(so) ((struct unpcb *)((so)->so_pcb))

Index: sys/kern/uipc_usrreq.c
===================================================================
RCS file: /usr/cvs/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.98
diff -u -r1.98 uipc_usrreq.c
--- sys/kern/uipc_usrreq.c 3 Aug 2007 20:49:45 -0000 1.98
+++ sys/kern/uipc_usrreq.c 5 Aug 2007 17:07:33 -0000
@@ -113,8 +113,8 @@
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
-#include <sys/unpcb.h>
#include <sys/un.h>
+#include <sys/unpcb.h>
#include <sys/namei.h>
#include <sys/vnode.h>
#include <sys/file.h>
@@ -499,17 +499,22 @@

case PRCO_GETOPT:
switch (optname) {
+ case LOCAL_PEEREID:
+ if (unp->unp_flags & UNP_EIDSVALID) {
+ *mp = m = m_get(M_WAIT, MT_SOOPTS);
+ m->m_len = sizeof(struct unpcbid);
+ *mtod(m, struct unpcbid *) = unp->unp_connid;
+ } else {
+ error = EINVAL;
+ }
+ break;
case LOCAL_CREDS:
*mp = m = m_get(M_WAIT, MT_SOOPTS);
m->m_len = sizeof(int);
- switch (optname) {

#define OPTBIT(bit) (unp->unp_flags & (bit) ? 1 : 0)

- case LOCAL_CREDS:
- optval = OPTBIT(UNP_WANTCRED);
- break;
- }
+ optval = OPTBIT(UNP_WANTCRED);
*mtod(m, int *) = optval;
break;
#undef OPTBIT
@@ -658,6 +663,10 @@
unp->unp_vnode = vp;
unp->unp_addrlen = addrlen;
unp->unp_addr = sun;
+ unp->unp_connid.unp_pid = p->p_pid;
+ unp->unp_connid.unp_euid = kauth_cred_geteuid(p->p_cred);
+ unp->unp_connid.unp_egid = kauth_cred_getegid(p->p_cred);
+ unp->unp_flags |= UNP_EIDSBIND;
VOP_UNLOCK(vp, 0);
return (0);

@@ -672,11 +681,13 @@
struct sockaddr_un *sun;
struct vnode *vp;
struct socket *so2, *so3;
- struct unpcb *unp2, *unp3;
+ struct unpcb *unp, *unp2, *unp3;
size_t addrlen;
+ struct proc *p;
int error;
struct nameidata nd;

+ p = l->l_proc;
/*
* Allocate a temporary sockaddr. We have to allocate one extra
* byte so that we can ensure that the pathname is nul-terminated.
@@ -714,6 +725,7 @@
error = ECONNREFUSED;
goto bad;
}
+ unp = sotounpcb(so);
unp2 = sotounpcb(so2);
unp3 = sotounpcb(so3);
if (unp2->unp_addr) {
@@ -724,7 +736,15 @@
unp3->unp_addrlen = unp2->unp_addrlen;
}
unp3->unp_flags = unp2->unp_flags;
+ unp3->unp_connid.unp_pid = p->p_pid;
+ unp3->unp_connid.unp_euid = kauth_cred_geteuid(p->p_cred);
+ unp3->unp_connid.unp_egid = kauth_cred_getegid(p->p_cred);
+ unp3->unp_flags |= UNP_EIDSVALID;
so2 = so3;
+ if (unp2->unp_flags & UNP_EIDSBIND) {
+ unp->unp_connid = unp2->unp_connid;
+ unp->unp_flags |= UNP_EIDSVALID;
+ }
}
error = unp_connect2(so, so2, PRU_CONNECT);
bad:

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Arne H. Juul
2007-08-06 09:08:33 UTC
Permalink
Post by Arne H. Juul
Here's a patch implementing a LOCAL_PEEREID option for getsockopt().
and here's an updated version with some comments fixed, one
change to fstat (has to include sys/un.h before sys/unpcb.h)
and getpeereid() library function added.

- Arne H. J.


Index: sys/sys/un.h
===================================================================
RCS file: /usr/cvs/src/sys/sys/un.h,v
retrieving revision 1.39
diff -u -r1.39 un.h
--- sys/sys/un.h 23 Jul 2006 22:06:14 -0000 1.39
+++ sys/sys/un.h 6 Aug 2007 08:11:39 -0000
@@ -57,8 +57,18 @@
#if defined(_NETBSD_SOURCE)
#define LOCAL_CREDS 0x0001 /* pass credentials to receiver */
#define LOCAL_CONNWAIT 0x0002 /* connects block until accepted */
+#define LOCAL_PEEREID 0x0003 /* get peer identification */
#endif

+/*
+ * data automatically stored inside connect() for use by LOCAL_PEEREID
+ */
+struct unpcbid {
+ pid_t unp_pid; /* process id */
+ uid_t unp_euid; /* effective user id */
+ gid_t unp_egid; /* effective group id */
+};
+
#ifdef _KERNEL
struct unpcb;
struct socket;
Index: sys/sys/unpcb.h
===================================================================
RCS file: /usr/cvs/src/sys/sys/unpcb.h,v
retrieving revision 1.14
diff -u -r1.14 unpcb.h
--- sys/sys/unpcb.h 11 Dec 2005 12:25:21 -0000 1.14
+++ sys/sys/unpcb.h 6 Aug 2007 08:18:11 -0000
@@ -78,11 +78,25 @@
int unp_mbcnt; /* copy of rcv.sb_mbcnt */
struct timespec unp_ctime; /* holds creation time */
int unp_flags; /* misc flags; see below*/
+ struct unpcbid unp_connid; /* pid and eids of peer */
};

-/* unp_flags */
+/*
+ * Flags in unp_flags.
+ *
+ * UNP_EIDSVALID - indicates that the unp_connid member is filled in
+ * and is really the effective ids of the connected peer. This is used
+ * to determine whether the contents should be sent to the user or
+ * not.
+ *
+ * UNP_EIDSBIND - indicates that the unp_connid member is filled
+ * in with data for the listening process. This is set in unp_bind() when
+ * it fills in unp_connid for later consumption by unp_connect().
+ */
#define UNP_WANTCRED 0x0001 /* credentials wanted */
#define UNP_CONNWAIT 0x0002 /* connect blocks until accepted */
+#define UNP_EIDSVALID 0x0004 /* unp_connid contains valid data */
+#define UNP_EIDSBIND 0x0008 /* unp_connid was set by a bind */

#define sotounpcb(so) ((struct unpcb *)((so)->so_pcb))

Index: sys/kern/uipc_usrreq.c
===================================================================
RCS file: /usr/cvs/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.98
diff -u -r1.98 uipc_usrreq.c
--- sys/kern/uipc_usrreq.c 3 Aug 2007 20:49:45 -0000 1.98
+++ sys/kern/uipc_usrreq.c 5 Aug 2007 17:07:33 -0000
@@ -113,8 +113,8 @@
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
-#include <sys/unpcb.h>
#include <sys/un.h>
+#include <sys/unpcb.h>
#include <sys/namei.h>
#include <sys/vnode.h>
#include <sys/file.h>
@@ -499,17 +499,22 @@

case PRCO_GETOPT:
switch (optname) {
+ case LOCAL_PEEREID:
+ if (unp->unp_flags & UNP_EIDSVALID) {
+ *mp = m = m_get(M_WAIT, MT_SOOPTS);
+ m->m_len = sizeof(struct unpcbid);
+ *mtod(m, struct unpcbid *) = unp->unp_connid;
+ } else {
+ error = EINVAL;
+ }
+ break;
case LOCAL_CREDS:
*mp = m = m_get(M_WAIT, MT_SOOPTS);
m->m_len = sizeof(int);
- switch (optname) {

#define OPTBIT(bit) (unp->unp_flags & (bit) ? 1 : 0)

- case LOCAL_CREDS:
- optval = OPTBIT(UNP_WANTCRED);
- break;
- }
+ optval = OPTBIT(UNP_WANTCRED);
*mtod(m, int *) = optval;
break;
#undef OPTBIT
@@ -658,6 +663,10 @@
unp->unp_vnode = vp;
unp->unp_addrlen = addrlen;
unp->unp_addr = sun;
+ unp->unp_connid.unp_pid = p->p_pid;
+ unp->unp_connid.unp_euid = kauth_cred_geteuid(p->p_cred);
+ unp->unp_connid.unp_egid = kauth_cred_getegid(p->p_cred);
+ unp->unp_flags |= UNP_EIDSBIND;
VOP_UNLOCK(vp, 0);
return (0);

@@ -672,11 +681,13 @@
struct sockaddr_un *sun;
struct vnode *vp;
struct socket *so2, *so3;
- struct unpcb *unp2, *unp3;
+ struct unpcb *unp, *unp2, *unp3;
size_t addrlen;
+ struct proc *p;
int error;
struct nameidata nd;

+ p = l->l_proc;
/*
* Allocate a temporary sockaddr. We have to allocate one extra
* byte so that we can ensure that the pathname is nul-terminated.
@@ -714,6 +725,7 @@
error = ECONNREFUSED;
goto bad;
}
+ unp = sotounpcb(so);
unp2 = sotounpcb(so2);
unp3 = sotounpcb(so3);
if (unp2->unp_addr) {
@@ -724,7 +736,15 @@
unp3->unp_addrlen = unp2->unp_addrlen;
}
unp3->unp_flags = unp2->unp_flags;
+ unp3->unp_connid.unp_pid = p->p_pid;
+ unp3->unp_connid.unp_euid = kauth_cred_geteuid(p->p_cred);
+ unp3->unp_connid.unp_egid = kauth_cred_getegid(p->p_cred);
+ unp3->unp_flags |= UNP_EIDSVALID;
so2 = so3;
+ if (unp2->unp_flags & UNP_EIDSBIND) {
+ unp->unp_connid = unp2->unp_connid;
+ unp->unp_flags |= UNP_EIDSVALID;
+ }
}
error = unp_connect2(so, so2, PRU_CONNECT);
bad:
Index: usr.bin/fstat/fstat.c
===================================================================
RCS file: /usr/cvs/src/usr.bin/fstat/fstat.c,v
retrieving revision 1.75
diff -u -r1.75 fstat.c
--- usr.bin/fstat/fstat.c 11 May 2006 11:56:38 -0000 1.75
+++ usr.bin/fstat/fstat.c 5 Aug 2007 20:26:53 -0000
@@ -52,6 +52,7 @@
#include <sys/socketvar.h>
#include <sys/domain.h>
#include <sys/protosw.h>
+#include <sys/un.h>
#include <sys/unpcb.h>
#include <sys/sysctl.h>
#include <sys/filedesc.h>
Index: include/unistd.h
===================================================================
RCS file: /usr/cvs/src/include/unistd.h,v
retrieving revision 1.112
diff -u -r1.112 unistd.h
--- include/unistd.h 2 Aug 2007 21:49:10 -0000 1.112
+++ include/unistd.h 5 Aug 2007 20:33:06 -0000
@@ -312,6 +312,7 @@
int getgrouplist(const char *, gid_t, gid_t *, int *);
int getgroupmembership(const char *, gid_t, gid_t *, int, int *);
mode_t getmode(const void *, mode_t);
+int getpeereid(int, uid_t *, gid_t *);
int getsubopt(char **, char * const *, char **);
__aconst char *getusershell(void);
int initgroups(const char *, gid_t);
Index: lib/libc/net/Makefile.inc
===================================================================
RCS file: /usr/cvs/src/lib/libc/net/Makefile.inc,v
retrieving revision 1.71
diff -u -r1.71 Makefile.inc
--- lib/libc/net/Makefile.inc 26 Aug 2006 16:11:05 -0000 1.71
+++ lib/libc/net/Makefile.inc 5 Aug 2007 20:40:48 -0000
@@ -5,7 +5,7 @@
.PATH: ${ARCHDIR}/net ${.CURDIR}/net

SRCS+= __cmsg_alignbytes.c base64.c ethers.c gethnamaddr.c getifaddrs.c \
- getnetnamadr.c getnetent.c \
+ getnetnamadr.c getnetent.c getpeereid.c \
getprotobyname.c getprotobynumber.c getprotoent.c \
getprotobyname_r.c getprotobynumber_r.c getprotoent_r.c \
getservbyname.c getservbyport.c getservent.c \
@@ -42,7 +42,7 @@
.include "${ARCHDIR}/net/Makefile.inc"

MAN+= byteorder.3 ethers.3 gethostbyname.3 getifaddrs.3 \
- getnetent.3 getprotoent.3 \
+ getnetent.3 getprotoent.3 getpeereid.3 \
getservent.3 inet.3 inet_net.3 iso_addr.3 linkaddr.3 \
nsdispatch.3 rcmd.3 resolver.3 sockatmark.3

Index: lib/libc/net/getpeereid.c
===================================================================
RCS file: lib/libc/net/getpeereid.c
diff -N lib/libc/net/getpeereid.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ lib/libc/net/getpeereid.c 5 Aug 2007 20:34:50 -0000
@@ -0,0 +1,18 @@
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+
+int
+getpeereid(int s, uid_t *euid, gid_t *egid)
+{
+ struct unpcbid cred;
+ socklen_t len = sizeof(cred);
+ if (getsockopt(s, 0, LOCAL_PEEREID, &cred, &len) < 0) {
+ return -1;
+ } else {
+ *euid = cred.unp_euid;
+ *egid = cred.unp_egid;
+ return 0;
+ }
+}
Index: lib/libc/net/getpeereid.3
===================================================================
RCS file: lib/libc/net/getpeereid.3
diff -N lib/libc/net/getpeereid.3
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ lib/libc/net/getpeereid.3 5 Aug 2007 20:43:08 -0000
@@ -0,0 +1,140 @@
+.\"
+.\" Copyright (c) 2001 Dima Dorfman.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/lib/libc/gen/getpeereid.3,v 1.6 2002/12/18 10:13:54 ru Exp $
+.\"
+.Dd July 15, 2001
+.Dt GETPEEREID 3
+.Os
+.Sh NAME
+.Nm getpeereid
+.Nd get the effective credentials of a UNIX-domain peer
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In unistd.h
+.Ft int
+.Fn getpeereid "int s" "uid_t *euid" "gid_t *egid"
+.Sh DESCRIPTION
+The
+.Fn getpeereid
+function returns the effective user and group IDs of the
+peer connected to a
+.Ux Ns -domain
+socket.
+The argument
+.Fa s
+must be a
+.Ux Ns -domain
+socket
+.Pq Xr unix 4
+of type
+.Dv SOCK_STREAM
+on which either
+.Xr connect 2
+has been called, or one returned from
+.Xr accept 2
+after
+.Xr bind 2
+and
+.Xr listen 2
+have been called.
+The effective used ID is placed in
+.Fa euid ,
+and the effective group ID in
+.Fa egid .
+.Pp
+The credentials returned to the
+.Xr accept 2
+caller are those of its peer at the time it called
+.Xr connect 2 ;
+the credentials returned to the
+.Xr connect 2
+caller are those of its peer at the time it called
+.Xr bind 2 .
+This mechanism is reliable; there is no way for either side to influence
+the credentials returned to its peer except by calling the appropriate
+system call (i.e., either
+.Xr connect 2
+or
+.Xr bind 2 )
+under different effective credentials.
+.Pp
+One common use of this routine is for a
+.Ux Ns -domain
+server
+to verify the credentials of its client.
+Likewise, the client can verify the credentials of the server.
+.Sh IMPLEMENTATION NOTES
+On
+.Nx ,
+.Fn getpeereid
+is implemented in terms of the
+.Dv LOCAL_PEEREID
+.Xr unix 4
+socket option.
+.Sh RETURN VALUES
+.Rv -std getpeereid
+.Sh ERRORS
+The
+.Fn getpeereid
+function
+fails if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The argument
+.Fa s
+is not a valid descriptor.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is a file, not a socket.
+.It Bq Er ENOTCONN
+The argument
+.Fa s
+does not refer to a socket on which
+.Xr connect 2
+have been called nor one returned from
+.Xr listen 2 .
+.It Bq Er EINVAL
+The argument
+.Fa s
+does not refer to a socket of type
+.Dv SOCK_STREAM ,
+or the kernel returned invalid data.
+.El
+.Sh SEE ALSO
+.Xr connect 2 ,
+.Xr getpeername 2 ,
+.Xr getsockname 2 ,
+.Xr getsockopt 2 ,
+.Xr listen 2 ,
+.Xr unix 4
+.Sh HISTORY
+The
+.Fn getpeereid
+function appeared in
+.Fx 4.6 .

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Jason Thorpe
2007-08-06 16:10:04 UTC
Permalink
Post by Arne H. Juul
+int
+getpeereid(int s, uid_t *euid, gid_t *egid)
+{
+ struct unpcbid cred;
+ socklen_t len = sizeof(cred);
+ if (getsockopt(s, 0, LOCAL_PEEREID, &cred, &len) < 0) {
+ return -1;
+ } else {
+ *euid = cred.unp_euid;
+ *egid = cred.unp_egid;
My only comment ... fill these in conditional on them being non-NULL.

Otherwise, this looks great to me, and it would be nice to get this
into netbsd-4 as well.

Thanks for doing this!
Post by Arne H. Juul
+ return 0;
+ }
+}
-- thorpej


--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Jason Thorpe
2007-08-06 16:10:49 UTC
Permalink
Post by Arne H. Juul
+The
+.Fn getpeereid
+function appeared in
+.Fx 4.6 .
Oops, missed this the first time around ... ".Nx 4.0" ... assuming it
gets pulled into netbsd-4.

-- thorpej


--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Loading...