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 59extern char *program_name; 60 61static char *basename(char *path); 62static int match(char *line, char *name); 63static int _openchild(char *command, FILE **fto, FILE **ffrom); 64static char SHELL[] = "/bin/sh"; 65static char UPDATEFILE[] = "updaters"; 66static 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 */ 73int 74mapupdate(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 */ 147static 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 */ 202error3: 203 (void) close(pdfrom[0]); 204 (void) close(pdfrom[1]); 205error2: 206 (void) close(pdto[0]); 207 (void) close(pdto[1]); 208error1: 209 return (-1); 210} 211 212static char * 213basename(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 */ 229int 230localupdate(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 338static int 339match(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