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