diff options
author | wpaul <wpaul@FreeBSD.org> | 1997-03-21 16:12:32 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 1997-03-21 16:12:32 +0000 |
commit | cdd7ea42624c882c277e717173e0d9f2d4edfbd1 (patch) | |
tree | 4c9acd2b85ec891acf70c2c3de953ed480bd654e /sys | |
parent | 61cded15d6400a98014df014cb90523b2a94edd4 (diff) | |
download | FreeBSD-src-cdd7ea42624c882c277e717173e0d9f2d4edfbd1.zip FreeBSD-src-cdd7ea42624c882c277e717173e0d9f2d4edfbd1.tar.gz |
Add support to sendmsg()/recvmsg() for passing credentials between
processes using AF_LOCAL sockets. This hack is going to be used with
Secure RPC to duplicate a feature of STREAMS which has no real counterpart
in sockets (with STREAMS/TLI, you can apparently use t_getinfo() to learn
UID of a local process on the other side of a transport endpoint).
What happens is this: the client sets up a sendmsg() call with ancillary
data using the SCM_CREDS socket-level control message type. It does not
need to fill in the structure. When the kernel notices the data,
unp_internalize() fills in the cmesgcred structure with the sending
process' credentials (UID, EUID, GID, and ancillary groups). This data
is later delivered to the receiving process. The receiver can then
perform the follwing tests:
- Did the client send ancillary data?
o Yes, proceed.
o No, refuse to authenticate the client.
- The the client send data of type SCM_CREDS?
o Yes, proceed.
o No, refuse to authenticate the client.
- Is the cmsgcred structure the right size?
o Yes, proceed.
o No, signal a possible error.
The receiver can now inspect the credential information and use it to
authenticate the client.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/uipc_usrreq.c | 28 | ||||
-rw-r--r-- | sys/sys/socket.h | 26 |
2 files changed, 50 insertions, 4 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 3b668a2..3c68f05 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94 - * $Id: uipc_usrreq.c,v 1.19 1997/02/22 09:39:29 peter Exp $ + * $Id: uipc_usrreq.c,v 1.20 1997/02/24 20:30:58 wollman Exp $ */ #include <sys/param.h> @@ -697,6 +697,10 @@ unp_externalize(rights) return (0); } +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + static int unp_internalize(control, p) struct mbuf *control; @@ -707,11 +711,29 @@ unp_internalize(control, p) register struct file **rp; register struct file *fp; register int i, fd; + register struct cmsgcred *cmcred; int oldfds; - if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET || - cm->cmsg_len != control->m_len) + if ((cm->cmsg_type != SCM_RIGHTS && cm->cmsg_type != SCM_CREDS) || + cm->cmsg_level != SOL_SOCKET || cm->cmsg_len != control->m_len) return (EINVAL); + + /* + * Fill in credential information. + */ + if (cm->cmsg_type == SCM_CREDS) { + cmcred = (struct cmsgcred *)(cm + 1); + cmcred->cmcred_pid = p->p_pid; + cmcred->cmcred_uid = p->p_cred->p_ruid; + cmcred->cmcred_gid = p->p_cred->p_rgid; + cmcred->cmcred_euid = p->p_ucred->cr_uid; + cmcred->cmcred_ngroups = MIN(p->p_ucred->cr_ngroups, + CMGROUP_MAX); + for (i = 0; i < cmcred->cmcred_ngroups; i++) + cmcred->cmcred_groups[i] = p->p_ucred->cr_groups[i]; + return(0); + } + oldfds = (cm->cmsg_len - sizeof (*cm)) / sizeof (int); /* * check that all the FDs passed in refer to legal OPEN files diff --git a/sys/sys/socket.h b/sys/sys/socket.h index 7e0f6c7..c770a67 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)socket.h 8.4 (Berkeley) 2/21/94 - * $Id$ + * $Id: socket.h,v 1.17 1997/02/22 09:45:55 peter Exp $ */ #ifndef _SYS_SOCKET_H_ @@ -289,6 +289,29 @@ struct cmsghdr { /* followed by u_char cmsg_data[]; */ }; +/* + * While we may have more groups than this, the cmsgcred struct must + * be able to fit in an mbuf, and NGROUPS_MAX is too large to allow + * this. +*/ +#define CMGROUP_MAX 16 + +/* + * Credentials structure, used to verify the identity of a peer + * process that has sent us a message. This is allocated by the + * peer process but filled in by the kernel. This prevents the + * peer from lying about its identity. (Note that cmcred_groups[0] + * is the effective GID.) + */ +struct cmsgcred { + pid_t cmcred_pid; /* PID of sending process */ + uid_t cmcred_uid; /* real UID of sending process */ + uid_t cmcred_euid; /* effective UID of sending process */ + gid_t cmcred_gid; /* real GID of sending process */ + short cmcred_ngroups; /* number or groups */ + gid_t cmcred_groups[CMGROUP_MAX]; /* groups */ +}; + /* given pointer to struct cmsghdr, return pointer to data */ #define CMSG_DATA(cmsg) ((u_char *)((cmsg) + 1)) @@ -304,6 +327,7 @@ struct cmsghdr { /* "Socket"-level control message types: */ #define SCM_RIGHTS 0x01 /* access rights (array of int) */ #define SCM_TIMESTAMP 0x02 /* timestamp (struct timeval) */ +#define SCM_CREDS 0x03 /* process creds (struct cmsgcred) */ /* * 4.3 compat sockaddr, move to compat file later |