Esempio n. 1
0
int
main(int argc, char **argv)
{
    bool fork_desired = TRUE;
    bool log_to_stderr_desired = FALSE;
    int lockfd;
#ifdef NAT_TRAVERSAL
    bool nat_traversal = FALSE;
    unsigned int keep_alive = 0;
#endif
#ifdef VIRTUAL_IP
    char *virtual_private = NULL;
#endif

    char *ipsec0 = NULL;
    char *ipsec1 = NULL;
    char *ipsec2 = NULL;
    char *ipsec3 = NULL;
    
    /* handle arguments */
    for (;;)
    {
	static const struct option long_opts[] = {
	    /* name, has_arg, flag, val */
	    { "help", no_argument, NULL, 'h' },
	    { "version", no_argument, NULL, 'v' },
	    { "optionsfrom", required_argument, NULL, '+' },
	    { "nofork", no_argument, NULL, 'd' },
	    { "stderrlog", no_argument, NULL, 'e' },
	    { "noklips", no_argument, NULL, 'n' },
	    { "nocrsend", no_argument, NULL, 'c' },
	    { "uniqueids", no_argument, NULL, 'u' },
	    { "interface", required_argument, NULL, 'i' },
	    { "ikeport", required_argument, NULL, 'p' },
	    { "ctlbase", required_argument, NULL, 'b' },
	    { "secretsfile", required_argument, NULL, 's' },
	    { "adns", required_argument, NULL, 'a' },
#ifdef DEBUG
	    { "debug-none", no_argument, NULL, 'N' },
	    { "debug-all]", no_argument, NULL, 'A' },
	    { "debug-raw", no_argument, NULL, 'R' },
	    { "debug-crypt", no_argument, NULL, 'X' },
	    { "debug-parsing", no_argument, NULL, 'P' },
	    { "debug-emitting", no_argument, NULL, 'E' },
	    { "debug-control", no_argument, NULL, 'C' },
	    { "debug-lifecycle", no_argument, NULL, 'L' },
	    { "debug-klips", no_argument, NULL, 'K' },
	    { "debug-dns", no_argument, NULL, 'D' },
	    { "debug-private", no_argument, NULL, 'Z' },
#endif
#ifdef NAT_TRAVERSAL
	    { "nat_traversal", no_argument, NULL, '1' },
	    { "keep_alive", required_argument, NULL, '2' },
#endif
#ifdef VIRTUAL_IP
	    { "virtual_private", required_argument, NULL, '3' },
#endif
    	    { "ipsec0", required_argument, NULL, '4' },
	    { "ipsec1", required_argument, NULL, '5' },
	    { "ipsec2", required_argument, NULL, '6' },
	    { "ipsec3", required_argument, NULL, '7' },
	    { 0,0,0,0 }
	    };
	/* Note: we don't like the way short options get parsed
	 * by getopt_long, so we simply pass an empty string as
	 * the list.  It could be "hvdenp:l:s:" "NARXPECK".
	 */
	int c = getopt_long(argc, argv, "", long_opts, NULL);

	/* Note: "breaking" from case terminates loop */
	switch (c)
	{
	case EOF:	/* end of flags */
	    break;

	case 0: /* long option already handled */
	    continue;

	case ':':	/* diagnostic already printed by getopt_long */
	case '?':	/* diagnostic already printed by getopt_long */
	    usage("");
	    break;   /* not actually reached */

	case 'h':	/* --help */
	    usage(NULL);
	    break;	/* not actually reached */

	case 'v':	/* --version */
	    {
		const char **sp = ipsec_copyright_notice();

		printf("%s\n", ipsec_version_string());
		for (; *sp != NULL; sp++)
		    puts(*sp);
	    }
	    exit_pluto(0);
	    break;	/* not actually reached */

	case '+':	/* --optionsfrom <filename> */
	    optionsfrom(optarg, &argc, &argv, optind, stderr);
	    /* does not return on error */
	    continue;

	case 'd':	/* --nofork*/
	    fork_desired = FALSE;
	    continue;

	case 'e':	/* --stderrlog */
	    log_to_stderr_desired = TRUE;
	    continue;

	case 'n':	/* --noklips */
	    no_klips = TRUE;
	    continue;

	case 'c':	/* --nocrsend */
	    no_cr_send = TRUE;
	    continue
	    ;
	case 'u':	/* --uniquids */
	    uniqueIDs = TRUE;
	    continue;

	case 'i':	/* --interface <ifname> */
	    if (!use_interface(optarg))
		usage("too many --interface specifications");
	    continue;

	case 'p':	/* --port <portnumber> */
	    if (optarg == NULL || !isdigit(optarg[0]))
		usage("missing port number");

	    {
		char *endptr;
		long port = strtol(optarg, &endptr, 0);

		if (*endptr != '\0' || endptr == optarg
		|| port <= 0 || port > 0x10000)
		    usage("<port-number> must be a number between 1 and 65535");
		pluto_port = port;
	    }
	    continue;

	case 'b':	/* --ctlbase <path> */
	    if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path)
	    , "%s%s", optarg, CTL_SUFFIX) == -1)
		usage("<path>" CTL_SUFFIX " too long for sun_path");
	    if (snprintf(pluto_lock, sizeof(pluto_lock)
	    , "%s%s", optarg, LOCK_SUFFIX) == -1)
		usage("<path>" LOCK_SUFFIX " must fit");
	    continue;

	case 's':	/* --secretsfile <secrets-file> */
	    shared_secrets_file = optarg;
	    continue;

	case 'a':	/* --adns <pathname> */
	    pluto_adns_option = optarg;
	    continue;

#ifdef DEBUG
	case 'N':	/* --debug-none */
	    base_debugging = DBG_NONE;
	    continue;

	case 'A':	/* --debug-all */
	    base_debugging = DBG_ALL;
	    continue;

	case 'R':	/* --debug-raw */
	    base_debugging |= DBG_RAW;
	    continue;

	case 'X':	/* --debug-crypt */
	    base_debugging |= DBG_CRYPT;
	    continue;

	case 'P':	/* --debug-parsing */
	    base_debugging |= DBG_PARSING;
	    continue;

	case 'E':	/* --debug-emitting */
	    base_debugging |= DBG_EMITTING;
	    continue;

	case 'C':	/* --debug-control */
	    base_debugging |= DBG_CONTROL;
	    continue;

	case 'L':	/* --debug-lifecycle */
	    base_debugging |= DBG_LIFECYCLE;
	    continue;

	case 'K':	/* --debug-klips */
	    base_debugging |= DBG_KLIPS;
	    continue;

	case 'D':	/* --debug-dns */
	    base_debugging |= DBG_DNS;
	    continue;

	case 'Z':	/* --debug-private */
	    base_debugging |= DBG_PRIVATE;
	    continue;
#endif
#ifdef NAT_TRAVERSAL
	case '1':	/* --nat_traversal */
	    nat_traversal = TRUE;
	    continue;
	case '2':	/* --keep_alive */
	    keep_alive = atoi(optarg);
	    continue;
#endif
#ifdef VIRTUAL_IP
	case '3':	/* --virtual_private */
	    virtual_private = optarg;
	    continue;
#endif
	case '4':	/* --ipsec0 */
	    ipsec0 = optarg;
	    continue;
	case '5':	/* --ipsec1 */
	    ipsec1 = optarg;
	    continue;
	case '6':	/* --ipsec2 */
	    ipsec2 = optarg;
	    continue;
	case '7':	/* --ipsec3 */
	    ipsec3 = optarg;
	    continue;

	default:
	    impossible();
	}
	break;
    }
    if (optind != argc)
	usage("unexpected argument");
    reset_debugging();
    lockfd = create_lock();

    /* select between logging methods */

    if (log_to_stderr_desired)
	log_to_syslog = FALSE;
    else
	log_to_stderr = FALSE;

    /* create control socket.
     * We must create it before the parent process returns so that
     * there will be no race condition in using it.  The easiest
     * place to do this is before the daemon fork.
     */
    {
	err_t ugh = init_ctl_socket();

	if (ugh != NULL)
	{
	    fprintf(stderr, "pluto: %s", ugh);
	    exit_pluto(1);
	}
    }

    /* If not suppressed, do daemon fork */

#ifndef EMBED
    if (fork_desired)
    {
	{
	    pid_t pid = fork();

	    if (pid < 0)
	    {
		int e = errno;

		fprintf(stderr, "pluto: fork failed (%d %s)\n",
		    errno, strerror(e));
		exit_pluto(1);
	    }

	    if (pid != 0)
	    {
		/* parent: die, after filling PID into lock file.
		 * must not use exit_pluto: lock would be removed!
		 */
		exit(fill_lock(lockfd, pid)? 0 : 1);
	    }
	}

	if (setsid() < 0)
	{
	    int e = errno;

	    fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n",
		errno, strerror(e));
	    exit_pluto(1);
	}

	/* Close everything but ctl_fd and (if needed) stderr. */
	{
	    int i;

	    for (i = getdtablesize() - 1; i >= 0; i--)  /* Bad hack */
		if ((!log_to_stderr || i != 2)
		&& i != ctl_fd)
		    close(i);

	    /* make sure that stdin, stdout, stderr are reserved */
	    if (open("/dev/null", O_RDONLY) != 0)
		abort();
	    if (dup2(0, 1) != 1)
		abort();
	    if (!log_to_stderr && dup2(0, 2) != 2)
		abort();
	}
    }
    else
#endif
    {
	/* no daemon fork: we have to fill in lock file */
	(void) fill_lock(lockfd, getpid());
	fprintf(stdout, "Pluto initialized\n");
	fflush(stdout);
    }

    init_constants();
    init_log();
    /* Note: some scripts may look for this exact message -- don't change */
    log("Starting Pluto (FreeS/WAN Version %s)", ipsec_version_code());
    log("  including X.509 patch (Version %s)", x509patch_version);

#ifdef NAT_TRAVERSAL
    init_nat_traversal(nat_traversal,keep_alive);
#endif

#ifdef VIRTUAL_IP
    init_virtual_ip(virtual_private);
