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