1 /* $Id: main.c,v 1.14.2.3 2005/11/06 17:18:26 monas Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
38 #include <sys/sysctl.h>
40 #include <netinet/in.h>
55 * If we're using a debugging malloc library, this may define our
58 #define RACOON_MAIN_PROGRAM
67 #include "cfparse_proto.h"
68 #include "isakmp_var.h"
72 #include "isakmp_xauth.h"
73 #include "isakmp_cfg.h"
75 #include "remoteconf.h"
76 #include "localconf.h"
81 #include "crypto_openssl.h"
85 #include <CoreFoundation/CoreFoundation.h>
86 #include <SystemConfiguration/SystemConfiguration.h>
87 #ifndef TARGET_OS_EMBEDDED
89 #endif // !TARGET_OS_EMBEDDED
90 #include "power_mgmt.h"
92 //#include "package_version.h"
94 int f_local
= 0; /* local test mode. behave like a wall. */
95 int vflag
= 1; /* for print-isakmp.c */
96 static int loading_sa
= 0; /* install sa when racoon boots up. */
97 static int dump_config
= 0; /* dump parsed config file. */
98 static int exec_done
= 0; /* we've already been exec'd */
101 static char version
[] = "@(#)" TOP_PACKAGE_STRING
" (" TOP_PACKAGE_URL
")";
102 #else /* TOP_PACKAGE */
103 static char version
[] = "@(#) racoon / IPsec-tools";
104 #endif /* TOP_PACKAGE */
106 int main
__P((int, char **));
107 static void usage
__P((void));
108 static void parse
__P((int, char **));
109 static void restore_params
__P((void));
110 static void save_params
__P((void));
111 static void saverestore_params
__P((int));
112 static void cleanup_pidfile
__P((void));
113 #if 0 // <rdar://problem/9286626>
114 int launchedbylaunchd
__P((void));
117 pid_t racoon_pid
= 0;
118 int launchdlaunched
= 0;
119 int print_pid
= 1; /* for racoon only */
120 char logFileStr
[MAXPATHLEN
+1];
125 printf("usage: racoon [-BdDFvs%s] %s[-f (file)] [-l (file)] [-p (port)]\n",
131 #ifdef ENABLE_ADMINPORT
137 printf(" -B: install SA to the kernel from the file "
138 "specified by the configuration file.\n");
139 printf(" -d: debug level, more -d will generate more debug message.\n");
140 printf(" -D: started by LaunchD (implies daemon mode).\n");
141 printf(" -C: dump parsed config file.\n");
142 printf(" -L: include location in debug messages\n");
143 printf(" -F: run in foreground, do not become daemon.\n");
144 printf(" -v: be more verbose\n");
145 printf(" -s: override enable auto exit\n");
147 printf(" -4: IPv4 mode.\n");
148 printf(" -6: IPv6 mode.\n");
150 #ifdef ENABLE_ADMINPORT
151 printf(" -a: port number for admin port.\n");
153 printf(" -f: pathname for configuration file.\n");
154 printf(" -l: pathname for log file.\n");
155 printf(" -p: port number for isakmp (default: %d).\n", PORT_ISAKMP
);
156 printf(" -P: port number for NAT-T (default: %d).\n", PORT_ISAKMP_NATT
);
166 #ifndef TARGET_OS_EMBEDDED
167 char *sb_errorbuf
= NULL
;
168 #endif // !TARGET_OS_EMBEDDED
170 #ifndef TARGET_OS_EMBEDDED
171 if (sandbox_init("racoon", SANDBOX_NAMED
, &sb_errorbuf
) == -1) {
173 syslog(LOG_ERR
, "sandbox_init failed: %s\n", sb_errorbuf
);
174 sandbox_free_error(sb_errorbuf
);
177 syslog(LOG_ERR
, "sandbox_init failed\n");
180 #endif // !TARGET_OS_EMBEDDED
182 if (geteuid() != 0) {
183 errx(1, "must be root to invoke this program.");
188 * Don't let anyone read files I write. Although some files (such as
189 * the PID file) can be other readable, we dare to use the global mask,
190 * because racoon uses fopen(3), which can't specify the permission
191 * at the creation time.
194 if (umask(077) != 077) {
195 errx(1, "could not set umask");
199 #ifdef DEBUG_RECORD_MALLOCATION
221 SCPreferencesRef prefs
= NULL
;
222 CFPropertyListRef globals
;
223 CFStringRef logFileRef
;
224 CFNumberRef debugLevelRef
;
230 if ((prefs
= SCPreferencesCreate(0, CFSTR("racoon"), CFSTR("com.apple.ipsec.plist"))) == NULL
)
232 globals
= SCPreferencesGetValue(prefs
, CFSTR("Global"));
233 if (!globals
|| (CFGetTypeID(globals
) != CFDictionaryGetTypeID()))
235 debugLevelRef
= CFDictionaryGetValue(globals
, CFSTR("DebugLevel"));
236 if (!debugLevelRef
|| (CFGetTypeID(debugLevelRef
) != CFNumberGetTypeID()))
238 CFNumberGetValue(debugLevelRef
, kCFNumberSInt32Type
, &level
);
252 break; /* invalid - ignore */
255 logFileRef
= CFDictionaryGetValue(globals
, CFSTR("DebugLogfile"));
256 if (!logFileRef
|| (CFGetTypeID(logFileRef
) != CFStringGetTypeID())) {
259 CFStringGetCString(logFileRef
, logFileStr
, MAXPATHLEN
, kCFStringEncodingMacRoman
);
268 if (lcconf
->logfile_param
)
269 plogset(lcconf
->logfile_param
);
273 plog(LLV_INFO
, LOCATION
, NULL
, "***** racoon started: pid=%d started by: %d, launchdlaunched %d\n", getpid(), getppid(), launchdlaunched
);
274 plog(LLV_INFO
, LOCATION
, NULL
, "%s\n", version
);
276 plog(LLV_INFO
, LOCATION
, NULL
, "@(#)"
277 "This product linked %s (http://www.openssl.org/)"
278 "\n", eay_version());
280 plog(LLV_INFO
, LOCATION
, NULL
, "Reading configuration from \"%s\"\n",
281 lcconf
->racoon_conf
);
283 if (pfkey_init() < 0) {
284 errx(1, "something error happened "
285 "while pfkey initializing.");
290 if (isakmp_cfg_init(ISAKMP_CFG_INIT_COLD
))
291 errx(1, "could not initialize ISAKMP mode config structures");
295 if (xauth_ldap_init() != 0)
296 errx(1, "could not initialize libldap");
300 * in order to prefer the parameters by command line,
301 * saving some parameters before parsing configuration file.
306 errx(1, "failed to parse configuration file.");
309 if (lcconf
->logfile_param
== NULL
&& logFileStr
[0] == 0)
310 plogreset(lcconf
->pathinfo
[LC_PATHTYPE_LOGFILE
]);
313 /* Tell the kernel which port to use for UDP encapsulation */
315 int udp_port
= PORT_ISAKMP_NATT
;
316 if (sysctlbyname("net.inet.ipsec.esp_port", NULL
, NULL
, &udp_port
, sizeof(udp_port
)) != 0)
317 errx(1, "couldn't set net.inet.ipsec.esp_port to %d. (%s)",
318 udp_port
, strerror(errno
));
322 #ifdef HAVE_LIBRADIUS
323 if (xauth_radius_init() != 0) {
324 errx(1, "could not initialize libradius");
330 if(isakmp_cfg_config
.network4
&& isakmp_cfg_config
.pool_size
== 0)
331 if ((error
= isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX
)) != 0)
339 * install SAs from the specified file. If the file is not specified
340 * by the configuration file, racoon will exit.
342 if (loading_sa
&& !f_local
) {
343 if (backupsa_from_file() != 0)
344 errx(1, "something error happened "
351 if ( !exec_done
&& launchdlaunched
){
352 plog(LLV_INFO
, LOCATION
, NULL
,
353 "racoon launched by launchd.\n");
355 if (atexit(cleanup_pidfile
) < 0) {
356 plog(LLV_ERROR
, LOCATION
, NULL
,
357 "cannot register pidfile cleanup");
362 if (atexit(cleanup_pidfile
) < 0) {
363 plog(LLV_ERROR
, LOCATION
, NULL
,
364 "cannot register pidfile cleanup");
367 #define MAX_EXEC_ARGS 32
369 char *args
[MAX_EXEC_ARGS
+ 2]; /* 2 extra, for '-x' and NULL */
373 if (ac
> MAX_EXEC_ARGS
) {
374 plog(LLV_ERROR
, LOCATION
, NULL
,
375 "too many arguments.\n");
379 if (daemon(0, 0) < 0) {
380 errx(1, "failed to be daemon. (%s)",
384 /* Radar 5129006 - Prevent non-root user from killing racoon
385 * when launched by setuid process
388 plog(LLV_ERROR
, LOCATION
, NULL
,
389 "cannot set uid.\n");
393 plog(LLV_ERROR
, LOCATION
, NULL
,
394 "cannot set gid.\n");
398 /* setup args to re-exec - for CoreFoundation issues */
399 args
[0] = PATHRACOON
;
400 for (i
= 1; i
< ac
; i
++)
402 args
[ac
] = "-x"; /* tells racoon its been exec'd */
405 execve(PATHRACOON
, args
, env
);
406 plog(LLV_ERROR
, LOCATION
, NULL
,
407 "failed to exec racoon. (%s)", strerror(errno
));
418 #if 0 // <rdar://problem/9286626>
421 launch_data_t checkin_response
= NULL
;
423 if ((checkin_response
= launch_socket_service_check_in()) == NULL
) {
424 plog(LLV_ERROR
, LOCATION
, NULL
,
425 "launch_socket_service_check_in fails.\n");
429 if (LAUNCH_DATA_ERRNO
== launch_data_get_type(checkin_response
)) {
430 plog(LLV_ERROR
, LOCATION
, NULL
,
431 "launch_data_get_type fails errno %d.\n", launch_data_get_errno(checkin_response
));
437 /* clean up before we leave */
438 if ( checkin_response
)
439 launch_data_free(checkin_response
);
440 return launchdlaunched
;
447 char pid_file
[MAXPATHLEN
];
450 /* if it's not child process, clean everything */
451 if (racoon_pid
== p
) {
452 if (lcconf
->pathinfo
[LC_PATHTYPE_PIDFILE
] == NULL
)
453 strlcpy(pid_file
, _PATH_VARRUN
"racoon.pid", sizeof(pid_file
));
454 else if (lcconf
->pathinfo
[LC_PATHTYPE_PIDFILE
][0] == '/')
455 strlcpy(pid_file
, lcconf
->pathinfo
[LC_PATHTYPE_PIDFILE
], sizeof(pid_file
));
457 strlcat(pid_file
, _PATH_VARRUN
, sizeof(pid_file
));
458 strlcat(pid_file
, lcconf
->pathinfo
[LC_PATHTYPE_PIDFILE
], sizeof(pid_file
));
460 (void) unlink(pid_file
);
477 pname
= strrchr(*av
, '/');
483 #if 0 /* for debugging */
485 plogset("/tmp/racoon.log");
488 while ((c
= getopt(ac
, av
, "dDLFp:P:a:f:l:vsZBCx"
502 fprintf(stderr
, "-D and -F are mutually exclusive\n");
511 if (launchdlaunched
) {
512 fprintf(stderr
, "-D and -F are mutually exclusive\n");
515 printf("Foreground mode.\n");
519 lcconf
->port_isakmp
= atoi(optarg
);
522 lcconf
->port_isakmp_natt
= atoi(optarg
);
525 #ifdef ENABLE_ADMINPORT
526 lcconf
->port_admin
= atoi(optarg
);
529 fprintf(stderr
, "%s: the option is disabled "
530 "in the configuration\n", pname
);
534 lcconf
->racoon_conf
= optarg
;
537 lcconf
->logfile_param
= optarg
;
543 lcconf
->auto_exit_state
&= ~LC_AUTOEXITSTATE_CLIENT
; /* override default auto exit state */
551 * To specify -Z option and to choice a appropriate
552 * port number for ISAKMP, you can launch some racoons
553 * on the local host for debug.
554 * pk_sendadd() on initiator side is always failed
555 * even if this flag is used. Because there is same
556 * spi in the SAD which is inserted by pk_sendgetspi()
559 printf("Local test mode.\n");
569 lcconf
->default_af
= AF_INET
;
572 lcconf
->default_af
= AF_INET6
;
600 saverestore_params(1);
606 saverestore_params(0);
610 saverestore_params(f
)
613 static u_int16_t s_port_isakmp
;
614 #ifdef ENABLE_ADMINPORT
615 static u_int16_t s_port_admin
;
618 /* 0: save, 1: restore */
620 lcconf
->port_isakmp
= s_port_isakmp
;
621 #ifdef ENABLE_ADMINPORT
622 lcconf
->port_admin
= s_port_admin
;
625 s_port_isakmp
= lcconf
->port_isakmp
;
626 #ifdef ENABLE_ADMINPORT
627 s_port_admin
= lcconf
->port_admin
;