#endif
    init_interfaces(ipsec0, ipsec1, ipsec2, ipsec3);
    init_rnd_pool();
    init_secret();
    init_states();
    init_crypto();
    init_demux();
    init_kernel();
    init_adns();

    /* loading CA certificates */
    load_cacerts();
    /* loading CRLs */
    load_crls();
    /* loading my X.509 or OpenPGP certificate */
    load_mycert();

    call_server();
    return -1;        /* Shouldn't ever reach this */
}
Esempio n. 2
0
int
main(int argc, char **argv)
{
/*	int fd; */
	char *endptr;
/*	int ret; */
	int c;
	const char* error_s;

	int error = 0;

	char ipaddr_txt[ADDRTOT_BUF];                
	struct sadb_ext *extensions[K_SADB_EXT_MAX + 1];
	struct sadb_msg *pfkey_msg;
	ip_address pfkey_address_s_ska;
	/*struct sockaddr_in pfkey_address_d_ska;*/
	ip_address pfkey_address_sflow_ska;
	ip_address pfkey_address_dflow_ska;
	ip_address pfkey_address_smask_ska;
	ip_address pfkey_address_dmask_ska;

	int transport_proto = 0;
	int src_port = 0;
	int dst_port = 0;
	ip_said said;
	ip_subnet s_subnet, d_subnet;
 	int eroute_af = 0;
 	int said_af = 0;
	int sa_flags=0;

	int argcount = argc;


	progname = argv[0];

	memset(&pfkey_address_s_ska, 0, sizeof(ip_address));
	memset(&pfkey_address_sflow_ska, 0, sizeof(ip_address));
	memset(&pfkey_address_dflow_ska, 0, sizeof(ip_address));
	memset(&pfkey_address_smask_ska, 0, sizeof(ip_address));
	memset(&pfkey_address_dmask_ska, 0, sizeof(ip_address));
	memset(&said, 0, sizeof(ip_said));
	memset(&s_subnet, 0, sizeof(ip_subnet));
	memset(&d_subnet, 0, sizeof(ip_subnet));

	eroute_af_opt = said_af_opt = edst_opt = spi_opt = proto_opt = said_opt = dst_opt = src_opt = NULL;

	while((c = getopt_long(argc, argv, ""/*"acdD:e:i:hprs:S:f:vl:+:g"*/, longopts, 0)) != EOF) {
		switch(c) {
		case 'g':
			debug = 1;
			pfkey_lib_debug = PF_KEY_DEBUG_PARSE_MAX;
			argcount--;
			break;
		case 'a':
			if(action_type) {
				fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--replacein', '--clear', or '--del' options permitted.\n",
					progname);
				exit(1);
			}
			action_type = EMT_SETEROUTE;
			break;
		case 'A':
			if(action_type) {
				fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--replacein', '--clear', or '--del' options permitted.\n",
					progname);
				exit(1);
			}
			action_type = EMT_INEROUTE;
			break;
		case 'r':
			if(action_type) {
				fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--replacein', '--clear', or '--del' options permitted.\n",
					progname);
				exit(1);
			}
			action_type = EMT_REPLACEROUTE;
			break;
		case 'E':
			if(action_type) {
				fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--replacein', '--clear', or '--del' options permitted.\n",
					progname);
				exit(1);
			}
			action_type = EMT_INREPLACEROUTE;
			break;
		case 'c':
			if(action_type) {
				fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--clear', or '--del' options permitted.\n",
					progname);
				exit(1);
			}
			action_type = EMT_CLREROUTE;
			break;
		case 'd':
			if(action_type) {
				fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--clear', or '--del' options permitted.\n",
					progname);
				exit(1);
			}
			action_type = EMT_DELEROUTE;
			break;
		case 'e':
			if(said_opt) {
				fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined in SA:%s\n",
					progname, optarg, said_opt);
				exit (1);
			}				
			if(edst_opt) {
				fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined as:%s\n",
					progname, optarg, edst_opt);
				exit (1);
			}				
			error_s = ttoaddr(optarg, 0, said_af, &said.dst);
			if(error_s != NULL) {
				fprintf(stderr, "%s: Error, %s converting --edst argument:%s\n",
					progname, error_s, optarg);
				exit (1);
			}
			edst_opt = optarg;
			break;
		case 'h':
		case '?':
			usage(progname);
			exit(1);
		case 's':
			if(said_opt) {
				fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined in SA:%s\n",
					progname, optarg, said_opt);
				exit (1);
			}				
			if(spi_opt) {
				fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined as:%s\n",
					progname, optarg, spi_opt);
				exit (1);
			}				
			said.spi = htonl(strtoul(optarg, &endptr, 0));
			if(!(endptr == optarg + strlen(optarg))) {
				fprintf(stderr, "%s: Invalid character in SPI parameter: %s\n",
					progname, optarg);
				exit (1);
			}
			if(ntohl(said.spi) < 0x100) {
				fprintf(stderr, "%s: Illegal reserved spi: %s => 0x%x Must be larger than 0x100.\n",
					progname, optarg, ntohl(said.spi));
				exit(1);
			}
			spi_opt = optarg;
			break;
		case 'p':
			if(said_opt) {
				fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined in SA:%s\n",
					progname, optarg, said_opt);
				exit (1);
			}				
			if(proto_opt) {
				fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined as:%s\n",
					progname, optarg, proto_opt);
				exit (1);
			}
#if 0
			if(said.proto) {
				fprintf(stderr, "%s: Warning, PROTO parameter redefined:%s\n",
					progname, optarg);
				exit (1);
			}
