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