yppasswdd_main.c revision 16134
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 * 3216134Swpaul * $Id: yppasswdd_main.c,v 1.11 1996/06/03 03:21:24 wpaul Exp $ 3314062Swpaul */ 3414062Swpaul 3514062Swpaul#include "yppasswd.h" 3614062Swpaul#include <stdio.h> 3714062Swpaul#include <sys/types.h> 3814062Swpaul#include <stdlib.h> /* getenv, exit */ 3914062Swpaul#include <unistd.h> 4014062Swpaul#include <string.h> 4114062Swpaul#include <sys/param.h> 4214062Swpaul#include <rpc/pmap_clnt.h> /* for pmap_unset */ 4314062Swpaul#include <string.h> /* strcmp */ 4414062Swpaul#include <signal.h> 4514062Swpaul#include <fcntl.h> 4614062Swpaul#include <sys/ioctl.h> 4714062Swpaul#include <sys/stat.h> 4814062Swpaul#include <sys/ttycom.h> /* TIOCNOTTY */ 4914062Swpaul#ifdef __cplusplus 5014062Swpaul#include <sysent.h> /* getdtablesize, open */ 5114062Swpaul#endif /* __cplusplus */ 5214062Swpaul#include <memory.h> 5314062Swpaul#include <sys/socket.h> 5414062Swpaul#include <netinet/in.h> 5514062Swpaul#include <syslog.h> 5614062Swpaul#include <err.h> 5714062Swpaul#include <errno.h> 5814062Swpaul#include <rpcsvc/yp.h> 5914062Swpaulstruct dom_binding {}; 6014062Swpaul#include <rpcsvc/ypclnt.h> 6114062Swpaul#include "yppasswdd_extern.h" 6214062Swpaul#include "yppasswd_comm.h" 6314062Swpaul#include "ypxfr_extern.h" 6414062Swpaul 6514062Swpaul#ifndef SIG_PF 6614062Swpaul#define SIG_PF void(*)(int) 6714062Swpaul#endif 6814062Swpaul 6914062Swpaul#ifdef DEBUG 7014062Swpaul#define RPC_SVC_FG 7114062Swpaul#endif 7214062Swpaul 7314062Swpaul#define _RPCSVC_CLOSEDOWN 120 7414062Swpaul#ifndef lint 7516134Swpaulstatic const char rcsid[] = "$Id: yppasswdd_main.c,v 1.11 1996/06/03 03:21:24 wpaul Exp $"; 7614062Swpaul#endif /* not lint */ 7714062Swpaulint _rpcpmstart = 0; /* Started by a port monitor ? */ 7814062Swpaulstatic int _rpcfdtype; 7914062Swpaul /* Whether Stream or Datagram ? */ 8014062Swpaul /* States a server can be in wrt request */ 8114062Swpaul 8214062Swpaul#define _IDLE 0 8314062Swpaul#define _SERVED 1 8414062Swpaul#define _SERVING 2 8514062Swpaul 8614062Swpaulextern int _rpcsvcstate; /* Set when a request is serviced */ 8714062Swpaulchar *progname = "rpc.yppasswdd"; 8814062Swpaulchar *passfile_default = "/var/yp/master.passwd"; 8914062Swpaulchar *passfile; 9014062Swpaulchar *yppasswd_domain = NULL; 9114062Swpaulint no_chsh = 0; 9214062Swpaulint no_chfn = 0; 9314062Swpaulint allow_additions = 0; 9414062Swpaulint multidomain = 0; 9514062Swpaulint verbose = 0; 9614241Swpaulint resvport = 1; 9716134Swpaulint inplace = 0; 9814062Swpaulchar *yp_dir = "/var/yp/"; 9914062Swpaulint yp_sock; 10014062Swpaul 10114062Swpaul 10214062Swpaulstatic void 10314062Swpaulmy_svc_run() 10414062Swpaul{ 10514062Swpaul#ifdef FD_SETSIZE 10614062Swpaul fd_set readfds; 10714062Swpaul#else 10814062Swpaul int readfds; 10914062Swpaul#endif /* def FD_SETSIZE */ 11014062Swpaul extern int errno; 11114062Swpaul 11214062Swpaul for (;;) { 11314062Swpaul 11414062Swpaul 11514062Swpaul#ifdef FD_SETSIZE 11614062Swpaul readfds = svc_fdset; 11714062Swpaul#else 11814062Swpaul readfds = svc_fds; 11914062Swpaul#endif /* def FD_SETSIZE */ 12014062Swpaul FD_SET(yp_sock, &readfds); 12114062Swpaul 12214062Swpaul switch (select(_rpc_dtablesize(), &readfds, (fd_set *)0, (fd_set *)0, 12314062Swpaul (struct timeval *)0)) { 12414062Swpaul case -1: 12514062Swpaul if (errno == EINTR) { 12614062Swpaul continue; 12714062Swpaul } 12814062Swpaul perror("svc_run: - select failed"); 12914062Swpaul return; 13014062Swpaul case 0: 13114062Swpaul continue; 13214062Swpaul default: 13314062Swpaul if (FD_ISSET(yp_sock, &readfds)) { 13414062Swpaul do_master(); 13514062Swpaul FD_CLR(yp_sock, &readfds); 13614062Swpaul } 13714062Swpaul svc_getreqset(&readfds); 13814062Swpaul } 13914062Swpaul } 14014062Swpaul} 14114062Swpaul 14214062Swpaulstatic void terminate(sig) 14314062Swpaul int sig; 14414062Swpaul{ 14514062Swpaul svc_unregister(YPPASSWDPROG, YPPASSWDVERS); 14614062Swpaul close(yp_sock); 14714062Swpaul unlink(sockname); 14814062Swpaul exit(0); 14914062Swpaul} 15014241Swpaul 15114241Swpaulstatic void reload(sig) 15214241Swpaul int sig; 15314241Swpaul{ 15414241Swpaul load_securenets(); 15514241Swpaul} 15614241Swpaul 15714062Swpaulstatic void 15814062Swpaulclosedown(int sig) 15914062Swpaul{ 16014062Swpaul if (_rpcsvcstate == _IDLE) { 16114062Swpaul extern fd_set svc_fdset; 16214062Swpaul static int size; 16314062Swpaul int i, openfd; 16414062Swpaul 16514062Swpaul if (_rpcfdtype == SOCK_DGRAM) { 16614062Swpaul close(yp_sock); 16714062Swpaul unlink(sockname); 16814062Swpaul exit(0); 16914062Swpaul } 17014062Swpaul if (size == 0) { 17114062Swpaul size = getdtablesize(); 17214062Swpaul } 17314062Swpaul for (i = 0, openfd = 0; i < size && openfd < 2; i++) 17414062Swpaul if (FD_ISSET(i, &svc_fdset)) 17514062Swpaul openfd++; 17614062Swpaul if (openfd <= 1) { 17714062Swpaul close(yp_sock); 17814062Swpaul unlink(sockname); 17914062Swpaul exit(0); 18014062Swpaul } 18114062Swpaul } 18214062Swpaul if (_rpcsvcstate == _SERVED) 18314062Swpaul _rpcsvcstate = _IDLE; 18414062Swpaul 18514062Swpaul (void) signal(SIGALRM, (SIG_PF) closedown); 18614062Swpaul (void) alarm(_RPCSVC_CLOSEDOWN/2); 18714062Swpaul} 18814062Swpaul 18914062Swpaulstatic void usage() 19014062Swpaul{ 19114062Swpaul fprintf(stderr, "Usage: %s [-t master.passwd file] [-d domain] \ 19216134Swpaul[-p path] [-s] [-f] [-m] [-i] [-a] [-v] [-u] [-h]\n", 19314062Swpaul progname); 19414062Swpaul exit(1); 19514062Swpaul} 19614062Swpaul 19714062Swpaulmain(argc, argv) 19814062Swpaul int argc; 19914062Swpaul char *argv[]; 20014062Swpaul{ 20114062Swpaul register SVCXPRT *transp = NULL; 20214062Swpaul int sock; 20314062Swpaul int proto = 0; 20414062Swpaul struct sockaddr_in saddr; 20514062Swpaul int asize = sizeof (saddr); 20614062Swpaul int ch; 20714062Swpaul int rval; 20814062Swpaul char *mastername; 20914062Swpaul char myname[MAXHOSTNAMELEN + 2]; 21014062Swpaul extern int errno; 21114062Swpaul extern int debug; 21214062Swpaul 21314062Swpaul debug = 1; 21414062Swpaul 21516134Swpaul while ((ch = getopt(argc, argv, "t:d:p:sfamivh")) != EOF) { 21614062Swpaul switch(ch) { 21714062Swpaul case 't': 21814062Swpaul passfile_default = optarg; 21914062Swpaul break; 22014062Swpaul case 'd': 22114062Swpaul yppasswd_domain = optarg; 22214062Swpaul break; 22314062Swpaul case 's': 22414062Swpaul no_chsh++; 22514062Swpaul break; 22614062Swpaul case 'f': 22714062Swpaul no_chfn++; 22814062Swpaul break; 22914062Swpaul case 'p': 23014062Swpaul yp_dir = optarg; 23114062Swpaul break; 23214062Swpaul case 'a': 23314062Swpaul allow_additions++; 23414062Swpaul break; 23514062Swpaul case 'm': 23614062Swpaul multidomain++; 23714062Swpaul break; 23816134Swpaul case 'i': 23916134Swpaul inplace++; 24016134Swpaul break; 24114062Swpaul case 'v': 24214062Swpaul verbose++; 24314062Swpaul break; 24414241Swpaul case 'u': 24514241Swpaul resvport = 0; 24614241Swpaul break; 24714062Swpaul default: 24814062Swpaul case 'h': 24914062Swpaul usage(); 25014062Swpaul break; 25114062Swpaul } 25214062Swpaul } 25314062Swpaul 25414062Swpaul if (yppasswd_domain == NULL) { 25514062Swpaul if (yp_get_default_domain(&yppasswd_domain)) { 25614062Swpaul yp_error("no domain specified and system domain \ 25714062Swpaulname isn't set -- aborting"); 25814062Swpaul usage(); 25914062Swpaul } 26014062Swpaul } 26114062Swpaul 26214241Swpaul load_securenets(); 26314241Swpaul 26414062Swpaul if (getrpcport("localhost", YPPROG, YPVERS, IPPROTO_UDP) <= 0) { 26514062Swpaul yp_error("this host is not an NIS server -- aborting"); 26614062Swpaul exit(1); 26714062Swpaul } 26814062Swpaul 26914062Swpaul if ((mastername = ypxfr_get_master(yppasswd_domain, "passwd.byname", 27014062Swpaul "localhost",0)) == NULL) { 27114062Swpaul yp_error("can't get name of NIS master server"); 27214062Swpaul exit(1); 27314062Swpaul } 27414062Swpaul 27514062Swpaul if (gethostname((char *)&myname, sizeof(myname)) == -1) { 27614062Swpaul yp_error("can't get local hostname: %s", strerror(errno)); 27714062Swpaul exit(1); 27814062Swpaul } 27914062Swpaul 28014062Swpaul if (strncmp(mastername, (char *)&myname, sizeof(myname))) { 28114062Swpaul yp_error("this host is not an NIS master server -- aborting"); 28214062Swpaul exit(1); 28314062Swpaul } 28414062Swpaul 28514241Swpaul debug = 0; 28614241Swpaul 28714062Swpaul if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { 28814062Swpaul int ssize = sizeof (int); 28914062Swpaul 29014062Swpaul if (saddr.sin_family != AF_INET) 29114062Swpaul exit(1); 29214062Swpaul if (getsockopt(0, SOL_SOCKET, SO_TYPE, 29314062Swpaul (char *)&_rpcfdtype, &ssize) == -1) 29414062Swpaul exit(1); 29514062Swpaul sock = 0; 29614062Swpaul _rpcpmstart = 1; 29714062Swpaul proto = 0; 29814062Swpaul openlog(progname, LOG_PID, LOG_DAEMON); 29914062Swpaul } else { 30014062Swpaul#ifndef RPC_SVC_FG 30114062Swpaul int size; 30214062Swpaul int pid, i; 30314062Swpaul 30414062Swpaul pid = fork(); 30514062Swpaul if (pid < 0) { 30614062Swpaul perror("cannot fork"); 30714062Swpaul exit(1); 30814062Swpaul } 30914062Swpaul if (pid) 31014062Swpaul exit(0); 31114062Swpaul size = getdtablesize(); 31214062Swpaul for (i = 0; i < size; i++) 31314062Swpaul (void) close(i); 31414062Swpaul i = open("/dev/console", 2); 31514062Swpaul (void) dup2(i, 1); 31614062Swpaul (void) dup2(i, 2); 31714062Swpaul i = open("/dev/tty", 2); 31814062Swpaul if (i >= 0) { 31914062Swpaul (void) ioctl(i, TIOCNOTTY, (char *)NULL); 32014062Swpaul (void) close(i); 32114062Swpaul } 32214062Swpaul openlog(progname, LOG_PID, LOG_DAEMON); 32314062Swpaul#endif 32414062Swpaul sock = RPC_ANYSOCK; 32514062Swpaul (void) pmap_unset(YPPASSWDPROG, YPPASSWDVERS); 32614062Swpaul } 32714062Swpaul 32814062Swpaul if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { 32914062Swpaul transp = svcudp_create(sock); 33014062Swpaul if (transp == NULL) { 33114062Swpaul yp_error("cannot create udp service."); 33214062Swpaul exit(1); 33314062Swpaul } 33414062Swpaul if (!_rpcpmstart) 33514062Swpaul proto = IPPROTO_UDP; 33614062Swpaul if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) { 33714062Swpaul yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, udp)."); 33814062Swpaul exit(1); 33914062Swpaul } 34014062Swpaul } 34114062Swpaul 34214062Swpaul if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { 34314062Swpaul transp = svctcp_create(sock, 0, 0); 34414062Swpaul if (transp == NULL) { 34514062Swpaul yp_error("cannot create tcp service."); 34614062Swpaul exit(1); 34714062Swpaul } 34814062Swpaul if (!_rpcpmstart) 34914062Swpaul proto = IPPROTO_TCP; 35014062Swpaul if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) { 35114062Swpaul yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, tcp)."); 35214062Swpaul exit(1); 35314062Swpaul } 35414062Swpaul } 35514062Swpaul 35614062Swpaul if (transp == (SVCXPRT *)NULL) { 35714062Swpaul yp_error("could not create a handle"); 35814062Swpaul exit(1); 35914062Swpaul } 36014062Swpaul if (_rpcpmstart) { 36114062Swpaul (void) signal(SIGALRM, (SIG_PF) closedown); 36214062Swpaul (void) alarm(_RPCSVC_CLOSEDOWN/2); 36314062Swpaul } 36414241Swpaul /* set up resource limits and block signals */ 36514062Swpaul pw_init(); 36614062Swpaul 36714062Swpaul /* except SIGCHLD, which we need to catch */ 36814062Swpaul install_reaper(1); 36914062Swpaul signal(SIGTERM, (SIG_PF) terminate); 37014062Swpaul 37114241Swpaul signal(SIGHUP, (SIG_PF) reload); 37214241Swpaul 37314062Swpaul unlink(sockname); 37414062Swpaul yp_sock = makeservsock(); 37514062Swpaul if (chmod(sockname, 0)) 37614062Swpaul err(1, "chmod of %s failed", sockname); 37714062Swpaul 37814062Swpaul my_svc_run(); 37914062Swpaul yp_error("svc_run returned"); 38014062Swpaul exit(1); 38114062Swpaul /* NOTREACHED */ 38214062Swpaul} 383