yppasswdd_main.c revision 24428
1/* 2 * Copyright (c) 1995, 1996 3 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Bill Paul. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $Id: yppasswdd_main.c,v 1.9 1997/02/22 16:12:56 peter Exp $ 33 */ 34 35#include "yppasswd.h" 36#include <stdio.h> 37#include <sys/types.h> 38#include <stdlib.h> /* getenv, exit */ 39#include <unistd.h> 40#include <string.h> 41#include <sys/param.h> 42#include <rpc/pmap_clnt.h> /* for pmap_unset */ 43#include <string.h> /* strcmp */ 44#include <signal.h> 45#include <fcntl.h> 46#include <sys/ioctl.h> 47#include <sys/stat.h> 48#include <sys/ttycom.h> /* TIOCNOTTY */ 49#ifdef __cplusplus 50#include <sysent.h> /* getdtablesize, open */ 51#endif /* __cplusplus */ 52#include <memory.h> 53#include <sys/socket.h> 54#include <netinet/in.h> 55#include <syslog.h> 56#include <err.h> 57#include <errno.h> 58#include <rpcsvc/yp.h> 59struct dom_binding {}; 60#include <rpcsvc/ypclnt.h> 61#include "yppasswdd_extern.h" 62#include "yppasswd_comm.h" 63#include "ypxfr_extern.h" 64 65#ifndef SIG_PF 66#define SIG_PF void(*)(int) 67#endif 68 69#ifdef DEBUG 70#define RPC_SVC_FG 71#endif 72 73#define _RPCSVC_CLOSEDOWN 120 74#ifndef lint 75static const char rcsid[] = "$Id: yppasswdd_main.c,v 1.9 1997/02/22 16:12:56 peter Exp $"; 76#endif /* not lint */ 77int _rpcpmstart = 0; /* Started by a port monitor ? */ 78static int _rpcfdtype; 79 /* Whether Stream or Datagram ? */ 80 /* States a server can be in wrt request */ 81 82#define _IDLE 0 83#define _SERVED 1 84#define _SERVING 2 85 86extern int _rpcsvcstate; /* Set when a request is serviced */ 87char *progname = "rpc.yppasswdd"; 88char *yp_dir = _PATH_YP; 89char *passfile_default = _PATH_YP "master.passwd"; 90char *passfile; 91char *yppasswd_domain = NULL; 92int no_chsh = 0; 93int no_chfn = 0; 94int allow_additions = 0; 95int multidomain = 0; 96int verbose = 0; 97int resvport = 1; 98int inplace = 0; 99int yp_sock; 100 101 102static void 103my_svc_run() 104{ 105#ifdef FD_SETSIZE 106 fd_set readfds; 107#else 108 int readfds; 109#endif /* def FD_SETSIZE */ 110 extern int errno; 111 112 for (;;) { 113 114 115#ifdef FD_SETSIZE 116 readfds = svc_fdset; 117#else 118 readfds = svc_fds; 119#endif /* def FD_SETSIZE */ 120 FD_SET(yp_sock, &readfds); 121 122 switch (select(_rpc_dtablesize(), &readfds, (fd_set *)0, (fd_set *)0, 123 (struct timeval *)0)) { 124 case -1: 125 if (errno == EINTR) { 126 continue; 127 } 128 perror("svc_run: - select failed"); 129 return; 130 case 0: 131 continue; 132 default: 133 if (FD_ISSET(yp_sock, &readfds)) { 134 do_master(); 135 FD_CLR(yp_sock, &readfds); 136 } 137 svc_getreqset(&readfds); 138 } 139 } 140} 141 142static void terminate(sig) 143 int sig; 144{ 145 svc_unregister(YPPASSWDPROG, YPPASSWDVERS); 146 close(yp_sock); 147 unlink(sockname); 148 exit(0); 149} 150 151static void reload(sig) 152 int sig; 153{ 154 load_securenets(); 155} 156 157static void 158closedown(int sig) 159{ 160 if (_rpcsvcstate == _IDLE) { 161 extern fd_set svc_fdset; 162 static int size; 163 int i, openfd; 164 165 if (_rpcfdtype == SOCK_DGRAM) { 166 close(yp_sock); 167 unlink(sockname); 168 exit(0); 169 } 170 if (size == 0) { 171 size = getdtablesize(); 172 } 173 for (i = 0, openfd = 0; i < size && openfd < 2; i++) 174 if (FD_ISSET(i, &svc_fdset)) 175 openfd++; 176 if (openfd <= 1) { 177 close(yp_sock); 178 unlink(sockname); 179 exit(0); 180 } 181 } 182 if (_rpcsvcstate == _SERVED) 183 _rpcsvcstate = _IDLE; 184 185 (void) signal(SIGALRM, (SIG_PF) closedown); 186 (void) alarm(_RPCSVC_CLOSEDOWN/2); 187} 188 189static void usage() 190{ 191 fprintf(stderr, "Usage: %s [-t master.passwd file] [-d domain] \ 192[-p path] [-s] [-f] [-m] [-i] [-a] [-v] [-u] [-h]\n", 193 progname); 194 exit(1); 195} 196 197int 198main(argc, argv) 199 int argc; 200 char *argv[]; 201{ 202 register SVCXPRT *transp = NULL; 203 int sock; 204 int proto = 0; 205 struct sockaddr_in saddr; 206 int asize = sizeof (saddr); 207 int ch; 208 char *mastername; 209 char myname[MAXHOSTNAMELEN + 2]; 210 extern int errno; 211 extern int debug; 212 213 debug = 1; 214 215 while ((ch = getopt(argc, argv, "t:d:p:sfamuivh")) != -1) { 216 switch(ch) { 217 case 't': 218 passfile_default = optarg; 219 break; 220 case 'd': 221 yppasswd_domain = optarg; 222 break; 223 case 's': 224 no_chsh++; 225 break; 226 case 'f': 227 no_chfn++; 228 break; 229 case 'p': 230 yp_dir = optarg; 231 break; 232 case 'a': 233 allow_additions++; 234 break; 235 case 'm': 236 multidomain++; 237 break; 238 case 'i': 239 inplace++; 240 break; 241 case 'v': 242 verbose++; 243 break; 244 case 'u': 245 resvport = 0; 246 break; 247 default: 248 case 'h': 249 usage(); 250 break; 251 } 252 } 253 254 if (yppasswd_domain == NULL) { 255 if (yp_get_default_domain(&yppasswd_domain)) { 256 yp_error("no domain specified and system domain \ 257name isn't set -- aborting"); 258 usage(); 259 } 260 } 261 262 load_securenets(); 263 264 if (getrpcport("localhost", YPPROG, YPVERS, IPPROTO_UDP) <= 0) { 265 yp_error("no ypserv processes registered with local portmap"); 266 yp_error("this host is not an NIS server -- aborting"); 267 exit(1); 268 } 269 270 if ((mastername = ypxfr_get_master(yppasswd_domain, "passwd.byname", 271 "localhost",0)) == NULL) { 272 yp_error("can't get name of NIS master server for domain %s", 273 yppasswd_domain); 274 exit(1); 275 } 276 277 if (gethostname((char *)&myname, sizeof(myname)) == -1) { 278 yp_error("can't get local hostname: %s", strerror(errno)); 279 exit(1); 280 } 281 282 if (strncmp(mastername, (char *)&myname, sizeof(myname))) { 283 yp_error("master of %s is %s, but we are %s", 284 "passwd.byname", mastername, myname); 285 yp_error("this host is not the NIS master server for \ 286the %s domain -- aborting", yppasswd_domain); 287 exit(1); 288 } 289 290 debug = 0; 291 292 if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { 293 int ssize = sizeof (int); 294 295 if (saddr.sin_family != AF_INET) 296 exit(1); 297 if (getsockopt(0, SOL_SOCKET, SO_TYPE, 298 (char *)&_rpcfdtype, &ssize) == -1) 299 exit(1); 300 sock = 0; 301 _rpcpmstart = 1; 302 proto = 0; 303 openlog(progname, LOG_PID, LOG_DAEMON); 304 } else { 305 if (!debug) { 306 if (daemon(0,0)) { 307 err(1,"cannot fork"); 308 } 309 } 310 openlog(progname, LOG_PID, LOG_DAEMON); 311 sock = RPC_ANYSOCK; 312 (void) pmap_unset(YPPASSWDPROG, YPPASSWDVERS); 313 } 314 315 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { 316 transp = svcudp_create(sock); 317 if (transp == NULL) { 318 yp_error("cannot create udp service."); 319 exit(1); 320 } 321 if (!_rpcpmstart) 322 proto = IPPROTO_UDP; 323 if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) { 324 yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, udp)."); 325 exit(1); 326 } 327 } 328 329 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { 330 transp = svctcp_create(sock, 0, 0); 331 if (transp == NULL) { 332 yp_error("cannot create tcp service."); 333 exit(1); 334 } 335 if (!_rpcpmstart) 336 proto = IPPROTO_TCP; 337 if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) { 338 yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, tcp)."); 339 exit(1); 340 } 341 } 342 343 if (transp == (SVCXPRT *)NULL) { 344 yp_error("could not create a handle"); 345 exit(1); 346 } 347 if (_rpcpmstart) { 348 (void) signal(SIGALRM, (SIG_PF) closedown); 349 (void) alarm(_RPCSVC_CLOSEDOWN/2); 350 } 351 /* set up resource limits and block signals */ 352 pw_init(); 353 354 /* except SIGCHLD, which we need to catch */ 355 install_reaper(1); 356 signal(SIGTERM, (SIG_PF) terminate); 357 358 signal(SIGHUP, (SIG_PF) reload); 359 360 unlink(sockname); 361 yp_sock = makeservsock(); 362 if (chmod(sockname, 0)) 363 err(1, "chmod of %s failed", sockname); 364 365 my_svc_run(); 366 yp_error("svc_run returned"); 367 exit(1); 368 /* NOTREACHED */ 369} 370