yppasswdd_main.c revision 50479
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
341556Srgrimesstatic const char rcsid[] =
351556Srgrimes  "$FreeBSD: head/usr.sbin/rpc.yppasswdd/yppasswdd_main.c 50479 1999-08-28 01:35:59Z peter $";
361556Srgrimes#endif /* not lint */
371556Srgrimes
3836150Scharnier#include "yppasswd.h"
3936150Scharnier#include <stdio.h>
4036150Scharnier#include <sys/types.h>
4136150Scharnier#include <stdlib.h> /* getenv, exit */
4236150Scharnier#include <unistd.h>
431556Srgrimes#include <string.h>
441556Srgrimes#include <sys/param.h>
4517987Speter#include <rpc/pmap_clnt.h> /* for pmap_unset */
4617987Speter#include <string.h> /* strcmp */
4717987Speter#include <signal.h>
481556Srgrimes#include <fcntl.h>
491556Srgrimes#include <sys/ioctl.h>
501556Srgrimes#include <sys/stat.h>
511556Srgrimes#include <sys/ttycom.h> /* TIOCNOTTY */
521556Srgrimes#ifdef __cplusplus
531556Srgrimes#include <sysent.h> /* getdtablesize, open */
541556Srgrimes#endif /* __cplusplus */
551556Srgrimes#include <memory.h>
561556Srgrimes#include <sys/socket.h>
571556Srgrimes#include <netinet/in.h>
581556Srgrimes#include <syslog.h>
591556Srgrimes#include <err.h>
601556Srgrimes#include <errno.h>
611556Srgrimes#include <rpcsvc/yp.h>
621556Srgrimesstruct dom_binding {};
631556Srgrimes#include <rpcsvc/ypclnt.h>
641556Srgrimes#include "yppasswdd_extern.h"
651556Srgrimes#include "yppasswd_private.h"
661556Srgrimes#include "ypxfr_extern.h"
671556Srgrimes
681556Srgrimes#ifndef SIG_PF
6917987Speter#define	SIG_PF void(*)(int)
701556Srgrimes#endif
7117987Speter
721556Srgrimes#ifdef DEBUG
7317987Speter#define	RPC_SVC_FG
741556Srgrimes#endif
751556Srgrimes
761556Srgrimes#define	_RPCSVC_CLOSEDOWN 120
771556Srgrimesint _rpcpmstart = 0;		/* Started by a port monitor ? */
781556Srgrimesstatic int _rpcfdtype;
791556Srgrimes		 /* Whether Stream or Datagram ? */
801556Srgrimes	/* States a server can be in wrt request */
811556Srgrimes
821556Srgrimes#define	_IDLE 0
831556Srgrimes#define	_SERVED 1
841556Srgrimes#define	_SERVING 2
851556Srgrimes
861556Srgrimesextern int _rpcsvcstate;	 /* Set when a request is serviced */
871556Srgrimeschar *progname = "rpc.yppasswdd";
881556Srgrimeschar *yp_dir = _PATH_YP;
891556Srgrimeschar *passfile_default = _PATH_YP "master.passwd";
9017987Speterchar *passfile;
911556Srgrimeschar *yppasswd_domain = NULL;
921556Srgrimesint no_chsh = 0;
9317987Speterint no_chfn = 0;
9417987Speterint allow_additions = 0;
9517987Speterint multidomain = 0;
9617987Speterint verbose = 0;
9717987Speterint resvport = 1;
9817987Speterint inplace = 0;
9917987Speterchar *sockname = YP_SOCKNAME;
10017987Speter
1011556Srgrimesstatic void terminate(sig)
1021556Srgrimes	int sig;
1031556Srgrimes{
1041556Srgrimes	svc_unregister(YPPASSWDPROG, YPPASSWDVERS);
1051556Srgrimes	svc_unregister(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS);
1061556Srgrimes	unlink(sockname);
1071556Srgrimes	exit(0);
1081556Srgrimes}
1091556Srgrimes
1101556Srgrimesstatic void reload(sig)
1111556Srgrimes	int sig;
1121556Srgrimes{
1131556Srgrimes	load_securenets();
1141556Srgrimes}
1151556Srgrimes
1161556Srgrimesstatic void
1171556Srgrimesclosedown(int sig)
1181556Srgrimes{
1191556Srgrimes	if (_rpcsvcstate == _IDLE) {
1201556Srgrimes		extern fd_set svc_fdset;
1211556Srgrimes		static int size;
1221556Srgrimes		int i, openfd;
1231556Srgrimes
1241556Srgrimes		if (_rpcfdtype == SOCK_DGRAM) {
1251556Srgrimes			unlink(sockname);
1261556Srgrimes			exit(0);
12717987Speter		}
12820425Ssteve		if (size == 0) {
12917987Speter			size = getdtablesize();
13020425Ssteve		}
1311556Srgrimes		for (i = 0, openfd = 0; i < size && openfd < 2; i++)
1321556Srgrimes			if (FD_ISSET(i, &svc_fdset))
1331556Srgrimes				openfd++;
1341556Srgrimes		if (openfd <= 1) {
1351556Srgrimes			unlink(sockname);
1361556Srgrimes			exit(0);
1371556Srgrimes		}
1381556Srgrimes	}
1391556Srgrimes	if (_rpcsvcstate == _SERVED)
1401556Srgrimes		_rpcsvcstate = _IDLE;
1411556Srgrimes
1421556Srgrimes	(void) signal(SIGALRM, (SIG_PF) closedown);
1431556Srgrimes	(void) alarm(_RPCSVC_CLOSEDOWN/2);
1441556Srgrimes}
1451556Srgrimes
1461556Srgrimesstatic void usage()
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]");
1511556Srgrimes	exit(1);
1521556Srgrimes}
1531556Srgrimes
1541556Srgrimesint
1551556Srgrimesmain(argc, argv)
1561556Srgrimes	int argc;
1571556Srgrimes	char *argv[];
1581556Srgrimes{
1591556Srgrimes	register SVCXPRT *transp = NULL;
1601556Srgrimes	int sock;
1611556Srgrimes	int proto = 0;
1621556Srgrimes	struct sockaddr_in saddr;
1631556Srgrimes	int asize = sizeof (saddr);
1641556Srgrimes	int ch;
1651556Srgrimes	char *mastername;
1661556Srgrimes	char myname[MAXHOSTNAMELEN + 2];
1671556Srgrimes	extern int errno;
1681556Srgrimes	extern int debug;
1691556Srgrimes
1701556Srgrimes	debug = 1;
1711556Srgrimes
1721556Srgrimes	while ((ch = getopt(argc, argv, "t:d:p:sfamuivh")) != -1) {
1731556Srgrimes		switch(ch) {
1741556Srgrimes		case 't':
1751556Srgrimes			passfile_default = optarg;
1761556Srgrimes			break;
1771556Srgrimes		case 'd':
1781556Srgrimes			yppasswd_domain = optarg;
1791556Srgrimes			break;
1801556Srgrimes		case 's':
1811556Srgrimes			no_chsh++;
1821556Srgrimes			break;
1831556Srgrimes		case 'f':
1841556Srgrimes			no_chfn++;
1851556Srgrimes			break;
1861556Srgrimes		case 'p':
1871556Srgrimes			yp_dir = optarg;
18817987Speter			break;
18917987Speter		case 'a':
1901556Srgrimes			allow_additions++;
1911556Srgrimes			break;
1921556Srgrimes		case 'm':
1931556Srgrimes			multidomain++;
1941556Srgrimes			break;
19517987Speter		case 'i':
1961556Srgrimes			inplace++;
19717987Speter			break;
19817987Speter		case 'v':
1991556Srgrimes			verbose++;
2001556Srgrimes			break;
2011556Srgrimes		case 'u':
2021556Srgrimes			resvport = 0;
2031556Srgrimes			break;
2041556Srgrimes		default:
2051556Srgrimes		case 'h':
2061556Srgrimes			usage();
2071556Srgrimes			break;
20818754Ssteve		}
20918754Ssteve	}
2101556Srgrimes
21118754Ssteve	if (yppasswd_domain == NULL) {
2121556Srgrimes		if (yp_get_default_domain(&yppasswd_domain)) {
2131556Srgrimes			yp_error("no domain specified and system domain \
2141556Srgrimesname isn't set -- aborting");
2151556Srgrimes		usage();
2161556Srgrimes		}
2171556Srgrimes	}
2181556Srgrimes
2191556Srgrimes	load_securenets();
2201556Srgrimes
2211556Srgrimes	if (getrpcport("localhost", YPPROG, YPVERS, IPPROTO_UDP) <= 0) {
2221556Srgrimes		yp_error("no ypserv processes registered with local portmap");
2231556Srgrimes		yp_error("this host is not an NIS server -- aborting");
2241556Srgrimes		exit(1);
2251556Srgrimes	}
2261556Srgrimes
2271556Srgrimes	if ((mastername = ypxfr_get_master(yppasswd_domain, "passwd.byname",
2281556Srgrimes						"localhost",0)) == NULL) {
2291556Srgrimes		yp_error("can't get name of NIS master server for domain %s",
2301556Srgrimes			 				yppasswd_domain);
2311556Srgrimes		exit(1);
2321556Srgrimes	}
2331556Srgrimes
2341556Srgrimes	if (gethostname((char *)&myname, sizeof(myname)) == -1) {
2351556Srgrimes		yp_error("can't get local hostname: %s", strerror(errno));
23620425Ssteve		exit(1);
2371556Srgrimes	}
23817987Speter
2391556Srgrimes	if (strncasecmp(mastername, (char *)&myname, sizeof(myname))) {
24020425Ssteve		yp_error("master of %s is %s, but we are %s",
24120425Ssteve			"passwd.byname", mastername, myname);
2421556Srgrimes		yp_error("this host is not the NIS master server for \
2431556Srgrimesthe %s domain -- aborting", yppasswd_domain);
2441556Srgrimes		exit(1);
2451556Srgrimes	}
2461556Srgrimes
2471556Srgrimes	debug = 0;
2481556Srgrimes
2491556Srgrimes	if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {
2501556Srgrimes		int ssize = sizeof (int);
2511556Srgrimes
2521556Srgrimes		if (saddr.sin_family != AF_INET)
2531556Srgrimes			exit(1);
2541556Srgrimes		if (getsockopt(0, SOL_SOCKET, SO_TYPE,
2551556Srgrimes				(char *)&_rpcfdtype, &ssize) == -1)
2561556Srgrimes			exit(1);
2571556Srgrimes		sock = 0;
2581556Srgrimes		_rpcpmstart = 1;
2591556Srgrimes		proto = 0;
2601556Srgrimes		openlog("rpc.yppasswdd", LOG_PID, LOG_DAEMON);
2611556Srgrimes	} else {
2621556Srgrimes		if (!debug) {
2631556Srgrimes			if (daemon(0,0)) {
2641556Srgrimes				err(1,"cannot fork");
2651556Srgrimes			}
2661556Srgrimes		}
2671556Srgrimes		openlog("rpc.yppasswdd", LOG_PID, LOG_DAEMON);
2681556Srgrimes		sock = RPC_ANYSOCK;
2691556Srgrimes		(void) pmap_unset(YPPASSWDPROG, YPPASSWDVERS);
2701556Srgrimes		(void) pmap_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS);
2711556Srgrimes		unlink(sockname);
2721556Srgrimes	}
2731556Srgrimes
2741556Srgrimes	if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) {
2751556Srgrimes		transp = svcudp_create(sock);
2761556Srgrimes		if (transp == NULL) {
2771556Srgrimes			yp_error("cannot create udp service.");
2781556Srgrimes			exit(1);
2791556Srgrimes		}
2801556Srgrimes		if (!_rpcpmstart)
2811556Srgrimes			proto = IPPROTO_UDP;
2821556Srgrimes		if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) {
2831556Srgrimes			yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, udp).");
2841556Srgrimes			exit(1);
28517987Speter		}
2861556Srgrimes	}
2871556Srgrimes
2881556Srgrimes	if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) {
2891556Srgrimes		transp = svctcp_create(sock, 0, 0);
2901556Srgrimes		if (transp == NULL) {
2911556Srgrimes			yp_error("cannot create tcp service.");
2921556Srgrimes			exit(1);
2931556Srgrimes		}
2941556Srgrimes		if (!_rpcpmstart)
2951556Srgrimes			proto = IPPROTO_TCP;
2961556Srgrimes		if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) {
2971556Srgrimes			yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, tcp).");
2981556Srgrimes			exit(1);
2991556Srgrimes		}
3001556Srgrimes	}
3011556Srgrimes
3021556Srgrimes	unlink(sockname);
3031556Srgrimes	transp = svcunix_create(sock, 0, 0, sockname);
3041556Srgrimes	if (transp == NULL) {
3051556Srgrimes		yp_error("cannot create AF_LOCAL service.");
3061556Srgrimes		exit(1);
3071556Srgrimes	}
3081556Srgrimes	if (!svc_register(transp, MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, master_yppasswdprog_1, 0)) {
3091556Srgrimes		yp_error("unable to register (MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, unix).");
3101556Srgrimes		exit(1);
3111556Srgrimes	}
3121556Srgrimes	/* Only root may connect() to the AF_UNIX link. */
3131556Srgrimes	if (chmod(sockname, 0))
3141556Srgrimes		err(1, "chmod of %s failed", sockname);
3151556Srgrimes
3161556Srgrimes	if (transp == (SVCXPRT *)NULL) {
3171556Srgrimes		yp_error("could not create a handle");
3181556Srgrimes		exit(1);
3191556Srgrimes	}
3201556Srgrimes	if (_rpcpmstart) {
32117987Speter		(void) signal(SIGALRM, (SIG_PF) closedown);
32217987Speter		(void) alarm(_RPCSVC_CLOSEDOWN/2);
3231556Srgrimes	}
3241556Srgrimes	/* set up resource limits and block signals */
3251556Srgrimes	pw_init();
3261556Srgrimes
3271556Srgrimes	/* except SIGCHLD, which we need to catch */
3281556Srgrimes	install_reaper(1);
3291556Srgrimes	signal(SIGTERM, (SIG_PF) terminate);
3301556Srgrimes
33117987Speter	signal(SIGHUP, (SIG_PF) reload);
3321556Srgrimes
3331556Srgrimes	svc_run();
3341556Srgrimes	yp_error("svc_run returned");
3351556Srgrimes	exit(1);
3361556Srgrimes	/* NOTREACHED */
3371556Srgrimes}
3381556Srgrimes