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