#endif
			if(!strcmp(optarg, "ah"))
				said.proto = SA_AH;
			if(!strcmp(optarg, "esp"))
				said.proto = SA_ESP;
			if(!strcmp(optarg, "tun"))
				said.proto = SA_IPIP;
			if(!strcmp(optarg, "comp"))
				said.proto = SA_COMP;
			if(said.proto == 0) {
				fprintf(stderr, "%s: Invalid PROTO parameter: %s\n",
					progname, optarg);
				exit (1);
			}
			proto_opt = optarg;
			break;
		case 'I':
			if(said_opt) {
				fprintf(stderr, "%s: Error, SAID parameter redefined:%s, already defined in SA:%s\n",
					progname, optarg, said_opt);
				exit (1);
			}				
			if(proto_opt) {
				fprintf(stderr, "%s: Error, PROTO parameter redefined in SA:%s, already defined as:%s\n",
					progname, optarg, proto_opt);
				exit (1);
			}
			if(edst_opt) {
				fprintf(stderr, "%s: Error, EDST parameter redefined in SA:%s, already defined as:%s\n",
					progname, optarg, edst_opt);
				exit (1);
			}
			if(spi_opt) {
				fprintf(stderr, "%s: Error, SPI parameter redefined in SA:%s, already defined as:%s\n",
					progname, optarg, spi_opt);
				exit (1);
			}
			if(said_af_opt) {
				fprintf(stderr, "%s: Error, address family parameter redefined in SA:%s, already defined as:%s\n",
					progname, optarg, said_af_opt);
				exit (1);
			}
			error_s = ttosa(optarg, 0, &said);
			if(error_s != NULL) {
				fprintf(stderr, "%s: Error, %s converting --sa argument:%s\n",
					progname, error_s, optarg);
				exit (1);
			} else if(ntohl(said.spi) < 0x100){
				fprintf(stderr, "%s: Illegal reserved spi: %s => 0x%x Must be larger than or equal to 0x100.\n",
					progname, optarg, said.spi);
				exit(1);
			}
			said_af = addrtypeof(&said.dst);
			said_opt = optarg;
			break;
		case 'v':
			fprintf(stdout, "%s %s\n", me, ipsec_version_code());
			fprintf(stdout, "See `ipsec --copyright' for copyright information.\n");
			exit(1);
		case 'D':
			if(dst_opt) {
				fprintf(stderr, "%s: Error, --dst parameter redefined:%s, already defined as:%s\n",
					progname, optarg, dst_opt);
				exit (1);
			}				
			error_s = ttosubnet(optarg, 0, eroute_af, &d_subnet);
			if (error_s != NULL) {
				fprintf(stderr, "%s: Error, %s converting --dst argument: %s\n",
					progname, error_s, optarg);
				exit (1);
			}
			dst_opt = optarg;
			break;
		case 'S':
			if(src_opt) {
				fprintf(stderr, "%s: Error, --src parameter redefined:%s, already defined as:%s\n",
					progname, optarg, src_opt);
				exit (1);
			}				
			error_s = ttosubnet(optarg, 0, eroute_af, &s_subnet);
			if (error_s != NULL) {
				fprintf(stderr, "%s: Error, %s converting --src argument: %s\n",
					progname, error_s, optarg);
				exit (1);
			}
			src_opt = optarg;
			break;
		case 'P':
			if (transport_proto_opt) {
				fprintf(stderr, "%s: Error, --transport-proto"
					" parameter redefined:%s, "
					"already defined as:%s\n",
					progname, optarg,
					transport_proto_opt);
				exit(1);
			}
			transport_proto_opt = optarg;
			break;
		case 'Q':
			if (src_port_opt) {
				fprintf(stderr, "%s: Error, --src-port"
					" parameter redefined:%s, "
					"already defined as:%s\n",
					progname, optarg, src_port_opt);
				exit(1);
			}
			src_port_opt = optarg;
			break;
		case 'R':
			if (dst_port_opt) {
				fprintf(stderr, "%s: Error, --dst-port"
					" parameter redefined:%s, "
					"already defined as:%s\n",
					progname, optarg, dst_port_opt);
				exit(1);
			}
			dst_port_opt = optarg;
			break;
		case 'l':
			progname = malloc(strlen(argv[0])
					      + 10 /* update this when changing the sprintf() */
					      + strlen(optarg));
			sprintf(progname, "%s --label %s",
				argv[0],
				optarg);
			argcount -= 2;
			break;
		case 'i': /* specifies the address family of the SAID, stored in said_af */
			if(said_af_opt) {
				fprintf(stderr, "%s: Error, address family of SAID redefined:%s, already defined as:%s\n",
					progname, optarg, said_af_opt);
				exit (1);
			}				
			if(!strcmp(optarg, "inet"))
				said_af = AF_INET;
			if(!strcmp(optarg, "inet6"))
				said_af = AF_INET6;
			if(said_af == 0) {
				fprintf(stderr, "%s: Invalid address family parameter for SAID: %s\n",
					progname, optarg);
				exit (1);
			}
			said_af_opt = optarg;
			break;
		case 'f': /* specifies the address family of the eroute, stored in eroute_af */
			if(eroute_af_opt) {
				fprintf(stderr, "%s: Error, address family of eroute redefined:%s, already defined as:%s\n",
					progname, optarg, eroute_af_opt);
				exit (1);
			}				
			if(!strcmp(optarg, "inet"))
				eroute_af = AF_INET;
			if(!strcmp(optarg, "inet6"))
				eroute_af = AF_INET6;
			if(eroute_af == 0) {
				fprintf(stderr, "%s: Invalid address family parameter for eroute: %s\n",
					progname, optarg);
				exit (1);
			}
			eroute_af_opt = optarg;
			break;
		case '+': /* optionsfrom */
			optionsfrom(optarg, &argc, &argv, optind, stderr);
			/* no return on error */
			break;
		default:
			break;
		}
	}

	if(debug) {
		fprintf(stdout, "%s: DEBUG: argc=%d\n", progname, argc);
	}
	
        if(argcount == 1) {
                struct stat sts;
                if ( ((stat ("/proc/net/pfkey", &sts)) == 0) )  {
                         fprintf(stderr, "%s: NETKEY does not support eroute table.\n",progname);

                        exit(1);
                }
                else {
			int ret = 1;
			if ((stat ("/proc/net/ipsec_eroute", &sts)) != 0)  {
				fprintf(stderr, "%s: No eroute table - no IPsec support in kernel (are the modules loaded?)\n", progname);
			} else {
				ret = system("cat /proc/net/ipsec_eroute");
				ret = ret != -1 && WIFEXITED(ret) ? WEXITSTATUS(ret) : 1;
			}
			exit(ret);
                }
        }
	

	/* Sanity checks */

	if(debug) {
		fprintf(stdout, "%s: DEBUG: action_type=%d\n", progname, action_type);
	}

	if (transport_proto_opt != 0) {
	     struct protoent * proto = getprotobyname(transport_proto_opt);
	     if (proto != 0) {
		  transport_proto = proto->p_proto;
	     } else {
		  transport_proto = strtoul(transport_proto_opt, &endptr, 0);
		  if ((*endptr != '\0') 
		      || (transport_proto == 0 && endptr == transport_proto_opt)) {
		       fprintf(stderr, "%s: Invalid character in --transport-proto parameter: %s\n",
			       progname, transport_proto_opt);
		       exit (1);
		  }
		  if (transport_proto > 255) {
		       fprintf(stderr, "%s: --transport-proto parameter: %s must be in the range 0 to 255 inclusive\n",
			       progname, transport_proto_opt);
		       exit (1);
		  }
	     }
	}

        if (src_port_opt != 0 || dst_port_opt != 0) {
		switch (transport_proto) {
		case IPPROTO_UDP:
		case IPPROTO_TCP:
			break;
		default:
			fprintf(stderr, "%s: --transport-proto with either UDP or TCP must be specified if --src-port or --dst-port is used\n", progname);
			exit(1);
		}
        }

	if (src_port_opt) {
	     struct servent * ent = getservbyname(src_port_opt, 0);
	     if (ent != 0) {
		  src_port = ent->s_port;
	     } else {
		  src_port = strtoul(src_port_opt, &endptr, 0);
		  if ((*endptr != '\0')
		      || (src_port == 0 && endptr == src_port_opt)) {
		       fprintf(stderr, "%s: Invalid character in --src-port parameter: %s\n",
			       progname, src_port_opt);
		       exit (1);
		  }
		  if (src_port > 65535) {
		       fprintf(stderr, "%s: --src-port parameter: %s must be in the range 0 to 65535 inclusive\n",
			       progname, src_port_opt);
		  }
		  src_port = htons(src_port);
	     }
	}

	if (dst_port_opt) {
	     struct servent * ent = getservbyname(dst_port_opt, 0);
	     if (ent != 0) {
		  dst_port = ent->s_port;
	     } else {
		  dst_port = strtoul(dst_port_opt, &endptr, 0);
		  if ((*endptr != '\0')
		      || (dst_port == 0 && endptr == dst_port_opt)) {
		       fprintf(stderr, "%s: Invalid character in --dst-port parameter: %s\n",
			       progname, dst_port_opt);
		       exit (1);
		  }
		  if (dst_port > 65535) {
		       fprintf(stderr, "%s: --dst-port parameter: %s must be in the range 0 to 65535 inclusive\n",
			       progname, dst_port_opt);
		  }
		  dst_port = htons(dst_port);
	     }
	}

	switch(action_type) {
	case EMT_SETEROUTE:
	case EMT_REPLACEROUTE:
	case EMT_INEROUTE:
	case EMT_INREPLACEROUTE:
		if(!(said_af_opt && edst_opt && spi_opt && proto_opt) && !(said_opt)) {
			fprintf(stderr, "%s: add and addin options must have SA specified.\n",
				progname);
			exit(1);
		}
	case EMT_DELEROUTE:
		if(!src_opt) {
			fprintf(stderr, "%s: Error -- %s option '--src' is required.\n",
				progname, (action_type == EMT_SETEROUTE) ? "add" : "del");
			exit(1);
		}
		if(!dst_opt) {
			fprintf(stderr, "%s: Error -- %s option '--dst' is required.\n",
				progname, (action_type == EMT_SETEROUTE) ? "add" : "del");
			exit(1);
		}
	case EMT_CLREROUTE:
		break;
	default:
		fprintf(stderr, "%s: exactly one of '--add', '--addin', '--replace', '--del' or '--clear' options must be specified.\n"
			"Try %s --help' for usage information.\n",
			progname, progname);
		exit(1);
	}

	pfkey_sock = pfkey_open_sock_with_error();
	if(pfkey_sock == -1) {
		exit(1);
	}

	if(debug) {
		fprintf(stdout, "%s: DEBUG: PFKEYv2 socket successfully openned=%d.\n", progname, pfkey_sock);
	}

	/* Build an SADB_X_ADDFLOW or SADB_X_DELFLOW message to send down. */
	/* It needs <base, SA, address(SD), flow(SD), mask(SD)> minimum. */
	pfkey_extensions_init(extensions);
	if((error = pfkey_msg_hdr_build(&extensions[0],
					(action_type == EMT_SETEROUTE
					 || action_type == EMT_REPLACEROUTE
					 || action_type == EMT_INREPLACEROUTE
					 || action_type == EMT_INEROUTE)
					? SADB_X_ADDFLOW : SADB_X_DELFLOW,
					proto2satype(said.proto),
					0,
					++pfkey_seq,
					getpid()))) {
		fprintf(stderr, "%s: Trouble building message header, error=%d.\n",
			progname, error);
		pfkey_extensions_free(extensions);
		exit(1);
	}

	if(debug) {
		fprintf(stdout, "%s: DEBUG: pfkey_msg_hdr_build successfull.\n", progname);
	}

	switch(action_type) {
	case EMT_CLREROUTE:
		sa_flags = SADB_X_SAFLAGS_CLEARFLOW;
		goto sa_build;

	case EMT_REPLACEROUTE:
		sa_flags = SADB_X_SAFLAGS_REPLACEFLOW;
		goto sa_build;

	case EMT_INREPLACEROUTE:
		sa_flags = SADB_X_SAFLAGS_REPLACEFLOW | SADB_X_SAFLAGS_INFLOW;
		goto sa_build;

	case EMT_INEROUTE:
		sa_flags = SADB_X_SAFLAGS_INFLOW;
		goto sa_build;

	case EMT_SETEROUTE:
	sa_build:
		if((error = pfkey_sa_build(&extensions[SADB_EXT_SA],
					   SADB_EXT_SA,
					   said.spi, /* in network order */
					   0,
					   0,
					   0,
					   0,
					   sa_flags))) {
			fprintf(stderr, "%s: Trouble building sa extension, error=%d.\n",
				progname, error);
			pfkey_extensions_free(extensions);
			exit(1);
		}
		if(debug) {
			fprintf(stdout, "%s: DEBUG: pfkey_sa_build successful.\n", progname);
		}

	default:
		break;
	}

	switch(action_type) {
	case EMT_SETEROUTE:
	case EMT_REPLACEROUTE:
	case EMT_INEROUTE:
	case EMT_INREPLACEROUTE:
		anyaddr(said_af, &pfkey_address_s_ska);
		if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC],
						SADB_EXT_ADDRESS_SRC,
						0,
						0,
						sockaddrof(&pfkey_address_s_ska)))) {
			addrtot(&pfkey_address_s_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
			fprintf(stderr, "%s: Trouble building address_s extension (%s), error=%d.\n",
				progname, ipaddr_txt, error);
			pfkey_extensions_free(extensions);
			exit(1);
		}
		if(debug) {
			fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for src.\n", progname);
		}

		if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST],
						SADB_EXT_ADDRESS_DST,
						0,
						0,
						sockaddrof(&said.dst)))) {
			addrtot(&said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt));
			fprintf(stderr, "%s: Trouble building address_d extension (%s), error=%d.\n",
				progname, ipaddr_txt, error);
			pfkey_extensions_free(extensions);
			exit(1);
		}
		if(debug) {
			fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for dst.\n", progname);
		}
	default:
		break;
	}
	
	switch(action_type) {
	case EMT_SETEROUTE:
	case EMT_REPLACEROUTE:
	case EMT_INEROUTE:
	case EMT_INREPLACEROUTE:
	case EMT_DELEROUTE:
		networkof(&s_subnet, &pfkey_address_sflow_ska); /* src flow */
		add_port(eroute_af, &pfkey_address_sflow_ska, src_port);
		if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_SRC_FLOW],
						SADB_X_EXT_ADDRESS_SRC_FLOW,
						0,
						0,
						sockaddrof(&pfkey_address_sflow_ska)))) {
			addrtot(&pfkey_address_sflow_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
			fprintf(stderr, "%s: Trouble building address_sflow extension (%s), error=%d.\n",
				progname, ipaddr_txt, error);
			pfkey_extensions_free(extensions);
			exit(1);
		}
		if(debug) {
			fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for src flow.\n", progname);
		}
	
		networkof(&d_subnet, &pfkey_address_dflow_ska); /* dst flow */
		add_port(eroute_af, &pfkey_address_dflow_ska, dst_port);
		if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_DST_FLOW],
						SADB_X_EXT_ADDRESS_DST_FLOW,
						0,
						0,
						sockaddrof(&pfkey_address_dflow_ska)))) {
			addrtot(&pfkey_address_dflow_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
			fprintf(stderr, "%s: Trouble building address_dflow extension (%s), error=%d.\n",
				progname, ipaddr_txt, error);
			pfkey_extensions_free(extensions);
			exit(1);
		}
		if(debug) {
			fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for dst flow.\n", progname);
		}
		
		maskof(&s_subnet, &pfkey_address_smask_ska); /* src mask */
		add_port(eroute_af, &pfkey_address_smask_ska, src_port ? ~0:0);
		if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_SRC_MASK],
						SADB_X_EXT_ADDRESS_SRC_MASK,
						0,
						0,
						sockaddrof(&pfkey_address_smask_ska)))) {
			addrtot(&pfkey_address_smask_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
			fprintf(stderr, "%s: Trouble building address_smask extension (%s), error=%d.\n",
				progname, ipaddr_txt, error);
			pfkey_extensions_free(extensions);
			exit(1);
		}
		if(debug) {
			fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for src mask.\n", progname);
		}
		
		maskof(&d_subnet, &pfkey_address_dmask_ska); /* dst mask */
		add_port(eroute_af, &pfkey_address_dmask_ska, dst_port ? ~0:0);
		if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_DST_MASK],
						SADB_X_EXT_ADDRESS_DST_MASK,
						0,
						0,
						sockaddrof(&pfkey_address_dmask_ska)))) {
			addrtot(&pfkey_address_dmask_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
			fprintf(stderr, "%s: Trouble building address_dmask extension (%s), error=%d.\n",
				progname, ipaddr_txt, error);
			pfkey_extensions_free(extensions);
			exit(1);
		}
		if(debug) {
			fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for dst mask.\n", progname);
		}
	}
	
	if (transport_proto != 0) {
		if ((error = pfkey_x_protocol_build(&extensions[SADB_X_EXT_PROTOCOL],
						    transport_proto))) {
			fprintf(stderr, "%s: Trouble building transport"
				" protocol extension, error=%d.\n",
				progname, error);
			exit(1);
		}
	}

	if((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN))) {
		fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n",
			progname, error);
		pfkey_extensions_free(extensions);
		pfkey_msg_free(&pfkey_msg);
		exit(1);
	}
	if(debug) {
		fprintf(stdout, "%s: DEBUG: pfkey_msg_build successful.\n", progname);
	}

	if((error = write(pfkey_sock,
				pfkey_msg,
				pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) !=
	   (ssize_t)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) {
		fprintf(stderr, "%s: pfkey write failed, returning %d with errno=%d.\n",
			progname, error, errno);
		pfkey_extensions_free(extensions);
		pfkey_msg_free(&pfkey_msg);
		switch(errno) {
		case EINVAL:
			fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
			break;
		case ENXIO:
			if((action_type == EMT_SETEROUTE) ||
			   (action_type == EMT_REPLACEROUTE)) {
				fprintf(stderr, "Invalid mask.\n");
				break;
			}
			if(action_type == EMT_DELEROUTE) {
				fprintf(stderr, "Mask not found.\n");
				break;
			}
		case EFAULT:
			if((action_type == EMT_SETEROUTE) ||
			   (action_type == EMT_REPLACEROUTE)) {
				fprintf(stderr, "Invalid address.\n");
				break;
			}
			if(action_type == EMT_DELEROUTE) {
				fprintf(stderr, "Address not found.\n");
				break;
			}
		case EACCES:
			fprintf(stderr, "access denied.  ");
			if(getuid() == 0) {
				fprintf(stderr, "Check permissions.  Should be 600.\n");
			} else {
				fprintf(stderr, "You must be root to open this file.\n");
			}
			break;
		case EUNATCH:
			fprintf(stderr, "KLIPS not loaded.\n");
			break;
		case EBUSY:
			fprintf(stderr, "KLIPS is busy.  Most likely a serious internal error occured in a previous command.  Please report as much detail as possible to development team.\n");
			break;
		case ENODEV:
			fprintf(stderr, "KLIPS not loaded or enabled.\n");
			fprintf(stderr, "No device?!?\n");
			break;
		case ENOBUFS:
			fprintf(stderr, "No kernel memory to allocate SA.\n");
			break;
		case ESOCKTNOSUPPORT:
			fprintf(stderr, "Algorithm support not available in the kernel.  Please compile in support.\n");
			break;
		case EEXIST:
			fprintf(stderr, "eroute already in use.  Delete old one first.\n");
			break;
		case ENOENT:
			if(action_type == EMT_INEROUTE || action_type == EMT_INREPLACEROUTE) {
				fprintf(stderr, "non-existant IPIP SA.\n");
				break;
			}
			fprintf(stderr, "eroute doesn't exist.  Can't delete.\n");
			break;
		case ENOSPC:
			fprintf(stderr, "no room in kernel SAref table.  Cannot process request.\n");
			break;
		case ESPIPE:
			fprintf(stderr, "kernel SAref table internal error.  Cannot process request.\n");
			break;
		default:
			fprintf(stderr, "Unknown socket write error %d.  Please report as much detail as possible to development team.\n", errno);
		}
/*		fprintf(stderr, "%s: socket write returned errno %d\n",
		progname, errno);*/
		exit(1);
	}
	if(debug) {
		fprintf(stdout, "%s: DEBUG: pfkey write successful.\n", progname);
	}

	if(pfkey_msg) {
		pfkey_extensions_free(extensions);
		pfkey_msg_free(&pfkey_msg);
	}

	(void) close(pfkey_sock);  /* close the socket */

	if(debug) {
		fprintf(stdout, "%s: DEBUG: write ok\n", progname);
	}

	exit(0);
}
Esempio n. 3
0
int
main(int argc, char **argv)
{
    bool fork_desired = TRUE;
    int lockfd;
    char* ocspuri = NULL;
    int nhelpers = -1;
    char *coredir;
    const struct osw_conf_options *oco;

#ifdef NAT_TRAVERSAL
    /** Overridden by nat_traversal= in ipsec.conf */
    bool nat_traversal = FALSE;
    bool nat_t_spf = TRUE;  /* support port floating */
    unsigned int keep_alive = 0;
    bool force_keepalive = FALSE;
#endif
    /** Overridden by virtual_private= in ipsec.conf */
    char *virtual_private = NULL;
#ifdef LEAK_DETECTIVE
    leak_detective=1;
#else
    leak_detective=0;
#endif

#ifdef HAVE_LIBCAP_NG
	/* Drop capabilities */
	capng_clear(CAPNG_SELECT_BOTH);
	capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
			CAP_NET_BIND_SERVICE, CAP_NET_ADMIN, CAP_NET_RAW,
			CAP_IPC_LOCK, -1);
	/* our children must be able to CAP_NET_ADMIN to change routes.
	 */
	capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET,
			CAP_NET_ADMIN, -1);
	capng_apply(CAPNG_SELECT_BOTH);
#endif


    global_argv = argv;
    global_argc = argc;
#ifdef DEBUG
    openswan_passert_fail = passert_fail;
