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