diff options
author | Bill Paul <wpaul@FreeBSD.org> | 1997-07-29 15:43:21 +0000 |
---|---|---|
committer | Bill Paul <wpaul@FreeBSD.org> | 1997-07-29 15:43:21 +0000 |
commit | 1f9224050ea95fee5abe885a632cdbb6038a438a (patch) | |
tree | f80e7d4b09aeb3a9bf8f767cd8869768240553f1 /usr.sbin | |
parent | 6ee8b26997adbf13785ab5146a6c1b146468d496 (diff) | |
download | src-1f9224050ea95fee5abe885a632cdbb6038a438a.tar.gz src-1f9224050ea95fee5abe885a632cdbb6038a438a.zip |
Modify rpc.yppasswdd to use the new AF_LOCAL transport in the RPC library
instead of its own kludged up version. This makes the special 'superuser-only'
update procedure work just like a real RPC service.
Notes
Notes:
svn path=/head/; revision=27758
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/rpc.yppasswdd/Makefile | 13 | ||||
-rw-r--r-- | usr.sbin/rpc.yppasswdd/yppasswd_comm.c | 303 | ||||
-rw-r--r-- | usr.sbin/rpc.yppasswdd/yppasswd_comm.h | 46 | ||||
-rw-r--r-- | usr.sbin/rpc.yppasswdd/yppasswd_private.x | 20 | ||||
-rw-r--r-- | usr.sbin/rpc.yppasswdd/yppasswdd_extern.h | 4 | ||||
-rw-r--r-- | usr.sbin/rpc.yppasswdd/yppasswdd_main.c | 76 | ||||
-rw-r--r-- | usr.sbin/rpc.yppasswdd/yppasswdd_server.c | 91 |
7 files changed, 104 insertions, 449 deletions
diff --git a/usr.sbin/rpc.yppasswdd/Makefile b/usr.sbin/rpc.yppasswdd/Makefile index f6090ab7be54..60cb1e9c19e2 100644 --- a/usr.sbin/rpc.yppasswdd/Makefile +++ b/usr.sbin/rpc.yppasswdd/Makefile @@ -1,11 +1,11 @@ -# $Id$ +# $Id: Makefile,v 1.2 1997/07/28 18:31:11 wpaul Exp $ PROG= rpc.yppasswdd SRCS= pw_copy.c pw_util.c util.c yppasswd_svc.c yp_error.c ypxfr_misc.c \ yp_dblookup.c yp_dbwrite.c yp_access.c yppasswd_private_xdr.c \ - yp_clnt.c yppasswdd_server.c yppasswd_comm.c yppasswdd_main.c + yppasswd_private_svc.c yp_clnt.c yppasswdd_server.c yppasswdd_main.c -RPCDIR= ${.CURDIR}/../../include/rpcsvc +RPCDIR= ${DESTDIR}/usr/include/rpcsvc .PATH: ${.CURDIR}/../../usr.sbin/ypserv ${.CURDIR}/../../usr.bin/chpass \ ${.CURDIR}/../../libexec/ypxfr ${RPCDIR} @@ -21,7 +21,7 @@ LDADD= -lrpcsvc -lcrypt CLEANFILES= yppasswd_svc.c yppasswd.h \ yppasswd_private_xdr.c yppasswd_private.h \ - yp.h yp_clnt.c + yppasswd_private_svc.c yp.h yp_clnt.c RPCGEN= rpcgen -I -C @@ -52,6 +52,11 @@ yppasswd_private_xdr.c: yppasswd_private.x yppasswd_private.h rm -f ${.TARGET} ${RPCGEN} -c -o ${.TARGET} ${.CURDIR}/yppasswd_private.x +yppasswd_private_svc.c: yppasswd_private.x yppasswd_private.h + rm -f ${.TARGET} + ${RPCGEN} -m ${.CURDIR}/yppasswd_private.x | \ + sed s/"static int _rpcsvcstate = _IDLE"/"extern int _rpcsvcstate"/g > ${.TARGET} + afterinstall: ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ ${.CURDIR}/yppwupdate \ diff --git a/usr.sbin/rpc.yppasswdd/yppasswd_comm.c b/usr.sbin/rpc.yppasswdd/yppasswd_comm.c deleted file mode 100644 index a5a5bf0ef85d..000000000000 --- a/usr.sbin/rpc.yppasswdd/yppasswd_comm.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) 1995, 1996 - * Bill Paul <wpaul@ctr.columbia.edu>. 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. - * - * $Id$ - */ - -/* - * This file contains a UNIX domain socket communications package - * that lets a client process send pseudo-RPCs to rpc.yppasswdd - * without using IP. This 'local-only' communications channel is - * only used when the superuser runs passwd(1) or chpass(1) on - * the NIS master server. The idea is that we want to grant the - * superuser permission to perfom certain special operations, but - * we need an iron-clad way to tell when we're receiving a request - * from the superuser and when we aren't. To connect to a UNIX - * domain socket, one needs to be able to access a file in the - * filesystem. The socket created by rpc.yppasswdd is owned by - * root and has all its permission bits cleared, so the only - * user who can sucessfully connect() to it is root. - * - * It is the server's responsibility to initialize the listening - * socket with the makeservsock() function and to add the socket to - * the set of file descriptors monitored by the svc_run() loop. - * Once this is done, calls made through the UNIX domain socket - * can be handled almost exactly like a normal RPC. We even use - * the XDR functions for serializing data between the client and - * server to simplify the passing of complex data structures. - */ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <err.h> -#include <errno.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/fcntl.h> -#include <rpc/rpc.h> -#include <rpcsvc/yp.h> -#include "yppasswd_comm.h" -#include "yppasswd_private.h" -#include "ypxfr_extern.h" - -#ifndef lint -static const char rcsid[] = "$Id$"; -#endif - -char *sockname = "/var/run/ypsock"; -FILE *serv_fp; -FILE *clnt_fp; -int serv_sock; -int clnt_sock; - -/* - * serialize_data() and serialize_resp() are what really do most of - * the work. These functions (ab)use xdrstdio_create() as the interface - * to the XDR library. The RPC library uses xdrrec_create() and friends - * for TCP based connections. I suppose we could use that here, but - * the interface is a bit too complicated to justify using in an - * applicatuion such as this. With xdrstdio_create(), the only catch - * is that we need to provide a buffered file stream rather than - * a simple socket descriptor, but we can easily turn the latter into - * the former using fdopen(2). - * - * Doing things this way buys us the ability to change the form of - * the data being exchanged without having to modify any of the - * routines in this package. - */ -static int serialize_data(data, fp, op) - struct master_yppasswd *data; - FILE *fp; - int op; -{ - XDR xdrs; - - xdrstdio_create(&xdrs, fp, op); - - if (!xdr_master_yppasswd(&xdrs, data)) { - xdr_destroy(&xdrs); - return(1); - } - return(0); -} - -static int serialize_resp(resp, fp, op) - int *resp; - FILE *fp; - int op; -{ - XDR xdrs; - - xdrstdio_create(&xdrs, fp, op); - - if (!xdr_int(&xdrs, resp)) { - xdr_destroy(&xdrs); - return(1); - } - return(0); -} - -/* - * Build the server's listening socket. The descriptor generated - * here will be monitored for new connections by the svc_run() loop. - */ -int makeservsock() -{ - static int ypsock; - struct sockaddr_un us; - int len; - - unlink(sockname); - - if ((ypsock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) - err(1, "failed to create UNIX domain socket"); - - bzero((char *)&us, sizeof(us)); - us.sun_family = AF_UNIX; - strcpy((char *)&us.sun_path, sockname); - us.sun_len = len = sizeof(us.sun_len) + sizeof(us.sun_family) + - strlen(us.sun_path) + 1; - - if (bind(ypsock, (struct sockaddr *)&us, len) == -1) - err(1,"failed to bind UNIX domain socket"); - - listen (ypsock, 1); - - return(ypsock); -} - -/* - * Create a socket for a client and try to connect() it to the - * server. - */ -static int makeclntsock() -{ - static int ypsock; - struct sockaddr_un us; - int len; - - if ((ypsock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - warn("failed to create UNIX domain socket"); - return(-1); - } - - bzero((char *)&us, sizeof(us)); - us.sun_family = AF_UNIX; - strcpy((char *)&us.sun_path, sockname); - us.sun_len = len = sizeof(us.sun_len) + sizeof(us.sun_family) + - strlen(us.sun_path) + 1; - - if (connect(ypsock, (struct sockaddr *)&us, len) == -1) { - warn("failed to connect to server"); - return(-1); - } - - return(ypsock); -} - -/* - * This function is used by the server to accept a new connection - * from a client and read its request data into a master_yppasswd - * stucture. - */ -struct master_yppasswd *getdat(sock) - int sock; -{ - int len; - struct sockaddr_un us; - static struct master_yppasswd pw; - struct timeval tv; - fd_set fds; - - FD_ZERO(&fds); - FD_SET(sock, &fds); - - tv.tv_sec = CONNECTION_TIMEOUT; - tv.tv_usec = 0; - - switch(select(FD_SETSIZE, &fds, NULL, NULL, &tv)) { - case 0: - yp_error("select timed out"); - return(NULL); - break; - case -1: - yp_error("select() failed: %s", strerror(errno)); - return(NULL); - break; - default: - break; - } - - len = sizeof(us); - if ((serv_sock = accept(sock, (struct sockaddr *)&us, &len)) == -1) { - yp_error("accept failed: %s", strerror(errno)); - return(NULL); - } - - if ((serv_fp = fdopen(serv_sock, "r+")) == NULL) { - yp_error("fdopen failed: %s",strerror(errno)); - return(NULL); - } - - if (serialize_data(&pw, serv_fp, XDR_DECODE)) { - yp_error("failed to receive data"); - return(NULL); - } - - return(&pw); -} - -/* - * Client uses this to read back a response code (a single - * integer) from the server. Note that we don't need to implement - * any special XDR function for this since an int is a base data - * type which the XDR library can handle directly. - */ -int *getresp() -{ - static int resp; - - if (serialize_resp(&resp, clnt_fp, XDR_DECODE)) { - warn("failed to receive response"); - return(NULL); - } - - fclose(clnt_fp); - close(clnt_sock); - return(&resp); -} - -/* - * Create a connection to the server and send a reqest - * to be processed. - */ -int senddat(pw) - struct master_yppasswd *pw; -{ - - if ((clnt_sock = makeclntsock()) == -1) { - warn("failed to create socket"); - return(1); - } - - if ((clnt_fp = fdopen(clnt_sock, "r+")) == NULL) { - warn("fdopen failed"); - return(1); - } - - if (serialize_data(pw, clnt_fp, XDR_ENCODE)) { - warn("failed to send data"); - return(1); - } - - return(0); -} - -/* - * This sends a response code back to the client. - */ -int sendresp(resp) - int resp; -{ - - if (serialize_resp(&resp, serv_fp, XDR_ENCODE)) { - yp_error("failed to send response"); - return(-1); - } - - fclose(serv_fp); - close(serv_sock); - return(0); -} diff --git a/usr.sbin/rpc.yppasswdd/yppasswd_comm.h b/usr.sbin/rpc.yppasswdd/yppasswd_comm.h deleted file mode 100644 index 91b13fb2f899..000000000000 --- a/usr.sbin/rpc.yppasswdd/yppasswd_comm.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 1995, 1996 - * Bill Paul <wpaul@ctr.columbia.edu>. 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. - * - * $Id$ - */ - -#include "yppasswd_private.h" - -#define CONNECTION_TIMEOUT 5 - -extern FILE *yp_fp; -extern char *sockname; -extern int yp_sock; -extern struct master_yppasswd *getdat __P(( int )); -extern int makeservsock __P(( void )); -extern int senddat __P(( struct master_yppasswd *pw )); -extern int *getresp __P(( void )); -extern int sendresp __P(( int )); diff --git a/usr.sbin/rpc.yppasswdd/yppasswd_private.x b/usr.sbin/rpc.yppasswdd/yppasswd_private.x index bd8599bc745f..7a101c03a9aa 100644 --- a/usr.sbin/rpc.yppasswdd/yppasswd_private.x +++ b/usr.sbin/rpc.yppasswdd/yppasswd_private.x @@ -29,20 +29,18 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: yppasswd_private.x,v 1.2 1997/07/28 18:31:11 wpaul Exp $ */ #ifndef RPC_HDR %#ifndef lint -%static const char rcsid[] = "$Id$"; +%static const char rcsid[] = "$Id: yppasswd_private.x,v 1.2 1997/07/28 18:31:11 wpaul Exp $"; %#endif /* not lint */ #endif -/* - * This protocol definition file is only used to - * generate some XDR functions. We don't actually - * define any RPC services here. - */ +#ifdef RPC_HDR +%#define YP_SOCKNAME "/var/run/yppasswdsock" +#endif struct x_master_passwd { string pw_name<>; /* username */ @@ -65,3 +63,11 @@ struct master_yppasswd { string domain<_YPMAXDOMAIN>; /* domain we want to operate on */ x_master_passwd newpw; /* new passwd entry */ }; + + +program MASTER_YPPASSWDPROG { + version MASTER_YPPASSWDVERS { + int + YPPASSWDPROC_UPDATE_MASTER(master_yppasswd) = 1; + } = 1; +} = 600100009; diff --git a/usr.sbin/rpc.yppasswdd/yppasswdd_extern.h b/usr.sbin/rpc.yppasswdd/yppasswdd_extern.h index 857248e267a6..76bacbce3bf8 100644 --- a/usr.sbin/rpc.yppasswdd/yppasswdd_extern.h +++ b/usr.sbin/rpc.yppasswdd/yppasswdd_extern.h @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: yppasswdd_extern.h,v 1.2 1997/07/28 18:31:11 wpaul Exp $ */ #include <sys/types.h> @@ -58,6 +58,8 @@ extern char *yp_dir; extern char *progname; extern void do_master __P(( void )); extern void yppasswdprog_1 __P(( struct svc_req *, register SVCXPRT * )); +extern void master_yppasswdprog_1 __P(( struct svc_req *, + register SVCXPRT * )); extern void reaper __P(( int )); extern void install_reaper __P(( int )); extern int pw_copy __P(( int, int, struct passwd * )); diff --git a/usr.sbin/rpc.yppasswdd/yppasswdd_main.c b/usr.sbin/rpc.yppasswdd/yppasswdd_main.c index 8034e154a66b..d785d6536ac0 100644 --- a/usr.sbin/rpc.yppasswdd/yppasswdd_main.c +++ b/usr.sbin/rpc.yppasswdd/yppasswdd_main.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: yppasswdd_main.c,v 1.9 1997/02/22 16:12:56 peter Exp $ + * $Id: yppasswdd_main.c,v 1.2 1997/07/28 18:31:11 wpaul Exp $ */ #include "yppasswd.h" @@ -59,7 +59,7 @@ struct dom_binding {}; #include <rpcsvc/ypclnt.h> #include "yppasswdd_extern.h" -#include "yppasswd_comm.h" +#include "yppasswd_private.h" #include "ypxfr_extern.h" #ifndef SIG_PF @@ -72,7 +72,7 @@ struct dom_binding {}; #define _RPCSVC_CLOSEDOWN 120 #ifndef lint -static const char rcsid[] = "$Id: yppasswdd_main.c,v 1.9 1997/02/22 16:12:56 peter Exp $"; +static const char rcsid[] = "$Id: yppasswdd_main.c,v 1.2 1997/07/28 18:31:11 wpaul Exp $"; #endif /* not lint */ int _rpcpmstart = 0; /* Started by a port monitor ? */ static int _rpcfdtype; @@ -96,54 +96,13 @@ int multidomain = 0; int verbose = 0; int resvport = 1; int inplace = 0; -int yp_sock; - - -static void -my_svc_run() -{ -#ifdef FD_SETSIZE - fd_set readfds; -#else - int readfds; -#endif /* def FD_SETSIZE */ - extern int errno; - - for (;;) { - - -#ifdef FD_SETSIZE - readfds = svc_fdset; -#else - readfds = svc_fds; -#endif /* def FD_SETSIZE */ - FD_SET(yp_sock, &readfds); - - switch (select(_rpc_dtablesize(), &readfds, (fd_set *)0, (fd_set *)0, - (struct timeval *)0)) { - case -1: - if (errno == EINTR) { - continue; - } - perror("svc_run: - select failed"); - return; - case 0: - continue; - default: - if (FD_ISSET(yp_sock, &readfds)) { - do_master(); - FD_CLR(yp_sock, &readfds); - } - svc_getreqset(&readfds); - } - } -} +char *sockname = YP_SOCKNAME; static void terminate(sig) int sig; { svc_unregister(YPPASSWDPROG, YPPASSWDVERS); - close(yp_sock); + svc_unregister(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS); unlink(sockname); exit(0); } @@ -163,7 +122,6 @@ closedown(int sig) int i, openfd; if (_rpcfdtype == SOCK_DGRAM) { - close(yp_sock); unlink(sockname); exit(0); } @@ -174,7 +132,6 @@ closedown(int sig) if (FD_ISSET(i, &svc_fdset)) openfd++; if (openfd <= 1) { - close(yp_sock); unlink(sockname); exit(0); } @@ -310,6 +267,8 @@ the %s domain -- aborting", yppasswd_domain); openlog(progname, LOG_PID, LOG_DAEMON); sock = RPC_ANYSOCK; (void) pmap_unset(YPPASSWDPROG, YPPASSWDVERS); + (void) pmap_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS); + unlink(sockname); } if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { @@ -340,6 +299,20 @@ the %s domain -- aborting", yppasswd_domain); } } + unlink(sockname); + transp = svcunix_create(sock, 0, 0, sockname); + if (transp == NULL) { + yp_error("cannot create AF_LOCAL service."); + exit(1); + } + if (!svc_register(transp, MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, master_yppasswdprog_1, 0)) { + yp_error("unable to register (MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, unix)."); + exit(1); + } + /* Only root may connect() to the AF_UNIX link. */ + if (chmod(sockname, 0)) + err(1, "chmod of %s failed", sockname); + if (transp == (SVCXPRT *)NULL) { yp_error("could not create a handle"); exit(1); @@ -357,12 +330,7 @@ the %s domain -- aborting", yppasswd_domain); signal(SIGHUP, (SIG_PF) reload); - unlink(sockname); - yp_sock = makeservsock(); - if (chmod(sockname, 0)) - err(1, "chmod of %s failed", sockname); - - my_svc_run(); + svc_run(); yp_error("svc_run returned"); exit(1); /* NOTREACHED */ diff --git a/usr.sbin/rpc.yppasswdd/yppasswdd_server.c b/usr.sbin/rpc.yppasswdd/yppasswdd_server.c index 398b07813ec1..02a4746112da 100644 --- a/usr.sbin/rpc.yppasswdd/yppasswdd_server.c +++ b/usr.sbin/rpc.yppasswdd/yppasswdd_server.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: yppasswdd_server.c,v 1.3 1997/07/29 00:21:00 wpaul Exp $ */ #include <stdio.h> @@ -58,10 +58,9 @@ struct dom_binding {}; #include "yppasswdd_extern.h" #include "yppasswd.h" #include "yppasswd_private.h" -#include "yppasswd_comm.h" #ifndef lint -static const char rcsid[] = "$Id$"; +static const char rcsid[] = "$Id: yppasswdd_server.c,v 1.3 1997/07/29 00:21:00 wpaul Exp $"; #endif /* not lint */ char *tempname; @@ -686,22 +685,67 @@ cleaning up and bailing out"); return (&result); } +struct cmessage { + struct cmsghdr cmsg; + struct cmsgcred cmcred; +}; + /* * Note that this function performs a little less sanity checking * than the last one. Since only the superuser is allowed to use it, * it is assumed that the caller knows what he's doing. */ -static int update_master(master_yppasswd *argp) +int *yppasswdproc_update_master_1_svc(master_yppasswd *argp, + struct svc_req *rqstp) { - int result; + static int result; int pfd, tfd; int pid; int rval = 0; DBT key, data; char *passfile_hold; char passfile_buf[MAXPATHLEN + 2]; + struct sockaddr_in *rqhost; + struct cmessage *cm; + SVCXPRT *transp; result = 1; + + /* + * NO AF_INET CONNETCIONS ALLOWED! + */ + rqhost = svc_getcaller(rqstp->rq_xprt); + if (rqhost->sin_family != AF_UNIX) { + yp_error("Alert! %s/%d attempted to use superuser-only \ +procedure!\n", inet_ntoa(rqhost->sin_addr), rqhost->sin_port); + svcerr_auth(rqstp->rq_xprt, AUTH_BADCRED); + return(&result); + } + + transp = rqstp->rq_xprt; + + if (transp->xp_verf.oa_length < sizeof(struct cmessage) || + transp->xp_verf.oa_base == NULL || + transp->xp_verf.oa_flavor != AUTH_UNIX) { + yp_error("caller didn't send proper credentials"); + svcerr_auth(rqstp->rq_xprt, AUTH_BADCRED); + return(&result); + } + + cm = (struct cmessage *)transp->xp_verf.oa_base; + if (cm->cmsg.cmsg_type != SCM_CREDS) { + yp_error("caller didn't send proper credentials"); + svcerr_auth(rqstp->rq_xprt, AUTH_BADCRED); + return(&result); + } + + if (cm->cmcred.cmcred_euid) { + yp_error("caller euid is %d, expecting 0 -- rejecting request", + cm->cmcred.cmcred_euid); + svcerr_auth(rqstp->rq_xprt, AUTH_BADCRED); + return(&result); + } + passfile = passfile_default; key.data = argp->newpw.pw_name; @@ -728,7 +772,7 @@ allow additions to be made to the password database", progname); yperr_string(rval)); } if (!allow_additions) - return(result); + return(&result); } else { /* Nul terminate, please. */ @@ -743,7 +787,7 @@ allow additions to be made to the password database", progname); if (validate_master(rval == YP_TRUE ? &yp_password:NULL,&argp->newpw)){ yp_error("rejecting update attempt for %s: bad arguments", argp->newpw.pw_name); - return(result); + return(&result); } /* @@ -758,17 +802,17 @@ allow additions to be made to the password database", progname); } if ((pfd = pw_lock()) < 0) { - return (result); + return (&result); } if ((tfd = pw_tmp()) < 0) { - return (result); + return (&result); } if (pw_copy(pfd, tfd, (struct passwd *)&argp->newpw)) { yp_error("failed to created updated password file -- \ cleaning up and bailing out"); unlink(tempname); - return(result); + return(&result); } passfile_hold = yp_mktmpnam(); @@ -778,7 +822,7 @@ cleaning up and bailing out"); } else { if (pw_mkdb(argp->newpw.pw_name) < 0) { yp_error("pwd_mkdb failed"); - return(result); + return(&result); } } @@ -791,7 +835,6 @@ cleaning up and bailing out"); switch((pid = fork())) { case 0: - close(yp_sock); if (inplace && !rval) { execlp(MAP_UPDATE_PATH, MAP_UPDATE, passfile, argp->domain, "pushpw", NULL); @@ -809,7 +852,7 @@ cleaning up and bailing out"); yp_error("fork() failed: %s", strerror(errno)); unlink(passfile); rename(passfile_hold, passfile); - return(result); + return(&result); break; default: unlink(passfile_hold); @@ -822,25 +865,5 @@ cleaning up and bailing out"); argp->domain); result = 0; - return(result); -} - -/* - * Pseudo-dispatcher for private 'superuser-only' update handler. - */ -void do_master() -{ - struct master_yppasswd *pw; - - if ((pw = getdat(yp_sock)) == NULL) { - return; - } - - yp_error("received update request from superuser on localhost"); - sendresp(update_master(pw)); - - /* Remember to free args. */ - xdr_free(xdr_master_yppasswd, (char *)pw); - - return; + return(&result); } |