#endif

    /* see if there is an environment variable */
    coredir = getenv("PLUTO_CORE_DIR");

    if(getenv("PLUTO_WAIT_FOR_GDB")) {
	sleep(120);
    }

    /* handle arguments */
    for (;;)
    {
#	define DBG_OFFSET 256
	static const struct option long_opts[] = {
	    /* name, has_arg, flag, val */
	    { "help", no_argument, NULL, 'h' },
	    { "version", no_argument, NULL, 'v' },
	    { "optionsfrom", required_argument, NULL, '+' },
	    { "nofork", no_argument, NULL, 'd' },
	    { "stderrlog", no_argument, NULL, 'e' },
	    { "noklips", no_argument, NULL, 'n' },
	    { "use-nostack",  no_argument, NULL, 'n' },
	    { "use-none",     no_argument, NULL, 'n' },
	    { "force_busy", no_argument, NULL, 'D' },
	    { "nocrsend", no_argument, NULL, 'c' },
	    { "strictcrlpolicy", no_argument, NULL, 'r' },
	    { "crlcheckinterval", required_argument, NULL, 'x'},
	    { "ocsprequestcert", required_argument, NULL, 'q'},
	    { "ocspuri", required_argument, NULL, 'o'},
	    { "uniqueids", no_argument, NULL, 'u' },
	    { "useklips",  no_argument, NULL, 'k' },
	    { "use-klips",  no_argument, NULL, 'k' },
	    { "use-auto",  no_argument, NULL, 'G' },
	    { "usenetkey", no_argument, NULL, 'K' },
	    { "use-netkey", no_argument, NULL, 'K' },
	    { "use-mast",   no_argument, NULL, 'M' },
	    { "use-mastklips",   no_argument, NULL, 'M' },
	    { "use-bsdkame",   no_argument, NULL, 'F' },
	    { "interface", required_argument, NULL, 'i' },
	    { "listen", required_argument, NULL, 'L' },
	    { "ikeport", required_argument, NULL, 'p' },
	    { "ctlbase", required_argument, NULL, 'b' },
	    { "secretsfile", required_argument, NULL, 's' },
	    { "foodgroupsdir", required_argument, NULL, 'f' },
	    { "perpeerlogbase", required_argument, NULL, 'P' },
	    { "perpeerlog", no_argument, NULL, 'l' },
	    { "noretransmits", no_argument, NULL, 'R' },
	    { "coredir", required_argument, NULL, 'C' },
	    { "ipsecdir", required_argument, NULL, 'f' },
	    { "ipsec_dir", required_argument, NULL, 'f' },
#ifdef USE_LWRES
	    { "lwdnsq", required_argument, NULL, 'a' },
#else /* !USE_LWRES */
	    { "adns", required_argument, NULL, 'a' },
#endif /* !USE_LWRES */
#ifdef NAT_TRAVERSAL
	    { "nat_traversal", no_argument, NULL, '1' },
	    { "keep_alive", required_argument, NULL, '2' },
	    { "force_keepalive", no_argument, NULL, '3' },
	    { "disable_port_floating", no_argument, NULL, '4' },
	    { "debug-nat_t", no_argument, NULL, '5' },
	    { "debug-nattraversal", no_argument, NULL, '5' },
	    { "debug-nat-t", no_argument, NULL, '5' },
#endif
	    { "virtual_private", required_argument, NULL, '6' },
	    { "nhelpers", required_argument, NULL, 'j' },
#ifdef DEBUG
	    { "debug-none", no_argument, NULL, 'N' },
	    { "debug-all", no_argument, NULL, 'A' },

	    { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET },
	    { "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET },
	    { "debug-crypto", no_argument, NULL, DBG_CRYPT + DBG_OFFSET },
	    { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET },
	    { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET },
	    { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET },
	    { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET },
	    { "debug-klips", no_argument, NULL, DBG_KLIPS + DBG_OFFSET },
	    { "debug-netkey", no_argument, NULL, DBG_NETKEY + DBG_OFFSET },
	    { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET },
	    { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET },
	    { "debug-oppoinfo", no_argument, NULL, DBG_OPPOINFO + DBG_OFFSET },
	    { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET },
	    { "debug-dpd", no_argument, NULL, DBG_DPD + DBG_OFFSET },
            { "debug-x509", no_argument, NULL, DBG_X509 + DBG_OFFSET },
	    { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET },
	    { "debug-pfkey", no_argument, NULL, DBG_PFKEY + DBG_OFFSET },

	    { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET },
	    { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET },
	    { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET },
	    { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET },
	    { "impair-sa-creation", no_argument, NULL, IMPAIR_SA_CREATION + DBG_OFFSET },
	    { "impair-die-oninfo", no_argument, NULL, IMPAIR_DIE_ONINFO + DBG_OFFSET },
	    { "impair-jacob-two-two", no_argument, NULL, IMPAIR_JACOB_TWO_TWO + DBG_OFFSET },
#endif
	    { 0,0,0,0 }
	    };
	/* Note: we don't like the way short options get parsed
	 * by getopt_long, so we simply pass an empty string as
	 * the list.  It could be "hvdenp:l:s:" "NARXPECK".
	 */
	int c = getopt_long(argc, argv, "", long_opts, NULL);

	/** Note: "breaking" from case terminates loop */
	switch (c)
	{
	case EOF:	/* end of flags */
	    break;

	case 0: /* long option already handled */
	    continue;

	case ':':	/* diagnostic already printed by getopt_long */
	case '?':	/* diagnostic already printed by getopt_long */
	    usage("");
	    break;   /* not actually reached */

	case 'h':	/* --help */
	    usage(NULL);
	    break;	/* not actually reached */

	case 'C':
	    coredir = clone_str(optarg, "coredir");
	    break;

	case 'v':	/* --version */
	    {
		const char **sp = ipsec_copyright_notice();

		printf("%s%s\n", ipsec_version_string(),
				 compile_time_interop_options);
		for (; *sp != NULL; sp++)
		    puts(*sp);
	    }
	    exit(0);	/* not exit_pluto because we are not initialized yet */
	    break;	/* not actually reached */

	case '+':	/* --optionsfrom <filename> */
	    optionsfrom(optarg, &argc, &argv, optind, stderr);
	    /* does not return on error */
	    continue;

	case 'j':	/* --nhelpers */
            if (optarg == NULL || !isdigit(optarg[0]))
                usage("missing number of pluto helpers");

            {
                char *endptr;
                long count = strtol(optarg, &endptr, 0);

                if (*endptr != '\0' || endptr == optarg
		    || count < -1)
                    usage("<nhelpers> must be a positive number, 0 or -1");
                nhelpers = count;
            }
	    continue;

	case 'd':	/* --nofork*/
	    fork_desired = FALSE;
	    continue;

	case 'e':	/* --stderrlog */
	    log_to_stderr_desired = TRUE;
	    continue;

	case 'G':       /* --use-auto */
	    kern_interface = AUTO_PICK;
	    continue;

	case 'k':       /* --use-klips */
	    kern_interface = USE_KLIPS;
	    continue;

	case 'L':	/* --listen ip_addr */
	    {
	    ip_address lip;
	     err_t e = ttoaddr(optarg,0,0,&lip);
	    if(e) {
		openswan_log("invalid listen argument ignored: %s\n",e);
	    } else {
		pluto_listen = clone_str(optarg, "pluto_listen");
		openswan_log("bind() will be filtered for %s\n",pluto_listen);
	    }
            }
	   continue;

	case 'M':       /* --use-mast */
	    kern_interface = USE_MASTKLIPS;
	    continue;

	case 'F':       /* --use-bsdkame */
	    kern_interface = USE_BSDKAME;
	    continue;

	case 'K':       /* --use-netkey */
	    kern_interface = USE_NETKEY;
	    continue;

	case 'n':	/* --use-nostack */
	    kern_interface = NO_KERNEL;
	    continue;

	case 'D':	/* --force_busy */
	    force_busy = TRUE;
	    continue
	    ;

	case 'c':	/* --nocrsend */
	    no_cr_send = TRUE;
	    continue
	    ;

	case 'r':	/* --strictcrlpolicy */
	    strict_crl_policy = TRUE;
	    continue
	    ;

	case 'R':
	    no_retransmits = TRUE;
	    continue;

	case 'x':	/* --crlcheckinterval <time>*/
            if (optarg == NULL || !isdigit(optarg[0]))
                usage("missing interval time");

            {
                char *endptr;
                long interval = strtol(optarg, &endptr, 0);

                if (*endptr != '\0' || endptr == optarg
                || interval <= 0)
                    usage("<interval-time> must be a positive number");
                crl_check_interval = interval;
            }
	    continue
	    ;

	case 'o':	/* --ocspuri */
	    ocspuri = optarg;
	    continue;

	case 'u':	/* --uniqueids */
	    uniqueIDs = TRUE;
	    continue;

	case 'i':	/* --interface <ifname|ifaddr> */
	    if (!use_interface(optarg))
		usage("too many --interface specifications");
	    continue;

	/* 
	 * This option does not really work, as this is the "left"
	 * site only, you also need --to --ikeport again later on
	 * It will result in: yourport -> 500, still not bypassing filters
	 */
	case 'p':	/* --ikeport <portnumber> */
	    if (optarg == NULL || !isdigit(optarg[0]))
		usage("missing port number");
	    {
		char *endptr;
		long port = strtol(optarg, &endptr, 0);

		if (*endptr != '\0' || endptr == optarg
		|| port <= 0 || port > 0x10000)
		    usage("<port-number> must be a number between 1 and 65535");
		pluto_port = port;
	    }
	    continue;

	case 'b':	/* --ctlbase <path> */
	    ctlbase = optarg;
	    if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path)
			 , "%s%s", ctlbase, CTL_SUFFIX) == -1)
		usage("<path>" CTL_SUFFIX " too long for sun_path");
	    if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path)
			 , "%s%s", ctlbase, INFO_SUFFIX) == -1)
		usage("<path>" INFO_SUFFIX " too long for sun_path");
	    if (snprintf(pluto_lock, sizeof(pluto_lock)
			 , "%s%s", ctlbase, LOCK_SUFFIX) == -1)
		usage("<path>" LOCK_SUFFIX " must fit");
	    continue;

	case 's':	/* --secretsfile <secrets-file> */
	    pluto_shared_secrets_file = optarg;
	    continue;

	case 'f':	/* --ipsecdir <ipsec-dir> */
	    (void)osw_init_ipsecdir(optarg);
	    continue;

	case 'a':	/* --adns <pathname> */
	    pluto_adns_option = optarg;
	    continue;

#ifdef DEBUG
	case 'N':	/* --debug-none */
	    base_debugging = DBG_NONE;
	    continue;

	case 'A':	/* --debug-all */
	    base_debugging = DBG_ALL;
	    continue;
#endif

	case 'P':       /* --perpeerlogbase */
	    base_perpeer_logdir = optarg;
	    continue;

	case 'l':
	    log_to_perpeer = TRUE;
	    continue;

#ifdef NAT_TRAVERSAL
	case '1':	/* --nat_traversal */
	    nat_traversal = TRUE;
	    continue;
	case '2':	/* --keep_alive */
	    keep_alive = atoi(optarg);
	    continue;
	case '3':	/* --force_keepalive */
	    force_keepalive = TRUE;
	    continue;
	case '4':	/* --disable_port_floating */
	    nat_t_spf = FALSE;
	    continue;
#ifdef DEBUG
	case '5':	/* --debug-nat_t */
	    base_debugging |= DBG_NATT;
	    continue;
#endif
#endif
	case '6':	/* --virtual_private */
	    virtual_private = optarg;
	    continue;

	default:
#ifdef DEBUG
	    if (c >= DBG_OFFSET)
	    {
		base_debugging |= c - DBG_OFFSET;
		continue;
	    }
#	undef DBG_OFFSET
#endif
	    bad_case(c);
	}
	break;
    }
    if (optind != argc)
	usage("unexpected argument");
    reset_debugging();

#ifdef HAVE_NO_FORK
	fork_desired = FALSE;
	nhelpers = 0;
#endif

    /* if a core dir was set, chdir there */
    if(coredir) 
	if(chdir(coredir) == -1) {
	   int e = errno;
	   openswan_log("pluto: chdir() do dumpdir failed (%d %s)\n",
                    e, strerror(e));
    }

    oco = osw_init_options();
    lockfd = create_lock();

    /* select between logging methods */

    if (log_to_stderr_desired)
	log_to_syslog = FALSE;
    else
	log_to_stderr = FALSE;

#ifdef DEBUG
#if 0
    if(kernel_ops->set_debug) {
	(*kernel_ops->set_debug)(cur_debugging, DBG_log, DBG_log);
    }
