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 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