]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/main.c
ipsec-93.8.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
A
69#ifdef ENABLE_HYBRID
70#include <resolv.h>
52b7d2ce
A
71#include "isakmp.h"
72#include "isakmp_xauth.h"
d1e348cf 73#include "isakmp_cfg.h"
52b7d2ce
A
74#endif
75#include "remoteconf.h"
76#include "localconf.h"
77#include "session.h"
78#include "oakley.h"
79#include "pfkey.h"
d1e348cf 80#include "policy.h"
52b7d2ce
A
81#include "crypto_openssl.h"
82#include "backupsa.h"
83#include "vendorid.h"
84
d1e348cf
A
85#ifdef __APPLE__
86#include <CoreFoundation/CoreFoundation.h>
87#include <SystemConfiguration/SystemConfiguration.h>
88#endif
89
52b7d2ce
A
90//#include "package_version.h"
91
92int f_local = 0; /* local test mode. behave like a wall. */
93int vflag = 1; /* for print-isakmp.c */
94static int loading_sa = 0; /* install sa when racoon boots up. */
95static int dump_config = 0; /* dump parsed config file. */
96static int exec_done = 0; /* we've already been exec'd */
97
98#ifdef TOP_PACKAGE
99static char version[] = "@(#)" TOP_PACKAGE_STRING " (" TOP_PACKAGE_URL ")";
100#else /* TOP_PACKAGE */
101static char version[] = "@(#) racoon / IPsec-tools";
102#endif /* TOP_PACKAGE */
103
104int main __P((int, char **));
105static void usage __P((void));
106static void parse __P((int, char **));
107static void restore_params __P((void));
108static void save_params __P((void));
109static void saverestore_params __P((int));
110static void cleanup_pidfile __P((void));
d1e348cf 111static int launchedbylaunchd(void);
52b7d2ce
A
112
113pid_t racoon_pid = 0;
114int print_pid = 1; /* for racoon only */
115
116void
117usage()
118{
d1e348cf 119 printf("usage: racoon [-BdFvs%s] %s[-f (file)] [-l (file)] [-p (port)]\n",
52b7d2ce
A
120#ifdef INET6
121 "46",
122#else
123 "",
124#endif
125#ifdef ENABLE_ADMINPORT
126 "[-a (port)] "
127#else
128 ""
129#endif
130 );
131 printf(" -B: install SA to the kernel from the file "
132 "specified by the configuration file.\n");
133 printf(" -d: debug level, more -d will generate more debug message.\n");
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");
142#endif
143#ifdef ENABLE_ADMINPORT
144 printf(" -a: port number for admin port.\n");
145#endif
146 printf(" -f: pathname for configuration file.\n");
147 printf(" -l: pathname for log file.\n");
148 printf(" -p: port number for isakmp (default: %d).\n", PORT_ISAKMP);
149 printf(" -P: port number for NAT-T (default: %d).\n", PORT_ISAKMP_NATT);
150 exit(1);
151}
152
153int
154main(ac, av)
155 int ac;
156 char **av;
157{
158 int error;
d1e348cf 159 char logFileStr[MAXPATHLEN+1];
52b7d2ce
A
160
161 if (geteuid() != 0) {
162 errx(1, "must be root to invoke this program.");
163 /* NOTREACHED*/
164 }
165
166 /*
167 * Don't let anyone read files I write. Although some files (such as
168 * the PID file) can be other readable, we dare to use the global mask,
169 * because racoon uses fopen(3), which can't specify the permission
170 * at the creation time.
171 */
172 umask(077);
173 if (umask(077) != 077) {
174 errx(1, "could not set umask");
175 /* NOTREACHED*/
176 }
177
178#ifdef DEBUG_RECORD_MALLOCATION
179 DRM_init();
180#endif
181
d1e348cf
A
182 logFileStr[0] = 0;
183
52b7d2ce
A
184 eay_init();
185 initlcconf();
186 initrmconf();
187 oakley_dhinit();
188 compute_vendorids();
189
190 parse(ac, av);
d1e348cf
A
191
192 #ifdef __APPLE__
193 /*
194 * Check IPSec plist
195 */
196 {
197 SCPreferencesRef prefs = NULL;
198 CFPropertyListRef globals;
199 CFStringRef logFileRef;
200 CFNumberRef debugLevelRef;
201
202 int level = 0;
203
204 logFileStr[0] = 0;
205
206 if ((prefs = SCPreferencesCreate(0, CFSTR("racoon"), CFSTR("com.apple.ipsec.plist"))) == NULL)
207 goto skip;
208 globals = SCPreferencesGetValue(prefs, CFSTR("Global"));
209 if (!globals || (CFGetTypeID(globals) != CFDictionaryGetTypeID()))
210 goto skip;
211 debugLevelRef = CFDictionaryGetValue(globals, CFSTR("DebugLevel"));
212 if (!debugLevelRef || (CFGetTypeID(debugLevelRef) != CFNumberGetTypeID()))
213 goto skip;
214 CFNumberGetValue(debugLevelRef, kCFNumberSInt32Type, &level);
215 switch (level)
216 {
217 case 0:
218 loglevel = 5;
219 goto skip;
220 break;
221 case 1:
222 loglevel = 6;
223 break;
224 case 2:
225 loglevel = 7;
226 break;
227 default:
228 break; /* invalid - ignore */
229 }
230
231 logFileRef = CFDictionaryGetValue(globals, CFSTR("DebugLogfile"));
232 if (!logFileRef || (CFGetTypeID(logFileRef) != CFStringGetTypeID())) {
233 goto skip;
234 }
235 CFStringGetCString(logFileRef, logFileStr, MAXPATHLEN, kCFStringEncodingMacRoman);
236skip:
237 if (prefs)
238 CFRelease(prefs);
239 }
240
241 if (logFileStr[0])
242 plogset(logFileStr);
243 else
244#endif /* __APPLE__ */
245 if (lcconf->logfile_param)
246 plogset(lcconf->logfile_param);
247
52b7d2ce
A
248 ploginit();
249
250 plog(LLV_INFO, LOCATION, NULL, "***** racoon started: pid=%d started by: %d\n", getpid(), getppid());
251 plog(LLV_INFO, LOCATION, NULL, "%s\n", version);
252 plog(LLV_INFO, LOCATION, NULL, "@(#)"
253 "This product linked %s (http://www.openssl.org/)"
254 "\n", eay_version());
d1e348cf
A
255 plog(LLV_INFO, LOCATION, NULL, "Reading configuration from \"%s\"\n",
256 lcconf->racoon_conf);
52b7d2ce
A
257
258 if (pfkey_init() < 0) {
259 errx(1, "something error happened "
260 "while pfkey initializing.");
261 /* NOTREACHED*/
262 }
263
d1e348cf
A
264#ifdef ENABLE_HYBRID
265 if (isakmp_cfg_init(ISAKMP_CFG_INIT_COLD))
266 errx(1, "could not initialize ISAKMP mode config structures");
267#endif
268
269#ifdef HAVE_LIBLDAP
270 if (xauth_ldap_init() != 0)
271 errx(1, "could not initialize libldap");
272#endif
273
52b7d2ce
A
274 /*
275 * in order to prefer the parameters by command line,
276 * saving some parameters before parsing configuration file.
277 */
278 save_params();
279 error = cfparse();
280 if (error != 0)
281 errx(1, "failed to parse configuration file.");
282 restore_params();
d1e348cf
A
283
284 if (lcconf->logfile_param == NULL && logFileStr[0] == 0)
52b7d2ce
A
285 plogreset(lcconf->pathinfo[LC_PATHTYPE_LOGFILE]);
286
287#ifdef ENABLE_NATT
288 /* Tell the kernel which port to use for UDP encapsulation */
289 {
290 int udp_port = PORT_ISAKMP_NATT;
291 if (sysctlbyname("net.inet.ipsec.esp_port", NULL, NULL, &udp_port, sizeof(udp_port)) != 0)
292 errx(1, "couldn't set net.inet.ipsec.esp_port to %d. (%s)",
293 udp_port, strerror(errno));
294 }
295#endif
296
297#ifdef HAVE_LIBRADIUS
298 if (xauth_radius_init() != 0) {
299 errx(1, "could not initialize libradius");
300 /* NOTREACHED*/
301 }
302#endif
303
47612122
A
304#ifdef ENABLE_HYBRID
305 if(isakmp_cfg_config.network4 && isakmp_cfg_config.pool_size == 0)
306 if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
307 return error;
308#endif
309
52b7d2ce
A
310 if (dump_config)
311 dumprmconf ();
312
313 /*
314 * install SAs from the specified file. If the file is not specified
315 * by the configuration file, racoon will exit.
316 */
317 if (loading_sa && !f_local) {
318 if (backupsa_from_file() != 0)
319 errx(1, "something error happened "
320 "SA recovering.");
321 }
322
323 if (f_foreground)
324 close(0);
d1e348cf
A
325 else {
326 if ( !exec_done && launchedbylaunchd() ){
327 plog(LLV_INFO, LOCATION, NULL,
328 "racoon launched by launchd.\n");
329 exec_done = 1;
330 if (atexit(cleanup_pidfile) < 0) {
331 plog(LLV_ERROR, LOCATION, NULL,
332 "cannot register pidfile cleanup");
333 }
334 }else {
52b7d2ce 335
d1e348cf
A
336 if (exec_done) {
337 if (atexit(cleanup_pidfile) < 0) {
338 plog(LLV_ERROR, LOCATION, NULL,
339 "cannot register pidfile cleanup");
340 }
341 } else {
342 #define MAX_EXEC_ARGS 32
343
344 char *args[MAX_EXEC_ARGS + 2]; /* 2 extra, for '-x' and NULL */
345 char *env[1] = {0};
346 int i;
347
348 if (ac > MAX_EXEC_ARGS) {
349 plog(LLV_ERROR, LOCATION, NULL,
350 "too many arguments.\n");
351 exit(1);
352 }
353
354 if (daemon(0, 0) < 0) {
355 errx(1, "failed to be daemon. (%s)",
356 strerror(errno));
357 }
358
359 /* Radar 5129006 - Prevent non-root user from killing racoon
360 * when launched by setuid process
361 */
362 if (setuid(0)) {
363 plog(LLV_ERROR, LOCATION, NULL,
364 "cannot set uid.\n");
365 exit(1);
366 }
367 if (setgid(0)) {
368 plog(LLV_ERROR, LOCATION, NULL,
369 "cannot set gid.\n");
370 exit(1);
371 }
372
373 /* setup args to re-exec - for CoreFoundation issues */
374 args[0] = PATHRACOON;
375 for (i = 1; i < ac; i++)
376 args[i] = *(av + i);
377 args[ac] = "-x"; /* tells racoon its been exec'd */
378 args[ac+1] = 0;
379
380 execve(PATHRACOON, args, env);
381 plog(LLV_ERROR, LOCATION, NULL,
382 "failed to exec racoon. (%s)", strerror(errno));
383 exit(1);
384 }
52b7d2ce 385 }
52b7d2ce
A
386 }
387
388 session();
389
390 exit(0);
391}
392
393
d1e348cf
A
394static int
395launchedbylaunchd(){
396 int launchdlaunched = 1;
397 launch_data_t checkin_response = NULL;
398 launch_data_t checkin_request = NULL;
399
400 /* check in with launchd */
401 if ((checkin_request = launch_data_new_string(LAUNCH_KEY_CHECKIN)) == NULL) {
402 plog(LLV_ERROR, LOCATION, NULL,
403 "launch_data_new_string fails.\n");
404 launchdlaunched = 0;
405 goto done;
406 }
407 if ((checkin_response = launch_msg(checkin_request)) == NULL) {
408 plog(LLV_ERROR, LOCATION, NULL,
409 "launch_msg fails.\n");
410 launchdlaunched = 0;
411 goto done;
412 }
413 if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) {
414 plog(LLV_ERROR, LOCATION, NULL,
415 "launch_data_get_type fails errno %d.\n", launch_data_get_errno(checkin_response));
416 launchdlaunched = 0;
417 goto done;
418 }
419
420done:
421 /* clean up before we leave */
422 if ( checkin_request )
423 launch_data_free(checkin_request);
424 if ( checkin_response )
425 launch_data_free(checkin_response);
426 return launchdlaunched;
427}
428
52b7d2ce
A
429static void
430cleanup_pidfile()
431{
432 char pid_file[MAXPATHLEN];
433 pid_t p = getpid();
434
435 /* if it's not child process, clean everything */
436 if (racoon_pid == p) {
437 if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE] == NULL)
d1e348cf 438 strlcpy(pid_file, _PATH_VARRUN "racoon.pid", sizeof(pid_file));
52b7d2ce 439 else if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE][0] == '/')
d1e348cf 440 strlcpy(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], sizeof(pid_file));
52b7d2ce 441 else {
d1e348cf
A
442 strlcat(pid_file, _PATH_VARRUN, sizeof(pid_file));
443 strlcat(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], sizeof(pid_file));
52b7d2ce
A
444 }
445 (void) unlink(pid_file);
446 }
447}
448
449
450static void
451parse(ac, av)
452 int ac;
453 char **av;
454{
455 extern char *optarg;
456 extern int optind;
457 int c;
458#ifdef YYDEBUG
459 extern int yydebug;
460#endif
461
462 pname = strrchr(*av, '/');
463 if (pname)
464 pname++;
465 else
466 pname = *av;
467
468#if 0 /* for debugging */
469 loglevel += 2;
470 plogset("/tmp/racoon.log");
471#endif
472
d1e348cf 473 while ((c = getopt(ac, av, "dLFp:P:a:f:l:vsZBCx"
52b7d2ce
A
474#ifdef YYDEBUG
475 "y"
476#endif
477#ifdef INET6
478 "46"
479#endif
480 )) != -1) {
481 switch (c) {
482 case 'd':
483 loglevel++;
484 break;
485 case 'L':
486 print_location = 1;
487 break;
488 case 'F':
489 printf("Foreground mode.\n");
490 f_foreground = 1;
491 break;
492 case 'p':
493 lcconf->port_isakmp = atoi(optarg);
494 break;
495 case 'P':
496 lcconf->port_isakmp_natt = atoi(optarg);
497 break;
498 case 'a':
499#ifdef ENABLE_ADMINPORT
500 lcconf->port_admin = atoi(optarg);
501 break;
502#else
503 fprintf(stderr, "%s: the option is disabled "
504 "in the configuration\n", pname);
505 exit(1);
506#endif
507 case 'f':
508 lcconf->racoon_conf = optarg;
509 break;
510 case 'l':
511 lcconf->logfile_param = optarg;
512 break;
513 case 'v':
514 vflag++;
515 break;
d1e348cf
A
516 case 's':
517 lcconf->auto_exit_state &= ~LC_AUTOEXITSTATE_CLIENT; /* override default auto exit state */
52b7d2ce
A
518 break;
519 case 'x':
520 exec_done = 1;
521 break;
522 case 'Z':
523 /*
524 * only local test.
525 * To specify -Z option and to choice a appropriate
526 * port number for ISAKMP, you can launch some racoons
527 * on the local host for debug.
528 * pk_sendadd() on initiator side is always failed
529 * even if this flag is used. Because there is same
530 * spi in the SAD which is inserted by pk_sendgetspi()
531 * on responder side.
532 */
533 printf("Local test mode.\n");
534 f_local = 1;
535 break;
536#ifdef YYDEBUG
537 case 'y':
538 yydebug = 1;
539 break;
540#endif
541#ifdef INET6
542 case '4':
543 lcconf->default_af = AF_INET;
544 break;
545 case '6':
546 lcconf->default_af = AF_INET6;
547 break;
548#endif
549 case 'B':
550 loading_sa++;
551 break;
552 case 'C':
553 dump_config++;
554 break;
555 default:
556 usage();
557 /* NOTREACHED */
558 }
559 }
560 ac -= optind;
561 av += optind;
562
563 if (ac != 0) {
564 usage();
565 /* NOTREACHED */
566 }
567
568 return;
569}
570
571static void
572restore_params()
573{
574 saverestore_params(1);
575}
576
577static void
578save_params()
579{
580 saverestore_params(0);
581}
582
583static void
584saverestore_params(f)
585 int f;
586{
587 static u_int16_t s_port_isakmp;
588#ifdef ENABLE_ADMINPORT
589 static u_int16_t s_port_admin;
590#endif
591
592 /* 0: save, 1: restore */
593 if (f) {
594 lcconf->port_isakmp = s_port_isakmp;
595#ifdef ENABLE_ADMINPORT
596 lcconf->port_admin = s_port_admin;
597#endif
598 } else {
599 s_port_isakmp = lcconf->port_isakmp;
600#ifdef ENABLE_ADMINPORT
601 s_port_admin = lcconf->port_admin;
602#endif
603 }
604}