#endif
#endif

    /** create control socket.
     * We must create it before the parent process returns so that
     * there will be no race condition in using it.  The easiest
     * place to do this is before the daemon fork.
     */
    {
	err_t ugh = init_ctl_socket();

	if (ugh != NULL)
	{
	    fprintf(stderr, "pluto: %s", ugh);
	    exit_pluto(1);
	}
    }

#ifdef IPSECPOLICY
    /* create info socket. */
    {
	err_t ugh = init_info_socket();

	if (ugh != NULL)
	{
	    fprintf(stderr, "pluto: %s", ugh);
	    exit_pluto(1);
	}
    }
#endif

    /* If not suppressed, do daemon fork */

    if (fork_desired)
    {
	{
	    pid_t pid = fork();

	    if (pid < 0)
	    {
		int e = errno;

		fprintf(stderr, "pluto: fork failed (%d %s)\n",
		    errno, strerror(e));
		exit_pluto(1);
	    }

	    if (pid != 0)
	    {
		/* parent: die, after filling PID into lock file.
		 * must not use exit_pluto: lock would be removed!
		 */
		exit(fill_lock(lockfd, pid)? 0 : 1);
	    }
	}

	if (setsid() < 0)
	{
	    int e = errno;

	    fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n",
		errno, strerror(e));
	    exit_pluto(1);
	}
    }
    else
    {
	/* no daemon fork: we have to fill in lock file */
	(void) fill_lock(lockfd, getpid());
	fprintf(stdout, "Pluto initialized\n");
	fflush(stdout);
    }

    /** Close everything but ctl_fd and (if needed) stderr.
     * There is some danger that a library that we don't know
     * about is using some fd that we don't know about.
     * I guess we'll soon find out.
     */
    {
	int i;

	for (i = getdtablesize() - 1; i >= 0; i--)  /* Bad hack */
	    if ((!log_to_stderr || i != 2)
#ifdef IPSECPOLICY
	    && i != info_fd
#endif
	    && i != ctl_fd)
		close(i);

	/* make sure that stdin, stdout, stderr are reserved */
	if (open("/dev/null", O_RDONLY) != 0)
	    osw_abort();
	if (dup2(0, 1) != 1)
	    osw_abort();
	if (!log_to_stderr && dup2(0, 2) != 2)
	    osw_abort();
    }

    init_constants();
    pluto_init_log();

#ifdef HAVE_LIBNSS
	char buf[100];
	snprintf(buf, sizeof(buf), "%s",oco->confddir);
	loglog(RC_LOG_SERIOUS,"nss directory plutomain: %s",buf);
	SECStatus nss_init_status= NSS_InitReadWrite(buf);
	if (nss_init_status != SECSuccess) {
	    loglog(RC_LOG_SERIOUS, "NSS initialization failed (err %d)\n", PR_GetError());
        exit_pluto(10);
	} else {
	    loglog(RC_LOG_SERIOUS, "NSS Initialized");
	    PK11_SetPasswordFunc(getNSSPassword);

#ifdef FIPS_CHECK
	const char *package_files[]= { IPSECLIBDIR"/setup",
				        IPSECLIBDIR"/addconn",
				        IPSECLIBDIR"/auto",
				        IPSECLIBDIR"/barf",
				        IPSECLIBDIR"/_copyright",
				        IPSECLIBDIR"/eroute",
  				        IPSECLIBDIR"/ikeping",
				        IPSECLIBDIR"/_include",
					IPSECLIBDIR"/_keycensor",
					IPSECLIBDIR"/klipsdebug",
					IPSECLIBDIR"/look",
					IPSECLIBDIR"/newhostkey",
					IPSECLIBDIR"/pf_key",
					IPSECLIBDIR"/_pluto_adns",
					IPSECLIBDIR"/_plutoload",
					IPSECLIBDIR"/_plutorun",
					IPSECLIBDIR"/ranbits",
					IPSECLIBDIR"/_realsetup",
					IPSECLIBDIR"/rsasigkey",
					IPSECLIBDIR"/pluto",
					IPSECLIBDIR"/_secretcensor",
					IPSECLIBDIR"/secrets",
					IPSECLIBDIR"/showdefaults",
					IPSECLIBDIR"/showhostkey",
					IPSECLIBDIR"/showpolicy",
					IPSECLIBDIR"/spi",
					IPSECLIBDIR"/spigrp",
					IPSECLIBDIR"/_startklips",
					IPSECLIBDIR"/_startnetkey",
					IPSECLIBDIR"/tncfg",
					IPSECLIBDIR"/_updown",
					IPSECLIBDIR"/_updown.klips",
					IPSECLIBDIR"/_updown.mast",
					IPSECLIBDIR"/_updown.netkey", 
					IPSECLIBDIR"/verify",
					IPSECLIBDIR"/whack",
					IPSECSBINDIR"/ipsec",
					NULL
					};

       if (Pluto_IsFIPS() && !FIPSCHECK_verify_files(package_files)) {
             loglog(RC_LOG_SERIOUS, "FIPS integrity verification test failed");
             exit_pluto(10);
        }
#endif

      }
#endif

    /* Note: some scripts may look for this exact message -- don't change
     * ipsec barf was one, but it no longer does.
     */
    {
	const char *vc = ipsec_version_code();
#ifdef PLUTO_SENDS_VENDORID
	const char *v = init_pluto_vendorid();
	openswan_log("Starting Pluto (Openswan Version %s%s; Vendor ID %s) pid:%u"
		     , vc, compile_time_interop_options, v, getpid());
#else
	openswan_log("Starting Pluto (Openswan Version %s%s) pid:%u"
		     , vc, compile_time_interop_options, getpid());
#endif
#ifdef HAVE_LIBNSS
	if(Pluto_IsFIPS()) {
		openswan_log("Pluto is running in FIPS mode");
	}
#endif

	if((vc[0]=='c' && vc[1]=='v' && vc[2]=='s') ||
	   (vc[2]=='g' && vc[3]=='i' && vc[4]=='t')) {
	    /*
	     * when people build RPMs from CVS or GIT, make sure they
	     * get blamed appropriately, and that we get some way to
	     * identify who did it, and when they did it. Use string concat,
	     * so that strings the binary can or classic SCCS "what", will find
	     * stuff too.
	     */
	    openswan_log("@(#) built on "__DATE__":" __TIME__ " by " BUILDER);
	}
#if defined(USE_1DES)
	openswan_log("WARNING: 1DES is enabled");
#endif
    }

    if(coredir) {
	openswan_log("core dump dir: %s", coredir);
    }

#ifdef LEAK_DETECTIVE
	openswan_log("LEAK_DETECTIVE support [enabled]");
#else
	openswan_log("LEAK_DETECTIVE support [disabled]");
#endif

#ifdef HAVE_OCF
       {
        struct stat buf;
	errno=0;

	if( stat("/dev/crypto",&buf) != -1) 
		openswan_log("OCF support for IKE via /dev/crypto [enabled]");
	else 
		openswan_log("OCF support for IKE via /dev/crypto [failed:%s]", strerror(errno));
       }
#else
	openswan_log("OCF support for IKE [disabled]");
#endif

   /* Check for SAREF support */
#ifdef KLIPS_MAST
#include <ipsec_saref.h>
    {
	int e, sk, saref;
	saref = 1;
	errno=0;

	sk = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_REFINFO, &saref, sizeof(saref));
	if (e == -1 ) {
		openswan_log("SAref support [disabled]: %s" , strerror(errno));
	}
	else {
		openswan_log("SAref support [enabled]");
	}
	errno=0;
	e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_BINDREF, &saref, sizeof(saref));
	if (e == -1 ) {
		openswan_log("SAbind support [disabled]: %s" , strerror(errno));
	}
	else {
		openswan_log("SAbind support [enabled]");
	}


	close(sk);
    }
#endif

#ifdef HAVE_LIBNSS
	openswan_log("NSS support [enabled]");
#else
	openswan_log("NSS support [disabled]");
#endif

#ifdef HAVE_STATSD
	openswan_log("HAVE_STATSD notification via /bin/openswan-statsd enabled");
#else
	openswan_log("HAVE_STATSD notification support not compiled in");
#endif


/** Log various impair-* functions if they were enabled */

    if(DBGP(IMPAIR_BUST_MI2))
	openswan_log("Warning: IMPAIR_BUST_MI2 enabled");
    if(DBGP(IMPAIR_BUST_MR2))
	openswan_log("Warning: IMPAIR_BUST_MR2 enabled");
    if(DBGP(IMPAIR_SA_CREATION))
	openswan_log("Warning: IMPAIR_SA_CREATION enabled");
    if(DBGP(IMPAIR_JACOB_TWO_TWO))
	openswan_log("Warning: IMPAIR_JACOB_TWO_TWO enabled");
    if(DBGP(IMPAIR_DIE_ONINFO))
	openswan_log("Warning: IMPAIR_DIE_ONINFO enabled");
    if(DBGP(IMPAIR_DELAY_ADNS_KEY_ANSWER))
	openswan_log("Warning: IMPAIR_DELAY_ADNS_KEY_ANSWER enabled");
    if(DBGP(IMPAIR_DELAY_ADNS_TXT_ANSWER))
	openswan_log("Warning: IMPAIR_DELAY_ADNS_TXT_ANSWER enabled");

/** Initialize all of the various features */

#ifdef NAT_TRAVERSAL
    init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf);
#endif

    init_virtual_ip(virtual_private);
    init_rnd_pool();
    init_timer();
    init_secret();
    init_states();
    init_connections();
    init_crypto();
    init_crypto_helpers(nhelpers);
    load_oswcrypto();
    init_demux();
    init_kernel();
    init_adns();
    init_id();

#ifdef TPM
    init_tpm();
#endif

#ifdef HAVE_THREADS
    init_fetch();
#endif

    ocsp_set_default_uri(ocspuri);

    /* loading X.509 CA certificates */
    load_authcerts("CA cert", oco->cacerts_dir, AUTH_CA);
    /* loading X.509 AA certificates */
    load_authcerts("AA cert", oco->aacerts_dir, AUTH_AA);
    /* loading X.509 OCSP certificates */
    load_authcerts("OCSP cert", oco->ocspcerts_dir, AUTH_OCSP);

    /* loading X.509 CRLs */
    load_crls();
    /* loading attribute certificates (experimental) */
    load_acerts();

#ifdef HAVE_LIBNSS
    /*Loading CA certs from NSS DB*/
    load_authcerts_from_nss("CA cert",  AUTH_CA);
