/* $NetBSD: main.c,v 1.6.6.2 2008/11/27 15:25:26 vanhu Exp $ */ /* Id: main.c,v 1.25 2006/06/20 20:31:34 manubsd Exp */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "config.h" #include <sys/types.h> #include <sys/param.h> #include <sys/socket.h> #include <sys/stat.h> #include <netinet/in.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <limits.h> #ifdef HAVE_UNISTD_H #include <unistd.h> #endif #include <paths.h> #include <err.h> /* * If we're using a debugging malloc library, this may define our * wrapper stubs. */ #define RACOON_MAIN_PROGRAM #include "gcmalloc.h" #include "var.h" #include "misc.h" #include "vmbuf.h" #include "plog.h" #include "debug.h" #include "cfparse_proto.h" #include "isakmp_var.h" #ifdef ENABLE_HYBRID #include <resolv.h> #include "isakmp.h" #include "isakmp_xauth.h" #include "isakmp_cfg.h" #endif #include "remoteconf.h" #include "localconf.h" #include "session.h" #include "oakley.h" #include "pfkey.h" #include "policy.h" #include "crypto_openssl.h" #include "backupsa.h" #include "vendorid.h" #include "package_version.h" int f_local = 0; /* local test mode. behave like a wall. */ int vflag = 1; /* for print-isakmp.c */ static int loading_sa = 0; /* install sa when racoon boots up. */ static int dump_config = 0; /* dump parsed config file. */ #ifdef TOP_PACKAGE static char version[] = "@(#)" TOP_PACKAGE_STRING " (" TOP_PACKAGE_URL ")"; #else /* TOP_PACKAGE */ static char version[] = "@(#) racoon / IPsec-tools"; #endif /* TOP_PACKAGE */ int main __P((int, char **)); static void usage __P((void)); static void parse __P((int, char **)); #if 0 static void cleanup_pidfile __P((void)); #endif void usage() { printf("usage: racoon [-BdFv%s] %s[-f (file)] [-l (file)] [-p (port)]\n", #ifdef INET6 "46", #else "", #endif #ifdef ENABLE_ADMINPORT "[-a (port)] " #else "" #endif ); printf(" -B: install SA to the kernel from the file " "specified by the configuration file.\n"); printf(" -d: debug level, more -d will generate more debug message.\n"); printf(" -C: dump parsed config file.\n"); printf(" -L: include location in debug messages\n"); printf(" -F: run in foreground, do not become daemon.\n"); printf(" -v: be more verbose\n"); #ifdef INET6 printf(" -4: IPv4 mode.\n"); printf(" -6: IPv6 mode.\n"); #endif #ifdef ENABLE_ADMINPORT printf(" -a: port number for admin port.\n"); #endif printf(" -f: pathname for configuration file.\n"); printf(" -l: pathname for log file.\n"); printf(" -p: port number for isakmp (default: %d).\n", PORT_ISAKMP); printf(" -P: port number for NAT-T (default: %d).\n", PORT_ISAKMP_NATT); exit(1); } int main(ac, av) int ac; char **av; { int error; if (geteuid() != 0) { errx(1, "must be root to invoke this program."); /* NOTREACHED*/ } /* * Don't let anyone read files I write. Although some files (such as * the PID file) can be other readable, we dare to use the global mask, * because racoon uses fopen(3), which can't specify the permission * at the creation time. */ umask(077); if (umask(077) != 077) { errx(1, "could not set umask"); /* NOTREACHED*/ } #ifdef DEBUG_RECORD_MALLOCATION DRM_init(); #endif #ifdef HAVE_SECCTX init_avc(); #endif eay_init(); initlcconf(); initrmconf(); oakley_dhinit(); compute_vendorids(); parse(ac, av); ploginit(); plog(LLV_INFO, LOCATION, NULL, "%s\n", version); plog(LLV_INFO, LOCATION, NULL, "@(#)" "This product linked %s (http://www.openssl.org/)" "\n", eay_version()); plog(LLV_INFO, LOCATION, NULL, "Reading configuration from \"%s\"\n", lcconf->racoon_conf); if (pfkey_init() < 0) { errx(1, "something error happened " "while pfkey initializing."); /* NOTREACHED*/ } #ifdef ENABLE_HYBRID if (isakmp_cfg_init(ISAKMP_CFG_INIT_COLD)) errx(1, "could not initialize ISAKMP mode config structures"); #endif #ifdef HAVE_LIBLDAP if (xauth_ldap_init() != 0) errx(1, "could not initialize libldap"); #endif /* * in order to prefer the parameters by command line, * saving some parameters before parsing configuration file. */ save_params(); error = cfparse(); if (error != 0) errx(1, "failed to parse configuration file."); restore_params(); #ifdef ENABLE_HYBRID if(isakmp_cfg_config.network4 && isakmp_cfg_config.pool_size == 0) if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0) return error; #endif if (dump_config) dumprmconf (); #ifdef HAVE_LIBRADIUS if (xauth_radius_init() != 0) { errx(1, "could not initialize libradius"); /* NOTREACHED*/ } #endif /* * install SAs from the specified file. If the file is not specified * by the configuration file, racoon will exit. */ if (loading_sa && !f_local) { if (backupsa_from_file() != 0) errx(1, "something error happened " "SA recovering."); } if (f_foreground) close(0); else { if (daemon(0, 0) < 0) { errx(1, "failed to be daemon. (%s)", strerror(errno)); } #ifndef __linux__ /* * In case somebody has started inetd manually, we need to * clear the logname, so that old servers run as root do not * get the user's logname.. */ if (setlogin("") < 0) { plog(LLV_ERROR, LOCATION, NULL, "cannot clear logname: %s\n", strerror(errno)); /* no big deal if it fails.. */ } #endif if (!f_local) { #if 0 if (atexit(cleanup_pidfile) < 0) { plog(LLV_ERROR, LOCATION, NULL, "cannot register pidfile cleanup"); } #endif } } session(); exit(0); } #if 0 static void cleanup_pidfile() { pid_t p = getpid(); /* if it's not child process, clean everything */ if (racoon_pid == p) { const char *pid_file = _PATH_VARRUN "racoon.pid"; (void) unlink(pid_file); } } #endif static void parse(ac, av) int ac; char **av; { extern char *optarg; extern int optind; int c; #ifdef YYDEBUG extern int yydebug; #endif pname = strrchr(*av, '/'); if (pname) pname++; else pname = *av; while ((c = getopt(ac, av, "dLFp:P:a:f:l:vZBC" #ifdef YYDEBUG "y" #endif #ifdef INET6 "46" #endif )) != -1) { switch (c) { case 'd': loglevel++; break; case 'L': print_location = 1; break; case 'F': printf("Foreground mode.\n"); f_foreground = 1; break; case 'p': lcconf->port_isakmp = atoi(optarg); break; case 'P': lcconf->port_isakmp_natt = atoi(optarg); break; case 'a': #ifdef ENABLE_ADMINPORT lcconf->port_admin = atoi(optarg); break; #else fprintf(stderr, "%s: the option is disabled " "in the configuration\n", pname); exit(1); #endif case 'f': lcconf->racoon_conf = optarg; break; case 'l': plogset(optarg); break; case 'v': vflag++; break; case 'Z': /* * only local test. * To specify -Z option and to choice a appropriate * port number for ISAKMP, you can launch some racoons * on the local host for debug. * pk_sendadd() on initiator side is always failed * even if this flag is used. Because there is same * spi in the SAD which is inserted by pk_sendgetspi() * on responder side. */ printf("Local test mode.\n"); f_local = 1; break; #ifdef YYDEBUG case 'y': yydebug = 1; break; #endif #ifdef INET6 case '4': lcconf->default_af = AF_INET; break; case '6': lcconf->default_af = AF_INET6; break; #endif case 'B': loading_sa++; break; case 'C': dump_config++; break; default: usage(); /* NOTREACHED */ } } ac -= optind; av += optind; if (ac != 0) { usage(); /* NOTREACHED */ } return; }