yppasswdd_main.c revision 14063
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.8 1996/02/09 04:21:35 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.8 1996/02/09 04:21:35 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; 96char *yp_dir = "/var/yp/"; 97int yp_sock; 98 99 100static void 101my_svc_run() 102{ 103#ifdef FD_SETSIZE 104 fd_set readfds; 105#else 106 int readfds; 107#endif /* def FD_SETSIZE */ 108 extern int errno; 109 110 for (;;) { 111 112 113#ifdef FD_SETSIZE 114 readfds = svc_fdset; 115#else 116 readfds = svc_fds; 117#endif /* def FD_SETSIZE */ 118 FD_SET(yp_sock, &readfds); 119 120 switch (select(_rpc_dtablesize(), &readfds, (fd_set *)0, (fd_set *)0, 121 (struct timeval *)0)) { 122 case -1: 123 if (errno == EINTR) { 124 continue; 125 } 126 perror("svc_run: - select failed"); 127 return; 128 case 0: 129 continue; 130 default: 131 if (FD_ISSET(yp_sock, &readfds)) { 132 do_master(); 133 FD_CLR(yp_sock, &readfds); 134 } 135 svc_getreqset(&readfds); 136 } 137 } 138} 139 140static void terminate(sig) 141 int sig; 142{ 143 svc_unregister(YPPASSWDPROG, YPPASSWDVERS); 144 close(yp_sock); 145 unlink(sockname); 146 exit(0); 147} 148 149static void 150closedown(int sig) 151{ 152 if (_rpcsvcstate == _IDLE) { 153 extern fd_set svc_fdset; 154 static int size; 155 int i, openfd; 156 157 if (_rpcfdtype == SOCK_DGRAM) { 158 close(yp_sock); 159 unlink(sockname); 160 exit(0); 161 } 162 if (size == 0) { 163 size = getdtablesize(); 164 } 165 for (i = 0, openfd = 0; i < size && openfd < 2; i++) 166 if (FD_ISSET(i, &svc_fdset)) 167 openfd++; 168 if (openfd <= 1) { 169 close(yp_sock); 170 unlink(sockname); 171 exit(0); 172 } 173 } 174 if (_rpcsvcstate == _SERVED) 175 _rpcsvcstate = _IDLE; 176 177 (void) signal(SIGALRM, (SIG_PF) closedown); 178 (void) alarm(_RPCSVC_CLOSEDOWN/2); 179} 180 181static void usage() 182{ 183 fprintf(stderr, "Usage: %s [-t master.passwd file] [-d domain] \ 184[-p path] [-s] [-f] [-m] [-a] [-v] [-h]\n", 185 progname); 186 exit(1); 187} 188 189main(argc, argv) 190 int argc; 191 char *argv[]; 192{ 193 register SVCXPRT *transp = NULL; 194 int sock; 195 int proto = 0; 196 struct sockaddr_in saddr; 197 int asize = sizeof (saddr); 198 int ch; 199 int rval; 200 char *mastername; 201 char myname[MAXHOSTNAMELEN + 2]; 202 extern int errno; 203 extern int debug; 204 205 debug = 1; 206 207 while ((ch = getopt(argc, argv, "t:d:p:sfamvh")) != EOF) { 208 switch(ch) { 209 case 't': 210 passfile_default = optarg; 211 break; 212 case 'd': 213 yppasswd_domain = optarg; 214 break; 215 case 's': 216 no_chsh++; 217 break; 218 case 'f': 219 no_chfn++; 220 break; 221 case 'p': 222 yp_dir = optarg; 223 break; 224 case 'a': 225 allow_additions++; 226 break; 227 case 'm': 228 multidomain++; 229 break; 230 case 'v': 231 verbose++; 232 break; 233 default: 234 case 'h': 235 usage(); 236 break; 237 } 238 } 239 240 if (yppasswd_domain == NULL) { 241 if (yp_get_default_domain(&yppasswd_domain)) { 242 yp_error("no domain specified and system domain \ 243name isn't set -- aborting"); 244 usage(); 245 } 246 } 247 248 if (getrpcport("localhost", YPPROG, YPVERS, IPPROTO_UDP) <= 0) { 249 yp_error("this host is not an NIS server -- aborting"); 250 exit(1); 251 } 252 253 if ((mastername = ypxfr_get_master(yppasswd_domain, "passwd.byname", 254 "localhost",0)) == NULL) { 255 yp_error("can't get name of NIS master server"); 256 exit(1); 257 } 258 259 if (gethostname((char *)&myname, sizeof(myname)) == -1) { 260 yp_error("can't get local hostname: %s", strerror(errno)); 261 exit(1); 262 } 263 264 if (strncmp(mastername, (char *)&myname, sizeof(myname))) { 265 yp_error("this host is not an NIS master server -- aborting"); 266 exit(1); 267 } 268 269 if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { 270 int ssize = sizeof (int); 271 272 if (saddr.sin_family != AF_INET) 273 exit(1); 274 if (getsockopt(0, SOL_SOCKET, SO_TYPE, 275 (char *)&_rpcfdtype, &ssize) == -1) 276 exit(1); 277 sock = 0; 278 _rpcpmstart = 1; 279 proto = 0; 280 openlog(progname, LOG_PID, LOG_DAEMON); 281 } else { 282#ifndef RPC_SVC_FG 283 int size; 284 int pid, i; 285 286 pid = fork(); 287 if (pid < 0) { 288 perror("cannot fork"); 289 exit(1); 290 } 291 if (pid) 292 exit(0); 293 size = getdtablesize(); 294 for (i = 0; i < size; i++) 295 (void) close(i); 296 i = open("/dev/console", 2); 297 (void) dup2(i, 1); 298 (void) dup2(i, 2); 299 i = open("/dev/tty", 2); 300 if (i >= 0) { 301 (void) ioctl(i, TIOCNOTTY, (char *)NULL); 302 (void) close(i); 303 } 304 openlog(progname, LOG_PID, LOG_DAEMON); 305#endif 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 resporce 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 unlink(sockname); 354 yp_sock = makeservsock(); 355 if (chmod(sockname, 0)) 356 err(1, "chmod of %s failed", sockname); 357 358 my_svc_run(); 359 yp_error("svc_run returned"); 360 exit(1); 361 /* NOTREACHED */ 362} 363