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) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * Portions of this source code were derived from Berkeley 4.3 BSD 32 * under license from the Regents of the University of California. 33 */ 34 35 #pragma ident "%Z%%M% %I% %E% SMI" 36 37 #ifndef lint 38 static char sccsid[] = "@(#)rpc.ypupdated.c 1.9 87/10/30 Copyr 1986 Sun Micro"; 39 #endif 40 41 /* 42 * YP update service 43 */ 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <sys/types.h> 47 #include <sys/file.h> 48 #include <sys/signal.h> 49 #include <sys/wait.h> 50 #include <rpc/rpc.h> 51 #include <rpc/nettype.h> 52 #include <rpcsvc/ypupd.h> 53 #include <rpcsvc/ypclnt.h> 54 #include <netdir.h> 55 #include <stropts.h> 56 #ifdef SYSLOG 57 #include <syslog.h> 58 #else 59 #define LOG_ERR 1 60 #define openlog(a, b, c) 61 #endif 62 63 #ifdef DEBUG 64 #define RPC_SVC_FG 65 #define debug(msg) fprintf(stderr, "%s\n", msg); 66 #else 67 #define debug(msg) /* turn off debugging */ 68 #endif 69 70 static char YPDIR[] = "/var/yp"; 71 static char UPDATEFILE[] = "/var/yp/updaters"; 72 #define _RPCSVC_CLOSEDOWN 120 73 74 static int addr2netname(); 75 static void closedown(); 76 static void ypupdate_prog(); 77 static void msgout(); 78 static int update(); 79 static int insecure; 80 static int _rpcpmstart; /* Started by a port monitor ? */ 81 static int _rpcsvcdirty; /* Still serving ? */ 82 83 extern unsigned int alarm(); 84 extern void exit(); 85 extern int close(); 86 extern long fork(); 87 extern int free(); 88 extern struct netconfig *getnetconfigent(); 89 extern int strcmp(); 90 extern int strcpy(); 91 extern int syslog(); 92 extern void *signal(); 93 extern int setsid(); 94 extern int t_getinfo(); 95 extern int user2netname(); 96 extern int _openchild(); 97 98 main(argc, argv) 99 int argc; 100 char *argv[]; 101 { 102 pid_t pid; 103 char *cmd; 104 char mname[FMNAMESZ + 1]; 105 106 if (geteuid() != 0) { 107 (void) fprintf(stderr, "must be root to run %s\n", argv[0]); 108 exit(1); 109 } 110 111 cmd = argv[0]; 112 switch (argc) { 113 case 0: 114 cmd = "ypupdated"; 115 break; 116 case 1: 117 break; 118 case 2: 119 if (strcmp(argv[1], "-i") == 0) { 120 insecure++; 121 break; 122 } 123 default: 124 fprintf(stderr, "%s: warning -- options ignored\n", cmd); 125 break; 126 } 127 128 if (chdir(YPDIR) < 0) { 129 fprintf(stderr, "%s: can't chdir to ", cmd); 130 perror(YPDIR); 131 exit(1); 132 } 133 134 if (!ioctl(0, I_LOOK, mname) && 135 (strcmp(mname, "sockmod") == 0 || 136 strcmp(mname, "timod") == 0)) { 137 /* 138 * Started from port monitor: use 0 as fd 139 */ 140 char *netid; 141 struct netconfig *nconf = NULL; 142 SVCXPRT *transp; 143 int pmclose; 144 extern char *getenv(); 145 146 _rpcpmstart = 1; 147 if ((netid = getenv("NLSPROVIDER")) == NULL) { 148 msgout("cannot get transport name"); 149 } 150 if ((nconf = getnetconfigent(netid)) == NULL) { 151 msgout("cannot get transport info"); 152 } 153 if (strcmp(mname, "sockmod") == 0) { 154 if (ioctl(0, I_POP, 0) || ioctl(0, I_PUSH, "timod")) { 155 msgout("could not get the right module"); 156 exit(1); 157 } 158 } 159 pmclose = (t_getstate(0) != T_DATAXFER); 160 if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) { 161 msgout("cannot create update server handle"); 162 exit(1); 163 } 164 if (!svc_reg(transp, YPU_PROG, YPU_VERS, ypupdate_prog, 0)) { 165 msgout("unable to register (YPBINDPROG, YPBINDVERS)."); 166 exit(1); 167 } 168 if (nconf) 169 freenetconfigent(nconf); 170 171 if (pmclose) { 172 (void) signal(SIGALRM, closedown); 173 (void) alarm(_RPCSVC_CLOSEDOWN); 174 } 175 svc_run(); 176 exit(1); 177 } 178 #ifndef RPC_SVC_FG 179 /* 180 * Started from shell; background thyself and run 181 */ 182 pid = fork(); 183 184 if (pid < 0) { 185 perror("cannot fork"); 186 exit(1); 187 } 188 if (pid) 189 exit(0); 190 closefrom(0); 191 (void) setsid(); 192 openlog("ypupdated", LOG_PID, LOG_DAEMON); 193 #endif 194 if (!svc_create(ypupdate_prog, YPU_PROG, YPU_VERS, "netpath")) { 195 msgout("unable to create (YPU_PROG, YPU_VERS) for netpath."); 196 exit(1); 197 } 198 199 svc_run(); 200 msgout("svc_run returned"); 201 exit(1); 202 /* NOTREACHED */ 203 } 204 205 static void 206 ypupdate_prog(rqstp, transp) 207 struct svc_req *rqstp; 208 SVCXPRT *transp; 209 { 210 struct ypupdate_args args; 211 uint_t rslt; 212 uint_t op; 213 char *netname; 214 char namebuf[MAXNETNAMELEN+1]; 215 struct authunix_parms *aup; 216 217 switch (rqstp->rq_proc) { 218 case NULLPROC: 219 svc_sendreply(transp, xdr_void, NULL); 220 return; 221 case YPU_CHANGE: 222 op = YPOP_CHANGE; 223 break; 224 case YPU_DELETE: 225 op = YPOP_DELETE; 226 break; 227 case YPU_INSERT: 228 op = YPOP_INSERT; 229 break; 230 case YPU_STORE: 231 op = YPOP_STORE; 232 break; 233 default: 234 svcerr_noproc(transp); 235 return; 236 } 237 #ifdef DEBUG 238 fprintf(stderr, "ypupdated: request received\n"); 239 #endif 240 switch (rqstp->rq_cred.oa_flavor) { 241 case AUTH_DES: 242 netname = ((struct authdes_cred *) 243 rqstp->rq_clntcred)->adc_fullname.name; 244 break; 245 case AUTH_UNIX: 246 if (insecure) { 247 aup = (struct authunix_parms *)rqstp->rq_clntcred; 248 if (aup->aup_uid == 0) { 249 if (addr2netname(namebuf, transp) != 0) { 250 fprintf(stderr, 251 "addr2netname failing for %d\n", 252 aup->aup_uid); 253 svcerr_systemerr(transp); 254 return; 255 } 256 } else { 257 if (user2netname(namebuf, aup->aup_uid, NULL) 258 != 0) { 259 fprintf(stderr, 260 "user2netname failing for %d\n", 261 aup->aup_uid); 262 svcerr_systemerr(transp); 263 return; 264 } 265 } 266 netname = namebuf; 267 break; 268 } 269 default: 270 svcerr_weakauth(transp); 271 return; 272 } 273 memset(&args, 0, sizeof (args)); 274 if (!svc_getargs(transp, xdr_ypupdate_args, (char *)&args)) { 275 svcerr_decode(transp); 276 return; 277 } 278 #ifdef DEBUG 279 fprintf(stderr, "netname = %s\n, map=%s\n key=%s\n", 280 netname, args.mapname, args.key.yp_buf_val); 281 #endif 282 rslt = update(netname, args.mapname, op, 283 args.key.yp_buf_len, args.key.yp_buf_val, 284 args.datum.yp_buf_len, args.datum.yp_buf_val); 285 if (!svc_sendreply(transp, xdr_u_int, (char *)&rslt)) { 286 debug("svc_sendreply failed"); 287 } 288 if (!svc_freeargs(transp, xdr_ypupdate_args, (char *)&args)) { 289 debug("svc_freeargs failed"); 290 } 291 } 292 293 /* 294 * Determine if requester is allowed to update the given map, 295 * and update it if so. Returns the yp status, which is zero 296 * if there is no access violation. 297 */ 298 static 299 update(requester, mapname, op, keylen, key, datalen, data) 300 char *requester; 301 char *mapname; 302 uint_t op; 303 uint_t keylen; 304 char *key; 305 uint_t datalen; 306 char *data; 307 { 308 char updater[MAXMAPNAMELEN + 40]; 309 FILE *childargs; 310 FILE *childrslt; 311 int status; 312 int yperrno = 0; 313 int pid; 314 315 sprintf(updater, "/usr/ccs/bin/make -s -f %s %s", UPDATEFILE, mapname); 316 #ifdef DEBUG 317 fprintf(stderr, "updater: %s\n", updater); 318 fprintf(stderr, "requestor = %s, op = %d, key = %s\n", 319 requester, op, key); 320 fprintf(stderr, "data = %s\n", data); 321 #endif 322 pid = _openchild(updater, &childargs, &childrslt); 323 if (pid < 0) { 324 debug("openpipes failed"); 325 return (YPERR_YPERR); 326 } 327 328 /* 329 * Write to child 330 */ 331 fprintf(childargs, "%s\n", requester); 332 fprintf(childargs, "%u\n", op); 333 fprintf(childargs, "%u\n", keylen); 334 fwrite(key, keylen, 1, childargs); 335 fprintf(childargs, "\n"); 336 fprintf(childargs, "%u\n", datalen); 337 fwrite(data, datalen, 1, childargs); 338 fprintf(childargs, "\n"); 339 fclose(childargs); 340 341 /* 342 * Read from child 343 */ 344 fscanf(childrslt, "%d", &yperrno); 345 fclose(childrslt); 346 347 wait(&status); 348 if (!WIFEXITED(status)) { 349 return (YPERR_YPERR); 350 } 351 return (yperrno); 352 } 353 354 static void 355 msgout(msg) 356 char *msg; 357 { 358 if (_rpcpmstart) 359 syslog(LOG_ERR, msg); 360 else 361 (void) fprintf(stderr, "%s\n", msg); 362 } 363 364 void 365 closedown() 366 { 367 if (_rpcsvcdirty == 0) { 368 int i, openfd; 369 struct t_info tinfo; 370 371 if (t_getinfo(0, tinfo) || (tinfo.servtype == T_CLTS)) 372 exit(0); 373 374 for (i = 0, openfd = 0; i < svc_max_pollfd && openfd < 2; i++) 375 if (svc_pollfd[i].fd >= 0) 376 openfd++; 377 378 if (openfd <= 1) 379 exit(0); 380 } 381 (void) alarm(_RPCSVC_CLOSEDOWN); 382 } 383 384 static int 385 addr2netname(namebuf, transp) 386 char *namebuf; 387 SVCXPRT *transp; 388 { 389 struct nd_hostservlist *hostservs = NULL; 390 struct netconfig *nconf; 391 struct netbuf *who; 392 393 who = svc_getrpccaller(transp); 394 if ((who == NULL) || (who->len == 0)) 395 return (-1); 396 if ((nconf = getnetconfigent(transp->xp_netid)) 397 == (struct netconfig *)NULL) 398 return (-1); 399 if (netdir_getbyaddr(nconf, &hostservs, who) != 0) { 400 (void) freenetconfigent(nconf); 401 return (-1); 402 } 403 if (hostservs == NULL) { 404 msgout("ypupdated: netdir_getbyaddr failed\n"); 405 } else { 406 strcpy(namebuf, hostservs->h_hostservs->h_host); 407 } 408 (void) freenetconfigent(nconf); 409 netdir_free((char *)hostservs, ND_HOSTSERVLIST); 410 return (0); 411 } 412