update.c revision 344746
1189251Ssam/*
2189251Ssam * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3337817Scy * unrestricted use provided that this legend is included on all tape
4189251Ssam * media and as a part of the software program in whole or part.  Users
5252726Srpaulo * may copy or modify Sun RPC without charge, but are not authorized
6252726Srpaulo * to license or distribute it to anyone else except as part of a product or
7189251Ssam * program developed by the user or with the express written consent of
8189251Ssam * Sun Microsystems, Inc.
9189251Ssam *
10189251Ssam * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
11189251Ssam * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
12214734Srpaulo * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13214734Srpaulo *
14252726Srpaulo * Sun RPC is provided with no support and without any obligation on the
15214734Srpaulo * part of Sun Microsystems, Inc. to assist in its use, correction,
16252726Srpaulo * modification or enhancement.
17189251Ssam *
18189251Ssam * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
19189251Ssam * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
20189251Ssam * OR ANY PART THEREOF.
21189251Ssam *
22189251Ssam * In no event will Sun Microsystems, Inc. be liable for any lost revenue
23189251Ssam * or profits or other special, indirect and consequential damages, even if
24189251Ssam * Sun has been advised of the possibility of such damages.
25189251Ssam *
26189251Ssam * Sun Microsystems, Inc.
27189251Ssam * 2550 Garcia Avenue
28189251Ssam * Mountain View, California  94043
29189251Ssam */
30189251Ssam
31189251Ssam#ifndef lint
32189251Ssam#if 0
33189251Ssamstatic	char sccsid[] = "@(#)update.c 1.2 91/03/11 Copyr 1986 Sun Micro";
34189251Ssam#endif
35189251Ssamstatic const char rcsid[] =
36189251Ssam  "$FreeBSD: stable/10/usr.sbin/rpc.ypupdated/update.c 344746 2019-03-04 03:30:39Z avos $";
37189251Ssam#endif /* not lint */
38189251Ssam
39189251Ssam/*
40189251Ssam * Copyright (C) 1986, 1989, Sun Microsystems, Inc.
41189251Ssam */
42189251Ssam
43189251Ssam/*
44189251Ssam * Administrative tool to add a new user to the publickey database
45189251Ssam */
46189251Ssam#include <stdio.h>
47189251Ssam#include <stdlib.h>
48189251Ssam#include <unistd.h>
49189251Ssam#include <rpc/rpc.h>
50337817Scy#include <rpc/key_prot.h>
51337817Scy#ifdef YP
52189251Ssam#include <rpcsvc/yp_prot.h>
53337817Scy#include <rpcsvc/ypclnt.h>
54337817Scy#include <sys/wait.h>
55337817Scy#include <netdb.h>
56337817Scy#endif	/* YP */
57337817Scy#include <pwd.h>
58337817Scy#include <string.h>
59337817Scy#include <sys/resource.h>
60337817Scy#include "ypupdated_extern.h"
61337817Scy
62337817Scy#ifdef YP
63337817Scy#define	MAXMAPNAMELEN 256
64337817Scy#else
65337817Scy#define	YPOP_CHANGE 1			/* change, do not add */
66337817Scy#define	YPOP_INSERT 2			/* add, do not change */
67337817Scy#define	YPOP_DELETE 3			/* delete this entry */
68337817Scy#define	YPOP_STORE  4			/* add, or change */
69337817Scy#endif
70337817Scy
71337817Scy#ifdef YP
72189251Ssamstatic char SHELL[] = "/bin/sh";
73189251Ssamstatic char YPDBPATH[]="/var/yp";	/* This is defined but not used! */
74189251Ssamstatic char PKMAP[] = "publickey.byname";
75346981Scystatic char UPDATEFILE[] = "updaters";
76346981Scystatic char PKFILE[] = "/etc/publickey";
77346981Scy#endif	/* YP */
78189251Ssam
79252726Srpaulo#ifdef YP
80189251Ssamstatic int _openchild(char *, FILE **, FILE **);
81189251Ssam
82189251Ssam/*
83189251Ssam * Determine if requester is allowed to update the given map,
84189251Ssam * and update it if so. Returns the yp status, which is zero
85189251Ssam * if there is no access violation.
86189251Ssam */
87337817Scyint
88189251Ssammapupdate(char *requester, char *mapname, u_int op, u_int keylen, char *key,
89189251Ssam    u_int datalen, char *data)
90189251Ssam{
91189251Ssam	char updater[MAXMAPNAMELEN + 40];
92189251Ssam	FILE *childargs;
93189251Ssam	FILE *childrslt;
94189251Ssam#ifdef WEXITSTATUS
95189251Ssam	int status;
96189251Ssam#else
97189251Ssam	union wait status;
98189251Ssam#endif
99189251Ssam	pid_t pid;
100189251Ssam	u_int yperrno;
101189251Ssam
102189251Ssam
103189251Ssam#ifdef DEBUG
104189251Ssam	printf("%s %s\n", key, data);
105189251Ssam#endif
106189251Ssam	(void)sprintf(updater, "make -s -f %s/%s %s", YPDBPATH, /* !!! */
107337817Scy					UPDATEFILE, mapname);
108189251Ssam	pid = _openchild(updater, &childargs, &childrslt);
109189251Ssam	if (pid < 0) {
110189251Ssam		return (YPERR_YPERR);
111189251Ssam	}
112189251Ssam
113189251Ssam	/*
114189251Ssam	 * Write to child
115189251Ssam	 */
116189251Ssam	(void)fprintf(childargs, "%s\n", requester);
117189251Ssam	(void)fprintf(childargs, "%u\n", op);
118189251Ssam	(void)fprintf(childargs, "%u\n", keylen);
119189251Ssam	(void)fwrite(key, (int)keylen, 1, childargs);
120189251Ssam	(void)fprintf(childargs, "\n");
121189251Ssam	(void)fprintf(childargs, "%u\n", datalen);
122189251Ssam	(void)fwrite(data, (int)datalen, 1, childargs);
123189251Ssam	(void)fprintf(childargs, "\n");
124189251Ssam	(void)fclose(childargs);
125189251Ssam
126189251Ssam	/*
127337817Scy	 * Read from child
128337817Scy	 */
129337817Scy	(void)fscanf(childrslt, "%d", &yperrno);
130337817Scy	(void)fclose(childrslt);
131337817Scy
132337817Scy	(void)wait(&status);
133337817Scy#ifdef WEXITSTATUS
134337817Scy	if (WEXITSTATUS(status) != 0)
135337817Scy#else
136337817Scy	if (status.w_retcode != 0)
137337817Scy#endif
138337817Scy		return (YPERR_YPERR);
139337817Scy	return (yperrno);
140337817Scy}
141337817Scy
142337817Scy/*
143337817Scy * returns pid, or -1 for failure
144337817Scy */
145337817Scystatic int
146337817Scy_openchild(char *command, FILE **fto, FILE **ffrom)
147337817Scy{
148337817Scy	int i;
149337817Scy	pid_t pid;
150337817Scy	int pdto[2];
151337817Scy	int pdfrom[2];
152337817Scy	char *com;
153337817Scy	struct rlimit rl;
154337817Scy
155337817Scy	if (pipe(pdto) < 0) {
156189251Ssam		goto error1;
157189251Ssam	}
158189251Ssam	if (pipe(pdfrom) < 0) {
159189251Ssam		goto error2;
160189251Ssam	}
161189251Ssam	switch (pid = fork()) {
162337817Scy	case -1:
163337817Scy		goto error3;
164337817Scy
165337817Scy	case 0:
166337817Scy		/*
167337817Scy		 * child: read from pdto[0], write into pdfrom[1]
168337817Scy		 */
169337817Scy		(void)close(0);
170337817Scy		(void)dup(pdto[0]);
171337817Scy		(void)close(1);
172337817Scy		(void)dup(pdfrom[1]);
173337817Scy		getrlimit(RLIMIT_NOFILE, &rl);
174337817Scy		for (i = rl.rlim_max - 1; i >= 3; i--) {
175337817Scy			(void) close(i);
176337817Scy		}
177337817Scy		com = malloc((unsigned) strlen(command) + 6);
178337817Scy		if (com == NULL) {
179337817Scy			_exit(~0);
180337817Scy		}
181337817Scy		(void)sprintf(com, "exec %s", command);
182337817Scy		execl(SHELL, basename(SHELL), "-c", com, (char *)NULL);
183337817Scy		_exit(~0);
184337817Scy
185337817Scy	default:
186337817Scy		/*
187337817Scy		 * parent: write into pdto[1], read from pdfrom[0]
188337817Scy		 */
189337817Scy		*fto = fdopen(pdto[1], "w");
190337817Scy		(void)close(pdto[0]);
191337817Scy		*ffrom = fdopen(pdfrom[0], "r");
192337817Scy		(void)close(pdfrom[1]);
193337817Scy		break;
194337817Scy	}
195337817Scy	return (pid);
196337817Scy
197337817Scy	/*
198337817Scy	 * error cleanup and return
199337817Scy	 */
200337817Scyerror3:
201337817Scy	(void)close(pdfrom[0]);
202337817Scy	(void)close(pdfrom[1]);
203337817Scyerror2:
204337817Scy	(void)close(pdto[0]);
205337817Scy	(void)close(pdto[1]);
206337817Scyerror1:
207337817Scy	return (-1);
208337817Scy}
209337817Scy
210337817Scystatic char *
211337817Scybasename(char *path)
212337817Scy{
213337817Scy	char *p;
214337817Scy
215337817Scy	p = strrchr(path, '/');
216337817Scy	if (p == NULL) {
217337817Scy		return (path);
218337817Scy	} else {
219337817Scy		return (p + 1);
220337817Scy	}
221337817Scy}
222337817Scy
223337817Scy#else /* YP */
224337817Scy
225337817Scystatic int match(char *, char *);
226337817Scy
227337817Scy/*
228337817Scy * Determine if requester is allowed to update the given map,
229337817Scy * and update it if so. Returns the status, which is zero
230337817Scy * if there is no access violation. This function updates
231337817Scy * the local file and then shuts up.
232337817Scy */
233337817Scyint
234337817Scylocalupdate(char *name, char *filename, u_int op, u_int keylen __unused,
235337817Scy    char *key, u_int datalen __unused, char *data)
236337817Scy{
237337817Scy	char line[256];
238337817Scy	FILE *rf;
239337817Scy	FILE *wf;
240337817Scy	char *tmpname;
241337817Scy	int err;
242337817Scy
243337817Scy	/*
244337817Scy	 * Check permission
245189251Ssam	 */
246189251Ssam	if (strcmp(name, key) != 0) {
247189251Ssam		return (ERR_ACCESS);
248189251Ssam	}
249252726Srpaulo	if (strcmp(name, "nobody") == 0) {
250252726Srpaulo		/*
251189251Ssam		 * Can't change "nobody"s key.
252189251Ssam		 */
253189251Ssam		return (ERR_ACCESS);
254189251Ssam	}
255189251Ssam
256189251Ssam	/*
257189251Ssam	 * Open files
258189251Ssam	 */
259189251Ssam	tmpname = malloc(strlen(filename) + 4);
260189251Ssam	if (tmpname == NULL) {
261189251Ssam		return (ERR_MALLOC);
262189251Ssam	}
263189251Ssam	sprintf(tmpname, "%s.tmp", filename);
264189251Ssam	rf = fopen(filename, "r");
265189251Ssam	if (rf == NULL) {
266189251Ssam		err = ERR_READ;
267189251Ssam		goto cleanup;
268189251Ssam	}
269189251Ssam	wf = fopen(tmpname, "w");
270189251Ssam	if (wf == NULL) {
271189251Ssam		fclose(rf);
272337817Scy		err = ERR_WRITE;
273337817Scy		goto cleanup;
274337817Scy	}
275337817Scy	err = -1;
276337817Scy	while (fgets(line, sizeof (line), rf)) {
277189251Ssam		if (err < 0 && match(line, name)) {
278189251Ssam			switch (op) {
279189251Ssam			case YPOP_INSERT:
280189251Ssam				err = ERR_KEY;
281189251Ssam				break;
282189251Ssam			case YPOP_STORE:
283189251Ssam			case YPOP_CHANGE:
284189251Ssam				fprintf(wf, "%s %s\n", key, data);
285189251Ssam				err = 0;
286189251Ssam				break;
287189251Ssam			case YPOP_DELETE:
288189251Ssam				/* do nothing */
289189251Ssam				err = 0;
290189251Ssam				break;
291189251Ssam			}
292189251Ssam		} else {
293189251Ssam			fputs(line, wf);
294189251Ssam		}
295189251Ssam	}
296189251Ssam	if (err < 0) {
297337817Scy		switch (op) {
298189251Ssam		case YPOP_CHANGE:
299189251Ssam		case YPOP_DELETE:
300189251Ssam			err = ERR_KEY;
301189251Ssam			break;
302189251Ssam		case YPOP_INSERT:
303189251Ssam		case YPOP_STORE:
304189251Ssam			err = 0;
305189251Ssam			fprintf(wf, "%s %s\n", key, data);
306189251Ssam			break;
307189251Ssam		}
308189251Ssam	}
309189251Ssam	fclose(wf);
310189251Ssam	fclose(rf);
311189251Ssam	if (err == 0) {
312189251Ssam		if (rename(tmpname, filename) < 0) {
313189251Ssam			err = ERR_DBASE;
314189251Ssam			goto cleanup;
315189251Ssam		}
316189251Ssam	} else {
317189251Ssam		if (unlink(tmpname) < 0) {
318189251Ssam			err = ERR_DBASE;
319189251Ssam			goto cleanup;
320189251Ssam		}
321189251Ssam	}
322189251Ssamcleanup:
323189251Ssam	free(tmpname);
324189251Ssam	return (err);
325189251Ssam}
326189251Ssam
327189251Ssamstatic int
328189251Ssammatch(char *line, char *name)
329189251Ssam{
330189251Ssam	int len;
331252726Srpaulo
332252726Srpaulo	len = strlen(name);
333189251Ssam	return (strncmp(line, name, len) == 0 &&
334189251Ssam		(line[len] == ' ' || line[len] == '\t'));
335189251Ssam}
336189251Ssam#endif /* !YP */
337189251Ssam