source: rtems-libbsd/ipsec-tools/src/racoon/session.c @ 6915758

Last change on this file since 6915758 was 6915758, checked in by Sebastian Huber <sebastian.huber@…>, on 06/10/22 at 05:58:11

ipsec-tools: Do not use signals

  • Property mode set to 100644
File size: 13.2 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2#ifdef __rtems__
3#include <machine/rtems-bsd-program.h>
4#include "rtems-bsd-racoon-namespace.h"
5#endif /* __rtems__ */
6/*      $NetBSD: session.c,v 1.32 2011/03/02 15:09:16 vanhu Exp $       */
7
8/*      $KAME: session.c,v 1.32 2003/09/24 02:01:17 jinmei Exp $        */
9
10/*
11 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 *    notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 *    notice, this list of conditions and the following disclaimer in the
21 *    documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the project nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39#include "config.h"
40
41#include <sys/types.h>
42#include <sys/param.h>
43#include <sys/time.h>
44#include <sys/socket.h>
45#if HAVE_SYS_WAIT_H
46# include <sys/wait.h>
47#endif
48#ifndef WEXITSTATUS
49# define WEXITSTATUS(s) ((unsigned)(s) >> 8)
50#endif
51#ifndef WIFEXITED
52# define WIFEXITED(s)   (((s) & 255) == 0)
53#endif
54
55#include PATH_IPSEC_H
56
57#include <stdlib.h>
58#include <stdio.h>
59#include <string.h>
60#include <errno.h>
61#ifdef HAVE_UNISTD_H
62#include <unistd.h>
63#endif
64#include <signal.h>
65#include <sys/stat.h>
66#include <paths.h>
67#include <err.h>
68#ifdef __rtems__
69#include <sys/param.h>
70#include <rtems/libio_.h>
71#endif /* __rtems__ */
72
73#include <netinet/in.h>
74#include <resolv.h>
75
76#include "libpfkey.h"
77
78#include "var.h"
79#include "misc.h"
80#include "vmbuf.h"
81#include "plog.h"
82#include "debug.h"
83
84#include "schedule.h"
85#include "session.h"
86#include "grabmyaddr.h"
87#include "evt.h"
88#include "cfparse_proto.h"
89#include "isakmp_var.h"
90#include "isakmp.h"
91#include "isakmp_var.h"
92#include "isakmp_xauth.h"
93#include "isakmp_cfg.h"
94#include "admin_var.h"
95#include "admin.h"
96#include "privsep.h"
97#include "oakley.h"
98#include "pfkey.h"
99#include "handler.h"
100#include "localconf.h"
101#include "remoteconf.h"
102#include "backupsa.h"
103#include "remoteconf.h"
104#ifdef ENABLE_NATT
105#include "nattraversal.h"
106#endif
107
108#include "algorithm.h" /* XXX ??? */
109
110#include "sainfo.h"
111
112struct fd_monitor {
113        int (*callback)(void *ctx, int fd);
114        void *ctx;
115        int prio;
116        int fd;
117        TAILQ_ENTRY(fd_monitor) chain;
118};
119
120#define NUM_PRIORITIES 2
121
122#ifndef __rtems__
123static void close_session __P((void));
124static void initfds __P((void));
125static void init_signal __P((void));
126static int set_signal __P((int sig, RETSIGTYPE (*func) __P((int))));
127static void check_sigreq __P((void));
128static void check_flushsa __P((void));
129static int close_sockets __P((void));
130#endif /* __rtems__ */
131
132#ifndef __rtems__
133static fd_set preset_mask, active_mask;
134static struct fd_monitor fd_monitors[FD_SETSIZE];
135#else /* __rtems__ */
136static fd_set *allocated_preset_mask, *allocated_active_mask;
137static struct fd_monitor *allocated_fd_monitors;
138#define preset_mask (*allocated_preset_mask)
139#define active_mask (*allocated_active_mask)
140#define fd_monitors (allocated_fd_monitors)
141#endif /* __rtems__ */
142static TAILQ_HEAD(fd_monitor_list, fd_monitor) fd_monitor_tree[NUM_PRIORITIES];
143static int nfds = 0;
144
145#ifndef __rtems__
146static volatile sig_atomic_t sigreq[NSIG + 1];
147static struct sched scflushsa = SCHED_INITIALIZER();
148#endif /* __rtems__ */
149
150void
151monitor_fd(int fd, int (*callback)(void *, int), void *ctx, int priority)
152{
153#ifndef __rtems__
154        if (fd < 0 || fd >= FD_SETSIZE) {
155#else /* __rtems__ */
156        if (fd < 0 || fd >= rtems_libio_number_iops) {
157#endif /* __rtems__ */
158                plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun");
159                exit(1);
160        }
161
162        FD_SET(fd, &preset_mask);
163        if (fd > nfds)
164                nfds = fd;
165        if (priority <= 0)
166                priority = 0;
167        if (priority >= NUM_PRIORITIES)
168                priority = NUM_PRIORITIES - 1;
169
170        fd_monitors[fd].callback = callback;
171        fd_monitors[fd].ctx = ctx;
172        fd_monitors[fd].prio = priority;
173        fd_monitors[fd].fd = fd;
174        TAILQ_INSERT_TAIL(&fd_monitor_tree[priority],
175                          &fd_monitors[fd], chain);
176}
177
178void
179unmonitor_fd(int fd)
180{
181#ifndef __rtems__
182        if (fd < 0 || fd >= FD_SETSIZE) {
183#else /* __rtems__ */
184        if (fd < 0 || fd >= rtems_libio_number_iops) {
185#endif /* __rtems__ */
186                plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun");
187                exit(1);
188        }
189
190        if (fd_monitors[fd].callback == NULL)
191                return;
192
193        FD_CLR(fd, &preset_mask);
194        FD_CLR(fd, &active_mask);
195        fd_monitors[fd].callback = NULL;
196        fd_monitors[fd].ctx = NULL;
197        TAILQ_REMOVE(&fd_monitor_tree[fd_monitors[fd].prio],
198                     &fd_monitors[fd], chain);
199}
200
201int
202session(void)
203{
204        struct timeval *timeout;
205        int error;
206#ifndef __rtems__
207        char pid_file[MAXPATHLEN];
208        FILE *fp;
209        pid_t racoon_pid = 0;
210#endif /* __rtems__ */
211        int i, count;
212        struct fd_monitor *fdm;
213
214        nfds = 0;
215#ifndef __rtems__
216        FD_ZERO(&preset_mask);
217#else /* __rtems__ */
218        allocated_preset_mask = calloc(sizeof(fd_set),
219            howmany(rtems_libio_number_iops, sizeof(fd_set) * 8));
220        if (allocated_preset_mask == NULL)
221                errx(1, "failed to allocate preset_mask");
222        allocated_active_mask = calloc(sizeof(fd_set),
223            howmany(rtems_libio_number_iops, sizeof(fd_set) * 8));
224        if (allocated_active_mask == NULL)
225                errx(1, "failed to allocate active_mask");
226        allocated_fd_monitors = calloc(
227            rtems_libio_number_iops, sizeof(struct fd_monitor));
228        if (allocated_fd_monitors == NULL)
229                errx(1, "failed to allocate fd_monitors");
230#endif /* __rtems__ */
231
232        for (i = 0; i < NUM_PRIORITIES; i++)
233                TAILQ_INIT(&fd_monitor_tree[i]);
234
235        /* initialize schedular */
236        sched_init();
237#ifndef __rtems__
238        init_signal();
239#endif /* __rtems__ */
240
241        if (pfkey_init() < 0)
242                errx(1, "failed to initialize pfkey socket");
243
244        if (isakmp_init() < 0)
245                errx(1, "failed to initialize ISAKMP structures");
246
247#ifdef ENABLE_HYBRID
248        if (isakmp_cfg_init(ISAKMP_CFG_INIT_COLD))
249                errx(1, "could not initialize ISAKMP mode config structures");
250#endif
251
252#ifdef HAVE_LIBLDAP
253        if (xauth_ldap_init_conf() != 0)
254                errx(1, "could not initialize ldap config");
255#endif
256
257#ifdef HAVE_LIBRADIUS
258        if (xauth_radius_init_conf(0) != 0)
259                errx(1, "could not initialize radius config");
260#endif
261
262        myaddr_init_lists();
263
264        /*
265         * in order to prefer the parameters by command line,
266         * saving some parameters before parsing configuration file.
267         */
268        save_params();
269        if (cfparse() != 0)
270                errx(1, "failed to parse configuration file.");
271        restore_params();
272
273#ifdef ENABLE_ADMINPORT
274        if (admin_init() < 0)
275                errx(1, "failed to initialize admin port socket");
276#endif
277
278
279#ifdef ENABLE_HYBRID
280        if(isakmp_cfg_config.network4 && isakmp_cfg_config.pool_size == 0)
281                if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
282                        return error;
283#endif
284
285        if (dump_config)
286                dumprmconf();
287
288#ifdef HAVE_LIBRADIUS
289        if (xauth_radius_init() != 0)
290                errx(1, "could not initialize libradius");
291#endif
292
293        if (myaddr_init() != 0)
294                errx(1, "failed to listen to configured addresses");
295        myaddr_sync();
296
297#ifdef ENABLE_NATT
298        natt_keepalive_init ();
299#endif
300
301#ifndef __rtems__
302        /* write .pid file */
303        if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE] == NULL)
304                strlcpy(pid_file, _PATH_VARRUN "racoon.pid", MAXPATHLEN);
305        else if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE][0] == '/')
306                strlcpy(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
307        else {
308                strlcat(pid_file, _PATH_VARRUN, MAXPATHLEN);
309                strlcat(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
310        }
311        fp = fopen(pid_file, "w");
312        if (fp) {
313                if (fchmod(fileno(fp),
314                        S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
315                        syslog(LOG_ERR, "%s", strerror(errno));
316                        fclose(fp);
317                        exit(1);
318                }
319        } else {
320                plog(LLV_ERROR, LOCATION, NULL,
321                        "cannot open %s", pid_file);
322        }
323#endif /* __rtems__ */
324
325        if (privsep_init() != 0)
326                exit(1);
327
328#ifndef __rtems__
329        /*
330         * The fork()'ed privileged side will close its copy of fp.  We wait
331         * until here to get the correct child pid.
332         */
333        racoon_pid = getpid();
334        fprintf(fp, "%ld\n", (long)racoon_pid);
335        fclose(fp);
336
337        for (i = 0; i <= NSIG; i++)
338                sigreq[i] = 0;
339#endif /* __rtems__ */
340
341        while (1) {
342#ifndef __rtems__
343                /*
344                 * asynchronous requests via signal.
345                 * make sure to reset sigreq to 0.
346                 */
347                check_sigreq();
348#endif /* __rtems__ */
349
350                /* scheduling */
351                timeout = schedular();
352
353                /* schedular can change select() mask, so we reset
354                 * the working copy here */
355                active_mask = preset_mask;
356
357                error = select(nfds + 1, &active_mask, NULL, NULL, timeout);
358                if (error < 0) {
359                        switch (errno) {
360                        case EINTR:
361                                continue;
362                        default:
363                                plog(LLV_ERROR, LOCATION, NULL,
364                                        "failed to select (%s)\n",
365                                        strerror(errno));
366                                return -1;
367                        }
368                        /*NOTREACHED*/
369                }
370
371                count = 0;
372                for (i = 0; i < NUM_PRIORITIES; i++) {
373                        TAILQ_FOREACH(fdm, &fd_monitor_tree[i], chain) {
374                                if (!FD_ISSET(fdm->fd, &active_mask))
375                                        continue;
376
377                                FD_CLR(fdm->fd, &active_mask);
378                                if (fdm->callback != NULL) {
379                                        fdm->callback(fdm->ctx, fdm->fd);
380                                        count++;
381                                } else
382                                        plog(LLV_ERROR, LOCATION, NULL,
383                                        "fd %d set, but no active callback\n", i);
384                        }
385                        if (count != 0)
386                                break;
387                }
388
389        }
390}
391
392#ifndef __rtems__
393/* clear all status and exit program. */
394static void
395close_session()
396{
397        evt_generic(EVT_RACOON_QUIT, NULL);
398        pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC);
399        flushph2();
400        flushph1();
401        flushrmconf();
402        flushsainfo();
403        close_sockets();
404        backupsa_clean();
405
406        plog(LLV_INFO, LOCATION, NULL, "racoon process %d shutdown\n", getpid());
407
408        exit(0);
409}
410
411static int signals[] = {
412        SIGHUP,
413        SIGINT,
414        SIGTERM,
415        SIGUSR1,
416        SIGUSR2,
417        SIGCHLD,
418        0
419};
420
421/*
422 * asynchronous requests will actually dispatched in the
423 * main loop in session().
424 */
425RETSIGTYPE
426signal_handler(sig)
427        int sig;
428{
429        sigreq[sig] = 1;
430}
431
432
433/* XXX possible mem leaks and no way to go back for now !!!
434 */
435static void reload_conf(){
436        int error;
437
438#ifdef ENABLE_HYBRID
439        if ((isakmp_cfg_init(ISAKMP_CFG_INIT_WARM)) != 0) {
440                plog(LLV_ERROR, LOCATION, NULL,
441                    "ISAKMP mode config structure reset failed, "
442                    "not reloading\n");
443                return;
444        }
445#endif
446
447        sainfo_start_reload();
448
449        /* TODO: save / restore / flush old lcconf (?) / rmtree
450         */
451        rmconf_start_reload();
452
453#ifdef HAVE_LIBRADIUS
454        /* free and init radius configuration */
455        xauth_radius_init_conf(1);
456#endif
457
458        pfkey_reload();
459
460        save_params();
461        flushlcconf();
462        error = cfparse();
463        if (error != 0){
464                plog(LLV_ERROR, LOCATION, NULL, "config reload failed\n");
465                /* We are probably in an inconsistant state... */
466                return;
467        }
468        restore_params();
469
470#if 0
471        if (dump_config)
472                dumprmconf ();
473#endif
474
475        myaddr_sync();
476
477#ifdef HAVE_LIBRADIUS
478        /* re-initialize radius state */
479        xauth_radius_init();
480#endif
481
482        /* Revalidate ph1 / ph2tree !!!
483         * update ctdtree if removing some ph1 !
484         */
485        revalidate_ph12();
486        /* Update ctdtree ?
487         */
488
489        sainfo_finish_reload();
490        rmconf_finish_reload();
491}
492
493static void
494check_sigreq()
495{
496        int sig, s;
497
498        for (sig = 0; sig <= NSIG; sig++) {
499                if (sigreq[sig] == 0)
500                        continue;
501                sigreq[sig] = 0;
502
503                switch(sig) {
504                case 0:
505                        return;
506
507                case SIGCHLD:
508                        /* Reap all pending children */
509                        while (waitpid(-1, &s, WNOHANG) > 0)
510                                ;
511                        break;
512
513#ifdef DEBUG_RECORD_MALLOCATION
514                /*
515                 * XXX This operation is signal handler unsafe and may lead to
516                 * crashes and security breaches: See Henning Brauer talk at
517                 * EuroBSDCon 2005. Do not run in production with this option
518                 * enabled.
519                 */
520                case SIGUSR2:
521                        DRM_dump();
522                        break;
523#endif
524
525                case SIGHUP:
526                        /* Save old configuration, load new one...  */
527                        reload_conf();
528                        break;
529
530                case SIGINT:
531                case SIGTERM:
532                        plog(LLV_INFO, LOCATION, NULL,
533                            "caught signal %d\n", sig);
534                        close_session();
535                        break;
536
537                default:
538                        plog(LLV_INFO, LOCATION, NULL,
539                            "caught signal %d\n", sig);
540                        break;
541                }
542        }
543}
544
545static void
546init_signal()
547{
548        int i;
549
550        /*
551         * Ignore SIGPIPE as we check the return value of system calls
552         * that write to pipe-like fds.
553         */
554        signal(SIGPIPE, SIG_IGN);
555
556        for (i = 0; signals[i] != 0; i++)
557                if (set_signal(signals[i], signal_handler) < 0) {
558                        plog(LLV_ERROR, LOCATION, NULL,
559                                "failed to set_signal (%s)\n",
560                                strerror(errno));
561                        exit(1);
562                }
563}
564
565static int
566set_signal(sig, func)
567        int sig;
568        RETSIGTYPE (*func) __P((int));
569{
570        struct sigaction sa;
571
572        memset((caddr_t)&sa, 0, sizeof(sa));
573        sa.sa_handler = func;
574        sa.sa_flags = SA_RESTART;
575
576        if (sigemptyset(&sa.sa_mask) < 0)
577                return -1;
578
579        if (sigaction(sig, &sa, (struct sigaction *)0) < 0)
580                return(-1);
581
582        return 0;
583}
584
585static int
586close_sockets()
587{
588        myaddr_close();
589        pfkey_close(lcconf->sock_pfkey);
590#ifdef ENABLE_ADMINPORT
591        (void)admin_close();
592#endif
593        return 0;
594}
595#endif /* __rtems__ */
596
597#ifdef __rtems__
598#include "rtems-bsd-racoon-session-data.h"
599#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.