yppasswdd_main.c revision 184459
1195609Smp/* 259243Sobrien * Copyright (c) 1995, 1996 359243Sobrien * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 459243Sobrien * 559243Sobrien * Redistribution and use in source and binary forms, with or without 659243Sobrien * modification, are permitted provided that the following conditions 759243Sobrien * are met: 859243Sobrien * 1. Redistributions of source code must retain the above copyright 959243Sobrien * notice, this list of conditions and the following disclaimer. 1059243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1159243Sobrien * notice, this list of conditions and the following disclaimer in the 1259243Sobrien * documentation and/or other materials provided with the distribution. 1359243Sobrien * 3. All advertising materials mentioning features or use of this software 1459243Sobrien * must display the following acknowledgement: 1559243Sobrien * This product includes software developed by Bill Paul. 1659243Sobrien * 4. Neither the name of the author nor the names of any co-contributors 1759243Sobrien * may be used to endorse or promote products derived from this software 18100616Smp * without specific prior written permission. 1959243Sobrien * 2059243Sobrien * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2159243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2259243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2359243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 2459243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2559243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2659243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2759243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2859243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2959243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3059243Sobrien * SUCH DAMAGE. 3159243Sobrien */ 3259243Sobrien 3359243Sobrien#include <sys/cdefs.h> 3459243Sobrien__FBSDID("$FreeBSD: head/usr.sbin/rpc.yppasswdd/yppasswdd_main.c 184459 2008-10-30 01:54:31Z rafan $"); 3559243Sobrien 3659243Sobrien#include <sys/param.h> 3759243Sobrien#include <sys/ioctl.h> 3859243Sobrien#include <sys/stat.h> 3959243Sobrien#include <sys/socket.h> 40167465Smp#include <sys/time.h> 41145479Smp#include <sys/resource.h> 42145479Smp#include <netinet/in.h> 43145479Smp 44145479Smp#include <err.h> 45145479Smp#include <errno.h> 46145479Smp#include <fcntl.h> 4759243Sobrien#include <memory.h> 4859243Sobrien#include <signal.h> 4959243Sobrien#include <stdio.h> 5059243Sobrien#include <stdlib.h> /* getenv, exit */ 5159243Sobrien#include <string.h> 5259243Sobrien#include <string.h> /* strcmp */ 5359243Sobrien#include <syslog.h> 5459243Sobrien#include <unistd.h> 5559243Sobrien 5659243Sobrien#include <rpc/rpc.h> 5759243Sobrien#include <rpc/rpc_com.h> 5859243Sobrien#include <rpc/pmap_clnt.h> /* for pmap_unset */ 5959243Sobrien#include <rpcsvc/yp.h> 6059243Sobrien#include <rpcsvc/ypclnt.h> 6159243Sobrien 6259243Sobrien#include "yppasswd.h" 6383098Smp#include "yppasswdd_extern.h" 64100616Smp#include "yppasswd_private.h" 6559243Sobrien#include "ypxfr_extern.h" 6659243Sobrien#include "yp_extern.h" 67195609Smp 6859243Sobrien#ifndef SIG_PF 69195609Smp#define SIG_PF void(*)(int) 7059243Sobrien#endif 7159243Sobrien 7259243Sobrien#ifdef DEBUG 7359243Sobrien#define RPC_SVC_FG 7459243Sobrien#endif 7559243Sobrien 7659243Sobrien#define _RPCSVC_CLOSEDOWN 120 77195609Smpint _rpcpmstart = 0; /* Started by a port monitor ? */ 78195609Smpstatic int _rpcfdtype; 7959243Sobrien /* Whether Stream or Datagram ? */ 80195609Smp /* States a server can be in wrt request */ 8159243Sobrien 82195609Smp#define _IDLE 0 8359243Sobrien#define _SERVED 1 84195609Smp#define _SERVING 2 85195609Smp 86195609Smpstatic char _localhost[] = "localhost"; 87195609Smpstatic char _passwd_byname[] = "passwd.byname"; 88195609Smpextern int _rpcsvcstate; /* Set when a request is serviced */ 89195609Smpstatic char _progname[] = "rpc.yppasswdd"; 90195609Smpchar *progname = _progname; 91195609Smpstatic char _yp_dir[] = _PATH_YP; 92195609Smpchar *yp_dir = _yp_dir; 9359243Sobrienstatic char _passfile_default[] = _PATH_YP "master.passwd"; 94195609Smpchar *passfile_default = _passfile_default; 9559243Sobrienchar *passfile; 96195609Smpchar *yppasswd_domain = NULL; 9759243Sobrienint no_chsh = 0; 98195609Smpint no_chfn = 0; 9959243Sobrienint allow_additions = 0; 100195609Smpint multidomain = 0; 10159243Sobrienint verbose = 0; 102195609Smpint resvport = 1; 10359243Sobrienint inplace = 0; 104195609Smpchar sockname[] = YP_SOCKNAME; 105145479Smp 106195609Smpstatic void 107195609Smpterminate(int sig __unused) 108145479Smp{ 109195609Smp rpcb_unset(YPPASSWDPROG, YPPASSWDVERS, NULL); 110195609Smp rpcb_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, NULL); 111195609Smp unlink(sockname); 112195609Smp exit(0); 113195609Smp} 114145479Smp 115195609Smpstatic void 116195609Smpreload(int sig __unused) 11759243Sobrien{ 118195609Smp load_securenets(); 119195609Smp} 120195609Smp 121195609Smpstatic void 122195609Smpclosedown(int sig __unused) 12359243Sobrien{ 124195609Smp if (_rpcsvcstate == _IDLE) { 12559243Sobrien extern fd_set svc_fdset; 126195609Smp static int size; 12759243Sobrien int i, openfd; 12859243Sobrien 129145479Smp if (_rpcfdtype == SOCK_DGRAM) { 130167465Smp unlink(sockname); 131167465Smp exit(0); 132145479Smp } 133145479Smp if (size == 0) { 13459243Sobrien size = getdtablesize(); 135145479Smp } 136145479Smp for (i = 0, openfd = 0; i < size && openfd < 2; i++) 13769408Sache if (FD_ISSET(i, &svc_fdset)) 138145479Smp openfd++; 139145479Smp if (openfd <= 1) { 140145479Smp unlink(sockname); 14159243Sobrien exit(0); 14259243Sobrien } 143167465Smp } 14459243Sobrien if (_rpcsvcstate == _SERVED) 14559243Sobrien _rpcsvcstate = _IDLE; 14659243Sobrien 14759243Sobrien (void) signal(SIGALRM, (SIG_PF) closedown); 148167465Smp (void) alarm(_RPCSVC_CLOSEDOWN/2); 149145479Smp} 15059243Sobrien 151145479Smpstatic void 152145479Smpusage(void) 153167465Smp{ 154167465Smp fprintf(stderr, "%s\n%s\n", 155145479Smp"usage: rpc.yppasswdd [-t master.passwd file] [-d domain] [-p path] [-s]", 15669408Sache" [-f] [-m] [-i] [-a] [-v] [-u] [-h]"); 157167465Smp exit(1); 158167465Smp} 159145479Smp 160145479Smpint 161145479Smpmain(int argc, char *argv[]) 162167465Smp{ 163167465Smp struct rlimit rlim; 16469408Sache SVCXPRT *transp = NULL; 16559243Sobrien struct sockaddr_in saddr; 166167465Smp socklen_t asize = sizeof (saddr); 167167465Smp struct netconfig *nconf; 168167465Smp struct sigaction sa; 169167465Smp void *localhandle; 170145479Smp int ch; 171145479Smp char *mastername; 172145479Smp char myname[MAXHOSTNAMELEN + 2]; 173145479Smp int maxrec = RPC_MAXDATASIZE; 174145479Smp 175145479Smp extern int debug; 176145479Smp 177195609Smp debug = 1; 178195609Smp 179145479Smp while ((ch = getopt(argc, argv, "t:d:p:sfamuivh")) != -1) { 180195609Smp switch (ch) { 181195609Smp case 't': 182195609Smp passfile_default = optarg; 183145479Smp break; 18459243Sobrien case 'd': 18559243Sobrien yppasswd_domain = optarg; 18659243Sobrien break; 18759243Sobrien case 's': 18859243Sobrien no_chsh++; 18959243Sobrien break; 190145479Smp case 'f': 191145479Smp no_chfn++; 192145479Smp break; 193145479Smp case 'p': 194145479Smp yp_dir = optarg; 195145479Smp break; 196145479Smp case 'a': 197145479Smp allow_additions++; 198145479Smp break; 199145479Smp case 'm': 200145479Smp multidomain++; 201145479Smp break; 202145479Smp case 'i': 203145479Smp inplace++; 20459243Sobrien break; 20559243Sobrien case 'v': 20659243Sobrien verbose++; 20759243Sobrien break; 20859243Sobrien case 'u': 20959243Sobrien resvport = 0; 21059243Sobrien break; 21159243Sobrien default: 21259243Sobrien case 'h': 21359243Sobrien usage(); 21459243Sobrien break; 21559243Sobrien } 21659243Sobrien } 21759243Sobrien 21859243Sobrien if (yppasswd_domain == NULL) { 21959243Sobrien if (yp_get_default_domain(&yppasswd_domain)) { 22059243Sobrien yp_error("no domain specified and system domain \ 22159243Sobrienname isn't set -- aborting"); 22259243Sobrien usage(); 22359243Sobrien } 22469408Sache } 22559243Sobrien 22659243Sobrien load_securenets(); 22759243Sobrien 22859243Sobrien if (getrpcport(_localhost, YPPROG, YPVERS, IPPROTO_UDP) <= 0) { 22959243Sobrien yp_error("no ypserv processes registered with local portmap"); 23059243Sobrien yp_error("this host is not an NIS server -- aborting"); 23159243Sobrien exit(1); 23259243Sobrien } 23359243Sobrien 23459243Sobrien if ((mastername = ypxfr_get_master(yppasswd_domain, 23559243Sobrien _passwd_byname, _localhost, 0)) == NULL) { 23659243Sobrien yp_error("can't get name of NIS master server for domain %s", 23759243Sobrien yppasswd_domain); 23859243Sobrien exit(1); 23959243Sobrien } 24059243Sobrien 24159243Sobrien if (gethostname((char *)&myname, sizeof(myname)) == -1) { 24259243Sobrien yp_error("can't get local hostname: %s", strerror(errno)); 24359243Sobrien exit(1); 24459243Sobrien } 24559243Sobrien 24659243Sobrien if (strncasecmp(mastername, (char *)&myname, sizeof(myname))) { 24759243Sobrien yp_error("master of %s is %s, but we are %s", 24859243Sobrien "passwd.byname", mastername, myname); 24959243Sobrien yp_error("this host is not the NIS master server for \ 25059243Sobrienthe %s domain -- aborting", yppasswd_domain); 25159243Sobrien exit(1); 25259243Sobrien } 25359243Sobrien 25459243Sobrien debug = 0; 25559243Sobrien 25659243Sobrien if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { 25759243Sobrien socklen_t ssize = sizeof (int); 25859243Sobrien if (saddr.sin_family != AF_INET) 25959243Sobrien exit(1); 26059243Sobrien if (getsockopt(0, SOL_SOCKET, SO_TYPE, 26159243Sobrien (char *)&_rpcfdtype, &ssize) == -1) 26259243Sobrien exit(1); 26359243Sobrien _rpcpmstart = 1; 26459243Sobrien } 26569408Sache 26659243Sobrien if (!debug && _rpcpmstart == 0) { 26759243Sobrien if (daemon(0,0)) { 26859243Sobrien err(1,"cannot fork"); 26959243Sobrien } 27059243Sobrien } 27159243Sobrien openlog("rpc.yppasswdd", LOG_PID, LOG_DAEMON); 27259243Sobrien memset(&sa, 0, sizeof(sa)); 27359243Sobrien sa.sa_flags = SA_NOCLDWAIT; 27459243Sobrien sigaction(SIGCHLD, &sa, NULL); 27559243Sobrien 27659243Sobrien rpcb_unset(YPPASSWDPROG, YPPASSWDVERS, NULL); 27759243Sobrien rpcb_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, NULL); 27859243Sobrien 27959243Sobrien rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); 28059243Sobrien 28159243Sobrien if (svc_create(yppasswdprog_1, YPPASSWDPROG, YPPASSWDVERS, "netpath") == 0) { 28259243Sobrien yp_error("cannot create yppasswd service."); 28359243Sobrien exit(1); 28459243Sobrien } 28569408Sache if (svc_create(master_yppasswdprog_1, MASTER_YPPASSWDPROG, 28659243Sobrien MASTER_YPPASSWDVERS, "netpath") == 0) { 28759243Sobrien yp_error("cannot create master_yppasswd service."); 288167465Smp exit(1); 289167465Smp } 290167465Smp 291167465Smp nconf = NULL; 292167465Smp localhandle = setnetconfig(); 293145479Smp while ((nconf = getnetconfig(localhandle)) != NULL) { 294145479Smp if (nconf->nc_protofmly != NULL && 295167465Smp strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) 296167465Smp break; 29759243Sobrien } 298167465Smp if (nconf == NULL) { 29959243Sobrien yp_error("getnetconfigent unix: %s", nc_sperror()); 300167465Smp exit(1); 30159243Sobrien } 30259243Sobrien unlink(sockname); 303167465Smp transp = svcunix_create(RPC_ANYSOCK, 0, 0, sockname); 304167465Smp if (transp == NULL) { 30559243Sobrien yp_error("cannot create AF_LOCAL service."); 306167465Smp exit(1); 30759243Sobrien } 30859243Sobrien if (!svc_reg(transp, MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, 30959243Sobrien master_yppasswdprog_1, nconf)) { 31059243Sobrien yp_error("unable to register (MASTER_YPPASSWDPROG, \ 31159243Sobrien MASTER_YPPASSWDVERS, unix)."); 31259243Sobrien exit(1); 31359243Sobrien } 31459243Sobrien endnetconfig(localhandle); 31559243Sobrien 316 /* Only root may connect() to the AF_UNIX link. */ 317 if (chmod(sockname, 0)) 318 err(1, "chmod of %s failed", sockname); 319 320 if (transp == (SVCXPRT *)NULL) { 321 yp_error("could not create a handle"); 322 exit(1); 323 } 324 if (_rpcpmstart) { 325 (void) signal(SIGALRM, (SIG_PF) closedown); 326 (void) alarm(_RPCSVC_CLOSEDOWN/2); 327 } 328 329 /* Unlimited resource limits. */ 330 rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; 331 (void)setrlimit(RLIMIT_CPU, &rlim); 332 (void)setrlimit(RLIMIT_FSIZE, &rlim); 333 (void)setrlimit(RLIMIT_STACK, &rlim); 334 (void)setrlimit(RLIMIT_DATA, &rlim); 335 (void)setrlimit(RLIMIT_RSS, &rlim); 336 337 /* Don't drop core (not really necessary, but GP's). */ 338 rlim.rlim_cur = rlim.rlim_max = 0; 339 (void)setrlimit(RLIMIT_CORE, &rlim); 340 341 /* Turn off signals. */ 342 (void)signal(SIGALRM, SIG_IGN); 343 (void)signal(SIGHUP, (SIG_PF) reload); 344 (void)signal(SIGINT, SIG_IGN); 345 (void)signal(SIGPIPE, SIG_IGN); 346 (void)signal(SIGQUIT, SIG_IGN); 347 (void)signal(SIGTERM, (SIG_PF) terminate); 348 349 svc_run(); 350 yp_error("svc_run returned"); 351 exit(1); 352 /* NOTREACHED */ 353} 354