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