update.c revision 26238
1/*
2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3 * unrestricted use provided that this legend is included on all tape
4 * media and as a part of the software program in whole or part.  Users
5 * may copy or modify Sun RPC without charge, but are not authorized
6 * to license or distribute it to anyone else except as part of a product or
7 * program developed by the user or with the express written consent of
8 * Sun Microsystems, Inc.
9 *
10 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
11 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13 *
14 * Sun RPC is provided with no support and without any obligation on the
15 * part of Sun Microsystems, Inc. to assist in its use, correction,
16 * modification or enhancement.
17 *
18 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
19 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
20 * OR ANY PART THEREOF.
21 *
22 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
23 * or profits or other special, indirect and consequential damages, even if
24 * Sun has been advised of the possibility of such damages.
25 *
26 * Sun Microsystems, Inc.
27 * 2550 Garcia Avenue
28 * Mountain View, California  94043
29 */
30#ifndef lint
31static	char sccsid[] = "@(#)update.c 1.2 91/03/11 Copyr 1986 Sun Micro";
32#endif
33
34/*
35 * Copyright (C) 1986, 1989, Sun Microsystems, Inc.
36 */
37
38/*
39 * Administrative tool to add a new user to the publickey database
40 */
41#include <stdio.h>
42#include <rpc/rpc.h>
43#include <rpc/key_prot.h>
44#ifdef YP
45#include <rpcsvc/yp_prot.h>
46#include <rpcsvc/ypclnt.h>
47#include <sys/wait.h>
48#include <netdb.h>
49#endif	/* YP */
50#include <pwd.h>
51#include <string.h>
52#include <sys/resource.h>
53
54#ifdef YP
55#define	MAXMAPNAMELEN 256
56#else
57#define	YPOP_CHANGE 1			/* change, do not add */
58#define	YPOP_INSERT 2			/* add, do not change */
59#define	YPOP_DELETE 3			/* delete this entry */
60#define	YPOP_STORE  4			/* add, or change */
61#endif
62
63extern char *getpass();
64extern char *malloc();
65
66#ifdef YP
67static char *basename();
68static char SHELL[] = "/bin/sh";
69static char YPDBPATH[]="/var/yp";	/* This is defined but not used! */
70static char PKMAP[] = "publickey.byname";
71static char UPDATEFILE[] = "updaters";
72#else
73static char PKFILE[] = "/etc/publickey";
74#endif	/* YP */
75
76#ifdef YP
77static int _openchild __P(( char *, FILE **, FILE ** ));
78
79/*
80 * Determine if requester is allowed to update the given map,
81 * and update it if so. Returns the yp status, which is zero
82 * if there is no access violation.
83 */
84mapupdate(requester, mapname, op, keylen, key, datalen, data)
85	char *requester;
86	char *mapname;
87	u_int op;
88	u_int keylen;
89	char *key;
90	u_int datalen;
91	char *data;
92{
93	char updater[MAXMAPNAMELEN + 40];
94	FILE *childargs;
95	FILE *childrslt;
96#ifdef WEXITSTATUS
97	int status;
98#else
99	union wait status;
100#endif
101	pid_t pid;
102	u_int yperrno;
103
104
105#ifdef DEBUG
106	printf("%s %s\n", key, data);
107#endif
108	(void)sprintf(updater, "make -s -f %s/%s %s", YPDBPATH, /* !!! */
109					UPDATEFILE, mapname);
110	pid = _openchild(updater, &childargs, &childrslt);
111	if (pid < 0) {
112		return (YPERR_YPERR);
113	}
114
115	/*
116	 * Write to child
117	 */
118	(void)fprintf(childargs, "%s\n", requester);
119	(void)fprintf(childargs, "%u\n", op);
120	(void)fprintf(childargs, "%u\n", keylen);
121	(void)fwrite(key, (int)keylen, 1, childargs);
122	(void)fprintf(childargs, "\n");
123	(void)fprintf(childargs, "%u\n", datalen);
124	(void)fwrite(data, (int)datalen, 1, childargs);
125	(void)fprintf(childargs, "\n");
126	(void)fclose(childargs);
127
128	/*
129	 * Read from child
130	 */
131	(void)fscanf(childrslt, "%d", &yperrno);
132	(void)fclose(childrslt);
133
134	(void)wait(&status);
135#ifdef WEXITSTATUS
136	if (WEXITSTATUS(status) != 0) {
137#else
138	if (status.w_retcode != 0) {
139#endif
140		return (YPERR_YPERR);
141	}
142	return (yperrno);
143}
144
145/*
146 * returns pid, or -1 for failure
147 */
148static
149_openchild(command, fto, ffrom)
150	char *command;
151	FILE **fto;
152	FILE **ffrom;
153{
154	int i;
155	pid_t pid;
156	int pdto[2];
157	int pdfrom[2];
158	char *com;
159	struct rlimit rl;
160
161	if (pipe(pdto) < 0) {
162		goto error1;
163	}
164	if (pipe(pdfrom) < 0) {
165		goto error2;
166	}
167#ifdef VFORK
168	switch (pid = vfork()) {
169#else
170	switch (pid = fork()) {
171#endif
172	case -1:
173		goto error3;
174
175	case 0:
176		/*
177		 * child: read from pdto[0], write into pdfrom[1]
178		 */
179		(void)close(0);
180		(void)dup(pdto[0]);
181		(void)close(1);
182		(void)dup(pdfrom[1]);
183		getrlimit(RLIMIT_NOFILE, &rl);
184		for (i = rl.rlim_max - 1; i >= 3; i--) {
185			(void) close(i);
186		}
187		com = malloc((unsigned) strlen(command) + 6);
188		if (com == NULL) {
189			_exit(~0);
190		}
191		(void)sprintf(com, "exec %s", command);
192		execl(SHELL, basename(SHELL), "-c", com, NULL);
193		_exit(~0);
194
195	default:
196		/*
197		 * parent: write into pdto[1], read from pdfrom[0]
198		 */
199		*fto = fdopen(pdto[1], "w");
200		(void)close(pdto[0]);
201		*ffrom = fdopen(pdfrom[0], "r");
202		(void)close(pdfrom[1]);
203		break;
204	}
205	return (pid);
206
207	/*
208	 * error cleanup and return
209	 */
210error3:
211	(void)close(pdfrom[0]);
212	(void)close(pdfrom[1]);
213error2:
214	(void)close(pdto[0]);
215	(void)close(pdto[1]);
216error1:
217	return (-1);
218}
219
220static char *
221basename(path)
222	char *path;
223{
224	char *p;
225
226	p = strrchr(path, '/');
227	if (p == NULL) {
228		return (path);
229	} else {
230		return (p + 1);
231	}
232}
233
234#else /* YP */
235
236#define	ERR_ACCESS	1
237#define	ERR_MALLOC	2
238#define	ERR_READ	3
239#define	ERR_WRITE	4
240#define	ERR_DBASE	5
241#define	ERR_KEY		6
242extern char *malloc();
243
244static int match __P(( char * , char * ));
245
246/*
247 * Determine if requester is allowed to update the given map,
248 * and update it if so. Returns the status, which is zero
249 * if there is no access violation. This function updates
250 * the local file and then shuts up.
251 */
252localupdate(name, filename, op, keylen, key, datalen, data)
253	char *name;	/* Name of the requestor */
254	char *filename;
255	u_int op;
256	u_int keylen;	/* Not used */
257	char *key;
258	u_int datalen;	/* Not used */
259	char *data;
260{
261	char line[256];
262	FILE *rf;
263	FILE *wf;
264	char *tmpname;
265	int err;
266
267	/*
268	 * Check permission
269	 */
270	if (strcmp(name, key) != 0) {
271		return (ERR_ACCESS);
272	}
273	if (strcmp(name, "nobody") == 0) {
274		/*
275		 * Can't change "nobody"s key.
276		 */
277		return (ERR_ACCESS);
278	}
279
280	/*
281	 * Open files
282	 */
283	tmpname = malloc(strlen(filename) + 4);
284	if (tmpname == NULL) {
285		return (ERR_MALLOC);
286	}
287	sprintf(tmpname, "%s.tmp", filename);
288	rf = fopen(filename, "r");
289	if (rf == NULL) {
290		return (ERR_READ);
291	}
292	wf = fopen(tmpname, "w");
293	if (wf == NULL) {
294		return (ERR_WRITE);
295	}
296	err = -1;
297	while (fgets(line, sizeof (line), rf)) {
298		if (err < 0 && match(line, name)) {
299			switch (op) {
300			case YPOP_INSERT:
301				err = ERR_KEY;
302				break;
303			case YPOP_STORE:
304			case YPOP_CHANGE:
305				fprintf(wf, "%s %s\n", key, data);
306				err = 0;
307				break;
308			case YPOP_DELETE:
309				/* do nothing */
310				err = 0;
311				break;
312			}
313		} else {
314			fputs(line, wf);
315		}
316	}
317	if (err < 0) {
318		switch (op) {
319		case YPOP_CHANGE:
320		case YPOP_DELETE:
321			err = ERR_KEY;
322			break;
323		case YPOP_INSERT:
324		case YPOP_STORE:
325			err = 0;
326			fprintf(wf, "%s %s\n", key, data);
327			break;
328		}
329	}
330	fclose(wf);
331	fclose(rf);
332	if (err == 0) {
333		if (rename(tmpname, filename) < 0) {
334			return (ERR_DBASE);
335		}
336	} else {
337		if (unlink(tmpname) < 0) {
338			return (ERR_DBASE);
339		}
340	}
341	return (err);
342}
343
344static
345match(line, name)
346	char *line;
347	char *name;
348{
349	int len;
350
351	len = strlen(name);
352	return (strncmp(line, name, len) == 0 &&
353		(line[len] == ' ' || line[len] == '\t'));
354}
355#endif /* !YP */
356
357