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