From cdd7ea42624c882c277e717173e0d9f2d4edfbd1 Mon Sep 17 00:00:00 2001 From: wpaul Date: Fri, 21 Mar 1997 16:12:32 +0000 Subject: 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. --- sys/kern/uipc_usrreq.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'sys/kern') 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 @@ -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 -- cgit v1.1