diff options
Diffstat (limited to 'usr.sbin/rpc.ypupdated')
-rw-r--r-- | usr.sbin/rpc.ypupdated/Makefile | 33 | ||||
-rw-r--r-- | usr.sbin/rpc.ypupdated/Makefile.depend | 29 | ||||
-rw-r--r-- | usr.sbin/rpc.ypupdated/update.c | 329 | ||||
-rw-r--r-- | usr.sbin/rpc.ypupdated/yp_dbdelete.c | 68 | ||||
-rw-r--r-- | usr.sbin/rpc.ypupdated/yp_dbupdate.c | 147 | ||||
-rwxr-xr-x | usr.sbin/rpc.ypupdated/ypupdate | 33 | ||||
-rw-r--r-- | usr.sbin/rpc.ypupdated/ypupdated_extern.h | 33 | ||||
-rw-r--r-- | usr.sbin/rpc.ypupdated/ypupdated_main.c | 285 | ||||
-rw-r--r-- | usr.sbin/rpc.ypupdated/ypupdated_server.c | 227 |
9 files changed, 1184 insertions, 0 deletions
diff --git a/usr.sbin/rpc.ypupdated/Makefile b/usr.sbin/rpc.ypupdated/Makefile new file mode 100644 index 0000000..d5c346e --- /dev/null +++ b/usr.sbin/rpc.ypupdated/Makefile @@ -0,0 +1,33 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../ypserv ${.CURDIR}/../../libexec/ypxfr + +PROG= rpc.ypupdated +MAN= +SRCS= ypupdate_prot_svc.c ypupdate_prot.h ypupdated_main.c \ + yp_error.c update.c ypupdated_server.c \ + yp_dblookup.c yp_dbwrite.c yp_dbdelete.c yp_dbupdate.c + +#CFLAGS+= -DYP +CFLAGS+= -I${.CURDIR}/../ypserv -I. -I${.CURDIR}/../../libexec/ypxfr + +WARNS?= 1 + +LIBADD= rpcsvc + +CLEANFILES= ypupdate_prot_svc.c ypupdate_prot.h + +RPCDIR= ${DESTDIR}/usr/include/rpcsvc +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -I -C + +# We need to remove the 'static' keyword from _rpcsvcstate so that +# ypupdated_main.c can see it. +ypupdate_prot_svc.c: ${RPCDIR}/ypupdate_prot.x + rm -f ${.TARGET} + ${RPCGEN} -m ${RPCDIR}/ypupdate_prot.x | \ + sed s/"static int _rpcsvcstate"/"int _rpcsvcstate"/g > ${.TARGET} + +ypupdate_prot.h: ${RPCDIR}/ypupdate_prot.x + ${RPCGEN} -h -o ${.TARGET} ${RPCDIR}/ypupdate_prot.x + +.include <bsd.prog.mk> diff --git a/usr.sbin/rpc.ypupdated/Makefile.depend b/usr.sbin/rpc.ypupdated/Makefile.depend new file mode 100644 index 0000000..11b2940 --- /dev/null +++ b/usr.sbin/rpc.ypupdated/Makefile.depend @@ -0,0 +1,29 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + gnu/lib/csu \ + gnu/lib/libgcc \ + include \ + include/rpc \ + include/rpcsvc \ + include/xlocale \ + lib/${CSU_DIR} \ + lib/libc \ + lib/libcompiler_rt \ + lib/librpcsvc \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +ypupdate_prot_svc.o: ypupdate_prot.h +ypupdate_prot_svc.o: ypupdate_prot_svc.c +ypupdate_prot_svc.po: ypupdate_prot.h +ypupdate_prot_svc.po: ypupdate_prot_svc.c +ypupdated_main.o: ypupdate_prot.h +ypupdated_main.po: ypupdate_prot.h +ypupdated_server.o: ypupdate_prot.h +ypupdated_server.po: ypupdate_prot.h +.endif diff --git a/usr.sbin/rpc.ypupdated/update.c b/usr.sbin/rpc.ypupdated/update.c new file mode 100644 index 0000000..956b057 --- /dev/null +++ b/usr.sbin/rpc.ypupdated/update.c @@ -0,0 +1,329 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)update.c 1.2 91/03/11 Copyr 1986 Sun Micro"; +#endif +static const char rcsid[] = + "$FreeBSD$"; +#endif /* not lint */ + +/* + * Copyright (C) 1986, 1989, Sun Microsystems, Inc. + */ + +/* + * Administrative tool to add a new user to the publickey database + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <rpc/rpc.h> +#include <rpc/key_prot.h> +#ifdef YP +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> +#include <sys/wait.h> +#include <netdb.h> +#endif /* YP */ +#include <pwd.h> +#include <string.h> +#include <sys/resource.h> +#include "ypupdated_extern.h" + +#ifdef YP +#define MAXMAPNAMELEN 256 +#else +#define YPOP_CHANGE 1 /* change, do not add */ +#define YPOP_INSERT 2 /* add, do not change */ +#define YPOP_DELETE 3 /* delete this entry */ +#define YPOP_STORE 4 /* add, or change */ +#endif + +#ifdef YP +static char SHELL[] = "/bin/sh"; +static char YPDBPATH[]="/var/yp"; /* This is defined but not used! */ +static char PKMAP[] = "publickey.byname"; +static char UPDATEFILE[] = "updaters"; +static char PKFILE[] = "/etc/publickey"; +#endif /* YP */ + +#ifdef YP +static int _openchild(char *, FILE **, FILE **); + +/* + * Determine if requester is allowed to update the given map, + * and update it if so. Returns the yp status, which is zero + * if there is no access violation. + */ +int +mapupdate(char *requester, char *mapname, u_int op, u_int keylen, char *key, + u_int datalen, char *data) +{ + char updater[MAXMAPNAMELEN + 40]; + FILE *childargs; + FILE *childrslt; +#ifdef WEXITSTATUS + int status; +#else + union wait status; +#endif + pid_t pid; + u_int yperrno; + + +#ifdef DEBUG + printf("%s %s\n", key, data); +#endif + (void)sprintf(updater, "make -s -f %s/%s %s", YPDBPATH, /* !!! */ + UPDATEFILE, mapname); + pid = _openchild(updater, &childargs, &childrslt); + if (pid < 0) { + return (YPERR_YPERR); + } + + /* + * Write to child + */ + (void)fprintf(childargs, "%s\n", requester); + (void)fprintf(childargs, "%u\n", op); + (void)fprintf(childargs, "%u\n", keylen); + (void)fwrite(key, (int)keylen, 1, childargs); + (void)fprintf(childargs, "\n"); + (void)fprintf(childargs, "%u\n", datalen); + (void)fwrite(data, (int)datalen, 1, childargs); + (void)fprintf(childargs, "\n"); + (void)fclose(childargs); + + /* + * Read from child + */ + (void)fscanf(childrslt, "%d", &yperrno); + (void)fclose(childrslt); + + (void)wait(&status); +#ifdef WEXITSTATUS + if (WEXITSTATUS(status) != 0) +#else + if (status.w_retcode != 0) +#endif + return (YPERR_YPERR); + return (yperrno); +} + +/* + * returns pid, or -1 for failure + */ +static int +_openchild(char *command, FILE **fto, FILE **ffrom) +{ + int i; + pid_t pid; + int pdto[2]; + int pdfrom[2]; + char *com; + struct rlimit rl; + + if (pipe(pdto) < 0) { + goto error1; + } + if (pipe(pdfrom) < 0) { + goto error2; + } + switch (pid = fork()) { + case -1: + goto error3; + + case 0: + /* + * child: read from pdto[0], write into pdfrom[1] + */ + (void)close(0); + (void)dup(pdto[0]); + (void)close(1); + (void)dup(pdfrom[1]); + getrlimit(RLIMIT_NOFILE, &rl); + for (i = rl.rlim_max - 1; i >= 3; i--) { + (void) close(i); + } + com = malloc((unsigned) strlen(command) + 6); + if (com == NULL) { + _exit(~0); + } + (void)sprintf(com, "exec %s", command); + execl(SHELL, basename(SHELL), "-c", com, (char *)NULL); + _exit(~0); + + default: + /* + * parent: write into pdto[1], read from pdfrom[0] + */ + *fto = fdopen(pdto[1], "w"); + (void)close(pdto[0]); + *ffrom = fdopen(pdfrom[0], "r"); + (void)close(pdfrom[1]); + break; + } + return (pid); + + /* + * error cleanup and return + */ +error3: + (void)close(pdfrom[0]); + (void)close(pdfrom[1]); +error2: + (void)close(pdto[0]); + (void)close(pdto[1]); +error1: + return (-1); +} + +static char * +basename(char *path) +{ + char *p; + + p = strrchr(path, '/'); + if (p == NULL) { + return (path); + } else { + return (p + 1); + } +} + +#else /* YP */ + +static int match(char *, char *); + +/* + * Determine if requester is allowed to update the given map, + * and update it if so. Returns the status, which is zero + * if there is no access violation. This function updates + * the local file and then shuts up. + */ +int +localupdate(char *name, char *filename, u_int op, u_int keylen __unused, + char *key, u_int datalen __unused, char *data) +{ + char line[256]; + FILE *rf; + FILE *wf; + char *tmpname; + int err; + + /* + * Check permission + */ + if (strcmp(name, key) != 0) { + return (ERR_ACCESS); + } + if (strcmp(name, "nobody") == 0) { + /* + * Can't change "nobody"s key. + */ + return (ERR_ACCESS); + } + + /* + * Open files + */ + tmpname = malloc(strlen(filename) + 4); + if (tmpname == NULL) { + return (ERR_MALLOC); + } + sprintf(tmpname, "%s.tmp", filename); + rf = fopen(filename, "r"); + if (rf == NULL) { + return (ERR_READ); + } + wf = fopen(tmpname, "w"); + if (wf == NULL) { + return (ERR_WRITE); + } + err = -1; + while (fgets(line, sizeof (line), rf)) { + if (err < 0 && match(line, name)) { + switch (op) { + case YPOP_INSERT: + err = ERR_KEY; + break; + case YPOP_STORE: + case YPOP_CHANGE: + fprintf(wf, "%s %s\n", key, data); + err = 0; + break; + case YPOP_DELETE: + /* do nothing */ + err = 0; + break; + } + } else { + fputs(line, wf); + } + } + if (err < 0) { + switch (op) { + case YPOP_CHANGE: + case YPOP_DELETE: + err = ERR_KEY; + break; + case YPOP_INSERT: + case YPOP_STORE: + err = 0; + fprintf(wf, "%s %s\n", key, data); + break; + } + } + fclose(wf); + fclose(rf); + if (err == 0) { + if (rename(tmpname, filename) < 0) { + return (ERR_DBASE); + } + } else { + if (unlink(tmpname) < 0) { + return (ERR_DBASE); + } + } + return (err); +} + +static int +match(char *line, char *name) +{ + int len; + + len = strlen(name); + return (strncmp(line, name, len) == 0 && + (line[len] == ' ' || line[len] == '\t')); +} +#endif /* !YP */ diff --git a/usr.sbin/rpc.ypupdated/yp_dbdelete.c b/usr.sbin/rpc.ypupdated/yp_dbdelete.c new file mode 100644 index 0000000..0552aab --- /dev/null +++ b/usr.sbin/rpc.ypupdated/yp_dbdelete.c @@ -0,0 +1,68 @@ +/* + * 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. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <string.h> +#include <limits.h> +#include <unistd.h> +#include <db.h> +#include <sys/stat.h> +#include <errno.h> +#include <paths.h> +#include <rpcsvc/yp.h> +#include "ypxfr_extern.h" + +int +yp_del_record(DB *dbp, DBT *key) +{ + int rval; + + if ((rval = (dbp->del)(dbp,key,0))) { + switch (rval) { + case 1: + return(YP_FALSE); + break; + case -1: + default: + (void)(dbp->close)(dbp); + return(YP_BADDB); + break; + } + } + + return(YP_TRUE); +} diff --git a/usr.sbin/rpc.ypupdated/yp_dbupdate.c b/usr.sbin/rpc.ypupdated/yp_dbupdate.c new file mode 100644 index 0000000..3481a6b --- /dev/null +++ b/usr.sbin/rpc.ypupdated/yp_dbupdate.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 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. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/fcntl.h> + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <limits.h> +#include <db.h> +#include <unistd.h> +#include <rpcsvc/ypclnt.h> +#include <rpcsvc/ypupdate_prot.h> +#include "ypxfr_extern.h" +#include "ypupdated_extern.h" + +static int +yp_domake(char *map, char *domain) +{ + int pid; + + switch ((pid = fork())) { + case 0: + execlp(MAP_UPDATE_PATH, MAP_UPDATE, map, domain, (char *)NULL); + yp_error("couldn't exec map update process: %s", + strerror(errno)); + exit(1); + break; + case -1: + yp_error("fork() failed: %s", strerror(errno)); + return(YPERR_YPERR); + break; + default: + children++; + break; + } + + return(0); +} + +int +ypmap_update(char *netname, char *map, unsigned int op, unsigned int keylen, + char *keyval, unsigned int datlen, char *datval) +{ + DB *dbp; + DBT key = { NULL, 0 }, data = { NULL, 0 }; + char *yp_last = "YP_LAST_MODIFIED"; + char yplastbuf[YPMAXRECORD]; + char *domptr; + int rval = 0; + + if ((domptr = strchr(netname, '@')) == NULL) + return(ERR_ACCESS); + domptr++; + + + dbp = yp_open_db_rw(domptr, map, O_RDWR); + if (dbp == NULL) + return(ERR_DBASE); + + key.data = keyval; + key.size = keylen; + data.data = datval; + data.size = datlen; + + switch (op) { + case YPOP_DELETE: /* delete this entry */ + rval = yp_del_record(dbp, &key); + if (rval == YP_TRUE) + rval = 0; + break; + case YPOP_INSERT: /* add, do not change */ + rval = yp_put_record(dbp, &key, &data, 0); + if (rval == YP_TRUE) + rval = 0; + break; + case YPOP_STORE: /* add, or change */ + rval = yp_put_record(dbp, &key, &data, 1); + if (rval == YP_TRUE) + rval = 0; + break; + case YPOP_CHANGE: /* change, do not add */ + if (yp_get_record(domptr, map, &key, &data, 0) != YP_TRUE) { + rval = ERR_KEY; + break; + } + rval = yp_put_record(dbp, &key, &data, 1); + if (rval == YP_TRUE) + rval = 0; + break; + default: + yp_error("unknown update command: (%d)", op); + } + + if (rval) { + (void)(dbp->close)(dbp); + return(rval); + } + + snprintf(yplastbuf, sizeof(yplastbuf), "%jd", (intmax_t)time(NULL)); + key.data = yp_last; + key.size = strlen(yp_last); + data.data = (char *)&yplastbuf; + data.size = strlen(yplastbuf); + if (yp_put_record(dbp, &key, &data, 1) != YP_TRUE) { + yp_error("failed to update timestamp in %s/%s", domptr, map); + (void)(dbp->close)(dbp); + return(ERR_DBASE); + } + + (void)(dbp->close)(dbp); + return(yp_domake(map, domptr)); +} diff --git a/usr.sbin/rpc.ypupdated/ypupdate b/usr.sbin/rpc.ypupdated/ypupdate new file mode 100755 index 0000000..4a26f4b --- /dev/null +++ b/usr.sbin/rpc.ypupdated/ypupdate @@ -0,0 +1,33 @@ +#!/bin/sh +# +# This script is invoked by rpc.ypupdatedd to propagate NIS maps +# after the master map databases have been modified. It expects +# to be passed two arguments: the name of the map that was updated +# and the name of the domain where the map resides. +# These are passed to /var/yp/Makefile. +# +# Comment out the LOG=yes line to disable logging. +# +# $FreeBSD$ +# + +LOG=yes +LOGFILE=/var/yp/ypupdate.log + +umask 077 + +if [ ! -f $LOGFILE ]; +then + /usr/bin/touch $LOGFILE + echo "# Edit /usr/libexec/yppwupdate to disable" >> $LOGFILE + echo "# logging to this file from yppasswdd." >> $LOGFILE + echo -n "# Log started on: " >> $LOGFILE + /bin/date >> $LOGFILE +fi + +if [ ! $LOG ]; +then + cd /var/yp/$2; /usr/bin/make -f ../Makefile $1 2>&1 +else + cd /var/yp/$2; /usr/bin/make -f ../Makefile $1 >> $LOGFILE +fi diff --git a/usr.sbin/rpc.ypupdated/ypupdated_extern.h b/usr.sbin/rpc.ypupdated/ypupdated_extern.h new file mode 100644 index 0000000..2cacb95 --- /dev/null +++ b/usr.sbin/rpc.ypupdated/ypupdated_extern.h @@ -0,0 +1,33 @@ +/* + * $FreeBSD$ + */ + +#include <db.h> + +#define YPOP_CHANGE 1 /* change, do not add */ +#define YPOP_INSERT 2 /* add, do not change */ +#define YPOP_DELETE 3 /* delete this entry */ +#define YPOP_STORE 4 /* add, or change */ + +#define ERR_ACCESS 1 +#define ERR_MALLOC 2 +#define ERR_READ 3 +#define ERR_WRITE 4 +#define ERR_DBASE 5 +#define ERR_KEY 6 + +#ifndef YPLIBDIR +#define YPLIBDIR "/usr/libexec/" +#endif + +#ifndef MAP_UPPATE +#define MAP_UPDATE "ypupdate" +#endif + +#define MAP_UPDATE_PATH YPLIBDIR MAP_UPDATE + +extern int children; +extern void ypu_prog_1(struct svc_req *, register SVCXPRT *); +extern int localupdate(char *, char *, u_int, u_int, char *, u_int, char *); +extern int ypmap_update(char *, char *, u_int, u_int, char *, u_int, char *); +extern int yp_del_record(DB *, DBT *); diff --git a/usr.sbin/rpc.ypupdated/ypupdated_main.c b/usr.sbin/rpc.ypupdated/ypupdated_main.c new file mode 100644 index 0000000..92d8374 --- /dev/null +++ b/usr.sbin/rpc.ypupdated/ypupdated_main.c @@ -0,0 +1,285 @@ +/* + * 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. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "ypupdate_prot.h" +#include <stdio.h> +#include <stdlib.h> /* getenv, exit */ +#include <rpc/pmap_clnt.h> /* for pmap_unset */ +#include <rpc/rpc_com.h> +#include <string.h> /* strcmp */ +#include <signal.h> +#ifdef __cplusplus +#include <sysent.h> /* getdtablesize, open */ +#endif /* __cplusplus */ +#include <memory.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <syslog.h> +#include <sys/wait.h> +#include <errno.h> +#include <err.h> +#include <unistd.h> +#include "ypupdated_extern.h" +#include "yp_extern.h" + +#ifndef SIG_PF +#define SIG_PF void(*)(int) +#endif + +#ifdef DEBUG +#define RPC_SVC_FG +#endif + +#define _RPCSVC_CLOSEDOWN 120 +int _rpcpmstart; /* Started by a port monitor ? */ +static int _rpcfdtype; + /* Whether Stream or Datagram ? */ + /* States a server can be in wrt request */ + +#define _IDLE 0 +#define _SERVED 1 +#define _SERVING 2 + +extern int _rpcsvcstate; /* Set when a request is serviced */ + +char *progname = "rpc.ypupdated"; +char *yp_dir = "/var/yp/"; + +static void +_msgout(char* msg) +{ +#ifdef RPC_SVC_FG + if (_rpcpmstart) + syslog(LOG_ERR, "%s", msg); + else + warnx("%s", msg); +#else + syslog(LOG_ERR, "%s", msg); +#endif +} + +static void +closedown(int sig) +{ + if (_rpcsvcstate == _IDLE) { + extern fd_set svc_fdset; + static int size; + int i, openfd; + + if (_rpcfdtype == SOCK_DGRAM) + exit(0); + if (size == 0) { + size = getdtablesize(); + } + for (i = 0, openfd = 0; i < size && openfd < 2; i++) + if (FD_ISSET(i, &svc_fdset)) + openfd++; + if (openfd <= 1) + exit(0); + } + if (_rpcsvcstate == _SERVED) + _rpcsvcstate = _IDLE; + + (void) signal(SIGALRM, (SIG_PF) closedown); + (void) alarm(_RPCSVC_CLOSEDOWN/2); +} + +static void +ypupdated_svc_run(void) +{ +#ifdef FD_SETSIZE + fd_set readfds; +#else + int readfds; +#endif /* def FD_SETSIZE */ + extern int forked; + int pid; + int fd_setsize = _rpc_dtablesize(); + + /* Establish the identity of the parent ypupdated process. */ + pid = getpid(); + + for (;;) { +#ifdef FD_SETSIZE + readfds = svc_fdset; +#else + readfds = svc_fds; +#endif /* def FD_SETSIZE */ + switch (select(fd_setsize, &readfds, NULL, NULL, + (struct timeval *)0)) { + case -1: + if (errno == EINTR) { + continue; + } + warn("svc_run: - select failed"); + return; + case 0: + continue; + default: + svc_getreqset(&readfds); + if (forked && pid != getpid()) + exit(0); + } + } +} + +static void +reaper(int sig) +{ + int status; + + if (sig == SIGHUP) { +#ifdef foo + load_securenets(); +#endif + return; + } + + if (sig == SIGCHLD) { + while (wait3(&status, WNOHANG, NULL) > 0) + children--; + } else { + (void) pmap_unset(YPU_PROG, YPU_VERS); + exit(0); + } +} + +void +usage(void) +{ + fprintf(stderr, "rpc.ypupdatedd [-p path]\n"); + exit(0); +} + +int +main(int argc, char *argv[]) +{ + register SVCXPRT *transp = NULL; + int sock; + int proto = 0; + struct sockaddr_in saddr; + int asize = sizeof (saddr); + int ch; + + while ((ch = getopt(argc, argv, "p:h")) != -1) { + switch (ch) { + case 'p': + yp_dir = optarg; + break; + default: + usage(); + break; + } + } +#ifdef foo + load_securenets(); +#endif + + if (svc_auth_reg(AUTH_DES, _svcauth_des) == -1) { + yp_error("failed to register AUTH_DES flavor"); + exit(1); + } + + if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { + int ssize = sizeof (int); + + if (saddr.sin_family != AF_INET) + exit(1); + if (getsockopt(0, SOL_SOCKET, SO_TYPE, + (char *)&_rpcfdtype, &ssize) == -1) + exit(1); + sock = 0; + _rpcpmstart = 1; + proto = 0; + openlog("rpc.ypupdatedd", LOG_PID, LOG_DAEMON); + } else { +#ifndef RPC_SVC_FG + if (daemon(0,0)) { + err(1, "cannot fork"); + } + openlog("rpc.ypupdated", LOG_PID, LOG_DAEMON); +#endif + sock = RPC_ANYSOCK; + (void) pmap_unset(YPU_PROG, YPU_VERS); + } + + if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { + transp = svcudp_create(sock); + if (transp == NULL) { + _msgout("cannot create udp service."); + exit(1); + } + if (!_rpcpmstart) + proto = IPPROTO_UDP; + if (!svc_register(transp, YPU_PROG, YPU_VERS, ypu_prog_1, proto)) { + _msgout("unable to register (YPU_PROG, YPU_VERS, udp)."); + exit(1); + } + } + + if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { + transp = svctcp_create(sock, 0, 0); + if (transp == NULL) { + _msgout("cannot create tcp service."); + exit(1); + } + if (!_rpcpmstart) + proto = IPPROTO_TCP; + if (!svc_register(transp, YPU_PROG, YPU_VERS, ypu_prog_1, proto)) { + _msgout("unable to register (YPU_PROG, YPU_VERS, tcp)."); + exit(1); + } + } + + if (transp == (SVCXPRT *)NULL) { + _msgout("could not create a handle"); + exit(1); + } + if (_rpcpmstart) { + (void) signal(SIGALRM, (SIG_PF) closedown); + (void) alarm(_RPCSVC_CLOSEDOWN/2); + } + + (void) signal(SIGPIPE, SIG_IGN); + (void) signal(SIGCHLD, (SIG_PF) reaper); + (void) signal(SIGTERM, (SIG_PF) reaper); + (void) signal(SIGINT, (SIG_PF) reaper); + (void) signal(SIGHUP, (SIG_PF) reaper); + + ypupdated_svc_run(); + _msgout("svc_run returned"); + exit(1); + /* NOTREACHED */ +} diff --git a/usr.sbin/rpc.ypupdated/ypupdated_server.c b/usr.sbin/rpc.ypupdated/ypupdated_server.c new file mode 100644 index 0000000..c4e163a --- /dev/null +++ b/usr.sbin/rpc.ypupdated/ypupdated_server.c @@ -0,0 +1,227 @@ +/* + * 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. + * + * ypupdate server implementation + * + * Written by Bill Paul <wpaul@ctr.columbia.edu> + * Center for Telecommunications Research + * Columbia University, New York City + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <rpc/rpc.h> +#include <rpc/key_prot.h> +#include <sys/param.h> +#include <rpcsvc/yp.h> +#include "ypupdate_prot.h" +#include "ypupdated_extern.h" +#include "yp_extern.h" +#include "ypxfr_extern.h" + +int children = 0; +int forked = 0; + +/* + * Try to avoid spoofing: if a client chooses to use a very large + * window and then tries a bunch of randomly chosen encrypted timestamps, + * there's a chance he might stumble onto a valid combination. + * We therefore reject any RPCs with a window size larger than a preset + * value. + */ +#ifndef WINDOW +#define WINDOW (60*60) +#endif + +static enum auth_stat +yp_checkauth(struct svc_req *svcreq) +{ + struct authdes_cred *des_cred; + + switch (svcreq->rq_cred.oa_flavor) { + case AUTH_DES: + des_cred = (struct authdes_cred *) svcreq->rq_clntcred; + if (des_cred->adc_fullname.window > WINDOW) { + yp_error("warning: client-specified window size \ +was too large -- possible spoof attempt"); + return(AUTH_BADCRED); + } + return(AUTH_OK); + break; + case AUTH_UNIX: + case AUTH_NONE: + yp_error("warning: client didn't use DES authentication"); + return(AUTH_TOOWEAK); + break; + default: + yp_error("client used unknown auth flavor"); + return(AUTH_REJECTEDCRED); + break; + } +} + +unsigned int * +ypu_change_1_svc(struct ypupdate_args *args, struct svc_req *svcreq) +{ + struct authdes_cred *des_cred; + static int res; + char *netname; + enum auth_stat astat; + + res = 0; + + astat = yp_checkauth(svcreq); + + if (astat != AUTH_OK) { + svcerr_auth(svcreq->rq_xprt, astat); + return(&res); + } + + des_cred = (struct authdes_cred *) svcreq->rq_clntcred; + netname = des_cred->adc_fullname.name; + + res = localupdate(netname, "/etc/publickey", YPOP_CHANGE, + args->key.yp_buf_len, args->key.yp_buf_val, + args->datum.yp_buf_len, args->datum.yp_buf_val); + + if (res) + return (&res); + + res = ypmap_update(netname, args->mapname, YPOP_CHANGE, + args->key.yp_buf_len, args->key.yp_buf_val, + args->datum.yp_buf_len, args->datum.yp_buf_val); + + return (&res); +} + +unsigned int * +ypu_insert_1_svc(struct ypupdate_args *args, struct svc_req *svcreq) +{ + struct authdes_cred *des_cred; + static int res; + char *netname; + enum auth_stat astat; + + res = 0; + + astat = yp_checkauth(svcreq); + + if (astat != AUTH_OK) { + svcerr_auth(svcreq->rq_xprt, astat); + return(&res); + } + + des_cred = (struct authdes_cred *) svcreq->rq_clntcred; + netname = des_cred->adc_fullname.name; + + res = localupdate(netname, "/etc/publickey", YPOP_INSERT, + args->key.yp_buf_len, args->key.yp_buf_val, + args->datum.yp_buf_len, args->datum.yp_buf_val); + + if (res) + return (&res); + + res = ypmap_update(netname, args->mapname, YPOP_INSERT, + args->key.yp_buf_len, args->key.yp_buf_val, + args->datum.yp_buf_len, args->datum.yp_buf_val); + + return (&res); +} + +unsigned int * +ypu_delete_1_svc(struct ypdelete_args *args, struct svc_req *svcreq) +{ + struct authdes_cred *des_cred; + static int res; + char *netname; + enum auth_stat astat; + + res = 0; + + astat = yp_checkauth(svcreq); + + if (astat != AUTH_OK) { + svcerr_auth(svcreq->rq_xprt, astat); + return(&res); + } + + des_cred = (struct authdes_cred *) svcreq->rq_clntcred; + netname = des_cred->adc_fullname.name; + + res = localupdate(netname, "/etc/publickey", YPOP_DELETE, + args->key.yp_buf_len, args->key.yp_buf_val, + 0, NULL); + + if (res) + return (&res); + + res = ypmap_update(netname, args->mapname, YPOP_DELETE, + args->key.yp_buf_len, args->key.yp_buf_val, + 0, NULL); + + return (&res); +} + +unsigned int * +ypu_store_1_svc(struct ypupdate_args *args, struct svc_req *svcreq) +{ + struct authdes_cred *des_cred; + static int res; + char *netname; + enum auth_stat astat; + + res = 0; + + astat = yp_checkauth(svcreq); + + if (astat != AUTH_OK) { + svcerr_auth(svcreq->rq_xprt, astat); + return(&res); + } + + des_cred = (struct authdes_cred *) svcreq->rq_clntcred; + netname = des_cred->adc_fullname.name; + + res = localupdate(netname, "/etc/publickey", YPOP_STORE, + args->key.yp_buf_len, args->key.yp_buf_val, + args->datum.yp_buf_len, args->datum.yp_buf_val); + + if (res) + return (&res); + + res = ypmap_update(netname, args->mapname, YPOP_STORE, + args->key.yp_buf_len, args->key.yp_buf_val, + args->datum.yp_buf_len, args->datum.yp_buf_val); + + return (&res); +} |