yppasswdd_main.c revision 19096
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.4 1996/06/23 22:44:04 wpaul 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.4 1996/06/23 22:44:04 wpaul 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 197main(argc, argv) 198 int argc; 199 char *argv[]; 200{ 201 register SVCXPRT *transp = NULL; 202 int sock; 203 int proto = 0; 204 struct sockaddr_in saddr; 205 int asize = sizeof (saddr); 206 int ch; 207 int rval; 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")) != EOF) { 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("this host is not an NIS server -- aborting"); 266 exit(1); 267 } 268 269 if ((mastername = ypxfr_get_master(yppasswd_domain, "passwd.byname", 270 "localhost",0)) == NULL) { 271 yp_error("can't get name of NIS master server"); 272 exit(1); 273 } 274 275 if (gethostname((char *)&myname, sizeof(myname)) == -1) { 276 yp_error("can't get local hostname: %s", strerror(errno)); 277 exit(1); 278 } 279 280 if (strncmp(mastername, (char *)&myname, sizeof(myname))) { 281 yp_error("this host is not an NIS master server -- aborting"); 282 exit(1); 283 } 284 285 debug = 0; 286 287 if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { 288 int ssize = sizeof (int); 289 290 if (saddr.sin_family != AF_INET) 291 exit(1); 292 if (getsockopt(0, SOL_SOCKET, SO_TYPE, 293 (char *)&_rpcfdtype, &ssize) == -1) 294 exit(1); 295 sock = 0; 296 _rpcpmstart = 1; 297 proto = 0; 298 openlog(progname, LOG_PID, LOG_DAEMON); 299 } else { 300 if (!debug) { 301 if (daemon(0,0)) { 302 err(1,"cannot fork"); 303 } 304 } 305 openlog(progname, LOG_PID, LOG_DAEMON); 306 sock = RPC_ANYSOCK; 307 (void) pmap_unset(YPPASSWDPROG, YPPASSWDVERS); 308 } 309 310 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { 311 transp = svcudp_create(sock); 312 if (transp == NULL) { 313 yp_error("cannot create udp service."); 314 exit(1); 315 } 316 if (!_rpcpmstart) 317 proto = IPPROTO_UDP; 318 if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) { 319 yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, udp)."); 320 exit(1); 321 } 322 } 323 324 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { 325 transp = svctcp_create(sock, 0, 0); 326 if (transp == NULL) { 327 yp_error("cannot create tcp service."); 328 exit(1); 329 } 330 if (!_rpcpmstart) 331 proto = IPPROTO_TCP; 332 if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) { 333 yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, tcp)."); 334 exit(1); 335 } 336 } 337 338 if (transp == (SVCXPRT *)NULL) { 339 yp_error("could not create a handle"); 340 exit(1); 341 } 342 if (_rpcpmstart) { 343 (void) signal(SIGALRM, (SIG_PF) closedown); 344 (void) alarm(_RPCSVC_CLOSEDOWN/2); 345 } 346 /* set up resource limits and block signals */ 347 pw_init(); 348 349 /* except SIGCHLD, which we need to catch */ 350 install_reaper(1); 351 signal(SIGTERM, (SIG_PF) terminate); 352 353 signal(SIGHUP, (SIG_PF) reload); 354 355 unlink(sockname); 356 yp_sock = makeservsock(); 357 if (chmod(sockname, 0)) 358 err(1, "chmod of %s failed", sockname); 359 360 my_svc_run(); 361 yp_error("svc_run returned"); 362 exit(1); 363 /* NOTREACHED */ 364} 365