1/* $OpenBSD: ypserv.c,v 1.12 1997/11/04 07:40:52 deraadt Exp $ */ 2 3/* 4 * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se> 5 * All rights reserved. 6 * Portions copyright (c) 2004-2007 Apple Inc. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Mats O Jansson 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 23 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35#include <sys/cdefs.h> 36#ifndef LINT 37__unused static char rcsid[] = "$OpenBSD: ypserv.c,v 1.12 1997/11/04 07:40:52 deraadt Exp $"; 38#endif 39 40#include "yp.h" 41#include "ypv1.h" 42#include <stdio.h> 43#include <stdlib.h>/* getenv, exit */ 44#include <rpc/pmap_clnt.h> /* for pmap_unset */ 45#include <string.h> /* strcmp */ 46#include <unistd.h> 47#include <netdb.h> 48#include <signal.h> 49#include <errno.h> 50#include <sys/ttycom.h>/* TIOCNOTTY */ 51#ifdef __cplusplus 52#include <sysent.h> /* getdtablesize, open */ 53#endif /* __cplusplus */ 54#include <memory.h> 55#include <sys/socket.h> 56#include <netinet/in.h> 57#include <syslog.h> 58#include "acl.h" 59#include "yplog.h" 60#include "ypdef.h" 61#include <sys/wait.h> 62#include <sys/ioctl.h> /* for ioctl */ 63#include <sys/fcntl.h> /* for open */ 64 65#ifdef __STDC__ 66#define SIG_PF void(*)(int) 67#endif 68 69#ifdef DEBUG 70#define RPC_SVC_FG 71#endif 72 73#define _RPCSVC_CLOSEDOWN 120 74static int _rpcpmstart; /* Started by a port monitor ? */ 75static int _rpcfdtype; /* Whether Stream or Datagram ? */ 76static int _rpcsvcdirty; /* Still serving ? */ 77 78int usedns = FALSE; 79char *progname = "ypserv"; 80char *aclfile = NULL; 81 82void sig_child(); 83void sig_hup(); 84extern void ypdb_init(void); 85 86/* in the RPC library */ 87SVCXPRT *svcfd_create(int, u_int, u_int); 88 89static 90void _msgout(char* msg) 91{ 92#ifdef RPC_SVC_FG 93 if (_rpcpmstart) 94 syslog(LOG_ERR, msg); 95 else 96 (void) fprintf(stderr, "%s\n", msg); 97#else 98 syslog(LOG_ERR, "%s", msg); 99#endif 100} 101 102static void 103closedown() 104{ 105 if (_rpcsvcdirty == 0) { 106 extern fd_set svc_fdset; 107 static int size; 108 int i, openfd; 109 110 if (_rpcfdtype == SOCK_DGRAM) 111 exit(0); 112 if (size == 0) { 113 size = getdtablesize(); 114 } 115 for (i = 0, openfd = 0; i < size && openfd < 2; i++) 116 if (FD_ISSET(i, &svc_fdset)) 117 openfd++; 118 if (openfd <= (_rpcpmstart?0:1)) 119 exit(0); 120 } 121 (void) alarm(_RPCSVC_CLOSEDOWN); 122} 123 124static void 125ypprog_1(struct svc_req *rqstp, register SVCXPRT *transp) 126{ 127 union { 128 domainname ypproc_domain_1_arg; 129 domainname ypproc_domain_nonack_1_arg; 130 yprequest ypproc_match_1_arg; 131 yprequest ypproc_first_1_arg; 132 yprequest ypproc_next_1_arg; 133 yprequest ypproc_poll_1_arg; 134 yprequest ypproc_push_1_arg; 135 yprequest ypproc_pull_1_arg; 136 yprequest ypproc_get_1_arg; 137 } argument; 138 char *result; 139 xdrproc_t xdr_argument, xdr_result; 140 char *(*local)(char *, struct svc_req *); 141 142 _rpcsvcdirty = 1; 143 switch (rqstp->rq_proc) { 144 case YPOLDPROC_NULL: 145 xdr_argument = (xdrproc_t) xdr_void; 146 xdr_result = (xdrproc_t) xdr_void; 147 local = (char *(*)(char *, struct svc_req *)) ypproc_null_1_svc; 148 break; 149 150 case YPOLDPROC_DOMAIN: 151 xdr_argument = (xdrproc_t) xdr_domainname; 152 xdr_result = (xdrproc_t) xdr_bool; 153 local = (char *(*)(char *, struct svc_req *)) ypproc_domain_1_svc; 154 break; 155 156 case YPOLDPROC_DOMAIN_NONACK: 157 xdr_argument = (xdrproc_t) xdr_domainname; 158 xdr_result = (xdrproc_t) xdr_bool; 159 local = (char *(*)(char *, struct svc_req *)) ypproc_domain_nonack_1_svc; 160 break; 161 162 case YPOLDPROC_MATCH: 163 xdr_argument = (xdrproc_t) xdr_yprequest; 164 xdr_result = (xdrproc_t) xdr_ypresponse; 165 local = (char *(*)(char *, struct svc_req *)) ypproc_match_1_svc; 166 break; 167 168 case YPOLDPROC_FIRST: 169 xdr_argument = (xdrproc_t) xdr_yprequest; 170 xdr_result = (xdrproc_t) xdr_ypresponse; 171 local = (char *(*)(char *, struct svc_req *)) ypproc_first_1_svc; 172 break; 173 174 case YPOLDPROC_NEXT: 175 xdr_argument = (xdrproc_t) xdr_yprequest; 176 xdr_result = (xdrproc_t) xdr_ypresponse; 177 local = (char *(*)(char *, struct svc_req *)) ypproc_next_1_svc; 178 break; 179 180 case YPOLDPROC_POLL: 181 xdr_argument = (xdrproc_t) xdr_yprequest; 182 xdr_result = (xdrproc_t) xdr_ypresponse; 183 local = (char *(*)(char *, struct svc_req *)) ypproc_poll_1_svc; 184 break; 185 186 case YPOLDPROC_PUSH: 187 xdr_argument = (xdrproc_t) xdr_yprequest; 188 xdr_result = (xdrproc_t) xdr_void; 189 local = (char *(*)(char *, struct svc_req *)) ypproc_push_1_svc; 190 break; 191 192 case YPOLDPROC_PULL: 193 xdr_argument = (xdrproc_t) xdr_yprequest; 194 xdr_result = (xdrproc_t) xdr_void; 195 local = (char *(*)(char *, struct svc_req *)) ypproc_pull_1_svc; 196 break; 197 198 case YPOLDPROC_GET: 199 xdr_argument = (xdrproc_t) xdr_yprequest; 200 xdr_result = (xdrproc_t) xdr_void; 201 local = (char *(*)(char *, struct svc_req *)) ypproc_get_1_svc; 202 break; 203 204 default: 205 svcerr_noproc(transp); 206 _rpcsvcdirty = 0; 207 return; 208 } 209 (void) memset((char *)&argument, 0, sizeof (argument)); 210 if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) { 211 svcerr_decode(transp); 212 _rpcsvcdirty = 0; 213 return; 214 } 215 result = (*local)((char *)&argument, rqstp); 216 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { 217 svcerr_systemerr(transp); 218 } 219 if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) { 220 _msgout("unable to free arguments"); 221 exit(1); 222 } 223 _rpcsvcdirty = 0; 224 return; 225} 226 227static void 228ypprog_2(struct svc_req *rqstp, register SVCXPRT *transp) 229{ 230 union { 231 domainname ypproc_domain_2_arg; 232 domainname ypproc_domain_nonack_2_arg; 233 ypreq_key ypproc_match_2_arg; 234 ypreq_nokey ypproc_first_2_arg; 235 ypreq_key ypproc_next_2_arg; 236 ypreq_xfr ypproc_xfr_2_arg; 237 ypreq_nokey ypproc_all_2_arg; 238 ypreq_nokey ypproc_master_2_arg; 239 ypreq_nokey ypproc_order_2_arg; 240 domainname ypproc_maplist_2_arg; 241 } argument; 242 char *result; 243 xdrproc_t xdr_argument, xdr_result; 244 char *(*local)(char *, struct svc_req *); 245 246 _rpcsvcdirty = 1; 247 switch (rqstp->rq_proc) { 248 case YPPROC_NULL: 249 xdr_argument = (xdrproc_t) xdr_void; 250 xdr_result = (xdrproc_t) xdr_void; 251 local = (char *(*)(char *, struct svc_req *)) ypproc_null_2_svc; 252 break; 253 254 case YPPROC_DOMAIN: 255 xdr_argument = (xdrproc_t) xdr_domainname; 256 xdr_result = (xdrproc_t) xdr_bool; 257 local = (char *(*)(char *, struct svc_req *)) ypproc_domain_2_svc; 258 break; 259 260 case YPPROC_DOMAIN_NONACK: 261 xdr_argument = (xdrproc_t) xdr_domainname; 262 xdr_result = (xdrproc_t) xdr_bool; 263 local = (char *(*)(char *, struct svc_req *)) ypproc_domain_nonack_2_svc; 264 break; 265 266 case YPPROC_MATCH: 267 xdr_argument = (xdrproc_t) xdr_ypreq_key; 268 xdr_result = (xdrproc_t) xdr_ypresp_val; 269 local = (char *(*)(char *, struct svc_req *)) ypproc_match_2_svc; 270 break; 271 272 case YPPROC_FIRST: 273 xdr_argument = (xdrproc_t) xdr_ypreq_nokey; 274 xdr_result = (xdrproc_t) xdr_ypresp_key_val; 275 local = (char *(*)(char *, struct svc_req *)) ypproc_first_2_svc; 276 break; 277 278 case YPPROC_NEXT: 279 xdr_argument = (xdrproc_t) xdr_ypreq_key; 280 xdr_result = (xdrproc_t) xdr_ypresp_key_val; 281 local = (char *(*)(char *, struct svc_req *)) ypproc_next_2_svc; 282 break; 283 284 case YPPROC_XFR: 285 xdr_argument = (xdrproc_t) xdr_ypreq_xfr; 286 xdr_result = (xdrproc_t) xdr_ypresp_xfr; 287 local = (char *(*)(char *, struct svc_req *)) ypproc_xfr_2_svc; 288 break; 289 290 case YPPROC_CLEAR: 291 xdr_argument = (xdrproc_t) xdr_void; 292 xdr_result = (xdrproc_t) xdr_void; 293 local = (char *(*)(char *, struct svc_req *)) ypproc_clear_2_svc; 294 break; 295 296 case YPPROC_ALL: 297 xdr_argument = (xdrproc_t) xdr_ypreq_nokey; 298 xdr_result = (xdrproc_t) xdr_ypresp_all; 299 local = (char *(*)(char *, struct svc_req *)) ypproc_all_2_svc; 300 break; 301 302 case YPPROC_MASTER: 303 xdr_argument = (xdrproc_t) xdr_ypreq_nokey; 304 xdr_result = (xdrproc_t) xdr_ypresp_master; 305 local = (char *(*)(char *, struct svc_req *)) ypproc_master_2_svc; 306 break; 307 308 case YPPROC_ORDER: 309 xdr_argument = (xdrproc_t) xdr_ypreq_nokey; 310 xdr_result = (xdrproc_t) xdr_ypresp_order; 311 local = (char *(*)(char *, struct svc_req *)) ypproc_order_2_svc; 312 break; 313 314 case YPPROC_MAPLIST: 315 xdr_argument = (xdrproc_t) xdr_domainname; 316 xdr_result = (xdrproc_t) xdr_ypresp_maplist; 317 local = (char *(*)(char *, struct svc_req *)) ypproc_maplist_2_svc; 318 break; 319 320 default: 321 svcerr_noproc(transp); 322 _rpcsvcdirty = 0; 323 return; 324 } 325 (void) memset((char *)&argument, 0, sizeof (argument)); 326 if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) { 327 svcerr_decode(transp); 328 _rpcsvcdirty = 0; 329 return; 330 } 331 result = (*local)((char *)&argument, rqstp); 332 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { 333 svcerr_systemerr(transp); 334 } 335 if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) { 336 _msgout("unable to free arguments"); 337 exit(1); 338 } 339 _rpcsvcdirty = 0; 340 return; 341} 342 343int 344main (argc,argv) 345int argc; 346char *argv[]; 347{ 348 register SVCXPRT *transp = NULL; 349 int sock; 350 int proto = 0; 351 struct sockaddr_in saddr; 352 socklen_t asize = sizeof (saddr); 353 int usage = 0; 354 int xflag = 0; 355 int allowv1 = 0; 356 int ch; 357 extern char *optarg; 358 359 while ((ch = getopt(argc, argv, "1a:dx")) != -1) 360 switch (ch) { 361 case '1': 362 allowv1 = TRUE; 363 break; 364 case 'a': 365 aclfile = optarg; 366 break; 367 case 'd': 368 usedns = TRUE; 369 break; 370 case 'x': 371 xflag = TRUE; 372 break; 373 default: 374 usage++; 375 break; 376 } 377 378 if (usage) { 379 (void)fprintf(stderr,"usage: %s [-a aclfile] [-d] [-x]\n",progname); 380 exit(1); 381 } 382 383 if (geteuid() != 0) { 384 (void)fprintf(stderr,"%s: must be root to run.\n",progname); 385 exit(1); 386 } 387 388 if (aclfile != NULL) { 389 (void)yp_acl_init(aclfile); 390 } else { 391 (void)yp_acl_securenet(YP_SECURENET_FILE); 392 } 393 if (xflag) { 394 exit(1); 395 }; 396 397 if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { 398 socklen_t ssize = sizeof (int); 399 400 if (saddr.sin_family != AF_INET) 401 exit(1); 402 if (getsockopt(0, SOL_SOCKET, SO_TYPE, 403 (char *)&_rpcfdtype, &ssize) == -1) 404 exit(1); 405 sock = 0; 406 _rpcpmstart = 1; 407 proto = 0; 408 openlog("ypserv", LOG_PID, LOG_DAEMON); 409 } else { 410#ifndef __APPLE__ 411#ifndef RPC_SVC_FG 412 int size; 413 int pid, i; 414 415 pid = fork(); 416 if (pid < 0) { 417 perror("cannot fork"); 418 exit(1); 419 } 420 if (pid) 421 exit(0); 422 size = getdtablesize(); 423 for (i = 0; i < size; i++) 424 (void) close(i); 425 i = open("/dev/console", 2); 426 (void) dup2(i, 1); 427 (void) dup2(i, 2); 428 i = open("/dev/tty", 2); 429 if (i >= 0) { 430 (void) ioctl(i, TIOCNOTTY, (char *)NULL); 431 (void) close(i); 432 } 433 openlog("ypserv", LOG_PID, LOG_DAEMON); 434#endif 435#endif /* __APPLE__ */ 436 sock = RPC_ANYSOCK; 437 (void) pmap_unset(YPPROG, YPVERS); 438 (void) pmap_unset(YPPROG, YPOLDVERS); 439 } 440 441 ypopenlog(); /* open log file */ 442 ypdb_init(); /* init db stuff */ 443 444 chdir("/"); 445 446 (void)signal(SIGCHLD, sig_child); 447 (void)signal(SIGHUP, sig_hup); 448 { FILE *pidfile = fopen(YPSERV_PID_PATH, "w"); 449 if (pidfile != NULL) { 450 fprintf(pidfile, "%d\n", getpid()); 451 fclose(pidfile); 452 } 453 } 454 455 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { 456 transp = svcudp_create(sock); 457 if (transp == NULL) { 458 _msgout("cannot create udp service."); 459 exit(1); 460 } 461 if (transp->xp_port >= IPPORT_RESERVED) { 462 _msgout("cannot allocate udp privileged port."); 463 exit(1); 464 } 465 if (!_rpcpmstart) 466 proto = IPPROTO_UDP; 467 if (allowv1) { 468 if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) { 469 _msgout("unable to register (YPPROG, YPOLDVERS, udp)."); 470 exit(1); 471 } 472 } 473 if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) { 474 _msgout("unable to register (YPPROG, YPVERS, udp)."); 475 exit(1); 476 } 477 } 478 479 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { 480 if (_rpcpmstart) 481 transp = svcfd_create(sock, 0, 0); 482 else 483 transp = svctcp_create(sock, 0, 0); 484 if (transp == NULL) { 485 _msgout("cannot create tcp service."); 486 exit(1); 487 } 488 if (transp->xp_port >= IPPORT_RESERVED) { 489 _msgout("cannot allocate tcp privileged port."); 490 exit(1); 491 } 492 if (!_rpcpmstart) 493 proto = IPPROTO_TCP; 494 if (allowv1) { 495 if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) { 496 _msgout("unable to register (YPPROG, YPOLDVERS, tcp)."); 497 exit(1); 498 } 499 } 500 if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) { 501 _msgout("unable to register (YPPROG, YPVERS, tcp)."); 502 exit(1); 503 } 504 } 505 506 if (transp == (SVCXPRT *)NULL) { 507 _msgout("could not create a handle"); 508 exit(1); 509 } 510 if (_rpcpmstart) { 511 (void) signal(SIGALRM, (SIG_PF) closedown); 512 (void) alarm(_RPCSVC_CLOSEDOWN); 513 } 514 svc_run(); 515 _msgout("svc_run returned"); 516 exit(1); 517 /* NOTREACHED */ 518} 519 520void 521sig_child() 522{ 523 int save_errno = errno; 524 525 while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0) 526 ; 527 errno = save_errno; 528} 529 530void 531sig_hup() 532{ 533 yp_acl_reset(); 534 if (aclfile != NULL) { 535 yplog("sig_hup: reread %s",aclfile); 536 (void)yp_acl_init(aclfile); 537 } else { 538 yplog("sig_hup: reread %s",YP_SECURENET_FILE); 539 (void)yp_acl_securenet(YP_SECURENET_FILE); 540 } 541} 542