1/* 2 * Copyright (c) 1990,1993 Regents of The University of Michigan. 3 * All Rights Reserved. See COPYRIGHT. 4 */ 5 6#ifdef HAVE_CONFIG_H 7#include "config.h" 8#endif /* HAVE_CONFIG_H */ 9 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13#include <signal.h> 14 15#include <sys/param.h> 16#include <sys/uio.h> 17#include <atalk/logger.h> 18#include <sys/time.h> 19#include <sys/socket.h> 20#include <sys/poll.h> 21#include <errno.h> 22#include <sys/wait.h> 23#include <sys/resource.h> 24 25#include <atalk/adouble.h> 26 27#include <netatalk/at.h> 28#include <atalk/compat.h> 29#include <atalk/dsi.h> 30#include <atalk/atp.h> 31#include <atalk/asp.h> 32#include <atalk/afp.h> 33#include <atalk/paths.h> 34#include <atalk/util.h> 35#include <atalk/server_child.h> 36#include <atalk/server_ipc.h> 37#include <atalk/globals.h> 38 39#include "afp_config.h" 40#include "status.h" 41#include "fork.h" 42#include "uam_auth.h" 43#include "afp_zeroconf.h" 44 45#ifdef TRU64 46#include <sys/security.h> 47#include <prot.h> 48#include <sia.h> 49 50static int argc = 0; 51static char **argv = NULL; 52#endif /* TRU64 */ 53 54unsigned char nologin = 0; 55 56struct afp_options default_options; 57static AFPConfig *configs; 58static server_child *server_children; 59static sig_atomic_t reloadconfig = 0; 60 61/* Two pointers to dynamic allocated arrays which store pollfds and associated data */ 62static struct pollfd *fdset; 63static struct polldata *polldata; 64static int fdset_size; /* current allocated size */ 65static int fdset_used; /* number of used elements */ 66static int disasociated_ipc_fd; /* disasociated sessions uses this fd for IPC */ 67 68#ifdef TRU64 69void afp_get_cmdline( int *ac, char ***av) 70{ 71 *ac = argc; 72 *av = argv; 73} 74#endif /* TRU64 */ 75 76/* This is registered with atexit() */ 77static void afp_exit(void) 78{ 79 if (parent_or_child == 0) 80 /* Only do this in the parent */ 81 server_unlock(default_options.pidfile); 82} 83 84 85/* ------------------ 86 initialize fd set we are waiting for. 87*/ 88static void fd_set_listening_sockets(void) 89{ 90 AFPConfig *config; 91 92 for (config = configs; config; config = config->next) { 93 if (config->fd < 0) /* for proxies */ 94 continue; 95 fdset_add_fd(&fdset, &polldata, &fdset_used, &fdset_size, config->fd, LISTEN_FD, config); 96 } 97 fdset_add_fd(&fdset, &polldata, &fdset_used, &fdset_size, disasociated_ipc_fd, DISASOCIATED_IPC_FD, NULL); 98} 99 100static void fd_reset_listening_sockets(void) 101{ 102 AFPConfig *config; 103 104 for (config = configs; config; config = config->next) { 105 if (config->fd < 0) /* for proxies */ 106 continue; 107 fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, config->fd); 108 } 109 fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, disasociated_ipc_fd); 110} 111 112/* ------------------ */ 113static void afp_goaway(int sig) 114{ 115 AFPConfig *config; 116 117#ifndef NO_DDP 118 asp_kill(sig); 119#endif /* ! NO_DDP */ 120 121 switch( sig ) { 122 123 case SIGTERM: 124 case SIGQUIT: 125 switch (sig) { 126 case SIGTERM: 127 LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGTERM"); 128 break; 129 case SIGQUIT: 130 LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGQUIT, NOT disconnecting clients"); 131 break; 132 } 133 if (server_children) 134 server_child_kill(server_children, CHILD_DSIFORK, sig); 135 136 for (config = configs; config; config = config->next) 137 if (config->server_cleanup) 138 config->server_cleanup(config); 139 server_unlock(default_options.pidfile); 140 exit(0); 141 break; 142 143 case SIGUSR1 : 144 nologin++; 145 auth_unload(); 146 LOG(log_info, logtype_afpd, "disallowing logins"); 147 148 if (server_children) 149 server_child_kill(server_children, CHILD_DSIFORK, sig); 150 break; 151 152 case SIGHUP : 153 /* w/ a configuration file, we can force a re-read if we want */ 154 reloadconfig = 1; 155 break; 156 157 default : 158 LOG(log_error, logtype_afpd, "afp_goaway: bad signal" ); 159 } 160 return; 161} 162 163static void child_handler(int sig _U_) 164{ 165 int fd; 166 int status, i; 167 pid_t pid; 168 169#ifndef WAIT_ANY 170#define WAIT_ANY (-1) 171#endif /* ! WAIT_ANY */ 172 173 while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) { 174 for (i = 0; i < server_children->nforks; i++) { 175 if ((fd = server_child_remove(server_children, i, pid)) != -1) { 176 fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, fd); 177 break; 178 } 179 } 180 181 if (WIFEXITED(status)) { 182 if (WEXITSTATUS(status)) 183 LOG(log_info, logtype_afpd, "child[%d]: exited %d", pid, WEXITSTATUS(status)); 184 else 185 LOG(log_info, logtype_afpd, "child[%d]: done", pid); 186 } else { 187 if (WIFSIGNALED(status)) 188 LOG(log_info, logtype_afpd, "child[%d]: killed by signal %d", pid, WTERMSIG(status)); 189 else 190 LOG(log_info, logtype_afpd, "child[%d]: died", pid); 191 } 192 } 193} 194 195static int setlimits(void) 196{ 197 struct rlimit rlim; 198 199 if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) { 200 LOG(log_error, logtype_afpd, "setlimits: %s", strerror(errno)); 201 exit(1); 202 } 203 if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < 65535) { 204 rlim.rlim_cur = 65535; 205 if (rlim.rlim_max != RLIM_INFINITY && rlim.rlim_max < 65535) 206 rlim.rlim_max = 65535; 207 if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) { 208 LOG(log_error, logtype_afpd, "setlimits: %s", strerror(errno)); 209 exit(1); 210 } 211 } 212 return 0; 213} 214 215int main(int ac, char **av) 216{ 217 AFPConfig *config; 218 fd_set rfds; 219 void *ipc; 220 struct sigaction sv; 221 sigset_t sigs; 222 int ret; 223 int i; 224 225#ifdef TRU64 226 argc = ac; 227 argv = av; 228 set_auth_parameters( ac, av ); 229#endif /* TRU64 */ 230 231 /* Log SIGBUS/SIGSEGV SBT */ 232 fault_setup(NULL); 233 234 /* Default log setup: log to syslog */ 235 /*setuplog("default log_note");*/ /* Foxconn removed */ 236 237 afp_options_init(&default_options); 238 if (!afp_options_parse(ac, av, &default_options)) 239 exit(EXITERR_CONF); 240 241 /* Save the user's current umask for use with CNID (and maybe some 242 * other things, too). */ 243 default_options.save_mask = umask( default_options.umask ); 244 245 switch(server_lock("afpd", default_options.pidfile, 246 default_options.flags & OPTION_DEBUG)) { 247 case -1: /* error */ 248 exit(EXITERR_SYS); 249 case 0: /* child */ 250 break; 251 default: /* server */ 252 exit(0); 253 } 254 atexit(afp_exit); 255 256 /* install child handler for asp and dsi. we do this before afp_goaway 257 * as afp_goaway references stuff from here. 258 * XXX: this should really be setup after the initial connections. */ 259 if (!(server_children = server_child_alloc(default_options.connections, 260 CHILD_NFORKS))) { 261 LOG(log_error, logtype_afpd, "main: server_child alloc: %s", strerror(errno) ); 262 exit(EXITERR_SYS); 263 } 264 265 memset(&sv, 0, sizeof(sv)); 266 /* linux at least up to 2.4.22 send a SIGXFZ for vfat fs, 267 even if the file is open with O_LARGEFILE ! */ 268#ifdef SIGXFSZ 269 sv.sa_handler = SIG_IGN; 270 sigemptyset( &sv.sa_mask ); 271 if (sigaction(SIGXFSZ, &sv, NULL ) < 0 ) { 272 LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); 273 exit(EXITERR_SYS); 274 } 275#endif 276 277 sv.sa_handler = child_handler; 278 sigemptyset( &sv.sa_mask ); 279 sigaddset(&sv.sa_mask, SIGALRM); 280 sigaddset(&sv.sa_mask, SIGHUP); 281 sigaddset(&sv.sa_mask, SIGTERM); 282 sigaddset(&sv.sa_mask, SIGUSR1); 283 sigaddset(&sv.sa_mask, SIGQUIT); 284 sv.sa_flags = SA_RESTART; 285 if ( sigaction( SIGCHLD, &sv, NULL ) < 0 ) { 286 LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); 287 exit(EXITERR_SYS); 288 } 289 290 sv.sa_handler = afp_goaway; 291 sigemptyset( &sv.sa_mask ); 292 sigaddset(&sv.sa_mask, SIGALRM); 293 sigaddset(&sv.sa_mask, SIGTERM); 294 sigaddset(&sv.sa_mask, SIGHUP); 295 sigaddset(&sv.sa_mask, SIGCHLD); 296 sigaddset(&sv.sa_mask, SIGQUIT); 297 sv.sa_flags = SA_RESTART; 298 if ( sigaction( SIGUSR1, &sv, NULL ) < 0 ) { 299 LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); 300 exit(EXITERR_SYS); 301 } 302 303 sigemptyset( &sv.sa_mask ); 304 sigaddset(&sv.sa_mask, SIGALRM); 305 sigaddset(&sv.sa_mask, SIGTERM); 306 sigaddset(&sv.sa_mask, SIGUSR1); 307 sigaddset(&sv.sa_mask, SIGCHLD); 308 sigaddset(&sv.sa_mask, SIGQUIT); 309 sv.sa_flags = SA_RESTART; 310 if ( sigaction( SIGHUP, &sv, NULL ) < 0 ) { 311 LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); 312 exit(EXITERR_SYS); 313 } 314 315 316 sigemptyset( &sv.sa_mask ); 317 sigaddset(&sv.sa_mask, SIGALRM); 318 sigaddset(&sv.sa_mask, SIGHUP); 319 sigaddset(&sv.sa_mask, SIGUSR1); 320 sigaddset(&sv.sa_mask, SIGCHLD); 321 sigaddset(&sv.sa_mask, SIGQUIT); 322 sv.sa_flags = SA_RESTART; 323 if ( sigaction( SIGTERM, &sv, NULL ) < 0 ) { 324 LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); 325 exit(EXITERR_SYS); 326 } 327 328 sigemptyset( &sv.sa_mask ); 329 sigaddset(&sv.sa_mask, SIGALRM); 330 sigaddset(&sv.sa_mask, SIGHUP); 331 sigaddset(&sv.sa_mask, SIGUSR1); 332 sigaddset(&sv.sa_mask, SIGCHLD); 333 sigaddset(&sv.sa_mask, SIGTERM); 334 sv.sa_flags = SA_RESTART; 335 if (sigaction(SIGQUIT, &sv, NULL ) < 0 ) { 336 LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); 337 exit(EXITERR_SYS); 338 } 339 340 /* afpd.conf: not in config file: lockfile, connections, configfile 341 * preference: command-line provides defaults. 342 * config file over-writes defaults. 343 * 344 * we also need to make sure that killing afpd during startup 345 * won't leave any lingering registered names around. 346 */ 347 348 sigemptyset(&sigs); 349 sigaddset(&sigs, SIGALRM); 350 sigaddset(&sigs, SIGHUP); 351 sigaddset(&sigs, SIGUSR1); 352#if 0 353 /* don't block SIGTERM */ 354 sigaddset(&sigs, SIGTERM); 355#endif 356 sigaddset(&sigs, SIGCHLD); 357 358 pthread_sigmask(SIG_BLOCK, &sigs, NULL); 359 if (!(configs = configinit(&default_options))) { 360 LOG(log_error, logtype_afpd, "main: no servers configured"); 361 exit(EXITERR_CONF); 362 } 363 pthread_sigmask(SIG_UNBLOCK, &sigs, NULL); 364 365 /* Register CNID */ 366 cnid_init(); 367 368 /* watch atp, dsi sockets and ipc parent/child file descriptor. */ 369 disasociated_ipc_fd = ipc_server_uds(_PATH_AFP_IPC); 370 fd_set_listening_sockets(); 371 372 /* set limits */ 373 (void)setlimits(); 374 375 afp_child_t *child; 376 int fd[2]; /* we only use one, but server_child_add expects [2] */ 377 pid_t pid; 378 379 /* wait for an appleshare connection. parent remains in the loop 380 * while the children get handled by afp_over_{asp,dsi}. this is 381 * currently vulnerable to a denial-of-service attack if a 382 * connection is made without an actual login attempt being made 383 * afterwards. establishing timeouts for logins is a possible 384 * solution. */ 385 while (1) { 386 LOG(log_maxdebug, logtype_afpd, "main: polling %i fds", fdset_used); 387 pthread_sigmask(SIG_UNBLOCK, &sigs, NULL); 388 ret = poll(fdset, fdset_used, -1); 389 pthread_sigmask(SIG_BLOCK, &sigs, NULL); 390 int saveerrno = errno; 391 392 if (reloadconfig) { 393 nologin++; 394 auth_unload(); 395 fd_reset_listening_sockets(); 396 397 LOG(log_info, logtype_afpd, "re-reading configuration file"); 398 for (config = configs; config; config = config->next) 399 if (config->server_cleanup) 400 config->server_cleanup(config); 401 402 /* configfree close atp socket used for DDP tickle, there's an issue 403 * with atp tid. */ 404 configfree(configs, NULL); 405 if (!(configs = configinit(&default_options))) { 406 LOG(log_error, logtype_afpd, "config re-read: no servers configured"); 407 exit(EXITERR_CONF); 408 } 409 410 fd_set_listening_sockets(); 411 412 nologin = 0; 413 reloadconfig = 0; 414 errno = saveerrno; 415 continue; 416 } 417 418 if (ret == 0) 419 continue; 420 421 if (ret < 0) { 422 if (errno == EINTR) 423 continue; 424 LOG(log_error, logtype_afpd, "main: can't wait for input: %s", strerror(errno)); 425 break; 426 } 427 428 for (i = 0; i < fdset_used; i++) { 429 if (fdset[i].revents & (POLLIN | POLLERR | POLLHUP)) { 430 switch (polldata[i].fdtype) { 431 432 case LISTEN_FD: 433 config = (AFPConfig *)polldata[i].data; 434 /* config->server_start is afp_config.c:dsi_start() for DSI */ 435 if (child = config->server_start(config, configs, server_children)) { 436 /* Add IPC fd to select fd set */ 437 fdset_add_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fds[0], IPC_FD, child); 438 } 439 break; 440 441 case IPC_FD: 442 child = (afp_child_t *)polldata[i].data; 443 LOG(log_debug, logtype_afpd, "main: IPC request from child[%u]", child->pid); 444 445 if ((ret = ipc_server_read(server_children, child->ipc_fds[0])) == 0) { 446 fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fds[0]); 447 close(child->ipc_fds[0]); 448 child->ipc_fds[0] = -1; 449 if (child->disasociated) { 450 LOG(log_note, logtype_afpd, "main: removing reattached child[%u]", child->pid); 451 server_child_remove(server_children, CHILD_DSIFORK, child->pid); 452 } 453 } 454 break; 455 456 case DISASOCIATED_IPC_FD: 457 LOG(log_debug, logtype_afpd, "main: IPC reconnect request"); 458 if ((fd[0] = accept(disasociated_ipc_fd, NULL, NULL)) == -1) { 459 LOG(log_error, logtype_afpd, "main: accept: %s", strerror(errno)); 460 break; 461 } 462 if (readt(fd[0], &pid, sizeof(pid_t), 0, 1) != sizeof(pid_t)) { 463 LOG(log_error, logtype_afpd, "main: readt: %s", strerror(errno)); 464 close(fd[0]); 465 } 466 LOG(log_note, logtype_afpd, "main: IPC reconnect from [%u]", pid); 467 if ((child = server_child_add(server_children, CHILD_DSIFORK, pid, fd)) == NULL) { 468 LOG(log_error, logtype_afpd, "main: server_child_add"); 469 close(fd[0]); 470 break; 471 } 472 child->disasociated = 1; 473 fdset_add_fd(&fdset, &polldata, &fdset_used, &fdset_size, fd[0], IPC_FD, child); 474 break; 475 476 default: 477 LOG(log_debug, logtype_afpd, "main: IPC request for unknown type"); 478 break; 479 } /* switch */ 480 } /* if */ 481 } /* for (i)*/ 482 } /* while (1) */ 483 484 return 0; 485} 486