From 4ed6d63483283e86585a89ad889766e30c8cd865 Mon Sep 17 00:00:00 2001 From: Alfred Perlstein Date: Thu, 22 Mar 2001 04:31:30 +0000 Subject: [PATCH] Hopefully fix some of the bugs in passing credentials over UNIX domain sockets. Make struct cmessage visible from socket.h (about 4 places were defining it for themselves which wasn't good) Make __rpc_get_local_uid() useable and give it prototype that's visible. Fix some issues with printing out usernames from rpcbind and keyserv. --- lib/libc/rpc/clnt_vc.c | 9 +--- lib/libc/rpc/svc_vc.c | 49 ++++++++++++--------- sys/sys/socket.h | 5 +++ usr.sbin/keyserv/Makefile | 2 +- usr.sbin/keyserv/keyserv.c | 2 +- usr.sbin/keyserv/keyserv.h | 5 ++- usr.sbin/keyserv/keyserv_uid.c | 76 --------------------------------- usr.sbin/rpcbind/pmap_svc.c | 9 ++-- usr.sbin/rpcbind/rpcb_svc_com.c | 13 +++--- 9 files changed, 52 insertions(+), 118 deletions(-) delete mode 100644 usr.sbin/keyserv/keyserv_uid.c diff --git a/lib/libc/rpc/clnt_vc.c b/lib/libc/rpc/clnt_vc.c index bce8fbe31ae1..433291c82ff7 100644 --- a/lib/libc/rpc/clnt_vc.c +++ b/lib/libc/rpc/clnt_vc.c @@ -110,12 +110,6 @@ struct ct_data { XDR ct_xdrs; /* XDR stream */ }; -struct cmessage { - struct cmsghdr cmsg; - struct cmsgcred cmcred; -}; - - /* * This machinery implements per-fd locks for MT-safety. It is not * sufficient to do per-CLIENT handle locks for MT-safety because a @@ -785,6 +779,7 @@ time_not_ok(t) t->tv_usec <= -1 || t->tv_usec > 1000000); } +static int __msgread(sock, buf, cnt) int sock; void *buf; @@ -808,7 +803,7 @@ __msgread(sock, buf, cnt) return(_recvmsg(sock, &msg, 0)); } - + static int __msgwrite(sock, buf, cnt) int sock; diff --git a/lib/libc/rpc/svc_vc.c b/lib/libc/rpc/svc_vc.c index 1006988e769c..0e84d6fdb4c5 100644 --- a/lib/libc/rpc/svc_vc.c +++ b/lib/libc/rpc/svc_vc.c @@ -85,8 +85,8 @@ static bool_t svc_vc_reply __P((SVCXPRT *, struct rpc_msg *)); static void svc_vc_rendezvous_ops __P((SVCXPRT *)); static void svc_vc_ops __P((SVCXPRT *)); static bool_t svc_vc_control __P((SVCXPRT *xprt, const u_int rq, void *in)); +static int __msgread_withcred(int, void *, size_t, struct cmessage *); static int __msgwrite(int, void *, size_t); -static int __msgread(int, void *, size_t); struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */ u_int sendsize; @@ -100,12 +100,6 @@ struct cf_conn { /* kept in xprt->xp_p1 for actual connection */ char verf_body[MAX_AUTH_BYTES]; }; -struct cmessage { - struct cmsghdr cmsg; - struct cmsgcred cmcred; -}; - - /* * Usage: * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size); @@ -421,17 +415,18 @@ read_vc(xprtp, buf, len) if (errno == EINTR) continue; /*FALLTHROUGH*/ - case 0: - goto fatal_err; - default: - break; + case 0: + goto fatal_err; + + default: + break; } } while ((pollfd.revents & POLLIN) == 0); sa = (struct sockaddr *)xprt->xp_rtaddr.buf; if (sa->sa_family == AF_LOCAL) { - if ((len = __msgread(sock, buf, len)) > 0) { - cm = (struct cmessage *)xprt->xp_verf.oa_base; + cm = (struct cmessage *)xprt->xp_verf.oa_base; + if ((len = __msgread_withcred(sock, buf, len, cm)) > 0) { cmp = &cm->cmsg; sc = (struct sockcred *)(void *)CMSG_DATA(cmp); xprt->xp_p2 = sc; @@ -632,17 +627,17 @@ svc_vc_rendezvous_ops(xprt) mutex_unlock(&ops_lock); } -static int -__msgread(sock, buf, cnt) +int +__msgread_withcred(sock, buf, cnt, cmp) int sock; void *buf; size_t cnt; + struct cmessage *cmp; { struct iovec iov[1]; struct msghdr msg; - struct cmessage cm; - bzero((char *)&cm, sizeof(cm)); + bzero(cmp, sizeof(*cmp)); iov[0].iov_base = buf; iov[0].iov_len = cnt; @@ -650,13 +645,13 @@ __msgread(sock, buf, cnt) msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; - msg.msg_control = (caddr_t)&cm; + msg.msg_control = cmp; msg.msg_controllen = sizeof(struct cmessage); msg.msg_flags = 0; return(_recvmsg(sock, &msg, 0)); } - + static int __msgwrite(sock, buf, cnt) int sock; @@ -685,3 +680,19 @@ __msgwrite(sock, buf, cnt) return(_sendmsg(sock, &msg, 0)); } + +/* + * Get the effective UID of the sending process. Used by rpcbind and keyserv + * (AF_LOCAL). + */ +int +__rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) +{ + struct cmsgcred *cmcred; + + cmcred = __svc_getcallercreds(transp); + if (cmcred == NULL) + return(-1); + *uid = cmcred->cmcred_euid; + return(0); +} diff --git a/sys/sys/socket.h b/sys/sys/socket.h index cf0ee9cf45bf..d7d264509e37 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -364,6 +364,11 @@ struct cmsgcred { gid_t cmcred_groups[CMGROUP_MAX]; /* groups */ }; +struct cmessage { + struct cmsghdr cmsg; + struct cmsgcred cmcred; +}; + /* given pointer to struct cmsghdr, return pointer to data */ #define CMSG_DATA(cmsg) ((u_char *)(cmsg) + \ _ALIGN(sizeof(struct cmsghdr))) diff --git a/usr.sbin/keyserv/Makefile b/usr.sbin/keyserv/Makefile index ea8d9f48a895..169a9d5fbf04 100644 --- a/usr.sbin/keyserv/Makefile +++ b/usr.sbin/keyserv/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= keyserv -SRCS= keyserv.c setkey.c keyserv_uid.c crypt_svc.c crypt_server.c crypt.h +SRCS= keyserv.c setkey.c crypt_svc.c crypt_server.c crypt.h CFLAGS+= -DKEYSERV_RANDOM -DBROKEN_DES -I. .if $(OBJFORMAT) == elf diff --git a/usr.sbin/keyserv/keyserv.c b/usr.sbin/keyserv/keyserv.c index 9a156d51f1be..6486c0ff5492 100644 --- a/usr.sbin/keyserv/keyserv.c +++ b/usr.sbin/keyserv/keyserv.c @@ -741,7 +741,7 @@ root_auth(trans, rqstp) return (0); } - if (__rpc_get_local_uid(&uid, trans) < 0) { + if (__rpc_get_local_uid(trans, &uid) < 0) { if (debugging) fprintf(stderr, "__rpc_get_local_uid failed\n"); return (0); diff --git a/usr.sbin/keyserv/keyserv.h b/usr.sbin/keyserv/keyserv.h index 6e2402ddda79..0cc6a36fabef 100644 --- a/usr.sbin/keyserv/keyserv.h +++ b/usr.sbin/keyserv/keyserv.h @@ -1,4 +1,6 @@ - +/* + * $FreeBSD$ + */ extern void setmodulus __P((char *modx)); extern keystatus pk_setkey __P(( uid_t, keybuf ));; @@ -9,7 +11,6 @@ extern keystatus pk_netget __P(( uid_t, key_netstarg * )); extern keystatus pk_get_conv_key __P(( uid_t, keybuf, cryptkeyres * )); extern void pk_nodefaultkeys __P(( void )); -extern int __rpc_get_local_uid __P(( uid_t * , SVCXPRT * )); extern void crypt_prog_1 __P(( struct svc_req *, register SVCXPRT * )); extern void load_des __P(( int, char * )); diff --git a/usr.sbin/keyserv/keyserv_uid.c b/usr.sbin/keyserv/keyserv_uid.c deleted file mode 100644 index 8a46fd12bbff..000000000000 --- a/usr.sbin/keyserv/keyserv_uid.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 1996 - * Bill Paul . 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "keyserv.h" - -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif - -/* - * XXX should be declared somewhere - */ -struct cmessage { - struct cmsghdr cmsg; - struct cmsgcred cmcred; -}; - -int -__rpc_get_local_uid(uid, transp) - uid_t *uid; - SVCXPRT *transp; -{ - struct cmessage *cm; - - if (transp->xp_verf.oa_length < sizeof(struct cmessage) || - transp->xp_verf.oa_base == NULL || - transp->xp_verf.oa_flavor != AUTH_UNIX) - return(-1); - - cm = (struct cmessage *)transp->xp_verf.oa_base; - if (cm->cmsg.cmsg_type != SCM_CREDS) - return(-1); - - *uid = cm->cmcred.cmcred_euid; - return(0); -} diff --git a/usr.sbin/rpcbind/pmap_svc.c b/usr.sbin/rpcbind/pmap_svc.c index b2cedd991aad..26467d19fe1b 100644 --- a/usr.sbin/rpcbind/pmap_svc.c +++ b/usr.sbin/rpcbind/pmap_svc.c @@ -173,7 +173,7 @@ pmapproc_change(struct svc_req *rqstp, SVCXPRT *xprt, unsigned long op) RPCB rpcbreg; long ans; struct sockaddr_in *who; - struct cmsgcred *cmcred; + uid_t uid; char uidbuf[32]; #ifdef RPCBIND_DEBUG @@ -194,19 +194,18 @@ pmapproc_change(struct svc_req *rqstp, SVCXPRT *xprt, unsigned long op) } who = svc_getcaller(xprt); - cmcred = __svc_getcallercreds(xprt); /* * Can't use getpwnam here. We might end up calling ourselves * and looping. */ - if (cmcred == NULL) + if (__rpc_get_local_uid(xprt, &uid) < 0) rpcbreg.r_owner = "unknown"; - else if (cmcred->cmcred_uid == 0) + else if (uid == 0) rpcbreg.r_owner = "superuser"; else { /* r_owner will be strdup-ed later */ - snprintf(uidbuf, sizeof uidbuf, "%d", cmcred->cmcred_uid); + snprintf(uidbuf, sizeof uidbuf, "%d", uid); rpcbreg.r_owner = uidbuf; } diff --git a/usr.sbin/rpcbind/rpcb_svc_com.c b/usr.sbin/rpcbind/rpcb_svc_com.c index e0c74876afdd..55264c09daa2 100644 --- a/usr.sbin/rpcbind/rpcb_svc_com.c +++ b/usr.sbin/rpcbind/rpcb_svc_com.c @@ -1348,15 +1348,14 @@ find_service(rpcprog_t prog, rpcvers_t vers, char *netid) static char * getowner(SVCXPRT *transp, char *owner, size_t ownersize) { - struct cmsgcred *cmcred; - - cmcred = __svc_getcallercreds(transp); - if (cmcred == NULL) - strlcpy(owner, "unknown", ownersize); - else if (cmcred->cmcred_uid == 0) + uid_t uid; + + if (__rpc_get_local_uid(transp, &uid) < 0) + strlcpy(owner, "unknown", ownersize); + else if (uid == 0) strlcpy(owner, "superuser", ownersize); else - snprintf(owner, ownersize, "%d", cmcred->cmcred_uid); + snprintf(owner, ownersize, "%d", uid); return owner; }