No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / ipsec-tools / src / racoon / session.c
blob9c2c60e3a094b8451d0beb3f35ede9746270dc56
1 /* $NetBSD: session.c,v 1.25 2009/04/21 18:38:32 tteras Exp $ */
3 /* $KAME: session.c,v 1.32 2003/09/24 02:01:17 jinmei Exp $ */
5 /*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
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.
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.
34 #include "config.h"
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
50 #include PATH_IPSEC_H
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>
64 #include <netinet/in.h>
65 #include <resolv.h>
67 #include "libpfkey.h"
69 #include "var.h"
70 #include "misc.h"
71 #include "vmbuf.h"
72 #include "plog.h"
73 #include "debug.h"
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
99 #include "algorithm.h" /* XXX ??? */
101 #include "sainfo.h"
103 struct fd_monitor {
104 int (*callback)(void *ctx, int fd);
105 void *ctx;
108 static void close_session __P((void));
109 static void initfds __P((void));
110 static void init_signal __P((void));
111 static int set_signal __P((int sig, RETSIGTYPE (*func) __P((int))));
112 static void check_sigreq __P((void));
113 static void check_flushsa __P((void));
114 static int close_sockets __P((void));
116 static fd_set preset_mask, active_mask;
117 static struct fd_monitor fd_monitors[FD_SETSIZE];
118 static int nfds = 0;
120 static volatile sig_atomic_t sigreq[NSIG + 1];
121 static struct sched scflushsa = SCHED_INITIALIZER();
123 void
124 monitor_fd(int fd, int (*callback)(void *, int), void *ctx)
126 if (fd < 0 || fd >= FD_SETSIZE) {
127 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun");
128 exit(1);
131 FD_SET(fd, &preset_mask);
132 if (fd > nfds)
133 nfds = fd;
135 fd_monitors[fd].callback = callback;
136 fd_monitors[fd].ctx = ctx;
139 void
140 unmonitor_fd(int fd)
142 if (fd < 0 || fd >= FD_SETSIZE) {
143 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun");
144 exit(1);
147 FD_CLR(fd, &preset_mask);
148 FD_CLR(fd, &active_mask);
149 fd_monitors[fd].callback = NULL;
150 fd_monitors[fd].ctx = NULL;
154 session(void)
156 struct timeval *timeout;
157 int error;
158 char pid_file[MAXPATHLEN];
159 FILE *fp;
160 pid_t racoon_pid = 0;
161 int i;
163 nfds = 0;
164 FD_ZERO(&preset_mask);
166 /* initialize schedular */
167 sched_init();
168 init_signal();
170 if (pfkey_init() < 0)
171 errx(1, "failed to initialize pfkey socket");
173 #ifdef ENABLE_ADMINPORT
174 if (admin_init() < 0)
175 errx(1, "failed to initialize admin port socket");
176 #endif
178 if (isakmp_init() < 0)
179 errx(1, "failed to initialize ISAKMP structures");
181 #ifdef ENABLE_HYBRID
182 if (isakmp_cfg_init(ISAKMP_CFG_INIT_COLD))
183 errx(1, "could not initialize ISAKMP mode config structures");
184 #endif
186 #ifdef HAVE_LIBLDAP
187 if (xauth_ldap_init_conf() != 0)
188 errx(1, "could not initialize ldap config");
189 #endif
191 #ifdef HAVE_LIBRADIUS
192 if (xauth_radius_init_conf(0) != 0)
193 errx(1, "could not initialize radius config");
194 #endif
196 myaddr_init_lists();
199 * in order to prefer the parameters by command line,
200 * saving some parameters before parsing configuration file.
202 save_params();
203 if (cfparse() != 0)
204 errx(1, "failed to parse configuration file.");
205 restore_params();
207 #ifdef ENABLE_HYBRID
208 if(isakmp_cfg_config.network4 && isakmp_cfg_config.pool_size == 0)
209 if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
210 return error;
211 #endif
213 if (dump_config)
214 dumprmconf();
216 #ifdef HAVE_LIBRADIUS
217 if (xauth_radius_init() != 0)
218 errx(1, "could not initialize libradius");
219 #endif
221 if (myaddr_init() != 0)
222 errx(1, "failed to listen to configured addresses");
223 myaddr_sync();
225 #ifdef ENABLE_NATT
226 natt_keepalive_init ();
227 #endif
229 /* write .pid file */
230 if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE] == NULL)
231 strlcpy(pid_file, _PATH_VARRUN "racoon.pid", MAXPATHLEN);
232 else if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE][0] == '/')
233 strlcpy(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
234 else {
235 strlcat(pid_file, _PATH_VARRUN, MAXPATHLEN);
236 strlcat(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
238 fp = fopen(pid_file, "w");
239 if (fp) {
240 if (fchmod(fileno(fp),
241 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
242 syslog(LOG_ERR, "%s", strerror(errno));
243 fclose(fp);
244 exit(1);
246 } else {
247 plog(LLV_ERROR, LOCATION, NULL,
248 "cannot open %s", pid_file);
251 if (privsep_init() != 0)
252 exit(1);
255 * The fork()'ed privileged side will close its copy of fp. We wait
256 * until here to get the correct child pid.
258 racoon_pid = getpid();
259 fprintf(fp, "%ld\n", (long)racoon_pid);
260 fclose(fp);
262 for (i = 0; i <= NSIG; i++)
263 sigreq[i] = 0;
265 while (1) {
267 * asynchronous requests via signal.
268 * make sure to reset sigreq to 0.
270 check_sigreq();
272 /* scheduling */
273 timeout = schedular();
275 /* schedular can change select() mask, so we reset
276 * the working copy here */
277 active_mask = preset_mask;
279 error = select(nfds + 1, &active_mask, NULL, NULL, timeout);
280 if (error < 0) {
281 switch (errno) {
282 case EINTR:
283 continue;
284 default:
285 plog(LLV_ERROR, LOCATION, NULL,
286 "failed to select (%s)\n",
287 strerror(errno));
288 return -1;
290 /*NOTREACHED*/
293 for (i = 0; i <= nfds; i++) {
294 if (!FD_ISSET(i, &active_mask))
295 continue;
297 if (fd_monitors[i].callback != NULL)
298 fd_monitors[i].callback(fd_monitors[i].ctx, i);
299 else
300 plog(LLV_ERROR, LOCATION, NULL,
301 "fd %d set, but no active callback\n", i);
306 /* clear all status and exit program. */
307 static void
308 close_session()
310 evt_generic(EVT_RACOON_QUIT, NULL);
311 pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC);
312 flushph2();
313 flushph1();
314 close_sockets();
315 backupsa_clean();
317 plog(LLV_INFO, LOCATION, NULL, "racoon process %d shutdown\n", getpid());
319 exit(0);
322 static int signals[] = {
323 SIGHUP,
324 SIGINT,
325 SIGTERM,
326 SIGUSR1,
327 SIGUSR2,
328 SIGCHLD,
333 * asynchronous requests will actually dispatched in the
334 * main loop in session().
336 RETSIGTYPE
337 signal_handler(sig)
338 int sig;
340 sigreq[sig] = 1;
344 /* XXX possible mem leaks and no way to go back for now !!!
346 static void reload_conf(){
347 int error;
349 #ifdef ENABLE_HYBRID
350 if ((isakmp_cfg_init(ISAKMP_CFG_INIT_WARM)) != 0) {
351 plog(LLV_ERROR, LOCATION, NULL,
352 "ISAKMP mode config structure reset failed, "
353 "not reloading\n");
354 return;
356 #endif
358 save_sainfotree();
360 /* TODO: save / restore / flush old lcconf (?) / rmtree
362 save_rmconf();
363 initrmconf();
365 #ifdef HAVE_LIBRADIUS
366 /* free and init radius configuration */
367 xauth_radius_init_conf(1);
368 #endif
370 pfkey_reload();
372 save_params();
373 flushlcconf();
374 error = cfparse();
375 if (error != 0){
376 plog(LLV_ERROR, LOCATION, NULL, "config reload failed\n");
377 /* We are probably in an inconsistant state... */
378 return;
380 restore_params();
382 #if 0
383 if (dump_config)
384 dumprmconf ();
385 #endif
387 myaddr_sync();
389 #ifdef HAVE_LIBRADIUS
390 /* re-initialize radius state */
391 xauth_radius_init();
392 #endif
394 /* Revalidate ph1 / ph2tree !!!
395 * update ctdtree if removing some ph1 !
397 revalidate_ph12();
398 /* Update ctdtree ?
401 save_sainfotree_flush();
402 save_rmconf_flush();
405 static void
406 check_sigreq()
408 int sig, s;
410 for (sig = 0; sig <= NSIG; sig++) {
411 if (sigreq[sig] == 0)
412 continue;
413 sigreq[sig] = 0;
415 switch(sig) {
416 case 0:
417 return;
419 case SIGCHLD:
420 /* Reap all pending children */
421 while (waitpid(-1, &s, WNOHANG) > 0)
423 break;
425 #ifdef DEBUG_RECORD_MALLOCATION
427 * XXX This operation is signal handler unsafe and may lead to
428 * crashes and security breaches: See Henning Brauer talk at
429 * EuroBSDCon 2005. Do not run in production with this option
430 * enabled.
432 case SIGUSR2:
433 DRM_dump();
434 break;
435 #endif
437 case SIGHUP:
438 /* Save old configuration, load new one... */
439 reload_conf();
440 break;
442 case SIGINT:
443 case SIGTERM:
444 plog(LLV_INFO, LOCATION, NULL,
445 "caught signal %d\n", sig);
446 close_session();
447 break;
449 default:
450 plog(LLV_INFO, LOCATION, NULL,
451 "caught signal %d\n", sig);
452 break;
457 static void
458 init_signal()
460 int i;
463 * Ignore SIGPIPE as we check the return value of system calls
464 * that write to pipe-like fds.
466 signal(SIGPIPE, SIG_IGN);
468 for (i = 0; signals[i] != 0; i++)
469 if (set_signal(signals[i], signal_handler) < 0) {
470 plog(LLV_ERROR, LOCATION, NULL,
471 "failed to set_signal (%s)\n",
472 strerror(errno));
473 exit(1);
477 static int
478 set_signal(sig, func)
479 int sig;
480 RETSIGTYPE (*func) __P((int));
482 struct sigaction sa;
484 memset((caddr_t)&sa, 0, sizeof(sa));
485 sa.sa_handler = func;
486 sa.sa_flags = SA_RESTART;
488 if (sigemptyset(&sa.sa_mask) < 0)
489 return -1;
491 if (sigaction(sig, &sa, (struct sigaction *)0) < 0)
492 return(-1);
494 return 0;
497 static int
498 close_sockets()
500 myaddr_close();
501 pfkey_close(lcconf->sock_pfkey);
502 #ifdef ENABLE_ADMINPORT
503 (void)admin_close();
504 #endif
505 return 0;