xref: /freebsd/usr.sbin/rpc.ypupdated/update.c (revision 994558c335fabca7a2116fd94a4a371aaa72d87a)
140a5f74dSBill Paul /*
240a5f74dSBill Paul  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
340a5f74dSBill Paul  * unrestricted use provided that this legend is included on all tape
440a5f74dSBill Paul  * media and as a part of the software program in whole or part.  Users
540a5f74dSBill Paul  * may copy or modify Sun RPC without charge, but are not authorized
640a5f74dSBill Paul  * to license or distribute it to anyone else except as part of a product or
740a5f74dSBill Paul  * program developed by the user or with the express written consent of
840a5f74dSBill Paul  * Sun Microsystems, Inc.
940a5f74dSBill Paul  *
1040a5f74dSBill Paul  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
1140a5f74dSBill Paul  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
1240a5f74dSBill Paul  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
1340a5f74dSBill Paul  *
1440a5f74dSBill Paul  * Sun RPC is provided with no support and without any obligation on the
1540a5f74dSBill Paul  * part of Sun Microsystems, Inc. to assist in its use, correction,
1640a5f74dSBill Paul  * modification or enhancement.
1740a5f74dSBill Paul  *
1840a5f74dSBill Paul  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
1940a5f74dSBill Paul  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
2040a5f74dSBill Paul  * OR ANY PART THEREOF.
2140a5f74dSBill Paul  *
2240a5f74dSBill Paul  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
2340a5f74dSBill Paul  * or profits or other special, indirect and consequential damages, even if
2440a5f74dSBill Paul  * Sun has been advised of the possibility of such damages.
2540a5f74dSBill Paul  *
2640a5f74dSBill Paul  * Sun Microsystems, Inc.
2740a5f74dSBill Paul  * 2550 Garcia Avenue
2840a5f74dSBill Paul  * Mountain View, California  94043
2940a5f74dSBill Paul  */
301e96bb57SPhilippe Charnier 
3140a5f74dSBill Paul #ifndef lint
321e96bb57SPhilippe Charnier #if 0
3340a5f74dSBill Paul static	char sccsid[] = "@(#)update.c 1.2 91/03/11 Copyr 1986 Sun Micro";
3440a5f74dSBill Paul #endif
351e96bb57SPhilippe Charnier static const char rcsid[] =
3697d92980SPeter Wemm   "$FreeBSD$";
371e96bb57SPhilippe Charnier #endif /* not lint */
3840a5f74dSBill Paul 
3940a5f74dSBill Paul /*
4040a5f74dSBill Paul  * Copyright (C) 1986, 1989, Sun Microsystems, Inc.
4140a5f74dSBill Paul  */
4240a5f74dSBill Paul 
4340a5f74dSBill Paul /*
4440a5f74dSBill Paul  * Administrative tool to add a new user to the publickey database
4540a5f74dSBill Paul  */
4640a5f74dSBill Paul #include <stdio.h>
4740a5f74dSBill Paul #include <stdlib.h>
4840a5f74dSBill Paul #include <unistd.h>
4940a5f74dSBill Paul #include <rpc/rpc.h>
5040a5f74dSBill Paul #include <rpc/key_prot.h>
5140a5f74dSBill Paul #ifdef YP
5240a5f74dSBill Paul #include <rpcsvc/yp_prot.h>
5340a5f74dSBill Paul #include <rpcsvc/ypclnt.h>
5440a5f74dSBill Paul #include <sys/wait.h>
5540a5f74dSBill Paul #include <netdb.h>
5640a5f74dSBill Paul #endif	/* YP */
5740a5f74dSBill Paul #include <pwd.h>
5840a5f74dSBill Paul #include <string.h>
5940a5f74dSBill Paul #include <sys/resource.h>
6040a5f74dSBill Paul #include "ypupdated_extern.h"
6140a5f74dSBill Paul 
6240a5f74dSBill Paul #ifdef YP
6340a5f74dSBill Paul #define	MAXMAPNAMELEN 256
6440a5f74dSBill Paul #else
6540a5f74dSBill Paul #define	YPOP_CHANGE 1			/* change, do not add */
6640a5f74dSBill Paul #define	YPOP_INSERT 2			/* add, do not change */
6740a5f74dSBill Paul #define	YPOP_DELETE 3			/* delete this entry */
6840a5f74dSBill Paul #define	YPOP_STORE  4			/* add, or change */
6940a5f74dSBill Paul #endif
7040a5f74dSBill Paul 
7140a5f74dSBill Paul #ifdef YP
7240a5f74dSBill Paul static char SHELL[] = "/bin/sh";
7340a5f74dSBill Paul static char YPDBPATH[]="/var/yp";	/* This is defined but not used! */
7440a5f74dSBill Paul static char PKMAP[] = "publickey.byname";
7540a5f74dSBill Paul static char UPDATEFILE[] = "updaters";
7640a5f74dSBill Paul static char PKFILE[] = "/etc/publickey";
7740a5f74dSBill Paul #endif	/* YP */
7840a5f74dSBill Paul 
7940a5f74dSBill Paul #ifdef YP
80ed4d1c46SDag-Erling Smørgrav static int _openchild(char *, FILE **, FILE **);
8140a5f74dSBill Paul 
8240a5f74dSBill Paul /*
8340a5f74dSBill Paul  * Determine if requester is allowed to update the given map,
8440a5f74dSBill Paul  * and update it if so. Returns the yp status, which is zero
8540a5f74dSBill Paul  * if there is no access violation.
8640a5f74dSBill Paul  */
87dc584ddbSDag-Erling Smørgrav int
88dc584ddbSDag-Erling Smørgrav mapupdate(char *requester, char *mapname, u_int op, u_int keylen, char *key,
89dc584ddbSDag-Erling Smørgrav     u_int datalen, char *data)
9040a5f74dSBill Paul {
9140a5f74dSBill Paul 	char updater[MAXMAPNAMELEN + 40];
9240a5f74dSBill Paul 	FILE *childargs;
9340a5f74dSBill Paul 	FILE *childrslt;
9440a5f74dSBill Paul #ifdef WEXITSTATUS
9540a5f74dSBill Paul 	int status;
9640a5f74dSBill Paul #else
9740a5f74dSBill Paul 	union wait status;
9840a5f74dSBill Paul #endif
9940a5f74dSBill Paul 	pid_t pid;
10040a5f74dSBill Paul 	u_int yperrno;
10140a5f74dSBill Paul 
10240a5f74dSBill Paul 
10340a5f74dSBill Paul #ifdef DEBUG
10440a5f74dSBill Paul 	printf("%s %s\n", key, data);
10540a5f74dSBill Paul #endif
10640a5f74dSBill Paul 	(void)sprintf(updater, "make -s -f %s/%s %s", YPDBPATH, /* !!! */
10740a5f74dSBill Paul 					UPDATEFILE, mapname);
10840a5f74dSBill Paul 	pid = _openchild(updater, &childargs, &childrslt);
10940a5f74dSBill Paul 	if (pid < 0) {
11040a5f74dSBill Paul 		return (YPERR_YPERR);
11140a5f74dSBill Paul 	}
11240a5f74dSBill Paul 
11340a5f74dSBill Paul 	/*
11440a5f74dSBill Paul 	 * Write to child
11540a5f74dSBill Paul 	 */
11640a5f74dSBill Paul 	(void)fprintf(childargs, "%s\n", requester);
11740a5f74dSBill Paul 	(void)fprintf(childargs, "%u\n", op);
11840a5f74dSBill Paul 	(void)fprintf(childargs, "%u\n", keylen);
11940a5f74dSBill Paul 	(void)fwrite(key, (int)keylen, 1, childargs);
12040a5f74dSBill Paul 	(void)fprintf(childargs, "\n");
12140a5f74dSBill Paul 	(void)fprintf(childargs, "%u\n", datalen);
12240a5f74dSBill Paul 	(void)fwrite(data, (int)datalen, 1, childargs);
12340a5f74dSBill Paul 	(void)fprintf(childargs, "\n");
12440a5f74dSBill Paul 	(void)fclose(childargs);
12540a5f74dSBill Paul 
12640a5f74dSBill Paul 	/*
12740a5f74dSBill Paul 	 * Read from child
12840a5f74dSBill Paul 	 */
12940a5f74dSBill Paul 	(void)fscanf(childrslt, "%d", &yperrno);
13040a5f74dSBill Paul 	(void)fclose(childrslt);
13140a5f74dSBill Paul 
13240a5f74dSBill Paul 	(void)wait(&status);
13340a5f74dSBill Paul #ifdef WEXITSTATUS
134dc584ddbSDag-Erling Smørgrav 	if (WEXITSTATUS(status) != 0)
13540a5f74dSBill Paul #else
136dc584ddbSDag-Erling Smørgrav 	if (status.w_retcode != 0)
13740a5f74dSBill Paul #endif
13840a5f74dSBill Paul 		return (YPERR_YPERR);
13940a5f74dSBill Paul 	return (yperrno);
14040a5f74dSBill Paul }
14140a5f74dSBill Paul 
14240a5f74dSBill Paul /*
14340a5f74dSBill Paul  * returns pid, or -1 for failure
14440a5f74dSBill Paul  */
145dc584ddbSDag-Erling Smørgrav static int
146dc584ddbSDag-Erling Smørgrav _openchild(char *command, FILE **fto, FILE **ffrom)
14740a5f74dSBill Paul {
14840a5f74dSBill Paul 	int i;
14940a5f74dSBill Paul 	pid_t pid;
15040a5f74dSBill Paul 	int pdto[2];
15140a5f74dSBill Paul 	int pdfrom[2];
15240a5f74dSBill Paul 	char *com;
15340a5f74dSBill Paul 	struct rlimit rl;
15440a5f74dSBill Paul 
15540a5f74dSBill Paul 	if (pipe(pdto) < 0) {
15640a5f74dSBill Paul 		goto error1;
15740a5f74dSBill Paul 	}
15840a5f74dSBill Paul 	if (pipe(pdfrom) < 0) {
15940a5f74dSBill Paul 		goto error2;
16040a5f74dSBill Paul 	}
16140a5f74dSBill Paul 	switch (pid = fork()) {
16240a5f74dSBill Paul 	case -1:
16340a5f74dSBill Paul 		goto error3;
16440a5f74dSBill Paul 
16540a5f74dSBill Paul 	case 0:
16640a5f74dSBill Paul 		/*
16740a5f74dSBill Paul 		 * child: read from pdto[0], write into pdfrom[1]
16840a5f74dSBill Paul 		 */
16940a5f74dSBill Paul 		(void)close(0);
17040a5f74dSBill Paul 		(void)dup(pdto[0]);
17140a5f74dSBill Paul 		(void)close(1);
17240a5f74dSBill Paul 		(void)dup(pdfrom[1]);
17340a5f74dSBill Paul 		getrlimit(RLIMIT_NOFILE, &rl);
17440a5f74dSBill Paul 		for (i = rl.rlim_max - 1; i >= 3; i--) {
17540a5f74dSBill Paul 			(void) close(i);
17640a5f74dSBill Paul 		}
17740a5f74dSBill Paul 		com = malloc((unsigned) strlen(command) + 6);
17840a5f74dSBill Paul 		if (com == NULL) {
17940a5f74dSBill Paul 			_exit(~0);
18040a5f74dSBill Paul 		}
18140a5f74dSBill Paul 		(void)sprintf(com, "exec %s", command);
1827bc6d015SBrian Somers 		execl(SHELL, basename(SHELL), "-c", com, (char *)NULL);
18340a5f74dSBill Paul 		_exit(~0);
18440a5f74dSBill Paul 
18540a5f74dSBill Paul 	default:
18640a5f74dSBill Paul 		/*
18740a5f74dSBill Paul 		 * parent: write into pdto[1], read from pdfrom[0]
18840a5f74dSBill Paul 		 */
18940a5f74dSBill Paul 		*fto = fdopen(pdto[1], "w");
19040a5f74dSBill Paul 		(void)close(pdto[0]);
19140a5f74dSBill Paul 		*ffrom = fdopen(pdfrom[0], "r");
19240a5f74dSBill Paul 		(void)close(pdfrom[1]);
19340a5f74dSBill Paul 		break;
19440a5f74dSBill Paul 	}
19540a5f74dSBill Paul 	return (pid);
19640a5f74dSBill Paul 
19740a5f74dSBill Paul 	/*
19840a5f74dSBill Paul 	 * error cleanup and return
19940a5f74dSBill Paul 	 */
20040a5f74dSBill Paul error3:
20140a5f74dSBill Paul 	(void)close(pdfrom[0]);
20240a5f74dSBill Paul 	(void)close(pdfrom[1]);
20340a5f74dSBill Paul error2:
20440a5f74dSBill Paul 	(void)close(pdto[0]);
20540a5f74dSBill Paul 	(void)close(pdto[1]);
20640a5f74dSBill Paul error1:
20740a5f74dSBill Paul 	return (-1);
20840a5f74dSBill Paul }
20940a5f74dSBill Paul 
21040a5f74dSBill Paul static char *
211dc584ddbSDag-Erling Smørgrav basename(char *path)
21240a5f74dSBill Paul {
21340a5f74dSBill Paul 	char *p;
21440a5f74dSBill Paul 
21540a5f74dSBill Paul 	p = strrchr(path, '/');
21640a5f74dSBill Paul 	if (p == NULL) {
21740a5f74dSBill Paul 		return (path);
21840a5f74dSBill Paul 	} else {
21940a5f74dSBill Paul 		return (p + 1);
22040a5f74dSBill Paul 	}
22140a5f74dSBill Paul }
22240a5f74dSBill Paul 
22340a5f74dSBill Paul #else /* YP */
22440a5f74dSBill Paul 
225ed4d1c46SDag-Erling Smørgrav static int match(char *, char *);
22640a5f74dSBill Paul 
22740a5f74dSBill Paul /*
22840a5f74dSBill Paul  * Determine if requester is allowed to update the given map,
22940a5f74dSBill Paul  * and update it if so. Returns the status, which is zero
23040a5f74dSBill Paul  * if there is no access violation. This function updates
23140a5f74dSBill Paul  * the local file and then shuts up.
23240a5f74dSBill Paul  */
23340a5f74dSBill Paul int
234dc584ddbSDag-Erling Smørgrav localupdate(char *name, char *filename, u_int op, u_int keylen __unused,
235dc584ddbSDag-Erling Smørgrav     char *key, u_int datalen __unused, char *data)
23640a5f74dSBill Paul {
23740a5f74dSBill Paul 	char line[256];
23840a5f74dSBill Paul 	FILE *rf;
23940a5f74dSBill Paul 	FILE *wf;
24040a5f74dSBill Paul 	char *tmpname;
24140a5f74dSBill Paul 	int err;
24240a5f74dSBill Paul 
24340a5f74dSBill Paul 	/*
24440a5f74dSBill Paul 	 * Check permission
24540a5f74dSBill Paul 	 */
24640a5f74dSBill Paul 	if (strcmp(name, key) != 0) {
24740a5f74dSBill Paul 		return (ERR_ACCESS);
24840a5f74dSBill Paul 	}
24940a5f74dSBill Paul 	if (strcmp(name, "nobody") == 0) {
25040a5f74dSBill Paul 		/*
25140a5f74dSBill Paul 		 * Can't change "nobody"s key.
25240a5f74dSBill Paul 		 */
25340a5f74dSBill Paul 		return (ERR_ACCESS);
25440a5f74dSBill Paul 	}
25540a5f74dSBill Paul 
25640a5f74dSBill Paul 	/*
25740a5f74dSBill Paul 	 * Open files
25840a5f74dSBill Paul 	 */
25940a5f74dSBill Paul 	tmpname = malloc(strlen(filename) + 4);
26040a5f74dSBill Paul 	if (tmpname == NULL) {
26140a5f74dSBill Paul 		return (ERR_MALLOC);
26240a5f74dSBill Paul 	}
26340a5f74dSBill Paul 	sprintf(tmpname, "%s.tmp", filename);
26440a5f74dSBill Paul 	rf = fopen(filename, "r");
26540a5f74dSBill Paul 	if (rf == NULL) {
266*994558c3SAndriy Voskoboinyk 		err = ERR_READ;
267*994558c3SAndriy Voskoboinyk 		goto cleanup;
26840a5f74dSBill Paul 	}
26940a5f74dSBill Paul 	wf = fopen(tmpname, "w");
27040a5f74dSBill Paul 	if (wf == NULL) {
271*994558c3SAndriy Voskoboinyk 		fclose(rf);
272*994558c3SAndriy Voskoboinyk 		err = ERR_WRITE;
273*994558c3SAndriy Voskoboinyk 		goto cleanup;
27440a5f74dSBill Paul 	}
27540a5f74dSBill Paul 	err = -1;
27640a5f74dSBill Paul 	while (fgets(line, sizeof (line), rf)) {
27740a5f74dSBill Paul 		if (err < 0 && match(line, name)) {
27840a5f74dSBill Paul 			switch (op) {
27940a5f74dSBill Paul 			case YPOP_INSERT:
28040a5f74dSBill Paul 				err = ERR_KEY;
28140a5f74dSBill Paul 				break;
28240a5f74dSBill Paul 			case YPOP_STORE:
28340a5f74dSBill Paul 			case YPOP_CHANGE:
28440a5f74dSBill Paul 				fprintf(wf, "%s %s\n", key, data);
28540a5f74dSBill Paul 				err = 0;
28640a5f74dSBill Paul 				break;
28740a5f74dSBill Paul 			case YPOP_DELETE:
28840a5f74dSBill Paul 				/* do nothing */
28940a5f74dSBill Paul 				err = 0;
29040a5f74dSBill Paul 				break;
29140a5f74dSBill Paul 			}
29240a5f74dSBill Paul 		} else {
29340a5f74dSBill Paul 			fputs(line, wf);
29440a5f74dSBill Paul 		}
29540a5f74dSBill Paul 	}
29640a5f74dSBill Paul 	if (err < 0) {
29740a5f74dSBill Paul 		switch (op) {
29840a5f74dSBill Paul 		case YPOP_CHANGE:
29940a5f74dSBill Paul 		case YPOP_DELETE:
30040a5f74dSBill Paul 			err = ERR_KEY;
30140a5f74dSBill Paul 			break;
30240a5f74dSBill Paul 		case YPOP_INSERT:
30340a5f74dSBill Paul 		case YPOP_STORE:
30440a5f74dSBill Paul 			err = 0;
30540a5f74dSBill Paul 			fprintf(wf, "%s %s\n", key, data);
30640a5f74dSBill Paul 			break;
30740a5f74dSBill Paul 		}
30840a5f74dSBill Paul 	}
30940a5f74dSBill Paul 	fclose(wf);
31040a5f74dSBill Paul 	fclose(rf);
31140a5f74dSBill Paul 	if (err == 0) {
31240a5f74dSBill Paul 		if (rename(tmpname, filename) < 0) {
313*994558c3SAndriy Voskoboinyk 			err = ERR_DBASE;
314*994558c3SAndriy Voskoboinyk 			goto cleanup;
31540a5f74dSBill Paul 		}
31640a5f74dSBill Paul 	} else {
31740a5f74dSBill Paul 		if (unlink(tmpname) < 0) {
318*994558c3SAndriy Voskoboinyk 			err = ERR_DBASE;
319*994558c3SAndriy Voskoboinyk 			goto cleanup;
32040a5f74dSBill Paul 		}
32140a5f74dSBill Paul 	}
322*994558c3SAndriy Voskoboinyk cleanup:
323*994558c3SAndriy Voskoboinyk 	free(tmpname);
32440a5f74dSBill Paul 	return (err);
32540a5f74dSBill Paul }
32640a5f74dSBill Paul 
32740a5f74dSBill Paul static int
328dc584ddbSDag-Erling Smørgrav match(char *line, char *name)
32940a5f74dSBill Paul {
33040a5f74dSBill Paul 	int len;
33140a5f74dSBill Paul 
33240a5f74dSBill Paul 	len = strlen(name);
33340a5f74dSBill Paul 	return (strncmp(line, name, len) == 0 &&
33440a5f74dSBill Paul 		(line[len] == ' ' || line[len] == '\t'));
33540a5f74dSBill Paul }
33640a5f74dSBill Paul #endif /* !YP */
337