1/*	$NetBSD: main.c,v 1.6.6.2 2008/11/27 15:25:26 vanhu Exp $	*/
2
3/* Id: main.c,v 1.25 2006/06/20 20:31:34 manubsd 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/socket.h>
39#include <sys/stat.h>
40
41#include <netinet/in.h>
42
43#include <stdlib.h>
44#include <stdio.h>
45#include <string.h>
46#include <errno.h>
47#include <limits.h>
48#ifdef HAVE_UNISTD_H
49#include <unistd.h>
50#endif
51#include <paths.h>
52#include <err.h>
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"
69#ifdef ENABLE_HYBRID
70#include <resolv.h>
71#include "isakmp.h"
72#include "isakmp_xauth.h"
73#include "isakmp_cfg.h"
74#endif
75#include "remoteconf.h"
76#include "localconf.h"
77#include "session.h"
78#include "oakley.h"
79#include "pfkey.h"
80#include "policy.h"
81#include "crypto_openssl.h"
82#include "backupsa.h"
83#include "vendorid.h"
84
85#include "package_version.h"
86
87int f_local = 0;	/* local test mode.  behave like a wall. */
88int vflag = 1;		/* for print-isakmp.c */
89static int loading_sa = 0;	/* install sa when racoon boots up. */
90static int dump_config = 0;	/* dump parsed config file. */
91
92#ifdef TOP_PACKAGE
93static char version[] = "@(#)" TOP_PACKAGE_STRING " (" TOP_PACKAGE_URL ")";
94#else /* TOP_PACKAGE */
95static char version[] = "@(#) racoon / IPsec-tools";
96#endif /* TOP_PACKAGE */
97
98int main __P((int, char **));
99static void usage __P((void));
100static void parse __P((int, char **));
101#if 0
102static void cleanup_pidfile __P((void));
103#endif
104
105void
106usage()
107{
108	printf("usage: racoon [-BdFv%s] %s[-f (file)] [-l (file)] [-p (port)]\n",
109#ifdef INET6
110		"46",
111#else
112		"",
113#endif
114#ifdef ENABLE_ADMINPORT
115		"[-a (port)] "
116#else
117		""
118#endif
119		);
120	printf("   -B: install SA to the kernel from the file "
121		"specified by the configuration file.\n");
122	printf("   -d: debug level, more -d will generate more debug message.\n");
123	printf("   -C: dump parsed config file.\n");
124	printf("   -L: include location in debug messages\n");
125	printf("   -F: run in foreground, do not become daemon.\n");
126	printf("   -v: be more verbose\n");
127#ifdef INET6
128	printf("   -4: IPv4 mode.\n");
129	printf("   -6: IPv6 mode.\n");
130#endif
131#ifdef ENABLE_ADMINPORT
132	printf("   -a: port number for admin port.\n");
133#endif
134	printf("   -f: pathname for configuration file.\n");
135	printf("   -l: pathname for log file.\n");
136	printf("   -p: port number for isakmp (default: %d).\n", PORT_ISAKMP);
137	printf("   -P: port number for NAT-T (default: %d).\n", PORT_ISAKMP_NATT);
138	exit(1);
139}
140
141int
142main(ac, av)
143	int ac;
144	char **av;
145{
146	int error;
147
148	if (geteuid() != 0) {
149		errx(1, "must be root to invoke this program.");
150		/* NOTREACHED*/
151	}
152
153	/*
154	 * Don't let anyone read files I write.  Although some files (such as
155	 * the PID file) can be other readable, we dare to use the global mask,
156	 * because racoon uses fopen(3), which can't specify the permission
157	 * at the creation time.
158	 */
159	umask(077);
160	if (umask(077) != 077) {
161		errx(1, "could not set umask");
162		/* NOTREACHED*/
163	}
164
165#ifdef DEBUG_RECORD_MALLOCATION
166	DRM_init();
167#endif
168
169#ifdef HAVE_SECCTX
170	init_avc();
171#endif
172	eay_init();
173	initlcconf();
174	initrmconf();
175	oakley_dhinit();
176	compute_vendorids();
177
178	parse(ac, av);
179
180	ploginit();
181
182	plog(LLV_INFO, LOCATION, NULL, "%s\n", version);
183	plog(LLV_INFO, LOCATION, NULL, "@(#)"
184	    "This product linked %s (http://www.openssl.org/)"
185	    "\n", eay_version());
186	plog(LLV_INFO, LOCATION, NULL, "Reading configuration from \"%s\"\n",
187	    lcconf->racoon_conf);
188
189	if (pfkey_init() < 0) {
190		errx(1, "something error happened "
191			"while pfkey initializing.");
192		/* NOTREACHED*/
193	}
194
195#ifdef ENABLE_HYBRID
196	if (isakmp_cfg_init(ISAKMP_CFG_INIT_COLD))
197		errx(1, "could not initialize ISAKMP mode config structures");
198#endif
199
200#ifdef HAVE_LIBLDAP
201	if (xauth_ldap_init() != 0)
202		errx(1, "could not initialize libldap");
203#endif
204
205	/*
206	 * in order to prefer the parameters by command line,
207	 * saving some parameters before parsing configuration file.
208	 */
209	save_params();
210	error = cfparse();
211	if (error != 0)
212		errx(1, "failed to parse configuration file.");
213	restore_params();
214
215#ifdef ENABLE_HYBRID
216	if(isakmp_cfg_config.network4 && isakmp_cfg_config.pool_size == 0)
217		if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
218			return error;
219#endif
220
221	if (dump_config)
222		dumprmconf ();
223
224#ifdef HAVE_LIBRADIUS
225	if (xauth_radius_init() != 0) {
226		errx(1, "could not initialize libradius");
227		/* NOTREACHED*/
228	}
229#endif
230
231	/*
232	 * install SAs from the specified file.  If the file is not specified
233	 * by the configuration file, racoon will exit.
234	 */
235	if (loading_sa && !f_local) {
236		if (backupsa_from_file() != 0)
237			errx(1, "something error happened "
238				"SA recovering.");
239	}
240
241	if (f_foreground)
242		close(0);
243	else {
244		if (daemon(0, 0) < 0) {
245			errx(1, "failed to be daemon. (%s)",
246				strerror(errno));
247		}
248#ifndef __linux__
249		/*
250		 * In case somebody has started inetd manually, we need to
251		 * clear the logname, so that old servers run as root do not
252		 * get the user's logname..
253		 */
254		if (setlogin("") < 0) {
255			plog(LLV_ERROR, LOCATION, NULL,
256				"cannot clear logname: %s\n", strerror(errno));
257			/* no big deal if it fails.. */
258		}
259#endif
260		if (!f_local) {
261#if 0
262			if (atexit(cleanup_pidfile) < 0) {
263				plog(LLV_ERROR, LOCATION, NULL,
264					"cannot register pidfile cleanup");
265			}
266#endif
267		}
268	}
269
270	session();
271
272	exit(0);
273}
274
275#if 0
276static void
277cleanup_pidfile()
278{
279	pid_t p = getpid();
280
281	/* if it's not child process, clean everything */
282	if (racoon_pid == p) {
283		const char *pid_file = _PATH_VARRUN "racoon.pid";
284
285		(void) unlink(pid_file);
286	}
287}
288#endif
289
290static void
291parse(ac, av)
292	int ac;
293	char **av;
294{
295	extern char *optarg;
296	extern int optind;
297	int c;
298#ifdef YYDEBUG
299	extern int yydebug;
300#endif
301
302	pname = strrchr(*av, '/');
303	if (pname)
304		pname++;
305	else
306		pname = *av;
307
308	while ((c = getopt(ac, av, "dLFp:P:a:f:l:vZBC"
309#ifdef YYDEBUG
310			"y"
311#endif
312#ifdef INET6
313			"46"
314#endif
315			)) != -1) {
316		switch (c) {
317		case 'd':
318			loglevel++;
319			break;
320		case 'L':
321			print_location = 1;
322			break;
323		case 'F':
324			printf("Foreground mode.\n");
325			f_foreground = 1;
326			break;
327		case 'p':
328			lcconf->port_isakmp = atoi(optarg);
329			break;
330		case 'P':
331			lcconf->port_isakmp_natt = atoi(optarg);
332			break;
333		case 'a':
334#ifdef ENABLE_ADMINPORT
335			lcconf->port_admin = atoi(optarg);
336			break;
337#else
338			fprintf(stderr, "%s: the option is disabled "
339			    "in the configuration\n", pname);
340			exit(1);
341#endif
342		case 'f':
343			lcconf->racoon_conf = optarg;
344			break;
345		case 'l':
346			plogset(optarg);
347			break;
348		case 'v':
349			vflag++;
350			break;
351		case 'Z':
352			/*
353			 * only local test.
354			 * To specify -Z option and to choice a appropriate
355			 * port number for ISAKMP, you can launch some racoons
356			 * on the local host for debug.
357			 * pk_sendadd() on initiator side is always failed
358			 * even if this flag is used.  Because there is same
359			 * spi in the SAD which is inserted by pk_sendgetspi()
360			 * on responder side.
361			 */
362			printf("Local test mode.\n");
363			f_local = 1;
364			break;
365#ifdef YYDEBUG
366		case 'y':
367			yydebug = 1;
368			break;
369#endif
370#ifdef INET6
371		case '4':
372			lcconf->default_af = AF_INET;
373			break;
374		case '6':
375			lcconf->default_af = AF_INET6;
376			break;
377#endif
378		case 'B':
379			loading_sa++;
380			break;
381		case 'C':
382			dump_config++;
383			break;
384		default:
385			usage();
386			/* NOTREACHED */
387		}
388	}
389	ac -= optind;
390	av += optind;
391
392	if (ac != 0) {
393		usage();
394		/* NOTREACHED */
395	}
396
397	return;
398}
399