1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2000 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 /*
41 * Administrative tool to add a new user to the publickey database
42 */
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <rpc/rpc.h>
47 #include <rpc/key_prot.h>
48 #include <rpcsvc/ypclnt.h>
49 #include <sys/wait.h>
50 #include <netdb.h>
51 #include <string.h>
52 #include <sys/stat.h>
53 #include <errno.h>
54
55 #define MAXMAPNAMELEN 256
56
57 extern char *program_name;
58
59 static char *basename(char *path);
60 static int match(char *line, char *name);
61 static int _openchild(char *command, FILE **fto, FILE **ffrom);
62 static char SHELL[] = "/bin/sh";
63 static char UPDATEFILE[] = "updaters";
64 static char MAKE[] = "/usr/ccs/bin/make";
65
66 /*
67 * Determine if requester is allowed to update the given map,
68 * and update it if so. Returns the yp status, which is zero
69 * if there is no access violation.
70 */
71 int
mapupdate(char * name,char * mapname,uint_t op,char * data)72 mapupdate(char *name, char *mapname, uint_t op, char *data)
73 {
74 char updater[MAXMAPNAMELEN + 40];
75 FILE *childargs;
76 FILE *childrslt;
77 #ifdef WEXITSTATUS
78 int status;
79 #else
80 union wait status;
81 #endif
82 pid_t pid;
83 uint_t yperrno;
84 int namelen, datalen;
85 struct stat stbuf;
86
87 #ifdef DEBUG
88 (void) fprintf(stderr, "%s %s\n", name, data);
89 #endif
90 namelen = strlen(name);
91 datalen = strlen(data);
92 errno = 0;
93 if (stat(MAKE, &stbuf) < 0)
94 switch (errno) {
95 case ENOENT:
96 (void) fprintf(stderr,
97 "%s: %s not found, please install on the system\n",
98 program_name, MAKE);
99 return (1);
100 default:
101 (void) fprintf(stderr,
102 "%s: cannot access %s, errno=%d.\n",
103 program_name, MAKE, errno);
104 return (1);
105 }
106 (void) sprintf(updater, "%s -s -f %s %s",
107 MAKE, UPDATEFILE, mapname);
108 pid = _openchild(updater, &childargs, &childrslt);
109 if (pid < 0)
110 return (YPERR_YPERR);
111
112 /*
113 * Write to child
114 */
115 (void) fprintf(childargs, "%s\n", name);
116 (void) fprintf(childargs, "%u\n", op);
117 (void) fprintf(childargs, "%u\n", namelen);
118 (void) fwrite(name, namelen, 1, childargs);
119 (void) fprintf(childargs, "\n");
120 (void) fprintf(childargs, "%u\n", datalen);
121 (void) fwrite(data, datalen, 1, childargs);
122 (void) fprintf(childargs, "\n");
123 (void) fclose(childargs);
124
125 /*
126 * Read from child
127 */
128 (void) fscanf(childrslt, "%d", &yperrno);
129 (void) fclose(childrslt);
130
131 (void) wait(&status);
132 #ifdef WEXITSTATUS
133 if (WEXITSTATUS(status) != 0) {
134 #else
135 if (status.w_retcode != 0) {
136 #endif
137 return (YPERR_YPERR);
138 }
139 return (yperrno);
140 }
141
142 /*
143 * returns pid, or -1 for failure
144 */
145 static int
146 _openchild(char *command, FILE **fto, FILE **ffrom)
147 {
148 int i;
149 pid_t pid;
150 int pdto[2];
151 int pdfrom[2];
152 char *com;
153
154 if (pipe(pdto) < 0) {
155 goto error1;
156 }
157 if (pipe(pdfrom) < 0) {
158 goto error2;
159 }
160 #ifdef VFORK
161 switch (pid = vfork()) {
162 #else
163 switch (pid = fork()) {
164 #endif
165 case -1:
166 goto error3;
167
168 case 0:
169 /*
170 * child: read from pdto[0], write into pdfrom[1]
171 */
172 (void) close(0);
173 (void) dup(pdto[0]);
174 (void) close(1);
175 (void) dup(pdfrom[1]);
176 closefrom(3);
177 com = malloc((unsigned)strlen(command) + 6);
178 if (com == NULL) {
179 _exit(~0);
180 }
181 (void) sprintf(com, "exec %s", command);
182 execl(SHELL, basename(SHELL), "-c", com, NULL);
183 _exit(~0);
184
185 default:
186 /*
187 * parent: write into pdto[1], read from pdfrom[0]
188 */
189 *fto = fdopen(pdto[1], "w");
190 (void) close(pdto[0]);
191 *ffrom = fdopen(pdfrom[0], "r");
192 (void) close(pdfrom[1]);
193 break;
194 }
195 return (pid);
196
197 /*
198 * error cleanup and return
199 */
200 error3:
201 (void) close(pdfrom[0]);
202 (void) close(pdfrom[1]);
203 error2:
204 (void) close(pdto[0]);
205 (void) close(pdto[1]);
206 error1:
207 return (-1);
208 }
209
210 static char *
211 basename(char *path)
212 {
213 char *p;
214
215 p = strrchr(path, '/');
216 if (p == NULL)
217 return (path);
218 return (p + 1);
219 }
220
221 /*
222 * Determine if requester is allowed to update the given map,
223 * and update it if so. Returns the status, which is zero
224 * if there is no access violation, 1 otherwise.
225 * This function updates the local file.
226 */
227 int
228 localupdate(char *name, char *filename, uint_t op, char *data)
229 {
230 char line[256];
231 FILE *rf;
232 FILE *wf;
233 int wfd;
234 char tmpname[80];
235 int err;
236
237 /*
238 * Check permission
239 */
240 if (strcmp(name, "nobody") == 0) {
241 /* cannot change keys for nobody */
242 (void) fprintf(stderr,
243 "%s: cannot change key-pair for %s\n",
244 program_name, name);
245 return (1);
246 }
247
248 /*
249 * Open files
250 */
251 (void) memset(tmpname, 0, 80);
252 (void) sprintf(tmpname, "%s.tmp", filename);
253 rf = fopen(filename, "r");
254 if (rf == NULL) {
255 (void) fprintf(stderr,
256 "%s: cannot read %s\n", program_name, filename);
257 return (1);
258 }
259
260 (void) umask(0);
261
262 /*
263 * Create the new file with the correct permissions
264 */
265 wfd = open(tmpname, O_CREAT|O_RDWR|O_TRUNC,
266 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
267 if (wfd == -1) {
268 (void) fprintf(stderr, "%s: cannot create '%s' to write to.\n",
269 program_name, tmpname);
270 (void) fclose(rf);
271 return (1);
272 }
273 wf = fdopen(wfd, "w");
274 if (wf == NULL) {
275 (void) fprintf(stderr, "%s: cannot fdopen '%s'.\n",
276 program_name, tmpname);
277 (void) close(wfd);
278 (void) fclose(rf);
279 return (1);
280 }
281
282 err = -1;
283 while (fgets(line, sizeof (line), rf)) {
284 if (err < 0 && match(line, name)) {
285 switch (op) {
286 case YPOP_INSERT:
287 err = 1;
288 break;
289 case YPOP_STORE:
290 case YPOP_CHANGE:
291 (void) fprintf(wf, "%s\t%s\n", name, data);
292 err = 0;
293 break;
294 case YPOP_DELETE:
295 /* do nothing */
296 err = 0;
297 break;
298 }
299 } else {
300 fputs(line, wf);
301 }
302 }
303 if (err < 0) {
304 switch (op) {
305 case YPOP_CHANGE:
306 case YPOP_DELETE:
307 err = 1;
308 break;
309 case YPOP_INSERT:
310 case YPOP_STORE:
311 err = 0;
312 (void) fprintf(wf, "%s\t%s\n", name, data);
313 break;
314 }
315 }
316 (void) fclose(wf);
317 (void) fclose(rf);
318 if (err == 0) {
319 if (rename(tmpname, filename) < 0) {
320 (void) fprintf(stderr,
321 "%s: cannot rename %s to %s\n",
322 program_name, tmpname, filename);
323 return (1);
324 }
325 } else {
326 if (unlink(tmpname) < 0) {
327 (void) fprintf(stderr,
328 "%s: cannot delete %s\n",
329 program_name, tmpname);
330 return (1);
331 }
332 }
333 return (err);
334 }
335
336 static int
337 match(char *line, char *name)
338 {
339 int len;
340
341 len = strlen(name);
342 return (strncmp(line, name, len) == 0 &&
343 (line[len] == ' ' || line[len] == '\t'));
344 }
345