#endif

    daily_log_event();
    call_server();
    return -1;	/* Shouldn't ever reach this */
}
Esempio n. 4
0
int
main(int argc, char **argv)
{
/*	int fd; */
	unsigned char action = 0;
	int c;
	
	int error = 0;
	int argcount = argc;
	int em_db_tn, em_db_nl, em_db_xf, em_db_er, em_db_sp;
	int em_db_rj, em_db_es, em_db_ah, em_db_rx, em_db_ky;
	int em_db_gz, em_db_vb;

	struct sadb_ext *extensions[K_SADB_EXT_MAX + 1];
	struct sadb_msg *pfkey_msg;
	
	em_db_tn=em_db_nl=em_db_xf=em_db_er=em_db_sp=0;
	em_db_rj=em_db_es=em_db_ah=em_db_rx=em_db_ky=0;
	em_db_gz=em_db_vb=0;


	program_name = argv[0];

	while((c = getopt_long(argc, argv, ""/*"s:c:anhvl:+:d"*/, longopts, 0)) != EOF) {
		switch(c) {
		case 'd':
			pfkey_lib_debug = PF_KEY_DEBUG_PARSE_MAX;
			argcount--;
			break;
		case 's':
			if(action) {
				fprintf(stderr, "%s: Only one of '--set', '--clear', '--all' or '--none' options permitted.\n",
					program_name);
				exit(1);
			}
			action = 's';
			em_db_tn=em_db_nl=em_db_xf=em_db_er=em_db_sp=0;
			em_db_rj=em_db_es=em_db_ah=em_db_rx=em_db_ky=0;
			em_db_gz=em_db_vb=0;
			if(strcmp(optarg, "all") == 0) {
				em_db_tn=em_db_nl=em_db_xf=em_db_er=em_db_sp=-1;
				em_db_rj=em_db_es=em_db_ah=em_db_rx=em_db_ky=-1;
				em_db_gz=-1;
				em_db_vb= 0;
			} else if(strcmp(optarg, "tunnel") == 0) {
				em_db_tn = -1L;
			} else if(strcmp(optarg, "tncfg") == 0) {
			        em_db_tn = DB_TN_REVEC;
			} else if(strcmp(optarg, "xmit") == 0
					|| strcmp(optarg, "tunnel-xmit") == 0) {
				em_db_tn = DB_TN_XMIT;
			} else if(strcmp(optarg, "netlink") == 0) {
				em_db_nl = -1L;
			} else if(strcmp(optarg, "xform") == 0) {
				em_db_xf = -1L;
			} else if(strcmp(optarg, "eroute") == 0) {
				em_db_er = -1L;
			} else if(strcmp(optarg, "spi") == 0) {
				em_db_sp = -1L;
			} else if(strcmp(optarg, "radij") == 0) {
				em_db_rj = -1L;
			} else if(strcmp(optarg, "esp") == 0) {
				em_db_es = -1L;
			} else if(strcmp(optarg, "ah") == 0) {
				em_db_ah = -1L;
			} else if(strcmp(optarg, "rcv") == 0) {
				em_db_rx = -1L;
			} else if(strcmp(optarg, "pfkey") == 0) {
				em_db_ky = -1L;
			} else if(strcmp(optarg, "comp") == 0) {
				em_db_gz = -1L;
			} else if(strcmp(optarg, "verbose") == 0) {
				em_db_vb = -1L;
			} else {
				fprintf(stdout, "%s: unknown set argument '%s'\n",
						program_name, optarg);
				usage(program_name);
			}
			em_db_nl |= 1 << (sizeof(em_db_nl) * 8 -1);
			break;
		case 'c':
			if(action) {
				fprintf(stderr, "%s: Only one of '--set', '--clear', '--all' or '--none' options permitted.\n",
					program_name);
				exit(1);
			}
			em_db_tn=em_db_nl=em_db_xf=em_db_er=em_db_sp=-1;
			em_db_rj=em_db_es=em_db_ah=em_db_rx=em_db_ky=-1;
			em_db_gz=em_db_vb=-1;

			action = 'c';
			if(strcmp(optarg, "all") == 0) {
				em_db_tn=em_db_nl=em_db_xf=em_db_er=em_db_sp=0;
				em_db_rj=em_db_es=em_db_ah=em_db_rx=em_db_ky=0;
				em_db_gz=em_db_vb=0;
			} else if(strcmp(optarg, "tunnel") == 0) {
				em_db_tn = 0;
			} else if(strcmp(optarg, "tunnel-xmit") == 0
				  || strcmp(optarg, "xmit") == 0) {
				em_db_tn = ~DB_TN_XMIT;
			} else if(strcmp(optarg, "netlink") == 0) {
				em_db_nl = 0;
			} else if(strcmp(optarg, "xform") == 0) {
				em_db_xf = 0;
			} else if(strcmp(optarg, "eroute") == 0) {
				em_db_er = 0;
			} else if(strcmp(optarg, "spi") == 0) {
				em_db_sp = 0;
			} else if(strcmp(optarg, "radij") == 0) {
				em_db_rj = 0;
			} else if(strcmp(optarg, "esp") == 0) {
				em_db_es = 0;
			} else if(strcmp(optarg, "ah") == 0) {
				em_db_ah = 0;
			} else if(strcmp(optarg, "rcv") == 0) {
				em_db_rx = 0;
			} else if(strcmp(optarg, "pfkey") == 0) {
				em_db_ky = 0;
			} else if(strcmp(optarg, "comp") == 0) {
				em_db_gz = 0;
			} else if(strcmp(optarg, "verbose") == 0) {
				em_db_vb = 0;
			} else {
				fprintf(stdout, "%s: unknown clear argument '%s'\n",
						program_name, optarg);
				usage(program_name);
			}
			em_db_nl &= ~(1 << (sizeof(em_db_nl) * 8 -1));
			break;
		case 'a':
			if(action) {
				fprintf(stderr, "%s: Only one of '--set', '--clear', '--all' or '--none' options permitted.\n",
					program_name);
				exit(1);
			}
			action = 'a';
			em_db_tn=em_db_nl=em_db_xf=em_db_er=em_db_sp=-1;
			em_db_rj=em_db_es=em_db_ah=em_db_rx=em_db_ky=-1;
			em_db_gz=-1;
			em_db_vb= 0;
			break;
		case 'n':
			if(action) {
				fprintf(stderr, "%s: Only one of '--set', '--clear', '--all' or '--none' options permitted.\n",
					program_name);
				exit(1);
			}
			action = 'n';
			em_db_tn=em_db_nl=em_db_xf=em_db_er=em_db_sp=0;
			em_db_rj=em_db_es=em_db_ah=em_db_rx=em_db_ky=0;
			em_db_gz=em_db_vb=0;
			break;
		case 'h':
		case '?':
			usage(program_name);
			exit(1);
		case 'v':
			fprintf(stdout, "klipsdebug (Openswan %s) \n",
				ipsec_version_code());
			fputs(copyright, stdout);
			exit(0);
		case 'l':
			program_name = malloc(strlen(argv[0])
					      + 10 /* update this when changing the sprintf() */
					      + strlen(optarg));
			sprintf(program_name, "%s --label %s",
				argv[0],
				optarg);
			argcount -= 2;
			break;
		case '+': /* optionsfrom */
			optionsfrom(optarg, &argc, &argv, optind, stderr);
			/* no return on error */
			break;
		default:
			fprintf(stdout, "%s: unknown option '%s'\n",
					program_name, argv[optind]);
			break;
		}
	}

	if(argcount == 1) {
		int ret = system("cat /proc/net/ipsec_klipsdebug");
		exit(ret != -1 && WIFEXITED(ret) ? WEXITSTATUS(ret) : 1);
	}

	if(!action) {
		usage(program_name);
	}

	if((pfkey_sock = safe_socket(PF_KEY, SOCK_RAW, PF_KEY_V2) ) < 0) {
		fprintf(stderr, "%s: Trouble opening PF_KEY family socket with error: ",
			program_name);
		switch(errno) {
		case ENOENT:
			fprintf(stderr, "device does not exist.  See FreeS/WAN installation procedure.\n");
			break;
		case EACCES:
			fprintf(stderr, "access denied.  ");
			if(getuid() == 0) {
				fprintf(stderr, "Check permissions.  Should be 600.\n");
			} else {
				fprintf(stderr, "You must be root to open this file.\n");
			}
			break;
		case EUNATCH:
			fprintf(stderr, "Netlink not enabled OR KLIPS not loaded.\n");
			break;
		case ENODEV:
			fprintf(stderr, "KLIPS not loaded or enabled.\n");
			break;
		case EBUSY:
			fprintf(stderr, "KLIPS is busy.  Most likely a serious internal error occured in a previous command.  Please report as much detail as possible to development team.\n");
			break;
		case EINVAL:
			fprintf(stderr, "Invalid argument, KLIPS not loaded or check kernel log messages for specifics.\n");
			break;
		case ENOBUFS:
			fprintf(stderr, "No kernel memory to allocate SA.\n");
			break;
		case ESOCKTNOSUPPORT:
			fprintf(stderr, "Algorithm support not available in the kernel.  Please compile in support.\n");
			break;
		case EEXIST:
			fprintf(stderr, "SA already in use.  Delete old one first.\n");
			break;
		case ENXIO:
			fprintf(stderr, "SA does not exist.  Cannot delete.\n");
			break;
		case EAFNOSUPPORT:
			fprintf(stderr, "KLIPS not loaded or enabled.\n");
			break;
		default:
			fprintf(stderr, "Unknown file open error %d.  Please report as much detail as possible to development team.\n", errno);
		}
		exit(1);
	}

	pfkey_extensions_init(extensions);

	if((error = pfkey_msg_hdr_build(&extensions[0],
					SADB_X_DEBUG,
					0,
					0,
					++pfkey_seq,
					getpid()))) {
		fprintf(stderr, "%s: Trouble building message header, error=%d.\n",
			program_name, error);
		pfkey_extensions_free(extensions);
		exit(1);
	}
	
	if((error = pfkey_x_debug_build(&extensions[SADB_X_EXT_DEBUG],
					em_db_tn,
					em_db_nl,
					em_db_xf,
					em_db_er,
					em_db_sp,
					em_db_rj,
					em_db_es,
					em_db_ah,
					em_db_rx,
					em_db_ky,
					em_db_gz,
					em_db_vb))) {
		fprintf(stderr, "%s: Trouble building message header, error=%d.\n",
			program_name, error);
		pfkey_extensions_free(extensions);
		exit(1);
	}
	
	if((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN))) {
		fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n",
			program_name, error);
		pfkey_extensions_free(extensions);
		pfkey_msg_free(&pfkey_msg);
		exit(1);
	}
	
	if((error = write(pfkey_sock,
			  pfkey_msg,
			  pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) !=
	   (ssize_t)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) {
		fprintf(stderr,
			"%s: pfkey write failed, tried to write %u octets, returning %d with errno=%d.\n",
			program_name,
			(unsigned)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN),
			error,
			errno);
		pfkey_extensions_free(extensions);
		pfkey_msg_free(&pfkey_msg);
		switch(errno) {
		case EACCES:
			fprintf(stderr, "access denied.  ");
			if(getuid() == 0) {
				fprintf(stderr, "Check permissions.  Should be 600.\n");
			} else {
				fprintf(stderr, "You must be root to open this file.\n");
			}
			break;
		case EUNATCH:
			fprintf(stderr, "Netlink not enabled OR KLIPS not loaded.\n");
			break;
		case EBUSY:
			fprintf(stderr, "KLIPS is busy.  Most likely a serious internal error occured in a previous command.  Please report as much detail as possible to development team.\n");
			break;
		case EINVAL:
			fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
			break;
		case ENODEV:
			fprintf(stderr, "KLIPS not loaded or enabled.\n");
			fprintf(stderr, "No device?!?\n");
			break;
		case ENOBUFS:
			fprintf(stderr, "No kernel memory to allocate SA.\n");
			break;
		case ESOCKTNOSUPPORT:
			fprintf(stderr, "Algorithm support not available in the kernel.  Please compile in support.\n");
			break;
		case EEXIST:
			fprintf(stderr, "SA already in use.  Delete old one first.\n");
			break;
		case ENOENT:
			fprintf(stderr, "device does not exist.  See FreeS/WAN installation procedure.\n");
			break;
		case ENXIO:
			fprintf(stderr, "SA does not exist.  Cannot delete.\n");
			break;
		case ENOSPC:
			fprintf(stderr, "no room in kernel SAref table.  Cannot process request.\n");
			break;
		case ESPIPE:
			fprintf(stderr, "kernel SAref table internal error.  Cannot process request.\n");
			break;
		default:
			fprintf(stderr, "Unknown socket write error %d.  Please report as much detail as possible to development team.\n", errno);
		}
		exit(1);
	}

	if(pfkey_msg) {
		pfkey_extensions_free(extensions);
		pfkey_msg_free(&pfkey_msg);
	}

	(void) close(pfkey_sock);  /* close the socket */
	exit(0);
}
Esempio n. 5
0
int
main(int argc, char *argv[])
{
	struct ifreq ifr;
	struct ipsectunnelconf shc;
	int s;
	int c;
	int argcount = argc;
	int createdelete = 0;
	char virtname[64];
        struct stat sts;
     
	memset(&ifr, 0, sizeof(ifr));
	memset(&shc, 0, sizeof(shc));
	virtname[0]='\0';
	progname = argv[0];

	tool_init_log();

	while((c = getopt_long_only(argc, argv, ""/*"adchvV:P:l:+:"*/, longopts, 0)) != EOF) {
		switch(c) {
		case 'g':
			debug = 1;
			argcount--;
			break;
		case 'a':
			check_conflict(shc.cf_cmd, createdelete);
			shc.cf_cmd = IPSEC_SET_DEV;
			break;
		case 'd':
			check_conflict(shc.cf_cmd, createdelete);
			shc.cf_cmd = IPSEC_DEL_DEV;
			break;
		case 'c':
			check_conflict(shc.cf_cmd, createdelete);
			shc.cf_cmd = IPSEC_CLR_DEV;
			break;
		case 'h':
			usage(progname);
			break;
		case 'v':
			if(optarg) {
				fprintf(stderr, "%s: warning; '-v' and '--version' options don't expect arguments, arg '%s' found, perhaps unintended.\n",
					progname, optarg);
			}
			fprintf(stdout, "%s, use ipsec --version instead\n", progname);
			exit(1);
			break;

		case 'C':
			check_conflict(shc.cf_cmd, createdelete);
			createdelete = SADB_X_PLUMBIF;
			strncat(virtname, optarg, sizeof(virtname)-1);
			break;
		case 'D':
			check_conflict(shc.cf_cmd, createdelete);
			createdelete = SADB_X_UNPLUMBIF;
			strncat(virtname, optarg, sizeof(virtname)-1);
			break;

		case 'V':
			strncpy(ifr.ifr_name, optarg, sizeof(ifr.ifr_name));
			break;
		case 'P':
			strncpy(shc.cf_name, optarg, sizeof(shc.cf_name));
			break;
		case 'l':
			progname = malloc(strlen(argv[0])
					      + 10 /* update this when changing the sprintf() */
					      + strlen(optarg));
			sprintf(progname, "%s --label %s",
				argv[0],
				optarg);
			argcount -= 2;
			break;
		case '+': /* optionsfrom */
			optionsfrom(optarg, &argc, &argv, optind, stderr);
			/* no return on error */
			break;
		default:
			usage(progname);
			break;
		}
	}

        if ( ((stat ("/proc/net/pfkey", &sts)) == 0) )  {
                fprintf(stderr, "%s: NETKEY does not support virtual interfaces.\n",progname);
                exit(1);
        }

        if(argcount == 1) {
                int ret = 1;
                if ((stat ("/proc/net/ipsec_tncfg", &sts)) != 0)  {
                        fprintf(stderr, "%s: No tncfg - no IPsec support in kernel (are the modules loaded?)\n", progname);
                } else {
                        ret = system("cat /proc/net/ipsec_tncfg");
                        ret = ret != -1 && WIFEXITED(ret) ? WEXITSTATUS(ret) : 1;
                }
                exit(ret);
        }

	/* overlay our struct ipsectunnel onto ifr.ifr_ifru union (hope it fits!) */
	if (sizeof(ifr.ifr_ifru) < sizeof(shc)) {
	    fprintf(stderr, "%s: Internal error: struct ipsectunnelconf won't fit inside struct ifreq\n",
		progname);
	    exit(1);
	}
	memcpy(&ifr.ifr_ifru.ifru_newname, &shc, sizeof(shc));

	/* are we creating/deleting a virtual (mastXXX/ipsecXXX) interface? */
	if(createdelete) {
		exit(createdelete_virtual(createdelete, virtname));
	}

	switch(shc.cf_cmd) {
	case IPSEC_SET_DEV:
		if(!shc.cf_name[0]) {
			fprintf(stderr, "%s: physical I/F parameter missing.\n",
				progname);
			exit(1);
		}
	case IPSEC_DEL_DEV:
		if(!ifr.ifr_name[0]) {
			fprintf(stderr, "%s: virtual I/F parameter missing.\n",
				progname);
			exit(1);
		}
		break;
	case IPSEC_CLR_DEV:
		strncpy(ifr.ifr_name, "ipsec0", sizeof(ifr.ifr_name));
		break;
	default:
		fprintf(stderr, "%s: exactly one of '--attach', '--detach' or '--clear' options must be specified.\n"
			"Try %s --help' for usage information.\n",
			progname, progname);
		exit(1);
	}

	s=safe_socket(AF_INET, SOCK_DGRAM,0);
	if(s==-1)
	{
		fprintf(stderr, "%s: Socket creation failed -- ", progname);
		switch(errno)
		{
		case EACCES:
			if(getuid()==0)
				fprintf(stderr, "Root denied permission!?!\n");
			else
				fprintf(stderr, "Run as root user.\n");
			break;
		case EPROTONOSUPPORT:
			fprintf(stderr, "Internet Protocol not enabled");
			break;
		case EMFILE:
		case ENFILE:
		case ENOBUFS:
			fprintf(stderr, "Insufficient system resources.\n");
			break;
		case ENODEV:
			fprintf(stderr, "No such device.  Is the virtual device valid?  Is the ipsec module linked into the kernel or loaded as a module?\n");
			break;
		default:
			fprintf(stderr, "Unknown socket error %d.\n", errno);
		}
		exit(1);
	}
	if(ioctl(s, shc.cf_cmd, &ifr)==-1)
	{
		switch (shc.cf_cmd)
		{
		case IPSEC_SET_DEV:
			fprintf(stderr, "%s: Socket ioctl failed on attach -- ", progname);
			switch(errno)
			{
			case EINVAL:
				fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
				break;
			case ENODEV:
				fprintf(stderr, "No such device.  Is the virtual device valid?  Is the ipsec module linked into the kernel or loaded as a module?\n");
				break;
			case ENXIO:
				fprintf(stderr, "No such device.  Is the physical device valid?\n");
				break;
			case EBUSY:
				fprintf(stderr, "Device busy.  Virtual device %s is already attached to a physical device -- Use detach first.\n",
				       ifr.ifr_name);
				break;
			default:
				fprintf(stderr, "Unknown socket error %d.\n", errno);
			}
			exit(1);

		case IPSEC_DEL_DEV:
			fprintf(stderr, "%s: Socket ioctl failed on detach -- ", progname);
			switch(errno)
			{
			case EINVAL:
				fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
				break;
			case ENODEV:
				fprintf(stderr, "No such device.  Is the virtual device valid?  The ipsec module may not be linked into the kernel or loaded as a module.\n");
				break;
			case ENXIO:
				fprintf(stderr, "Device requested is not linked to any physical device.\n");
				break;
			default:
				fprintf(stderr, "Unknown socket error %d.\n", errno);
			}
			exit(1);

		case IPSEC_CLR_DEV:
			fprintf(stderr, "%s: Socket ioctl failed on clear -- ", progname);
			switch(errno)
			{
			case EINVAL:
				fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
				break;
			case ENODEV:
				fprintf(stderr, "Failed.  Is the ipsec module linked into the kernel or loaded as a module?.\n");
				break;
			default:
				fprintf(stderr, "Unknown socket error %d.\n", errno);
			}
			exit(1);
		default:
			fprintf(stderr, "%s: Socket ioctl failed on unknown operation %u -- %s", progname, (unsigned) shc.cf_cmd, strerror(errno));
			exit(1);
		}
	}
	exit(0);
}
Esempio n. 6
0
int
main(int argc, char **argv)
{
    bool fork_desired = TRUE;
    bool log_to_stderr_desired = FALSE;
    int lockfd;
    char* ocspuri = NULL;

#ifdef NAT_TRAVERSAL
    /** Overridden by nat_traversal= in ipsec.conf */
    bool nat_traversal = FALSE;
    bool nat_t_spf = TRUE;  /* support port floating */
    unsigned int keep_alive = 0;
    bool force_keepalive = FALSE;
#endif
#ifdef VIRTUAL_IP
    /** Overridden by virtual_private= in ipsec.conf */
    char *virtual_private = NULL;
#endif

    /* handle arguments */
    for (;;)
    {
#	define DBG_OFFSET 256
	static const struct option long_opts[] = {
	    /* name, has_arg, flag, val */
	    { "help", no_argument, NULL, 'h' },
	    { "version", no_argument, NULL, 'v' },
	    { "optionsfrom", required_argument, NULL, '+' },
	    { "nofork", no_argument, NULL, 'd' },
	    { "stderrlog", no_argument, NULL, 'e' },
	    { "noklips", no_argument, NULL, 'n' },
	    { "nocrsend", no_argument, NULL, 'c' },
	    { "strictcrlpolicy", no_argument, NULL, 'r' },
	    { "crlcheckinterval", required_argument, NULL, 'x'},
	    { "ocsprequestcert", required_argument, NULL, 'q'},
	    { "ocspuri", required_argument, NULL, 'o'},
	    { "uniqueids", no_argument, NULL, 'u' },
	    { "interface", required_argument, NULL, 'i' },
	    { "ikeport", required_argument, NULL, 'p' },
	    { "ctlbase", required_argument, NULL, 'b' },
	    { "secretsfile", required_argument, NULL, 's' },
	    { "foodgroupsdir", required_argument, NULL, 'f' },
	    { "perpeerlogbase", required_argument, NULL, 'P' },
	    { "perpeerlog", no_argument, NULL, 'l' },
	    { "noretransmits", no_argument, NULL, 'R' },
	    { "ipsecdir", required_argument, NULL, 'f' },
	    { "ipsec_dir", required_argument, NULL, 'f' },
#ifdef USE_LWRES
	    { "lwdnsq", required_argument, NULL, 'a' },
#else /* !USE_LWRES */
	    { "adns", required_argument, NULL, 'a' },
#endif /* !USE_LWRES */
#ifdef NAT_TRAVERSAL
	    { "nat_traversal", no_argument, NULL, '1' },
	    { "keep_alive", required_argument, NULL, '2' },
	    { "force_keepalive", no_argument, NULL, '3' },
	    { "disable_port_floating", no_argument, NULL, '4' },
	    { "debug-nat_t", no_argument, NULL, '5' },
#endif
#ifdef VIRTUAL_IP
	    { "virtual_private", required_argument, NULL, '6' },
#endif
#ifdef DEBUG
	    { "debug-none", no_argument, NULL, 'N' },
	    { "debug-all]", no_argument, NULL, 'A' },

	    { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET },
	    { "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET },
	    { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET },
	    { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET },
	    { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET },
	    { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET },
	    { "debug-klips", no_argument, NULL, DBG_KLIPS + DBG_OFFSET },
	    { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET },
	    { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET },
	    { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET },
	    { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET },
	    { "debug-pfkey", no_argument, NULL, DBG_PFKEY + DBG_OFFSET },

	    { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET },
	    { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET },
	    { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET },
	    { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET },
#endif
	    { 0,0,0,0 }
	    };
	/* Note: we don't like the way short options get parsed
	 * by getopt_long, so we simply pass an empty string as
	 * the list.  It could be "hvdenp:l:s:" "NARXPECK".
	 */
	int c = getopt_long(argc, argv, "", long_opts, NULL);

	/** Note: "breaking" from case terminates loop */
	switch (c)
	{
	case EOF:	/* end of flags */
	    break;

	case 0: /* long option already handled */
	    continue;

	case ':':	/* diagnostic already printed by getopt_long */
	case '?':	/* diagnostic already printed by getopt_long */
	    usage("");
	    break;   /* not actually reached */

	case 'h':	/* --help */
	    usage(NULL);
	    break;	/* not actually reached */

	case 'v':	/* --version */
	    {
		const char **sp = ipsec_copyright_notice();

		printf("%s%s\n", ipsec_version_string(),
				 compile_time_interop_options);
		for (; *sp != NULL; sp++)
		    puts(*sp);
	    }
	    exit(0);	/* not exit_pluto because we are not initialized yet */
	    break;	/* not actually reached */

	case '+':	/* --optionsfrom <filename> */
	    optionsfrom(optarg, &argc, &argv, optind, stderr);
	    /* does not return on error */
	    continue;

	case 'd':	/* --nofork*/
	    fork_desired = FALSE;
	    continue;

	case 'e':	/* --stderrlog */
	    log_to_stderr_desired = TRUE;
	    continue;

	case 'n':	/* --noklips */
	    no_klips = TRUE;
	    continue;

	case 'c':	/* --nocrsend */
	    no_cr_send = TRUE;
	    continue
	    ;

	case 'r':	/* --strictcrlpolicy */
	    strict_crl_policy = TRUE;
	    continue
	    ;

	case 'R':
	    no_retransmits = TRUE;
	    continue;

	case 'x':	/* --crlcheckinterval <time>*/
            if (optarg == NULL || !isdigit(optarg[0]))
                usage("missing interval time");

            {
                char *endptr;
                long interval = strtol(optarg, &endptr, 0);

                if (*endptr != '\0' || endptr == optarg
                || interval <= 0)
                    usage("<interval-time> must be a positive number");
                crl_check_interval = interval;
            }
	    continue
	    ;

	case 'o':	/* --ocspuri */
	    ocspuri = optarg;
	    continue;

	case 'u':	/* --uniqueids */
	    uniqueIDs = TRUE;
	    continue;

	case 'i':	/* --interface <ifname> */
	    if (!use_interface(optarg))
		usage("too many --interface specifications");
	    continue;

	case 'p':	/* --port <portnumber> */
	    if (optarg == NULL || !isdigit(optarg[0]))
		usage("missing port number");

	    {
		char *endptr;
		long port = strtol(optarg, &endptr, 0);

		if (*endptr != '\0' || endptr == optarg
		|| port <= 0 || port > 0x10000)
		    usage("<port-number> must be a number between 1 and 65535");
		pluto_port = port;
	    }
	    continue;

	case 'b':	/* --ctlbase <path> */
	    if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path)
	    , "%s%s", optarg, CTL_SUFFIX) == -1)
		usage("<path>" CTL_SUFFIX " too long for sun_path");
	    if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path)
	    , "%s%s", optarg, INFO_SUFFIX) == -1)
		usage("<path>" INFO_SUFFIX " too long for sun_path");
	    if (snprintf(pluto_lock, sizeof(pluto_lock)
	    , "%s%s", optarg, LOCK_SUFFIX) == -1)
		usage("<path>" LOCK_SUFFIX " must fit");
	    continue;

	case 's':	/* --secretsfile <secrets-file> */
	    shared_secrets_file = optarg;
	    continue;

	case 'f':	/* --ipsecdir <ipsec-dir> */
	    ipsec_dir = optarg;
	    continue;

	case 'a':	/* --adns <pathname> */
	    pluto_adns_option = optarg;
	    continue;

