yppasswdd_main.c revision 96391
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
3330377Scharnier#ifndef lint
3430377Scharnierstatic const char rcsid[] =
3550479Speter  "$FreeBSD: head/usr.sbin/rpc.yppasswdd/yppasswdd_main.c 96391 2002-05-11 04:10:49Z alfred $";
3630377Scharnier#endif /* not lint */
3730377Scharnier
3814062Swpaul#include <sys/param.h>
3914062Swpaul#include <sys/ioctl.h>
4014062Swpaul#include <sys/stat.h>
4114062Swpaul#include <sys/socket.h>
4296222Sdes#include <sys/time.h>
4396222Sdes#include <sys/resource.h>
4414062Swpaul#include <netinet/in.h>
4596222Sdes
4614062Swpaul#include <err.h>
4714062Swpaul#include <errno.h>
4896222Sdes#include <fcntl.h>
4996222Sdes#include <memory.h>
5096222Sdes#include <signal.h>
5196222Sdes#include <stdio.h>
5296222Sdes#include <stdlib.h> /* getenv, exit */
5396222Sdes#include <string.h>
5496222Sdes#include <string.h> /* strcmp */
5596222Sdes#include <syslog.h>
5696222Sdes#include <unistd.h>
5796222Sdes
5896222Sdes#include <rpc/rpc.h>
5996222Sdes#include <rpc/pmap_clnt.h> /* for pmap_unset */
6014062Swpaul#include <rpcsvc/yp.h>
6114062Swpaulstruct dom_binding {};
6214062Swpaul#include <rpcsvc/ypclnt.h>
6396222Sdes
6496222Sdes#include "yppasswd.h"
6514062Swpaul#include "yppasswdd_extern.h"
6627758Swpaul#include "yppasswd_private.h"
6714062Swpaul#include "ypxfr_extern.h"
6896222Sdes#include "yp_extern.h"
6914062Swpaul
7014062Swpaul#ifndef SIG_PF
7114062Swpaul#define	SIG_PF void(*)(int)
7214062Swpaul#endif
7314062Swpaul
7414062Swpaul#ifdef DEBUG
7514062Swpaul#define	RPC_SVC_FG
7614062Swpaul#endif
7714062Swpaul
7814062Swpaul#define	_RPCSVC_CLOSEDOWN 120
7914062Swpaulint _rpcpmstart = 0;		/* Started by a port monitor ? */
8014062Swpaulstatic int _rpcfdtype;
8114062Swpaul		 /* Whether Stream or Datagram ? */
8214062Swpaul	/* States a server can be in wrt request */
8314062Swpaul
8414062Swpaul#define	_IDLE 0
8514062Swpaul#define	_SERVED 1
8614062Swpaul#define	_SERVING 2
8714062Swpaul
8896222Sdesstatic char _localhost[] = "localhost";
8996222Sdesstatic char _passwd_byname[] = "passwd.byname";
9014062Swpaulextern int _rpcsvcstate;	 /* Set when a request is serviced */
9196222Sdesstatic char _progname[] = "rpc.yppasswdd";
9296222Sdeschar *progname = _progname;
9396222Sdesstatic char _yp_dir[] = _PATH_YP;
9496222Sdeschar *yp_dir = _yp_dir;
9596222Sdesstatic char _passfile_default[] = _PATH_YP "master.passwd";
9696222Sdeschar *passfile_default = _passfile_default;
9714062Swpaulchar *passfile;
9814062Swpaulchar *yppasswd_domain = NULL;
9914062Swpaulint no_chsh = 0;
10014062Swpaulint no_chfn = 0;
10114062Swpaulint allow_additions = 0;
10214062Swpaulint multidomain = 0;
10314062Swpaulint verbose = 0;
10414241Swpaulint resvport = 1;
10516134Swpaulint inplace = 0;
10696222Sdeschar sockname[] = YP_SOCKNAME;
10714062Swpaul
10890298Sdesstatic void
10996222Sdesterminate(int sig __unused)
11014062Swpaul{
11190253Salfred	rpcb_unset(YPPASSWDPROG, YPPASSWDVERS, NULL);
11290253Salfred	rpcb_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, NULL);
11314062Swpaul	unlink(sockname);
11414062Swpaul	exit(0);
11514062Swpaul}
11614241Swpaul
11790298Sdesstatic void
11896222Sdesreload(int sig __unused)
11914241Swpaul{
12014241Swpaul	load_securenets();
12114241Swpaul}
12214241Swpaul
12314062Swpaulstatic void
12496222Sdesclosedown(int sig __unused)
12514062Swpaul{
12614062Swpaul	if (_rpcsvcstate == _IDLE) {
12714062Swpaul		extern fd_set svc_fdset;
12814062Swpaul		static int size;
12914062Swpaul		int i, openfd;
13014062Swpaul
13114062Swpaul		if (_rpcfdtype == SOCK_DGRAM) {
13214062Swpaul			unlink(sockname);
13314062Swpaul			exit(0);
13414062Swpaul		}
13514062Swpaul		if (size == 0) {
13614062Swpaul			size = getdtablesize();
13714062Swpaul		}
13814062Swpaul		for (i = 0, openfd = 0; i < size && openfd < 2; i++)
13914062Swpaul			if (FD_ISSET(i, &svc_fdset))
14014062Swpaul				openfd++;
14114062Swpaul		if (openfd <= 1) {
14214062Swpaul			unlink(sockname);
14314062Swpaul			exit(0);
14414062Swpaul		}
14514062Swpaul	}
14614062Swpaul	if (_rpcsvcstate == _SERVED)
14714062Swpaul		_rpcsvcstate = _IDLE;
14814062Swpaul
14914062Swpaul	(void) signal(SIGALRM, (SIG_PF) closedown);
15014062Swpaul	(void) alarm(_RPCSVC_CLOSEDOWN/2);
15114062Swpaul}
15214062Swpaul
15390298Sdesstatic void
15490298Sdesusage(void)
15514062Swpaul{
15630377Scharnier	fprintf(stderr, "%s\n%s\n",
15730377Scharnier"usage: rpc.yppasswdd [-t master.passwd file] [-d domain] [-p path] [-s]",
15830377Scharnier"                     [-f] [-m] [-i] [-a] [-v] [-u] [-h]");
15914062Swpaul	exit(1);
16014062Swpaul}
16114062Swpaul
16219778Speterint
16390298Sdesmain(int argc, char *argv[])
16414062Swpaul{
16596222Sdes	struct rlimit rlim;
16696222Sdes	SVCXPRT *transp = NULL;
16714062Swpaul	struct sockaddr_in saddr;
16814062Swpaul	int asize = sizeof (saddr);
16990253Salfred	struct netconfig *nconf;
17090253Salfred	void *localhandle;
17114062Swpaul	int ch;
17214062Swpaul	char *mastername;
17314062Swpaul	char myname[MAXHOSTNAMELEN + 2];
17490253Salfred
17514062Swpaul	extern int debug;
17614062Swpaul
17714062Swpaul	debug = 1;
17814062Swpaul
17924428Simp	while ((ch = getopt(argc, argv, "t:d:p:sfamuivh")) != -1) {
18090297Sdes		switch (ch) {
18114062Swpaul		case 't':
18214062Swpaul			passfile_default = optarg;
18314062Swpaul			break;
18414062Swpaul		case 'd':
18514062Swpaul			yppasswd_domain = optarg;
18614062Swpaul			break;
18714062Swpaul		case 's':
18814062Swpaul			no_chsh++;
18914062Swpaul			break;
19014062Swpaul		case 'f':
19114062Swpaul			no_chfn++;
19214062Swpaul			break;
19314062Swpaul		case 'p':
19414062Swpaul			yp_dir = optarg;
19514062Swpaul			break;
19614062Swpaul		case 'a':
19714062Swpaul			allow_additions++;
19814062Swpaul			break;
19914062Swpaul		case 'm':
20014062Swpaul			multidomain++;
20114062Swpaul			break;
20216134Swpaul		case 'i':
20316134Swpaul			inplace++;
20416134Swpaul			break;
20514062Swpaul		case 'v':
20614062Swpaul			verbose++;
20714062Swpaul			break;
20814241Swpaul		case 'u':
20914241Swpaul			resvport = 0;
21014241Swpaul			break;
21114062Swpaul		default:
21214062Swpaul		case 'h':
21314062Swpaul			usage();
21414062Swpaul			break;
21514062Swpaul		}
21614062Swpaul	}
21714062Swpaul
21814062Swpaul	if (yppasswd_domain == NULL) {
21914062Swpaul		if (yp_get_default_domain(&yppasswd_domain)) {
22014062Swpaul			yp_error("no domain specified and system domain \
22114062Swpaulname isn't set -- aborting");
22214062Swpaul		usage();
22314062Swpaul		}
22414062Swpaul	}
22514062Swpaul
22614241Swpaul	load_securenets();
22714241Swpaul
22896222Sdes	if (getrpcport(_localhost, YPPROG, YPVERS, IPPROTO_UDP) <= 0) {
22919130Swpaul		yp_error("no ypserv processes registered with local portmap");
23014062Swpaul		yp_error("this host is not an NIS server -- aborting");
23114062Swpaul		exit(1);
23214062Swpaul	}
23314062Swpaul
23496222Sdes	if ((mastername = ypxfr_get_master(yppasswd_domain,
23596222Sdes		 _passwd_byname, _localhost, 0)) == NULL) {
23619130Swpaul		yp_error("can't get name of NIS master server for domain %s",
23719130Swpaul			 				yppasswd_domain);
23814062Swpaul		exit(1);
23914062Swpaul	}
24014062Swpaul
24114062Swpaul	if (gethostname((char *)&myname, sizeof(myname)) == -1) {
24214062Swpaul		yp_error("can't get local hostname: %s", strerror(errno));
24314062Swpaul		exit(1);
24414062Swpaul	}
24514062Swpaul
24644791Sbrian	if (strncasecmp(mastername, (char *)&myname, sizeof(myname))) {
24719130Swpaul		yp_error("master of %s is %s, but we are %s",
24819130Swpaul			"passwd.byname", mastername, myname);
24919130Swpaul		yp_error("this host is not the NIS master server for \
25019130Swpaulthe %s domain -- aborting", yppasswd_domain);
25114062Swpaul		exit(1);
25214062Swpaul	}
25314062Swpaul
25414241Swpaul	debug = 0;
25514241Swpaul
25614062Swpaul	if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {
25714062Swpaul		int ssize = sizeof (int);
25814062Swpaul		if (saddr.sin_family != AF_INET)
25914062Swpaul			exit(1);
26014062Swpaul		if (getsockopt(0, SOL_SOCKET, SO_TYPE,
26190253Salfred		    (char *)&_rpcfdtype, &ssize) == -1)
26214062Swpaul			exit(1);
26314062Swpaul		_rpcpmstart = 1;
26414062Swpaul	}
26514062Swpaul
26690253Salfred	if (!debug && _rpcpmstart == 0) {
26790253Salfred		if (daemon(0,0)) {
26890253Salfred			err(1,"cannot fork");
26914062Swpaul		}
27014062Swpaul	}
27190253Salfred	openlog("rpc.yppasswdd", LOG_PID, LOG_DAEMON);
27214062Swpaul
27390253Salfred	rpcb_unset(YPPASSWDPROG, YPPASSWDVERS, NULL);
27490253Salfred	rpcb_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, NULL);
27590253Salfred
27690253Salfred	if (svc_create(yppasswdprog_1, YPPASSWDPROG, YPPASSWDVERS, "netpath") == 0) {
27790253Salfred		yp_error("cannot create yppasswd service.");
27890253Salfred		exit(1);
27914062Swpaul	}
28090253Salfred	if (svc_create(master_yppasswdprog_1, MASTER_YPPASSWDPROG,
28190253Salfred	    MASTER_YPPASSWDVERS, "netpath") == 0) {
28290253Salfred		yp_error("cannot create master_yppasswd service.");
28390253Salfred		exit(1);
28490253Salfred	}
28514062Swpaul
28690253Salfred	nconf = NULL;
28790253Salfred	localhandle = setnetconfig();
28890253Salfred	while ((nconf = getnetconfig(localhandle)) != NULL) {
28990253Salfred		if (nconf->nc_protofmly != NULL &&
29090253Salfred		    strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
29190253Salfred			break;
29290253Salfred	}
29390253Salfred	if (nconf == NULL) {
29490253Salfred		yp_error("getnetconfigent unix: %s", nc_sperror());
29590253Salfred		exit(1);
29690253Salfred	}
29727758Swpaul	unlink(sockname);
29890253Salfred	transp = svcunix_create(RPC_ANYSOCK, 0, 0, sockname);
29927758Swpaul	if (transp == NULL) {
30027758Swpaul		yp_error("cannot create AF_LOCAL service.");
30127758Swpaul		exit(1);
30227758Swpaul	}
30390253Salfred	if (!svc_reg(transp, MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS,
30490253Salfred	    master_yppasswdprog_1, nconf)) {
30596391Salfred		yp_error("unable to register (MASTER_YPPASSWDPROG, \
30690253Salfred		    MASTER_YPPASSWDVERS, unix).");
30727758Swpaul		exit(1);
30827758Swpaul	}
30990253Salfred	endnetconfig(localhandle);
31090253Salfred
31127758Swpaul	/* Only root may connect() to the AF_UNIX link. */
31227758Swpaul	if (chmod(sockname, 0))
31327758Swpaul		err(1, "chmod of %s failed", sockname);
31427758Swpaul
31514062Swpaul	if (transp == (SVCXPRT *)NULL) {
31614062Swpaul		yp_error("could not create a handle");
31714062Swpaul		exit(1);
31814062Swpaul	}
31914062Swpaul	if (_rpcpmstart) {
32014062Swpaul		(void) signal(SIGALRM, (SIG_PF) closedown);
32114062Swpaul		(void) alarm(_RPCSVC_CLOSEDOWN/2);
32214062Swpaul	}
32314062Swpaul
32496222Sdes	/* Unlimited resource limits. */
32596222Sdes	rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
32696222Sdes	(void)setrlimit(RLIMIT_CPU, &rlim);
32796222Sdes	(void)setrlimit(RLIMIT_FSIZE, &rlim);
32896222Sdes	(void)setrlimit(RLIMIT_STACK, &rlim);
32996222Sdes	(void)setrlimit(RLIMIT_DATA, &rlim);
33096222Sdes	(void)setrlimit(RLIMIT_RSS, &rlim);
33114062Swpaul
33296222Sdes	/* Don't drop core (not really necessary, but GP's). */
33396222Sdes	rlim.rlim_cur = rlim.rlim_max = 0;
33496222Sdes	(void)setrlimit(RLIMIT_CORE, &rlim);
33514241Swpaul
33696222Sdes	/* Turn off signals. */
33796222Sdes	(void)signal(SIGALRM, SIG_IGN);
33896222Sdes	(void)signal(SIGHUP, (SIG_PF) reload);
33996222Sdes	(void)signal(SIGINT, SIG_IGN);
34096222Sdes	(void)signal(SIGPIPE, SIG_IGN);
34196222Sdes	(void)signal(SIGQUIT, SIG_IGN);
34296222Sdes	(void)signal(SIGTERM, (SIG_PF) terminate);
34396222Sdes
34427758Swpaul	svc_run();
34514062Swpaul	yp_error("svc_run returned");
34614062Swpaul	exit(1);
34714062Swpaul	/* NOTREACHED */
34814062Swpaul}
349