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