yppasswdd_main.c revision 14241
11797Sphk/* 21797Sphk * Copyright (c) 1995, 1996 31797Sphk * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 41797Sphk * 51797Sphk * Redistribution and use in source and binary forms, with or without 61797Sphk * modification, are permitted provided that the following conditions 71797Sphk * are met: 81797Sphk * 1. Redistributions of source code must retain the above copyright 91797Sphk * notice, this list of conditions and the following disclaimer. 101797Sphk * 2. Redistributions in binary form must reproduce the above copyright 111797Sphk * notice, this list of conditions and the following disclaimer in the 121797Sphk * documentation and/or other materials provided with the distribution. 131797Sphk * 3. All advertising materials mentioning features or use of this software 141797Sphk * must display the following acknowledgement: 151797Sphk * This product includes software developed by Bill Paul. 161797Sphk * 4. Neither the name of the author nor the names of any co-contributors 171797Sphk * 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.10 1996/02/24 21:41:15 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.10 1996/02/24 21:41:15 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 *passfile_default = "/var/yp/master.passwd"; 89char *passfile; 90char *yppasswd_domain = NULL; 91int no_chsh = 0; 92int no_chfn = 0; 93int allow_additions = 0; 94int multidomain = 0; 95int verbose = 0; 96int resvport = 1; 97char *yp_dir = "/var/yp/"; 98int yp_sock; 99 100 101static void 102my_svc_run() 103{ 104#ifdef FD_SETSIZE 105 fd_set readfds; 106#else 107 int readfds; 108#endif /* def FD_SETSIZE */ 109 extern int errno; 110 111 for (;;) { 112 113 114#ifdef FD_SETSIZE 115 readfds = svc_fdset; 116#else 117 readfds = svc_fds; 118#endif /* def FD_SETSIZE */ 119 FD_SET(yp_sock, &readfds); 120 121 switch (select(_rpc_dtablesize(), &readfds, (fd_set *)0, (fd_set *)0, 122 (struct timeval *)0)) { 123 case -1: 124 if (errno == EINTR) { 125 continue; 126 } 127 perror("svc_run: - select failed"); 128 return; 129 case 0: 130 continue; 131 default: 132 if (FD_ISSET(yp_sock, &readfds)) { 133 do_master(); 134 FD_CLR(yp_sock, &readfds); 135 } 136 svc_getreqset(&readfds); 137 } 138 } 139} 140 141static void terminate(sig) 142 int sig; 143{ 144 svc_unregister(YPPASSWDPROG, YPPASSWDVERS); 145 close(yp_sock); 146 unlink(sockname); 147 exit(0); 148} 149 150static void reload(sig) 151 int sig; 152{ 153 load_securenets(); 154} 155 156static void 157closedown(int sig) 158{ 159 if (_rpcsvcstate == _IDLE) { 160 extern fd_set svc_fdset; 161 static int size; 162 int i, openfd; 163 164 if (_rpcfdtype == SOCK_DGRAM) { 165 close(yp_sock); 166 unlink(sockname); 167 exit(0); 168 } 169 if (size == 0) { 170 size = getdtablesize(); 171 } 172 for (i = 0, openfd = 0; i < size && openfd < 2; i++) 173 if (FD_ISSET(i, &svc_fdset)) 174 openfd++; 175 if (openfd <= 1) { 176 close(yp_sock); 177 unlink(sockname); 178 exit(0); 179 } 180 } 181 if (_rpcsvcstate == _SERVED) 182 _rpcsvcstate = _IDLE; 183 184 (void) signal(SIGALRM, (SIG_PF) closedown); 185 (void) alarm(_RPCSVC_CLOSEDOWN/2); 186} 187 188static void usage() 189{ 190 fprintf(stderr, "Usage: %s [-t master.passwd file] [-d domain] \ 191[-p path] [-s] [-f] [-m] [-a] [-v] [-u] [-h]\n", 192 progname); 193 exit(1); 194} 195 196main(argc, argv) 197 int argc; 198 char *argv[]; 199{ 200 register SVCXPRT *transp = NULL; 201 int sock; 202 int proto = 0; 203 struct sockaddr_in saddr; 204 int asize = sizeof (saddr); 205 int ch; 206 int rval; 207 char *mastername; 208 char myname[MAXHOSTNAMELEN + 2]; 209 extern int errno; 210 extern int debug; 211 212 debug = 1; 213 214 while ((ch = getopt(argc, argv, "t:d:p:sfamvh")) != EOF) { 215 switch(ch) { 216 case 't': 217 passfile_default = optarg; 218 break; 219 case 'd': 220 yppasswd_domain = optarg; 221 break; 222 case 's': 223 no_chsh++; 224 break; 225 case 'f': 226 no_chfn++; 227 break; 228 case 'p': 229 yp_dir = optarg; 230 break; 231 case 'a': 232 allow_additions++; 233 break; 234 case 'm': 235 multidomain++; 236 break; 237 case 'v': 238 verbose++; 239 break; 240 case 'u': 241 resvport = 0; 242 break; 243 default: 244 case 'h': 245 usage(); 246 break; 247 } 248 } 249 250 if (yppasswd_domain == NULL) { 251 if (yp_get_default_domain(&yppasswd_domain)) { 252 yp_error("no domain specified and system domain \ 253name isn't set -- aborting"); 254 usage(); 255 } 256 } 257 258 load_securenets(); 259 260 if (getrpcport("localhost", YPPROG, YPVERS, IPPROTO_UDP) <= 0) { 261 yp_error("this host is not an NIS server -- aborting"); 262 exit(1); 263 } 264 265 if ((mastername = ypxfr_get_master(yppasswd_domain, "passwd.byname", 266 "localhost",0)) == NULL) { 267 yp_error("can't get name of NIS master server"); 268 exit(1); 269 } 270 271 if (gethostname((char *)&myname, sizeof(myname)) == -1) { 272 yp_error("can't get local hostname: %s", strerror(errno)); 273 exit(1); 274 } 275 276 if (strncmp(mastername, (char *)&myname, sizeof(myname))) { 277 yp_error("this host is not an NIS master server -- aborting"); 278 exit(1); 279 } 280 281 debug = 0; 282 283 if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { 284 int ssize = sizeof (int); 285 286 if (saddr.sin_family != AF_INET) 287 exit(1); 288 if (getsockopt(0, SOL_SOCKET, SO_TYPE, 289 (char *)&_rpcfdtype, &ssize) == -1) 290 exit(1); 291 sock = 0; 292 _rpcpmstart = 1; 293 proto = 0; 294 openlog(progname, LOG_PID, LOG_DAEMON); 295 } else { 296#ifndef RPC_SVC_FG 297 int size; 298 int pid, i; 299 300 pid = fork(); 301 if (pid < 0) { 302 perror("cannot fork"); 303 exit(1); 304 } 305 if (pid) 306 exit(0); 307 size = getdtablesize(); 308 for (i = 0; i < size; i++) 309 (void) close(i); 310 i = open("/dev/console", 2); 311 (void) dup2(i, 1); 312 (void) dup2(i, 2); 313 i = open("/dev/tty", 2); 314 if (i >= 0) { 315 (void) ioctl(i, TIOCNOTTY, (char *)NULL); 316 (void) close(i); 317 } 318 openlog(progname, LOG_PID, LOG_DAEMON); 319#endif 320 sock = RPC_ANYSOCK; 321 (void) pmap_unset(YPPASSWDPROG, YPPASSWDVERS); 322 } 323 324 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { 325 transp = svcudp_create(sock); 326 if (transp == NULL) { 327 yp_error("cannot create udp service."); 328 exit(1); 329 } 330 if (!_rpcpmstart) 331 proto = IPPROTO_UDP; 332 if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) { 333 yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, udp)."); 334 exit(1); 335 } 336 } 337 338 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { 339 transp = svctcp_create(sock, 0, 0); 340 if (transp == NULL) { 341 yp_error("cannot create tcp service."); 342 exit(1); 343 } 344 if (!_rpcpmstart) 345 proto = IPPROTO_TCP; 346 if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) { 347 yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, tcp)."); 348 exit(1); 349 } 350 } 351 352 if (transp == (SVCXPRT *)NULL) { 353 yp_error("could not create a handle"); 354 exit(1); 355 } 356 if (_rpcpmstart) { 357 (void) signal(SIGALRM, (SIG_PF) closedown); 358 (void) alarm(_RPCSVC_CLOSEDOWN/2); 359 } 360 /* set up resource limits and block signals */ 361 pw_init(); 362 363 /* except SIGCHLD, which we need to catch */ 364 install_reaper(1); 365 signal(SIGTERM, (SIG_PF) terminate); 366 367 signal(SIGHUP, (SIG_PF) reload); 368 369 unlink(sockname); 370 yp_sock = makeservsock(); 371 if (chmod(sockname, 0)) 372 err(1, "chmod of %s failed", sockname); 373 374 my_svc_run(); 375 yp_error("svc_run returned"); 376 exit(1); 377 /* NOTREACHED */ 378} 379