114062Swpaul/* 214062Swpaul * Copyright (c) 1995, 1996 314062Swpaul * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 414062Swpaul * 514062Swpaul * Redistribution and use in source and binary forms, with or without 614062Swpaul * modification, are permitted provided that the following conditions 714062Swpaul * are met: 814062Swpaul * 1. Redistributions of source code must retain the above copyright 914062Swpaul * notice, this list of conditions and the following disclaimer. 1014062Swpaul * 2. Redistributions in binary form must reproduce the above copyright 1114062Swpaul * notice, this list of conditions and the following disclaimer in the 1214062Swpaul * documentation and/or other materials provided with the distribution. 1314062Swpaul * 3. All advertising materials mentioning features or use of this software 1414062Swpaul * must display the following acknowledgement: 1514062Swpaul * This product includes software developed by Bill Paul. 1614062Swpaul * 4. Neither the name of the author nor the names of any co-contributors 1714062Swpaul * may be used to endorse or promote products derived from this software 1814062Swpaul * without specific prior written permission. 1914062Swpaul * 2014062Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2114062Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2214062Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2314062Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 2414062Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2514062Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2614062Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2714062Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2814062Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2914062Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3014062Swpaul * SUCH DAMAGE. 3114062Swpaul */ 3214062Swpaul 33114601Sobrien#include <sys/cdefs.h> 34114601Sobrien__FBSDID("$FreeBSD$"); 3530377Scharnier 3614062Swpaul#include <sys/param.h> 3714062Swpaul#include <sys/ioctl.h> 3814062Swpaul#include <sys/stat.h> 3914062Swpaul#include <sys/socket.h> 4096222Sdes#include <sys/time.h> 4196222Sdes#include <sys/resource.h> 4214062Swpaul#include <netinet/in.h> 4396222Sdes 4414062Swpaul#include <err.h> 4514062Swpaul#include <errno.h> 4696222Sdes#include <fcntl.h> 4796222Sdes#include <memory.h> 4896222Sdes#include <signal.h> 4996222Sdes#include <stdio.h> 5096222Sdes#include <stdlib.h> /* getenv, exit */ 5196222Sdes#include <string.h> /* strcmp */ 5296222Sdes#include <syslog.h> 5396222Sdes#include <unistd.h> 5496222Sdes 5596222Sdes#include <rpc/rpc.h> 56109363Smbr#include <rpc/rpc_com.h> 5796222Sdes#include <rpc/pmap_clnt.h> /* for pmap_unset */ 5814062Swpaul#include <rpcsvc/yp.h> 5914062Swpaul#include <rpcsvc/ypclnt.h> 6096222Sdes 6196222Sdes#include "yppasswd.h" 6214062Swpaul#include "yppasswdd_extern.h" 6327758Swpaul#include "yppasswd_private.h" 6414062Swpaul#include "ypxfr_extern.h" 6596222Sdes#include "yp_extern.h" 6614062Swpaul 6714062Swpaul#ifndef SIG_PF 6814062Swpaul#define SIG_PF void(*)(int) 6914062Swpaul#endif 7014062Swpaul 7114062Swpaul#ifdef DEBUG 7214062Swpaul#define RPC_SVC_FG 7314062Swpaul#endif 7414062Swpaul 7514062Swpaul#define _RPCSVC_CLOSEDOWN 120 7614062Swpaulint _rpcpmstart = 0; /* Started by a port monitor ? */ 7714062Swpaulstatic int _rpcfdtype; 7814062Swpaul /* Whether Stream or Datagram ? */ 7914062Swpaul /* States a server can be in wrt request */ 8014062Swpaul 8114062Swpaul#define _IDLE 0 8214062Swpaul#define _SERVED 1 8314062Swpaul#define _SERVING 2 8414062Swpaul 8596222Sdesstatic char _localhost[] = "localhost"; 8696222Sdesstatic char _passwd_byname[] = "passwd.byname"; 8714062Swpaulextern int _rpcsvcstate; /* Set when a request is serviced */ 8896222Sdesstatic char _progname[] = "rpc.yppasswdd"; 8996222Sdeschar *progname = _progname; 9096222Sdesstatic char _yp_dir[] = _PATH_YP; 9196222Sdeschar *yp_dir = _yp_dir; 9296222Sdesstatic char _passfile_default[] = _PATH_YP "master.passwd"; 9396222Sdeschar *passfile_default = _passfile_default; 9414062Swpaulchar *passfile; 9514062Swpaulchar *yppasswd_domain = NULL; 9614062Swpaulint no_chsh = 0; 9714062Swpaulint no_chfn = 0; 9814062Swpaulint allow_additions = 0; 9914062Swpaulint multidomain = 0; 10014062Swpaulint verbose = 0; 10114241Swpaulint resvport = 1; 10216134Swpaulint inplace = 0; 10396222Sdeschar sockname[] = YP_SOCKNAME; 10414062Swpaul 10590298Sdesstatic void 10696222Sdesterminate(int sig __unused) 10714062Swpaul{ 10890253Salfred rpcb_unset(YPPASSWDPROG, YPPASSWDVERS, NULL); 10990253Salfred rpcb_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, NULL); 11014062Swpaul unlink(sockname); 11114062Swpaul exit(0); 11214062Swpaul} 11314241Swpaul 11490298Sdesstatic void 11596222Sdesreload(int sig __unused) 11614241Swpaul{ 11714241Swpaul load_securenets(); 11814241Swpaul} 11914241Swpaul 12014062Swpaulstatic void 12196222Sdesclosedown(int sig __unused) 12214062Swpaul{ 12314062Swpaul if (_rpcsvcstate == _IDLE) { 12414062Swpaul extern fd_set svc_fdset; 12514062Swpaul static int size; 12614062Swpaul int i, openfd; 12714062Swpaul 12814062Swpaul if (_rpcfdtype == SOCK_DGRAM) { 12914062Swpaul unlink(sockname); 13014062Swpaul exit(0); 13114062Swpaul } 13214062Swpaul if (size == 0) { 13314062Swpaul size = getdtablesize(); 13414062Swpaul } 13514062Swpaul for (i = 0, openfd = 0; i < size && openfd < 2; i++) 13614062Swpaul if (FD_ISSET(i, &svc_fdset)) 13714062Swpaul openfd++; 13814062Swpaul if (openfd <= 1) { 13914062Swpaul unlink(sockname); 14014062Swpaul exit(0); 14114062Swpaul } 14214062Swpaul } 14314062Swpaul if (_rpcsvcstate == _SERVED) 14414062Swpaul _rpcsvcstate = _IDLE; 14514062Swpaul 14614062Swpaul (void) signal(SIGALRM, (SIG_PF) closedown); 14714062Swpaul (void) alarm(_RPCSVC_CLOSEDOWN/2); 14814062Swpaul} 14914062Swpaul 15090298Sdesstatic void 15190298Sdesusage(void) 15214062Swpaul{ 15330377Scharnier fprintf(stderr, "%s\n%s\n", 15430377Scharnier"usage: rpc.yppasswdd [-t master.passwd file] [-d domain] [-p path] [-s]", 15530377Scharnier" [-f] [-m] [-i] [-a] [-v] [-u] [-h]"); 15614062Swpaul exit(1); 15714062Swpaul} 15814062Swpaul 15919778Speterint 16090298Sdesmain(int argc, char *argv[]) 16114062Swpaul{ 16296222Sdes struct rlimit rlim; 16396222Sdes SVCXPRT *transp = NULL; 16414062Swpaul struct sockaddr_in saddr; 165145803Sdelphij socklen_t asize = sizeof (saddr); 16690253Salfred struct netconfig *nconf; 167184459Srafan struct sigaction sa; 16890253Salfred void *localhandle; 16914062Swpaul int ch; 17014062Swpaul char *mastername; 17114062Swpaul char myname[MAXHOSTNAMELEN + 2]; 172109363Smbr int maxrec = RPC_MAXDATASIZE; 17390253Salfred 17414062Swpaul extern int debug; 17514062Swpaul 17614062Swpaul debug = 1; 17714062Swpaul 17824428Simp while ((ch = getopt(argc, argv, "t:d:p:sfamuivh")) != -1) { 17990297Sdes switch (ch) { 18014062Swpaul case 't': 18114062Swpaul passfile_default = optarg; 18214062Swpaul break; 18314062Swpaul case 'd': 18414062Swpaul yppasswd_domain = optarg; 18514062Swpaul break; 18614062Swpaul case 's': 18714062Swpaul no_chsh++; 18814062Swpaul break; 18914062Swpaul case 'f': 19014062Swpaul no_chfn++; 19114062Swpaul break; 19214062Swpaul case 'p': 19314062Swpaul yp_dir = optarg; 19414062Swpaul break; 19514062Swpaul case 'a': 19614062Swpaul allow_additions++; 19714062Swpaul break; 19814062Swpaul case 'm': 19914062Swpaul multidomain++; 20014062Swpaul break; 20116134Swpaul case 'i': 20216134Swpaul inplace++; 20316134Swpaul break; 20414062Swpaul case 'v': 20514062Swpaul verbose++; 20614062Swpaul break; 20714241Swpaul case 'u': 20814241Swpaul resvport = 0; 20914241Swpaul break; 21014062Swpaul default: 21114062Swpaul case 'h': 21214062Swpaul usage(); 21314062Swpaul break; 21414062Swpaul } 21514062Swpaul } 21614062Swpaul 21714062Swpaul if (yppasswd_domain == NULL) { 21814062Swpaul if (yp_get_default_domain(&yppasswd_domain)) { 21914062Swpaul yp_error("no domain specified and system domain \ 22014062Swpaulname isn't set -- aborting"); 22114062Swpaul usage(); 22214062Swpaul } 22314062Swpaul } 22414062Swpaul 22514241Swpaul load_securenets(); 22614241Swpaul 22796222Sdes if (getrpcport(_localhost, YPPROG, YPVERS, IPPROTO_UDP) <= 0) { 22819130Swpaul yp_error("no ypserv processes registered with local portmap"); 22914062Swpaul yp_error("this host is not an NIS server -- aborting"); 23014062Swpaul exit(1); 23114062Swpaul } 23214062Swpaul 23396222Sdes if ((mastername = ypxfr_get_master(yppasswd_domain, 23496222Sdes _passwd_byname, _localhost, 0)) == NULL) { 23519130Swpaul yp_error("can't get name of NIS master server for domain %s", 23619130Swpaul yppasswd_domain); 23714062Swpaul exit(1); 23814062Swpaul } 23914062Swpaul 24014062Swpaul if (gethostname((char *)&myname, sizeof(myname)) == -1) { 24114062Swpaul yp_error("can't get local hostname: %s", strerror(errno)); 24214062Swpaul exit(1); 24314062Swpaul } 24414062Swpaul 24544791Sbrian if (strncasecmp(mastername, (char *)&myname, sizeof(myname))) { 24619130Swpaul yp_error("master of %s is %s, but we are %s", 24719130Swpaul "passwd.byname", mastername, myname); 24819130Swpaul yp_error("this host is not the NIS master server for \ 24919130Swpaulthe %s domain -- aborting", yppasswd_domain); 25014062Swpaul exit(1); 25114062Swpaul } 25214062Swpaul 25314241Swpaul debug = 0; 25414241Swpaul 25514062Swpaul if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { 256145803Sdelphij socklen_t ssize = sizeof (int); 25714062Swpaul if (saddr.sin_family != AF_INET) 25814062Swpaul exit(1); 25914062Swpaul if (getsockopt(0, SOL_SOCKET, SO_TYPE, 26090253Salfred (char *)&_rpcfdtype, &ssize) == -1) 26114062Swpaul exit(1); 26214062Swpaul _rpcpmstart = 1; 26314062Swpaul } 26414062Swpaul 26590253Salfred if (!debug && _rpcpmstart == 0) { 26690253Salfred if (daemon(0,0)) { 26790253Salfred err(1,"cannot fork"); 26814062Swpaul } 26914062Swpaul } 27090253Salfred openlog("rpc.yppasswdd", LOG_PID, LOG_DAEMON); 271184459Srafan memset(&sa, 0, sizeof(sa)); 272184459Srafan sa.sa_flags = SA_NOCLDWAIT; 273184459Srafan sigaction(SIGCHLD, &sa, NULL); 27414062Swpaul 27590253Salfred rpcb_unset(YPPASSWDPROG, YPPASSWDVERS, NULL); 27690253Salfred rpcb_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, NULL); 27790253Salfred 278109363Smbr rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); 279109363Smbr 28090253Salfred if (svc_create(yppasswdprog_1, YPPASSWDPROG, YPPASSWDVERS, "netpath") == 0) { 28190253Salfred yp_error("cannot create yppasswd service."); 28290253Salfred exit(1); 28314062Swpaul } 28490253Salfred if (svc_create(master_yppasswdprog_1, MASTER_YPPASSWDPROG, 28590253Salfred MASTER_YPPASSWDVERS, "netpath") == 0) { 28690253Salfred yp_error("cannot create master_yppasswd service."); 28790253Salfred exit(1); 28890253Salfred } 28914062Swpaul 29090253Salfred nconf = NULL; 29190253Salfred localhandle = setnetconfig(); 29290253Salfred while ((nconf = getnetconfig(localhandle)) != NULL) { 29390253Salfred if (nconf->nc_protofmly != NULL && 29490253Salfred strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) 29590253Salfred break; 29690253Salfred } 29790253Salfred if (nconf == NULL) { 29890253Salfred yp_error("getnetconfigent unix: %s", nc_sperror()); 29990253Salfred exit(1); 30090253Salfred } 30127758Swpaul unlink(sockname); 30290253Salfred transp = svcunix_create(RPC_ANYSOCK, 0, 0, sockname); 30327758Swpaul if (transp == NULL) { 30427758Swpaul yp_error("cannot create AF_LOCAL service."); 30527758Swpaul exit(1); 30627758Swpaul } 30790253Salfred if (!svc_reg(transp, MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, 30890253Salfred master_yppasswdprog_1, nconf)) { 30996391Salfred yp_error("unable to register (MASTER_YPPASSWDPROG, \ 31090253Salfred MASTER_YPPASSWDVERS, unix)."); 31127758Swpaul exit(1); 31227758Swpaul } 31390253Salfred endnetconfig(localhandle); 31490253Salfred 31527758Swpaul /* Only root may connect() to the AF_UNIX link. */ 31627758Swpaul if (chmod(sockname, 0)) 31727758Swpaul err(1, "chmod of %s failed", sockname); 31827758Swpaul 31914062Swpaul if (transp == (SVCXPRT *)NULL) { 32014062Swpaul yp_error("could not create a handle"); 32114062Swpaul exit(1); 32214062Swpaul } 32314062Swpaul if (_rpcpmstart) { 32414062Swpaul (void) signal(SIGALRM, (SIG_PF) closedown); 32514062Swpaul (void) alarm(_RPCSVC_CLOSEDOWN/2); 32614062Swpaul } 32714062Swpaul 32896222Sdes /* Unlimited resource limits. */ 32996222Sdes rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; 33096222Sdes (void)setrlimit(RLIMIT_CPU, &rlim); 33196222Sdes (void)setrlimit(RLIMIT_FSIZE, &rlim); 33296222Sdes (void)setrlimit(RLIMIT_STACK, &rlim); 33396222Sdes (void)setrlimit(RLIMIT_DATA, &rlim); 33496222Sdes (void)setrlimit(RLIMIT_RSS, &rlim); 33514062Swpaul 33696222Sdes /* Don't drop core (not really necessary, but GP's). */ 33796222Sdes rlim.rlim_cur = rlim.rlim_max = 0; 33896222Sdes (void)setrlimit(RLIMIT_CORE, &rlim); 33914241Swpaul 34096222Sdes /* Turn off signals. */ 34196222Sdes (void)signal(SIGALRM, SIG_IGN); 34296222Sdes (void)signal(SIGHUP, (SIG_PF) reload); 34396222Sdes (void)signal(SIGINT, SIG_IGN); 34496222Sdes (void)signal(SIGPIPE, SIG_IGN); 34596222Sdes (void)signal(SIGQUIT, SIG_IGN); 34696222Sdes (void)signal(SIGTERM, (SIG_PF) terminate); 34796222Sdes 34827758Swpaul svc_run(); 34914062Swpaul yp_error("svc_run returned"); 35014062Swpaul exit(1); 35114062Swpaul /* NOTREACHED */ 35214062Swpaul} 353