]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/main.c
ipsec-317.220.1.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / main.c
CommitLineData
52b7d2ce
A
1/* $Id: main.c,v 1.14.2.3 2005/11/06 17:18:26 monas Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include "config.h"
33
34#include <sys/types.h>
35#include <sys/param.h>
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/sysctl.h>
39
40#include <netinet/in.h>
41
42#include <stdlib.h>
43#include <stdio.h>
44#include <string.h>
45#include <errno.h>
46#include <limits.h>
47#ifdef HAVE_UNISTD_H
48#include <unistd.h>
49#endif
50#include <paths.h>
51#include <err.h>
d1e348cf 52#include <launch.h>
52b7d2ce
A
53
54/*
55 * If we're using a debugging malloc library, this may define our
56 * wrapper stubs.
57 */
58#define RACOON_MAIN_PROGRAM
59#include "gcmalloc.h"
60
61#include "var.h"
62#include "misc.h"
63#include "vmbuf.h"
64#include "plog.h"
65#include "debug.h"
66
67#include "cfparse_proto.h"
68#include "isakmp_var.h"
d1e348cf 69#ifdef ENABLE_HYBRID
52b7d2ce
A
70#include "isakmp.h"
71#include "isakmp_xauth.h"
d1e348cf 72#include "isakmp_cfg.h"
52b7d2ce
A
73#endif
74#include "remoteconf.h"
75#include "localconf.h"
76#include "session.h"
77#include "oakley.h"
78#include "pfkey.h"
d1e348cf 79#include "policy.h"
52b7d2ce 80#include "crypto_openssl.h"
52b7d2ce
A
81#include "vendorid.h"
82
886926c0
A
83#if !TARGET_OS_EMBEDDED
84#include <sandbox.h>
85#endif // !TARGET_OS_EMBEDDED
86
87
d1e348cf 88#include <CoreFoundation/CoreFoundation.h>
e8d9021d 89#include "power_mgmt.h"
65c25746 90#include "preferences.h"
d1e348cf 91
52b7d2ce
A
92//#include "package_version.h"
93
94int f_local = 0; /* local test mode. behave like a wall. */
95int vflag = 1; /* for print-isakmp.c */
52b7d2ce
A
96static int dump_config = 0; /* dump parsed config file. */
97static int exec_done = 0; /* we've already been exec'd */
98
99#ifdef TOP_PACKAGE
100static char version[] = "@(#)" TOP_PACKAGE_STRING " (" TOP_PACKAGE_URL ")";
101#else /* TOP_PACKAGE */
102static char version[] = "@(#) racoon / IPsec-tools";
103#endif /* TOP_PACKAGE */
104
65c25746
A
105int main (int, char **);
106static void usage (void);
107static void parse (int, char **);
108static void restore_params (void);
109static void save_params (void);
110static void saverestore_params (int);
111static void cleanup_pidfile (void);
85f41bec 112#if 0 // <rdar://problem/9286626>
65c25746 113int launchedbylaunchd (void);
85f41bec 114#endif
52b7d2ce
A
115
116pid_t racoon_pid = 0;
85f41bec 117int launchdlaunched = 0;
52b7d2ce 118int print_pid = 1; /* for racoon only */
65c25746 119
52b7d2ce
A
120
121void
122usage()
123{
85f41bec 124 printf("usage: racoon [-BdDFvs%s] %s[-f (file)] [-l (file)] [-p (port)]\n",
52b7d2ce
A
125#ifdef INET6
126 "46",
127#else
128 "",
129#endif
52b7d2ce 130 ""
52b7d2ce 131 );
52b7d2ce 132 printf(" -d: debug level, more -d will generate more debug message.\n");
85f41bec 133 printf(" -D: started by LaunchD (implies daemon mode).\n");
52b7d2ce
A
134 printf(" -C: dump parsed config file.\n");
135 printf(" -L: include location in debug messages\n");
136 printf(" -F: run in foreground, do not become daemon.\n");
137 printf(" -v: be more verbose\n");
d1e348cf 138 printf(" -s: override enable auto exit\n");
52b7d2ce
A
139#ifdef INET6
140 printf(" -4: IPv4 mode.\n");
141 printf(" -6: IPv6 mode.\n");
52b7d2ce
A
142#endif
143 printf(" -f: pathname for configuration file.\n");
144 printf(" -l: pathname for log file.\n");
145 printf(" -p: port number for isakmp (default: %d).\n", PORT_ISAKMP);
146 printf(" -P: port number for NAT-T (default: %d).\n", PORT_ISAKMP_NATT);
147 exit(1);
148}
149
150int
151main(ac, av)
152 int ac;
153 char **av;
154{
155 int error;
e8d9021d 156
886926c0
A
157#if !TARGET_OS_EMBEDDED
158 char *errorbuf;
159 if (sandbox_init("racoon", SANDBOX_NAMED, &errorbuf) == -1) {
160 plog(ASL_LEVEL_ERR, "initializing sandbox failed %s", errorbuf);
161 sandbox_free_error(errorbuf);
162 return -1;
163 }
164#endif // !TARGET_OS_EMBEDDED
165
65c25746
A
166 /*
167 * Check IPSec plist
168 */
169 prefsinit();
170 ploginit();
171
52b7d2ce
A
172 if (geteuid() != 0) {
173 errx(1, "must be root to invoke this program.");
174 /* NOTREACHED*/
175 }
176
177 /*
178 * Don't let anyone read files I write. Although some files (such as
179 * the PID file) can be other readable, we dare to use the global mask,
180 * because racoon uses fopen(3), which can't specify the permission
181 * at the creation time.
182 */
183 umask(077);
184 if (umask(077) != 077) {
185 errx(1, "could not set umask");
186 /* NOTREACHED*/
187 }
188
e8d9021d 189#ifdef HAVE_OPENSSL
52b7d2ce 190 eay_init();
e8d9021d
A
191#endif
192
52b7d2ce
A
193 initlcconf();
194 initrmconf();
195 oakley_dhinit();
196 compute_vendorids();
197
198 parse(ac, av);
d1e348cf 199
7ebaebe2
A
200 plog(ASL_LEVEL_NOTICE, "racoon started: pid=%d started by: %d, launchdlaunched %d\n", getpid(), getppid(), launchdlaunched);
201 plog(ASL_LEVEL_NOTICE, "%s\n", version);
e8d9021d 202#ifdef HAVE_OPENSSL
7ebaebe2 203 plog(ASL_LEVEL_NOTICE, "@(#)"
52b7d2ce
A
204 "This product linked %s (http://www.openssl.org/)"
205 "\n", eay_version());
e8d9021d 206#endif
7ebaebe2 207 plog(ASL_LEVEL_NOTICE, "Reading configuration from \"%s\"\n",
d1e348cf 208 lcconf->racoon_conf);
52b7d2ce 209
65c25746 210 //%%%%% this sould probably be moved to session()
52b7d2ce 211 if (pfkey_init() < 0) {
65c25746 212 errx(1, "failed to initialize pfkey.\n");
52b7d2ce
A
213 /* NOTREACHED*/
214 }
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 error = cfparse();
222 if (error != 0)
223 errx(1, "failed to parse configuration file.");
224 restore_params();
d1e348cf
A
225
226 if (lcconf->logfile_param == NULL && logFileStr[0] == 0)
65c25746 227 plogresetfile(lcconf->pathinfo[LC_PATHTYPE_LOGFILE]);
52b7d2ce
A
228
229#ifdef ENABLE_NATT
230 /* Tell the kernel which port to use for UDP encapsulation */
231 {
232 int udp_port = PORT_ISAKMP_NATT;
233 if (sysctlbyname("net.inet.ipsec.esp_port", NULL, NULL, &udp_port, sizeof(udp_port)) != 0)
234 errx(1, "couldn't set net.inet.ipsec.esp_port to %d. (%s)",
235 udp_port, strerror(errno));
236 }
237#endif
238
52b7d2ce 239
47612122
A
240#ifdef ENABLE_HYBRID
241 if(isakmp_cfg_config.network4 && isakmp_cfg_config.pool_size == 0)
242 if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
243 return error;
244#endif
245
52b7d2ce
A
246 if (dump_config)
247 dumprmconf ();
248
249 /*
250 * install SAs from the specified file. If the file is not specified
251 * by the configuration file, racoon will exit.
252 */
52b7d2ce
A
253
254 if (f_foreground)
255 close(0);
d1e348cf 256 else {
85f41bec 257 if ( !exec_done && launchdlaunched ){
7ebaebe2 258 plog(ASL_LEVEL_NOTICE,
d1e348cf
A
259 "racoon launched by launchd.\n");
260 exec_done = 1;
261 if (atexit(cleanup_pidfile) < 0) {
65c25746 262 plog(ASL_LEVEL_ERR,
d1e348cf
A
263 "cannot register pidfile cleanup");
264 }
265 }else {
52b7d2ce 266
d1e348cf
A
267 if (exec_done) {
268 if (atexit(cleanup_pidfile) < 0) {
65c25746 269 plog(ASL_LEVEL_ERR,
d1e348cf
A
270 "cannot register pidfile cleanup");
271 }
272 } else {
273 #define MAX_EXEC_ARGS 32
274
275 char *args[MAX_EXEC_ARGS + 2]; /* 2 extra, for '-x' and NULL */
276 char *env[1] = {0};
277 int i;
278
279 if (ac > MAX_EXEC_ARGS) {
65c25746 280 plog(ASL_LEVEL_ERR,
d1e348cf
A
281 "too many arguments.\n");
282 exit(1);
283 }
284
285 if (daemon(0, 0) < 0) {
286 errx(1, "failed to be daemon. (%s)",
287 strerror(errno));
288 }
289
290 /* Radar 5129006 - Prevent non-root user from killing racoon
291 * when launched by setuid process
292 */
293 if (setuid(0)) {
65c25746 294 plog(ASL_LEVEL_ERR,
d1e348cf
A
295 "cannot set uid.\n");
296 exit(1);
297 }
298 if (setgid(0)) {
65c25746 299 plog(ASL_LEVEL_ERR,
d1e348cf
A
300 "cannot set gid.\n");
301 exit(1);
302 }
303
304 /* setup args to re-exec - for CoreFoundation issues */
305 args[0] = PATHRACOON;
306 for (i = 1; i < ac; i++)
307 args[i] = *(av + i);
308 args[ac] = "-x"; /* tells racoon its been exec'd */
309 args[ac+1] = 0;
310
311 execve(PATHRACOON, args, env);
65c25746 312 plog(ASL_LEVEL_ERR,
d1e348cf
A
313 "failed to exec racoon. (%s)", strerror(errno));
314 exit(1);
315 }
52b7d2ce 316 }
52b7d2ce 317 }
65c25746
A
318
319
320 /* start the session */
52b7d2ce 321 session();
52b7d2ce
A
322}
323
85f41bec 324#if 0 // <rdar://problem/9286626>
e97d2cf9 325int
d1e348cf 326launchedbylaunchd(){
d1e348cf 327 launch_data_t checkin_response = NULL;
65c25746 328
85f41bec 329 if ((checkin_response = launch_socket_service_check_in()) == NULL) {
d1e348cf 330 plog(LLV_ERROR, LOCATION, NULL,
85f41bec 331 "launch_socket_service_check_in fails.\n");
d1e348cf
A
332 launchdlaunched = 0;
333 goto done;
334 }
335 if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) {
336 plog(LLV_ERROR, LOCATION, NULL,
337 "launch_data_get_type fails errno %d.\n", launch_data_get_errno(checkin_response));
338 launchdlaunched = 0;
339 goto done;
340 }
85f41bec 341 launchdlaunched = 1;
d1e348cf
A
342done:
343 /* clean up before we leave */
d1e348cf
A
344 if ( checkin_response )
345 launch_data_free(checkin_response);
346 return launchdlaunched;
347}
85f41bec 348#endif
d1e348cf 349
52b7d2ce
A
350static void
351cleanup_pidfile()
352{
353 char pid_file[MAXPATHLEN];
354 pid_t p = getpid();
355
356 /* if it's not child process, clean everything */
357 if (racoon_pid == p) {
358 if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE] == NULL)
d1e348cf 359 strlcpy(pid_file, _PATH_VARRUN "racoon.pid", sizeof(pid_file));
52b7d2ce 360 else if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE][0] == '/')
d1e348cf 361 strlcpy(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], sizeof(pid_file));
52b7d2ce 362 else {
d1e348cf
A
363 strlcat(pid_file, _PATH_VARRUN, sizeof(pid_file));
364 strlcat(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], sizeof(pid_file));
52b7d2ce
A
365 }
366 (void) unlink(pid_file);
367 }
368}
369
370
371static void
372parse(ac, av)
373 int ac;
374 char **av;
375{
376 extern char *optarg;
377 extern int optind;
378 int c;
379#ifdef YYDEBUG
380 extern int yydebug;
381#endif
382
383 pname = strrchr(*av, '/');
384 if (pname)
385 pname++;
386 else
387 pname = *av;
388
85f41bec 389 while ((c = getopt(ac, av, "dDLFp:P:a:f:l:vsZBCx"
52b7d2ce
A
390#ifdef YYDEBUG
391 "y"
392#endif
393#ifdef INET6
394 "46"
395#endif
396 )) != -1) {
397 switch (c) {
398 case 'd':
65c25746 399 plogsetlevel(ASL_LEVEL_DEBUG);
52b7d2ce 400 break;
85f41bec
A
401 case 'D':
402 if (f_foreground) {
403 fprintf(stderr, "-D and -F are mutually exclusive\n");
404 exit(1);
405 }
406 launchdlaunched = 1;
407 break;
52b7d2ce
A
408 case 'L':
409 print_location = 1;
410 break;
411 case 'F':
85f41bec
A
412 if (launchdlaunched) {
413 fprintf(stderr, "-D and -F are mutually exclusive\n");
414 exit(1);
415 }
52b7d2ce
A
416 printf("Foreground mode.\n");
417 f_foreground = 1;
418 break;
419 case 'p':
420 lcconf->port_isakmp = atoi(optarg);
421 break;
422 case 'P':
423 lcconf->port_isakmp_natt = atoi(optarg);
424 break;
425 case 'a':
52b7d2ce
A
426 fprintf(stderr, "%s: the option is disabled "
427 "in the configuration\n", pname);
428 exit(1);
52b7d2ce
A
429 case 'f':
430 lcconf->racoon_conf = optarg;
431 break;
432 case 'l':
433 lcconf->logfile_param = optarg;
434 break;
435 case 'v':
436 vflag++;
437 break;
d1e348cf
A
438 case 's':
439 lcconf->auto_exit_state &= ~LC_AUTOEXITSTATE_CLIENT; /* override default auto exit state */
52b7d2ce
A
440 break;
441 case 'x':
442 exec_done = 1;
443 break;
444 case 'Z':
445 /*
446 * only local test.
447 * To specify -Z option and to choice a appropriate
448 * port number for ISAKMP, you can launch some racoons
449 * on the local host for debug.
450 * pk_sendadd() on initiator side is always failed
451 * even if this flag is used. Because there is same
452 * spi in the SAD which is inserted by pk_sendgetspi()
453 * on responder side.
454 */
455 printf("Local test mode.\n");
456 f_local = 1;
457 break;
458#ifdef YYDEBUG
459 case 'y':
460 yydebug = 1;
461 break;
462#endif
463#ifdef INET6
464 case '4':
465 lcconf->default_af = AF_INET;
466 break;
467 case '6':
468 lcconf->default_af = AF_INET6;
469 break;
470#endif
52b7d2ce
A
471 case 'C':
472 dump_config++;
473 break;
474 default:
475 usage();
476 /* NOTREACHED */
477 }
478 }
479 ac -= optind;
480 av += optind;
481
482 if (ac != 0) {
483 usage();
484 /* NOTREACHED */
485 }
486
487 return;
488}
489
490static void
491restore_params()
492{
493 saverestore_params(1);
494}
495
496static void
497save_params()
498{
499 saverestore_params(0);
500}
501
502static void
503saverestore_params(f)
504 int f;
505{
506 static u_int16_t s_port_isakmp;
52b7d2ce
A
507
508 /* 0: save, 1: restore */
509 if (f) {
510 lcconf->port_isakmp = s_port_isakmp;
52b7d2ce
A
511 } else {
512 s_port_isakmp = lcconf->port_isakmp;
52b7d2ce
A
513 }
514}