You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
709 lines
22 KiB
709 lines
22 KiB
/*
|
|
* Copyright (C) 2011 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/param.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <netinet/ip.h>
|
|
#include <netdb.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "config.h"
|
|
#include "gcmalloc.h"
|
|
#include "libpfkey.h"
|
|
#include "var.h"
|
|
#include "isakmp_var.h"
|
|
#include "isakmp.h"
|
|
#include "isakmp_xauth.h"
|
|
#include "vmbuf.h"
|
|
#include "crypto_openssl.h"
|
|
#include "oakley.h"
|
|
#include "ipsec_doi.h"
|
|
#include "algorithm.h"
|
|
#include "vendorid.h"
|
|
#include "schedule.h"
|
|
#include "pfkey.h"
|
|
#include "nattraversal.h"
|
|
#include "proposal.h"
|
|
#include "sainfo.h"
|
|
#include "localconf.h"
|
|
#include "remoteconf.h"
|
|
#include "sockmisc.h"
|
|
#include "grabmyaddr.h"
|
|
#include "plog.h"
|
|
#include "admin.h"
|
|
#include "privsep.h"
|
|
#include "throttle.h"
|
|
#include "misc.h"
|
|
#include "handler.h"
|
|
|
|
static struct localconf localconf;
|
|
static struct sainfo sainfo;
|
|
static char *pre_shared_key;
|
|
|
|
static struct sockaddr *targets[2];
|
|
static struct sockaddr *source;
|
|
static struct myaddrs myaddrs[2];
|
|
|
|
struct localconf *lcconf = &localconf;
|
|
int f_local = 0;
|
|
|
|
/*****************************************************************************/
|
|
|
|
static void add_sainfo_algorithm(int class, int algorithm, int length)
|
|
{
|
|
struct sainfoalg *p = calloc(1, sizeof(struct sainfoalg));
|
|
p->alg = algorithm;
|
|
p->encklen = length;
|
|
|
|
if (!sainfo.algs[class]) {
|
|
sainfo.algs[class] = p;
|
|
} else {
|
|
struct sainfoalg *q = sainfo.algs[class];
|
|
while (q->next) {
|
|
q = q->next;
|
|
}
|
|
q->next = p;
|
|
}
|
|
}
|
|
|
|
static void add_sainfo() {
|
|
if (pk_checkalg(algclass_ipsec_auth, algtype_hmac_sha2_512, 0) == 0) {
|
|
add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_SHA2_512, 0);
|
|
} else {
|
|
do_plog(LLV_WARNING, "Kernel does not support SHA512, not enabling\n");
|
|
}
|
|
if (pk_checkalg(algclass_ipsec_auth, algtype_hmac_sha2_384, 0) == 0) {
|
|
add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_SHA2_384, 0);
|
|
} else {
|
|
do_plog(LLV_WARNING, "Kernel does not support SHA384, not enabling\n");
|
|
}
|
|
add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_SHA1, 0);
|
|
add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_SHA2_256, 0);
|
|
add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_MD5, 0);
|
|
add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_AES, 256);
|
|
add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_AES, 128);
|
|
add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_3DES, 0);
|
|
add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_DES, 0);
|
|
}
|
|
|
|
static void set_globals(char *server)
|
|
{
|
|
struct addrinfo hints = {
|
|
.ai_flags = AI_NUMERICSERV,
|
|
#ifndef INET6
|
|
.ai_family = AF_INET,
|
|
#else
|
|
.ai_family = AF_UNSPEC,
|
|
#endif
|
|
.ai_socktype = SOCK_DGRAM,
|
|
};
|
|
struct addrinfo *info;
|
|
|
|
if (getaddrinfo(server, "500", &hints, &info) != 0) {
|
|
do_plog(LLV_ERROR, "Cannot resolve address: %s\n", server);
|
|
exit(1);
|
|
}
|
|
if (info->ai_next) {
|
|
do_plog(LLV_WARNING, "Found multiple addresses. Use the first one.\n");
|
|
}
|
|
targets[0] = dupsaddr(info->ai_addr);
|
|
freeaddrinfo(info);
|
|
|
|
source = getlocaladdr(targets[0]);
|
|
if (!source) {
|
|
do_plog(LLV_ERROR, "Cannot get local address\n");
|
|
exit(1);
|
|
}
|
|
set_port(targets[0], 0);
|
|
set_port(source, 0);
|
|
|
|
myaddrs[0].addr = dupsaddr(source);
|
|
set_port(myaddrs[0].addr, PORT_ISAKMP);
|
|
myaddrs[0].sock = -1;
|
|
#ifdef ENABLE_NATT
|
|
myaddrs[0].next = &myaddrs[1];
|
|
myaddrs[1].addr = dupsaddr(myaddrs[0].addr);
|
|
set_port(myaddrs[1].addr, PORT_ISAKMP_NATT);
|
|
myaddrs[1].sock = -1;
|
|
myaddrs[1].udp_encap = 1;
|
|
#endif
|
|
|
|
localconf.myaddrs = &myaddrs[0];
|
|
localconf.port_isakmp = PORT_ISAKMP;
|
|
localconf.port_isakmp_natt = PORT_ISAKMP_NATT;
|
|
localconf.default_af = AF_INET;
|
|
localconf.pathinfo[LC_PATHTYPE_CERT] = "./";
|
|
localconf.pad_random = LC_DEFAULT_PAD_RANDOM;
|
|
localconf.pad_randomlen = LC_DEFAULT_PAD_RANDOM;
|
|
localconf.pad_strict = LC_DEFAULT_PAD_STRICT;
|
|
localconf.pad_excltail = LC_DEFAULT_PAD_EXCLTAIL;
|
|
localconf.retry_counter = 10;
|
|
localconf.retry_interval = 3;
|
|
localconf.count_persend = LC_DEFAULT_COUNT_PERSEND;
|
|
localconf.secret_size = LC_DEFAULT_SECRETSIZE;
|
|
localconf.retry_checkph1 = LC_DEFAULT_RETRY_CHECKPH1;
|
|
localconf.wait_ph2complete = LC_DEFAULT_WAIT_PH2COMPLETE;
|
|
localconf.natt_ka_interval = LC_DEFAULT_NATT_KA_INTERVAL;
|
|
|
|
sainfo.lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
|
|
sainfo.lifebyte = IPSECDOI_ATTR_SA_LD_KB_MAX;
|
|
|
|
memset(script_names, 0, sizeof(script_names));
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static int policy_match(struct sadb_address *address)
|
|
{
|
|
if (address) {
|
|
struct sockaddr *addr = PFKEY_ADDR_SADDR(address);
|
|
return !cmpsaddrwop(addr, targets[0]) || !cmpsaddrwop(addr, targets[1]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* flush; spdflush; */
|
|
static void flush()
|
|
{
|
|
struct sadb_msg *p;
|
|
int replies = 0;
|
|
int key = pfkey_open();
|
|
|
|
if (pfkey_send_dump(key, SADB_SATYPE_UNSPEC) <= 0 ||
|
|
pfkey_send_spddump(key) <= 0) {
|
|
do_plog(LLV_ERROR, "Cannot dump SAD and SPD\n");
|
|
exit(1);
|
|
}
|
|
|
|
for (p = NULL; replies < 2 && (p = pfkey_recv(key)) != NULL; free(p)) {
|
|
caddr_t q[SADB_EXT_MAX + 1];
|
|
|
|
if (p->sadb_msg_type != SADB_DUMP &&
|
|
p->sadb_msg_type != SADB_X_SPDDUMP) {
|
|
continue;
|
|
}
|
|
replies += !p->sadb_msg_seq;
|
|
|
|
if (p->sadb_msg_errno || pfkey_align(p, q) || pfkey_check(q)) {
|
|
continue;
|
|
}
|
|
if (policy_match((struct sadb_address *)q[SADB_EXT_ADDRESS_SRC]) ||
|
|
policy_match((struct sadb_address *)q[SADB_EXT_ADDRESS_DST])) {
|
|
p->sadb_msg_type = (p->sadb_msg_type == SADB_DUMP) ?
|
|
SADB_DELETE : SADB_X_SPDDELETE;
|
|
p->sadb_msg_reserved = 0;
|
|
p->sadb_msg_seq = 0;
|
|
pfkey_send(key, p, PFKEY_UNUNIT64(p->sadb_msg_len));
|
|
}
|
|
}
|
|
|
|
pfkey_close(key);
|
|
}
|
|
|
|
/* spdadd src dst protocol -P out ipsec esp/transport//require;
|
|
* spdadd dst src protocol -P in ipsec esp/transport//require;
|
|
* or
|
|
* spdadd src any protocol -P out ipsec esp/tunnel/local-remote/require;
|
|
* spdadd any src protocol -P in ipsec esp/tunnel/remote-local/require; */
|
|
static void spdadd(struct sockaddr *src, struct sockaddr *dst,
|
|
int protocol, struct sockaddr *local, struct sockaddr *remote)
|
|
{
|
|
struct __attribute__((packed)) {
|
|
struct sadb_x_policy p;
|
|
struct sadb_x_ipsecrequest q;
|
|
char addresses[sizeof(struct sockaddr_storage) * 2];
|
|
} policy;
|
|
|
|
struct sockaddr_storage any = {
|
|
#ifndef __linux__
|
|
.ss_len = src->sa_len,
|
|
#endif
|
|
.ss_family = src->sa_family,
|
|
};
|
|
|
|
int src_prefix = (src->sa_family == AF_INET) ? 32 : 128;
|
|
int dst_prefix = src_prefix;
|
|
int length = 0;
|
|
int key;
|
|
|
|
/* Fill values for outbound policy. */
|
|
memset(&policy, 0, sizeof(policy));
|
|
policy.p.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
|
|
policy.p.sadb_x_policy_type = IPSEC_POLICY_IPSEC;
|
|
policy.p.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
|
|
#ifdef HAVE_PFKEY_POLICY_PRIORITY
|
|
policy.p.sadb_x_policy_priority = PRIORITY_DEFAULT;
|
|
#endif
|
|
policy.q.sadb_x_ipsecrequest_proto = IPPROTO_ESP;
|
|
policy.q.sadb_x_ipsecrequest_mode = IPSEC_MODE_TRANSPORT;
|
|
policy.q.sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
|
|
|
|
/* Deal with tunnel mode. */
|
|
if (!dst) {
|
|
int size = sysdep_sa_len(local);
|
|
memcpy(policy.addresses, local, size);
|
|
memcpy(&policy.addresses[size], remote, size);
|
|
length += size + size;
|
|
|
|
policy.q.sadb_x_ipsecrequest_mode = IPSEC_MODE_TUNNEL;
|
|
dst = (struct sockaddr *)&any;
|
|
dst_prefix = 0;
|
|
|
|
/* Also use the source address to filter policies. */
|
|
targets[1] = dupsaddr(src);
|
|
}
|
|
|
|
/* Fix lengths. */
|
|
length += sizeof(policy.q);
|
|
policy.q.sadb_x_ipsecrequest_len = length;
|
|
length += sizeof(policy.p);
|
|
policy.p.sadb_x_policy_len = PFKEY_UNIT64(length);
|
|
|
|
/* Always do a flush before adding new policies. */
|
|
flush();
|
|
|
|
/* Set outbound policy. */
|
|
key = pfkey_open();
|
|
if (pfkey_send_spdadd(key, src, src_prefix, dst, dst_prefix, protocol,
|
|
(caddr_t)&policy, length, 0) <= 0) {
|
|
do_plog(LLV_ERROR, "Cannot set outbound policy\n");
|
|
exit(1);
|
|
}
|
|
|
|
/* Flip values for inbound policy. */
|
|
policy.p.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
|
|
if (!dst_prefix) {
|
|
int size = sysdep_sa_len(local);
|
|
memcpy(policy.addresses, remote, size);
|
|
memcpy(&policy.addresses[size], local, size);
|
|
}
|
|
|
|
/* Set inbound policy. */
|
|
if (pfkey_send_spdadd(key, dst, dst_prefix, src, src_prefix, protocol,
|
|
(caddr_t)&policy, length, 0) <= 0) {
|
|
do_plog(LLV_ERROR, "Cannot set inbound policy\n");
|
|
exit(1);
|
|
}
|
|
|
|
pfkey_close(key);
|
|
atexit(flush);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static void add_proposal(struct remoteconf *remoteconf,
|
|
int auth, int hash, int encryption, int length)
|
|
{
|
|
struct isakmpsa *p = racoon_calloc(1, sizeof(struct isakmpsa));
|
|
p->prop_no = 1;
|
|
p->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
|
|
p->enctype = encryption;
|
|
p->encklen = length;
|
|
p->authmethod = auth;
|
|
p->hashtype = hash;
|
|
p->dh_group = OAKLEY_ATTR_GRP_DESC_MODP1024;
|
|
p->vendorid = VENDORID_UNKNOWN;
|
|
p->rmconf = remoteconf;
|
|
|
|
if (!remoteconf->proposal) {
|
|
p->trns_no = 1;
|
|
remoteconf->proposal = p;
|
|
} else {
|
|
struct isakmpsa *q = remoteconf->proposal;
|
|
while (q->next) {
|
|
q = q->next;
|
|
}
|
|
p->trns_no = q->trns_no + 1;
|
|
q->next = p;
|
|
}
|
|
}
|
|
|
|
static vchar_t *strtovchar(char *string)
|
|
{
|
|
vchar_t *vchar = string ? vmalloc(strlen(string) + 1) : NULL;
|
|
if (vchar) {
|
|
memcpy(vchar->v, string, vchar->l);
|
|
vchar->l -= 1;
|
|
}
|
|
return vchar;
|
|
}
|
|
|
|
static void set_pre_shared_key(struct remoteconf *remoteconf,
|
|
char *identifier, char *key)
|
|
{
|
|
pre_shared_key = key;
|
|
if (identifier[0]) {
|
|
remoteconf->idv = strtovchar(identifier);
|
|
remoteconf->etypes->type = ISAKMP_ETYPE_AGG;
|
|
|
|
remoteconf->idvtype = IDTYPE_KEYID;
|
|
if (strchr(identifier, '.')) {
|
|
remoteconf->idvtype = IDTYPE_FQDN;
|
|
if (strchr(identifier, '@')) {
|
|
remoteconf->idvtype = IDTYPE_USERFQDN;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void set_certificates(struct remoteconf *remoteconf,
|
|
char *user_private_key, char *user_certificate,
|
|
char *ca_certificate, char *server_certificate)
|
|
{
|
|
remoteconf->myprivfile = user_private_key;
|
|
remoteconf->mycertfile = user_certificate;
|
|
if (user_certificate) {
|
|
remoteconf->idvtype = IDTYPE_ASN1DN;
|
|
}
|
|
if (!ca_certificate[0]) {
|
|
remoteconf->verify_cert = FALSE;
|
|
} else {
|
|
remoteconf->cacertfile = ca_certificate;
|
|
}
|
|
if (server_certificate[0]) {
|
|
remoteconf->peerscertfile = server_certificate;
|
|
remoteconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
|
|
}
|
|
}
|
|
|
|
#ifdef ENABLE_HYBRID
|
|
|
|
static void set_xauth_and_more(struct remoteconf *remoteconf,
|
|
char *username, char *password, char *phase1_up, char *script_arg)
|
|
{
|
|
struct xauth_rmconf *xauth = racoon_calloc(1, sizeof(struct xauth_rmconf));
|
|
xauth->login = strtovchar(username);
|
|
xauth->login->l += 1;
|
|
xauth->pass = strtovchar(password);
|
|
// Unlike the code that reads login, the code that reads pass does not
|
|
// strip trailing nulls, so don't add one here.
|
|
remoteconf->xauth = xauth;
|
|
remoteconf->mode_cfg = TRUE;
|
|
remoteconf->script[SCRIPT_PHASE1_UP] = strtovchar(phase1_up);
|
|
script_names[SCRIPT_PHASE1_UP] = script_arg;
|
|
}
|
|
|
|
#endif
|
|
|
|
extern void monitor_fd(int fd, void (*callback)(int));
|
|
|
|
void add_isakmp_handler(int fd, const char *interface)
|
|
{
|
|
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
|
|
interface, strlen(interface))) {
|
|
do_plog(LLV_WARNING, "Cannot bind socket to %s\n", interface);
|
|
}
|
|
monitor_fd(fd, (void *)isakmp_handler);
|
|
}
|
|
|
|
void setup(int argc, char **argv)
|
|
{
|
|
struct remoteconf *remoteconf = NULL;
|
|
int auth;
|
|
|
|
if (argc > 2) {
|
|
set_globals(argv[2]);
|
|
|
|
/* Initialize everything else. */
|
|
eay_init();
|
|
initrmconf();
|
|
oakley_dhinit();
|
|
compute_vendorids();
|
|
sched_init();
|
|
if (pfkey_init() < 0 || isakmp_init() < 0) {
|
|
exit(1);
|
|
}
|
|
add_sainfo();
|
|
monitor_fd(localconf.sock_pfkey, (void *)pfkey_handler);
|
|
add_isakmp_handler(myaddrs[0].sock, argv[1]);
|
|
|
|
#ifdef ENABLE_NATT
|
|
add_isakmp_handler(myaddrs[1].sock, argv[1]);
|
|
natt_keepalive_init();
|
|
#endif
|
|
|
|
/* Create remote configuration. */
|
|
remoteconf = newrmconf();
|
|
remoteconf->etypes = racoon_calloc(1, sizeof(struct etypes));
|
|
remoteconf->etypes->type = ISAKMP_ETYPE_IDENT;
|
|
remoteconf->idvtype = IDTYPE_ADDRESS;
|
|
remoteconf->ike_frag = TRUE;
|
|
remoteconf->pcheck_level = PROP_CHECK_CLAIM;
|
|
remoteconf->certtype = ISAKMP_CERT_X509SIGN;
|
|
remoteconf->gen_policy = TRUE;
|
|
remoteconf->nat_traversal = TRUE;
|
|
remoteconf->dh_group = OAKLEY_ATTR_GRP_DESC_MODP1024;
|
|
remoteconf->script[SCRIPT_PHASE1_UP] = strtovchar("");
|
|
remoteconf->script[SCRIPT_PHASE1_DOWN] = strtovchar("");
|
|
oakley_setdhgroup(remoteconf->dh_group, &remoteconf->dhgrp);
|
|
remoteconf->remote = dupsaddr(targets[0]);
|
|
}
|
|
|
|
/* Set authentication method and credentials. */
|
|
if (argc == 7 && !strcmp(argv[3], "udppsk")) {
|
|
set_pre_shared_key(remoteconf, argv[4], argv[5]);
|
|
auth = OAKLEY_ATTR_AUTH_METHOD_PSKEY;
|
|
|
|
set_port(targets[0], atoi(argv[6]));
|
|
spdadd(source, targets[0], IPPROTO_UDP, NULL, NULL);
|
|
} else if (argc == 9 && !strcmp(argv[3], "udprsa")) {
|
|
set_certificates(remoteconf, argv[4], argv[5], argv[6], argv[7]);
|
|
auth = OAKLEY_ATTR_AUTH_METHOD_RSASIG;
|
|
|
|
set_port(targets[0], atoi(argv[8]));
|
|
spdadd(source, targets[0], IPPROTO_UDP, NULL, NULL);
|
|
#ifdef ENABLE_HYBRID
|
|
} else if (argc == 10 && !strcmp(argv[3], "xauthpsk")) {
|
|
set_pre_shared_key(remoteconf, argv[4], argv[5]);
|
|
set_xauth_and_more(remoteconf, argv[6], argv[7], argv[8], argv[9]);
|
|
auth = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I;
|
|
} else if (argc == 12 && !strcmp(argv[3], "xauthrsa")) {
|
|
set_certificates(remoteconf, argv[4], argv[5], argv[6], argv[7]);
|
|
set_xauth_and_more(remoteconf, argv[8], argv[9], argv[10], argv[11]);
|
|
auth = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I;
|
|
} else if (argc == 10 && !strcmp(argv[3], "hybridrsa")) {
|
|
set_certificates(remoteconf, NULL, NULL, argv[4], argv[5]);
|
|
set_xauth_and_more(remoteconf, argv[6], argv[7], argv[8], argv[9]);
|
|
auth = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I;
|
|
#endif
|
|
} else {
|
|
printf("Usage: %s <interface> <server> [...], where [...] can be:\n"
|
|
" udppsk <identifier> <pre-shared-key> <port>; \n"
|
|
" udprsa <user-private-key> <user-certificate> \\\n"
|
|
" <ca-certificate> <server-certificate> <port>;\n"
|
|
#ifdef ENABLE_HYBRID
|
|
" xauthpsk <identifier> <pre-shared-key> \\\n"
|
|
" <username> <password> <phase1-up> <script-arg>;\n"
|
|
" xauthrsa <user-private-key> <user-certificate> \\\n"
|
|
" <ca-certificate> <server-certificate> \\\n"
|
|
" <username> <password> <phase1-up> <script-arg>;\n"
|
|
" hybridrsa <ca-certificate> <server-certificate> \\\n"
|
|
" <username> <password> <phase1-up> <script-arg>;\n"
|
|
#endif
|
|
"", argv[0]);
|
|
exit(0);
|
|
}
|
|
|
|
/* Add proposals. */
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_SHA2_384, OAKLEY_ATTR_ENC_ALG_AES, 256);
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_SHA2_256, OAKLEY_ATTR_ENC_ALG_AES, 256);
|
|
// VPNs to openswan breaks when SHA2_512 is used as the first proposal.
|
|
// openswan supports SHA2_256 or lower hash alg. With this add_proposal
|
|
// order, openswan picks SHA2_256 and others pick SHA2_384
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_SHA2_512, OAKLEY_ATTR_ENC_ALG_AES, 256);
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_AES, 256);
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_AES, 256);
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_SHA2_512, OAKLEY_ATTR_ENC_ALG_AES, 128);
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_SHA2_384, OAKLEY_ATTR_ENC_ALG_AES, 128);
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_SHA2_256, OAKLEY_ATTR_ENC_ALG_AES, 128);
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_AES, 128);
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_AES, 128);
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_SHA2_256, OAKLEY_ATTR_ENC_ALG_3DES, 0);
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_3DES, 0);
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_3DES, 0);
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_SHA2_256, OAKLEY_ATTR_ENC_ALG_DES, 0);
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_DES, 0);
|
|
add_proposal(remoteconf, auth,
|
|
OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_DES, 0);
|
|
|
|
/* Install remote configuration. */
|
|
insrmconf(remoteconf);
|
|
|
|
/* Start phase 1 negotiation for xauth. */
|
|
if (remoteconf->xauth) {
|
|
isakmp_ph1begin_i(remoteconf, remoteconf->remote, source);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* localconf.h */
|
|
|
|
vchar_t *getpskbyaddr(struct sockaddr *addr)
|
|
{
|
|
return strtovchar(pre_shared_key);
|
|
}
|
|
|
|
vchar_t *getpskbyname(vchar_t *name)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
void getpathname(char *path, int length, int type, const char *name)
|
|
{
|
|
if (pname) {
|
|
snprintf(path, length, pname, name);
|
|
} else {
|
|
strncpy(path, name, length);
|
|
}
|
|
path[length - 1] = '\0';
|
|
}
|
|
|
|
/* grabmyaddr.h */
|
|
|
|
int myaddr_getsport(struct sockaddr *addr)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int getsockmyaddr(struct sockaddr *addr)
|
|
{
|
|
#ifdef ENABLE_NATT
|
|
if (!cmpsaddrstrict(addr, myaddrs[1].addr)) {
|
|
return myaddrs[1].sock;
|
|
}
|
|
#endif
|
|
if (!cmpsaddrwop(addr, myaddrs[0].addr)) {
|
|
return myaddrs[0].sock;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/* privsep.h */
|
|
|
|
int privsep_pfkey_open()
|
|
{
|
|
return pfkey_open();
|
|
}
|
|
|
|
void privsep_pfkey_close(int key)
|
|
{
|
|
pfkey_close(key);
|
|
}
|
|
|
|
vchar_t *privsep_eay_get_pkcs1privkey(char *file)
|
|
{
|
|
return eay_get_pkcs1privkey(file);
|
|
}
|
|
|
|
static char *get_env(char * const *envp, char *key)
|
|
{
|
|
int length = strlen(key);
|
|
while (*envp && (strncmp(*envp, key, length) || (*envp)[length] != '=')) {
|
|
++envp;
|
|
}
|
|
return *envp ? &(*envp)[length + 1] : "";
|
|
}
|
|
|
|
static int skip_script = 0;
|
|
extern const char *android_hook(char **envp);
|
|
|
|
int privsep_script_exec(char *script, int name, char * const *envp)
|
|
{
|
|
if (skip_script) {
|
|
return 0;
|
|
}
|
|
skip_script = 1;
|
|
|
|
if (name == SCRIPT_PHASE1_DOWN) {
|
|
exit(1);
|
|
}
|
|
if (script_names[SCRIPT_PHASE1_UP]) {
|
|
/* Racoon ignores INTERNAL_IP6_ADDRESS, so we only do IPv4. */
|
|
struct sockaddr *addr4 = str2saddr(get_env(envp, "INTERNAL_ADDR4"),
|
|
NULL);
|
|
struct sockaddr *local = str2saddr(get_env(envp, "LOCAL_ADDR"),
|
|
get_env(envp, "LOCAL_PORT"));
|
|
struct sockaddr *remote = str2saddr(get_env(envp, "REMOTE_ADDR"),
|
|
get_env(envp, "REMOTE_PORT"));
|
|
|
|
if (addr4 && local && remote) {
|
|
#ifdef ANDROID_CHANGES
|
|
if (pname) {
|
|
script = (char *)android_hook((char **)envp);
|
|
}
|
|
#endif
|
|
spdadd(addr4, NULL, IPPROTO_IP, local, remote);
|
|
} else {
|
|
do_plog(LLV_ERROR, "Cannot get parameters for SPD policy.\n");
|
|
exit(1);
|
|
}
|
|
|
|
racoon_free(addr4);
|
|
racoon_free(local);
|
|
racoon_free(remote);
|
|
return script_exec(script, name, envp);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int privsep_accounting_system(int port, struct sockaddr *addr,
|
|
char *user, int status)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int privsep_xauth_login_system(char *user, char *password)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
/* misc.h */
|
|
|
|
int racoon_hexdump(void *data, size_t length)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* sainfo.h */
|
|
|
|
struct sainfo *getsainfo(const vchar_t *src, const vchar_t *dst,
|
|
const vchar_t *peer, int remoteid)
|
|
{
|
|
return &sainfo;
|
|
}
|
|
|
|
const char *sainfo2str(const struct sainfo *si)
|
|
{
|
|
return "*";
|
|
}
|
|
|
|
/* throttle.h */
|
|
|
|
int throttle_host(struct sockaddr *addr, int fail)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void shutdown_session()
|
|
{
|
|
flushph2();
|
|
flushph1();
|
|
isakmp_close();
|
|
pfkey_close(localconf.sock_pfkey);
|
|
}
|