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