xref: /freebsd/usr.sbin/rpc.ypupdated/update.c (revision 1e96bb57a67cf7296e06e4e57554c017e3c9948c)
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[] =
361e96bb57SPhilippe Charnier 	"$Id$";
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 <stdlib.h>
6140a5f74dSBill Paul #include "ypupdated_extern.h"
6240a5f74dSBill Paul 
6340a5f74dSBill Paul #ifdef YP
6440a5f74dSBill Paul #define	MAXMAPNAMELEN 256
6540a5f74dSBill Paul #else
6640a5f74dSBill Paul #define	YPOP_CHANGE 1			/* change, do not add */
6740a5f74dSBill Paul #define	YPOP_INSERT 2			/* add, do not change */
6840a5f74dSBill Paul #define	YPOP_DELETE 3			/* delete this entry */
6940a5f74dSBill Paul #define	YPOP_STORE  4			/* add, or change */
7040a5f74dSBill Paul #endif
7140a5f74dSBill Paul 
7240a5f74dSBill Paul #ifdef YP
7340a5f74dSBill Paul static char SHELL[] = "/bin/sh";
7440a5f74dSBill Paul static char YPDBPATH[]="/var/yp";	/* This is defined but not used! */
7540a5f74dSBill Paul static char PKMAP[] = "publickey.byname";
7640a5f74dSBill Paul static char UPDATEFILE[] = "updaters";
7740a5f74dSBill Paul static char PKFILE[] = "/etc/publickey";
7840a5f74dSBill Paul #endif	/* YP */
7940a5f74dSBill Paul 
8040a5f74dSBill Paul #ifdef YP
8140a5f74dSBill Paul static int _openchild __P(( char *, FILE **, FILE ** ));
8240a5f74dSBill Paul 
8340a5f74dSBill Paul /*
8440a5f74dSBill Paul  * Determine if requester is allowed to update the given map,
8540a5f74dSBill Paul  * and update it if so. Returns the yp status, which is zero
8640a5f74dSBill Paul  * if there is no access violation.
8740a5f74dSBill Paul  */
8840a5f74dSBill Paul mapupdate(requester, mapname, op, keylen, key, datalen, data)
8940a5f74dSBill Paul 	char *requester;
9040a5f74dSBill Paul 	char *mapname;
9140a5f74dSBill Paul 	u_int op;
9240a5f74dSBill Paul 	u_int keylen;
9340a5f74dSBill Paul 	char *key;
9440a5f74dSBill Paul 	u_int datalen;
9540a5f74dSBill Paul 	char *data;
9640a5f74dSBill Paul {
9740a5f74dSBill Paul 	char updater[MAXMAPNAMELEN + 40];
9840a5f74dSBill Paul 	FILE *childargs;
9940a5f74dSBill Paul 	FILE *childrslt;
10040a5f74dSBill Paul #ifdef WEXITSTATUS
10140a5f74dSBill Paul 	int status;
10240a5f74dSBill Paul #else
10340a5f74dSBill Paul 	union wait status;
10440a5f74dSBill Paul #endif
10540a5f74dSBill Paul 	pid_t pid;
10640a5f74dSBill Paul 	u_int yperrno;
10740a5f74dSBill Paul 
10840a5f74dSBill Paul 
10940a5f74dSBill Paul #ifdef DEBUG
11040a5f74dSBill Paul 	printf("%s %s\n", key, data);
11140a5f74dSBill Paul #endif
11240a5f74dSBill Paul 	(void)sprintf(updater, "make -s -f %s/%s %s", YPDBPATH, /* !!! */
11340a5f74dSBill Paul 					UPDATEFILE, mapname);
11440a5f74dSBill Paul 	pid = _openchild(updater, &childargs, &childrslt);
11540a5f74dSBill Paul 	if (pid < 0) {
11640a5f74dSBill Paul 		return (YPERR_YPERR);
11740a5f74dSBill Paul 	}
11840a5f74dSBill Paul 
11940a5f74dSBill Paul 	/*
12040a5f74dSBill Paul 	 * Write to child
12140a5f74dSBill Paul 	 */
12240a5f74dSBill Paul 	(void)fprintf(childargs, "%s\n", requester);
12340a5f74dSBill Paul 	(void)fprintf(childargs, "%u\n", op);
12440a5f74dSBill Paul 	(void)fprintf(childargs, "%u\n", keylen);
12540a5f74dSBill Paul 	(void)fwrite(key, (int)keylen, 1, childargs);
12640a5f74dSBill Paul 	(void)fprintf(childargs, "\n");
12740a5f74dSBill Paul 	(void)fprintf(childargs, "%u\n", datalen);
12840a5f74dSBill Paul 	(void)fwrite(data, (int)datalen, 1, childargs);
12940a5f74dSBill Paul 	(void)fprintf(childargs, "\n");
13040a5f74dSBill Paul 	(void)fclose(childargs);
13140a5f74dSBill Paul 
13240a5f74dSBill Paul 	/*
13340a5f74dSBill Paul 	 * Read from child
13440a5f74dSBill Paul 	 */
13540a5f74dSBill Paul 	(void)fscanf(childrslt, "%d", &yperrno);
13640a5f74dSBill Paul 	(void)fclose(childrslt);
13740a5f74dSBill Paul 
13840a5f74dSBill Paul 	(void)wait(&status);
13940a5f74dSBill Paul #ifdef WEXITSTATUS
14040a5f74dSBill Paul 	if (WEXITSTATUS(status) != 0) {
14140a5f74dSBill Paul #else
14240a5f74dSBill Paul 	if (status.w_retcode != 0) {
14340a5f74dSBill Paul #endif
14440a5f74dSBill Paul 		return (YPERR_YPERR);
14540a5f74dSBill Paul 	}
14640a5f74dSBill Paul 	return (yperrno);
14740a5f74dSBill Paul }
14840a5f74dSBill Paul 
14940a5f74dSBill Paul /*
15040a5f74dSBill Paul  * returns pid, or -1 for failure
15140a5f74dSBill Paul  */
15240a5f74dSBill Paul static
15340a5f74dSBill Paul _openchild(command, fto, ffrom)
15440a5f74dSBill Paul 	char *command;
15540a5f74dSBill Paul 	FILE **fto;
15640a5f74dSBill Paul 	FILE **ffrom;
15740a5f74dSBill Paul {
15840a5f74dSBill Paul 	int i;
15940a5f74dSBill Paul 	pid_t pid;
16040a5f74dSBill Paul 	int pdto[2];
16140a5f74dSBill Paul 	int pdfrom[2];
16240a5f74dSBill Paul 	char *com;
16340a5f74dSBill Paul 	struct rlimit rl;
16440a5f74dSBill Paul 
16540a5f74dSBill Paul 	if (pipe(pdto) < 0) {
16640a5f74dSBill Paul 		goto error1;
16740a5f74dSBill Paul 	}
16840a5f74dSBill Paul 	if (pipe(pdfrom) < 0) {
16940a5f74dSBill Paul 		goto error2;
17040a5f74dSBill Paul 	}
17140a5f74dSBill Paul #ifdef VFORK
17240a5f74dSBill Paul 	switch (pid = vfork()) {
17340a5f74dSBill Paul #else
17440a5f74dSBill Paul 	switch (pid = fork()) {
17540a5f74dSBill Paul #endif
17640a5f74dSBill Paul 	case -1:
17740a5f74dSBill Paul 		goto error3;
17840a5f74dSBill Paul 
17940a5f74dSBill Paul 	case 0:
18040a5f74dSBill Paul 		/*
18140a5f74dSBill Paul 		 * child: read from pdto[0], write into pdfrom[1]
18240a5f74dSBill Paul 		 */
18340a5f74dSBill Paul 		(void)close(0);
18440a5f74dSBill Paul 		(void)dup(pdto[0]);
18540a5f74dSBill Paul 		(void)close(1);
18640a5f74dSBill Paul 		(void)dup(pdfrom[1]);
18740a5f74dSBill Paul 		getrlimit(RLIMIT_NOFILE, &rl);
18840a5f74dSBill Paul 		for (i = rl.rlim_max - 1; i >= 3; i--) {
18940a5f74dSBill Paul 			(void) close(i);
19040a5f74dSBill Paul 		}
19140a5f74dSBill Paul 		com = malloc((unsigned) strlen(command) + 6);
19240a5f74dSBill Paul 		if (com == NULL) {
19340a5f74dSBill Paul 			_exit(~0);
19440a5f74dSBill Paul 		}
19540a5f74dSBill Paul 		(void)sprintf(com, "exec %s", command);
19640a5f74dSBill Paul 		execl(SHELL, basename(SHELL), "-c", com, NULL);
19740a5f74dSBill Paul 		_exit(~0);
19840a5f74dSBill Paul 
19940a5f74dSBill Paul 	default:
20040a5f74dSBill Paul 		/*
20140a5f74dSBill Paul 		 * parent: write into pdto[1], read from pdfrom[0]
20240a5f74dSBill Paul 		 */
20340a5f74dSBill Paul 		*fto = fdopen(pdto[1], "w");
20440a5f74dSBill Paul 		(void)close(pdto[0]);
20540a5f74dSBill Paul 		*ffrom = fdopen(pdfrom[0], "r");
20640a5f74dSBill Paul 		(void)close(pdfrom[1]);
20740a5f74dSBill Paul 		break;
20840a5f74dSBill Paul 	}
20940a5f74dSBill Paul 	return (pid);
21040a5f74dSBill Paul 
21140a5f74dSBill Paul 	/*
21240a5f74dSBill Paul 	 * error cleanup and return
21340a5f74dSBill Paul 	 */
21440a5f74dSBill Paul error3:
21540a5f74dSBill Paul 	(void)close(pdfrom[0]);
21640a5f74dSBill Paul 	(void)close(pdfrom[1]);
21740a5f74dSBill Paul error2:
21840a5f74dSBill Paul 	(void)close(pdto[0]);
21940a5f74dSBill Paul 	(void)close(pdto[1]);
22040a5f74dSBill Paul error1:
22140a5f74dSBill Paul 	return (-1);
22240a5f74dSBill Paul }
22340a5f74dSBill Paul 
22440a5f74dSBill Paul static char *
22540a5f74dSBill Paul basename(path)
22640a5f74dSBill Paul 	char *path;
22740a5f74dSBill Paul {
22840a5f74dSBill Paul 	char *p;
22940a5f74dSBill Paul 
23040a5f74dSBill Paul 	p = strrchr(path, '/');
23140a5f74dSBill Paul 	if (p == NULL) {
23240a5f74dSBill Paul 		return (path);
23340a5f74dSBill Paul 	} else {
23440a5f74dSBill Paul 		return (p + 1);
23540a5f74dSBill Paul 	}
23640a5f74dSBill Paul }
23740a5f74dSBill Paul 
23840a5f74dSBill Paul #else /* YP */
23940a5f74dSBill Paul 
24040a5f74dSBill Paul #ifdef foo
24140a5f74dSBill Paul #define	ERR_ACCESS	1
24240a5f74dSBill Paul #define	ERR_MALLOC	2
24340a5f74dSBill Paul #define	ERR_READ	3
24440a5f74dSBill Paul #define	ERR_WRITE	4
24540a5f74dSBill Paul #define	ERR_DBASE	5
24640a5f74dSBill Paul #define	ERR_KEY		6
24740a5f74dSBill Paul extern char *malloc();
24840a5f74dSBill Paul #endif
24940a5f74dSBill Paul 
25040a5f74dSBill Paul static int match __P(( char * , char * ));
25140a5f74dSBill Paul 
25240a5f74dSBill Paul /*
25340a5f74dSBill Paul  * Determine if requester is allowed to update the given map,
25440a5f74dSBill Paul  * and update it if so. Returns the status, which is zero
25540a5f74dSBill Paul  * if there is no access violation. This function updates
25640a5f74dSBill Paul  * the local file and then shuts up.
25740a5f74dSBill Paul  */
25840a5f74dSBill Paul int
25940a5f74dSBill Paul localupdate(name, filename, op, keylen, key, datalen, data)
26040a5f74dSBill Paul 	char *name;	/* Name of the requestor */
26140a5f74dSBill Paul 	char *filename;
26240a5f74dSBill Paul 	u_int op;
26340a5f74dSBill Paul 	u_int keylen;	/* Not used */
26440a5f74dSBill Paul 	char *key;
26540a5f74dSBill Paul 	u_int datalen;	/* Not used */
26640a5f74dSBill Paul 	char *data;
26740a5f74dSBill Paul {
26840a5f74dSBill Paul 	char line[256];
26940a5f74dSBill Paul 	FILE *rf;
27040a5f74dSBill Paul 	FILE *wf;
27140a5f74dSBill Paul 	char *tmpname;
27240a5f74dSBill Paul 	int err;
27340a5f74dSBill Paul 
27440a5f74dSBill Paul 	/*
27540a5f74dSBill Paul 	 * Check permission
27640a5f74dSBill Paul 	 */
27740a5f74dSBill Paul 	if (strcmp(name, key) != 0) {
27840a5f74dSBill Paul 		return (ERR_ACCESS);
27940a5f74dSBill Paul 	}
28040a5f74dSBill Paul 	if (strcmp(name, "nobody") == 0) {
28140a5f74dSBill Paul 		/*
28240a5f74dSBill Paul 		 * Can't change "nobody"s key.
28340a5f74dSBill Paul 		 */
28440a5f74dSBill Paul 		return (ERR_ACCESS);
28540a5f74dSBill Paul 	}
28640a5f74dSBill Paul 
28740a5f74dSBill Paul 	/*
28840a5f74dSBill Paul 	 * Open files
28940a5f74dSBill Paul 	 */
29040a5f74dSBill Paul 	tmpname = malloc(strlen(filename) + 4);
29140a5f74dSBill Paul 	if (tmpname == NULL) {
29240a5f74dSBill Paul 		return (ERR_MALLOC);
29340a5f74dSBill Paul 	}
29440a5f74dSBill Paul 	sprintf(tmpname, "%s.tmp", filename);
29540a5f74dSBill Paul 	rf = fopen(filename, "r");
29640a5f74dSBill Paul 	if (rf == NULL) {
29740a5f74dSBill Paul 		return (ERR_READ);
29840a5f74dSBill Paul 	}
29940a5f74dSBill Paul 	wf = fopen(tmpname, "w");
30040a5f74dSBill Paul 	if (wf == NULL) {
30140a5f74dSBill Paul 		return (ERR_WRITE);
30240a5f74dSBill Paul 	}
30340a5f74dSBill Paul 	err = -1;
30440a5f74dSBill Paul 	while (fgets(line, sizeof (line), rf)) {
30540a5f74dSBill Paul 		if (err < 0 && match(line, name)) {
30640a5f74dSBill Paul 			switch (op) {
30740a5f74dSBill Paul 			case YPOP_INSERT:
30840a5f74dSBill Paul 				err = ERR_KEY;
30940a5f74dSBill Paul 				break;
31040a5f74dSBill Paul 			case YPOP_STORE:
31140a5f74dSBill Paul 			case YPOP_CHANGE:
31240a5f74dSBill Paul 				fprintf(wf, "%s %s\n", key, data);
31340a5f74dSBill Paul 				err = 0;
31440a5f74dSBill Paul 				break;
31540a5f74dSBill Paul 			case YPOP_DELETE:
31640a5f74dSBill Paul 				/* do nothing */
31740a5f74dSBill Paul 				err = 0;
31840a5f74dSBill Paul 				break;
31940a5f74dSBill Paul 			}
32040a5f74dSBill Paul 		} else {
32140a5f74dSBill Paul 			fputs(line, wf);
32240a5f74dSBill Paul 		}
32340a5f74dSBill Paul 	}
32440a5f74dSBill Paul 	if (err < 0) {
32540a5f74dSBill Paul 		switch (op) {
32640a5f74dSBill Paul 		case YPOP_CHANGE:
32740a5f74dSBill Paul 		case YPOP_DELETE:
32840a5f74dSBill Paul 			err = ERR_KEY;
32940a5f74dSBill Paul 			break;
33040a5f74dSBill Paul 		case YPOP_INSERT:
33140a5f74dSBill Paul 		case YPOP_STORE:
33240a5f74dSBill Paul 			err = 0;
33340a5f74dSBill Paul 			fprintf(wf, "%s %s\n", key, data);
33440a5f74dSBill Paul 			break;
33540a5f74dSBill Paul 		}
33640a5f74dSBill Paul 	}
33740a5f74dSBill Paul 	fclose(wf);
33840a5f74dSBill Paul 	fclose(rf);
33940a5f74dSBill Paul 	if (err == 0) {
34040a5f74dSBill Paul 		if (rename(tmpname, filename) < 0) {
34140a5f74dSBill Paul 			return (ERR_DBASE);
34240a5f74dSBill Paul 		}
34340a5f74dSBill Paul 	} else {
34440a5f74dSBill Paul 		if (unlink(tmpname) < 0) {
34540a5f74dSBill Paul 			return (ERR_DBASE);
34640a5f74dSBill Paul 		}
34740a5f74dSBill Paul 	}
34840a5f74dSBill Paul 	return (err);
34940a5f74dSBill Paul }
35040a5f74dSBill Paul 
35140a5f74dSBill Paul static int
35240a5f74dSBill Paul match(line, name)
35340a5f74dSBill Paul 	char *line;
35440a5f74dSBill Paul 	char *name;
35540a5f74dSBill Paul {
35640a5f74dSBill Paul 	int len;
35740a5f74dSBill Paul 
35840a5f74dSBill Paul 	len = strlen(name);
35940a5f74dSBill Paul 	return (strncmp(line, name, len) == 0 &&
36040a5f74dSBill Paul 		(line[len] == ' ' || line[len] == '\t'));
36140a5f74dSBill Paul }
36240a5f74dSBill Paul #endif /* !YP */
36340a5f74dSBill Paul 
364