update.c revision 26237
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 31static char sccsid[] = "@(#)update.c 1.2 91/03/11 Copyr 1986 Sun Micro"; 32#endif 33 34/* 35 * Copyright (C) 1986, 1989, Sun Microsystems, Inc. 36 */ 37 38/* 39 * Administrative tool to add a new user to the publickey database 40 */ 41#include <stdio.h> 42#include <stdlib.h> 43#include <unistd.h> 44#include <rpc/rpc.h> 45#include <rpc/key_prot.h> 46#ifdef YP 47#include <rpcsvc/yp_prot.h> 48#include <rpcsvc/ypclnt.h> 49#include <sys/wait.h> 50#include <netdb.h> 51#endif /* YP */ 52#include <pwd.h> 53#include <string.h> 54#include <sys/resource.h> 55#include <stdlib.h> 56#include "ypupdated_extern.h" 57 58#ifdef YP 59#define MAXMAPNAMELEN 256 60#else 61#define YPOP_CHANGE 1 /* change, do not add */ 62#define YPOP_INSERT 2 /* add, do not change */ 63#define YPOP_DELETE 3 /* delete this entry */ 64#define YPOP_STORE 4 /* add, or change */ 65#endif 66 67extern char *getpass(); 68extern char *malloc(); 69 70#ifdef YP 71static char *basename(); 72static char SHELL[] = "/bin/sh"; 73static char YPDBPATH[]="/var/yp"; /* This is defined but not used! */ 74static char PKMAP[] = "publickey.byname"; 75static char UPDATEFILE[] = "updaters"; 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#ifdef foo 240#define ERR_ACCESS 1 241#define ERR_MALLOC 2 242#define ERR_READ 3 243#define ERR_WRITE 4 244#define ERR_DBASE 5 245#define ERR_KEY 6 246extern char *malloc(); 247#endif 248 249static int match __P(( char * , char * )); 250 251/* 252 * Determine if requester is allowed to update the given map, 253 * and update it if so. Returns the status, which is zero 254 * if there is no access violation. This function updates 255 * the local file and then shuts up. 256 */ 257int 258localupdate(name, filename, op, keylen, key, datalen, data) 259 char *name; /* Name of the requestor */ 260 char *filename; 261 u_int op; 262 u_int keylen; /* Not used */ 263 char *key; 264 u_int datalen; /* Not used */ 265 char *data; 266{ 267 char line[256]; 268 FILE *rf; 269 FILE *wf; 270 char *tmpname; 271 int err; 272 273 /* 274 * Check permission 275 */ 276 if (strcmp(name, key) != 0) { 277 return (ERR_ACCESS); 278 } 279 if (strcmp(name, "nobody") == 0) { 280 /* 281 * Can't change "nobody"s key. 282 */ 283 return (ERR_ACCESS); 284 } 285 286 /* 287 * Open files 288 */ 289 tmpname = malloc(strlen(filename) + 4); 290 if (tmpname == NULL) { 291 return (ERR_MALLOC); 292 } 293 sprintf(tmpname, "%s.tmp", filename); 294 rf = fopen(filename, "r"); 295 if (rf == NULL) { 296 return (ERR_READ); 297 } 298 wf = fopen(tmpname, "w"); 299 if (wf == NULL) { 300 return (ERR_WRITE); 301 } 302 err = -1; 303 while (fgets(line, sizeof (line), rf)) { 304 if (err < 0 && match(line, name)) { 305 switch (op) { 306 case YPOP_INSERT: 307 err = ERR_KEY; 308 break; 309 case YPOP_STORE: 310 case YPOP_CHANGE: 311 fprintf(wf, "%s %s\n", key, data); 312 err = 0; 313 break; 314 case YPOP_DELETE: 315 /* do nothing */ 316 err = 0; 317 break; 318 } 319 } else { 320 fputs(line, wf); 321 } 322 } 323 if (err < 0) { 324 switch (op) { 325 case YPOP_CHANGE: 326 case YPOP_DELETE: 327 err = ERR_KEY; 328 break; 329 case YPOP_INSERT: 330 case YPOP_STORE: 331 err = 0; 332 fprintf(wf, "%s %s\n", key, data); 333 break; 334 } 335 } 336 fclose(wf); 337 fclose(rf); 338 if (err == 0) { 339 if (rename(tmpname, filename) < 0) { 340 return (ERR_DBASE); 341 } 342 } else { 343 if (unlink(tmpname) < 0) { 344 return (ERR_DBASE); 345 } 346 } 347 return (err); 348} 349 350static int 351match(line, name) 352 char *line; 353 char *name; 354{ 355 int len; 356 357 len = strlen(name); 358 return (strncmp(line, name, len) == 0 && 359 (line[len] == ' ' || line[len] == '\t')); 360} 361#endif /* !YP */ 362 363