126238Swpaul/*
226238Swpaul * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
326238Swpaul * unrestricted use provided that this legend is included on all tape
426238Swpaul * media and as a part of the software program in whole or part.  Users
526238Swpaul * may copy or modify Sun RPC without charge, but are not authorized
626238Swpaul * to license or distribute it to anyone else except as part of a product or
726238Swpaul * program developed by the user or with the express written consent of
826238Swpaul * Sun Microsystems, Inc.
926238Swpaul *
1026238Swpaul * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
1126238Swpaul * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
1226238Swpaul * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
1326238Swpaul *
1426238Swpaul * Sun RPC is provided with no support and without any obligation on the
1526238Swpaul * part of Sun Microsystems, Inc. to assist in its use, correction,
1626238Swpaul * modification or enhancement.
1726238Swpaul *
1826238Swpaul * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
1926238Swpaul * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
2026238Swpaul * OR ANY PART THEREOF.
2126238Swpaul *
2226238Swpaul * In no event will Sun Microsystems, Inc. be liable for any lost revenue
2326238Swpaul * or profits or other special, indirect and consequential damages, even if
2426238Swpaul * Sun has been advised of the possibility of such damages.
2526238Swpaul *
2626238Swpaul * Sun Microsystems, Inc.
2726238Swpaul * 2550 Garcia Avenue
2826238Swpaul * Mountain View, California  94043
2926238Swpaul */
3095633Smarkm
3126238Swpaul#ifndef lint
3227754Scharnier#if 0
3326238Swpaulstatic	char sccsid[] = "@(#)update.c 1.2 91/03/11 Copyr 1986 Sun Micro";
3426238Swpaul#endif
3527754Scharnier#endif
3626238Swpaul
3726238Swpaul/*
3826238Swpaul * Copyright (C) 1986, 1989, Sun Microsystems, Inc.
3926238Swpaul */
4026238Swpaul
4126238Swpaul/*
4226238Swpaul * Administrative tool to add a new user to the publickey database
4326238Swpaul */
4495633Smarkm#include <sys/cdefs.h>
4595633Smarkm__FBSDID("$FreeBSD$");
4695633Smarkm
4787204Smarkm#include <sys/types.h>
4887204Smarkm#include <sys/time.h>
4987204Smarkm#include <sys/resource.h>
5095633Smarkm
5126238Swpaul#include <rpc/rpc.h>
5226238Swpaul#include <rpc/key_prot.h>
5395633Smarkm
5426238Swpaul#ifdef YP
5587204Smarkm#include <sys/wait.h>
5626238Swpaul#include <rpcsvc/yp_prot.h>
5726238Swpaul#include <rpcsvc/ypclnt.h>
5826238Swpaul#include <netdb.h>
5926238Swpaul#endif	/* YP */
6095633Smarkm
61200462Sdelphij#include <pwd.h>
6287204Smarkm#include <stdio.h>
6387204Smarkm#include <stdlib.h>
6426238Swpaul#include <string.h>
6527754Scharnier#include <unistd.h>
6626238Swpaul
6787204Smarkm#include "extern.h"
6826238Swpaul
6926238Swpaul#ifdef YP
7026238Swpaulstatic char SHELL[] = "/bin/sh";
7126238Swpaulstatic char YPDBPATH[]="/var/yp";	/* This is defined but not used! */
7226238Swpaulstatic char UPDATEFILE[] = "updaters";
7326238Swpaul
7492921Simpstatic int _openchild(char *, FILE **, FILE **);
7592921Simpstatic char *basename(char *path);
7626238Swpaul
7726238Swpaul/*
7826238Swpaul * Determine if requester is allowed to update the given map,
7926238Swpaul * and update it if so. Returns the yp status, which is zero
8026238Swpaul * if there is no access violation.
8126238Swpaul */
8287204Smarkmint
8395633Smarkmmapupdate(char *requester, char *mapname, u_int op, u_int keylen,
8495633Smarkm    char *key, u_int datalen, char *data)
8526238Swpaul{
8626238Swpaul	char updater[MAXMAPNAMELEN + 40];
8726238Swpaul	FILE *childargs;
8826238Swpaul	FILE *childrslt;
8926238Swpaul#ifdef WEXITSTATUS
9026238Swpaul	int status;
9126238Swpaul#else
9226238Swpaul	union wait status;
9326238Swpaul#endif
9426238Swpaul	pid_t pid;
9526238Swpaul	u_int yperrno;
9626238Swpaul
9726238Swpaul
9826238Swpaul#ifdef DEBUG
9926238Swpaul	printf("%s %s\n", key, data);
10026238Swpaul#endif
10126238Swpaul	(void)sprintf(updater, "make -s -f %s/%s %s", YPDBPATH, /* !!! */
10226238Swpaul					UPDATEFILE, mapname);
10326238Swpaul	pid = _openchild(updater, &childargs, &childrslt);
10426238Swpaul	if (pid < 0) {
10526238Swpaul		return (YPERR_YPERR);
10626238Swpaul	}
10726238Swpaul
10826238Swpaul	/*
10926238Swpaul	 * Write to child
11026238Swpaul	 */
11126238Swpaul	(void)fprintf(childargs, "%s\n", requester);
11226238Swpaul	(void)fprintf(childargs, "%u\n", op);
11326238Swpaul	(void)fprintf(childargs, "%u\n", keylen);
11426238Swpaul	(void)fwrite(key, (int)keylen, 1, childargs);
11526238Swpaul	(void)fprintf(childargs, "\n");
11626238Swpaul	(void)fprintf(childargs, "%u\n", datalen);
11726238Swpaul	(void)fwrite(data, (int)datalen, 1, childargs);
11826238Swpaul	(void)fprintf(childargs, "\n");
11926238Swpaul	(void)fclose(childargs);
12026238Swpaul
12126238Swpaul	/*
12226238Swpaul	 * Read from child
12326238Swpaul	 */
12426238Swpaul	(void)fscanf(childrslt, "%d", &yperrno);
12526238Swpaul	(void)fclose(childrslt);
12626238Swpaul
12726238Swpaul	(void)wait(&status);
12826238Swpaul#ifdef WEXITSTATUS
12926238Swpaul	if (WEXITSTATUS(status) != 0) {
13026238Swpaul#else
13126238Swpaul	if (status.w_retcode != 0) {
13226238Swpaul#endif
13326238Swpaul		return (YPERR_YPERR);
13426238Swpaul	}
13526238Swpaul	return (yperrno);
13626238Swpaul}
13726238Swpaul
13826238Swpaul/*
13926238Swpaul * returns pid, or -1 for failure
14026238Swpaul */
14187204Smarkmstatic pid_t
14295633Smarkm_openchild(char *command, FILE **fto, FILE **ffrom)
14326238Swpaul{
14426238Swpaul	int i;
14526238Swpaul	pid_t pid;
14626238Swpaul	int pdto[2];
14726238Swpaul	int pdfrom[2];
14826238Swpaul	char *com;
14926238Swpaul	struct rlimit rl;
15026238Swpaul
15126238Swpaul	if (pipe(pdto) < 0) {
15226238Swpaul		goto error1;
15326238Swpaul	}
15426238Swpaul	if (pipe(pdfrom) < 0) {
15526238Swpaul		goto error2;
15626238Swpaul	}
15726238Swpaul	switch (pid = fork()) {
15826238Swpaul	case -1:
15926238Swpaul		goto error3;
16026238Swpaul
16126238Swpaul	case 0:
16226238Swpaul		/*
16326238Swpaul		 * child: read from pdto[0], write into pdfrom[1]
16426238Swpaul		 */
16526238Swpaul		(void)close(0);
16626238Swpaul		(void)dup(pdto[0]);
16726238Swpaul		(void)close(1);
16826238Swpaul		(void)dup(pdfrom[1]);
16926238Swpaul		getrlimit(RLIMIT_NOFILE, &rl);
17026238Swpaul		for (i = rl.rlim_max - 1; i >= 3; i--) {
17126238Swpaul			(void) close(i);
17226238Swpaul		}
17326238Swpaul		com = malloc((unsigned) strlen(command) + 6);
17426238Swpaul		if (com == NULL) {
17526238Swpaul			_exit(~0);
17626238Swpaul		}
17726238Swpaul		(void)sprintf(com, "exec %s", command);
17879452Sbrian		execl(SHELL, basename(SHELL), "-c", com, (char *)NULL);
17926238Swpaul		_exit(~0);
18026238Swpaul
18126238Swpaul	default:
18226238Swpaul		/*
18326238Swpaul		 * parent: write into pdto[1], read from pdfrom[0]
18426238Swpaul		 */
18526238Swpaul		*fto = fdopen(pdto[1], "w");
18626238Swpaul		(void)close(pdto[0]);
18726238Swpaul		*ffrom = fdopen(pdfrom[0], "r");
18826238Swpaul		(void)close(pdfrom[1]);
18926238Swpaul		break;
19026238Swpaul	}
19126238Swpaul	return (pid);
19226238Swpaul
19326238Swpaul	/*
19426238Swpaul	 * error cleanup and return
19526238Swpaul	 */
19626238Swpaulerror3:
19726238Swpaul	(void)close(pdfrom[0]);
19826238Swpaul	(void)close(pdfrom[1]);
19926238Swpaulerror2:
20026238Swpaul	(void)close(pdto[0]);
20126238Swpaul	(void)close(pdto[1]);
20226238Swpaulerror1:
20326238Swpaul	return (-1);
20426238Swpaul}
20526238Swpaul
20626238Swpaulstatic char *
20795633Smarkmbasename(char *path)
20826238Swpaul{
20926238Swpaul	char *p;
21026238Swpaul
21126238Swpaul	p = strrchr(path, '/');
21226238Swpaul	if (p == NULL) {
21326238Swpaul		return (path);
21426238Swpaul	} else {
21526238Swpaul		return (p + 1);
21626238Swpaul	}
21726238Swpaul}
21826238Swpaul
21926238Swpaul#else /* YP */
22026238Swpaul
22126238Swpaul#define	ERR_ACCESS	1
22226238Swpaul#define	ERR_MALLOC	2
22326238Swpaul#define	ERR_READ	3
22426238Swpaul#define	ERR_WRITE	4
22526238Swpaul#define	ERR_DBASE	5
22626238Swpaul#define	ERR_KEY		6
22726238Swpaul
22895633Smarkmstatic int match(char *, char *);
22926238Swpaul
23026238Swpaul/*
23126238Swpaul * Determine if requester is allowed to update the given map,
23226238Swpaul * and update it if so. Returns the status, which is zero
23326238Swpaul * if there is no access violation. This function updates
23426238Swpaul * the local file and then shuts up.
23526238Swpaul */
236141482Sstefanfint
237189169Sedlocalupdate(char *name, char *filename, u_int op, u_int keylen __unused,
238189169Sed    char *key, u_int datalen __unused, char *data)
23926238Swpaul{
24026238Swpaul	char line[256];
24126238Swpaul	FILE *rf;
24226238Swpaul	FILE *wf;
24326238Swpaul	char *tmpname;
24426238Swpaul	int err;
24526238Swpaul
24626238Swpaul	/*
24726238Swpaul	 * Check permission
24826238Swpaul	 */
24926238Swpaul	if (strcmp(name, key) != 0) {
25026238Swpaul		return (ERR_ACCESS);
25126238Swpaul	}
25226238Swpaul	if (strcmp(name, "nobody") == 0) {
25326238Swpaul		/*
25426238Swpaul		 * Can't change "nobody"s key.
25526238Swpaul		 */
25626238Swpaul		return (ERR_ACCESS);
25726238Swpaul	}
25826238Swpaul
25926238Swpaul	/*
26026238Swpaul	 * Open files
26126238Swpaul	 */
26226238Swpaul	tmpname = malloc(strlen(filename) + 4);
26326238Swpaul	if (tmpname == NULL) {
26426238Swpaul		return (ERR_MALLOC);
26526238Swpaul	}
26626238Swpaul	sprintf(tmpname, "%s.tmp", filename);
26726238Swpaul	rf = fopen(filename, "r");
26826238Swpaul	if (rf == NULL) {
26926238Swpaul		return (ERR_READ);
27026238Swpaul	}
27126238Swpaul	wf = fopen(tmpname, "w");
27226238Swpaul	if (wf == NULL) {
27326238Swpaul		return (ERR_WRITE);
27426238Swpaul	}
27526238Swpaul	err = -1;
27626238Swpaul	while (fgets(line, sizeof (line), rf)) {
27726238Swpaul		if (err < 0 && match(line, name)) {
27826238Swpaul			switch (op) {
27926238Swpaul			case YPOP_INSERT:
28026238Swpaul				err = ERR_KEY;
28126238Swpaul				break;
28226238Swpaul			case YPOP_STORE:
28326238Swpaul			case YPOP_CHANGE:
28426238Swpaul				fprintf(wf, "%s %s\n", key, data);
28526238Swpaul				err = 0;
28626238Swpaul				break;
28726238Swpaul			case YPOP_DELETE:
28826238Swpaul				/* do nothing */
28926238Swpaul				err = 0;
29026238Swpaul				break;
29126238Swpaul			}
29226238Swpaul		} else {
29326238Swpaul			fputs(line, wf);
29426238Swpaul		}
29526238Swpaul	}
29626238Swpaul	if (err < 0) {
29726238Swpaul		switch (op) {
29826238Swpaul		case YPOP_CHANGE:
29926238Swpaul		case YPOP_DELETE:
30026238Swpaul			err = ERR_KEY;
30126238Swpaul			break;
30226238Swpaul		case YPOP_INSERT:
30326238Swpaul		case YPOP_STORE:
30426238Swpaul			err = 0;
30526238Swpaul			fprintf(wf, "%s %s\n", key, data);
30626238Swpaul			break;
30726238Swpaul		}
30826238Swpaul	}
30926238Swpaul	fclose(wf);
31026238Swpaul	fclose(rf);
31126238Swpaul	if (err == 0) {
31226238Swpaul		if (rename(tmpname, filename) < 0) {
31326238Swpaul			return (ERR_DBASE);
31426238Swpaul		}
31526238Swpaul	} else {
31626238Swpaul		if (unlink(tmpname) < 0) {
31726238Swpaul			return (ERR_DBASE);
31826238Swpaul		}
31926238Swpaul	}
32026238Swpaul	return (err);
32126238Swpaul}
32226238Swpaul
323141482Sstefanfstatic int
32495633Smarkmmatch(char *line, char *name)
32526238Swpaul{
32626238Swpaul	int len;
32726238Swpaul
32826238Swpaul	len = strlen(name);
32926238Swpaul	return (strncmp(line, name, len) == 0 &&
33026238Swpaul		(line[len] == ' ' || line[len] == '\t'));
33126238Swpaul}
33226238Swpaul#endif /* !YP */
333