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 #pragma ident "%Z%%M% %I% %E% SMI"
41
42 /*
43 * Administrative tool to add a new user to the publickey database
44 */
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <unistd.h>
48 #include <rpc/rpc.h>
49 #include <rpc/key_prot.h>
50 #include <rpcsvc/ypclnt.h>
51 #include <sys/wait.h>
52 #include <netdb.h>
53 #include <string.h>
54 #include <sys/stat.h>
55 #include <errno.h>
56
57 #define MAXMAPNAMELEN 256
58
59 extern char *program_name;
60
61 static char *basename(char *path);
62 static int match(char *line, char *name);
63 static int _openchild(char *command, FILE **fto, FILE **ffrom);
64 static char SHELL[] = "/bin/sh";
65 static char UPDATEFILE[] = "updaters";
66 static char MAKE[] = "/usr/ccs/bin/make";
67
68 /*
69 * Determine if requester is allowed to update the given map,
70 * and update it if so. Returns the yp status, which is zero
71 * if there is no access violation.
72 */
73 int
mapupdate(char * name,char * mapname,uint_t op,char * data)74 mapupdate(char *name, char *mapname, uint_t op, char *data)
75 {
76 char updater[MAXMAPNAMELEN + 40];
77 FILE *childargs;
78 FILE *childrslt;
79 #ifdef WEXITSTATUS
80 int status;
81 #else
82 union wait status;
83 #endif
84 pid_t pid;
85 uint_t yperrno;
86 int namelen, datalen;
87 struct stat stbuf;
88
89 #ifdef DEBUG
90 (void) fprintf(stderr, "%s %s\n", name, data);
91 #endif
92 namelen = strlen(name);
93 datalen = strlen(data);
94 errno = 0;
95 if (stat(MAKE, &stbuf) < 0)
96 switch (errno) {
97 case ENOENT:
98 (void) fprintf(stderr,
99 "%s: %s not found, please install on the system\n",
100 program_name, MAKE);
101 return (1);
102 default:
103 (void) fprintf(stderr,
104 "%s: cannot access %s, errno=%d.\n",
105 program_name, MAKE, errno);
106 return (1);
107 }
108 (void) sprintf(updater, "%s -s -f %s %s",
109 MAKE, UPDATEFILE, mapname);
110 pid = _openchild(updater, &childargs, &childrslt);
111 if (pid < 0)
112 return (YPERR_YPERR);
113
114 /*
115 * Write to child
116 */
117 (void) fprintf(childargs, "%s\n", name);
118 (void) fprintf(childargs, "%u\n", op);
119 (void) fprintf(childargs, "%u\n", namelen);
120 (void) fwrite(name, namelen, 1, childargs);
121 (void) fprintf(childargs, "\n");
122 (void) fprintf(childargs, "%u\n", datalen);
123 (void) fwrite(data, datalen, 1, childargs);
124 (void) fprintf(childargs, "\n");
125 (void) fclose(childargs);
126
127 /*
128 * Read from child
129 */
130 (void) fscanf(childrslt, "%d", &yperrno);
131 (void) fclose(childrslt);
132
133 (void) wait(&status);
134 #ifdef WEXITSTATUS
135 if (WEXITSTATUS(status) != 0) {
136 #else
137 if (status.w_retcode != 0) {
138 #endif
139 return (YPERR_YPERR);
140 }
141 return (yperrno);
142 }
143
144 /*
145 * returns pid, or -1 for failure
146 */
147 static int
148 _openchild(char *command, FILE **fto, FILE **ffrom)
149 {
150 int i;
151 pid_t pid;
152 int pdto[2];
153 int pdfrom[2];
154 char *com;
155
156 if (pipe(pdto) < 0) {
157 goto error1;
158 }
159 if (pipe(pdfrom) < 0) {
160 goto error2;
161 }
162 #ifdef VFORK
163 switch (pid = vfork()) {
164 #else
165 switch (pid = fork()) {
166 #endif
167 case -1:
168 goto error3;
169
170 case 0:
171 /*
172 * child: read from pdto[0], write into pdfrom[1]
173 */
174 (void) close(0);
175 (void) dup(pdto[0]);
176 (void) close(1);
177 (void) dup(pdfrom[1]);
178 closefrom(3);
179 com = malloc((unsigned)strlen(command) + 6);
180 if (com == NULL) {
181 _exit(~0);
182 }
183 (void) sprintf(com, "exec %s", command);
184 execl(SHELL, basename(SHELL), "-c", com, NULL);
185 _exit(~0);
186
187 default:
188 /*
189 * parent: write into pdto[1], read from pdfrom[0]
190 */
191 *fto = fdopen(pdto[1], "w");
192 (void) close(pdto[0]);
193 *ffrom = fdopen(pdfrom[0], "r");
194 (void) close(pdfrom[1]);
195 break;
196 }
197 return (pid);
198
199 /*
200 * error cleanup and return
201 */
202 error3:
203 (void) close(pdfrom[0]);
204 (void) close(pdfrom[1]);
205 error2:
206 (void) close(pdto[0]);
207 (void) close(pdto[1]);
208 error1:
209 return (-1);
210 }
211
212 static char *
213 basename(char *path)
214 {
215 char *p;
216
217 p = strrchr(path, '/');
218 if (p == NULL)
219 return (path);
220 return (p + 1);
221 }
222
223 /*
224 * Determine if requester is allowed to update the given map,
225 * and update it if so. Returns the status, which is zero
226 * if there is no access violation, 1 otherwise.
227 * This function updates the local file.
228 */
229 int
230 localupdate(char *name, char *filename, uint_t op, char *data)
231 {
232 char line[256];
233 FILE *rf;
234 FILE *wf;
235 int wfd;
236 char tmpname[80];
237 int err;
238
239 /*
240 * Check permission
241 */
242 if (strcmp(name, "nobody") == 0) {
243 /* cannot change keys for nobody */
244 (void) fprintf(stderr,
245 "%s: cannot change key-pair for %s\n",
246 program_name, name);
247 return (1);
248 }
249
250 /*
251 * Open files
252 */
253 (void) memset(tmpname, 0, 80);
254 (void) sprintf(tmpname, "%s.tmp", filename);
255 rf = fopen(filename, "r");
256 if (rf == NULL) {
257 (void) fprintf(stderr,
258 "%s: cannot read %s\n", program_name, filename);
259 return (1);
260 }
261
262 (void) umask(0);
263
264 /*
265 * Create the new file with the correct permissions
266 */
267 wfd = open(tmpname, O_CREAT|O_RDWR|O_TRUNC,
268 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
269 if (wfd == -1) {
270 (void) fprintf(stderr, "%s: cannot create '%s' to write to.\n",
271 program_name, tmpname);
272 (void) fclose(rf);
273 return (1);
274 }
275 wf = fdopen(wfd, "w");
276 if (wf == NULL) {
277 (void) fprintf(stderr, "%s: cannot fdopen '%s'.\n",
278 program_name, tmpname);
279 (void) close(wfd);
280 (void) fclose(rf);
281 return (1);
282 }
283
284 err = -1;
285 while (fgets(line, sizeof (line), rf)) {
286 if (err < 0 && match(line, name)) {
287 switch (op) {
288 case YPOP_INSERT:
289 err = 1;
290 break;
291 case YPOP_STORE:
292 case YPOP_CHANGE:
293 (void) fprintf(wf, "%s\t%s\n", name, data);
294 err = 0;
295 break;
296 case YPOP_DELETE:
297 /* do nothing */
298 err = 0;
299 break;
300 }
301 } else {
302 fputs(line, wf);
303 }
304 }
305 if (err < 0) {
306 switch (op) {
307 case YPOP_CHANGE:
308 case YPOP_DELETE:
309 err = 1;
310 break;
311 case YPOP_INSERT:
312 case YPOP_STORE:
313 err = 0;
314 (void) fprintf(wf, "%s\t%s\n", name, data);
315 break;
316 }
317 }
318 (void) fclose(wf);
319 (void) fclose(rf);
320 if (err == 0) {
321 if (rename(tmpname, filename) < 0) {
322 (void) fprintf(stderr,
323 "%s: cannot rename %s to %s\n",
324 program_name, tmpname, filename);
325 return (1);
326 }
327 } else {
328 if (unlink(tmpname) < 0) {
329 (void) fprintf(stderr,
330 "%s: cannot delete %s\n",
331 program_name, tmpname);
332 return (1);
333 }
334 }
335 return (err);
336 }
337
338 static int
339 match(char *line, char *name)
340 {
341 int len;
342
343 len = strlen(name);
344 return (strncmp(line, name, len) == 0 &&
345 (line[len] == ' ' || line[len] == '\t'));
346 }
347