yppasswdd_main.c revision 184459
1195609Smp/*
259243Sobrien * Copyright (c) 1995, 1996
359243Sobrien *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
459243Sobrien *
559243Sobrien * Redistribution and use in source and binary forms, with or without
659243Sobrien * modification, are permitted provided that the following conditions
759243Sobrien * are met:
859243Sobrien * 1. Redistributions of source code must retain the above copyright
959243Sobrien *    notice, this list of conditions and the following disclaimer.
1059243Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1159243Sobrien *    notice, this list of conditions and the following disclaimer in the
1259243Sobrien *    documentation and/or other materials provided with the distribution.
1359243Sobrien * 3. All advertising materials mentioning features or use of this software
1459243Sobrien *    must display the following acknowledgement:
1559243Sobrien *	This product includes software developed by Bill Paul.
1659243Sobrien * 4. Neither the name of the author nor the names of any co-contributors
1759243Sobrien *    may be used to endorse or promote products derived from this software
18100616Smp *    without specific prior written permission.
1959243Sobrien *
2059243Sobrien * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
2159243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2259243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2359243Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
2459243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2559243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2659243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2759243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2859243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2959243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3059243Sobrien * SUCH DAMAGE.
3159243Sobrien */
3259243Sobrien
3359243Sobrien#include <sys/cdefs.h>
3459243Sobrien__FBSDID("$FreeBSD: head/usr.sbin/rpc.yppasswdd/yppasswdd_main.c 184459 2008-10-30 01:54:31Z rafan $");
3559243Sobrien
3659243Sobrien#include <sys/param.h>
3759243Sobrien#include <sys/ioctl.h>
3859243Sobrien#include <sys/stat.h>
3959243Sobrien#include <sys/socket.h>
40167465Smp#include <sys/time.h>
41145479Smp#include <sys/resource.h>
42145479Smp#include <netinet/in.h>
43145479Smp
44145479Smp#include <err.h>
45145479Smp#include <errno.h>
46145479Smp#include <fcntl.h>
4759243Sobrien#include <memory.h>
4859243Sobrien#include <signal.h>
4959243Sobrien#include <stdio.h>
5059243Sobrien#include <stdlib.h> /* getenv, exit */
5159243Sobrien#include <string.h>
5259243Sobrien#include <string.h> /* strcmp */
5359243Sobrien#include <syslog.h>
5459243Sobrien#include <unistd.h>
5559243Sobrien
5659243Sobrien#include <rpc/rpc.h>
5759243Sobrien#include <rpc/rpc_com.h>
5859243Sobrien#include <rpc/pmap_clnt.h> /* for pmap_unset */
5959243Sobrien#include <rpcsvc/yp.h>
6059243Sobrien#include <rpcsvc/ypclnt.h>
6159243Sobrien
6259243Sobrien#include "yppasswd.h"
6383098Smp#include "yppasswdd_extern.h"
64100616Smp#include "yppasswd_private.h"
6559243Sobrien#include "ypxfr_extern.h"
6659243Sobrien#include "yp_extern.h"
67195609Smp
6859243Sobrien#ifndef SIG_PF
69195609Smp#define	SIG_PF void(*)(int)
7059243Sobrien#endif
7159243Sobrien
7259243Sobrien#ifdef DEBUG
7359243Sobrien#define	RPC_SVC_FG
7459243Sobrien#endif
7559243Sobrien
7659243Sobrien#define	_RPCSVC_CLOSEDOWN 120
77195609Smpint _rpcpmstart = 0;		/* Started by a port monitor ? */
78195609Smpstatic int _rpcfdtype;
7959243Sobrien		 /* Whether Stream or Datagram ? */
80195609Smp	/* States a server can be in wrt request */
8159243Sobrien
82195609Smp#define	_IDLE 0
8359243Sobrien#define	_SERVED 1
84195609Smp#define	_SERVING 2
85195609Smp
86195609Smpstatic char _localhost[] = "localhost";
87195609Smpstatic char _passwd_byname[] = "passwd.byname";
88195609Smpextern int _rpcsvcstate;	 /* Set when a request is serviced */
89195609Smpstatic char _progname[] = "rpc.yppasswdd";
90195609Smpchar *progname = _progname;
91195609Smpstatic char _yp_dir[] = _PATH_YP;
92195609Smpchar *yp_dir = _yp_dir;
9359243Sobrienstatic char _passfile_default[] = _PATH_YP "master.passwd";
94195609Smpchar *passfile_default = _passfile_default;
9559243Sobrienchar *passfile;
96195609Smpchar *yppasswd_domain = NULL;
9759243Sobrienint no_chsh = 0;
98195609Smpint no_chfn = 0;
9959243Sobrienint allow_additions = 0;
100195609Smpint multidomain = 0;
10159243Sobrienint verbose = 0;
102195609Smpint resvport = 1;
10359243Sobrienint inplace = 0;
104195609Smpchar sockname[] = YP_SOCKNAME;
105145479Smp
106195609Smpstatic void
107195609Smpterminate(int sig __unused)
108145479Smp{
109195609Smp	rpcb_unset(YPPASSWDPROG, YPPASSWDVERS, NULL);
110195609Smp	rpcb_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, NULL);
111195609Smp	unlink(sockname);
112195609Smp	exit(0);
113195609Smp}
114145479Smp
115195609Smpstatic void
116195609Smpreload(int sig __unused)
11759243Sobrien{
118195609Smp	load_securenets();
119195609Smp}
120195609Smp
121195609Smpstatic void
122195609Smpclosedown(int sig __unused)
12359243Sobrien{
124195609Smp	if (_rpcsvcstate == _IDLE) {
12559243Sobrien		extern fd_set svc_fdset;
126195609Smp		static int size;
12759243Sobrien		int i, openfd;
12859243Sobrien
129145479Smp		if (_rpcfdtype == SOCK_DGRAM) {
130167465Smp			unlink(sockname);
131167465Smp			exit(0);
132145479Smp		}
133145479Smp		if (size == 0) {
13459243Sobrien			size = getdtablesize();
135145479Smp		}
136145479Smp		for (i = 0, openfd = 0; i < size && openfd < 2; i++)
13769408Sache			if (FD_ISSET(i, &svc_fdset))
138145479Smp				openfd++;
139145479Smp		if (openfd <= 1) {
140145479Smp			unlink(sockname);
14159243Sobrien			exit(0);
14259243Sobrien		}
143167465Smp	}
14459243Sobrien	if (_rpcsvcstate == _SERVED)
14559243Sobrien		_rpcsvcstate = _IDLE;
14659243Sobrien
14759243Sobrien	(void) signal(SIGALRM, (SIG_PF) closedown);
148167465Smp	(void) alarm(_RPCSVC_CLOSEDOWN/2);
149145479Smp}
15059243Sobrien
151145479Smpstatic void
152145479Smpusage(void)
153167465Smp{
154167465Smp	fprintf(stderr, "%s\n%s\n",
155145479Smp"usage: rpc.yppasswdd [-t master.passwd file] [-d domain] [-p path] [-s]",
15669408Sache"                     [-f] [-m] [-i] [-a] [-v] [-u] [-h]");
157167465Smp	exit(1);
158167465Smp}
159145479Smp
160145479Smpint
161145479Smpmain(int argc, char *argv[])
162167465Smp{
163167465Smp	struct rlimit rlim;
16469408Sache	SVCXPRT *transp = NULL;
16559243Sobrien	struct sockaddr_in saddr;
166167465Smp	socklen_t asize = sizeof (saddr);
167167465Smp	struct netconfig *nconf;
168167465Smp	struct sigaction sa;
169167465Smp	void *localhandle;
170145479Smp	int ch;
171145479Smp	char *mastername;
172145479Smp	char myname[MAXHOSTNAMELEN + 2];
173145479Smp	int maxrec = RPC_MAXDATASIZE;
174145479Smp
175145479Smp	extern int debug;
176145479Smp
177195609Smp	debug = 1;
178195609Smp
179145479Smp	while ((ch = getopt(argc, argv, "t:d:p:sfamuivh")) != -1) {
180195609Smp		switch (ch) {
181195609Smp		case 't':
182195609Smp			passfile_default = optarg;
183145479Smp			break;
18459243Sobrien		case 'd':
18559243Sobrien			yppasswd_domain = optarg;
18659243Sobrien			break;
18759243Sobrien		case 's':
18859243Sobrien			no_chsh++;
18959243Sobrien			break;
190145479Smp		case 'f':
191145479Smp			no_chfn++;
192145479Smp			break;
193145479Smp		case 'p':
194145479Smp			yp_dir = optarg;
195145479Smp			break;
196145479Smp		case 'a':
197145479Smp			allow_additions++;
198145479Smp			break;
199145479Smp		case 'm':
200145479Smp			multidomain++;
201145479Smp			break;
202145479Smp		case 'i':
203145479Smp			inplace++;
20459243Sobrien			break;
20559243Sobrien		case 'v':
20659243Sobrien			verbose++;
20759243Sobrien			break;
20859243Sobrien		case 'u':
20959243Sobrien			resvport = 0;
21059243Sobrien			break;
21159243Sobrien		default:
21259243Sobrien		case 'h':
21359243Sobrien			usage();
21459243Sobrien			break;
21559243Sobrien		}
21659243Sobrien	}
21759243Sobrien
21859243Sobrien	if (yppasswd_domain == NULL) {
21959243Sobrien		if (yp_get_default_domain(&yppasswd_domain)) {
22059243Sobrien			yp_error("no domain specified and system domain \
22159243Sobrienname isn't set -- aborting");
22259243Sobrien		usage();
22359243Sobrien		}
22469408Sache	}
22559243Sobrien
22659243Sobrien	load_securenets();
22759243Sobrien
22859243Sobrien	if (getrpcport(_localhost, YPPROG, YPVERS, IPPROTO_UDP) <= 0) {
22959243Sobrien		yp_error("no ypserv processes registered with local portmap");
23059243Sobrien		yp_error("this host is not an NIS server -- aborting");
23159243Sobrien		exit(1);
23259243Sobrien	}
23359243Sobrien
23459243Sobrien	if ((mastername = ypxfr_get_master(yppasswd_domain,
23559243Sobrien		 _passwd_byname, _localhost, 0)) == NULL) {
23659243Sobrien		yp_error("can't get name of NIS master server for domain %s",
23759243Sobrien			 				yppasswd_domain);
23859243Sobrien		exit(1);
23959243Sobrien	}
24059243Sobrien
24159243Sobrien	if (gethostname((char *)&myname, sizeof(myname)) == -1) {
24259243Sobrien		yp_error("can't get local hostname: %s", strerror(errno));
24359243Sobrien		exit(1);
24459243Sobrien	}
24559243Sobrien
24659243Sobrien	if (strncasecmp(mastername, (char *)&myname, sizeof(myname))) {
24759243Sobrien		yp_error("master of %s is %s, but we are %s",
24859243Sobrien			"passwd.byname", mastername, myname);
24959243Sobrien		yp_error("this host is not the NIS master server for \
25059243Sobrienthe %s domain -- aborting", yppasswd_domain);
25159243Sobrien		exit(1);
25259243Sobrien	}
25359243Sobrien
25459243Sobrien	debug = 0;
25559243Sobrien
25659243Sobrien	if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {
25759243Sobrien		socklen_t ssize = sizeof (int);
25859243Sobrien		if (saddr.sin_family != AF_INET)
25959243Sobrien			exit(1);
26059243Sobrien		if (getsockopt(0, SOL_SOCKET, SO_TYPE,
26159243Sobrien		    (char *)&_rpcfdtype, &ssize) == -1)
26259243Sobrien			exit(1);
26359243Sobrien		_rpcpmstart = 1;
26459243Sobrien	}
26569408Sache
26659243Sobrien	if (!debug && _rpcpmstart == 0) {
26759243Sobrien		if (daemon(0,0)) {
26859243Sobrien			err(1,"cannot fork");
26959243Sobrien		}
27059243Sobrien	}
27159243Sobrien	openlog("rpc.yppasswdd", LOG_PID, LOG_DAEMON);
27259243Sobrien	memset(&sa, 0, sizeof(sa));
27359243Sobrien	sa.sa_flags = SA_NOCLDWAIT;
27459243Sobrien	sigaction(SIGCHLD, &sa, NULL);
27559243Sobrien
27659243Sobrien	rpcb_unset(YPPASSWDPROG, YPPASSWDVERS, NULL);
27759243Sobrien	rpcb_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, NULL);
27859243Sobrien
27959243Sobrien	rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
28059243Sobrien
28159243Sobrien	if (svc_create(yppasswdprog_1, YPPASSWDPROG, YPPASSWDVERS, "netpath") == 0) {
28259243Sobrien		yp_error("cannot create yppasswd service.");
28359243Sobrien		exit(1);
28459243Sobrien	}
28569408Sache	if (svc_create(master_yppasswdprog_1, MASTER_YPPASSWDPROG,
28659243Sobrien	    MASTER_YPPASSWDVERS, "netpath") == 0) {
28759243Sobrien		yp_error("cannot create master_yppasswd service.");
288167465Smp		exit(1);
289167465Smp	}
290167465Smp
291167465Smp	nconf = NULL;
292167465Smp	localhandle = setnetconfig();
293145479Smp	while ((nconf = getnetconfig(localhandle)) != NULL) {
294145479Smp		if (nconf->nc_protofmly != NULL &&
295167465Smp		    strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
296167465Smp			break;
29759243Sobrien	}
298167465Smp	if (nconf == NULL) {
29959243Sobrien		yp_error("getnetconfigent unix: %s", nc_sperror());
300167465Smp		exit(1);
30159243Sobrien	}
30259243Sobrien	unlink(sockname);
303167465Smp	transp = svcunix_create(RPC_ANYSOCK, 0, 0, sockname);
304167465Smp	if (transp == NULL) {
30559243Sobrien		yp_error("cannot create AF_LOCAL service.");
306167465Smp		exit(1);
30759243Sobrien	}
30859243Sobrien	if (!svc_reg(transp, MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS,
30959243Sobrien	    master_yppasswdprog_1, nconf)) {
31059243Sobrien		yp_error("unable to register (MASTER_YPPASSWDPROG, \
31159243Sobrien		    MASTER_YPPASSWDVERS, unix).");
31259243Sobrien		exit(1);
31359243Sobrien	}
31459243Sobrien	endnetconfig(localhandle);
31559243Sobrien
316	/* Only root may connect() to the AF_UNIX link. */
317	if (chmod(sockname, 0))
318		err(1, "chmod of %s failed", sockname);
319
320	if (transp == (SVCXPRT *)NULL) {
321		yp_error("could not create a handle");
322		exit(1);
323	}
324	if (_rpcpmstart) {
325		(void) signal(SIGALRM, (SIG_PF) closedown);
326		(void) alarm(_RPCSVC_CLOSEDOWN/2);
327	}
328
329	/* Unlimited resource limits. */
330	rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
331	(void)setrlimit(RLIMIT_CPU, &rlim);
332	(void)setrlimit(RLIMIT_FSIZE, &rlim);
333	(void)setrlimit(RLIMIT_STACK, &rlim);
334	(void)setrlimit(RLIMIT_DATA, &rlim);
335	(void)setrlimit(RLIMIT_RSS, &rlim);
336
337	/* Don't drop core (not really necessary, but GP's). */
338	rlim.rlim_cur = rlim.rlim_max = 0;
339	(void)setrlimit(RLIMIT_CORE, &rlim);
340
341	/* Turn off signals. */
342	(void)signal(SIGALRM, SIG_IGN);
343	(void)signal(SIGHUP, (SIG_PF) reload);
344	(void)signal(SIGINT, SIG_IGN);
345	(void)signal(SIGPIPE, SIG_IGN);
346	(void)signal(SIGQUIT, SIG_IGN);
347	(void)signal(SIGTERM, (SIG_PF) terminate);
348
349	svc_run();
350	yp_error("svc_run returned");
351	exit(1);
352	/* NOTREACHED */
353}
354