18256fad9SBill Paul /* 28256fad9SBill Paul * Copyright (c) 1995, 1996 38256fad9SBill Paul * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 48256fad9SBill Paul * 58256fad9SBill Paul * Redistribution and use in source and binary forms, with or without 68256fad9SBill Paul * modification, are permitted provided that the following conditions 78256fad9SBill Paul * are met: 88256fad9SBill Paul * 1. Redistributions of source code must retain the above copyright 98256fad9SBill Paul * notice, this list of conditions and the following disclaimer. 108256fad9SBill Paul * 2. Redistributions in binary form must reproduce the above copyright 118256fad9SBill Paul * notice, this list of conditions and the following disclaimer in the 128256fad9SBill Paul * documentation and/or other materials provided with the distribution. 138256fad9SBill Paul * 3. All advertising materials mentioning features or use of this software 148256fad9SBill Paul * must display the following acknowledgement: 158256fad9SBill Paul * This product includes software developed by Bill Paul. 168256fad9SBill Paul * 4. Neither the name of the author nor the names of any co-contributors 178256fad9SBill Paul * may be used to endorse or promote products derived from this software 188256fad9SBill Paul * without specific prior written permission. 198256fad9SBill Paul * 208256fad9SBill Paul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 218256fad9SBill Paul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 228256fad9SBill Paul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 238256fad9SBill Paul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 248256fad9SBill Paul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 258256fad9SBill Paul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 268256fad9SBill Paul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 278256fad9SBill Paul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 288256fad9SBill Paul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 298256fad9SBill Paul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 308256fad9SBill Paul * SUCH DAMAGE. 318256fad9SBill Paul */ 328256fad9SBill Paul 33fdd83901SPhilippe Charnier #ifndef lint 34fdd83901SPhilippe Charnier static const char rcsid[] = 357cf0cfedSBrian Somers "$Id: yppasswdd_main.c,v 1.12 1997/10/13 11:18:50 charnier Exp $"; 36fdd83901SPhilippe Charnier #endif /* not lint */ 37fdd83901SPhilippe Charnier 388256fad9SBill Paul #include "yppasswd.h" 398256fad9SBill Paul #include <stdio.h> 408256fad9SBill Paul #include <sys/types.h> 418256fad9SBill Paul #include <stdlib.h> /* getenv, exit */ 428256fad9SBill Paul #include <unistd.h> 438256fad9SBill Paul #include <string.h> 448256fad9SBill Paul #include <sys/param.h> 458256fad9SBill Paul #include <rpc/pmap_clnt.h> /* for pmap_unset */ 468256fad9SBill Paul #include <string.h> /* strcmp */ 478256fad9SBill Paul #include <signal.h> 488256fad9SBill Paul #include <fcntl.h> 498256fad9SBill Paul #include <sys/ioctl.h> 508256fad9SBill Paul #include <sys/stat.h> 518256fad9SBill Paul #include <sys/ttycom.h> /* TIOCNOTTY */ 528256fad9SBill Paul #ifdef __cplusplus 538256fad9SBill Paul #include <sysent.h> /* getdtablesize, open */ 548256fad9SBill Paul #endif /* __cplusplus */ 558256fad9SBill Paul #include <memory.h> 568256fad9SBill Paul #include <sys/socket.h> 578256fad9SBill Paul #include <netinet/in.h> 588256fad9SBill Paul #include <syslog.h> 598256fad9SBill Paul #include <err.h> 608256fad9SBill Paul #include <errno.h> 618256fad9SBill Paul #include <rpcsvc/yp.h> 628256fad9SBill Paul struct dom_binding {}; 638256fad9SBill Paul #include <rpcsvc/ypclnt.h> 648256fad9SBill Paul #include "yppasswdd_extern.h" 651f922405SBill Paul #include "yppasswd_private.h" 668256fad9SBill Paul #include "ypxfr_extern.h" 678256fad9SBill Paul 688256fad9SBill Paul #ifndef SIG_PF 698256fad9SBill Paul #define SIG_PF void(*)(int) 708256fad9SBill Paul #endif 718256fad9SBill Paul 728256fad9SBill Paul #ifdef DEBUG 738256fad9SBill Paul #define RPC_SVC_FG 748256fad9SBill Paul #endif 758256fad9SBill Paul 768256fad9SBill Paul #define _RPCSVC_CLOSEDOWN 120 778256fad9SBill Paul int _rpcpmstart = 0; /* Started by a port monitor ? */ 788256fad9SBill Paul static int _rpcfdtype; 798256fad9SBill Paul /* Whether Stream or Datagram ? */ 808256fad9SBill Paul /* States a server can be in wrt request */ 818256fad9SBill Paul 828256fad9SBill Paul #define _IDLE 0 838256fad9SBill Paul #define _SERVED 1 848256fad9SBill Paul #define _SERVING 2 858256fad9SBill Paul 868256fad9SBill Paul extern int _rpcsvcstate; /* Set when a request is serviced */ 878256fad9SBill Paul char *progname = "rpc.yppasswdd"; 88ba21c862SBill Paul char *yp_dir = _PATH_YP; 89ba21c862SBill Paul char *passfile_default = _PATH_YP "master.passwd"; 908256fad9SBill Paul char *passfile; 918256fad9SBill Paul char *yppasswd_domain = NULL; 928256fad9SBill Paul int no_chsh = 0; 938256fad9SBill Paul int no_chfn = 0; 948256fad9SBill Paul int allow_additions = 0; 958256fad9SBill Paul int multidomain = 0; 968256fad9SBill Paul int verbose = 0; 97589b8bfcSBill Paul int resvport = 1; 988b6a78c2SBill Paul int inplace = 0; 991f922405SBill Paul char *sockname = YP_SOCKNAME; 1008256fad9SBill Paul 1018256fad9SBill Paul static void terminate(sig) 1028256fad9SBill Paul int sig; 1038256fad9SBill Paul { 1048256fad9SBill Paul svc_unregister(YPPASSWDPROG, YPPASSWDVERS); 1051f922405SBill Paul svc_unregister(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS); 1068256fad9SBill Paul unlink(sockname); 1078256fad9SBill Paul exit(0); 1088256fad9SBill Paul } 1098256fad9SBill Paul 110589b8bfcSBill Paul static void reload(sig) 111589b8bfcSBill Paul int sig; 112589b8bfcSBill Paul { 113589b8bfcSBill Paul load_securenets(); 114589b8bfcSBill Paul } 115589b8bfcSBill Paul 1168256fad9SBill Paul static void 1178256fad9SBill Paul closedown(int sig) 1188256fad9SBill Paul { 1198256fad9SBill Paul if (_rpcsvcstate == _IDLE) { 1208256fad9SBill Paul extern fd_set svc_fdset; 1218256fad9SBill Paul static int size; 1228256fad9SBill Paul int i, openfd; 1238256fad9SBill Paul 1248256fad9SBill Paul if (_rpcfdtype == SOCK_DGRAM) { 1258256fad9SBill Paul unlink(sockname); 1268256fad9SBill Paul exit(0); 1278256fad9SBill Paul } 1288256fad9SBill Paul if (size == 0) { 1298256fad9SBill Paul size = getdtablesize(); 1308256fad9SBill Paul } 1318256fad9SBill Paul for (i = 0, openfd = 0; i < size && openfd < 2; i++) 1328256fad9SBill Paul if (FD_ISSET(i, &svc_fdset)) 1338256fad9SBill Paul openfd++; 1348256fad9SBill Paul if (openfd <= 1) { 1358256fad9SBill Paul unlink(sockname); 1368256fad9SBill Paul exit(0); 1378256fad9SBill Paul } 1388256fad9SBill Paul } 1398256fad9SBill Paul if (_rpcsvcstate == _SERVED) 1408256fad9SBill Paul _rpcsvcstate = _IDLE; 1418256fad9SBill Paul 1428256fad9SBill Paul (void) signal(SIGALRM, (SIG_PF) closedown); 1438256fad9SBill Paul (void) alarm(_RPCSVC_CLOSEDOWN/2); 1448256fad9SBill Paul } 1458256fad9SBill Paul 1468256fad9SBill Paul static void usage() 1478256fad9SBill Paul { 148fdd83901SPhilippe Charnier fprintf(stderr, "%s\n%s\n", 149fdd83901SPhilippe Charnier "usage: rpc.yppasswdd [-t master.passwd file] [-d domain] [-p path] [-s]", 150fdd83901SPhilippe Charnier " [-f] [-m] [-i] [-a] [-v] [-u] [-h]"); 1518256fad9SBill Paul exit(1); 1528256fad9SBill Paul } 1538256fad9SBill Paul 154d21fb5dcSPeter Wemm int 1558256fad9SBill Paul main(argc, argv) 1568256fad9SBill Paul int argc; 1578256fad9SBill Paul char *argv[]; 1588256fad9SBill Paul { 1598256fad9SBill Paul register SVCXPRT *transp = NULL; 1608256fad9SBill Paul int sock; 1618256fad9SBill Paul int proto = 0; 1628256fad9SBill Paul struct sockaddr_in saddr; 1638256fad9SBill Paul int asize = sizeof (saddr); 1648256fad9SBill Paul int ch; 1658256fad9SBill Paul char *mastername; 1668256fad9SBill Paul char myname[MAXHOSTNAMELEN + 2]; 1678256fad9SBill Paul extern int errno; 1688256fad9SBill Paul extern int debug; 1698256fad9SBill Paul 1708256fad9SBill Paul debug = 1; 1718256fad9SBill Paul 1726c3f552aSWarner Losh while ((ch = getopt(argc, argv, "t:d:p:sfamuivh")) != -1) { 1738256fad9SBill Paul switch(ch) { 1748256fad9SBill Paul case 't': 1758256fad9SBill Paul passfile_default = optarg; 1768256fad9SBill Paul break; 1778256fad9SBill Paul case 'd': 1788256fad9SBill Paul yppasswd_domain = optarg; 1798256fad9SBill Paul break; 1808256fad9SBill Paul case 's': 1818256fad9SBill Paul no_chsh++; 1828256fad9SBill Paul break; 1838256fad9SBill Paul case 'f': 1848256fad9SBill Paul no_chfn++; 1858256fad9SBill Paul break; 1868256fad9SBill Paul case 'p': 1878256fad9SBill Paul yp_dir = optarg; 1888256fad9SBill Paul break; 1898256fad9SBill Paul case 'a': 1908256fad9SBill Paul allow_additions++; 1918256fad9SBill Paul break; 1928256fad9SBill Paul case 'm': 1938256fad9SBill Paul multidomain++; 1948256fad9SBill Paul break; 1958b6a78c2SBill Paul case 'i': 1968b6a78c2SBill Paul inplace++; 1978b6a78c2SBill Paul break; 1988256fad9SBill Paul case 'v': 1998256fad9SBill Paul verbose++; 2008256fad9SBill Paul break; 201589b8bfcSBill Paul case 'u': 202589b8bfcSBill Paul resvport = 0; 203589b8bfcSBill Paul break; 2048256fad9SBill Paul default: 2058256fad9SBill Paul case 'h': 2068256fad9SBill Paul usage(); 2078256fad9SBill Paul break; 2088256fad9SBill Paul } 2098256fad9SBill Paul } 2108256fad9SBill Paul 2118256fad9SBill Paul if (yppasswd_domain == NULL) { 2128256fad9SBill Paul if (yp_get_default_domain(&yppasswd_domain)) { 2138256fad9SBill Paul yp_error("no domain specified and system domain \ 2148256fad9SBill Paul name isn't set -- aborting"); 2158256fad9SBill Paul usage(); 2168256fad9SBill Paul } 2178256fad9SBill Paul } 2188256fad9SBill Paul 219589b8bfcSBill Paul load_securenets(); 220589b8bfcSBill Paul 2218256fad9SBill Paul if (getrpcport("localhost", YPPROG, YPVERS, IPPROTO_UDP) <= 0) { 222511db384SBill Paul yp_error("no ypserv processes registered with local portmap"); 2238256fad9SBill Paul yp_error("this host is not an NIS server -- aborting"); 2248256fad9SBill Paul exit(1); 2258256fad9SBill Paul } 2268256fad9SBill Paul 2278256fad9SBill Paul if ((mastername = ypxfr_get_master(yppasswd_domain, "passwd.byname", 2288256fad9SBill Paul "localhost",0)) == NULL) { 229511db384SBill Paul yp_error("can't get name of NIS master server for domain %s", 230511db384SBill Paul yppasswd_domain); 2318256fad9SBill Paul exit(1); 2328256fad9SBill Paul } 2338256fad9SBill Paul 2348256fad9SBill Paul if (gethostname((char *)&myname, sizeof(myname)) == -1) { 2358256fad9SBill Paul yp_error("can't get local hostname: %s", strerror(errno)); 2368256fad9SBill Paul exit(1); 2378256fad9SBill Paul } 2388256fad9SBill Paul 2397cf0cfedSBrian Somers if (strncasecmp(mastername, (char *)&myname, sizeof(myname))) { 240511db384SBill Paul yp_error("master of %s is %s, but we are %s", 241511db384SBill Paul "passwd.byname", mastername, myname); 242511db384SBill Paul yp_error("this host is not the NIS master server for \ 243511db384SBill Paul the %s domain -- aborting", yppasswd_domain); 2448256fad9SBill Paul exit(1); 2458256fad9SBill Paul } 2468256fad9SBill Paul 247589b8bfcSBill Paul debug = 0; 248589b8bfcSBill Paul 2498256fad9SBill Paul if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { 2508256fad9SBill Paul int ssize = sizeof (int); 2518256fad9SBill Paul 2528256fad9SBill Paul if (saddr.sin_family != AF_INET) 2538256fad9SBill Paul exit(1); 2548256fad9SBill Paul if (getsockopt(0, SOL_SOCKET, SO_TYPE, 2558256fad9SBill Paul (char *)&_rpcfdtype, &ssize) == -1) 2568256fad9SBill Paul exit(1); 2578256fad9SBill Paul sock = 0; 2588256fad9SBill Paul _rpcpmstart = 1; 2598256fad9SBill Paul proto = 0; 260fdd83901SPhilippe Charnier openlog("rpc.yppasswdd", LOG_PID, LOG_DAEMON); 2618256fad9SBill Paul } else { 262df4ddde7SBill Paul if (!debug) { 263df4ddde7SBill Paul if (daemon(0,0)) { 264df4ddde7SBill Paul err(1,"cannot fork"); 2658256fad9SBill Paul } 2668256fad9SBill Paul } 267fdd83901SPhilippe Charnier openlog("rpc.yppasswdd", LOG_PID, LOG_DAEMON); 2688256fad9SBill Paul sock = RPC_ANYSOCK; 2698256fad9SBill Paul (void) pmap_unset(YPPASSWDPROG, YPPASSWDVERS); 2701f922405SBill Paul (void) pmap_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS); 2711f922405SBill Paul unlink(sockname); 2728256fad9SBill Paul } 2738256fad9SBill Paul 2748256fad9SBill Paul if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { 2758256fad9SBill Paul transp = svcudp_create(sock); 2768256fad9SBill Paul if (transp == NULL) { 2778256fad9SBill Paul yp_error("cannot create udp service."); 2788256fad9SBill Paul exit(1); 2798256fad9SBill Paul } 2808256fad9SBill Paul if (!_rpcpmstart) 2818256fad9SBill Paul proto = IPPROTO_UDP; 2828256fad9SBill Paul if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) { 2838256fad9SBill Paul yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, udp)."); 2848256fad9SBill Paul exit(1); 2858256fad9SBill Paul } 2868256fad9SBill Paul } 2878256fad9SBill Paul 2888256fad9SBill Paul if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { 2898256fad9SBill Paul transp = svctcp_create(sock, 0, 0); 2908256fad9SBill Paul if (transp == NULL) { 2918256fad9SBill Paul yp_error("cannot create tcp service."); 2928256fad9SBill Paul exit(1); 2938256fad9SBill Paul } 2948256fad9SBill Paul if (!_rpcpmstart) 2958256fad9SBill Paul proto = IPPROTO_TCP; 2968256fad9SBill Paul if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) { 2978256fad9SBill Paul yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, tcp)."); 2988256fad9SBill Paul exit(1); 2998256fad9SBill Paul } 3008256fad9SBill Paul } 3018256fad9SBill Paul 3021f922405SBill Paul unlink(sockname); 3031f922405SBill Paul transp = svcunix_create(sock, 0, 0, sockname); 3041f922405SBill Paul if (transp == NULL) { 3051f922405SBill Paul yp_error("cannot create AF_LOCAL service."); 3061f922405SBill Paul exit(1); 3071f922405SBill Paul } 3081f922405SBill Paul if (!svc_register(transp, MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, master_yppasswdprog_1, 0)) { 3091f922405SBill Paul yp_error("unable to register (MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, unix)."); 3101f922405SBill Paul exit(1); 3111f922405SBill Paul } 3121f922405SBill Paul /* Only root may connect() to the AF_UNIX link. */ 3131f922405SBill Paul if (chmod(sockname, 0)) 3141f922405SBill Paul err(1, "chmod of %s failed", sockname); 3151f922405SBill Paul 3168256fad9SBill Paul if (transp == (SVCXPRT *)NULL) { 3178256fad9SBill Paul yp_error("could not create a handle"); 3188256fad9SBill Paul exit(1); 3198256fad9SBill Paul } 3208256fad9SBill Paul if (_rpcpmstart) { 3218256fad9SBill Paul (void) signal(SIGALRM, (SIG_PF) closedown); 3228256fad9SBill Paul (void) alarm(_RPCSVC_CLOSEDOWN/2); 3238256fad9SBill Paul } 324589b8bfcSBill Paul /* set up resource limits and block signals */ 3258256fad9SBill Paul pw_init(); 3268256fad9SBill Paul 3278256fad9SBill Paul /* except SIGCHLD, which we need to catch */ 3288256fad9SBill Paul install_reaper(1); 3298256fad9SBill Paul signal(SIGTERM, (SIG_PF) terminate); 3308256fad9SBill Paul 331589b8bfcSBill Paul signal(SIGHUP, (SIG_PF) reload); 332589b8bfcSBill Paul 3331f922405SBill Paul svc_run(); 3348256fad9SBill Paul yp_error("svc_run returned"); 3358256fad9SBill Paul exit(1); 3368256fad9SBill Paul /* NOTREACHED */ 3378256fad9SBill Paul } 338