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