#ifdef DEBUG
	case 'N':	/* --debug-none */
	    base_debugging = DBG_NONE;
	    continue;

	case 'A':	/* --debug-all */
	    base_debugging = DBG_ALL;
	    continue;
#endif

	case 'P':       /* --perpeerlogbase */
	    base_perpeer_logdir = optarg;
	    continue;

	case 'l':
	    log_to_perpeer = TRUE;
	    continue;

#ifdef NAT_TRAVERSAL
	case '1':	/* --nat_traversal */
	    nat_traversal = TRUE;
	    continue;
	case '2':	/* --keep_alive */
	    keep_alive = atoi(optarg);
	    continue;
	case '3':	/* --force_keepalive */
	    force_keepalive = TRUE;
	    continue;
	case '4':	/* --disable_port_floating */
	    nat_t_spf = FALSE;
	    continue;
	case '5':	/* --debug-nat_t */
	    base_debugging |= DBG_NATT;
	    continue;
#endif
#ifdef VIRTUAL_IP
	case '6':	/* --virtual_private */
	    virtual_private = optarg;
	    continue;
#endif

	default:
#ifdef DEBUG
	    if (c >= DBG_OFFSET)
	    {
		base_debugging |= c - DBG_OFFSET;
		continue;
	    }
#	undef DBG_OFFSET
#endif
	    bad_case(c);
	}
	break;
    }
    if (optind != argc)
	usage("unexpected argument");
    reset_debugging();
    lockfd = create_lock();

    /* select between logging methods */

    if (log_to_stderr_desired)
	log_to_syslog = FALSE;
    else
	log_to_stderr = FALSE;

    /* set the logging function of pfkey debugging */
