yppasswdd_main.c revision 90298
11556Srgrimes/*
21556Srgrimes * Copyright (c) 1995, 1996
31556Srgrimes *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
41556Srgrimes *
51556Srgrimes * Redistribution and use in source and binary forms, with or without
61556Srgrimes * modification, are permitted provided that the following conditions
71556Srgrimes * are met:
81556Srgrimes * 1. Redistributions of source code must retain the above copyright
91556Srgrimes *    notice, this list of conditions and the following disclaimer.
101556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111556Srgrimes *    notice, this list of conditions and the following disclaimer in the
121556Srgrimes *    documentation and/or other materials provided with the distribution.
131556Srgrimes * 3. All advertising materials mentioning features or use of this software
141556Srgrimes *    must display the following acknowledgement:
151556Srgrimes *	This product includes software developed by Bill Paul.
161556Srgrimes * 4. Neither the name of the author nor the names of any co-contributors
171556Srgrimes *    may be used to endorse or promote products derived from this software
181556Srgrimes *    without specific prior written permission.
191556Srgrimes *
201556Srgrimes * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
211556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
241556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301556Srgrimes * SUCH DAMAGE.
311556Srgrimes */
321556Srgrimes
331556Srgrimes#ifndef lint
3420425Sstevestatic const char rcsid[] =
351556Srgrimes  "$FreeBSD: head/usr.sbin/rpc.yppasswdd/yppasswdd_main.c 90298 2002-02-06 15:26:07Z des $";
361556Srgrimes#endif /* not lint */
371556Srgrimes
381556Srgrimes#include "yppasswd.h"
391556Srgrimes#include <stdio.h>
4036150Scharnier#include <sys/types.h>
4136150Scharnier#include <stdlib.h> /* getenv, exit */
4236150Scharnier#include <unistd.h>
431556Srgrimes#include <string.h>
4499110Sobrien#include <sys/param.h>
4599110Sobrien#include <rpc/pmap_clnt.h> /* for pmap_unset */
461556Srgrimes#include <string.h> /* strcmp */
471556Srgrimes#include <signal.h>
481556Srgrimes#include <fcntl.h>
491556Srgrimes#include <sys/ioctl.h>
501556Srgrimes#include <sys/stat.h>
511556Srgrimes#ifdef __cplusplus
5217987Speter#include <sysent.h> /* getdtablesize, open */
531556Srgrimes#endif /* __cplusplus */
5417987Speter#include <memory.h>
551556Srgrimes#include <sys/socket.h>
561556Srgrimes#include <netinet/in.h>
571556Srgrimes#include <syslog.h>
581556Srgrimes#include <err.h>
591556Srgrimes#include <errno.h>
601556Srgrimes#include <rpcsvc/yp.h>
6117987Speterstruct dom_binding {};
6217987Speter#include <rpcsvc/ypclnt.h>
631556Srgrimes#include "yppasswdd_extern.h"
641556Srgrimes#include "yppasswd_private.h"
6553891Scracauer#include "ypxfr_extern.h"
661556Srgrimes
671556Srgrimes#ifndef SIG_PF
681556Srgrimes#define	SIG_PF void(*)(int)
691556Srgrimes#endif
7020425Ssteve
711556Srgrimes#ifdef DEBUG
721556Srgrimes#define	RPC_SVC_FG
731556Srgrimes#endif
741556Srgrimes
751556Srgrimes#define	_RPCSVC_CLOSEDOWN 120
761556Srgrimesint _rpcpmstart = 0;		/* Started by a port monitor ? */
771556Srgrimesstatic int _rpcfdtype;
781556Srgrimes		 /* Whether Stream or Datagram ? */
791556Srgrimes	/* States a server can be in wrt request */
801556Srgrimes
811556Srgrimes#define	_IDLE 0
821556Srgrimes#define	_SERVED 1
831556Srgrimes#define	_SERVING 2
841556Srgrimes
851556Srgrimesextern int _rpcsvcstate;	 /* Set when a request is serviced */
861556Srgrimeschar *progname = "rpc.yppasswdd";
871556Srgrimeschar *yp_dir = _PATH_YP;
881556Srgrimeschar *passfile_default = _PATH_YP "master.passwd";
891556Srgrimeschar *passfile;
901556Srgrimeschar *yppasswd_domain = NULL;
911556Srgrimesint no_chsh = 0;
928855Srgrimesint no_chfn = 0;
931556Srgrimesint allow_additions = 0;
941556Srgrimesint multidomain = 0;
951556Srgrimesint verbose = 0;
961556Srgrimesint resvport = 1;
971556Srgrimesint inplace = 0;
981556Srgrimeschar *sockname = YP_SOCKNAME;
991556Srgrimes
1001556Srgrimesstatic void
1011556Srgrimesterminate(int sig)
1021556Srgrimes{
1031556Srgrimes	rpcb_unset(YPPASSWDPROG, YPPASSWDVERS, NULL);
1041556Srgrimes	rpcb_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, NULL);
1051556Srgrimes	unlink(sockname);
1061556Srgrimes	exit(0);
1071556Srgrimes}
10820425Ssteve
1091556Srgrimesstatic void
1101556Srgrimesreload(int sig)
1111556Srgrimes{
1121556Srgrimes	load_securenets();
1131556Srgrimes}
1141556Srgrimes
1151556Srgrimesstatic void
1161556Srgrimesclosedown(int sig)
1171556Srgrimes{
1181556Srgrimes	if (_rpcsvcstate == _IDLE) {
1191556Srgrimes		extern fd_set svc_fdset;
1201556Srgrimes		static int size;
1211556Srgrimes		int i, openfd;
1221556Srgrimes
1231556Srgrimes		if (_rpcfdtype == SOCK_DGRAM) {
1241556Srgrimes			unlink(sockname);
1251556Srgrimes			exit(0);
1261556Srgrimes		}
1271556Srgrimes		if (size == 0) {
1281556Srgrimes			size = getdtablesize();
1291556Srgrimes		}
1301556Srgrimes		for (i = 0, openfd = 0; i < size && openfd < 2; i++)
1311556Srgrimes			if (FD_ISSET(i, &svc_fdset))
1321556Srgrimes				openfd++;
1331556Srgrimes		if (openfd <= 1) {
1341556Srgrimes			unlink(sockname);
1351556Srgrimes			exit(0);
136149019Sstefanf		}
137149019Sstefanf	}
138149019Sstefanf	if (_rpcsvcstate == _SERVED)
139149019Sstefanf		_rpcsvcstate = _IDLE;
1401556Srgrimes
1411556Srgrimes	(void) signal(SIGALRM, (SIG_PF) closedown);
1421556Srgrimes	(void) alarm(_RPCSVC_CLOSEDOWN/2);
1431556Srgrimes}
1441556Srgrimes
1451556Srgrimesstatic void
1461556Srgrimesusage(void)
1471556Srgrimes{
1481556Srgrimes	fprintf(stderr, "%s\n%s\n",
1491556Srgrimes"usage: rpc.yppasswdd [-t master.passwd file] [-d domain] [-p path] [-s]",
1501556Srgrimes"                     [-f] [-m] [-i] [-a] [-v] [-u] [-h]");
15190111Simp	exit(1);
15290111Simp}
15390111Simp
15490111Simpint
15590111Simpmain(int argc, char *argv[])
15690111Simp{
15790111Simp	register SVCXPRT *transp = NULL;
15890111Simp	struct sockaddr_in saddr;
15990111Simp	int asize = sizeof (saddr);
16090111Simp	struct netconfig *nconf;
16190111Simp	void *localhandle;
162193221Srse	int ch;
16390111Simp	char *mastername;
16490111Simp	char myname[MAXHOSTNAMELEN + 2];
1651556Srgrimes
1661556Srgrimes	extern int debug;
1671556Srgrimes
16817987Speter	debug = 1;
16990111Simp
17017987Speter	while ((ch = getopt(argc, argv, "t:d:p:sfamuivh")) != -1) {
1711556Srgrimes		switch (ch) {
1721556Srgrimes		case 't':
1731556Srgrimes			passfile_default = optarg;
1741556Srgrimes			break;
175149019Sstefanf		case 'd':
17617987Speter			yppasswd_domain = optarg;
1771556Srgrimes			break;
1781556Srgrimes		case 's':
17920425Ssteve			no_chsh++;
18017987Speter			break;
1811556Srgrimes		case 'f':
1821556Srgrimes			no_chfn++;
1831556Srgrimes			break;
1841556Srgrimes		case 'p':
1851556Srgrimes			yp_dir = optarg;
1861556Srgrimes			break;
1871556Srgrimes		case 'a':
1881556Srgrimes			allow_additions++;
18990111Simp			break;
19090111Simp		case 'm':
1911556Srgrimes			multidomain++;
19220425Ssteve			break;
1931556Srgrimes		case 'i':
1941556Srgrimes			inplace++;
1951556Srgrimes			break;
1961556Srgrimes		case 'v':
1971556Srgrimes			verbose++;
1981556Srgrimes			break;
1991556Srgrimes		case 'u':
2001556Srgrimes			resvport = 0;
2011556Srgrimes			break;
2021556Srgrimes		default:
2031556Srgrimes		case 'h':
2041556Srgrimes			usage();
2051556Srgrimes			break;
2061556Srgrimes		}
2071556Srgrimes	}
2081556Srgrimes
2091556Srgrimes	if (yppasswd_domain == NULL) {
2101556Srgrimes		if (yp_get_default_domain(&yppasswd_domain)) {
21111113Sjoerg			yp_error("no domain specified and system domain \
21211113Sjoergname isn't set -- aborting");
21320425Ssteve		usage();
21420425Ssteve		}
21511113Sjoerg	}
21611113Sjoerg
21720425Ssteve	load_securenets();
21820425Ssteve
21911113Sjoerg	if (getrpcport("localhost", YPPROG, YPVERS, IPPROTO_UDP) <= 0) {
22020425Ssteve		yp_error("no ypserv processes registered with local portmap");
22111113Sjoerg		yp_error("this host is not an NIS server -- aborting");
22220425Ssteve		exit(1);
22311113Sjoerg	}
22411113Sjoerg
2251556Srgrimes	if ((mastername = ypxfr_get_master(yppasswd_domain, "passwd.byname",
22611113Sjoerg						"localhost",0)) == NULL) {
2271556Srgrimes		yp_error("can't get name of NIS master server for domain %s",
2281556Srgrimes			 				yppasswd_domain);
2291556Srgrimes		exit(1);
2301556Srgrimes	}
2311556Srgrimes
2321556Srgrimes	if (gethostname((char *)&myname, sizeof(myname)) == -1) {
23390111Simp		yp_error("can't get local hostname: %s", strerror(errno));
23417987Speter		exit(1);
23525222Ssteve	}
2361556Srgrimes
2371556Srgrimes	if (strncasecmp(mastername, (char *)&myname, sizeof(myname))) {
2381556Srgrimes		yp_error("master of %s is %s, but we are %s",
2391556Srgrimes			"passwd.byname", mastername, myname);
2401556Srgrimes		yp_error("this host is not the NIS master server for \
2411556Srgrimesthe %s domain -- aborting", yppasswd_domain);
2421556Srgrimes		exit(1);
2431556Srgrimes	}
2441556Srgrimes
2451556Srgrimes	debug = 0;
2461556Srgrimes
2471556Srgrimes	if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {
2481556Srgrimes		int ssize = sizeof (int);
24990111Simp		if (saddr.sin_family != AF_INET)
25017987Speter			exit(1);
25125222Ssteve		if (getsockopt(0, SOL_SOCKET, SO_TYPE,
2521556Srgrimes		    (char *)&_rpcfdtype, &ssize) == -1)
2531556Srgrimes			exit(1);
2541556Srgrimes		_rpcpmstart = 1;
2551556Srgrimes	}
2561556Srgrimes
2571556Srgrimes	if (!debug && _rpcpmstart == 0) {
2581556Srgrimes		if (daemon(0,0)) {
2591556Srgrimes			err(1,"cannot fork");
2601556Srgrimes		}
2611556Srgrimes	}
2621556Srgrimes	openlog("rpc.yppasswdd", LOG_PID, LOG_DAEMON);
2631556Srgrimes
2641556Srgrimes	rpcb_unset(YPPASSWDPROG, YPPASSWDVERS, NULL);
2651556Srgrimes	rpcb_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, NULL);
2661556Srgrimes
2671556Srgrimes	if (svc_create(yppasswdprog_1, YPPASSWDPROG, YPPASSWDVERS, "netpath") == 0) {
2681556Srgrimes		yp_error("cannot create yppasswd service.");
2691556Srgrimes		exit(1);
2701556Srgrimes	}
2711556Srgrimes	if (svc_create(master_yppasswdprog_1, MASTER_YPPASSWDPROG,
27290111Simp	    MASTER_YPPASSWDVERS, "netpath") == 0) {
27390111Simp		yp_error("cannot create master_yppasswd service.");
2741556Srgrimes		exit(1);
2751556Srgrimes	}
2761556Srgrimes
2771556Srgrimes	nconf = NULL;
2781556Srgrimes	localhandle = setnetconfig();
2791556Srgrimes	while ((nconf = getnetconfig(localhandle)) != NULL) {
2801556Srgrimes		if (nconf->nc_protofmly != NULL &&
2811556Srgrimes		    strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
2821556Srgrimes			break;
2831556Srgrimes	}
2841556Srgrimes	if (nconf == NULL) {
2851556Srgrimes		yp_error("getnetconfigent unix: %s", nc_sperror());
2861556Srgrimes		exit(1);
2871556Srgrimes	}
2881556Srgrimes	unlink(sockname);
2891556Srgrimes	transp = svcunix_create(RPC_ANYSOCK, 0, 0, sockname);
2901556Srgrimes	if (transp == NULL) {
2911556Srgrimes		yp_error("cannot create AF_LOCAL service.");
2921556Srgrimes		exit(1);
2931556Srgrimes	}
2941556Srgrimes	if (!svc_reg(transp, MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS,
2951556Srgrimes	    master_yppasswdprog_1, nconf)) {
2961556Srgrimes		yp_error("unable to register (MASTER_YPPASSWDPROG,
2971556Srgrimes		    MASTER_YPPASSWDVERS, unix).");
2981556Srgrimes		exit(1);
2991556Srgrimes	}
3001556Srgrimes	endnetconfig(localhandle);
3011556Srgrimes
3021556Srgrimes	/* Only root may connect() to the AF_UNIX link. */
3031556Srgrimes	if (chmod(sockname, 0))
3041556Srgrimes		err(1, "chmod of %s failed", sockname);
3051556Srgrimes
3061556Srgrimes	if (transp == (SVCXPRT *)NULL) {
3071556Srgrimes		yp_error("could not create a handle");
3081556Srgrimes		exit(1);
30990111Simp	}
31090111Simp	if (_rpcpmstart) {
31125222Ssteve		(void) signal(SIGALRM, (SIG_PF) closedown);
3121556Srgrimes		(void) alarm(_RPCSVC_CLOSEDOWN/2);
31325222Ssteve	}
3141556Srgrimes	/* set up resource limits and block signals */
3151556Srgrimes	pw_init();
3161556Srgrimes
3171556Srgrimes	/* except SIGCHLD, which we need to catch */
3181556Srgrimes	install_reaper(1);
3191556Srgrimes	signal(SIGTERM, (SIG_PF) terminate);
3201556Srgrimes
3211556Srgrimes	signal(SIGHUP, (SIG_PF) reload);
3221556Srgrimes
3231556Srgrimes	svc_run();
3241556Srgrimes	yp_error("svc_run returned");
3251556Srgrimes	exit(1);
3261556Srgrimes	/* NOTREACHED */
3271556Srgrimes}
3281556Srgrimes