yppasswdd_main.c revision 14062
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 * $Id: yppasswdd_main.c,v 1.8 1996/02/09 04:21:35 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 7514062Swpaulstatic const char rcsid[] = "$Id: yppasswdd_main.c,v 1.8 1996/02/09 04:21:35 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; 9614062Swpaulchar *yp_dir = "/var/yp/"; 9714062Swpaulint yp_sock; 9814062Swpaul 9914062Swpaul 10014062Swpaulstatic void 10114062Swpaulmy_svc_run() 10214062Swpaul{ 10314062Swpaul#ifdef FD_SETSIZE 10414062Swpaul fd_set readfds; 10514062Swpaul#else 10614062Swpaul int readfds; 10714062Swpaul#endif /* def FD_SETSIZE */ 10814062Swpaul extern int errno; 10914062Swpaul 11014062Swpaul for (;;) { 11114062Swpaul 11214062Swpaul 11314062Swpaul#ifdef FD_SETSIZE 11414062Swpaul readfds = svc_fdset; 11514062Swpaul#else 11614062Swpaul readfds = svc_fds; 11714062Swpaul#endif /* def FD_SETSIZE */ 11814062Swpaul FD_SET(yp_sock, &readfds); 11914062Swpaul 12014062Swpaul switch (select(_rpc_dtablesize(), &readfds, (fd_set *)0, (fd_set *)0, 12114062Swpaul (struct timeval *)0)) { 12214062Swpaul case -1: 12314062Swpaul if (errno == EINTR) { 12414062Swpaul continue; 12514062Swpaul } 12614062Swpaul perror("svc_run: - select failed"); 12714062Swpaul return; 12814062Swpaul case 0: 12914062Swpaul continue; 13014062Swpaul default: 13114062Swpaul if (FD_ISSET(yp_sock, &readfds)) { 13214062Swpaul do_master(); 13314062Swpaul FD_CLR(yp_sock, &readfds); 13414062Swpaul } 13514062Swpaul svc_getreqset(&readfds); 13614062Swpaul } 13714062Swpaul } 13814062Swpaul} 13914062Swpaul 14014062Swpaulstatic void terminate(sig) 14114062Swpaul int sig; 14214062Swpaul{ 14314062Swpaul svc_unregister(YPPASSWDPROG, YPPASSWDVERS); 14414062Swpaul close(yp_sock); 14514062Swpaul unlink(sockname); 14614062Swpaul exit(0); 14714062Swpaul} 14814062Swpaul 14914062Swpaulstatic void 15014062Swpaulclosedown(int sig) 15114062Swpaul{ 15214062Swpaul if (_rpcsvcstate == _IDLE) { 15314062Swpaul extern fd_set svc_fdset; 15414062Swpaul static int size; 15514062Swpaul int i, openfd; 15614062Swpaul 15714062Swpaul if (_rpcfdtype == SOCK_DGRAM) { 15814062Swpaul close(yp_sock); 15914062Swpaul unlink(sockname); 16014062Swpaul exit(0); 16114062Swpaul } 16214062Swpaul if (size == 0) { 16314062Swpaul size = getdtablesize(); 16414062Swpaul } 16514062Swpaul for (i = 0, openfd = 0; i < size && openfd < 2; i++) 16614062Swpaul if (FD_ISSET(i, &svc_fdset)) 16714062Swpaul openfd++; 16814062Swpaul if (openfd <= 1) { 16914062Swpaul close(yp_sock); 17014062Swpaul unlink(sockname); 17114062Swpaul exit(0); 17214062Swpaul } 17314062Swpaul } 17414062Swpaul if (_rpcsvcstate == _SERVED) 17514062Swpaul _rpcsvcstate = _IDLE; 17614062Swpaul 17714062Swpaul (void) signal(SIGALRM, (SIG_PF) closedown); 17814062Swpaul (void) alarm(_RPCSVC_CLOSEDOWN/2); 17914062Swpaul} 18014062Swpaul 18114062Swpaulstatic void usage() 18214062Swpaul{ 18314062Swpaul fprintf(stderr, "Usage: %s [-t master.passwd file] [-d domain] \ 18414062Swpaul[-p path] [-s] [-f] [-m] [-a] [-v] [-h]\n", 18514062Swpaul progname); 18614062Swpaul exit(1); 18714062Swpaul} 18814062Swpaul 18914062Swpaulmain(argc, argv) 19014062Swpaul int argc; 19114062Swpaul char *argv[]; 19214062Swpaul{ 19314062Swpaul register SVCXPRT *transp = NULL; 19414062Swpaul int sock; 19514062Swpaul int proto = 0; 19614062Swpaul struct sockaddr_in saddr; 19714062Swpaul int asize = sizeof (saddr); 19814062Swpaul int ch; 19914062Swpaul int rval; 20014062Swpaul char *mastername; 20114062Swpaul char myname[MAXHOSTNAMELEN + 2]; 20214062Swpaul extern int errno; 20314062Swpaul extern int debug; 20414062Swpaul 20514062Swpaul debug = 1; 20614062Swpaul 20714062Swpaul while ((ch = getopt(argc, argv, "t:d:p:sfamvh")) != EOF) { 20814062Swpaul switch(ch) { 20914062Swpaul case 't': 21014062Swpaul passfile_default = optarg; 21114062Swpaul break; 21214062Swpaul case 'd': 21314062Swpaul yppasswd_domain = optarg; 21414062Swpaul break; 21514062Swpaul case 's': 21614062Swpaul no_chsh++; 21714062Swpaul break; 21814062Swpaul case 'f': 21914062Swpaul no_chfn++; 22014062Swpaul break; 22114062Swpaul case 'p': 22214062Swpaul yp_dir = optarg; 22314062Swpaul break; 22414062Swpaul case 'a': 22514062Swpaul allow_additions++; 22614062Swpaul break; 22714062Swpaul case 'm': 22814062Swpaul multidomain++; 22914062Swpaul break; 23014062Swpaul case 'v': 23114062Swpaul verbose++; 23214062Swpaul break; 23314062Swpaul default: 23414062Swpaul case 'h': 23514062Swpaul usage(); 23614062Swpaul break; 23714062Swpaul } 23814062Swpaul } 23914062Swpaul 24014062Swpaul if (yppasswd_domain == NULL) { 24114062Swpaul if (yp_get_default_domain(&yppasswd_domain)) { 24214062Swpaul yp_error("no domain specified and system domain \ 24314062Swpaulname isn't set -- aborting"); 24414062Swpaul usage(); 24514062Swpaul } 24614062Swpaul } 24714062Swpaul 24814062Swpaul if (getrpcport("localhost", YPPROG, YPVERS, IPPROTO_UDP) <= 0) { 24914062Swpaul yp_error("this host is not an NIS server -- aborting"); 25014062Swpaul exit(1); 25114062Swpaul } 25214062Swpaul 25314062Swpaul if ((mastername = ypxfr_get_master(yppasswd_domain, "passwd.byname", 25414062Swpaul "localhost",0)) == NULL) { 25514062Swpaul yp_error("can't get name of NIS master server"); 25614062Swpaul exit(1); 25714062Swpaul } 25814062Swpaul 25914062Swpaul if (gethostname((char *)&myname, sizeof(myname)) == -1) { 26014062Swpaul yp_error("can't get local hostname: %s", strerror(errno)); 26114062Swpaul exit(1); 26214062Swpaul } 26314062Swpaul 26414062Swpaul if (strncmp(mastername, (char *)&myname, sizeof(myname))) { 26514062Swpaul yp_error("this host is not an NIS master server -- aborting"); 26614062Swpaul exit(1); 26714062Swpaul } 26814062Swpaul 26914062Swpaul if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { 27014062Swpaul int ssize = sizeof (int); 27114062Swpaul 27214062Swpaul if (saddr.sin_family != AF_INET) 27314062Swpaul exit(1); 27414062Swpaul if (getsockopt(0, SOL_SOCKET, SO_TYPE, 27514062Swpaul (char *)&_rpcfdtype, &ssize) == -1) 27614062Swpaul exit(1); 27714062Swpaul sock = 0; 27814062Swpaul _rpcpmstart = 1; 27914062Swpaul proto = 0; 28014062Swpaul openlog(progname, LOG_PID, LOG_DAEMON); 28114062Swpaul } else { 28214062Swpaul#ifndef RPC_SVC_FG 28314062Swpaul int size; 28414062Swpaul int pid, i; 28514062Swpaul 28614062Swpaul pid = fork(); 28714062Swpaul if (pid < 0) { 28814062Swpaul perror("cannot fork"); 28914062Swpaul exit(1); 29014062Swpaul } 29114062Swpaul if (pid) 29214062Swpaul exit(0); 29314062Swpaul size = getdtablesize(); 29414062Swpaul for (i = 0; i < size; i++) 29514062Swpaul (void) close(i); 29614062Swpaul i = open("/dev/console", 2); 29714062Swpaul (void) dup2(i, 1); 29814062Swpaul (void) dup2(i, 2); 29914062Swpaul i = open("/dev/tty", 2); 30014062Swpaul if (i >= 0) { 30114062Swpaul (void) ioctl(i, TIOCNOTTY, (char *)NULL); 30214062Swpaul (void) close(i); 30314062Swpaul } 30414062Swpaul openlog(progname, LOG_PID, LOG_DAEMON); 30514062Swpaul#endif 30614062Swpaul sock = RPC_ANYSOCK; 30714062Swpaul (void) pmap_unset(YPPASSWDPROG, YPPASSWDVERS); 30814062Swpaul } 30914062Swpaul 31014062Swpaul if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { 31114062Swpaul transp = svcudp_create(sock); 31214062Swpaul if (transp == NULL) { 31314062Swpaul yp_error("cannot create udp service."); 31414062Swpaul exit(1); 31514062Swpaul } 31614062Swpaul if (!_rpcpmstart) 31714062Swpaul proto = IPPROTO_UDP; 31814062Swpaul if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) { 31914062Swpaul yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, udp)."); 32014062Swpaul exit(1); 32114062Swpaul } 32214062Swpaul } 32314062Swpaul 32414062Swpaul if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { 32514062Swpaul transp = svctcp_create(sock, 0, 0); 32614062Swpaul if (transp == NULL) { 32714062Swpaul yp_error("cannot create tcp service."); 32814062Swpaul exit(1); 32914062Swpaul } 33014062Swpaul if (!_rpcpmstart) 33114062Swpaul proto = IPPROTO_TCP; 33214062Swpaul if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) { 33314062Swpaul yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, tcp)."); 33414062Swpaul exit(1); 33514062Swpaul } 33614062Swpaul } 33714062Swpaul 33814062Swpaul if (transp == (SVCXPRT *)NULL) { 33914062Swpaul yp_error("could not create a handle"); 34014062Swpaul exit(1); 34114062Swpaul } 34214062Swpaul if (_rpcpmstart) { 34314062Swpaul (void) signal(SIGALRM, (SIG_PF) closedown); 34414062Swpaul (void) alarm(_RPCSVC_CLOSEDOWN/2); 34514062Swpaul } 34614062Swpaul /* set up resporce limits and block signals */ 34714062Swpaul pw_init(); 34814062Swpaul 34914062Swpaul /* except SIGCHLD, which we need to catch */ 35014062Swpaul install_reaper(1); 35114062Swpaul signal(SIGTERM, (SIG_PF) terminate); 35214062Swpaul 35314062Swpaul unlink(sockname); 35414062Swpaul yp_sock = makeservsock(); 35514062Swpaul if (chmod(sockname, 0)) 35614062Swpaul err(1, "chmod of %s failed", sockname); 35714062Swpaul 35814062Swpaul my_svc_run(); 35914062Swpaul yp_error("svc_run returned"); 36014062Swpaul exit(1); 36114062Swpaul /* NOTREACHED */ 36214062Swpaul} 363