#ifdef DEBUG
    pfkey_debug_func = DBG_log;
    pfkey_error_func = DBG_log;
#else
    pfkey_debug_func = NULL;
    pfkey_error_func = NULL;
#endif

    /** create control socket.
     * We must create it before the parent process returns so that
     * there will be no race condition in using it.  The easiest
     * place to do this is before the daemon fork.
     */
    {
	err_t ugh = init_ctl_socket();

	if (ugh != NULL)
	{
	    fprintf(stderr, "pluto: %s", ugh);
	    exit_pluto(1);
	}
    }

#ifdef IPSECPOLICY
    /* create info socket. */
    {
	err_t ugh = init_info_socket();

	if (ugh != NULL)
	{
	    fprintf(stderr, "pluto: %s", ugh);
	    exit_pluto(1);
	}
    }
#endif

    /* If not suppressed, do daemon fork */

    if (fork_desired)
    {
	{
	    pid_t pid = fork();

	    if (pid < 0)
	    {
		int e = errno;

		fprintf(stderr, "pluto: fork failed (%d %s)\n",
		    errno, strerror(e));
		exit_pluto(1);
	    }

	    if (pid != 0)
	    {
		/* parent: die, after filling PID into lock file.
		 * must not use exit_pluto: lock would be removed!
		 */
		exit(fill_lock(lockfd, pid)? 0 : 1);
	    }
	}

	if (setsid() < 0)
	{
	    int e = errno;

	    fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n",
		errno, strerror(e));
	    exit_pluto(1);
	}
    }
    else
    {
	/* no daemon fork: we have to fill in lock file */
	(void) fill_lock(lockfd, getpid());
	fprintf(stdout, "Pluto initialized\n");
	fflush(stdout);
    }

    /** Close everything but ctl_fd and (if needed) stderr.
     * There is some danger that a library that we don't know
     * about is using some fd that we don't know about.
     * I guess we'll soon find out.
     */
    {
	int i;

	for (i = getdtablesize() - 1; i >= 0; i--)  /* Bad hack */
	    if ((!log_to_stderr || i != 2)
#ifdef IPSECPOLICY
	    && i != info_fd
#endif
	    && i != ctl_fd)
		close(i);

	/* make sure that stdin, stdout, stderr are reserved */
	if (open("/dev/null", O_RDONLY) != 0)
	    abort();
	if (dup2(0, 1) != 1)
	    abort();
	if (!log_to_stderr && dup2(0, 2) != 2)
	    abort();
    }

    init_constants();
    pluto_init_log();

    /* Note: some scripts may look for this exact message -- don't change
     * ipsec barf was one, but it no longer does.
     */
    {
#ifdef PLUTO_SENDS_VENDORID
        const char *v = init_pluto_vendorid();

        openswan_log("Starting Pluto (Openswan Version %s%s; Vendor ID %s)"
            , ipsec_version_code()
            , compile_time_interop_options
            , v);
#else
        openswan_log("Starting Pluto (Openswan Version %s%s)"
            , ipsec_version_code()
            , compile_time_interop_options);
#endif
    }

/** Initialize all of the various features */

#ifdef NAT_TRAVERSAL
    init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf);
#endif

#ifdef VIRTUAL_IP
    init_virtual_ip(virtual_private);
#endif
    init_rnd_pool();
    init_secret();
    init_states();
    init_crypto();
    init_demux();
    init_kernel();
    init_adns();
    init_id();

#ifdef HAVE_THREADS
    init_fetch();
#endif

    ocsp_set_default_uri(ocspuri);

    /* loading X.509 CA certificates */
    load_authcerts("CA cert", CA_CERT_PATH, AUTH_CA);
    /* loading X.509 AA certificates */
    load_authcerts("AA cert", AA_CERT_PATH, AUTH_AA);
    /* loading X.509 OCSP certificates */
    load_authcerts("OCSP cert", OCSP_CERT_PATH, AUTH_OCSP);

    /* loading X.509 CRLs */
    load_crls();
    /* loading attribute certificates (experimental) */
    load_acerts();

    daily_log_event();
    call_server();
    return -1;	/* Shouldn't ever reach this */
}
Esempio n. 7
0
int
main(int argc, char *argv[])
{
	struct ifreq ifr;
	struct ipsectunnelconf *shc=(struct ipsectunnelconf *)&ifr.ifr_data;
	int s;
	int c, previous = -1;
	char *program_name;
	int debug = 0;
	int argcount = argc;
	char me[] = "ipsec tncfg";
     
	memset(&ifr, 0, sizeof(ifr));
	program_name = argv[0];

	while((c = getopt_long_only(argc, argv, ""/*"adchvV:P:l:+:"*/, longopts, 0)) != EOF) {
		switch(c) {
		case 'g':
			debug = 1;
			argcount--;
			break;
		case 'a':
			if(shc->cf_cmd) {
				fprintf(stderr, "%s: exactly one of '--attach', '--detach' or '--clear' options must be specified.\n",	program_name);
				exit(1);
			}
			shc->cf_cmd = IPSEC_SET_DEV;
			break;
		case 'd':
			if(shc->cf_cmd) {
				fprintf(stderr, "%s: exactly one of '--attach', '--detach' or '--clear' options must be specified.\n",	program_name);
				exit(1);
			}
			shc->cf_cmd = IPSEC_DEL_DEV;
			break;
		case 'c':
			if(shc->cf_cmd) {
				fprintf(stderr, "%s: exactly one of '--attach', '--detach' or '--clear' options must be specified.\n",	program_name);
				exit(1);
			}
			shc->cf_cmd = IPSEC_CLR_DEV;
			break;
		case 'h':
			usage(program_name);
			break;
		case 'v':
			if(optarg) {
				fprintf(stderr, "%s: warning; '-v' and '--version' options don't expect arguments, arg '%s' found, perhaps unintended.\n",
					program_name, optarg);
			}
			fprintf(stdout, "%s %s\n", me, ipsec_version_code());
			fprintf(stdout, "See `ipsec --copyright' for copyright information.\n");
			exit(1);
			break;
		case 'V':
			strcpy(ifr.ifr_name, optarg);
			break;
		case 'P':
			strcpy(shc->cf_name, optarg);
			break;
		case 'l':
			program_name = malloc(strlen(argv[0])
					      + 10 /* update this when changing the sprintf() */
					      + strlen(optarg));
			sprintf(program_name, "%s --label %s",
				argv[0],
				optarg);
			argcount -= 2;
			break;
		case '+': /* optionsfrom */
			optionsfrom(optarg, &argc, &argv, optind, stderr);
			/* no return on error */
			break;
		default:
			usage(program_name);
			break;
		}
		previous = c;
	}

	if(argcount == 1) {
		system("cat /proc/net/ipsec_tncfg");
		exit(0);
	}

	switch(shc->cf_cmd) {
	case IPSEC_SET_DEV:
		if(!shc->cf_name) {
			fprintf(stderr, "%s: physical I/F parameter missing.\n",
				program_name);
			exit(1);
		}
	case IPSEC_DEL_DEV:
		if(!ifr.ifr_name) {
			fprintf(stderr, "%s: virtual I/F parameter missing.\n",
				program_name);
			exit(1);
		}
		break;
	case IPSEC_CLR_DEV:
		strcpy(ifr.ifr_name, "ipsec0");
		break;
	default:
		fprintf(stderr, "%s: exactly one of '--attach', '--detach' or '--clear' options must be specified.\n"
			"Try %s --help' for usage information.\n",
			program_name, program_name);
		exit(1);
	}

	s=socket(AF_INET, SOCK_DGRAM,0);
	if(s==-1)
	{
		fprintf(stderr, "%s: Socket creation failed -- ", program_name);
		switch(errno)
		{
		case EACCES:
			if(getuid()==0)
				fprintf(stderr, "Root denied permission!?!\n");
			else
				fprintf(stderr, "Run as root user.\n");
			break;
		case EPROTONOSUPPORT:
			fprintf(stderr, "Internet Protocol not enabled");
			break;
		case EMFILE:
		case ENFILE:
		case ENOBUFS:
			fprintf(stderr, "Insufficient system resources.\n");
			break;
		case ENODEV:
			fprintf(stderr, "No such device.  Is the virtual device valid?  Is the ipsec module linked into the kernel or loaded as a module?\n");
			break;
		default:
			fprintf(stderr, "Unknown socket error %d.\n", errno);
		}
		exit(1);
	}
	if(ioctl(s, shc->cf_cmd, &ifr)==-1)
	{
		if(shc->cf_cmd == IPSEC_SET_DEV) {
			fprintf(stderr, "%s: Socket ioctl failed on attach -- ", program_name);
			switch(errno)
			{
			case EINVAL:
				fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
				break;
			case ENODEV:
				fprintf(stderr, "No such device.  Is the virtual device valid?  Is the ipsec module linked into the kernel or loaded as a module?\n");
				break;
			case ENXIO:
				fprintf(stderr, "No such device.  Is the physical device valid?\n");
				break;
			case EBUSY:
				fprintf(stderr, "Device busy.  Virtual device %s is already attached to a physical device -- Use detach first.\n",
				       ifr.ifr_name);
				break;
			default:
				fprintf(stderr, "Unknown socket error %d.\n", errno);
			}
			exit(1);
		}
		if(shc->cf_cmd == IPSEC_DEL_DEV) {
			fprintf(stderr, "%s: Socket ioctl failed on detach -- ", program_name);
			switch(errno)
			{
			case EINVAL:
				fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
				break;
			case ENODEV:
				fprintf(stderr, "No such device.  Is the virtual device valid?  The ipsec module may not be linked into the kernel or loaded as a module.\n");
				break;
			case ENXIO:
				fprintf(stderr, "Device requested is not linked to any physical device.\n");
				break;
			default:
				fprintf(stderr, "Unknown socket error %d.\n", errno);
			}
			exit(1);
		}
		if(shc->cf_cmd == IPSEC_CLR_DEV) {
			fprintf(stderr, "%s: Socket ioctl failed on clear -- ", program_name);
			switch(errno)
			{
			case EINVAL:
				fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
				break;
			case ENODEV:
				fprintf(stderr, "Failed.  Is the ipsec module linked into the kernel or loaded as a module?.\n");
				break;
			default:
				fprintf(stderr, "Unknown socket error %d.\n", errno);
			}
			exit(1);
		}
	}
	exit(0);
}