xref: /freebsd/usr.sbin/rpc.ypupdated/update.c (revision 4d65a7c6951cea0333f1a0c1b32c38489cdfa6c5)
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 /*
3240a5f74dSBill Paul  * Copyright (C) 1986, 1989, Sun Microsystems, Inc.
3340a5f74dSBill Paul  */
3440a5f74dSBill Paul 
3540a5f74dSBill Paul /*
3640a5f74dSBill Paul  * Administrative tool to add a new user to the publickey database
3740a5f74dSBill Paul  */
3840a5f74dSBill Paul #include <stdio.h>
3940a5f74dSBill Paul #include <stdlib.h>
4040a5f74dSBill Paul #include <unistd.h>
4140a5f74dSBill Paul #include <rpc/rpc.h>
4240a5f74dSBill Paul #include <rpc/key_prot.h>
4340a5f74dSBill Paul #ifdef YP
4440a5f74dSBill Paul #include <rpcsvc/yp_prot.h>
4540a5f74dSBill Paul #include <rpcsvc/ypclnt.h>
4640a5f74dSBill Paul #include <sys/wait.h>
4740a5f74dSBill Paul #include <netdb.h>
4840a5f74dSBill Paul #endif	/* YP */
4940a5f74dSBill Paul #include <pwd.h>
5040a5f74dSBill Paul #include <string.h>
5140a5f74dSBill Paul #include <sys/resource.h>
5240a5f74dSBill Paul #include "ypupdated_extern.h"
5340a5f74dSBill Paul 
5440a5f74dSBill Paul #ifdef YP
5540a5f74dSBill Paul #define	MAXMAPNAMELEN 256
5640a5f74dSBill Paul #else
5740a5f74dSBill Paul #define	YPOP_CHANGE 1			/* change, do not add */
5840a5f74dSBill Paul #define	YPOP_INSERT 2			/* add, do not change */
5940a5f74dSBill Paul #define	YPOP_DELETE 3			/* delete this entry */
6040a5f74dSBill Paul #define	YPOP_STORE  4			/* add, or change */
6140a5f74dSBill Paul #endif
6240a5f74dSBill Paul 
6340a5f74dSBill Paul #ifdef YP
6440a5f74dSBill Paul static char SHELL[] = "/bin/sh";
6540a5f74dSBill Paul static char YPDBPATH[]="/var/yp";	/* This is defined but not used! */
6640a5f74dSBill Paul static char PKMAP[] = "publickey.byname";
6740a5f74dSBill Paul static char UPDATEFILE[] = "updaters";
6840a5f74dSBill Paul static char PKFILE[] = "/etc/publickey";
6940a5f74dSBill Paul #endif	/* YP */
7040a5f74dSBill Paul 
7140a5f74dSBill Paul #ifdef YP
72ed4d1c46SDag-Erling Smørgrav static int _openchild(char *, FILE **, FILE **);
7340a5f74dSBill Paul 
7440a5f74dSBill Paul /*
7540a5f74dSBill Paul  * Determine if requester is allowed to update the given map,
7640a5f74dSBill Paul  * and update it if so. Returns the yp status, which is zero
7740a5f74dSBill Paul  * if there is no access violation.
7840a5f74dSBill Paul  */
79dc584ddbSDag-Erling Smørgrav int
mapupdate(char * requester,char * mapname,u_int op,u_int keylen,char * key,u_int datalen,char * data)80dc584ddbSDag-Erling Smørgrav mapupdate(char *requester, char *mapname, u_int op, u_int keylen, char *key,
81dc584ddbSDag-Erling Smørgrav     u_int datalen, char *data)
8240a5f74dSBill Paul {
8340a5f74dSBill Paul 	char updater[MAXMAPNAMELEN + 40];
8440a5f74dSBill Paul 	FILE *childargs;
8540a5f74dSBill Paul 	FILE *childrslt;
8640a5f74dSBill Paul #ifdef WEXITSTATUS
8740a5f74dSBill Paul 	int status;
8840a5f74dSBill Paul #else
8940a5f74dSBill Paul 	union wait status;
9040a5f74dSBill Paul #endif
9140a5f74dSBill Paul 	pid_t pid;
9240a5f74dSBill Paul 	u_int yperrno;
9340a5f74dSBill Paul 
9440a5f74dSBill Paul 
9540a5f74dSBill Paul #ifdef DEBUG
9640a5f74dSBill Paul 	printf("%s %s\n", key, data);
9740a5f74dSBill Paul #endif
9840a5f74dSBill Paul 	(void)sprintf(updater, "make -s -f %s/%s %s", YPDBPATH, /* !!! */
9940a5f74dSBill Paul 					UPDATEFILE, mapname);
10040a5f74dSBill Paul 	pid = _openchild(updater, &childargs, &childrslt);
10140a5f74dSBill Paul 	if (pid < 0) {
10240a5f74dSBill Paul 		return (YPERR_YPERR);
10340a5f74dSBill Paul 	}
10440a5f74dSBill Paul 
10540a5f74dSBill Paul 	/*
10640a5f74dSBill Paul 	 * Write to child
10740a5f74dSBill Paul 	 */
10840a5f74dSBill Paul 	(void)fprintf(childargs, "%s\n", requester);
10940a5f74dSBill Paul 	(void)fprintf(childargs, "%u\n", op);
11040a5f74dSBill Paul 	(void)fprintf(childargs, "%u\n", keylen);
11140a5f74dSBill Paul 	(void)fwrite(key, (int)keylen, 1, childargs);
11240a5f74dSBill Paul 	(void)fprintf(childargs, "\n");
11340a5f74dSBill Paul 	(void)fprintf(childargs, "%u\n", datalen);
11440a5f74dSBill Paul 	(void)fwrite(data, (int)datalen, 1, childargs);
11540a5f74dSBill Paul 	(void)fprintf(childargs, "\n");
11640a5f74dSBill Paul 	(void)fclose(childargs);
11740a5f74dSBill Paul 
11840a5f74dSBill Paul 	/*
11940a5f74dSBill Paul 	 * Read from child
12040a5f74dSBill Paul 	 */
12140a5f74dSBill Paul 	(void)fscanf(childrslt, "%d", &yperrno);
12240a5f74dSBill Paul 	(void)fclose(childrslt);
12340a5f74dSBill Paul 
12440a5f74dSBill Paul 	(void)wait(&status);
12540a5f74dSBill Paul #ifdef WEXITSTATUS
126dc584ddbSDag-Erling Smørgrav 	if (WEXITSTATUS(status) != 0)
12740a5f74dSBill Paul #else
128dc584ddbSDag-Erling Smørgrav 	if (status.w_retcode != 0)
12940a5f74dSBill Paul #endif
13040a5f74dSBill Paul 		return (YPERR_YPERR);
13140a5f74dSBill Paul 	return (yperrno);
13240a5f74dSBill Paul }
13340a5f74dSBill Paul 
13440a5f74dSBill Paul /*
13540a5f74dSBill Paul  * returns pid, or -1 for failure
13640a5f74dSBill Paul  */
137dc584ddbSDag-Erling Smørgrav static int
_openchild(char * command,FILE ** fto,FILE ** ffrom)138dc584ddbSDag-Erling Smørgrav _openchild(char *command, FILE **fto, FILE **ffrom)
13940a5f74dSBill Paul {
14040a5f74dSBill Paul 	int i;
14140a5f74dSBill Paul 	pid_t pid;
14240a5f74dSBill Paul 	int pdto[2];
14340a5f74dSBill Paul 	int pdfrom[2];
14440a5f74dSBill Paul 	char *com;
14540a5f74dSBill Paul 	struct rlimit rl;
14640a5f74dSBill Paul 
14740a5f74dSBill Paul 	if (pipe(pdto) < 0) {
14840a5f74dSBill Paul 		goto error1;
14940a5f74dSBill Paul 	}
15040a5f74dSBill Paul 	if (pipe(pdfrom) < 0) {
15140a5f74dSBill Paul 		goto error2;
15240a5f74dSBill Paul 	}
15340a5f74dSBill Paul 	switch (pid = fork()) {
15440a5f74dSBill Paul 	case -1:
15540a5f74dSBill Paul 		goto error3;
15640a5f74dSBill Paul 
15740a5f74dSBill Paul 	case 0:
15840a5f74dSBill Paul 		/*
15940a5f74dSBill Paul 		 * child: read from pdto[0], write into pdfrom[1]
16040a5f74dSBill Paul 		 */
16140a5f74dSBill Paul 		(void)close(0);
16240a5f74dSBill Paul 		(void)dup(pdto[0]);
16340a5f74dSBill Paul 		(void)close(1);
16440a5f74dSBill Paul 		(void)dup(pdfrom[1]);
16540a5f74dSBill Paul 		getrlimit(RLIMIT_NOFILE, &rl);
16640a5f74dSBill Paul 		for (i = rl.rlim_max - 1; i >= 3; i--) {
16740a5f74dSBill Paul 			(void) close(i);
16840a5f74dSBill Paul 		}
16940a5f74dSBill Paul 		com = malloc((unsigned) strlen(command) + 6);
17040a5f74dSBill Paul 		if (com == NULL) {
17140a5f74dSBill Paul 			_exit(~0);
17240a5f74dSBill Paul 		}
17340a5f74dSBill Paul 		(void)sprintf(com, "exec %s", command);
1747bc6d015SBrian Somers 		execl(SHELL, basename(SHELL), "-c", com, (char *)NULL);
17540a5f74dSBill Paul 		_exit(~0);
17640a5f74dSBill Paul 
17740a5f74dSBill Paul 	default:
17840a5f74dSBill Paul 		/*
17940a5f74dSBill Paul 		 * parent: write into pdto[1], read from pdfrom[0]
18040a5f74dSBill Paul 		 */
18140a5f74dSBill Paul 		*fto = fdopen(pdto[1], "w");
18240a5f74dSBill Paul 		(void)close(pdto[0]);
18340a5f74dSBill Paul 		*ffrom = fdopen(pdfrom[0], "r");
18440a5f74dSBill Paul 		(void)close(pdfrom[1]);
18540a5f74dSBill Paul 		break;
18640a5f74dSBill Paul 	}
18740a5f74dSBill Paul 	return (pid);
18840a5f74dSBill Paul 
18940a5f74dSBill Paul 	/*
19040a5f74dSBill Paul 	 * error cleanup and return
19140a5f74dSBill Paul 	 */
19240a5f74dSBill Paul error3:
19340a5f74dSBill Paul 	(void)close(pdfrom[0]);
19440a5f74dSBill Paul 	(void)close(pdfrom[1]);
19540a5f74dSBill Paul error2:
19640a5f74dSBill Paul 	(void)close(pdto[0]);
19740a5f74dSBill Paul 	(void)close(pdto[1]);
19840a5f74dSBill Paul error1:
19940a5f74dSBill Paul 	return (-1);
20040a5f74dSBill Paul }
20140a5f74dSBill Paul 
20240a5f74dSBill Paul static char *
basename(char * path)203dc584ddbSDag-Erling Smørgrav basename(char *path)
20440a5f74dSBill Paul {
20540a5f74dSBill Paul 	char *p;
20640a5f74dSBill Paul 
20740a5f74dSBill Paul 	p = strrchr(path, '/');
20840a5f74dSBill Paul 	if (p == NULL) {
20940a5f74dSBill Paul 		return (path);
21040a5f74dSBill Paul 	} else {
21140a5f74dSBill Paul 		return (p + 1);
21240a5f74dSBill Paul 	}
21340a5f74dSBill Paul }
21440a5f74dSBill Paul 
21540a5f74dSBill Paul #else /* YP */
21640a5f74dSBill Paul 
217ed4d1c46SDag-Erling Smørgrav static int match(char *, char *);
21840a5f74dSBill Paul 
21940a5f74dSBill Paul /*
22040a5f74dSBill Paul  * Determine if requester is allowed to update the given map,
22140a5f74dSBill Paul  * and update it if so. Returns the status, which is zero
22240a5f74dSBill Paul  * if there is no access violation. This function updates
22340a5f74dSBill Paul  * the local file and then shuts up.
22440a5f74dSBill Paul  */
22540a5f74dSBill Paul int
localupdate(char * name,char * filename,u_int op,u_int keylen __unused,char * key,u_int datalen __unused,char * data)226dc584ddbSDag-Erling Smørgrav localupdate(char *name, char *filename, u_int op, u_int keylen __unused,
227dc584ddbSDag-Erling Smørgrav     char *key, u_int datalen __unused, char *data)
22840a5f74dSBill Paul {
22940a5f74dSBill Paul 	char line[256];
23040a5f74dSBill Paul 	FILE *rf;
23140a5f74dSBill Paul 	FILE *wf;
23240a5f74dSBill Paul 	char *tmpname;
23340a5f74dSBill Paul 	int err;
23440a5f74dSBill Paul 
23540a5f74dSBill Paul 	/*
23640a5f74dSBill Paul 	 * Check permission
23740a5f74dSBill Paul 	 */
23840a5f74dSBill Paul 	if (strcmp(name, key) != 0) {
23940a5f74dSBill Paul 		return (ERR_ACCESS);
24040a5f74dSBill Paul 	}
24140a5f74dSBill Paul 	if (strcmp(name, "nobody") == 0) {
24240a5f74dSBill Paul 		/*
24340a5f74dSBill Paul 		 * Can't change "nobody"s key.
24440a5f74dSBill Paul 		 */
24540a5f74dSBill Paul 		return (ERR_ACCESS);
24640a5f74dSBill Paul 	}
24740a5f74dSBill Paul 
24840a5f74dSBill Paul 	/*
24940a5f74dSBill Paul 	 * Open files
25040a5f74dSBill Paul 	 */
25140a5f74dSBill Paul 	tmpname = malloc(strlen(filename) + 4);
25240a5f74dSBill Paul 	if (tmpname == NULL) {
25340a5f74dSBill Paul 		return (ERR_MALLOC);
25440a5f74dSBill Paul 	}
25540a5f74dSBill Paul 	sprintf(tmpname, "%s.tmp", filename);
25640a5f74dSBill Paul 	rf = fopen(filename, "r");
25740a5f74dSBill Paul 	if (rf == NULL) {
258*994558c3SAndriy Voskoboinyk 		err = ERR_READ;
259*994558c3SAndriy Voskoboinyk 		goto cleanup;
26040a5f74dSBill Paul 	}
26140a5f74dSBill Paul 	wf = fopen(tmpname, "w");
26240a5f74dSBill Paul 	if (wf == NULL) {
263*994558c3SAndriy Voskoboinyk 		fclose(rf);
264*994558c3SAndriy Voskoboinyk 		err = ERR_WRITE;
265*994558c3SAndriy Voskoboinyk 		goto cleanup;
26640a5f74dSBill Paul 	}
26740a5f74dSBill Paul 	err = -1;
26840a5f74dSBill Paul 	while (fgets(line, sizeof (line), rf)) {
26940a5f74dSBill Paul 		if (err < 0 && match(line, name)) {
27040a5f74dSBill Paul 			switch (op) {
27140a5f74dSBill Paul 			case YPOP_INSERT:
27240a5f74dSBill Paul 				err = ERR_KEY;
27340a5f74dSBill Paul 				break;
27440a5f74dSBill Paul 			case YPOP_STORE:
27540a5f74dSBill Paul 			case YPOP_CHANGE:
27640a5f74dSBill Paul 				fprintf(wf, "%s %s\n", key, data);
27740a5f74dSBill Paul 				err = 0;
27840a5f74dSBill Paul 				break;
27940a5f74dSBill Paul 			case YPOP_DELETE:
28040a5f74dSBill Paul 				/* do nothing */
28140a5f74dSBill Paul 				err = 0;
28240a5f74dSBill Paul 				break;
28340a5f74dSBill Paul 			}
28440a5f74dSBill Paul 		} else {
28540a5f74dSBill Paul 			fputs(line, wf);
28640a5f74dSBill Paul 		}
28740a5f74dSBill Paul 	}
28840a5f74dSBill Paul 	if (err < 0) {
28940a5f74dSBill Paul 		switch (op) {
29040a5f74dSBill Paul 		case YPOP_CHANGE:
29140a5f74dSBill Paul 		case YPOP_DELETE:
29240a5f74dSBill Paul 			err = ERR_KEY;
29340a5f74dSBill Paul 			break;
29440a5f74dSBill Paul 		case YPOP_INSERT:
29540a5f74dSBill Paul 		case YPOP_STORE:
29640a5f74dSBill Paul 			err = 0;
29740a5f74dSBill Paul 			fprintf(wf, "%s %s\n", key, data);
29840a5f74dSBill Paul 			break;
29940a5f74dSBill Paul 		}
30040a5f74dSBill Paul 	}
30140a5f74dSBill Paul 	fclose(wf);
30240a5f74dSBill Paul 	fclose(rf);
30340a5f74dSBill Paul 	if (err == 0) {
30440a5f74dSBill Paul 		if (rename(tmpname, filename) < 0) {
305*994558c3SAndriy Voskoboinyk 			err = ERR_DBASE;
306*994558c3SAndriy Voskoboinyk 			goto cleanup;
30740a5f74dSBill Paul 		}
30840a5f74dSBill Paul 	} else {
30940a5f74dSBill Paul 		if (unlink(tmpname) < 0) {
310*994558c3SAndriy Voskoboinyk 			err = ERR_DBASE;
311*994558c3SAndriy Voskoboinyk 			goto cleanup;
31240a5f74dSBill Paul 		}
31340a5f74dSBill Paul 	}
314*994558c3SAndriy Voskoboinyk cleanup:
315*994558c3SAndriy Voskoboinyk 	free(tmpname);
31640a5f74dSBill Paul 	return (err);
31740a5f74dSBill Paul }
31840a5f74dSBill Paul 
31940a5f74dSBill Paul static int
match(char * line,char * name)320dc584ddbSDag-Erling Smørgrav match(char *line, char *name)
32140a5f74dSBill Paul {
32240a5f74dSBill Paul 	int len;
32340a5f74dSBill Paul 
32440a5f74dSBill Paul 	len = strlen(name);
32540a5f74dSBill Paul 	return (strncmp(line, name, len) == 0 &&
32640a5f74dSBill Paul 		(line[len] == ' ' || line[len] == '\t'));
32740a5f74dSBill Paul }
32840a5f74dSBill Paul #endif /* !YP */
329