Merge branch 'kernel-policies'
This commit is contained in:
@@ -144,8 +144,16 @@ static peer_cfg_t* create_peer_cfg(private_cmd_connection_t *this)
|
||||
peer_cfg_t *peer_cfg;
|
||||
uint16_t local_port, remote_port = IKEV2_UDP_PORT;
|
||||
ike_version_t version = IKE_ANY;
|
||||
bool aggressive = FALSE;
|
||||
proposal_t *proposal;
|
||||
peer_cfg_create_t peer = {
|
||||
.cert_policy = CERT_SEND_IF_ASKED,
|
||||
.unique = UNIQUE_REPLACE,
|
||||
.keyingtries = 1,
|
||||
.rekey_time = 36000, /* 10h */
|
||||
.jitter_time = 600, /* 10min */
|
||||
.over_time = 600, /* 10min */
|
||||
.dpd = 30,
|
||||
};
|
||||
|
||||
switch (this->profile)
|
||||
{
|
||||
@@ -159,7 +167,7 @@ static peer_cfg_t* create_peer_cfg(private_cmd_connection_t *this)
|
||||
case PROF_V1_XAUTH_AM:
|
||||
case PROF_V1_XAUTH_PSK_AM:
|
||||
case PROF_V1_HYBRID_AM:
|
||||
aggressive = TRUE;
|
||||
peer.aggressive = TRUE;
|
||||
/* FALL */
|
||||
case PROF_V1_PUB:
|
||||
case PROF_V1_XAUTH:
|
||||
@@ -189,13 +197,7 @@ static peer_cfg_t* create_peer_cfg(private_cmd_connection_t *this)
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
|
||||
}
|
||||
peer_cfg = peer_cfg_create("cmd", ike_cfg,
|
||||
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
|
||||
36000, 0, /* rekey 10h, reauth none */
|
||||
600, 600, /* jitter, over 10min */
|
||||
TRUE, aggressive, TRUE, /* mobike, aggressive, pull */
|
||||
30, 0, /* DPD delay, timeout */
|
||||
FALSE, NULL, NULL); /* mediation */
|
||||
peer_cfg = peer_cfg_create("cmd", ike_cfg, &peer);
|
||||
|
||||
return peer_cfg;
|
||||
}
|
||||
@@ -335,18 +337,18 @@ static child_cfg_t* create_child_cfg(private_cmd_connection_t *this,
|
||||
traffic_selector_t *ts;
|
||||
proposal_t *proposal;
|
||||
bool has_v4 = FALSE, has_v6 = FALSE;
|
||||
lifetime_cfg_t lifetime = {
|
||||
.time = {
|
||||
.life = 10800 /* 3h */,
|
||||
.rekey = 10200 /* 2h50min */,
|
||||
.jitter = 300 /* 5min */
|
||||
}
|
||||
child_cfg_create_t child = {
|
||||
.lifetime = {
|
||||
.time = {
|
||||
.life = 10800 /* 3h */,
|
||||
.rekey = 10200 /* 2h50min */,
|
||||
.jitter = 300 /* 5min */
|
||||
}
|
||||
},
|
||||
.mode = MODE_TUNNEL,
|
||||
};
|
||||
|
||||
child_cfg = child_cfg_create("cmd", &lifetime,
|
||||
NULL, FALSE, MODE_TUNNEL, /* updown, hostaccess */
|
||||
ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
|
||||
0, 0, NULL, NULL, 0);
|
||||
child_cfg = child_cfg_create("cmd", &child);
|
||||
if (this->child_proposals->get_count(this->child_proposals))
|
||||
{
|
||||
while (this->child_proposals->remove_first(this->child_proposals,
|
||||
|
||||
@@ -289,7 +289,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
||||
NMSettingVPN *vpn;
|
||||
identification_t *user = NULL, *gateway = NULL;
|
||||
const char *address, *str;
|
||||
bool virtual, encap, ipcomp;
|
||||
bool virtual, encap;
|
||||
ike_cfg_t *ike_cfg;
|
||||
peer_cfg_t *peer_cfg;
|
||||
child_cfg_t *child_cfg;
|
||||
@@ -300,12 +300,23 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
||||
certificate_t *cert = NULL;
|
||||
x509_t *x509;
|
||||
bool agent = FALSE, smartcard = FALSE, loose_gateway_id = FALSE;
|
||||
lifetime_cfg_t lifetime = {
|
||||
.time = {
|
||||
.life = 10800 /* 3h */,
|
||||
.rekey = 10200 /* 2h50min */,
|
||||
.jitter = 300 /* 5min */
|
||||
}
|
||||
peer_cfg_create_t peer = {
|
||||
.cert_policy = CERT_SEND_IF_ASKED,
|
||||
.unique = UNIQUE_REPLACE,
|
||||
.keyingtries = 1,
|
||||
.rekey_time = 36000, /* 10h */
|
||||
.jitter_time = 600, /* 10min */
|
||||
.over_time = 600, /* 10min */
|
||||
};
|
||||
child_cfg_create_t child = {
|
||||
.lifetime = {
|
||||
.time = {
|
||||
.life = 10800 /* 3h */,
|
||||
.rekey = 10200 /* 2h50min */,
|
||||
.jitter = 300 /* 5min */
|
||||
},
|
||||
},
|
||||
.mode = MODE_TUNNEL,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -339,32 +350,29 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
||||
return FALSE;
|
||||
}
|
||||
str = nm_setting_vpn_get_data_item(vpn, "virtual");
|
||||
virtual = str && streq(str, "yes");
|
||||
virtual = streq(str, "yes");
|
||||
str = nm_setting_vpn_get_data_item(vpn, "encap");
|
||||
encap = str && streq(str, "yes");
|
||||
encap = streq(str, "yes");
|
||||
str = nm_setting_vpn_get_data_item(vpn, "ipcomp");
|
||||
ipcomp = str && streq(str, "yes");
|
||||
child.ipcomp = streq(str, "yes");
|
||||
str = nm_setting_vpn_get_data_item(vpn, "method");
|
||||
if (str)
|
||||
if (streq(str, "psk"))
|
||||
{
|
||||
if (streq(str, "psk"))
|
||||
{
|
||||
auth_class = AUTH_CLASS_PSK;
|
||||
}
|
||||
else if (streq(str, "agent"))
|
||||
{
|
||||
auth_class = AUTH_CLASS_PUBKEY;
|
||||
agent = TRUE;
|
||||
}
|
||||
else if (streq(str, "key"))
|
||||
{
|
||||
auth_class = AUTH_CLASS_PUBKEY;
|
||||
}
|
||||
else if (streq(str, "smartcard"))
|
||||
{
|
||||
auth_class = AUTH_CLASS_PUBKEY;
|
||||
smartcard = TRUE;
|
||||
}
|
||||
auth_class = AUTH_CLASS_PSK;
|
||||
}
|
||||
else if (streq(str, "agent"))
|
||||
{
|
||||
auth_class = AUTH_CLASS_PUBKEY;
|
||||
agent = TRUE;
|
||||
}
|
||||
else if (streq(str, "key"))
|
||||
{
|
||||
auth_class = AUTH_CLASS_PUBKEY;
|
||||
}
|
||||
else if (streq(str, "smartcard"))
|
||||
{
|
||||
auth_class = AUTH_CLASS_PUBKEY;
|
||||
smartcard = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -533,13 +541,8 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
||||
FRAGMENTATION_NO, 0);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
|
||||
peer_cfg = peer_cfg_create(priv->name, ike_cfg,
|
||||
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
|
||||
36000, 0, /* rekey 10h, reauth none */
|
||||
600, 600, /* jitter, over 10min */
|
||||
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
|
||||
0, 0, /* DPD delay, timeout */
|
||||
FALSE, NULL, NULL); /* mediation */
|
||||
|
||||
peer_cfg = peer_cfg_create(priv->name, ike_cfg, &peer);
|
||||
if (virtual)
|
||||
{
|
||||
peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
|
||||
@@ -561,10 +564,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
||||
auth->add(auth, AUTH_RULE_IDENTITY_LOOSE, loose_gateway_id);
|
||||
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
|
||||
|
||||
child_cfg = child_cfg_create(priv->name, &lifetime,
|
||||
NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */
|
||||
ACTION_NONE, ACTION_NONE, ACTION_NONE, ipcomp,
|
||||
0, 0, NULL, NULL, 0);
|
||||
child_cfg = child_cfg_create(priv->name, &child);
|
||||
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
|
||||
child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
|
||||
ts = traffic_selector_create_dynamic(0, 0, 65535);
|
||||
|
||||
@@ -81,13 +81,8 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, uint32_t reqid, mark_t mark,
|
||||
uint32_t tfc, lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
|
||||
uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
|
||||
uint16_t ipcomp, uint16_t cpi, uint32_t replay_window,
|
||||
bool initiator, bool encap, bool esn, bool inbound, bool update,
|
||||
linked_list_t* src_ts, linked_list_t* dst_ts)
|
||||
private_tkm_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_add_sa_t *data)
|
||||
{
|
||||
esa_info_t esa;
|
||||
esp_spi_type spi_loc, spi_rem;
|
||||
@@ -97,43 +92,43 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
esa_id_type esa_id;
|
||||
nonce_type nc_rem;
|
||||
|
||||
if (enc_key.ptr == NULL)
|
||||
if (data->enc_key.ptr == NULL)
|
||||
{
|
||||
DBG1(DBG_KNL, "Unable to get ESA information");
|
||||
return FAILED;
|
||||
}
|
||||
esa = *(esa_info_t *)(enc_key.ptr);
|
||||
esa = *(esa_info_t *)(data->enc_key.ptr);
|
||||
|
||||
/* only handle the case where we have both distinct ESP spi's available */
|
||||
if (esa.spi_r == spi)
|
||||
if (esa.spi_r == id->spi)
|
||||
{
|
||||
chunk_free(&esa.nonce_i);
|
||||
chunk_free(&esa.nonce_r);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (initiator)
|
||||
if (data->initiator)
|
||||
{
|
||||
spi_loc = spi;
|
||||
spi_loc = id->spi;
|
||||
spi_rem = esa.spi_r;
|
||||
local = dst;
|
||||
peer = src;
|
||||
local = id->dst;
|
||||
peer = id->src;
|
||||
nonce_loc = &esa.nonce_i;
|
||||
nonce_rem = &esa.nonce_r;
|
||||
}
|
||||
else
|
||||
{
|
||||
spi_loc = esa.spi_r;
|
||||
spi_rem = spi;
|
||||
local = src;
|
||||
peer = dst;
|
||||
spi_rem = id->spi;
|
||||
local = id->src;
|
||||
peer = id->dst;
|
||||
nonce_loc = &esa.nonce_r;
|
||||
nonce_rem = &esa.nonce_i;
|
||||
}
|
||||
|
||||
esa_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ESA);
|
||||
if (!tkm->sad->insert(tkm->sad, esa_id, reqid, local, peer, spi_loc, spi_rem,
|
||||
protocol))
|
||||
if (!tkm->sad->insert(tkm->sad, esa_id, data->reqid, local, peer,
|
||||
spi_loc, spi_rem, id->proto))
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to add entry (%llu) to SAD", esa_id);
|
||||
goto sad_failure;
|
||||
@@ -146,8 +141,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
nonce_loc_id = tkm->chunk_map->get_id(tkm->chunk_map, nonce_loc);
|
||||
if (nonce_loc_id == 0 && esa.dh_id == 0)
|
||||
{
|
||||
if (ike_esa_create_first(esa_id, esa.isa_id, reqid, 1, spi_loc, spi_rem)
|
||||
!= TKM_OK)
|
||||
if (ike_esa_create_first(esa_id, esa.isa_id, data->reqid, 1, spi_loc,
|
||||
spi_rem) != TKM_OK)
|
||||
{
|
||||
DBG1(DBG_KNL, "child SA (%llu, first) creation failed", esa_id);
|
||||
goto failure;
|
||||
@@ -157,9 +152,9 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
else if (nonce_loc_id != 0 && esa.dh_id == 0)
|
||||
{
|
||||
chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type));
|
||||
if (ike_esa_create_no_pfs(esa_id, esa.isa_id, reqid, 1, nonce_loc_id,
|
||||
nc_rem, initiator, spi_loc, spi_rem)
|
||||
!= TKM_OK)
|
||||
if (ike_esa_create_no_pfs(esa_id, esa.isa_id, data->reqid, 1,
|
||||
nonce_loc_id, nc_rem, data->initiator,
|
||||
spi_loc, spi_rem) != TKM_OK)
|
||||
{
|
||||
DBG1(DBG_KNL, "child SA (%llu, no PFS) creation failed", esa_id);
|
||||
goto failure;
|
||||
@@ -171,8 +166,9 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
else
|
||||
{
|
||||
chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type));
|
||||
if (ike_esa_create(esa_id, esa.isa_id, reqid, 1, esa.dh_id, nonce_loc_id,
|
||||
nc_rem, initiator, spi_loc, spi_rem) != TKM_OK)
|
||||
if (ike_esa_create(esa_id, esa.isa_id, data->reqid, 1, esa.dh_id,
|
||||
nonce_loc_id, nc_rem, data->initiator, spi_loc,
|
||||
spi_rem) != TKM_OK)
|
||||
{
|
||||
DBG1(DBG_KNL, "child SA (%llu) creation failed", esa_id);
|
||||
goto failure;
|
||||
@@ -192,7 +188,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
|
||||
DBG1(DBG_KNL, "added child SA (esa: %llu, isa: %llu, esp_spi_loc: %x, "
|
||||
"esp_spi_rem: %x, role: %s)", esa_id, esa.isa_id, ntohl(spi_loc),
|
||||
ntohl(spi_rem), initiator ? "initiator" : "responder");
|
||||
ntohl(spi_rem), data->initiator ? "initiator" : "responder");
|
||||
chunk_free(&esa.nonce_i);
|
||||
chunk_free(&esa.nonce_r);
|
||||
|
||||
@@ -208,20 +204,21 @@ sad_failure:
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||
private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, mark_t mark, uint64_t *bytes,
|
||||
uint64_t *packets, time_t *time)
|
||||
private_tkm_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
|
||||
time_t *time)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, del_sa, status_t,
|
||||
private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, uint16_t cpi, mark_t mark)
|
||||
private_tkm_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_del_sa_t *data)
|
||||
{
|
||||
esa_id_type esa_id, other_esa_id;
|
||||
|
||||
esa_id = tkm->sad->get_esa_id(tkm->sad, src, dst, spi, protocol);
|
||||
esa_id = tkm->sad->get_esa_id(tkm->sad, id->src, id->dst,
|
||||
id->spi, id->proto);
|
||||
if (esa_id)
|
||||
{
|
||||
other_esa_id = tkm->sad->get_other_esa_id(tkm->sad, esa_id);
|
||||
@@ -236,7 +233,7 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
|
||||
}
|
||||
|
||||
DBG1(DBG_KNL, "deleting child SA (esa: %llu, spi: %x)", esa_id,
|
||||
ntohl(spi));
|
||||
ntohl(id->spi));
|
||||
if (ike_esa_reset(esa_id) != TKM_OK)
|
||||
{
|
||||
DBG1(DBG_KNL, "child SA (%llu) deletion failed", esa_id);
|
||||
@@ -249,9 +246,8 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, update_sa, status_t,
|
||||
private_tkm_kernel_ipsec_t *this, uint32_t spi, uint8_t protocol,
|
||||
uint16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
|
||||
bool old_encap, bool new_encap, mark_t mark)
|
||||
private_tkm_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_update_sa_t *data)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
@@ -264,27 +260,22 @@ METHOD(kernel_ipsec_t, flush_sas, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, add_policy, status_t,
|
||||
private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
|
||||
mark_t mark, policy_priority_t priority)
|
||||
private_tkm_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||
private_tkm_kernel_ipsec_t *this, traffic_selector_t *src_ts,
|
||||
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
||||
time_t *use_time)
|
||||
private_tkm_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_query_policy_t *data, time_t *use_time)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, del_policy, status_t,
|
||||
private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
|
||||
mark_t mark, policy_priority_t priority)
|
||||
private_tkm_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
+14
-12
@@ -139,25 +139,23 @@ static ike_cfg_t *load_ike_config(private_config_t *this,
|
||||
static child_cfg_t *load_child_config(private_config_t *this,
|
||||
settings_t *settings, char *config, char *child)
|
||||
{
|
||||
child_cfg_create_t data = {
|
||||
.mode = MODE_TUNNEL,
|
||||
};
|
||||
child_cfg_t *child_cfg;
|
||||
lifetime_cfg_t lifetime = {};
|
||||
enumerator_t *enumerator;
|
||||
proposal_t *proposal;
|
||||
traffic_selector_t *ts;
|
||||
ipsec_mode_t mode = MODE_TUNNEL;
|
||||
char *token;
|
||||
uint32_t tfc;
|
||||
|
||||
if (settings->get_bool(settings, "configs.%s.%s.transport",
|
||||
FALSE, config, child))
|
||||
{
|
||||
mode = MODE_TRANSPORT;
|
||||
data.mode = MODE_TRANSPORT;
|
||||
}
|
||||
tfc = settings->get_int(settings, "configs.%s.%s.tfc_padding",
|
||||
0, config, child);
|
||||
child_cfg = child_cfg_create(child, &lifetime, NULL, FALSE, mode,
|
||||
ACTION_NONE, ACTION_NONE, ACTION_NONE,
|
||||
FALSE, 0, 0, NULL, NULL, tfc);
|
||||
data.tfc = settings->get_int(settings, "configs.%s.%s.tfc_padding",
|
||||
0, config, child);
|
||||
child_cfg = child_cfg_create(child, &data);
|
||||
|
||||
token = settings->get_str(settings, "configs.%s.%s.proposal",
|
||||
NULL, config, child);
|
||||
@@ -249,11 +247,15 @@ static peer_cfg_t *load_peer_config(private_config_t *this,
|
||||
identification_t *lid, *rid;
|
||||
char *child, *policy, *pool;
|
||||
uintptr_t strength;
|
||||
peer_cfg_create_t peer = {
|
||||
.cert_policy = CERT_ALWAYS_SEND,
|
||||
.unique = UNIQUE_NO,
|
||||
.keyingtries = 1,
|
||||
.no_mobike = TRUE,
|
||||
};
|
||||
|
||||
ike_cfg = load_ike_config(this, settings, config);
|
||||
peer_cfg = peer_cfg_create(config, ike_cfg, CERT_ALWAYS_SEND,
|
||||
UNIQUE_NO, 1, 0, 0, 0, 0, FALSE, FALSE, TRUE,
|
||||
0, 0, FALSE, NULL, NULL);
|
||||
peer_cfg = peer_cfg_create(config, ike_cfg, &peer);
|
||||
|
||||
auth = auth_cfg_create();
|
||||
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
|
||||
|
||||
@@ -673,12 +673,24 @@ static job_requeue_t initiate(private_android_service_t *this)
|
||||
traffic_selector_t *ts;
|
||||
ike_sa_t *ike_sa;
|
||||
auth_cfg_t *auth;
|
||||
lifetime_cfg_t lifetime = {
|
||||
.time = {
|
||||
.life = 3600, /* 1h */
|
||||
.rekey = 3000, /* 50min */
|
||||
.jitter = 300 /* 5min */
|
||||
}
|
||||
peer_cfg_create_t peer = {
|
||||
.cert_policy = CERT_SEND_IF_ASKED,
|
||||
.unique = UNIQUE_REPLACE,
|
||||
.rekey_time = 36000, /* 10h */
|
||||
.jitter_time = 600, /* 10min */
|
||||
.over_time = 600, /* 10min */
|
||||
};
|
||||
child_cfg_create_t child = {
|
||||
.lifetime = {
|
||||
.time = {
|
||||
.life = 3600, /* 1h */
|
||||
.rekey = 3000, /* 50min */
|
||||
.jitter = 300 /* 5min */
|
||||
},
|
||||
},
|
||||
.mode = MODE_TUNNEL,
|
||||
.dpd_action = ACTION_RESTART,
|
||||
.close_action = ACTION_RESTART,
|
||||
};
|
||||
char *type, *server;
|
||||
int port;
|
||||
@@ -692,13 +704,7 @@ static job_requeue_t initiate(private_android_service_t *this)
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
|
||||
|
||||
peer_cfg = peer_cfg_create("android", ike_cfg, CERT_SEND_IF_ASKED,
|
||||
UNIQUE_REPLACE, 0, /* keyingtries */
|
||||
36000, 0, /* rekey 10h, reauth none */
|
||||
600, 600, /* jitter, over 10min */
|
||||
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
|
||||
0, 0, /* DPD delay, timeout */
|
||||
FALSE, NULL, NULL); /* mediation */
|
||||
peer_cfg = peer_cfg_create("android", ike_cfg, &peer);
|
||||
peer_cfg->add_virtual_ip(peer_cfg, host_create_any(AF_INET));
|
||||
peer_cfg->add_virtual_ip(peer_cfg, host_create_any(AF_INET6));
|
||||
|
||||
@@ -731,9 +737,7 @@ static job_requeue_t initiate(private_android_service_t *this)
|
||||
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
|
||||
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
|
||||
|
||||
child_cfg = child_cfg_create("android", &lifetime, NULL, TRUE, MODE_TUNNEL,
|
||||
ACTION_NONE, ACTION_RESTART, ACTION_RESTART,
|
||||
FALSE, 0, 0, NULL, NULL, 0);
|
||||
child_cfg = child_cfg_create("android", &child);
|
||||
/* create ESP proposals with and without DH groups, let responder decide
|
||||
* if PFS is used */
|
||||
child_cfg->add_proposal(child_cfg, proposal_create_from_string(PROTO_ESP,
|
||||
|
||||
@@ -60,43 +60,40 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
private_kernel_android_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, uint32_t reqid, mark_t mark,
|
||||
uint32_t tfc, lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
|
||||
uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
|
||||
uint16_t ipcomp, uint16_t cpi, uint32_t replay_window,
|
||||
bool initiator, bool encap, bool esn, bool inbound, bool update,
|
||||
linked_list_t *src_ts, linked_list_t *dst_ts)
|
||||
private_kernel_android_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_add_sa_t *data)
|
||||
{
|
||||
return ipsec->sas->add_sa(ipsec->sas, src, dst, spi, protocol, reqid, mark,
|
||||
tfc, lifetime, enc_alg, enc_key, int_alg, int_key,
|
||||
mode, ipcomp, cpi, initiator, encap, esn,
|
||||
inbound, update);
|
||||
return ipsec->sas->add_sa(ipsec->sas, id->src, id->dst, id->spi, id->proto,
|
||||
data->reqid, id->mark, data->tfc, data->lifetime,
|
||||
data->enc_alg, data->enc_key, data->int_alg, data->int_key,
|
||||
data->mode, data->ipcomp, data->cpi, data->initiator,
|
||||
data->encap, data->esn, data->inbound, data->update);
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, update_sa, status_t,
|
||||
private_kernel_android_ipsec_t *this, uint32_t spi, uint8_t protocol,
|
||||
uint16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
|
||||
bool encap, bool new_encap, mark_t mark)
|
||||
private_kernel_android_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_update_sa_t *data)
|
||||
{
|
||||
return ipsec->sas->update_sa(ipsec->sas, spi, protocol, cpi, src, dst,
|
||||
new_src, new_dst, encap, new_encap, mark);
|
||||
return ipsec->sas->update_sa(ipsec->sas, id->spi, id->proto, data->cpi,
|
||||
id->src, id->dst, data->new_src, data->new_dst, data->encap,
|
||||
data->new_encap, id->mark);
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||
private_kernel_android_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, mark_t mark,
|
||||
uint64_t *bytes, uint64_t *packets, time_t *time)
|
||||
private_kernel_android_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
|
||||
time_t *time)
|
||||
{
|
||||
return ipsec->sas->query_sa(ipsec->sas, src, dst, spi, protocol, mark,
|
||||
bytes, packets, time);
|
||||
return ipsec->sas->query_sa(ipsec->sas, id->src, id->dst, id->spi,
|
||||
id->proto, id->mark, bytes, packets, time);
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, del_sa, status_t,
|
||||
private_kernel_android_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, uint16_t cpi, mark_t mark)
|
||||
private_kernel_android_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_del_sa_t *data)
|
||||
{
|
||||
return ipsec->sas->del_sa(ipsec->sas, src, dst, spi, protocol, cpi, mark);
|
||||
return ipsec->sas->del_sa(ipsec->sas, id->src, id->dst, id->spi, id->proto,
|
||||
data->cpi, id->mark);
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, flush_sas, status_t,
|
||||
@@ -106,33 +103,30 @@ METHOD(kernel_ipsec_t, flush_sas, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, add_policy, status_t,
|
||||
private_kernel_android_ipsec_t *this, host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, mark_t mark,
|
||||
policy_priority_t priority)
|
||||
private_kernel_android_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data)
|
||||
{
|
||||
return ipsec->policies->add_policy(ipsec->policies, src, dst, src_ts,
|
||||
dst_ts, direction, type, sa, mark,
|
||||
priority);
|
||||
return ipsec->policies->add_policy(ipsec->policies, data->src, data->dst,
|
||||
id->src_ts, id->dst_ts, id->dir,
|
||||
data->type, data->sa, id->mark,
|
||||
data->prio);
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||
private_kernel_android_ipsec_t *this, traffic_selector_t *src_ts,
|
||||
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
||||
time_t *use_time)
|
||||
private_kernel_android_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_query_policy_t *data, time_t *use_time)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, del_policy, status_t,
|
||||
private_kernel_android_ipsec_t *this, host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
|
||||
mark_t mark, policy_priority_t priority)
|
||||
private_kernel_android_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data)
|
||||
{
|
||||
return ipsec->policies->del_policy(ipsec->policies, src, dst, src_ts,
|
||||
dst_ts, direction, type, sa, mark,
|
||||
priority);
|
||||
return ipsec->policies->del_policy(ipsec->policies, data->src, data->dst,
|
||||
id->src_ts, id->dst_ts, id->dir,
|
||||
data->type, data->sa, id->mark,
|
||||
data->prio);
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, flush_policies, status_t,
|
||||
|
||||
@@ -78,6 +78,15 @@ static peer_cfg_t* create_peer_cfg(char *name, char *host)
|
||||
ike_cfg_t *ike_cfg;
|
||||
peer_cfg_t *peer_cfg;
|
||||
uint16_t local_port, remote_port = IKEV2_UDP_PORT;
|
||||
peer_cfg_create_t peer = {
|
||||
.cert_policy = CERT_SEND_IF_ASKED,
|
||||
.unique = UNIQUE_REPLACE,
|
||||
.keyingtries = 1,
|
||||
.rekey_time = 36000, /* 10h */
|
||||
.jitter_time = 600, /* 10min */
|
||||
.over_time = 600, /* 10min */
|
||||
.dpd = 30,
|
||||
};
|
||||
|
||||
local_port = charon->socket->get_port(charon->socket, FALSE);
|
||||
if (local_port != IKEV2_UDP_PORT)
|
||||
@@ -88,13 +97,7 @@ static peer_cfg_t* create_peer_cfg(char *name, char *host)
|
||||
host, remote_port, FRAGMENTATION_NO, 0);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
|
||||
peer_cfg = peer_cfg_create(name, ike_cfg,
|
||||
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
|
||||
36000, 0, /* rekey 10h, reauth none */
|
||||
600, 600, /* jitter, over 10min */
|
||||
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
|
||||
30, 0, /* DPD delay, timeout */
|
||||
FALSE, NULL, NULL); /* mediation */
|
||||
peer_cfg = peer_cfg_create(name, ike_cfg, &peer);
|
||||
peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
|
||||
|
||||
return peer_cfg;
|
||||
@@ -125,18 +128,18 @@ static child_cfg_t* create_child_cfg(char *name)
|
||||
{
|
||||
child_cfg_t *child_cfg;
|
||||
traffic_selector_t *ts;
|
||||
lifetime_cfg_t lifetime = {
|
||||
.time = {
|
||||
.life = 10800 /* 3h */,
|
||||
.rekey = 10200 /* 2h50min */,
|
||||
.jitter = 300 /* 5min */
|
||||
}
|
||||
child_cfg_create_t child = {
|
||||
.lifetime = {
|
||||
.time = {
|
||||
.life = 10800 /* 3h */,
|
||||
.rekey = 10200 /* 2h50min */,
|
||||
.jitter = 300 /* 5min */
|
||||
},
|
||||
},
|
||||
.mode = MODE_TUNNEL,
|
||||
};
|
||||
|
||||
child_cfg = child_cfg_create(name, &lifetime,
|
||||
NULL, FALSE, MODE_TUNNEL, /* updown, hostaccess */
|
||||
ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
|
||||
0, 0, NULL, NULL, 0);
|
||||
child_cfg = child_cfg_create(name, &child);
|
||||
child_cfg->add_proposal(child_cfg, proposal_create_from_string(PROTO_ESP,
|
||||
"aes128gcm8-aes128gcm12-aes128gcm16-"
|
||||
"aes256gcm8-aes256gcm12-aes256gcm16"));
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 Tobias Brunner
|
||||
* Copyright (C) 2016 Andreas Steffen
|
||||
* Copyright (C) 2008-2016 Tobias Brunner
|
||||
* Copyright (C) 2005-2007 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -132,6 +133,16 @@ struct private_child_cfg_t {
|
||||
*/
|
||||
uint32_t tfc;
|
||||
|
||||
/**
|
||||
* Optional manually-set IPsec policy priorities
|
||||
*/
|
||||
uint32_t manual_prio;
|
||||
|
||||
/**
|
||||
* Optional restriction of IPsec policy to a given network interface
|
||||
*/
|
||||
char *interface;
|
||||
|
||||
/**
|
||||
* set up IPsec transport SA in MIPv6 proxy mode
|
||||
*/
|
||||
@@ -500,6 +511,18 @@ METHOD(child_cfg_t, get_tfc, uint32_t,
|
||||
return this->tfc;
|
||||
}
|
||||
|
||||
METHOD(child_cfg_t, get_manual_prio, uint32_t,
|
||||
private_child_cfg_t *this)
|
||||
{
|
||||
return this->manual_prio;
|
||||
}
|
||||
|
||||
METHOD(child_cfg_t, get_interface, char*,
|
||||
private_child_cfg_t *this)
|
||||
{
|
||||
return this->interface;
|
||||
}
|
||||
|
||||
METHOD(child_cfg_t, get_replay_window, uint32_t,
|
||||
private_child_cfg_t *this)
|
||||
{
|
||||
@@ -512,13 +535,6 @@ METHOD(child_cfg_t, set_replay_window, void,
|
||||
this->replay_window = replay_window;
|
||||
}
|
||||
|
||||
METHOD(child_cfg_t, set_mipv6_options, void,
|
||||
private_child_cfg_t *this, bool proxy_mode, bool install_policy)
|
||||
{
|
||||
this->proxy_mode = proxy_mode;
|
||||
this->install_policy = install_policy;
|
||||
}
|
||||
|
||||
METHOD(child_cfg_t, use_proxy_mode, bool,
|
||||
private_child_cfg_t *this)
|
||||
{
|
||||
@@ -532,7 +548,7 @@ METHOD(child_cfg_t, install_policy, bool,
|
||||
}
|
||||
|
||||
#define LT_PART_EQUALS(a, b) ({ a.life == b.life && a.rekey == b.rekey && a.jitter == b.jitter; })
|
||||
#define LIFETIME_EQUALS(a, b) ({ LT_PART_EQUALS(a.time, b.time) && LT_PART_EQUALS(a.bytes, b.bytes) && LT_PART_EQUALS(a.packets, b.packets); })
|
||||
#define LIFETIME_EQUALS(a, b) ({ LT_PART_EQUALS(a.time, b.time) && LT_PART_EQUALS(a.bytes, b.bytes) && LT_PART_EQUALS(a.packets, b.packets); })
|
||||
|
||||
METHOD(child_cfg_t, equals, bool,
|
||||
private_child_cfg_t *this, child_cfg_t *other_pub)
|
||||
@@ -576,10 +592,12 @@ METHOD(child_cfg_t, equals, bool,
|
||||
this->mark_out.value == other->mark_out.value &&
|
||||
this->mark_out.mask == other->mark_out.mask &&
|
||||
this->tfc == other->tfc &&
|
||||
this->manual_prio == other->manual_prio &&
|
||||
this->replay_window == other->replay_window &&
|
||||
this->proxy_mode == other->proxy_mode &&
|
||||
this->install_policy == other->install_policy &&
|
||||
streq(this->updown, other->updown);
|
||||
streq(this->updown, other->updown) &&
|
||||
streq(this->interface, other->interface);
|
||||
}
|
||||
|
||||
METHOD(child_cfg_t, get_ref, child_cfg_t*,
|
||||
@@ -597,10 +615,8 @@ METHOD(child_cfg_t, destroy, void,
|
||||
this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
|
||||
this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
|
||||
this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
|
||||
if (this->updown)
|
||||
{
|
||||
free(this->updown);
|
||||
}
|
||||
free(this->updown);
|
||||
free(this->interface);
|
||||
free(this->name);
|
||||
free(this);
|
||||
}
|
||||
@@ -609,12 +625,7 @@ METHOD(child_cfg_t, destroy, void,
|
||||
/*
|
||||
* Described in header-file
|
||||
*/
|
||||
child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
|
||||
char *updown, bool hostaccess,
|
||||
ipsec_mode_t mode, action_t start_action,
|
||||
action_t dpd_action, action_t close_action,
|
||||
bool ipcomp, uint32_t inactivity, uint32_t reqid,
|
||||
mark_t *mark_in, mark_t *mark_out, uint32_t tfc)
|
||||
child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
|
||||
{
|
||||
private_child_cfg_t *this;
|
||||
|
||||
@@ -634,12 +645,13 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
|
||||
.get_close_action = _get_close_action,
|
||||
.get_lifetime = _get_lifetime,
|
||||
.get_dh_group = _get_dh_group,
|
||||
.set_mipv6_options = _set_mipv6_options,
|
||||
.use_ipcomp = _use_ipcomp,
|
||||
.get_inactivity = _get_inactivity,
|
||||
.get_reqid = _get_reqid,
|
||||
.get_mark = _get_mark,
|
||||
.get_tfc = _get_tfc,
|
||||
.get_manual_prio = _get_manual_prio,
|
||||
.get_interface = _get_interface,
|
||||
.get_replay_window = _get_replay_window,
|
||||
.set_replay_window = _set_replay_window,
|
||||
.use_proxy_mode = _use_proxy_mode,
|
||||
@@ -649,35 +661,30 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.name = strdup(name),
|
||||
.updown = strdupnull(updown),
|
||||
.hostaccess = hostaccess,
|
||||
.mode = mode,
|
||||
.start_action = start_action,
|
||||
.dpd_action = dpd_action,
|
||||
.close_action = close_action,
|
||||
.use_ipcomp = ipcomp,
|
||||
.inactivity = inactivity,
|
||||
.reqid = reqid,
|
||||
.proxy_mode = FALSE,
|
||||
.install_policy = TRUE,
|
||||
.updown = strdupnull(data->updown),
|
||||
.hostaccess = data->hostaccess,
|
||||
.reqid = data->reqid,
|
||||
.mode = data->mode,
|
||||
.proxy_mode = data->proxy_mode,
|
||||
.start_action = data->start_action,
|
||||
.dpd_action = data->dpd_action,
|
||||
.close_action = data->close_action,
|
||||
.mark_in = data->mark_in,
|
||||
.mark_out = data->mark_out,
|
||||
.lifetime = data->lifetime,
|
||||
.inactivity = data->inactivity,
|
||||
.use_ipcomp = data->ipcomp,
|
||||
.tfc = data->tfc,
|
||||
.manual_prio = data->priority,
|
||||
.interface = strdupnull(data->interface),
|
||||
.install_policy = !data->suppress_policies,
|
||||
.refcount = 1,
|
||||
.proposals = linked_list_create(),
|
||||
.my_ts = linked_list_create(),
|
||||
.other_ts = linked_list_create(),
|
||||
.tfc = tfc,
|
||||
.replay_window = lib->settings->get_int(lib->settings,
|
||||
"%s.replay_window", DEFAULT_REPLAY_WINDOW, lib->ns),
|
||||
"%s.replay_window", DEFAULT_REPLAY_WINDOW, lib->ns),
|
||||
);
|
||||
|
||||
if (mark_in)
|
||||
{
|
||||
this->mark_in = *mark_in;
|
||||
}
|
||||
if (mark_out)
|
||||
{
|
||||
this->mark_out = *mark_out;
|
||||
}
|
||||
memcpy(&this->lifetime, lifetime, sizeof(lifetime_cfg_t));
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 Tobias Brunner
|
||||
* Copyright (C) 2016 Andreas Steffen
|
||||
* Copyright (C) 2008-2016 Tobias Brunner
|
||||
* Copyright (C) 2005-2007 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -25,6 +26,7 @@
|
||||
|
||||
typedef enum action_t action_t;
|
||||
typedef struct child_cfg_t child_cfg_t;
|
||||
typedef struct child_cfg_create_t child_cfg_create_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <selectors/traffic_selector.h>
|
||||
@@ -234,6 +236,20 @@ struct child_cfg_t {
|
||||
*/
|
||||
uint32_t (*get_tfc)(child_cfg_t *this);
|
||||
|
||||
/**
|
||||
* Get optional manually-set IPsec policy priority
|
||||
*
|
||||
* @return manually-set IPsec policy priority (automatic if 0)
|
||||
*/
|
||||
uint32_t (*get_manual_prio)(child_cfg_t *this);
|
||||
|
||||
/**
|
||||
* Get optional network interface restricting IPsec policy
|
||||
*
|
||||
* @return network interface)
|
||||
*/
|
||||
char* (*get_interface)(child_cfg_t *this);
|
||||
|
||||
/**
|
||||
* Get anti-replay window size
|
||||
*
|
||||
@@ -248,15 +264,6 @@ struct child_cfg_t {
|
||||
*/
|
||||
void (*set_replay_window)(child_cfg_t *this, uint32_t window);
|
||||
|
||||
/**
|
||||
* Sets two options needed for Mobile IPv6 interoperability.
|
||||
*
|
||||
* @param proxy_mode use IPsec transport proxy mode (default FALSE)
|
||||
* @param install_policy install IPsec kernel policies (default TRUE)
|
||||
*/
|
||||
void (*set_mipv6_options)(child_cfg_t *this, bool proxy_mode,
|
||||
bool install_policy);
|
||||
|
||||
/**
|
||||
* Check whether IPsec transport SA should be set up in proxy mode.
|
||||
*
|
||||
@@ -297,38 +304,56 @@ struct child_cfg_t {
|
||||
void (*destroy) (child_cfg_t *this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Data passed to the constructor of a child_cfg_t object.
|
||||
*/
|
||||
struct child_cfg_create_t {
|
||||
/** Specific reqid to use for CHILD_SA, 0 for auto assignment */
|
||||
uint32_t reqid;
|
||||
/** Optional inbound mark */
|
||||
mark_t mark_in;
|
||||
/** Optional outbound mark */
|
||||
mark_t mark_out;
|
||||
/** Mode to propose for CHILD_SA */
|
||||
ipsec_mode_t mode;
|
||||
/** Use IPsec transport proxy mode */
|
||||
bool proxy_mode;
|
||||
/** Use IPComp, if peer supports it */
|
||||
bool ipcomp;
|
||||
/** TFC padding size, 0 to disable, -1 to pad to PMTU */
|
||||
uint32_t tfc;
|
||||
/** Optional manually-set IPsec policy priority */
|
||||
uint32_t priority;
|
||||
/** Optional network interface restricting IPsec policy (cloned) */
|
||||
char *interface;
|
||||
/** lifetime_cfg_t for this child_cfg */
|
||||
lifetime_cfg_t lifetime;
|
||||
/** Inactivity timeout in s before closing a CHILD_SA */
|
||||
uint32_t inactivity;
|
||||
/** Start action */
|
||||
action_t start_action;
|
||||
/** DPD action */
|
||||
action_t dpd_action;
|
||||
/** Close action */
|
||||
action_t close_action;
|
||||
/** updown script to execute on up/down event (cloned) */
|
||||
char *updown;
|
||||
/** TRUE to allow access to the local host */
|
||||
bool hostaccess;
|
||||
/** Don't install IPsec policies */
|
||||
bool suppress_policies;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a configuration template for CHILD_SA setup.
|
||||
*
|
||||
* The "name" string gets cloned.
|
||||
*
|
||||
* The lifetime_cfg_t object gets cloned.
|
||||
* To prevent two peers to start rekeying at the same time, a jitter may be
|
||||
* specified. Rekeying of an SA starts at (x.rekey - random(0, x.jitter)).
|
||||
*
|
||||
* After a call to create, a reference is obtained (refcount = 1).
|
||||
*
|
||||
* @param name name of the child_cfg
|
||||
* @param lifetime lifetime_cfg_t for this child_cfg
|
||||
* @param updown updown script to execute on up/down event
|
||||
* @param hostaccess TRUE to allow access to the local host
|
||||
* @param mode mode to propose for CHILD_SA, transport, tunnel or BEET
|
||||
* @param start_action start action
|
||||
* @param dpd_action DPD action
|
||||
* @param close_action close action
|
||||
* @param ipcomp use IPComp, if peer supports it
|
||||
* @param inactivity inactivity timeout in s before closing a CHILD_SA
|
||||
* @param reqid specific reqid to use for CHILD_SA, 0 for auto assign
|
||||
* @param mark_in optional inbound mark (can be NULL)
|
||||
* @param mark_out optional outbound mark (can be NULL)
|
||||
* @param tfc TFC padding size, 0 to disable, -1 to pad to PMTU
|
||||
* @param name name of the child_cfg (cloned)
|
||||
* @param data data for this child_cfg
|
||||
* @return child_cfg_t object
|
||||
*/
|
||||
child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
|
||||
char *updown, bool hostaccess,
|
||||
ipsec_mode_t mode, action_t start_action,
|
||||
action_t dpd_action, action_t close_action,
|
||||
bool ipcomp, uint32_t inactivity, uint32_t reqid,
|
||||
mark_t *mark_in, mark_t *mark_out, uint32_t tfc);
|
||||
child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data);
|
||||
|
||||
#endif /** CHILD_CFG_H_ @}*/
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2015 Tobias Brunner
|
||||
* Copyright (C) 2007-2016 Tobias Brunner
|
||||
* Copyright (C) 2005-2009 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -724,29 +724,22 @@ METHOD(peer_cfg_t, destroy, void,
|
||||
/*
|
||||
* Described in header-file
|
||||
*/
|
||||
peer_cfg_t *peer_cfg_create(char *name,
|
||||
ike_cfg_t *ike_cfg, cert_policy_t cert_policy,
|
||||
unique_policy_t unique, uint32_t keyingtries,
|
||||
uint32_t rekey_time, uint32_t reauth_time,
|
||||
uint32_t jitter_time, uint32_t over_time,
|
||||
bool mobike, bool aggressive, bool pull_mode,
|
||||
uint32_t dpd, uint32_t dpd_timeout,
|
||||
bool mediation, peer_cfg_t *mediated_by,
|
||||
identification_t *peer_id)
|
||||
peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg,
|
||||
peer_cfg_create_t *data)
|
||||
{
|
||||
private_peer_cfg_t *this;
|
||||
|
||||
if (rekey_time && jitter_time > rekey_time)
|
||||
if (data->rekey_time && data->jitter_time > data->rekey_time)
|
||||
{
|
||||
jitter_time = rekey_time;
|
||||
data->jitter_time = data->rekey_time;
|
||||
}
|
||||
if (reauth_time && jitter_time > reauth_time)
|
||||
if (data->reauth_time && data->jitter_time > data->reauth_time)
|
||||
{
|
||||
jitter_time = reauth_time;
|
||||
data->jitter_time = data->reauth_time;
|
||||
}
|
||||
if (dpd && dpd_timeout && dpd > dpd_timeout)
|
||||
if (data->dpd && data->dpd_timeout && data->dpd > data->dpd_timeout)
|
||||
{
|
||||
dpd_timeout = dpd;
|
||||
data->dpd_timeout = data->dpd;
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
@@ -789,33 +782,29 @@ peer_cfg_t *peer_cfg_create(char *name,
|
||||
.ike_cfg = ike_cfg,
|
||||
.child_cfgs = linked_list_create(),
|
||||
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
|
||||
.cert_policy = cert_policy,
|
||||
.unique = unique,
|
||||
.keyingtries = keyingtries,
|
||||
.rekey_time = rekey_time,
|
||||
.reauth_time = reauth_time,
|
||||
.jitter_time = jitter_time,
|
||||
.over_time = over_time,
|
||||
.use_mobike = mobike,
|
||||
.aggressive = aggressive,
|
||||
.pull_mode = pull_mode,
|
||||
.dpd = dpd,
|
||||
.dpd_timeout = dpd_timeout,
|
||||
.cert_policy = data->cert_policy,
|
||||
.unique = data->unique,
|
||||
.keyingtries = data->keyingtries,
|
||||
.rekey_time = data->rekey_time,
|
||||
.reauth_time = data->reauth_time,
|
||||
.jitter_time = data->jitter_time,
|
||||
.over_time = data->over_time,
|
||||
.use_mobike = !data->no_mobike,
|
||||
.aggressive = data->aggressive,
|
||||
.pull_mode = !data->push_mode,
|
||||
.dpd = data->dpd,
|
||||
.dpd_timeout = data->dpd_timeout,
|
||||
.vips = linked_list_create(),
|
||||
.pools = linked_list_create(),
|
||||
.local_auth = linked_list_create(),
|
||||
.remote_auth = linked_list_create(),
|
||||
.refcount = 1,
|
||||
);
|
||||
|
||||
#ifdef ME
|
||||
this->mediation = mediation;
|
||||
this->mediated_by = mediated_by;
|
||||
this->peer_id = peer_id;
|
||||
#else /* ME */
|
||||
DESTROY_IF(mediated_by);
|
||||
DESTROY_IF(peer_id);
|
||||
.mediation = data->mediation,
|
||||
.mediated_by = data->mediated_by,
|
||||
.peer_id = data->peer_id,
|
||||
#endif /* ME */
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2015 Tobias Brunner
|
||||
* Copyright (C) 2007-2016 Tobias Brunner
|
||||
* Copyright (C) 2005-2009 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -26,6 +26,7 @@
|
||||
typedef enum cert_policy_t cert_policy_t;
|
||||
typedef enum unique_policy_t unique_policy_t;
|
||||
typedef struct peer_cfg_t peer_cfg_t;
|
||||
typedef struct peer_cfg_create_t peer_cfg_create_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <utils/identification.h>
|
||||
@@ -366,43 +367,53 @@ struct peer_cfg_t {
|
||||
void (*destroy) (peer_cfg_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Data passed to the constructor of a peer_cfg_t object.
|
||||
*/
|
||||
struct peer_cfg_create_t {
|
||||
/** Whether to send a certificate payload */
|
||||
cert_policy_t cert_policy;
|
||||
/** Uniqueness of an IKE_SA */
|
||||
unique_policy_t unique;
|
||||
/** How many keying tries should be done before giving up */
|
||||
uint32_t keyingtries;
|
||||
/** Timeout in seconds before starting rekeying */
|
||||
uint32_t rekey_time;
|
||||
/** Timeout in seconds before starting reauthentication */
|
||||
uint32_t reauth_time;
|
||||
/** Time range in seconds to randomly subtract from rekey/reauth time */
|
||||
uint32_t jitter_time;
|
||||
/** Maximum overtime in seconds before closing a rekeying/reauth SA */
|
||||
uint32_t over_time;
|
||||
/** Disable MOBIKE (RFC4555) */
|
||||
bool no_mobike;
|
||||
/** Use/accept aggressive mode with IKEv1 */
|
||||
bool aggressive;
|
||||
/** TRUE to use modeconfig push, FALSE for pull */
|
||||
bool push_mode;
|
||||
/** DPD check interval, 0 to disable */
|
||||
uint32_t dpd;
|
||||
/** DPD timeout interval (IKEv1 only), if 0 default applies */
|
||||
uint32_t dpd_timeout;
|
||||
#ifdef ME
|
||||
/** TRUE if this is a mediation connection */
|
||||
bool mediation;
|
||||
/** peer_cfg_t of the mediation connection to mediate through (adopted) */
|
||||
peer_cfg_t *mediated_by;
|
||||
/** ID that identifies our peer at the mediation server (adopted) */
|
||||
identification_t *peer_id;
|
||||
#endif /* ME */
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a configuration object for IKE_AUTH and later.
|
||||
*
|
||||
* name-string gets cloned, ID's not.
|
||||
* Virtual IPs are used if they are != NULL. A %any host means the virtual
|
||||
* IP should be obtained from the other peer.
|
||||
* Lifetimes are in seconds. To prevent to peers to start rekeying at the
|
||||
* same time, a jitter may be specified. Rekeying of an SA starts at
|
||||
* (rekeylifetime - random(0, jitter)).
|
||||
*
|
||||
* @param name name of the peer_cfg
|
||||
* @param ike_cfg IKE config to use when acting as initiator
|
||||
* @param cert_policy should we send a certificate payload?
|
||||
* @param unique uniqueness of an IKE_SA
|
||||
* @param keyingtries how many keying tries should be done before giving up
|
||||
* @param rekey_time timeout before starting rekeying
|
||||
* @param reauth_time timeout before starting reauthentication
|
||||
* @param jitter_time timerange to randomly subtract from rekey/reauth time
|
||||
* @param over_time maximum overtime before closing a rekeying/reauth SA
|
||||
* @param mobike use MOBIKE (RFC4555) if peer supports it
|
||||
* @param aggressive use/accept aggressive mode with IKEv1
|
||||
* @param pull_mode TRUE to use modeconfig pull, FALSE for push
|
||||
* @param dpd DPD check interval, 0 to disable
|
||||
* @param dpd_timeout DPD timeout interval (IKEv1 only), if 0 default applies
|
||||
* @param mediation TRUE if this is a mediation connection
|
||||
* @param mediated_by peer_cfg_t of the mediation connection to mediate through
|
||||
* @param peer_id ID that identifies our peer at the mediation server
|
||||
* @param name name of the peer_cfg (cloned)
|
||||
* @param ike_cfg IKE config to use when acting as initiator (adopted)
|
||||
* @param data data for this peer_cfg
|
||||
* @return peer_cfg_t object
|
||||
*/
|
||||
peer_cfg_t *peer_cfg_create(char *name,
|
||||
ike_cfg_t *ike_cfg, cert_policy_t cert_policy,
|
||||
unique_policy_t unique, uint32_t keyingtries,
|
||||
uint32_t rekey_time, uint32_t reauth_time,
|
||||
uint32_t jitter_time, uint32_t over_time,
|
||||
bool mobike, bool aggressive, bool pull_mode,
|
||||
uint32_t dpd, uint32_t dpd_timeout,
|
||||
bool mediation, peer_cfg_t *mediated_by,
|
||||
identification_t *peer_id);
|
||||
peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg,
|
||||
peer_cfg_create_t *data);
|
||||
|
||||
#endif /** PEER_CFG_H_ @}*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 Tobias Brunner
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
* Copyright (C) 2008-2016 Tobias Brunner
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* Copyright (C) 2010 Martin Willi
|
||||
* Copyright (C) 2010 revosec AG
|
||||
*
|
||||
@@ -415,59 +416,48 @@ METHOD(kernel_interface_t, release_reqid, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_interface_t, add_sa, status_t,
|
||||
private_kernel_interface_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, uint32_t reqid, mark_t mark,
|
||||
uint32_t tfc, lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
|
||||
uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
|
||||
uint16_t ipcomp, uint16_t cpi, uint32_t replay_window,
|
||||
bool initiator, bool encap, bool esn, bool inbound, bool update,
|
||||
linked_list_t *src_ts, linked_list_t *dst_ts)
|
||||
private_kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_add_sa_t *data)
|
||||
{
|
||||
if (!this->ipsec)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid,
|
||||
mark, tfc, lifetime, enc_alg, enc_key, int_alg, int_key, mode,
|
||||
ipcomp, cpi, replay_window, initiator, encap, esn, inbound,
|
||||
update, src_ts, dst_ts);
|
||||
return this->ipsec->add_sa(this->ipsec, id, data);
|
||||
}
|
||||
|
||||
METHOD(kernel_interface_t, update_sa, status_t,
|
||||
private_kernel_interface_t *this, uint32_t spi, uint8_t protocol,
|
||||
uint16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
|
||||
bool encap, bool new_encap, mark_t mark)
|
||||
private_kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_update_sa_t *data)
|
||||
{
|
||||
if (!this->ipsec)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
return this->ipsec->update_sa(this->ipsec, spi, protocol, cpi, src, dst,
|
||||
new_src, new_dst, encap, new_encap, mark);
|
||||
return this->ipsec->update_sa(this->ipsec, id, data);
|
||||
}
|
||||
|
||||
METHOD(kernel_interface_t, query_sa, status_t,
|
||||
private_kernel_interface_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, mark_t mark,
|
||||
uint64_t *bytes, uint64_t *packets, time_t *time)
|
||||
private_kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
|
||||
time_t *time)
|
||||
{
|
||||
if (!this->ipsec)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, mark,
|
||||
bytes, packets, time);
|
||||
return this->ipsec->query_sa(this->ipsec, id, data, bytes, packets, time);
|
||||
}
|
||||
|
||||
METHOD(kernel_interface_t, del_sa, status_t,
|
||||
private_kernel_interface_t *this, host_t *src, host_t *dst, uint32_t spi,
|
||||
uint8_t protocol, uint16_t cpi, mark_t mark)
|
||||
private_kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_del_sa_t *data)
|
||||
{
|
||||
if (!this->ipsec)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
return this->ipsec->del_sa(this->ipsec, src, dst, spi, protocol, cpi, mark);
|
||||
return this->ipsec->del_sa(this->ipsec, id, data);
|
||||
}
|
||||
|
||||
METHOD(kernel_interface_t, flush_sas, status_t,
|
||||
@@ -481,44 +471,36 @@ METHOD(kernel_interface_t, flush_sas, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_interface_t, add_policy, status_t,
|
||||
private_kernel_interface_t *this, host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
|
||||
mark_t mark, policy_priority_t priority)
|
||||
private_kernel_interface_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data)
|
||||
{
|
||||
if (!this->ipsec)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
return this->ipsec->add_policy(this->ipsec, src, dst, src_ts, dst_ts,
|
||||
direction, type, sa, mark, priority);
|
||||
return this->ipsec->add_policy(this->ipsec, id, data);
|
||||
}
|
||||
|
||||
METHOD(kernel_interface_t, query_policy, status_t,
|
||||
private_kernel_interface_t *this, traffic_selector_t *src_ts,
|
||||
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
||||
time_t *use_time)
|
||||
private_kernel_interface_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_query_policy_t *data, time_t *use_time)
|
||||
{
|
||||
if (!this->ipsec)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
return this->ipsec->query_policy(this->ipsec, src_ts, dst_ts,
|
||||
direction, mark, use_time);
|
||||
return this->ipsec->query_policy(this->ipsec, id, data, use_time);
|
||||
}
|
||||
|
||||
METHOD(kernel_interface_t, del_policy, status_t,
|
||||
private_kernel_interface_t *this, host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
|
||||
mark_t mark, policy_priority_t priority)
|
||||
private_kernel_interface_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data)
|
||||
{
|
||||
if (!this->ipsec)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
return this->ipsec->del_policy(this->ipsec, src, dst, src_ts, dst_ts,
|
||||
direction, type, sa, mark, priority);
|
||||
return this->ipsec->del_policy(this->ipsec, id, data);
|
||||
}
|
||||
|
||||
METHOD(kernel_interface_t, flush_policies, status_t,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2015 Tobias Brunner
|
||||
* Copyright (C) 2006-2016 Tobias Brunner
|
||||
* Copyright (C) 2006 Daniel Roethlisberger
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -160,41 +160,12 @@ struct kernel_interface_t {
|
||||
* This function does install a single SA for a single protocol in one
|
||||
* direction.
|
||||
*
|
||||
* @param src source address for this SA
|
||||
* @param dst destination address for this SA
|
||||
* @param spi SPI allocated by us or remote peer
|
||||
* @param protocol protocol for this SA (ESP/AH)
|
||||
* @param reqid reqid for this SA
|
||||
* @param mark optional mark for this SA
|
||||
* @param tfc Traffic Flow Confidentiality padding for this SA
|
||||
* @param lifetime lifetime_cfg_t for this SA
|
||||
* @param enc_alg Algorithm to use for encryption (ESP only)
|
||||
* @param enc_key key to use for encryption
|
||||
* @param int_alg Algorithm to use for integrity protection
|
||||
* @param int_key key to use for integrity protection
|
||||
* @param mode mode of the SA (tunnel, transport)
|
||||
* @param ipcomp IPComp transform to use
|
||||
* @param cpi CPI for IPComp
|
||||
* @param replay_window anti-replay window size
|
||||
* @param initiator TRUE if initiator of the exchange creating this SA
|
||||
* @param encap enable UDP encapsulation for NAT traversal
|
||||
* @param esn TRUE to use Extended Sequence Numbers
|
||||
* @param inbound TRUE if this is an inbound SA
|
||||
* @param update TRUE if an SPI has already been allocated for SA
|
||||
* @param src_ts list of source traffic selectors
|
||||
* @param dst_ts list of destination traffic selectors
|
||||
* @param id data identifying this SA
|
||||
* @param data data for this SA
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*add_sa) (kernel_interface_t *this,
|
||||
host_t *src, host_t *dst, uint32_t spi,
|
||||
uint8_t protocol, uint32_t reqid, mark_t mark,
|
||||
uint32_t tfc, lifetime_cfg_t *lifetime,
|
||||
uint16_t enc_alg, chunk_t enc_key,
|
||||
uint16_t int_alg, chunk_t int_key,
|
||||
ipsec_mode_t mode, uint16_t ipcomp, uint16_t cpi,
|
||||
uint32_t replay_window, bool initiator, bool encap,
|
||||
bool esn, bool inbound, bool update,
|
||||
linked_list_t *src_ts, linked_list_t *dst_ts);
|
||||
status_t (*add_sa)(kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_add_sa_t *data);
|
||||
|
||||
/**
|
||||
* Update the hosts on an installed SA.
|
||||
@@ -204,85 +175,55 @@ struct kernel_interface_t {
|
||||
* to identify SAs. Therefore if the destination address changed we
|
||||
* create a new SA and delete the old one.
|
||||
*
|
||||
* @param spi SPI of the SA
|
||||
* @param protocol protocol for this SA (ESP/AH)
|
||||
* @param cpi CPI for IPComp, 0 if no IPComp is used
|
||||
* @param src current source address
|
||||
* @param dst current destination address
|
||||
* @param new_src new source address
|
||||
* @param new_dst new destination address
|
||||
* @param encap current use of UDP encapsulation
|
||||
* @param new_encap new use of UDP encapsulation
|
||||
* @param mark optional mark for this SA
|
||||
* @param id data identifying this SA
|
||||
* @param data updated data for this SA
|
||||
* @return SUCCESS if operation completed, NOT_SUPPORTED if
|
||||
* the kernel interface can't update the SA
|
||||
* the kernel interface can't update the SA
|
||||
*/
|
||||
status_t (*update_sa)(kernel_interface_t *this,
|
||||
uint32_t spi, uint8_t protocol, uint16_t cpi,
|
||||
host_t *src, host_t *dst,
|
||||
host_t *new_src, host_t *new_dst,
|
||||
bool encap, bool new_encap, mark_t mark);
|
||||
status_t (*update_sa)(kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_update_sa_t *data);
|
||||
|
||||
/**
|
||||
* Query the number of bytes processed by an SA from the SAD.
|
||||
*
|
||||
* @param src source address for this SA
|
||||
* @param dst destination address for this SA
|
||||
* @param spi SPI allocated by us or remote peer
|
||||
* @param protocol protocol for this SA (ESP/AH)
|
||||
* @param mark optional mark for this SA
|
||||
* @param id data identifying this SA
|
||||
* @param data data to query the SA
|
||||
* @param[out] bytes the number of bytes processed by SA
|
||||
* @param[out] packets number of packets processed by SA
|
||||
* @param[out] time last (monotonic) time of SA use
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*query_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, mark_t mark,
|
||||
uint64_t *bytes, uint64_t *packets, time_t *time);
|
||||
status_t (*query_sa)(kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_query_sa_t *data, uint64_t *bytes,
|
||||
uint64_t *packets, time_t *time);
|
||||
|
||||
/**
|
||||
* Delete a previously installed SA from the SAD.
|
||||
*
|
||||
* @param src source address for this SA
|
||||
* @param dst destination address for this SA
|
||||
* @param spi SPI allocated by us or remote peer
|
||||
* @param protocol protocol for this SA (ESP/AH)
|
||||
* @param cpi CPI for IPComp or 0
|
||||
* @param mark optional mark for this SA
|
||||
* @param id data identifying this SA
|
||||
* @param data data to delete the SA
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*del_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, uint16_t cpi,
|
||||
mark_t mark);
|
||||
status_t (*del_sa)(kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_del_sa_t *data);
|
||||
|
||||
/**
|
||||
* Flush all SAs from the SAD.
|
||||
*
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*flush_sas) (kernel_interface_t *this);
|
||||
status_t (*flush_sas)(kernel_interface_t *this);
|
||||
|
||||
/**
|
||||
* Add a policy to the SPD.
|
||||
*
|
||||
* @param src source address of SA
|
||||
* @param dst dest address of SA
|
||||
* @param src_ts traffic selector to match traffic source
|
||||
* @param dst_ts traffic selector to match traffic dest
|
||||
* @param direction direction of traffic, POLICY_(IN|OUT|FWD)
|
||||
* @param type type of policy, POLICY_(IPSEC|PASS|DROP)
|
||||
* @param sa details about the SA(s) tied to this policy
|
||||
* @param mark mark for this policy
|
||||
* @param priority priority of this policy
|
||||
* @param id data identifying this policy
|
||||
* @param data data for this policy
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*add_policy) (kernel_interface_t *this,
|
||||
host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts,
|
||||
traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type,
|
||||
ipsec_sa_cfg_t *sa, mark_t mark,
|
||||
policy_priority_t priority);
|
||||
status_t (*add_policy)(kernel_interface_t *this,
|
||||
kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data);
|
||||
|
||||
/**
|
||||
* Query the use time of a policy.
|
||||
@@ -290,47 +231,33 @@ struct kernel_interface_t {
|
||||
* The use time of a policy is the time the policy was used
|
||||
* for the last time.
|
||||
*
|
||||
* @param src_ts traffic selector to match traffic source
|
||||
* @param dst_ts traffic selector to match traffic dest
|
||||
* @param direction direction of traffic, POLICY_(IN|OUT|FWD)
|
||||
* @param mark optional mark
|
||||
* @param[out] use_time the (monotonic) time of this SA's last use
|
||||
* @param id data identifying this policy
|
||||
* @param data data to query the policy
|
||||
* @param[out] use_time the monotonic timestamp of this SA's last use
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*query_policy) (kernel_interface_t *this,
|
||||
traffic_selector_t *src_ts,
|
||||
traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, mark_t mark,
|
||||
time_t *use_time);
|
||||
status_t (*query_policy)(kernel_interface_t *this,
|
||||
kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_query_policy_t *data,
|
||||
time_t *use_time);
|
||||
|
||||
/**
|
||||
* Remove a policy from the SPD.
|
||||
*
|
||||
* @param src source address of SA
|
||||
* @param dst dest address of SA
|
||||
* @param src_ts traffic selector to match traffic source
|
||||
* @param dst_ts traffic selector to match traffic dest
|
||||
* @param direction direction of traffic, POLICY_(IN|OUT|FWD)
|
||||
* @param type type of policy, POLICY_(IPSEC|PASS|DROP)
|
||||
* @param sa details about the SA(s) tied to this policy
|
||||
* @param mark mark for this policy
|
||||
* @param priority priority of the policy
|
||||
* @param id data identifying this policy
|
||||
* @param data data for this policy
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*del_policy) (kernel_interface_t *this,
|
||||
host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts,
|
||||
traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type,
|
||||
ipsec_sa_cfg_t *sa, mark_t mark,
|
||||
policy_priority_t priority);
|
||||
status_t (*del_policy)(kernel_interface_t *this,
|
||||
kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data);
|
||||
|
||||
/**
|
||||
* Flush all policies from the SPD.
|
||||
*
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*flush_policies) (kernel_interface_t *this);
|
||||
status_t (*flush_policies)(kernel_interface_t *this);
|
||||
|
||||
/**
|
||||
* Get our outgoing source address for a destination.
|
||||
|
||||
+180
-113
@@ -1,9 +1,10 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2015 Tobias Brunner
|
||||
* Copyright (C) 2016 Andreas Steffen
|
||||
* Copyright (C) 2006-2016 Tobias Brunner
|
||||
* Copyright (C) 2006 Daniel Roethlisberger
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -25,6 +26,14 @@
|
||||
#define KERNEL_IPSEC_H_
|
||||
|
||||
typedef struct kernel_ipsec_t kernel_ipsec_t;
|
||||
typedef struct kernel_ipsec_sa_id_t kernel_ipsec_sa_id_t;
|
||||
typedef struct kernel_ipsec_add_sa_t kernel_ipsec_add_sa_t;
|
||||
typedef struct kernel_ipsec_update_sa_t kernel_ipsec_update_sa_t;
|
||||
typedef struct kernel_ipsec_query_sa_t kernel_ipsec_query_sa_t;
|
||||
typedef struct kernel_ipsec_del_sa_t kernel_ipsec_del_sa_t;
|
||||
typedef struct kernel_ipsec_policy_id_t kernel_ipsec_policy_id_t;
|
||||
typedef struct kernel_ipsec_manage_policy_t kernel_ipsec_manage_policy_t;
|
||||
typedef struct kernel_ipsec_query_policy_t kernel_ipsec_query_policy_t;
|
||||
|
||||
#include <networking/host.h>
|
||||
#include <ipsec/ipsec_types.h>
|
||||
@@ -32,6 +41,137 @@ typedef struct kernel_ipsec_t kernel_ipsec_t;
|
||||
#include <plugins/plugin.h>
|
||||
#include <kernel/kernel_interface.h>
|
||||
|
||||
/**
|
||||
* Data required to identify an SA in the kernel
|
||||
*/
|
||||
struct kernel_ipsec_sa_id_t {
|
||||
/** Source address */
|
||||
host_t *src;
|
||||
/** Destination address */
|
||||
host_t *dst;
|
||||
/** SPI */
|
||||
uint32_t spi;
|
||||
/** Protocol (ESP/AH) */
|
||||
uint8_t proto;
|
||||
/** Optional mark */
|
||||
mark_t mark;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data required to add an SA to the kernel
|
||||
*/
|
||||
struct kernel_ipsec_add_sa_t {
|
||||
/** Reqid */
|
||||
uint32_t reqid;
|
||||
/** Mode (tunnel, transport...) */
|
||||
ipsec_mode_t mode;
|
||||
/** List of source traffic selectors */
|
||||
linked_list_t *src_ts;
|
||||
/** List of destination traffic selectors */
|
||||
linked_list_t *dst_ts;
|
||||
/** Network interface restricting policy */
|
||||
char *interface;
|
||||
/** Lifetime configuration */
|
||||
lifetime_cfg_t *lifetime;
|
||||
/** Encryption algorithm */
|
||||
uint16_t enc_alg;
|
||||
/** Encryption key */
|
||||
chunk_t enc_key;
|
||||
/** Integrity protection algorithm */
|
||||
uint16_t int_alg;
|
||||
/** Integrity protection key */
|
||||
chunk_t int_key;
|
||||
/** Anti-replay window size */
|
||||
uint32_t replay_window;
|
||||
/** Traffic Flow Confidentiality padding */
|
||||
uint32_t tfc;
|
||||
/** IPComp transform */
|
||||
uint16_t ipcomp;
|
||||
/** CPI for IPComp */
|
||||
uint16_t cpi;
|
||||
/** TRUE to enable UDP encapsulation for NAT traversal */
|
||||
bool encap;
|
||||
/** TRUE to use Extended Sequence Numbers */
|
||||
bool esn;
|
||||
/** TRUE if initiator of the exchange creating the SA */
|
||||
bool initiator;
|
||||
/** TRUE if this is an inbound SA */
|
||||
bool inbound;
|
||||
/** TRUE if an SPI has already been allocated for this SA */
|
||||
bool update;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data required to update the hosts of an SA in the kernel
|
||||
*/
|
||||
struct kernel_ipsec_update_sa_t {
|
||||
/** CPI in case IPComp is used */
|
||||
uint16_t cpi;
|
||||
/** New source address */
|
||||
host_t *new_src;
|
||||
/** New destination address */
|
||||
host_t *new_dst;
|
||||
/** TRUE if UDP encapsulation is currently enabled */
|
||||
bool encap;
|
||||
/** TRUE to enable UDP encapsulation */
|
||||
bool new_encap;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data required to query an SA in the kernel
|
||||
*/
|
||||
struct kernel_ipsec_query_sa_t {
|
||||
uint16_t cpi;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data required to delete an SA in the kernel
|
||||
*/
|
||||
struct kernel_ipsec_del_sa_t {
|
||||
/** CPI in case IPComp is used */
|
||||
uint16_t cpi;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data identifying a policy in the kernel
|
||||
*/
|
||||
struct kernel_ipsec_policy_id_t {
|
||||
/** Direction of traffic */
|
||||
policy_dir_t dir;
|
||||
/** Source traffic selector */
|
||||
traffic_selector_t *src_ts;
|
||||
/** Destination traffic selector */
|
||||
traffic_selector_t *dst_ts;
|
||||
/** Optional mark */
|
||||
mark_t mark;
|
||||
/** Network interface restricting policy */
|
||||
char *interface;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data required to add/delete a policy to/from the kernel
|
||||
*/
|
||||
struct kernel_ipsec_manage_policy_t {
|
||||
/** Type of policy */
|
||||
policy_type_t type;
|
||||
/** Priority class */
|
||||
policy_priority_t prio;
|
||||
/** Manually-set priority (automatic if set to 0) */
|
||||
uint32_t manual_prio;
|
||||
/** Source address of the SA(s) tied to this policy */
|
||||
host_t *src;
|
||||
/** Destination address of the SA(s) tied to this policy */
|
||||
host_t *dst;
|
||||
/** Details about the SA(s) tied to this policy */
|
||||
ipsec_sa_cfg_t *sa;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data required to query a policy in the kernel
|
||||
*/
|
||||
struct kernel_ipsec_query_policy_t {
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface to the ipsec subsystem of the kernel.
|
||||
*
|
||||
@@ -81,41 +221,12 @@ struct kernel_ipsec_t {
|
||||
* This function does install a single SA for a single protocol in one
|
||||
* direction.
|
||||
*
|
||||
* @param src source address for this SA
|
||||
* @param dst destination address for this SA
|
||||
* @param spi SPI allocated by us or remote peer
|
||||
* @param protocol protocol for this SA (ESP/AH)
|
||||
* @param reqid unique ID for this SA
|
||||
* @param mark mark for this SA
|
||||
* @param tfc Traffic Flow Confidentiality padding for this SA
|
||||
* @param lifetime lifetime_cfg_t for this SA
|
||||
* @param enc_alg Algorithm to use for encryption (ESP only)
|
||||
* @param enc_key key to use for encryption
|
||||
* @param int_alg Algorithm to use for integrity protection
|
||||
* @param int_key key to use for integrity protection
|
||||
* @param mode mode of the SA (tunnel, transport)
|
||||
* @param ipcomp IPComp transform to use
|
||||
* @param cpi CPI for IPComp
|
||||
* @param replay_window anti-replay window size
|
||||
* @param initiator TRUE if initiator of the exchange creating this SA
|
||||
* @param encap enable UDP encapsulation for NAT traversal
|
||||
* @param esn TRUE to use Extended Sequence Numbers
|
||||
* @param inbound TRUE if this is an inbound SA
|
||||
* @param update TRUE if an SPI has already been allocated for SA
|
||||
* @param src_ts list of source traffic selectors
|
||||
* @param dst_ts list of destination traffic selectors
|
||||
* @param id data identifying this SA
|
||||
* @param data data for this SA
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*add_sa) (kernel_ipsec_t *this,
|
||||
host_t *src, host_t *dst, uint32_t spi,
|
||||
uint8_t protocol, uint32_t reqid,
|
||||
mark_t mark, uint32_t tfc, lifetime_cfg_t *lifetime,
|
||||
uint16_t enc_alg, chunk_t enc_key,
|
||||
uint16_t int_alg, chunk_t int_key,
|
||||
ipsec_mode_t mode, uint16_t ipcomp, uint16_t cpi,
|
||||
uint32_t replay_window, bool initiator, bool encap,
|
||||
bool esn, bool inbound, bool update,
|
||||
linked_list_t *src_ts, linked_list_t *dst_ts);
|
||||
status_t (*add_sa)(kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_add_sa_t *data);
|
||||
|
||||
/**
|
||||
* Update the hosts on an installed SA.
|
||||
@@ -125,85 +236,55 @@ struct kernel_ipsec_t {
|
||||
* to identify SAs. Therefore if the destination address changed we
|
||||
* create a new SA and delete the old one.
|
||||
*
|
||||
* @param spi SPI of the SA
|
||||
* @param protocol protocol for this SA (ESP/AH)
|
||||
* @param cpi CPI for IPComp, 0 if no IPComp is used
|
||||
* @param src current source address
|
||||
* @param dst current destination address
|
||||
* @param new_src new source address
|
||||
* @param new_dst new destination address
|
||||
* @param encap current use of UDP encapsulation
|
||||
* @param new_encap new use of UDP encapsulation
|
||||
* @param mark optional mark for this SA
|
||||
* @param id data identifying this SA
|
||||
* @param data updated data for this SA
|
||||
* @return SUCCESS if operation completed, NOT_SUPPORTED if
|
||||
* the kernel interface can't update the SA
|
||||
* the kernel interface can't update the SA
|
||||
*/
|
||||
status_t (*update_sa)(kernel_ipsec_t *this,
|
||||
uint32_t spi, uint8_t protocol, uint16_t cpi,
|
||||
host_t *src, host_t *dst,
|
||||
host_t *new_src, host_t *new_dst,
|
||||
bool encap, bool new_encap, mark_t mark);
|
||||
status_t (*update_sa)(kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_update_sa_t *data);
|
||||
|
||||
/**
|
||||
* Query the number of bytes processed by an SA from the SAD.
|
||||
*
|
||||
* @param src source address for this SA
|
||||
* @param dst destination address for this SA
|
||||
* @param spi SPI allocated by us or remote peer
|
||||
* @param protocol protocol for this SA (ESP/AH)
|
||||
* @param mark optional mark for this SA
|
||||
* @param id data identifying this SA
|
||||
* @param data data to query the SA
|
||||
* @param[out] bytes the number of bytes processed by SA
|
||||
* @param[out] packets number of packets processed by SA
|
||||
* @param[out] time last (monotonic) time of SA use
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*query_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, mark_t mark,
|
||||
uint64_t *bytes, uint64_t *packets, time_t *time);
|
||||
status_t (*query_sa)(kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_query_sa_t *data, uint64_t *bytes,
|
||||
uint64_t *packets, time_t *time);
|
||||
|
||||
/**
|
||||
* Delete a previusly installed SA from the SAD.
|
||||
* Delete a previously installed SA from the SAD.
|
||||
*
|
||||
* @param src source address for this SA
|
||||
* @param dst destination address for this SA
|
||||
* @param spi SPI allocated by us or remote peer
|
||||
* @param protocol protocol for this SA (ESP/AH)
|
||||
* @param cpi CPI for IPComp or 0
|
||||
* @param mark optional mark for this SA
|
||||
* @param id data identifying this SA
|
||||
* @param data data to delete the SA
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*del_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, uint16_t cpi,
|
||||
mark_t mark);
|
||||
status_t (*del_sa)(kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_del_sa_t *data);
|
||||
|
||||
/**
|
||||
* Flush all SAs from the SAD.
|
||||
*
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*flush_sas) (kernel_ipsec_t *this);
|
||||
status_t (*flush_sas)(kernel_ipsec_t *this);
|
||||
|
||||
/**
|
||||
* Add a policy to the SPD.
|
||||
*
|
||||
* @param src source address of SA
|
||||
* @param dst dest address of SA
|
||||
* @param src_ts traffic selector to match traffic source
|
||||
* @param dst_ts traffic selector to match traffic dest
|
||||
* @param direction direction of traffic, POLICY_(IN|OUT|FWD)
|
||||
* @param type type of policy, POLICY_(IPSEC|PASS|DROP)
|
||||
* @param sa details about the SA(s) tied to this policy
|
||||
* @param mark mark for this policy
|
||||
* @param priority priority of this policy
|
||||
* @param id data identifying this policy
|
||||
* @param data data for this policy
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*add_policy) (kernel_ipsec_t *this,
|
||||
host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts,
|
||||
traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type,
|
||||
ipsec_sa_cfg_t *sa, mark_t mark,
|
||||
policy_priority_t priority);
|
||||
status_t (*add_policy)(kernel_ipsec_t *this,
|
||||
kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data);
|
||||
|
||||
/**
|
||||
* Query the use time of a policy.
|
||||
@@ -212,47 +293,33 @@ struct kernel_ipsec_t {
|
||||
* time. It is not the system time, but a monotonic timestamp as returned
|
||||
* by time_monotonic.
|
||||
*
|
||||
* @param src_ts traffic selector to match traffic source
|
||||
* @param dst_ts traffic selector to match traffic dest
|
||||
* @param direction direction of traffic, POLICY_(IN|OUT|FWD)
|
||||
* @param mark optional mark
|
||||
* @param id data identifying this policy
|
||||
* @param data data to query the policy
|
||||
* @param[out] use_time the monotonic timestamp of this SA's last use
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*query_policy) (kernel_ipsec_t *this,
|
||||
traffic_selector_t *src_ts,
|
||||
traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, mark_t mark,
|
||||
time_t *use_time);
|
||||
status_t (*query_policy)(kernel_ipsec_t *this,
|
||||
kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_query_policy_t *data,
|
||||
time_t *use_time);
|
||||
|
||||
/**
|
||||
* Remove a policy from the SPD.
|
||||
*
|
||||
* @param src source address of SA
|
||||
* @param dst dest address of SA
|
||||
* @param src_ts traffic selector to match traffic source
|
||||
* @param dst_ts traffic selector to match traffic dest
|
||||
* @param direction direction of traffic, POLICY_(IN|OUT|FWD)
|
||||
* @param type type of policy, POLICY_(IPSEC|PASS|DROP)
|
||||
* @param sa details about the SA(s) tied to this policy
|
||||
* @param mark mark for this policy
|
||||
* @param priority priority of the policy
|
||||
* @param id data identifying this policy
|
||||
* @param data data for this policy
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*del_policy) (kernel_ipsec_t *this,
|
||||
host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts,
|
||||
traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type,
|
||||
ipsec_sa_cfg_t *sa, mark_t mark,
|
||||
policy_priority_t priority);
|
||||
status_t (*del_policy)(kernel_ipsec_t *this,
|
||||
kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data);
|
||||
|
||||
/**
|
||||
* Flush all policies from the SPD.
|
||||
*
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*flush_policies) (kernel_ipsec_t *this);
|
||||
status_t (*flush_policies)(kernel_ipsec_t *this);
|
||||
|
||||
/**
|
||||
* Install a bypass policy for the given socket.
|
||||
@@ -277,7 +344,7 @@ struct kernel_ipsec_t {
|
||||
/**
|
||||
* Destroy the implementation.
|
||||
*/
|
||||
void (*destroy) (kernel_ipsec_t *this);
|
||||
void (*destroy)(kernel_ipsec_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -183,10 +183,22 @@ static void setup_tunnel(private_ha_tunnel_t *this,
|
||||
auth_cfg_t *auth_cfg;
|
||||
child_cfg_t *child_cfg;
|
||||
traffic_selector_t *ts;
|
||||
lifetime_cfg_t lifetime = {
|
||||
.time = {
|
||||
.life = 21600, .rekey = 20400, .jitter = 400,
|
||||
peer_cfg_create_t peer = {
|
||||
.cert_policy = CERT_NEVER_SEND,
|
||||
.unique = UNIQUE_KEEP,
|
||||
.rekey_time = 86400, /* 24h */
|
||||
.jitter_time = 7200, /* 2h */
|
||||
.over_time = 3600, /* 1h */
|
||||
.no_mobike = TRUE,
|
||||
.dpd = 30,
|
||||
};
|
||||
child_cfg_create_t child = {
|
||||
.lifetime = {
|
||||
.time = {
|
||||
.life = 21600, .rekey = 20400, .jitter = 400,
|
||||
},
|
||||
},
|
||||
.mode = MODE_TRANSPORT,
|
||||
};
|
||||
|
||||
/* setup credentials */
|
||||
@@ -208,9 +220,7 @@ static void setup_tunnel(private_ha_tunnel_t *this,
|
||||
remote, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
|
||||
peer_cfg = peer_cfg_create("ha", ike_cfg, CERT_NEVER_SEND,
|
||||
UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE,
|
||||
TRUE, 30, 0, FALSE, NULL, NULL);
|
||||
peer_cfg = peer_cfg_create("ha", ike_cfg, &peer);
|
||||
|
||||
auth_cfg = auth_cfg_create();
|
||||
auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
|
||||
@@ -224,9 +234,7 @@ static void setup_tunnel(private_ha_tunnel_t *this,
|
||||
identification_create_from_string(remote));
|
||||
peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
|
||||
|
||||
child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE, MODE_TRANSPORT,
|
||||
ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
|
||||
0, 0, NULL, NULL, 0);
|
||||
child_cfg = child_cfg_create("ha", &child);
|
||||
ts = traffic_selector_create_dynamic(IPPROTO_UDP, HA_PORT, HA_PORT);
|
||||
child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
|
||||
ts = traffic_selector_create_dynamic(IPPROTO_ICMP, 0, 65535);
|
||||
|
||||
@@ -248,42 +248,38 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
private_kernel_libipsec_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, uint32_t reqid, mark_t mark,
|
||||
uint32_t tfc, lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
|
||||
uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
|
||||
uint16_t ipcomp, uint16_t cpi, uint32_t replay_window,
|
||||
bool initiator, bool encap, bool esn, bool inbound, bool update,
|
||||
linked_list_t *src_ts, linked_list_t *dst_ts)
|
||||
private_kernel_libipsec_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_add_sa_t *data)
|
||||
{
|
||||
return ipsec->sas->add_sa(ipsec->sas, src, dst, spi, protocol, reqid, mark,
|
||||
tfc, lifetime, enc_alg, enc_key, int_alg, int_key,
|
||||
mode, ipcomp, cpi, initiator, encap, esn,
|
||||
inbound, update);
|
||||
return ipsec->sas->add_sa(ipsec->sas, id->src, id->dst, id->spi, id->proto,
|
||||
data->reqid, id->mark, data->tfc, data->lifetime,
|
||||
data->enc_alg, data->enc_key, data->int_alg, data->int_key,
|
||||
data->mode, data->ipcomp, data->cpi, data->initiator,
|
||||
data->encap, data->esn, data->inbound, data->update);
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, update_sa, status_t,
|
||||
private_kernel_libipsec_ipsec_t *this, uint32_t spi, uint8_t protocol,
|
||||
uint16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
|
||||
bool encap, bool new_encap, mark_t mark)
|
||||
private_kernel_libipsec_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_update_sa_t *data)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||
private_kernel_libipsec_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, mark_t mark, uint64_t *bytes,
|
||||
uint64_t *packets, time_t *time)
|
||||
private_kernel_libipsec_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
|
||||
time_t *time)
|
||||
{
|
||||
return ipsec->sas->query_sa(ipsec->sas, src, dst, spi, protocol, mark,
|
||||
bytes, packets, time);
|
||||
return ipsec->sas->query_sa(ipsec->sas, id->src, id->dst, id->spi,
|
||||
id->proto, id->mark, bytes, packets, time);
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, del_sa, status_t,
|
||||
private_kernel_libipsec_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, uint16_t cpi, mark_t mark)
|
||||
private_kernel_libipsec_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_del_sa_t *data)
|
||||
{
|
||||
return ipsec->sas->del_sa(ipsec->sas, src, dst, spi, protocol, cpi, mark);
|
||||
return ipsec->sas->del_sa(ipsec->sas, id->src, id->dst, id->spi, id->proto,
|
||||
data->cpi, id->mark);
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, flush_sas, status_t,
|
||||
@@ -509,22 +505,22 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, add_policy, status_t,
|
||||
private_kernel_libipsec_ipsec_t *this, host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, mark_t mark,
|
||||
policy_priority_t priority)
|
||||
private_kernel_libipsec_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data)
|
||||
{
|
||||
policy_entry_t *policy, *found = NULL;
|
||||
status_t status;
|
||||
|
||||
status = ipsec->policies->add_policy(ipsec->policies, src, dst, src_ts,
|
||||
dst_ts, direction, type, sa, mark, priority);
|
||||
status = ipsec->policies->add_policy(ipsec->policies, data->src, data->dst,
|
||||
id->src_ts, id->dst_ts, id->dir,
|
||||
data->type, data->sa, id->mark,
|
||||
data->prio);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
/* we track policies in order to install routes */
|
||||
policy = create_policy_entry(src_ts, dst_ts, direction);
|
||||
policy = create_policy_entry(id->src_ts, id->dst_ts, id->dir);
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
if (this->policies->find_first(this->policies,
|
||||
@@ -540,7 +536,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
||||
}
|
||||
policy->refs++;
|
||||
|
||||
if (!install_route(this, src, dst, src_ts, dst_ts, policy))
|
||||
if (!install_route(this, data->src, data->dst, id->src_ts, id->dst_ts,
|
||||
policy))
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
@@ -548,26 +545,25 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||
private_kernel_libipsec_ipsec_t *this, traffic_selector_t *src_ts,
|
||||
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
||||
time_t *use_time)
|
||||
private_kernel_libipsec_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_query_policy_t *data, time_t *use_time)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, del_policy, status_t,
|
||||
private_kernel_libipsec_ipsec_t *this, host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
|
||||
mark_t mark, policy_priority_t priority)
|
||||
private_kernel_libipsec_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data)
|
||||
{
|
||||
policy_entry_t *policy, *found = NULL;
|
||||
status_t status;
|
||||
|
||||
status = ipsec->policies->del_policy(ipsec->policies, src, dst, src_ts,
|
||||
dst_ts, direction, type, sa, mark, priority);
|
||||
status = ipsec->policies->del_policy(ipsec->policies, data->src, data->dst,
|
||||
id->src_ts, id->dst_ts, id->dir,
|
||||
data->type, data->sa, id->mark,
|
||||
data->prio);
|
||||
|
||||
policy = create_policy_entry(src_ts, dst_ts, direction);
|
||||
policy = create_policy_entry(id->src_ts, id->dst_ts, id->dir);
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
if (this->policies->find_first(this->policies,
|
||||
@@ -596,8 +592,8 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
|
||||
route->src_ip, route->if_name) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "error uninstalling route installed with "
|
||||
"policy %R === %R %N", src_ts, dst_ts,
|
||||
policy_dir_names, direction);
|
||||
"policy %R === %R %N", id->src_ts, id->dst_ts,
|
||||
policy_dir_names, id->dir);
|
||||
}
|
||||
remove_exclude_route(this, route);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 Tobias Brunner
|
||||
* Copyright (C) 2008-2016 Tobias Brunner
|
||||
* Copyright (C) 2008 Andreas Steffen
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -1605,13 +1605,8 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, uint32_t spi,
|
||||
uint8_t protocol, uint32_t reqid, mark_t mark, uint32_t tfc,
|
||||
lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
|
||||
uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
|
||||
uint16_t ipcomp, uint16_t cpi, uint32_t replay_window,
|
||||
bool initiator, bool encap, bool esn, bool inbound, bool update,
|
||||
linked_list_t *src_ts, linked_list_t *dst_ts)
|
||||
private_kernel_pfkey_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_add_sa_t *data)
|
||||
{
|
||||
unsigned char request[PFKEY_BUFFER_SIZE];
|
||||
struct sadb_msg *msg, *out;
|
||||
@@ -1620,22 +1615,42 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
struct sadb_lifetime *lft;
|
||||
struct sadb_key *key;
|
||||
size_t len;
|
||||
uint16_t ipcomp = data->ipcomp;
|
||||
ipsec_mode_t mode = data->mode;
|
||||
|
||||
/* if IPComp is used, we install an additional IPComp SA. if the cpi is 0
|
||||
* we are in the recursive call below */
|
||||
if (ipcomp != IPCOMP_NONE && cpi != 0)
|
||||
if (ipcomp != IPCOMP_NONE && data->cpi != 0)
|
||||
{
|
||||
lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}};
|
||||
add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark,
|
||||
tfc, &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED,
|
||||
chunk_empty, mode, ipcomp, 0, 0, FALSE, FALSE, FALSE, inbound,
|
||||
update, NULL, NULL);
|
||||
kernel_ipsec_sa_id_t ipcomp_id = {
|
||||
.src = id->src,
|
||||
.dst = id->dst,
|
||||
.spi = htonl(ntohs(data->cpi)),
|
||||
.proto = IPPROTO_COMP,
|
||||
.mark = id->mark,
|
||||
};
|
||||
kernel_ipsec_add_sa_t ipcomp_sa = {
|
||||
.reqid = data->reqid,
|
||||
.mode = data->mode,
|
||||
.src_ts = data->src_ts,
|
||||
.dst_ts = data->dst_ts,
|
||||
.lifetime = &lft,
|
||||
.enc_alg = ENCR_UNDEFINED,
|
||||
.int_alg = AUTH_UNDEFINED,
|
||||
.tfc = data->tfc,
|
||||
.ipcomp = data->ipcomp,
|
||||
.initiator = data->initiator,
|
||||
.inbound = data->inbound,
|
||||
.update = data->update,
|
||||
};
|
||||
add_sa(this, &ipcomp_id, &ipcomp_sa);
|
||||
ipcomp = IPCOMP_NONE;
|
||||
/* use transport mode ESP SA, IPComp uses tunnel mode */
|
||||
mode = MODE_TRANSPORT;
|
||||
}
|
||||
|
||||
if (update)
|
||||
if (data->update)
|
||||
{
|
||||
/* As we didn't know the reqid during SPI allocation, we used reqid
|
||||
* zero. Unfortunately we can't SADB_UPDATE to the new reqid, hence we
|
||||
@@ -1643,10 +1658,16 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
* selector does not count for that, therefore we have to delete
|
||||
* that state before installing the new SA to avoid deleting the
|
||||
* the new state after installing it. */
|
||||
mark_t zeromark = {0, 0};
|
||||
kernel_ipsec_sa_id_t del_id = {
|
||||
.src = id->src,
|
||||
.dst = id->dst,
|
||||
.spi = id->spi,
|
||||
.proto = id->proto,
|
||||
};
|
||||
kernel_ipsec_del_sa_t del = { 0 };
|
||||
|
||||
if (this->public.interface.del_sa(&this->public.interface,
|
||||
src, dst, spi, protocol, 0, zeromark) != SUCCESS)
|
||||
if (this->public.interface.del_sa(&this->public.interface, &del_id,
|
||||
&del) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "deleting SPI allocation SA failed");
|
||||
}
|
||||
@@ -1655,20 +1676,20 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
memset(&request, 0, sizeof(request));
|
||||
|
||||
DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}",
|
||||
ntohl(spi), reqid);
|
||||
ntohl(id->spi), data->reqid);
|
||||
|
||||
msg = (struct sadb_msg*)request;
|
||||
msg->sadb_msg_version = PF_KEY_V2;
|
||||
msg->sadb_msg_type = SADB_ADD;
|
||||
msg->sadb_msg_satype = proto2satype(protocol);
|
||||
msg->sadb_msg_satype = proto2satype(id->proto);
|
||||
msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (encap)
|
||||
if (data->encap)
|
||||
{
|
||||
struct sadb_sa_2 *sa_2;
|
||||
sa_2 = (struct sadb_sa_2*)PFKEY_EXT_ADD_NEXT(msg);
|
||||
sa_2->sadb_sa_natt_port = dst->get_port(dst);
|
||||
sa_2->sadb_sa_natt_port = id->dst->get_port(id->dst);
|
||||
sa = &sa_2->sa;
|
||||
sa->sadb_sa_flags |= SADB_X_EXT_NATT;
|
||||
len = sizeof(struct sadb_sa_2);
|
||||
@@ -1681,22 +1702,24 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
}
|
||||
sa->sadb_sa_exttype = SADB_EXT_SA;
|
||||
sa->sadb_sa_len = PFKEY_LEN(len);
|
||||
sa->sadb_sa_spi = spi;
|
||||
if (protocol == IPPROTO_COMP)
|
||||
sa->sadb_sa_spi = id->spi;
|
||||
if (id->proto == IPPROTO_COMP)
|
||||
{
|
||||
sa->sadb_sa_encrypt = lookup_algorithm(COMPRESSION_ALGORITHM, ipcomp);
|
||||
sa->sadb_sa_encrypt = lookup_algorithm(COMPRESSION_ALGORITHM,
|
||||
ipcomp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Linux interprets sadb_sa_replay as number of packets/bits in the
|
||||
* replay window, whereas on BSD it's the size of the window in bytes */
|
||||
#ifdef __linux__
|
||||
sa->sadb_sa_replay = min(replay_window, 32);
|
||||
sa->sadb_sa_replay = min(data->replay_window, 32);
|
||||
#else
|
||||
sa->sadb_sa_replay = (replay_window + 7) / 8;
|
||||
sa->sadb_sa_replay = (data->replay_window + 7) / 8;
|
||||
#endif
|
||||
sa->sadb_sa_auth = lookup_algorithm(INTEGRITY_ALGORITHM, int_alg);
|
||||
sa->sadb_sa_encrypt = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg);
|
||||
sa->sadb_sa_auth = lookup_algorithm(INTEGRITY_ALGORITHM, data->int_alg);
|
||||
sa->sadb_sa_encrypt = lookup_algorithm(ENCRYPTION_ALGORITHM,
|
||||
data->enc_alg);
|
||||
}
|
||||
PFKEY_EXT_ADD(msg, sa);
|
||||
|
||||
@@ -1704,86 +1727,88 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
|
||||
sa2->sadb_x_sa2_len = PFKEY_LEN(sizeof(struct sadb_spirange));
|
||||
sa2->sadb_x_sa2_mode = mode2kernel(mode);
|
||||
sa2->sadb_x_sa2_reqid = reqid;
|
||||
sa2->sadb_x_sa2_reqid = data->reqid;
|
||||
PFKEY_EXT_ADD(msg, sa2);
|
||||
|
||||
add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
|
||||
add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
|
||||
add_addr_ext(msg, id->src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
|
||||
add_addr_ext(msg, id->dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
|
||||
|
||||
lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg);
|
||||
lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
|
||||
lft->sadb_lifetime_len = PFKEY_LEN(sizeof(struct sadb_lifetime));
|
||||
lft->sadb_lifetime_allocations = lifetime->packets.rekey;
|
||||
lft->sadb_lifetime_bytes = lifetime->bytes.rekey;
|
||||
lft->sadb_lifetime_addtime = lifetime->time.rekey;
|
||||
lft->sadb_lifetime_allocations = data->lifetime->packets.rekey;
|
||||
lft->sadb_lifetime_bytes = data->lifetime->bytes.rekey;
|
||||
lft->sadb_lifetime_addtime = data->lifetime->time.rekey;
|
||||
lft->sadb_lifetime_usetime = 0; /* we only use addtime */
|
||||
PFKEY_EXT_ADD(msg, lft);
|
||||
|
||||
lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg);
|
||||
lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
|
||||
lft->sadb_lifetime_len = PFKEY_LEN(sizeof(struct sadb_lifetime));
|
||||
lft->sadb_lifetime_allocations = lifetime->packets.life;
|
||||
lft->sadb_lifetime_bytes = lifetime->bytes.life;
|
||||
lft->sadb_lifetime_addtime = lifetime->time.life;
|
||||
lft->sadb_lifetime_allocations = data->lifetime->packets.life;
|
||||
lft->sadb_lifetime_bytes = data->lifetime->bytes.life;
|
||||
lft->sadb_lifetime_addtime = data->lifetime->time.life;
|
||||
lft->sadb_lifetime_usetime = 0; /* we only use addtime */
|
||||
PFKEY_EXT_ADD(msg, lft);
|
||||
|
||||
if (enc_alg != ENCR_UNDEFINED)
|
||||
if (data->enc_alg != ENCR_UNDEFINED)
|
||||
{
|
||||
if (!sa->sadb_sa_encrypt)
|
||||
{
|
||||
DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
|
||||
encryption_algorithm_names, enc_alg);
|
||||
encryption_algorithm_names, data->enc_alg);
|
||||
return FAILED;
|
||||
}
|
||||
DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
|
||||
encryption_algorithm_names, enc_alg, enc_key.len * 8);
|
||||
encryption_algorithm_names, data->enc_alg, data->enc_key.len * 8);
|
||||
|
||||
key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
|
||||
key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
|
||||
key->sadb_key_bits = enc_key.len * 8;
|
||||
key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + enc_key.len);
|
||||
memcpy(key + 1, enc_key.ptr, enc_key.len);
|
||||
key->sadb_key_bits = data->enc_key.len * 8;
|
||||
key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + data->enc_key.len);
|
||||
memcpy(key + 1, data->enc_key.ptr, data->enc_key.len);
|
||||
|
||||
PFKEY_EXT_ADD(msg, key);
|
||||
}
|
||||
|
||||
if (int_alg != AUTH_UNDEFINED)
|
||||
if (data->int_alg != AUTH_UNDEFINED)
|
||||
{
|
||||
if (!sa->sadb_sa_auth)
|
||||
{
|
||||
DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
|
||||
integrity_algorithm_names, int_alg);
|
||||
integrity_algorithm_names, data->int_alg);
|
||||
return FAILED;
|
||||
}
|
||||
DBG2(DBG_KNL, " using integrity algorithm %N with key size %d",
|
||||
integrity_algorithm_names, int_alg, int_key.len * 8);
|
||||
integrity_algorithm_names, data->int_alg, data->int_key.len * 8);
|
||||
|
||||
key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
|
||||
key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
|
||||
key->sadb_key_bits = int_key.len * 8;
|
||||
key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + int_key.len);
|
||||
memcpy(key + 1, int_key.ptr, int_key.len);
|
||||
key->sadb_key_bits = data->int_key.len * 8;
|
||||
key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + data->int_key.len);
|
||||
memcpy(key + 1, data->int_key.ptr, data->int_key.len);
|
||||
|
||||
PFKEY_EXT_ADD(msg, key);
|
||||
}
|
||||
|
||||
#ifdef HAVE_NATT
|
||||
if (encap)
|
||||
if (data->encap)
|
||||
{
|
||||
add_encap_ext(msg, src, dst);
|
||||
add_encap_ext(msg, id->src, id->dst);
|
||||
}
|
||||
#endif /*HAVE_NATT*/
|
||||
|
||||
if (pfkey_send(this, msg, &out, &len) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
|
||||
DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x",
|
||||
ntohl(id->spi));
|
||||
return FAILED;
|
||||
}
|
||||
else if (out->sadb_msg_errno)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x: %s (%d)",
|
||||
ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
|
||||
ntohl(id->spi), strerror(out->sadb_msg_errno),
|
||||
out->sadb_msg_errno);
|
||||
free(out);
|
||||
return FAILED;
|
||||
}
|
||||
@@ -1793,9 +1818,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, update_sa, status_t,
|
||||
private_kernel_pfkey_ipsec_t *this, uint32_t spi, uint8_t protocol,
|
||||
uint16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
|
||||
bool encap, bool new_encap, mark_t mark)
|
||||
private_kernel_pfkey_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_update_sa_t *data)
|
||||
{
|
||||
unsigned char request[PFKEY_BUFFER_SIZE];
|
||||
struct sadb_msg *msg, *out;
|
||||
@@ -1806,72 +1830,84 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
||||
/* we can't update the SA if any of the ip addresses have changed.
|
||||
* that's because we can't use SADB_UPDATE and by deleting and readding the
|
||||
* SA the sequence numbers would get lost */
|
||||
if (!src->ip_equals(src, new_src) ||
|
||||
!dst->ip_equals(dst, new_dst))
|
||||
if (!id->src->ip_equals(id->src, data->new_src) ||
|
||||
!id->dst->ip_equals(id->dst, data->new_dst))
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: address "
|
||||
"changes are not supported", ntohl(spi));
|
||||
"changes are not supported", ntohl(id->spi));
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* if IPComp is used, we first update the IPComp SA */
|
||||
if (cpi)
|
||||
if (data->cpi)
|
||||
{
|
||||
update_sa(this, htonl(ntohs(cpi)), IPPROTO_COMP, 0,
|
||||
src, dst, new_src, new_dst, FALSE, FALSE, mark);
|
||||
kernel_ipsec_sa_id_t ipcomp_id = {
|
||||
.src = id->src,
|
||||
.dst = id->dst,
|
||||
.spi = htonl(ntohs(data->cpi)),
|
||||
.proto = IPPROTO_COMP,
|
||||
.mark = id->mark,
|
||||
};
|
||||
kernel_ipsec_update_sa_t ipcomp = {
|
||||
.new_src = data->new_src,
|
||||
.new_dst = data->new_dst,
|
||||
};
|
||||
update_sa(this, &ipcomp_id, &ipcomp);
|
||||
}
|
||||
|
||||
memset(&request, 0, sizeof(request));
|
||||
|
||||
DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
|
||||
DBG2(DBG_KNL, "querying SAD entry with SPI %.8x for update",
|
||||
ntohl(id->spi));
|
||||
|
||||
msg = (struct sadb_msg*)request;
|
||||
msg->sadb_msg_version = PF_KEY_V2;
|
||||
msg->sadb_msg_type = SADB_GET;
|
||||
msg->sadb_msg_satype = proto2satype(protocol);
|
||||
msg->sadb_msg_satype = proto2satype(id->proto);
|
||||
msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
|
||||
|
||||
sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
|
||||
sa->sadb_sa_exttype = SADB_EXT_SA;
|
||||
sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
|
||||
sa->sadb_sa_spi = spi;
|
||||
sa->sadb_sa_spi = id->spi;
|
||||
PFKEY_EXT_ADD(msg, sa);
|
||||
|
||||
/* the kernel wants a SADB_EXT_ADDRESS_SRC to be present even though
|
||||
* it is not used for anything. */
|
||||
add_anyaddr_ext(msg, dst->get_family(dst), SADB_EXT_ADDRESS_SRC);
|
||||
add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
|
||||
add_anyaddr_ext(msg, id->dst->get_family(id->dst), SADB_EXT_ADDRESS_SRC);
|
||||
add_addr_ext(msg, id->dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
|
||||
|
||||
if (pfkey_send(this, msg, &out, &len) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi));
|
||||
DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x",
|
||||
ntohl(id->spi));
|
||||
return FAILED;
|
||||
}
|
||||
else if (out->sadb_msg_errno)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: %s (%d)",
|
||||
ntohl(spi), strerror(out->sadb_msg_errno),
|
||||
out->sadb_msg_errno);
|
||||
ntohl(id->spi), strerror(out->sadb_msg_errno),
|
||||
out->sadb_msg_errno);
|
||||
free(out);
|
||||
return FAILED;
|
||||
}
|
||||
else if (parse_pfkey_message(out, &response) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: parsing "
|
||||
"response from kernel failed", ntohl(spi));
|
||||
"response from kernel failed", ntohl(id->spi));
|
||||
free(out);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
DBG2(DBG_KNL, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H",
|
||||
ntohl(spi), src, dst, new_src, new_dst);
|
||||
ntohl(id->spi), id->src, id->dst, data->new_src, data->new_dst);
|
||||
|
||||
memset(&request, 0, sizeof(request));
|
||||
|
||||
msg = (struct sadb_msg*)request;
|
||||
msg->sadb_msg_version = PF_KEY_V2;
|
||||
msg->sadb_msg_type = SADB_UPDATE;
|
||||
msg->sadb_msg_satype = proto2satype(protocol);
|
||||
msg->sadb_msg_satype = proto2satype(id->proto);
|
||||
msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
|
||||
|
||||
#ifdef __APPLE__
|
||||
@@ -1880,9 +1916,9 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
||||
sa_2 = (struct sadb_sa_2*)PFKEY_EXT_ADD_NEXT(msg);
|
||||
sa_2->sa.sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa_2));
|
||||
memcpy(&sa_2->sa, response.sa, sizeof(struct sadb_sa));
|
||||
if (encap)
|
||||
if (data->encap)
|
||||
{
|
||||
sa_2->sadb_sa_natt_port = new_dst->get_port(new_dst);
|
||||
sa_2->sadb_sa_natt_port = data->new_dst->get_port(data->new_dst);
|
||||
sa_2->sa.sadb_sa_flags |= SADB_X_EXT_NATT;
|
||||
}
|
||||
}
|
||||
@@ -1908,9 +1944,9 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
||||
}
|
||||
|
||||
#ifdef HAVE_NATT
|
||||
if (new_encap)
|
||||
if (data->new_encap)
|
||||
{
|
||||
add_encap_ext(msg, new_src, new_dst);
|
||||
add_encap_ext(msg, data->new_src, data->new_dst);
|
||||
}
|
||||
#endif /*HAVE_NATT*/
|
||||
|
||||
@@ -1918,14 +1954,14 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
||||
|
||||
if (pfkey_send(this, msg, &out, &len) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
|
||||
DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x",
|
||||
ntohl(id->spi));
|
||||
return FAILED;
|
||||
}
|
||||
else if (out->sadb_msg_errno)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: %s (%d)",
|
||||
ntohl(spi), strerror(out->sadb_msg_errno),
|
||||
out->sadb_msg_errno);
|
||||
ntohl(id->spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
|
||||
free(out);
|
||||
return FAILED;
|
||||
}
|
||||
@@ -1935,9 +1971,9 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, mark_t mark,
|
||||
uint64_t *bytes, uint64_t *packets, time_t *time)
|
||||
private_kernel_pfkey_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
|
||||
time_t *time)
|
||||
{
|
||||
unsigned char request[PFKEY_BUFFER_SIZE];
|
||||
struct sadb_msg *msg, *out;
|
||||
@@ -1947,42 +1983,44 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||
|
||||
memset(&request, 0, sizeof(request));
|
||||
|
||||
DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
|
||||
DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(id->spi));
|
||||
|
||||
msg = (struct sadb_msg*)request;
|
||||
msg->sadb_msg_version = PF_KEY_V2;
|
||||
msg->sadb_msg_type = SADB_GET;
|
||||
msg->sadb_msg_satype = proto2satype(protocol);
|
||||
msg->sadb_msg_satype = proto2satype(id->proto);
|
||||
msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
|
||||
|
||||
sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
|
||||
sa->sadb_sa_exttype = SADB_EXT_SA;
|
||||
sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
|
||||
sa->sadb_sa_spi = spi;
|
||||
sa->sadb_sa_spi = id->spi;
|
||||
PFKEY_EXT_ADD(msg, sa);
|
||||
|
||||
/* the Linux Kernel doesn't care for the src address, but other systems do
|
||||
* (e.g. FreeBSD)
|
||||
*/
|
||||
add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
|
||||
add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
|
||||
add_addr_ext(msg, id->src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
|
||||
add_addr_ext(msg, id->dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
|
||||
|
||||
if (pfkey_send(this, msg, &out, &len) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi));
|
||||
DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x",
|
||||
ntohl(id->spi));
|
||||
return FAILED;
|
||||
}
|
||||
else if (out->sadb_msg_errno)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: %s (%d)",
|
||||
ntohl(spi), strerror(out->sadb_msg_errno),
|
||||
out->sadb_msg_errno);
|
||||
ntohl(id->spi), strerror(out->sadb_msg_errno),
|
||||
out->sadb_msg_errno);
|
||||
free(out);
|
||||
return FAILED;
|
||||
}
|
||||
else if (parse_pfkey_message(out, &response) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi));
|
||||
DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x",
|
||||
ntohl(id->spi));
|
||||
free(out);
|
||||
return FAILED;
|
||||
}
|
||||
@@ -2013,8 +2051,8 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, del_sa, status_t,
|
||||
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, uint16_t cpi, mark_t mark)
|
||||
private_kernel_pfkey_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_del_sa_t *data)
|
||||
{
|
||||
unsigned char request[PFKEY_BUFFER_SIZE];
|
||||
struct sadb_msg *msg, *out;
|
||||
@@ -2022,48 +2060,57 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
|
||||
size_t len;
|
||||
|
||||
/* if IPComp was used, we first delete the additional IPComp SA */
|
||||
if (cpi)
|
||||
if (data->cpi)
|
||||
{
|
||||
del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0, mark);
|
||||
kernel_ipsec_sa_id_t ipcomp_id = {
|
||||
.src = id->src,
|
||||
.dst = id->dst,
|
||||
.spi = htonl(ntohs(data->cpi)),
|
||||
.proto = IPPROTO_COMP,
|
||||
.mark = id->mark,
|
||||
};
|
||||
kernel_ipsec_del_sa_t ipcomp = { 0 };
|
||||
del_sa(this, &ipcomp_id, &ipcomp);
|
||||
}
|
||||
|
||||
memset(&request, 0, sizeof(request));
|
||||
|
||||
DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
|
||||
DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(id->spi));
|
||||
|
||||
msg = (struct sadb_msg*)request;
|
||||
msg->sadb_msg_version = PF_KEY_V2;
|
||||
msg->sadb_msg_type = SADB_DELETE;
|
||||
msg->sadb_msg_satype = proto2satype(protocol);
|
||||
msg->sadb_msg_satype = proto2satype(id->proto);
|
||||
msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
|
||||
|
||||
sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
|
||||
sa->sadb_sa_exttype = SADB_EXT_SA;
|
||||
sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
|
||||
sa->sadb_sa_spi = spi;
|
||||
sa->sadb_sa_spi = id->spi;
|
||||
PFKEY_EXT_ADD(msg, sa);
|
||||
|
||||
/* the Linux Kernel doesn't care for the src address, but other systems do
|
||||
* (e.g. FreeBSD)
|
||||
*/
|
||||
add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
|
||||
add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
|
||||
add_addr_ext(msg, id->src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
|
||||
add_addr_ext(msg, id->dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
|
||||
|
||||
if (pfkey_send(this, msg, &out, &len) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi));
|
||||
DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x",
|
||||
ntohl(id->spi));
|
||||
return FAILED;
|
||||
}
|
||||
else if (out->sadb_msg_errno)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x: %s (%d)",
|
||||
ntohl(spi), strerror(out->sadb_msg_errno),
|
||||
out->sadb_msg_errno);
|
||||
ntohl(id->spi), strerror(out->sadb_msg_errno),
|
||||
out->sadb_msg_errno);
|
||||
free(out);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
|
||||
DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(id->spi));
|
||||
free(out);
|
||||
return SUCCESS;
|
||||
}
|
||||
@@ -2381,53 +2428,56 @@ static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
|
||||
pol->sadb_x_policy_priority = mapping->priority;
|
||||
#endif
|
||||
|
||||
/* one or more sadb_x_ipsecrequest extensions are added to the
|
||||
* sadb_x_policy extension */
|
||||
proto_mode = ipsec->cfg.mode;
|
||||
|
||||
req = (struct sadb_x_ipsecrequest*)(pol + 1);
|
||||
|
||||
if (ipsec->cfg.ipcomp.transform != IPCOMP_NONE)
|
||||
if (mapping->type == POLICY_IPSEC && ipsec->cfg.reqid)
|
||||
{
|
||||
req->sadb_x_ipsecrequest_proto = IPPROTO_COMP;
|
||||
/* one or more sadb_x_ipsecrequest extensions are added to the
|
||||
* sadb_x_policy extension */
|
||||
proto_mode = ipsec->cfg.mode;
|
||||
|
||||
req = (struct sadb_x_ipsecrequest*)(pol + 1);
|
||||
|
||||
if (ipsec->cfg.ipcomp.transform != IPCOMP_NONE)
|
||||
{
|
||||
req->sadb_x_ipsecrequest_proto = IPPROTO_COMP;
|
||||
|
||||
/* !!! the length here MUST be in octets instead of 64 bit words */
|
||||
req->sadb_x_ipsecrequest_len = sizeof(struct sadb_x_ipsecrequest);
|
||||
req->sadb_x_ipsecrequest_mode = mode2kernel(ipsec->cfg.mode);
|
||||
req->sadb_x_ipsecrequest_reqid = ipsec->cfg.reqid;
|
||||
req->sadb_x_ipsecrequest_level = (policy->direction == POLICY_OUT) ?
|
||||
IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_USE;
|
||||
if (ipsec->cfg.mode == MODE_TUNNEL)
|
||||
{
|
||||
len = hostcpy(req + 1, ipsec->src, FALSE);
|
||||
req->sadb_x_ipsecrequest_len += len;
|
||||
len = hostcpy((char*)(req + 1) + len, ipsec->dst, FALSE);
|
||||
req->sadb_x_ipsecrequest_len += len;
|
||||
/* use transport mode for other SAs */
|
||||
proto_mode = MODE_TRANSPORT;
|
||||
}
|
||||
|
||||
pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len);
|
||||
req = (struct sadb_x_ipsecrequest*)((char*)(req) +
|
||||
req->sadb_x_ipsecrequest_len);
|
||||
}
|
||||
|
||||
req->sadb_x_ipsecrequest_proto = ipsec->cfg.esp.use ? IPPROTO_ESP
|
||||
: IPPROTO_AH;
|
||||
/* !!! the length here MUST be in octets instead of 64 bit words */
|
||||
req->sadb_x_ipsecrequest_len = sizeof(struct sadb_x_ipsecrequest);
|
||||
req->sadb_x_ipsecrequest_mode = mode2kernel(ipsec->cfg.mode);
|
||||
req->sadb_x_ipsecrequest_mode = mode2kernel(proto_mode);
|
||||
req->sadb_x_ipsecrequest_reqid = ipsec->cfg.reqid;
|
||||
req->sadb_x_ipsecrequest_level = (policy->direction == POLICY_OUT) ?
|
||||
IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_USE;
|
||||
if (ipsec->cfg.mode == MODE_TUNNEL)
|
||||
req->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
|
||||
if (proto_mode == MODE_TUNNEL)
|
||||
{
|
||||
len = hostcpy(req + 1, ipsec->src, FALSE);
|
||||
req->sadb_x_ipsecrequest_len += len;
|
||||
len = hostcpy((char*)(req + 1) + len, ipsec->dst, FALSE);
|
||||
req->sadb_x_ipsecrequest_len += len;
|
||||
/* use transport mode for other SAs */
|
||||
proto_mode = MODE_TRANSPORT;
|
||||
}
|
||||
|
||||
pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len);
|
||||
req = (struct sadb_x_ipsecrequest*)((char*)(req) +
|
||||
req->sadb_x_ipsecrequest_len);
|
||||
}
|
||||
|
||||
req->sadb_x_ipsecrequest_proto = ipsec->cfg.esp.use ? IPPROTO_ESP
|
||||
: IPPROTO_AH;
|
||||
/* !!! the length here MUST be in octets instead of 64 bit words */
|
||||
req->sadb_x_ipsecrequest_len = sizeof(struct sadb_x_ipsecrequest);
|
||||
req->sadb_x_ipsecrequest_mode = mode2kernel(proto_mode);
|
||||
req->sadb_x_ipsecrequest_reqid = ipsec->cfg.reqid;
|
||||
req->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
|
||||
if (proto_mode == MODE_TUNNEL)
|
||||
{
|
||||
len = hostcpy(req + 1, ipsec->src, FALSE);
|
||||
req->sadb_x_ipsecrequest_len += len;
|
||||
len = hostcpy((char*)(req + 1) + len, ipsec->dst, FALSE);
|
||||
req->sadb_x_ipsecrequest_len += len;
|
||||
}
|
||||
|
||||
pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len);
|
||||
PFKEY_EXT_ADD(msg, pol);
|
||||
|
||||
add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto,
|
||||
@@ -2506,23 +2556,21 @@ static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, add_policy, status_t,
|
||||
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
|
||||
mark_t mark, policy_priority_t priority)
|
||||
private_kernel_pfkey_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data)
|
||||
{
|
||||
policy_entry_t *policy, *found = NULL;
|
||||
policy_sa_t *assigned_sa, *current_sa;
|
||||
enumerator_t *enumerator;
|
||||
bool update = TRUE;
|
||||
|
||||
if (dir2kernel(direction) == IPSEC_DIR_INVALID)
|
||||
if (dir2kernel(id->dir) == IPSEC_DIR_INVALID)
|
||||
{ /* FWD policies are not supported on all platforms */
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* create a policy */
|
||||
policy = create_policy_entry(src_ts, dst_ts, direction);
|
||||
policy = create_policy_entry(id->src_ts, id->dst_ts, id->dir);
|
||||
|
||||
/* find a matching policy */
|
||||
this->mutex->lock(this->mutex);
|
||||
@@ -2531,7 +2579,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
||||
(void**)&found, policy) == SUCCESS)
|
||||
{ /* use existing policy */
|
||||
DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing "
|
||||
"refcount", src_ts, dst_ts, policy_dir_names, direction);
|
||||
"refcount", id->src_ts, id->dst_ts, policy_dir_names, id->dir);
|
||||
policy_entry_destroy(policy, this);
|
||||
policy = found;
|
||||
}
|
||||
@@ -2542,15 +2590,21 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
||||
}
|
||||
|
||||
/* cache the assigned IPsec SA */
|
||||
assigned_sa = policy_sa_create(this, direction, type, src, dst, src_ts,
|
||||
dst_ts, sa);
|
||||
assigned_sa->priority = get_priority(policy, priority);
|
||||
assigned_sa = policy_sa_create(this, id->dir, data->type, data->src,
|
||||
data->dst, id->src_ts, id->dst_ts, data->sa);
|
||||
assigned_sa->priority = get_priority(policy, data->prio);
|
||||
|
||||
/* insert the SA according to its priority */
|
||||
enumerator = policy->used_by->create_enumerator(policy->used_by);
|
||||
while (enumerator->enumerate(enumerator, (void**)¤t_sa))
|
||||
{
|
||||
if (current_sa->priority >= assigned_sa->priority)
|
||||
if (current_sa->priority > assigned_sa->priority)
|
||||
{
|
||||
break;
|
||||
}
|
||||
/* prefer SAs with a reqid over those without */
|
||||
if (current_sa->priority == assigned_sa->priority &&
|
||||
(!current_sa->sa->cfg.reqid || assigned_sa->sa->cfg.reqid))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -2567,23 +2621,22 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
||||
}
|
||||
|
||||
DBG2(DBG_KNL, "%s policy %R === %R %N",
|
||||
found ? "updating" : "adding", src_ts, dst_ts,
|
||||
policy_dir_names, direction);
|
||||
found ? "updating" : "adding", id->src_ts, id->dst_ts,
|
||||
policy_dir_names, id->dir);
|
||||
|
||||
if (add_policy_internal(this, policy, assigned_sa, found) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to %s policy %R === %R %N",
|
||||
found ? "update" : "add", src_ts, dst_ts,
|
||||
policy_dir_names, direction);
|
||||
found ? "update" : "add", id->src_ts, id->dst_ts,
|
||||
policy_dir_names, id->dir);
|
||||
return FAILED;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||
private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
|
||||
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
||||
time_t *use_time)
|
||||
private_kernel_pfkey_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_query_policy_t *data, time_t *use_time)
|
||||
{
|
||||
unsigned char request[PFKEY_BUFFER_SIZE];
|
||||
struct sadb_msg *msg, *out;
|
||||
@@ -2592,16 +2645,16 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||
pfkey_msg_t response;
|
||||
size_t len;
|
||||
|
||||
if (dir2kernel(direction) == IPSEC_DIR_INVALID)
|
||||
if (dir2kernel(id->dir) == IPSEC_DIR_INVALID)
|
||||
{ /* FWD policies are not supported on all platforms */
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts,
|
||||
policy_dir_names, direction);
|
||||
DBG2(DBG_KNL, "querying policy %R === %R %N", id->src_ts, id->dst_ts,
|
||||
policy_dir_names, id->dir);
|
||||
|
||||
/* create a policy */
|
||||
policy = create_policy_entry(src_ts, dst_ts, direction);
|
||||
policy = create_policy_entry(id->src_ts, id->dst_ts, id->dir);
|
||||
|
||||
/* find a matching policy */
|
||||
this->mutex->lock(this->mutex);
|
||||
@@ -2609,8 +2662,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||
(linked_list_match_t)policy_entry_equals,
|
||||
(void**)&found, policy) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "querying policy %R === %R %N failed, not found", src_ts,
|
||||
dst_ts, policy_dir_names, direction);
|
||||
DBG1(DBG_KNL, "querying policy %R === %R %N failed, not found",
|
||||
id->src_ts, id->dst_ts, policy_dir_names, id->dir);
|
||||
policy_entry_destroy(policy, this);
|
||||
this->mutex->unlock(this->mutex);
|
||||
return NOT_FOUND;
|
||||
@@ -2630,7 +2683,7 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||
pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
|
||||
pol->sadb_x_policy_id = policy->index;
|
||||
pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy));
|
||||
pol->sadb_x_policy_dir = dir2kernel(direction);
|
||||
pol->sadb_x_policy_dir = dir2kernel(id->dir);
|
||||
pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
|
||||
PFKEY_EXT_ADD(msg, pol);
|
||||
|
||||
@@ -2643,30 +2696,31 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||
|
||||
if (pfkey_send(this, msg, &out, &len) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to query policy %R === %R %N", src_ts, dst_ts,
|
||||
policy_dir_names, direction);
|
||||
DBG1(DBG_KNL, "unable to query policy %R === %R %N", id->src_ts,
|
||||
id->dst_ts, policy_dir_names, id->dir);
|
||||
return FAILED;
|
||||
}
|
||||
else if (out->sadb_msg_errno)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to query policy %R === %R %N: %s (%d)", src_ts,
|
||||
dst_ts, policy_dir_names, direction,
|
||||
strerror(out->sadb_msg_errno), out->sadb_msg_errno);
|
||||
DBG1(DBG_KNL, "unable to query policy %R === %R %N: %s (%d)",
|
||||
id->src_ts, id->dst_ts, policy_dir_names, id->dir,
|
||||
strerror(out->sadb_msg_errno), out->sadb_msg_errno);
|
||||
free(out);
|
||||
return FAILED;
|
||||
}
|
||||
else if (parse_pfkey_message(out, &response) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to query policy %R === %R %N: parsing response "
|
||||
"from kernel failed", src_ts, dst_ts, policy_dir_names,
|
||||
direction);
|
||||
"from kernel failed", id->src_ts, id->dst_ts, policy_dir_names,
|
||||
id->dir);
|
||||
free(out);
|
||||
return FAILED;
|
||||
}
|
||||
else if (response.lft_current == NULL)
|
||||
{
|
||||
DBG2(DBG_KNL, "unable to query policy %R === %R %N: kernel reports no "
|
||||
"use time", src_ts, dst_ts, policy_dir_names, direction);
|
||||
"use time", id->src_ts, id->dst_ts, policy_dir_names,
|
||||
id->dir);
|
||||
free(out);
|
||||
return FAILED;
|
||||
}
|
||||
@@ -2686,10 +2740,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, del_policy, status_t,
|
||||
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
|
||||
mark_t mark, policy_priority_t prio)
|
||||
private_kernel_pfkey_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data)
|
||||
{
|
||||
unsigned char request[PFKEY_BUFFER_SIZE];
|
||||
struct sadb_msg *msg, *out;
|
||||
@@ -2701,21 +2753,21 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
|
||||
uint32_t priority;
|
||||
size_t len;
|
||||
ipsec_sa_t assigned_sa = {
|
||||
.src = src,
|
||||
.dst = dst,
|
||||
.cfg = *sa,
|
||||
.src = data->src,
|
||||
.dst = data->dst,
|
||||
.cfg = *data->sa,
|
||||
};
|
||||
|
||||
if (dir2kernel(direction) == IPSEC_DIR_INVALID)
|
||||
if (dir2kernel(id->dir) == IPSEC_DIR_INVALID)
|
||||
{ /* FWD policies are not supported on all platforms */
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts,
|
||||
policy_dir_names, direction);
|
||||
DBG2(DBG_KNL, "deleting policy %R === %R %N", id->src_ts, id->dst_ts,
|
||||
policy_dir_names, id->dir);
|
||||
|
||||
/* create a policy */
|
||||
policy = create_policy_entry(src_ts, dst_ts, direction);
|
||||
policy = create_policy_entry(id->src_ts, id->dst_ts, id->dir);
|
||||
|
||||
/* find a matching policy */
|
||||
this->mutex->lock(this->mutex);
|
||||
@@ -2723,8 +2775,8 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
|
||||
(linked_list_match_t)policy_entry_equals,
|
||||
(void**)&found, policy) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
|
||||
dst_ts, policy_dir_names, direction);
|
||||
DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found",
|
||||
id->src_ts, id->dst_ts, policy_dir_names, id->dir);
|
||||
policy_entry_destroy(policy, this);
|
||||
this->mutex->unlock(this->mutex);
|
||||
return NOT_FOUND;
|
||||
@@ -2734,7 +2786,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
|
||||
|
||||
/* remove mapping to SA by reqid and priority, if multiple match, which
|
||||
* could happen when rekeying due to an address change, remove the oldest */
|
||||
priority = get_priority(policy, prio);
|
||||
priority = get_priority(policy, data->prio);
|
||||
enumerator = policy->used_by->create_enumerator(policy->used_by);
|
||||
while (enumerator->enumerate(enumerator, (void**)&mapping))
|
||||
{
|
||||
@@ -2762,7 +2814,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
|
||||
if (policy->used_by->get_count(policy->used_by) > 0)
|
||||
{ /* policy is used by more SAs, keep in kernel */
|
||||
DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
|
||||
policy_sa_destroy(mapping, &direction, this);
|
||||
policy_sa_destroy(mapping, &id->dir, this);
|
||||
|
||||
if (!is_installed)
|
||||
{ /* no need to update as the policy was not installed for this SA */
|
||||
@@ -2770,13 +2822,13 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
DBG2(DBG_KNL, "updating policy %R === %R %N", src_ts, dst_ts,
|
||||
policy_dir_names, direction);
|
||||
DBG2(DBG_KNL, "updating policy %R === %R %N", id->src_ts, id->dst_ts,
|
||||
policy_dir_names, id->dir);
|
||||
policy->used_by->get_first(policy->used_by, (void**)&mapping);
|
||||
if (add_policy_internal(this, policy, mapping, TRUE) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to update policy %R === %R %N",
|
||||
src_ts, dst_ts, policy_dir_names, direction);
|
||||
id->src_ts, id->dst_ts, policy_dir_names, id->dir);
|
||||
return FAILED;
|
||||
}
|
||||
return SUCCESS;
|
||||
@@ -2793,7 +2845,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
|
||||
pol = (struct sadb_x_policy*)PFKEY_EXT_ADD_NEXT(msg);
|
||||
pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
|
||||
pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy));
|
||||
pol->sadb_x_policy_dir = dir2kernel(direction);
|
||||
pol->sadb_x_policy_dir = dir2kernel(id->dir);
|
||||
pol->sadb_x_policy_type = type2kernel(mapping->type);
|
||||
PFKEY_EXT_ADD(msg, pol);
|
||||
|
||||
@@ -2810,28 +2862,28 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
|
||||
route->src_ip, route->if_name) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "error uninstalling route installed with "
|
||||
"policy %R === %R %N", src_ts, dst_ts,
|
||||
policy_dir_names, direction);
|
||||
"policy %R === %R %N", id->src_ts, id->dst_ts,
|
||||
policy_dir_names, id->dir);
|
||||
}
|
||||
remove_exclude_route(this, route);
|
||||
}
|
||||
|
||||
this->policies->remove(this->policies, found, NULL);
|
||||
policy_sa_destroy(mapping, &direction, this);
|
||||
policy_sa_destroy(mapping, &id->dir, this);
|
||||
policy_entry_destroy(policy, this);
|
||||
this->mutex->unlock(this->mutex);
|
||||
|
||||
if (pfkey_send(this, msg, &out, &len) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to delete policy %R === %R %N", src_ts, dst_ts,
|
||||
policy_dir_names, direction);
|
||||
DBG1(DBG_KNL, "unable to delete policy %R === %R %N", id->src_ts,
|
||||
id->dst_ts, policy_dir_names, id->dir);
|
||||
return FAILED;
|
||||
}
|
||||
else if (out->sadb_msg_errno)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to delete policy %R === %R %N: %s (%d)", src_ts,
|
||||
dst_ts, policy_dir_names, direction,
|
||||
strerror(out->sadb_msg_errno), out->sadb_msg_errno);
|
||||
DBG1(DBG_KNL, "unable to delete policy %R === %R %N: %s (%d)",
|
||||
id->src_ts, id->dst_ts, policy_dir_names, id->dir,
|
||||
strerror(out->sadb_msg_errno), out->sadb_msg_errno);
|
||||
free(out);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
@@ -2093,57 +2093,55 @@ static void schedule_expire(private_kernel_wfp_ipsec_t *this, uint32_t spi,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, uint32_t reqid, mark_t mark,
|
||||
uint32_t tfc, lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
|
||||
uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
|
||||
uint16_t ipcomp, uint16_t cpi, uint32_t replay_window,
|
||||
bool initiator, bool encap, bool esn, bool inbound, bool update,
|
||||
linked_list_t *src_ts, linked_list_t *dst_ts)
|
||||
private_kernel_wfp_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_add_sa_t *data)
|
||||
{
|
||||
host_t *local, *remote;
|
||||
entry_t *entry;
|
||||
|
||||
if (inbound)
|
||||
if (data->inbound)
|
||||
{
|
||||
/* comes first, create new entry */
|
||||
local = dst->clone(dst);
|
||||
remote = src->clone(src);
|
||||
local = id->dst->clone(id->dst);
|
||||
remote = id->src->clone(id->src);
|
||||
|
||||
INIT(entry,
|
||||
.reqid = reqid,
|
||||
.reqid = data->reqid,
|
||||
.isa = {
|
||||
.spi = spi,
|
||||
.spi = id->spi,
|
||||
.dst = local,
|
||||
.protocol = protocol,
|
||||
.lifetime = lifetime->time.life,
|
||||
.protocol = id->proto,
|
||||
.lifetime = data->lifetime->time.life,
|
||||
.encr = {
|
||||
.alg = enc_alg,
|
||||
.key = chunk_clone(enc_key),
|
||||
.alg = data->enc_alg,
|
||||
.key = chunk_clone(data->enc_key),
|
||||
},
|
||||
.integ = {
|
||||
.alg = int_alg,
|
||||
.key = chunk_clone(int_key),
|
||||
.alg = data->int_alg,
|
||||
.key = chunk_clone(data->int_key),
|
||||
},
|
||||
},
|
||||
.sps = array_create(0, 0),
|
||||
.local = local,
|
||||
.remote = remote,
|
||||
.mode = mode,
|
||||
.encap = encap,
|
||||
.mode = data->mode,
|
||||
.encap = data->encap,
|
||||
);
|
||||
|
||||
if (lifetime->time.life)
|
||||
if (data->lifetime->time.life)
|
||||
{
|
||||
schedule_expire(this, spi, local, lifetime->time.life, TRUE);
|
||||
schedule_expire(this, id->spi, local,
|
||||
data->lifetime->time.life, TRUE);
|
||||
}
|
||||
if (lifetime->time.rekey && lifetime->time.rekey != lifetime->time.life)
|
||||
if (data->lifetime->time.rekey &&
|
||||
data->lifetime->time.rekey != data->lifetime->time.life)
|
||||
{
|
||||
schedule_expire(this, spi, local, lifetime->time.rekey, FALSE);
|
||||
schedule_expire(this, id->spi, local,
|
||||
data->lifetime->time.rekey, FALSE);
|
||||
}
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
this->tsas->put(this->tsas, (void*)(uintptr_t)reqid, entry);
|
||||
this->tsas->put(this->tsas, (void*)(uintptr_t)data->reqid, entry);
|
||||
this->isas->put(this->isas, &entry->isa, entry);
|
||||
this->mutex->unlock(this->mutex);
|
||||
}
|
||||
@@ -2151,29 +2149,29 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
{
|
||||
/* comes after inbound, update entry */
|
||||
this->mutex->lock(this->mutex);
|
||||
entry = this->tsas->remove(this->tsas, (void*)(uintptr_t)reqid);
|
||||
entry = this->tsas->remove(this->tsas, (void*)(uintptr_t)data->reqid);
|
||||
this->mutex->unlock(this->mutex);
|
||||
|
||||
if (!entry)
|
||||
{
|
||||
DBG1(DBG_KNL, "adding outbound SA failed, no inbound SA found "
|
||||
"for reqid %u ", reqid);
|
||||
"for reqid %u ", data->reqid);
|
||||
return NOT_FOUND;
|
||||
}
|
||||
/* TODO: should we check for local/remote, mode etc.? */
|
||||
|
||||
entry->osa = (sa_entry_t){
|
||||
.spi = spi,
|
||||
.spi = id->spi,
|
||||
.dst = entry->remote,
|
||||
.protocol = protocol,
|
||||
.lifetime = lifetime->time.life,
|
||||
.protocol = id->proto,
|
||||
.lifetime = data->lifetime->time.life,
|
||||
.encr = {
|
||||
.alg = enc_alg,
|
||||
.key = chunk_clone(enc_key),
|
||||
.alg = data->enc_alg,
|
||||
.key = chunk_clone(data->enc_key),
|
||||
},
|
||||
.integ = {
|
||||
.alg = int_alg,
|
||||
.key = chunk_clone(int_key),
|
||||
.alg = data->int_alg,
|
||||
.key = chunk_clone(data->int_key),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2186,14 +2184,13 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, update_sa, status_t,
|
||||
private_kernel_wfp_ipsec_t *this, uint32_t spi, uint8_t protocol,
|
||||
uint16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
|
||||
bool encap, bool new_encap, mark_t mark)
|
||||
private_kernel_wfp_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_update_sa_t *data)
|
||||
{
|
||||
entry_t *entry;
|
||||
sa_entry_t key = {
|
||||
.dst = dst,
|
||||
.spi = spi,
|
||||
.dst = id->dst,
|
||||
.spi = id->spi,
|
||||
};
|
||||
UINT64 sa_id = 0;
|
||||
IPSEC_SA_CONTEXT1 *ctx;
|
||||
@@ -2233,16 +2230,16 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
||||
DBG1(DBG_KNL, "getting WFP SA context for updated failed: 0x%08x", res);
|
||||
return FAILED;
|
||||
}
|
||||
if (!hosts2traffic(this, new_dst, new_src, &ctx->inboundSa->traffic) ||
|
||||
!hosts2traffic(this, new_dst, new_src, &ctx->outboundSa->traffic))
|
||||
if (!hosts2traffic(this, data->new_dst, data->new_src, &ctx->inboundSa->traffic) ||
|
||||
!hosts2traffic(this, data->new_dst, data->new_src, &ctx->outboundSa->traffic))
|
||||
{
|
||||
FwpmFreeMemory0((void**)&ctx);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if (new_encap != encap)
|
||||
if (data->new_encap != data->encap)
|
||||
{
|
||||
if (new_encap)
|
||||
if (data->new_encap)
|
||||
{
|
||||
ctx->inboundSa->udpEncapsulation = &ports;
|
||||
ctx->outboundSa->udpEncapsulation = &ports;
|
||||
@@ -2273,8 +2270,8 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
||||
|
||||
entry->local->destroy(entry->local);
|
||||
entry->remote->destroy(entry->remote);
|
||||
entry->local = new_dst->clone(new_dst);
|
||||
entry->remote = new_src->clone(new_src);
|
||||
entry->local = data->new_dst->clone(data->new_dst);
|
||||
entry->remote = data->new_src->clone(data->new_src);
|
||||
entry->isa.dst = entry->local;
|
||||
entry->osa.dst = entry->remote;
|
||||
|
||||
@@ -2290,9 +2287,9 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||
private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, mark_t mark, uint64_t *bytes,
|
||||
uint64_t *packets, time_t *time)
|
||||
private_kernel_wfp_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
|
||||
time_t *time)
|
||||
{
|
||||
/* It does not seem that WFP provides any means of getting per-SA traffic
|
||||
* statistics. IPsecGetStatistics0/1() provides global stats, and
|
||||
@@ -2302,13 +2299,13 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, del_sa, status_t,
|
||||
private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, uint16_t cpi, mark_t mark)
|
||||
private_kernel_wfp_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_del_sa_t *data)
|
||||
{
|
||||
entry_t *entry;
|
||||
sa_entry_t key = {
|
||||
.dst = dst,
|
||||
.spi = spi,
|
||||
.dst = id->dst,
|
||||
.spi = id->spi,
|
||||
};
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
@@ -2341,25 +2338,23 @@ METHOD(kernel_ipsec_t, flush_sas, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, add_policy, status_t,
|
||||
private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, mark_t mark,
|
||||
policy_priority_t priority)
|
||||
private_kernel_wfp_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data)
|
||||
{
|
||||
status_t status = SUCCESS;
|
||||
entry_t *entry;
|
||||
sp_entry_t *sp;
|
||||
sa_entry_t key = {
|
||||
.spi = sa->esp.use ? sa->esp.spi : sa->ah.spi,
|
||||
.dst = dst,
|
||||
.spi = data->sa->esp.use ? data->sa->esp.spi : data->sa->ah.spi,
|
||||
.dst = data->dst,
|
||||
};
|
||||
|
||||
if (sa->esp.use && sa->ah.use)
|
||||
if (data->sa->esp.use && data->sa->ah.use)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
switch (data->type)
|
||||
{
|
||||
case POLICY_IPSEC:
|
||||
break;
|
||||
@@ -2368,7 +2363,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
switch (direction)
|
||||
switch (id->dir)
|
||||
{
|
||||
case POLICY_OUT:
|
||||
break;
|
||||
@@ -2380,18 +2375,20 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
switch (priority)
|
||||
switch (data->prio)
|
||||
{
|
||||
case POLICY_PRIORITY_DEFAULT:
|
||||
break;
|
||||
case POLICY_PRIORITY_ROUTED:
|
||||
if (!add_trap(this, sa->reqid, FALSE, src, dst, src_ts, dst_ts))
|
||||
if (!add_trap(this, data->sa->reqid, FALSE, data->src, data->dst,
|
||||
id->src_ts, id->dst_ts))
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
if (sa->mode == MODE_TUNNEL)
|
||||
if (data->sa->mode == MODE_TUNNEL)
|
||||
{
|
||||
if (!add_trap(this, sa->reqid, TRUE, src, dst, src_ts, dst_ts))
|
||||
if (!add_trap(this, data->sa->reqid, TRUE, data->src, data->dst,
|
||||
id->src_ts, id->dst_ts))
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
@@ -2406,14 +2403,14 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
||||
entry = this->osas->get(this->osas, &key);
|
||||
if (entry)
|
||||
{
|
||||
if (sa->mode == MODE_TUNNEL || array_count(entry->sps) == 0)
|
||||
if (data->sa->mode == MODE_TUNNEL || array_count(entry->sps) == 0)
|
||||
{
|
||||
INIT(sp,
|
||||
.src = src_ts->clone(src_ts),
|
||||
.dst = dst_ts->clone(dst_ts),
|
||||
.src = id->src_ts->clone(id->src_ts),
|
||||
.dst = id->dst_ts->clone(id->dst_ts),
|
||||
);
|
||||
array_insert(entry->sps, -1, sp);
|
||||
if (array_count(entry->sps) == sa->policy_count)
|
||||
if (array_count(entry->sps) == data->sa->policy_count)
|
||||
{
|
||||
if (!install(this, entry))
|
||||
{
|
||||
@@ -2442,25 +2439,24 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||
private_kernel_wfp_ipsec_t *this, traffic_selector_t *src_ts,
|
||||
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
||||
time_t *use_time)
|
||||
private_kernel_wfp_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_query_policy_t *data, time_t *use_time)
|
||||
{
|
||||
/* see query_sa() for some notes */
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, del_policy, status_t,
|
||||
private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
|
||||
mark_t mark, policy_priority_t priority)
|
||||
private_kernel_wfp_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data)
|
||||
{
|
||||
if (direction == POLICY_OUT && priority == POLICY_PRIORITY_ROUTED)
|
||||
if (id->dir == POLICY_OUT && data->prio == POLICY_PRIORITY_ROUTED)
|
||||
{
|
||||
if (remove_trap(this, sa->reqid, FALSE, src_ts, dst_ts))
|
||||
if (remove_trap(this, data->sa->reqid, FALSE, id->src_ts,
|
||||
id->dst_ts))
|
||||
{
|
||||
remove_trap(this, sa->reqid, TRUE, src_ts, dst_ts);
|
||||
remove_trap(this, data->sa->reqid, TRUE, id->src_ts,
|
||||
id->dst_ts);
|
||||
return SUCCESS;
|
||||
}
|
||||
return NOT_FOUND;
|
||||
|
||||
@@ -688,13 +688,25 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
|
||||
peer_cfg_t *peer_cfg;
|
||||
char local[32], *remote;
|
||||
host_t *addr;
|
||||
ipsec_mode_t mode = MODE_TUNNEL;
|
||||
lifetime_cfg_t lifetime = {
|
||||
.time = {
|
||||
.life = this->child_rekey * 2,
|
||||
.rekey = this->child_rekey,
|
||||
.jitter = 0
|
||||
}
|
||||
peer_cfg_create_t peer = {
|
||||
.cert_policy = CERT_SEND_IF_ASKED,
|
||||
.unique = UNIQUE_NO,
|
||||
.keyingtries = 1,
|
||||
.rekey_time = this->ike_rekey,
|
||||
.over_time = this->ike_rekey,
|
||||
.no_mobike = TRUE,
|
||||
.dpd = this->dpd_delay,
|
||||
.dpd_timeout = this->dpd_timeout,
|
||||
};
|
||||
child_cfg_create_t child = {
|
||||
.lifetime = {
|
||||
.time = {
|
||||
.life = this->child_rekey * 2,
|
||||
.rekey = this->child_rekey,
|
||||
.jitter = 0
|
||||
},
|
||||
},
|
||||
.mode = MODE_TUNNEL,
|
||||
};
|
||||
|
||||
if (num)
|
||||
@@ -737,14 +749,8 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
|
||||
FRAGMENTATION_NO, 0);
|
||||
}
|
||||
ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal));
|
||||
peer_cfg = peer_cfg_create("load-test", ike_cfg,
|
||||
CERT_SEND_IF_ASKED, UNIQUE_NO, 1, /* keytries */
|
||||
this->ike_rekey, 0, /* rekey, reauth */
|
||||
0, this->ike_rekey, /* jitter, overtime */
|
||||
FALSE, FALSE, TRUE, /* mobike, aggressive, pull */
|
||||
this->dpd_delay, /* dpd_delay */
|
||||
this->dpd_timeout, /* dpd_timeout */
|
||||
FALSE, NULL, NULL);
|
||||
peer_cfg = peer_cfg_create("load-test", ike_cfg, &peer);
|
||||
|
||||
if (this->vip)
|
||||
{
|
||||
peer_cfg->add_virtual_ip(peer_cfg, this->vip->clone(this->vip));
|
||||
@@ -768,17 +774,15 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
|
||||
{
|
||||
if (streq(this->mode, "transport"))
|
||||
{
|
||||
mode = MODE_TRANSPORT;
|
||||
child.mode = MODE_TRANSPORT;
|
||||
}
|
||||
else if (streq(this->mode, "beet"))
|
||||
{
|
||||
mode = MODE_BEET;
|
||||
child.mode = MODE_BEET;
|
||||
}
|
||||
}
|
||||
|
||||
child_cfg = child_cfg_create("load-test", &lifetime, NULL, TRUE, mode,
|
||||
ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
|
||||
0, 0, NULL, NULL, 0);
|
||||
child_cfg = child_cfg_create("load-test", &child);
|
||||
child_cfg->add_proposal(child_cfg, this->esp->clone(this->esp));
|
||||
|
||||
if (num)
|
||||
|
||||
@@ -50,63 +50,52 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, uint32_t reqid, mark_t mark,
|
||||
uint32_t tfc, lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
|
||||
uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
|
||||
uint16_t ipcomp, uint16_t cpi, uint32_t replay_window,
|
||||
bool initiator, bool encap, bool esn, bool inbound, bool update,
|
||||
linked_list_t *src_ts, linked_list_t *dst_ts)
|
||||
private_load_tester_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_add_sa_t *data)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, update_sa, status_t,
|
||||
private_load_tester_ipsec_t *this, uint32_t spi, uint8_t protocol,
|
||||
uint16_t cpi, host_t *src, host_t *dst, host_t *new_src,
|
||||
host_t *new_dst, bool encap, bool new_encap, mark_t mark)
|
||||
private_load_tester_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_update_sa_t *data)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||
private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, mark_t mark,
|
||||
uint64_t *bytes, uint64_t *packets, time_t *time)
|
||||
private_load_tester_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
|
||||
time_t *time)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, del_sa, status_t,
|
||||
private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
|
||||
uint32_t spi, uint8_t protocol, uint16_t cpi, mark_t mark)
|
||||
private_load_tester_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||
kernel_ipsec_del_sa_t *data)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, add_policy, status_t,
|
||||
private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
|
||||
mark_t mark, policy_priority_t priority)
|
||||
private_load_tester_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||
private_load_tester_ipsec_t *this, traffic_selector_t *src_ts,
|
||||
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
||||
time_t *use_time)
|
||||
private_load_tester_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_query_policy_t *data, time_t *use_time)
|
||||
{
|
||||
*use_time = 1;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, del_policy, status_t,
|
||||
private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
|
||||
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
|
||||
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
|
||||
mark_t mark, policy_priority_t priority)
|
||||
private_load_tester_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||
kernel_ipsec_manage_policy_t *data)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -236,12 +236,23 @@ static gboolean initiate_connection(private_maemo_service_t *this,
|
||||
traffic_selector_t *ts;
|
||||
auth_cfg_t *auth;
|
||||
certificate_t *cert;
|
||||
lifetime_cfg_t lifetime = {
|
||||
.time = {
|
||||
.life = 10800, /* 3h */
|
||||
.rekey = 10200, /* 2h50min */
|
||||
.jitter = 300 /* 5min */
|
||||
}
|
||||
peer_cfg_create_t peer = {
|
||||
.cert_policy = CERT_SEND_IF_ASKED,
|
||||
.unique = UNIQUE_REPLACE,
|
||||
.keyingtries = 1,
|
||||
.rekey_time = 36000, /* 10h */
|
||||
.jitter_time = 600, /* 10min */
|
||||
.over_time = 600, /* 10min */
|
||||
};
|
||||
child_cfg_create_t child = {
|
||||
.lifetime = {
|
||||
.time = {
|
||||
.life = 10800, /* 3h */
|
||||
.rekey = 10200, /* 2h50min */
|
||||
.jitter = 300 /* 5min */
|
||||
},
|
||||
},
|
||||
.mode = MODE_TUNNEL,
|
||||
};
|
||||
|
||||
if (this->status == VPN_STATUS_CONNECTED ||
|
||||
@@ -329,14 +340,7 @@ static gboolean initiate_connection(private_maemo_service_t *this,
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
|
||||
|
||||
peer_cfg = peer_cfg_create(this->current, ike_cfg,
|
||||
CERT_SEND_IF_ASKED,
|
||||
UNIQUE_REPLACE, 1, /* keyingtries */
|
||||
36000, 0, /* rekey 10h, reauth none */
|
||||
600, 600, /* jitter, over 10min */
|
||||
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
|
||||
0, 0, /* DPD delay, timeout */
|
||||
FALSE, NULL, NULL); /* mediation */
|
||||
peer_cfg = peer_cfg_create(this->current, ike_cfg, &peer);
|
||||
peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
|
||||
|
||||
auth = auth_cfg_create();
|
||||
@@ -348,9 +352,7 @@ static gboolean initiate_connection(private_maemo_service_t *this,
|
||||
auth->add(auth, AUTH_RULE_IDENTITY, gateway);
|
||||
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
|
||||
|
||||
child_cfg = child_cfg_create(this->current, &lifetime, NULL /* updown */,
|
||||
TRUE, MODE_TUNNEL, ACTION_NONE, ACTION_NONE,
|
||||
ACTION_NONE, FALSE, 0, 0, NULL, NULL, 0);
|
||||
child_cfg = child_cfg_create(this->current, &child);
|
||||
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
|
||||
child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
|
||||
ts = traffic_selector_create_dynamic(0, 0, 65535);
|
||||
|
||||
@@ -82,12 +82,25 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
|
||||
child_cfg_t *child_cfg;
|
||||
chunk_t me, other;
|
||||
char *address, *local_net, *remote_net;
|
||||
lifetime_cfg_t lifetime = {
|
||||
.time = {
|
||||
.life = this->rekey * 60 + this->rekey,
|
||||
.rekey = this->rekey,
|
||||
.jitter = this->rekey
|
||||
}
|
||||
peer_cfg_create_t peer = {
|
||||
.cert_policy = CERT_NEVER_SEND,
|
||||
.unique = UNIQUE_REPLACE,
|
||||
.keyingtries = 1,
|
||||
.rekey_time = this->rekey * 60,
|
||||
.jitter_time = this->rekey * 5,
|
||||
.over_time = this->rekey * 3,
|
||||
.dpd = this->dpd,
|
||||
.mediation = TRUE,
|
||||
};
|
||||
child_cfg_create_t child = {
|
||||
.lifetime = {
|
||||
.time = {
|
||||
.life = this->rekey * 60 + this->rekey,
|
||||
.rekey = this->rekey,
|
||||
.jitter = this->rekey
|
||||
},
|
||||
},
|
||||
.mode = MODE_TUNNEL,
|
||||
};
|
||||
|
||||
/* query mediation server config:
|
||||
@@ -107,14 +120,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
|
||||
address, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
|
||||
med_cfg = peer_cfg_create(
|
||||
"mediation", ike_cfg,
|
||||
CERT_NEVER_SEND, UNIQUE_REPLACE,
|
||||
1, this->rekey*60, 0, /* keytries, rekey, reauth */
|
||||
this->rekey*5, this->rekey*3, /* jitter, overtime */
|
||||
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
|
||||
this->dpd, 0, /* DPD delay, timeout */
|
||||
TRUE, NULL, NULL); /* mediation, med by, peer id */
|
||||
med_cfg = peer_cfg_create("mediation", ike_cfg, &peer);
|
||||
e->destroy(e);
|
||||
|
||||
auth = auth_cfg_create();
|
||||
@@ -144,15 +150,10 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
|
||||
DESTROY_IF(e);
|
||||
return NULL;
|
||||
}
|
||||
peer_cfg = peer_cfg_create(
|
||||
name, this->ike->get_ref(this->ike),
|
||||
CERT_NEVER_SEND, UNIQUE_REPLACE,
|
||||
1, this->rekey*60, 0, /* keytries, rekey, reauth */
|
||||
this->rekey*5, this->rekey*3, /* jitter, overtime */
|
||||
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
|
||||
this->dpd, 0, /* DPD delay, timeout */
|
||||
FALSE, med_cfg, /* mediation, med by */
|
||||
identification_create_from_encoding(ID_KEY_ID, other));
|
||||
peer.mediation = FALSE;
|
||||
peer.mediated_by = med_cfg;
|
||||
peer.peer_id = identification_create_from_encoding(ID_KEY_ID, other);
|
||||
peer_cfg = peer_cfg_create(name, this->ike->get_ref(this->ike), &peer);
|
||||
|
||||
auth = auth_cfg_create();
|
||||
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
|
||||
@@ -165,9 +166,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
|
||||
identification_create_from_encoding(ID_KEY_ID, other));
|
||||
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
|
||||
|
||||
child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
|
||||
ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
|
||||
0, 0, NULL, NULL, 0);
|
||||
child_cfg = child_cfg_create(name, &child);
|
||||
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
|
||||
child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
|
||||
child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
|
||||
@@ -205,12 +204,24 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
|
||||
chunk_t me, other;
|
||||
child_cfg_t *child_cfg;
|
||||
auth_cfg_t *auth;
|
||||
lifetime_cfg_t lifetime = {
|
||||
.time = {
|
||||
.life = this->rekey * 60 + this->rekey,
|
||||
.rekey = this->rekey,
|
||||
.jitter = this->rekey
|
||||
}
|
||||
peer_cfg_create_t peer = {
|
||||
.cert_policy = CERT_NEVER_SEND,
|
||||
.unique = UNIQUE_REPLACE,
|
||||
.keyingtries = 1,
|
||||
.rekey_time = this->rekey * 60,
|
||||
.jitter_time = this->rekey * 5,
|
||||
.over_time = this->rekey * 3,
|
||||
.dpd = this->dpd,
|
||||
};
|
||||
child_cfg_create_t child = {
|
||||
.lifetime = {
|
||||
.time = {
|
||||
.life = this->rekey * 60 + this->rekey,
|
||||
.rekey = this->rekey,
|
||||
.jitter = this->rekey
|
||||
},
|
||||
},
|
||||
.mode = MODE_TUNNEL,
|
||||
};
|
||||
|
||||
DESTROY_IF(this->current);
|
||||
@@ -220,14 +231,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
|
||||
this->current = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
this->current = peer_cfg_create(
|
||||
name, this->ike->get_ref(this->ike),
|
||||
CERT_NEVER_SEND, UNIQUE_REPLACE,
|
||||
1, this->rekey*60, 0, /* keytries, rekey, reauth */
|
||||
this->rekey*5, this->rekey*3, /* jitter, overtime */
|
||||
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
|
||||
this->dpd, 0, /* DPD delay, timeout */
|
||||
FALSE, NULL, NULL); /* mediation, med by, peer id */
|
||||
this->current = peer_cfg_create(name, this->ike->get_ref(this->ike), &peer);
|
||||
|
||||
auth = auth_cfg_create();
|
||||
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
|
||||
@@ -240,9 +244,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
|
||||
identification_create_from_encoding(ID_KEY_ID, other));
|
||||
this->current->add_auth_cfg(this->current, auth, FALSE);
|
||||
|
||||
child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
|
||||
ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
|
||||
0, 0, NULL, NULL, 0);
|
||||
child_cfg = child_cfg_create(name, &child);
|
||||
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
|
||||
child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
|
||||
child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
|
||||
|
||||
@@ -87,14 +87,18 @@ METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
|
||||
|
||||
if (e->enumerate(e, &name))
|
||||
{
|
||||
peer_cfg = peer_cfg_create(
|
||||
name, this->ike->get_ref(this->ike),
|
||||
CERT_NEVER_SEND, UNIQUE_REPLACE,
|
||||
1, this->rekey*60, 0, /* keytries, rekey, reauth */
|
||||
this->rekey*5, this->rekey*3, /* jitter, overtime */
|
||||
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
|
||||
this->dpd, 0, /* DPD delay, timeout */
|
||||
TRUE, NULL, NULL); /* mediation, med by, peer id */
|
||||
peer_cfg_create_t peer = {
|
||||
.cert_policy = CERT_NEVER_SEND,
|
||||
.unique = UNIQUE_REPLACE,
|
||||
.keyingtries = 1,
|
||||
.rekey_time = this->rekey * 60,
|
||||
.jitter_time = this->rekey * 5,
|
||||
.over_time = this->rekey * 3,
|
||||
.dpd = this->dpd,
|
||||
.mediation = TRUE,
|
||||
};
|
||||
peer_cfg = peer_cfg_create(name, this->ike->get_ref(this->ike),
|
||||
&peer);
|
||||
e->destroy(e);
|
||||
|
||||
auth = auth_cfg_create();
|
||||
|
||||
@@ -170,12 +170,22 @@ static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
|
||||
if (e->enumerate(e, &id, &name, &lifetime, &rekeytime, &jitter, &updown,
|
||||
&hostaccess, &mode, &start, &dpd, &close, &ipcomp, &reqid))
|
||||
{
|
||||
lifetime_cfg_t lft = {
|
||||
.time = { .life = lifetime, .rekey = rekeytime, .jitter = jitter }
|
||||
child_cfg_create_t child = {
|
||||
.mode = mode,
|
||||
.reqid = reqid,
|
||||
.ipcomp = ipcomp,
|
||||
.lifetime = {
|
||||
.time = {
|
||||
.life = lifetime, .rekey = rekeytime, .jitter = jitter
|
||||
},
|
||||
},
|
||||
.start_action = start,
|
||||
.dpd_action = dpd,
|
||||
.close_action = close,
|
||||
.updown = updown,
|
||||
.hostaccess = hostaccess,
|
||||
};
|
||||
child_cfg = child_cfg_create(name, &lft, updown, hostaccess, mode,
|
||||
start, dpd, close, ipcomp, 0, reqid,
|
||||
NULL, NULL, 0);
|
||||
child_cfg = child_cfg_create(name, &child);
|
||||
add_esp_proposals(this, child_cfg, id);
|
||||
add_traffic_selectors(this, child_cfg, id);
|
||||
return child_cfg;
|
||||
@@ -290,6 +300,7 @@ static ike_cfg_t* get_ike_cfg_by_id(private_sql_config_t *this, int id)
|
||||
return ike_cfg;
|
||||
}
|
||||
|
||||
#ifdef ME
|
||||
/**
|
||||
* Query a peer config by its id
|
||||
*/
|
||||
@@ -322,6 +333,7 @@ static peer_cfg_t *get_peer_cfg_by_id(private_sql_config_t *this, int id)
|
||||
}
|
||||
return peer_cfg;
|
||||
}
|
||||
#endif /* ME */
|
||||
|
||||
/**
|
||||
* Check if the two IDs match (the first one is optional)
|
||||
@@ -353,7 +365,7 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
|
||||
&mediation, &mediated_by, &p_type, &p_data))
|
||||
{
|
||||
identification_t *local_id, *remote_id, *peer_id = NULL;
|
||||
peer_cfg_t *peer_cfg, *mediated_cfg;
|
||||
peer_cfg_t *peer_cfg, *mediated_cfg = NULL;
|
||||
ike_cfg_t *ike;
|
||||
host_t *vip = NULL;
|
||||
auth_cfg_t *auth;
|
||||
@@ -367,22 +379,38 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
|
||||
continue;
|
||||
}
|
||||
ike = get_ike_cfg_by_id(this, ike_cfg);
|
||||
|
||||
#ifdef ME
|
||||
mediated_cfg = mediated_by ? get_peer_cfg_by_id(this, mediated_by) : NULL;
|
||||
if (p_type)
|
||||
{
|
||||
peer_id = identification_create_from_encoding(p_type, p_data);
|
||||
}
|
||||
#endif
|
||||
if (virtual)
|
||||
{
|
||||
vip = host_create_from_string(virtual, 0);
|
||||
}
|
||||
if (ike)
|
||||
{
|
||||
peer_cfg = peer_cfg_create(
|
||||
name, ike, cert_policy, uniqueid,
|
||||
keyingtries, rekeytime, reauthtime, jitter, overtime,
|
||||
mobike, FALSE, TRUE, dpd_delay, 0,
|
||||
mediation, mediated_cfg, peer_id);
|
||||
peer_cfg_create_t peer = {
|
||||
.cert_policy = cert_policy,
|
||||
.unique = uniqueid,
|
||||
.keyingtries = keyingtries,
|
||||
.rekey_time = rekeytime,
|
||||
.reauth_time = reauthtime,
|
||||
.jitter_time = jitter,
|
||||
.over_time = overtime,
|
||||
.no_mobike = !mobike,
|
||||
.dpd = dpd_delay,
|
||||
#ifdef ME
|
||||
.mediation = mediation,
|
||||
.mediated_by = mediated_cfg,
|
||||
.peer_id = peer_id,
|
||||
#endif /* ME */
|
||||
};
|
||||
|
||||
peer_cfg = peer_cfg_create(name, ike, &peer);
|
||||
if (vip)
|
||||
{
|
||||
peer_cfg->add_virtual_ip(peer_cfg, vip);
|
||||
|
||||
@@ -616,12 +616,17 @@ static mem_pool_t *create_pool_range(char *str)
|
||||
static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
|
||||
stroke_msg_t *msg, ike_cfg_t *ike_cfg)
|
||||
{
|
||||
identification_t *peer_id = NULL;
|
||||
peer_cfg_t *mediated_by = NULL;
|
||||
unique_policy_t unique;
|
||||
uint32_t rekey = 0, reauth = 0, over, jitter;
|
||||
peer_cfg_t *peer_cfg;
|
||||
auth_cfg_t *auth_cfg;
|
||||
peer_cfg_create_t peer = {
|
||||
.cert_policy = msg->add_conn.me.sendcert,
|
||||
.keyingtries = msg->add_conn.rekey.tries,
|
||||
.no_mobike = !msg->add_conn.mobike,
|
||||
.aggressive = msg->add_conn.aggressive,
|
||||
.push_mode = msg->add_conn.pushmode,
|
||||
.dpd = msg->add_conn.dpd.delay,
|
||||
.dpd_timeout = msg->add_conn.dpd.timeout,
|
||||
};
|
||||
|
||||
#ifdef ME
|
||||
if (msg->add_conn.ikeme.mediation && msg->add_conn.ikeme.mediated_by)
|
||||
@@ -633,14 +638,17 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
|
||||
|
||||
if (msg->add_conn.ikeme.mediation)
|
||||
{
|
||||
peer.mediation = TRUE;
|
||||
/* force unique connections for mediation connections */
|
||||
msg->add_conn.unique = 1;
|
||||
}
|
||||
|
||||
if (msg->add_conn.ikeme.mediated_by)
|
||||
{
|
||||
mediated_by = charon->backends->get_peer_cfg_by_name(charon->backends,
|
||||
msg->add_conn.ikeme.mediated_by);
|
||||
peer_cfg_t *mediated_by;
|
||||
|
||||
mediated_by = charon->backends->get_peer_cfg_by_name(
|
||||
charon->backends, msg->add_conn.ikeme.mediated_by);
|
||||
if (!mediated_by)
|
||||
{
|
||||
DBG1(DBG_CFG, "mediation connection '%s' not found, aborting",
|
||||
@@ -655,58 +663,55 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
|
||||
mediated_by->destroy(mediated_by);
|
||||
return NULL;
|
||||
}
|
||||
peer.mediated_by = mediated_by;
|
||||
if (msg->add_conn.ikeme.peerid)
|
||||
{
|
||||
peer_id = identification_create_from_string(msg->add_conn.ikeme.peerid);
|
||||
peer.peer_id = identification_create_from_string(
|
||||
msg->add_conn.ikeme.peerid);
|
||||
}
|
||||
else if (msg->add_conn.other.id)
|
||||
{
|
||||
peer_id = identification_create_from_string(msg->add_conn.other.id);
|
||||
peer.peer_id = identification_create_from_string(
|
||||
msg->add_conn.other.id);
|
||||
}
|
||||
}
|
||||
#endif /* ME */
|
||||
|
||||
jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100;
|
||||
over = msg->add_conn.rekey.margin;
|
||||
peer.jitter_time = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100;
|
||||
peer.over_time = msg->add_conn.rekey.margin;
|
||||
if (msg->add_conn.rekey.reauth)
|
||||
{
|
||||
reauth = msg->add_conn.rekey.ike_lifetime - over;
|
||||
peer.reauth_time = msg->add_conn.rekey.ike_lifetime - peer.over_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
rekey = msg->add_conn.rekey.ike_lifetime - over;
|
||||
peer.rekey_time = msg->add_conn.rekey.ike_lifetime - peer.over_time;
|
||||
}
|
||||
switch (msg->add_conn.unique)
|
||||
{
|
||||
case 1: /* yes */
|
||||
case 2: /* replace */
|
||||
unique = UNIQUE_REPLACE;
|
||||
peer.unique = UNIQUE_REPLACE;
|
||||
break;
|
||||
case 3: /* keep */
|
||||
unique = UNIQUE_KEEP;
|
||||
peer.unique = UNIQUE_KEEP;
|
||||
break;
|
||||
case 4: /* never */
|
||||
unique = UNIQUE_NEVER;
|
||||
peer.unique = UNIQUE_NEVER;
|
||||
break;
|
||||
default: /* no */
|
||||
unique = UNIQUE_NO;
|
||||
peer.unique = UNIQUE_NO;
|
||||
break;
|
||||
}
|
||||
if (msg->add_conn.dpd.action == 0)
|
||||
{ /* dpdaction=none disables DPD */
|
||||
msg->add_conn.dpd.delay = 0;
|
||||
peer.dpd = 0;
|
||||
}
|
||||
|
||||
/* other.sourceip is managed in stroke_attributes. If it is set, we define
|
||||
* the pool name as the connection name, which the attribute provider
|
||||
* uses to serve pool addresses. */
|
||||
peer_cfg = peer_cfg_create(msg->add_conn.name, ike_cfg,
|
||||
msg->add_conn.me.sendcert, unique,
|
||||
msg->add_conn.rekey.tries, rekey, reauth, jitter, over,
|
||||
msg->add_conn.mobike, msg->add_conn.aggressive,
|
||||
msg->add_conn.pushmode == 0,
|
||||
msg->add_conn.dpd.delay, msg->add_conn.dpd.timeout,
|
||||
msg->add_conn.ikeme.mediation, mediated_by, peer_id);
|
||||
peer_cfg = peer_cfg_create(msg->add_conn.name, ike_cfg, &peer);
|
||||
|
||||
if (msg->add_conn.other.sourceip)
|
||||
{
|
||||
@@ -1070,45 +1075,50 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
|
||||
stroke_msg_t *msg)
|
||||
{
|
||||
child_cfg_t *child_cfg;
|
||||
lifetime_cfg_t lifetime = {
|
||||
.time = {
|
||||
.life = msg->add_conn.rekey.ipsec_lifetime,
|
||||
.rekey = msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
|
||||
.jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100
|
||||
child_cfg_create_t child = {
|
||||
.lifetime = {
|
||||
.time = {
|
||||
.life = msg->add_conn.rekey.ipsec_lifetime,
|
||||
.rekey = msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
|
||||
.jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100
|
||||
},
|
||||
.bytes = {
|
||||
.life = msg->add_conn.rekey.life_bytes,
|
||||
.rekey = msg->add_conn.rekey.life_bytes - msg->add_conn.rekey.margin_bytes,
|
||||
.jitter = msg->add_conn.rekey.margin_bytes * msg->add_conn.rekey.fuzz / 100
|
||||
},
|
||||
.packets = {
|
||||
.life = msg->add_conn.rekey.life_packets,
|
||||
.rekey = msg->add_conn.rekey.life_packets - msg->add_conn.rekey.margin_packets,
|
||||
.jitter = msg->add_conn.rekey.margin_packets * msg->add_conn.rekey.fuzz / 100
|
||||
},
|
||||
},
|
||||
.bytes = {
|
||||
.life = msg->add_conn.rekey.life_bytes,
|
||||
.rekey = msg->add_conn.rekey.life_bytes - msg->add_conn.rekey.margin_bytes,
|
||||
.jitter = msg->add_conn.rekey.margin_bytes * msg->add_conn.rekey.fuzz / 100
|
||||
.mark_in = {
|
||||
.value = msg->add_conn.mark_in.value,
|
||||
.mask = msg->add_conn.mark_in.mask
|
||||
},
|
||||
.packets = {
|
||||
.life = msg->add_conn.rekey.life_packets,
|
||||
.rekey = msg->add_conn.rekey.life_packets - msg->add_conn.rekey.margin_packets,
|
||||
.jitter = msg->add_conn.rekey.margin_packets * msg->add_conn.rekey.fuzz / 100
|
||||
}
|
||||
};
|
||||
mark_t mark_in = {
|
||||
.value = msg->add_conn.mark_in.value,
|
||||
.mask = msg->add_conn.mark_in.mask
|
||||
};
|
||||
mark_t mark_out = {
|
||||
.value = msg->add_conn.mark_out.value,
|
||||
.mask = msg->add_conn.mark_out.mask
|
||||
.mark_out = {
|
||||
.value = msg->add_conn.mark_out.value,
|
||||
.mask = msg->add_conn.mark_out.mask
|
||||
},
|
||||
.reqid = msg->add_conn.reqid,
|
||||
.mode = msg->add_conn.mode,
|
||||
.proxy_mode = msg->add_conn.proxy_mode,
|
||||
.ipcomp = msg->add_conn.ipcomp,
|
||||
.tfc = msg->add_conn.tfc,
|
||||
.inactivity = msg->add_conn.inactivity,
|
||||
.dpd_action = map_action(msg->add_conn.dpd.action),
|
||||
.close_action = map_action(msg->add_conn.close_action),
|
||||
.updown = msg->add_conn.me.updown,
|
||||
.hostaccess = msg->add_conn.me.hostaccess,
|
||||
.suppress_policies = !msg->add_conn.install_policy,
|
||||
};
|
||||
|
||||
child_cfg = child_cfg_create(
|
||||
msg->add_conn.name, &lifetime, msg->add_conn.me.updown,
|
||||
msg->add_conn.me.hostaccess, msg->add_conn.mode, ACTION_NONE,
|
||||
map_action(msg->add_conn.dpd.action),
|
||||
map_action(msg->add_conn.close_action), msg->add_conn.ipcomp,
|
||||
msg->add_conn.inactivity, msg->add_conn.reqid,
|
||||
&mark_in, &mark_out, msg->add_conn.tfc);
|
||||
child_cfg = child_cfg_create(msg->add_conn.name, &child);
|
||||
if (msg->add_conn.replay_window != -1)
|
||||
{
|
||||
child_cfg->set_replay_window(child_cfg, msg->add_conn.replay_window);
|
||||
}
|
||||
child_cfg->set_mipv6_options(child_cfg, msg->add_conn.proxy_mode,
|
||||
msg->add_conn.install_policy);
|
||||
add_ts(this, &msg->add_conn.me, child_cfg, TRUE);
|
||||
add_ts(this, &msg->add_conn.other, child_cfg, FALSE);
|
||||
|
||||
|
||||
@@ -126,12 +126,23 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
|
||||
child_cfg_t *child_cfg;
|
||||
ike_cfg_t *ike_cfg;
|
||||
auth_cfg_t *auth;
|
||||
lifetime_cfg_t lifetime = {
|
||||
.time = {
|
||||
.life = create_rekey(esp_rekey) + 300,
|
||||
.rekey = create_rekey(esp_rekey),
|
||||
.jitter = 300
|
||||
}
|
||||
peer_cfg_create_t peer = {
|
||||
.cert_policy = CERT_SEND_IF_ASKED,
|
||||
.unique = UNIQUE_NO,
|
||||
.keyingtries = 1,
|
||||
.jitter_time = 1800,
|
||||
.over_time = 900,
|
||||
.dpd = 60,
|
||||
};
|
||||
child_cfg_create_t child = {
|
||||
.lifetime = {
|
||||
.time = {
|
||||
.life = create_rekey(esp_rekey) + 300,
|
||||
.rekey = create_rekey(esp_rekey),
|
||||
.jitter = 300
|
||||
},
|
||||
},
|
||||
.mode = MODE_TUNNEL,
|
||||
};
|
||||
|
||||
/* defaults */
|
||||
@@ -157,13 +168,8 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
|
||||
remote_addr, IKEV2_UDP_PORT,
|
||||
FRAGMENTATION_NO, 0);
|
||||
ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE));
|
||||
this->peer_cfg = peer_cfg_create(
|
||||
name, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_NO,
|
||||
1, create_rekey(ike_rekey), 0, /* keytries, rekey, reauth */
|
||||
1800, 900, /* jitter, overtime */
|
||||
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
|
||||
60, 0, /* DPD delay, timeout */
|
||||
FALSE, NULL, NULL); /* mediation, med by, peer id */
|
||||
peer.rekey_time = create_rekey(ike_rekey);
|
||||
this->peer_cfg = peer_cfg_create(name, ike_cfg, &peer);
|
||||
auth = auth_cfg_create();
|
||||
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
|
||||
auth->add(auth, AUTH_RULE_IDENTITY,
|
||||
@@ -179,9 +185,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
|
||||
}
|
||||
this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, FALSE);
|
||||
|
||||
child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
|
||||
ACTION_NONE, ACTION_NONE, ACTION_NONE,
|
||||
FALSE, 0, 0, NULL, NULL, 0);
|
||||
child_cfg = child_cfg_create(name, &child);
|
||||
child_cfg->add_proposal(child_cfg, create_proposal(esp_proposal, PROTO_ESP));
|
||||
child_cfg->add_traffic_selector(child_cfg, TRUE, create_ts(local_net));
|
||||
child_cfg->add_traffic_selector(child_cfg, FALSE, create_ts(remote_net));
|
||||
|
||||
@@ -206,7 +206,9 @@ static job_requeue_t add_exclude_async(entry_t *entry)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
child_cfg_t *child_cfg;
|
||||
lifetime_cfg_t lft = { .time = { .life = 0 } };
|
||||
child_cfg_create_t child = {
|
||||
.mode = MODE_PASS,
|
||||
};
|
||||
ike_sa_t *ike_sa;
|
||||
char name[128];
|
||||
host_t *host;
|
||||
@@ -216,9 +218,7 @@ static job_requeue_t add_exclude_async(entry_t *entry)
|
||||
{
|
||||
create_shunt_name(ike_sa, entry->ts, name, sizeof(name));
|
||||
|
||||
child_cfg = child_cfg_create(name, &lft, NULL, TRUE, MODE_PASS,
|
||||
ACTION_NONE, ACTION_NONE, ACTION_NONE,
|
||||
FALSE, 0, 0, NULL, NULL, FALSE);
|
||||
child_cfg = child_cfg_create(name, &child);
|
||||
child_cfg->add_traffic_selector(child_cfg, FALSE,
|
||||
entry->ts->clone(entry->ts));
|
||||
host = ike_sa->get_my_host(ike_sa);
|
||||
|
||||
@@ -422,24 +422,12 @@ static void free_peer_data(peer_data_t *data)
|
||||
*/
|
||||
typedef struct {
|
||||
request_data_t *request;
|
||||
lifetime_cfg_t lft;
|
||||
char* updown;
|
||||
bool hostaccess;
|
||||
bool ipcomp;
|
||||
bool policies;
|
||||
ipsec_mode_t mode;
|
||||
uint32_t replay_window;
|
||||
action_t dpd_action;
|
||||
action_t start_action;
|
||||
action_t close_action;
|
||||
uint32_t reqid;
|
||||
uint32_t tfc;
|
||||
mark_t mark_in;
|
||||
mark_t mark_out;
|
||||
uint64_t inactivity;
|
||||
linked_list_t *proposals;
|
||||
linked_list_t *local_ts;
|
||||
linked_list_t *remote_ts;
|
||||
uint32_t replay_window;
|
||||
bool policies;
|
||||
child_cfg_create_t cfg;
|
||||
} child_data_t;
|
||||
|
||||
/**
|
||||
@@ -447,35 +435,39 @@ typedef struct {
|
||||
*/
|
||||
static void log_child_data(child_data_t *data, char *name)
|
||||
{
|
||||
child_cfg_create_t *cfg = &data->cfg;
|
||||
|
||||
DBG2(DBG_CFG, " child %s:", name);
|
||||
DBG2(DBG_CFG, " rekey_time = %llu", data->lft.time.rekey);
|
||||
DBG2(DBG_CFG, " life_time = %llu", data->lft.time.life);
|
||||
DBG2(DBG_CFG, " rand_time = %llu", data->lft.time.jitter);
|
||||
DBG2(DBG_CFG, " rekey_bytes = %llu", data->lft.bytes.rekey);
|
||||
DBG2(DBG_CFG, " life_bytes = %llu", data->lft.bytes.life);
|
||||
DBG2(DBG_CFG, " rand_bytes = %llu", data->lft.bytes.jitter);
|
||||
DBG2(DBG_CFG, " rekey_packets = %llu", data->lft.packets.rekey);
|
||||
DBG2(DBG_CFG, " life_packets = %llu", data->lft.packets.life);
|
||||
DBG2(DBG_CFG, " rand_packets = %llu", data->lft.packets.jitter);
|
||||
DBG2(DBG_CFG, " updown = %s", data->updown);
|
||||
DBG2(DBG_CFG, " hostaccess = %u", data->hostaccess);
|
||||
DBG2(DBG_CFG, " ipcomp = %u", data->ipcomp);
|
||||
DBG2(DBG_CFG, " mode = %N", ipsec_mode_names, data->mode);
|
||||
DBG2(DBG_CFG, " rekey_time = %llu", cfg->lifetime.time.rekey);
|
||||
DBG2(DBG_CFG, " life_time = %llu", cfg->lifetime.time.life);
|
||||
DBG2(DBG_CFG, " rand_time = %llu", cfg->lifetime.time.jitter);
|
||||
DBG2(DBG_CFG, " rekey_bytes = %llu", cfg->lifetime.bytes.rekey);
|
||||
DBG2(DBG_CFG, " life_bytes = %llu", cfg->lifetime.bytes.life);
|
||||
DBG2(DBG_CFG, " rand_bytes = %llu", cfg->lifetime.bytes.jitter);
|
||||
DBG2(DBG_CFG, " rekey_packets = %llu", cfg->lifetime.packets.rekey);
|
||||
DBG2(DBG_CFG, " life_packets = %llu", cfg->lifetime.packets.life);
|
||||
DBG2(DBG_CFG, " rand_packets = %llu", cfg->lifetime.packets.jitter);
|
||||
DBG2(DBG_CFG, " updown = %s", cfg->updown);
|
||||
DBG2(DBG_CFG, " hostaccess = %u", cfg->hostaccess);
|
||||
DBG2(DBG_CFG, " ipcomp = %u", cfg->ipcomp);
|
||||
DBG2(DBG_CFG, " mode = %N", ipsec_mode_names, cfg->mode);
|
||||
DBG2(DBG_CFG, " policies = %u", data->policies);
|
||||
if (data->replay_window != REPLAY_UNDEFINED)
|
||||
{
|
||||
DBG2(DBG_CFG, " replay_window = %u", data->replay_window);
|
||||
}
|
||||
DBG2(DBG_CFG, " dpd_action = %N", action_names, data->dpd_action);
|
||||
DBG2(DBG_CFG, " start_action = %N", action_names, data->start_action);
|
||||
DBG2(DBG_CFG, " close_action = %N", action_names, data->close_action);
|
||||
DBG2(DBG_CFG, " reqid = %u", data->reqid);
|
||||
DBG2(DBG_CFG, " tfc = %d", data->tfc);
|
||||
DBG2(DBG_CFG, " dpd_action = %N", action_names, cfg->dpd_action);
|
||||
DBG2(DBG_CFG, " start_action = %N", action_names, cfg->start_action);
|
||||
DBG2(DBG_CFG, " close_action = %N", action_names, cfg->close_action);
|
||||
DBG2(DBG_CFG, " reqid = %u", cfg->reqid);
|
||||
DBG2(DBG_CFG, " tfc = %d", cfg->tfc);
|
||||
DBG2(DBG_CFG, " priority = %d", cfg->priority);
|
||||
DBG2(DBG_CFG, " interface = %s", cfg->interface);
|
||||
DBG2(DBG_CFG, " mark_in = %u/%u",
|
||||
data->mark_in.value, data->mark_in.mask);
|
||||
cfg->mark_in.value, cfg->mark_in.mask);
|
||||
DBG2(DBG_CFG, " mark_out = %u/%u",
|
||||
data->mark_out.value, data->mark_out.mask);
|
||||
DBG2(DBG_CFG, " inactivity = %llu", data->inactivity);
|
||||
cfg->mark_out.value, cfg->mark_out.mask);
|
||||
DBG2(DBG_CFG, " inactivity = %llu", cfg->inactivity);
|
||||
DBG2(DBG_CFG, " proposals = %#P", data->proposals);
|
||||
DBG2(DBG_CFG, " local_ts = %#R", data->local_ts);
|
||||
DBG2(DBG_CFG, " remote_ts = %#R", data->remote_ts);
|
||||
@@ -492,7 +484,8 @@ static void free_child_data(child_data_t *data)
|
||||
offsetof(traffic_selector_t, destroy));
|
||||
data->remote_ts->destroy_offset(data->remote_ts,
|
||||
offsetof(traffic_selector_t, destroy));
|
||||
free(data->updown);
|
||||
free(data->cfg.updown);
|
||||
free(data->cfg.interface);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1327,29 +1320,31 @@ CALLBACK(child_kv, bool,
|
||||
child_data_t *child, vici_message_t *message, char *name, chunk_t value)
|
||||
{
|
||||
parse_rule_t rules[] = {
|
||||
{ "updown", parse_string, &child->updown },
|
||||
{ "hostaccess", parse_bool, &child->hostaccess },
|
||||
{ "mode", parse_mode, &child->mode },
|
||||
{ "policies", parse_bool, &child->policies },
|
||||
{ "replay_window", parse_uint32, &child->replay_window },
|
||||
{ "rekey_time", parse_time, &child->lft.time.rekey },
|
||||
{ "life_time", parse_time, &child->lft.time.life },
|
||||
{ "rand_time", parse_time, &child->lft.time.jitter },
|
||||
{ "rekey_bytes", parse_bytes, &child->lft.bytes.rekey },
|
||||
{ "life_bytes", parse_bytes, &child->lft.bytes.life },
|
||||
{ "rand_bytes", parse_bytes, &child->lft.bytes.jitter },
|
||||
{ "rekey_packets", parse_uint64, &child->lft.packets.rekey },
|
||||
{ "life_packets", parse_uint64, &child->lft.packets.life },
|
||||
{ "rand_packets", parse_uint64, &child->lft.packets.jitter },
|
||||
{ "dpd_action", parse_action, &child->dpd_action },
|
||||
{ "start_action", parse_action, &child->start_action },
|
||||
{ "close_action", parse_action, &child->close_action },
|
||||
{ "ipcomp", parse_bool, &child->ipcomp },
|
||||
{ "inactivity", parse_time, &child->inactivity },
|
||||
{ "reqid", parse_uint32, &child->reqid },
|
||||
{ "mark_in", parse_mark, &child->mark_in },
|
||||
{ "mark_out", parse_mark, &child->mark_out },
|
||||
{ "tfc_padding", parse_tfc, &child->tfc },
|
||||
{ "updown", parse_string, &child->cfg.updown },
|
||||
{ "hostaccess", parse_bool, &child->cfg.hostaccess },
|
||||
{ "mode", parse_mode, &child->cfg.mode },
|
||||
{ "policies", parse_bool, &child->policies },
|
||||
{ "replay_window", parse_uint32, &child->replay_window },
|
||||
{ "rekey_time", parse_time, &child->cfg.lifetime.time.rekey },
|
||||
{ "life_time", parse_time, &child->cfg.lifetime.time.life },
|
||||
{ "rand_time", parse_time, &child->cfg.lifetime.time.jitter },
|
||||
{ "rekey_bytes", parse_bytes, &child->cfg.lifetime.bytes.rekey },
|
||||
{ "life_bytes", parse_bytes, &child->cfg.lifetime.bytes.life },
|
||||
{ "rand_bytes", parse_bytes, &child->cfg.lifetime.bytes.jitter },
|
||||
{ "rekey_packets", parse_uint64, &child->cfg.lifetime.packets.rekey },
|
||||
{ "life_packets", parse_uint64, &child->cfg.lifetime.packets.life },
|
||||
{ "rand_packets", parse_uint64, &child->cfg.lifetime.packets.jitter },
|
||||
{ "dpd_action", parse_action, &child->cfg.dpd_action },
|
||||
{ "start_action", parse_action, &child->cfg.start_action },
|
||||
{ "close_action", parse_action, &child->cfg.close_action },
|
||||
{ "ipcomp", parse_bool, &child->cfg.ipcomp },
|
||||
{ "inactivity", parse_time, &child->cfg.inactivity },
|
||||
{ "reqid", parse_uint32, &child->cfg.reqid },
|
||||
{ "mark_in", parse_mark, &child->cfg.mark_in },
|
||||
{ "mark_out", parse_mark, &child->cfg.mark_out },
|
||||
{ "tfc_padding", parse_tfc, &child->cfg.tfc },
|
||||
{ "priority", parse_uint32, &child->cfg.priority },
|
||||
{ "interface", parse_string, &child->cfg.interface },
|
||||
};
|
||||
|
||||
return parse_rules(rules, countof(rules), name, value,
|
||||
@@ -1430,6 +1425,51 @@ CALLBACK(peer_kv, bool,
|
||||
&peer->request->reply);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and update lifetimes
|
||||
*/
|
||||
static void check_lifetimes(lifetime_cfg_t *lft)
|
||||
{
|
||||
/* if no hard lifetime specified, add one at soft lifetime + 10% */
|
||||
if (lft->time.life == LFT_UNDEFINED)
|
||||
{
|
||||
lft->time.life = lft->time.rekey * 110 / 100;
|
||||
}
|
||||
if (lft->bytes.life == LFT_UNDEFINED)
|
||||
{
|
||||
lft->bytes.life = lft->bytes.rekey * 110 / 100;
|
||||
}
|
||||
if (lft->packets.life == LFT_UNDEFINED)
|
||||
{
|
||||
lft->packets.life = lft->packets.rekey * 110 / 100;
|
||||
}
|
||||
/* if no soft lifetime specified, add one at hard lifetime - 10% */
|
||||
if (lft->bytes.rekey == LFT_UNDEFINED)
|
||||
{
|
||||
lft->bytes.rekey = lft->bytes.life * 90 / 100;
|
||||
}
|
||||
if (lft->packets.rekey == LFT_UNDEFINED)
|
||||
{
|
||||
lft->packets.rekey = lft->packets.life * 90 / 100;
|
||||
}
|
||||
/* if no rand time defined, use difference of hard and soft */
|
||||
if (lft->time.jitter == LFT_UNDEFINED)
|
||||
{
|
||||
lft->time.jitter = lft->time.life -
|
||||
min(lft->time.life, lft->time.rekey);
|
||||
}
|
||||
if (lft->bytes.jitter == LFT_UNDEFINED)
|
||||
{
|
||||
lft->bytes.jitter = lft->bytes.life -
|
||||
min(lft->bytes.life, lft->bytes.rekey);
|
||||
}
|
||||
if (lft->packets.jitter == LFT_UNDEFINED)
|
||||
{
|
||||
lft->packets.jitter = lft->packets.life -
|
||||
min(lft->packets.life, lft->packets.rekey);
|
||||
}
|
||||
}
|
||||
|
||||
CALLBACK(children_sn, bool,
|
||||
peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx,
|
||||
char *name)
|
||||
@@ -1439,29 +1479,28 @@ CALLBACK(children_sn, bool,
|
||||
.proposals = linked_list_create(),
|
||||
.local_ts = linked_list_create(),
|
||||
.remote_ts = linked_list_create(),
|
||||
.mode = MODE_TUNNEL,
|
||||
.policies = TRUE,
|
||||
.replay_window = REPLAY_UNDEFINED,
|
||||
.dpd_action = ACTION_NONE,
|
||||
.start_action = ACTION_NONE,
|
||||
.close_action = ACTION_NONE,
|
||||
.lft = {
|
||||
.time = {
|
||||
.rekey = LFT_DEFAULT_CHILD_REKEY,
|
||||
.life = LFT_UNDEFINED,
|
||||
.jitter = LFT_UNDEFINED,
|
||||
.cfg = {
|
||||
.mode = MODE_TUNNEL,
|
||||
.lifetime = {
|
||||
.time = {
|
||||
.rekey = LFT_DEFAULT_CHILD_REKEY,
|
||||
.life = LFT_UNDEFINED,
|
||||
.jitter = LFT_UNDEFINED,
|
||||
},
|
||||
.bytes = {
|
||||
.rekey = LFT_UNDEFINED,
|
||||
.life = LFT_UNDEFINED,
|
||||
.jitter = LFT_UNDEFINED,
|
||||
},
|
||||
.packets = {
|
||||
.rekey = LFT_UNDEFINED,
|
||||
.life = LFT_UNDEFINED,
|
||||
.jitter = LFT_UNDEFINED,
|
||||
},
|
||||
},
|
||||
.bytes = {
|
||||
.rekey = LFT_UNDEFINED,
|
||||
.life = LFT_UNDEFINED,
|
||||
.jitter = LFT_UNDEFINED,
|
||||
},
|
||||
.packets = {
|
||||
.rekey = LFT_UNDEFINED,
|
||||
.life = LFT_UNDEFINED,
|
||||
.jitter = LFT_UNDEFINED,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
child_cfg_t *cfg;
|
||||
proposal_t *proposal;
|
||||
@@ -1496,55 +1535,13 @@ CALLBACK(children_sn, bool,
|
||||
child.proposals->insert_last(child.proposals, proposal);
|
||||
}
|
||||
}
|
||||
child.cfg.suppress_policies = !child.policies;
|
||||
|
||||
/* if no hard lifetime specified, add one at soft lifetime + 10% */
|
||||
if (child.lft.time.life == LFT_UNDEFINED)
|
||||
{
|
||||
child.lft.time.life = child.lft.time.rekey * 110 / 100;
|
||||
}
|
||||
if (child.lft.bytes.life == LFT_UNDEFINED)
|
||||
{
|
||||
child.lft.bytes.life = child.lft.bytes.rekey * 110 / 100;
|
||||
}
|
||||
if (child.lft.packets.life == LFT_UNDEFINED)
|
||||
{
|
||||
child.lft.packets.life = child.lft.packets.rekey * 110 / 100;
|
||||
}
|
||||
/* if no soft lifetime specified, add one at hard lifetime - 10% */
|
||||
if (child.lft.bytes.rekey == LFT_UNDEFINED)
|
||||
{
|
||||
child.lft.bytes.rekey = child.lft.bytes.life * 90 / 100;
|
||||
}
|
||||
if (child.lft.packets.rekey == LFT_UNDEFINED)
|
||||
{
|
||||
child.lft.packets.rekey = child.lft.packets.life * 90 / 100;
|
||||
}
|
||||
/* if no rand time defined, use difference of hard and soft */
|
||||
if (child.lft.time.jitter == LFT_UNDEFINED)
|
||||
{
|
||||
child.lft.time.jitter = child.lft.time.life -
|
||||
min(child.lft.time.life, child.lft.time.rekey);
|
||||
}
|
||||
if (child.lft.bytes.jitter == LFT_UNDEFINED)
|
||||
{
|
||||
child.lft.bytes.jitter = child.lft.bytes.life -
|
||||
min(child.lft.bytes.life, child.lft.bytes.rekey);
|
||||
}
|
||||
if (child.lft.packets.jitter == LFT_UNDEFINED)
|
||||
{
|
||||
child.lft.packets.jitter = child.lft.packets.life -
|
||||
min(child.lft.packets.life, child.lft.packets.rekey);
|
||||
}
|
||||
check_lifetimes(&child.cfg.lifetime);
|
||||
|
||||
log_child_data(&child, name);
|
||||
|
||||
cfg = child_cfg_create(name, &child.lft, child.updown,
|
||||
child.hostaccess, child.mode, child.start_action,
|
||||
child.dpd_action, child.close_action, child.ipcomp,
|
||||
child.inactivity, child.reqid, &child.mark_in,
|
||||
&child.mark_out, child.tfc);
|
||||
|
||||
cfg->set_mipv6_options(cfg, FALSE, child.policies);
|
||||
cfg = child_cfg_create(name, &child.cfg);
|
||||
|
||||
if (child.replay_window != REPLAY_UNDEFINED)
|
||||
{
|
||||
@@ -1987,6 +1984,7 @@ CALLBACK(config_sn, bool,
|
||||
.rand_time = LFT_UNDEFINED,
|
||||
};
|
||||
enumerator_t *enumerator;
|
||||
peer_cfg_create_t cfg;
|
||||
peer_cfg_t *peer_cfg;
|
||||
ike_cfg_t *ike_cfg;
|
||||
child_cfg_t *child_cfg;
|
||||
@@ -2083,12 +2081,22 @@ CALLBACK(config_sn, bool,
|
||||
peer.local_addrs, peer.local_port,
|
||||
peer.remote_addrs, peer.remote_port,
|
||||
peer.fragmentation, 0);
|
||||
peer_cfg = peer_cfg_create(name, ike_cfg, peer.send_cert, peer.unique,
|
||||
peer.keyingtries, peer.rekey_time, peer.reauth_time,
|
||||
peer.rand_time, peer.over_time, peer.mobike,
|
||||
peer.aggressive, peer.pull,
|
||||
peer.dpd_delay, peer.dpd_timeout,
|
||||
FALSE, NULL, NULL);
|
||||
|
||||
cfg = (peer_cfg_create_t){
|
||||
.cert_policy = peer.send_cert,
|
||||
.unique = peer.unique,
|
||||
.keyingtries = peer.keyingtries,
|
||||
.rekey_time = peer.rekey_time,
|
||||
.reauth_time = peer.reauth_time,
|
||||
.jitter_time = peer.rand_time,
|
||||
.over_time = peer.over_time,
|
||||
.no_mobike = !peer.mobike,
|
||||
.aggressive = peer.aggressive,
|
||||
.push_mode = !peer.pull,
|
||||
.dpd = peer.dpd_delay,
|
||||
.dpd_timeout = peer.dpd_timeout,
|
||||
};
|
||||
peer_cfg = peer_cfg_create(name, ike_cfg, &cfg);
|
||||
|
||||
while (peer.local->remove_first(peer.local,
|
||||
(void**)&auth) == SUCCESS)
|
||||
|
||||
@@ -682,7 +682,8 @@ CALLBACK(list_conns, vici_message_t*,
|
||||
peer_cfg_t *peer_cfg;
|
||||
ike_cfg_t *ike_cfg;
|
||||
child_cfg_t *child_cfg;
|
||||
char *ike, *str;
|
||||
char *ike, *str, *interface;
|
||||
uint32_t manual_prio;
|
||||
linked_list_t *list;
|
||||
traffic_selector_t *ts;
|
||||
vici_builder_t *b;
|
||||
@@ -761,6 +762,18 @@ CALLBACK(list_conns, vici_message_t*,
|
||||
list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
|
||||
b->end_list(b /* remote-ts */);
|
||||
|
||||
interface = child_cfg->get_interface(child_cfg);
|
||||
if (interface)
|
||||
{
|
||||
b->add_kv(b, "interface", "%s", interface);
|
||||
}
|
||||
|
||||
manual_prio = child_cfg->get_manual_prio(child_cfg);
|
||||
if (manual_prio)
|
||||
{
|
||||
b->add_kv(b, "priority", "%u", manual_prio);
|
||||
}
|
||||
|
||||
b->end_section(b);
|
||||
}
|
||||
children->destroy(children);
|
||||
|
||||
+248
-80
@@ -1,9 +1,10 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2015 Tobias Brunner
|
||||
* Coypright (C) 2016 Andreas Steffen
|
||||
* Copyright (C) 2006-2016 Tobias Brunner
|
||||
* Copyright (C) 2005-2008 Martin Willi
|
||||
* Copyright (C) 2006 Daniel Roethlisberger
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -468,10 +469,17 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
|
||||
{
|
||||
if (this->my_spi)
|
||||
{
|
||||
status = charon->kernel->query_sa(charon->kernel, this->other_addr,
|
||||
this->my_addr, this->my_spi,
|
||||
proto_ike2ip(this->protocol), this->mark_in,
|
||||
&bytes, &packets, &time);
|
||||
kernel_ipsec_sa_id_t id = {
|
||||
.src = this->other_addr,
|
||||
.dst = this->my_addr,
|
||||
.spi = this->my_spi,
|
||||
.proto = proto_ike2ip(this->protocol),
|
||||
.mark = this->mark_in,
|
||||
};
|
||||
kernel_ipsec_query_sa_t query = {};
|
||||
|
||||
status = charon->kernel->query_sa(charon->kernel, &id, &query,
|
||||
&bytes, &packets, &time);
|
||||
if (status == SUCCESS)
|
||||
{
|
||||
if (bytes > this->my_usebytes)
|
||||
@@ -492,10 +500,17 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
|
||||
{
|
||||
if (this->other_spi)
|
||||
{
|
||||
status = charon->kernel->query_sa(charon->kernel, this->my_addr,
|
||||
this->other_addr, this->other_spi,
|
||||
proto_ike2ip(this->protocol), this->mark_out,
|
||||
&bytes, &packets, &time);
|
||||
kernel_ipsec_sa_id_t id = {
|
||||
.src = this->my_addr,
|
||||
.dst = this->other_addr,
|
||||
.spi = this->other_spi,
|
||||
.proto = proto_ike2ip(this->protocol),
|
||||
.mark = this->mark_out,
|
||||
};
|
||||
kernel_ipsec_query_sa_t query = {};
|
||||
|
||||
status = charon->kernel->query_sa(charon->kernel, &id, &query,
|
||||
&bytes, &packets, &time);
|
||||
if (status == SUCCESS)
|
||||
{
|
||||
if (bytes > this->other_usebytes)
|
||||
@@ -531,15 +546,24 @@ static bool update_usetime(private_child_sa_t *this, bool inbound)
|
||||
|
||||
if (inbound)
|
||||
{
|
||||
if (charon->kernel->query_policy(charon->kernel, other_ts,
|
||||
my_ts, POLICY_IN, this->mark_in, &in) == SUCCESS)
|
||||
kernel_ipsec_policy_id_t id = {
|
||||
.dir = POLICY_IN,
|
||||
.src_ts = other_ts,
|
||||
.dst_ts = my_ts,
|
||||
.mark = this->mark_in,
|
||||
};
|
||||
kernel_ipsec_query_policy_t query = {};
|
||||
|
||||
if (charon->kernel->query_policy(charon->kernel, &id, &query,
|
||||
&in) == SUCCESS)
|
||||
{
|
||||
last_use = max(last_use, in);
|
||||
}
|
||||
if (this->mode != MODE_TRANSPORT)
|
||||
{
|
||||
if (charon->kernel->query_policy(charon->kernel, other_ts,
|
||||
my_ts, POLICY_FWD, this->mark_in, &fwd) == SUCCESS)
|
||||
id.dir = POLICY_FWD;
|
||||
if (charon->kernel->query_policy(charon->kernel, &id, &query,
|
||||
&fwd) == SUCCESS)
|
||||
{
|
||||
last_use = max(last_use, fwd);
|
||||
}
|
||||
@@ -547,8 +571,17 @@ static bool update_usetime(private_child_sa_t *this, bool inbound)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (charon->kernel->query_policy(charon->kernel, my_ts,
|
||||
other_ts, POLICY_OUT, this->mark_out, &out) == SUCCESS)
|
||||
kernel_ipsec_policy_id_t id = {
|
||||
.dir = POLICY_OUT,
|
||||
.src_ts = my_ts,
|
||||
.dst_ts = other_ts,
|
||||
.mark = this->mark_out,
|
||||
.interface = this->config->get_interface(this->config),
|
||||
};
|
||||
kernel_ipsec_query_policy_t query = {};
|
||||
|
||||
if (charon->kernel->query_policy(charon->kernel, &id, &query,
|
||||
&out) == SUCCESS)
|
||||
{
|
||||
last_use = max(last_use, out);
|
||||
}
|
||||
@@ -659,6 +692,8 @@ METHOD(child_sa_t, install, status_t,
|
||||
uint16_t esn = NO_EXT_SEQ_NUMBERS;
|
||||
linked_list_t *src_ts = NULL, *dst_ts = NULL;
|
||||
time_t now;
|
||||
kernel_ipsec_sa_id_t id;
|
||||
kernel_ipsec_add_sa_t sa;
|
||||
lifetime_cfg_t *lifetime;
|
||||
uint32_t tfc = 0;
|
||||
host_t *src, *dst;
|
||||
@@ -752,12 +787,36 @@ METHOD(child_sa_t, install, status_t,
|
||||
dst_ts = other_ts;
|
||||
}
|
||||
|
||||
status = charon->kernel->add_sa(charon->kernel,
|
||||
src, dst, spi, proto_ike2ip(this->protocol), this->reqid,
|
||||
inbound ? this->mark_in : this->mark_out, tfc,
|
||||
lifetime, enc_alg, encr, int_alg, integ, this->mode,
|
||||
this->ipcomp, cpi, this->config->get_replay_window(this->config),
|
||||
initiator, this->encap, esn, inbound, update, src_ts, dst_ts);
|
||||
id = (kernel_ipsec_sa_id_t){
|
||||
.src = src,
|
||||
.dst = dst,
|
||||
.spi = spi,
|
||||
.proto = proto_ike2ip(this->protocol),
|
||||
.mark = inbound ? this->mark_in : this->mark_out,
|
||||
};
|
||||
sa = (kernel_ipsec_add_sa_t){
|
||||
.reqid = this->reqid,
|
||||
.mode = this->mode,
|
||||
.src_ts = src_ts,
|
||||
.dst_ts = dst_ts,
|
||||
.interface = inbound ? NULL : this->config->get_interface(this->config),
|
||||
.lifetime = lifetime,
|
||||
.enc_alg = enc_alg,
|
||||
.enc_key = encr,
|
||||
.int_alg = int_alg,
|
||||
.int_key = integ,
|
||||
.replay_window = this->config->get_replay_window(this->config),
|
||||
.tfc = tfc,
|
||||
.ipcomp = this->ipcomp,
|
||||
.cpi = cpi,
|
||||
.encap = this->encap,
|
||||
.esn = esn,
|
||||
.initiator = initiator,
|
||||
.inbound = inbound,
|
||||
.update = update,
|
||||
};
|
||||
|
||||
status = charon->kernel->add_sa(charon->kernel, &id, &sa);
|
||||
|
||||
free(lifetime);
|
||||
|
||||
@@ -825,24 +884,55 @@ static void prepare_sa_cfg(private_child_sa_t *this, ipsec_sa_cfg_t *my_sa,
|
||||
static status_t install_policies_internal(private_child_sa_t *this,
|
||||
host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
|
||||
traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
|
||||
ipsec_sa_cfg_t *other_sa, policy_type_t type, policy_priority_t priority)
|
||||
ipsec_sa_cfg_t *other_sa, policy_type_t type,
|
||||
policy_priority_t priority, uint32_t manual_prio)
|
||||
{
|
||||
kernel_ipsec_policy_id_t out_id = {
|
||||
.dir = POLICY_OUT,
|
||||
.src_ts = my_ts,
|
||||
.dst_ts = other_ts,
|
||||
.mark = this->mark_out,
|
||||
.interface = this->config->get_interface(this->config),
|
||||
}, in_id = {
|
||||
.dir = POLICY_IN,
|
||||
.src_ts = other_ts,
|
||||
.dst_ts = my_ts,
|
||||
.mark = this->mark_in,
|
||||
};
|
||||
kernel_ipsec_manage_policy_t out_policy = {
|
||||
.type = type,
|
||||
.prio = priority,
|
||||
.manual_prio = manual_prio,
|
||||
.src = my_addr,
|
||||
.dst = other_addr,
|
||||
.sa = other_sa,
|
||||
}, in_policy = {
|
||||
.type = type,
|
||||
.prio = priority,
|
||||
.manual_prio = manual_prio,
|
||||
.src = other_addr,
|
||||
.dst = my_addr,
|
||||
.sa = my_sa,
|
||||
};
|
||||
status_t status = SUCCESS;
|
||||
status |= charon->kernel->add_policy(charon->kernel,
|
||||
my_addr, other_addr, my_ts, other_ts,
|
||||
POLICY_OUT, type, other_sa,
|
||||
this->mark_out, priority);
|
||||
|
||||
status |= charon->kernel->add_policy(charon->kernel,
|
||||
other_addr, my_addr, other_ts, my_ts,
|
||||
POLICY_IN, type, my_sa,
|
||||
this->mark_in, priority);
|
||||
status |= charon->kernel->add_policy(charon->kernel, &out_id, &out_policy);
|
||||
status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
|
||||
if (this->mode != MODE_TRANSPORT)
|
||||
{
|
||||
status |= charon->kernel->add_policy(charon->kernel,
|
||||
other_addr, my_addr, other_ts, my_ts,
|
||||
POLICY_FWD, type, my_sa,
|
||||
this->mark_in, priority);
|
||||
in_id.dir = POLICY_FWD;
|
||||
status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
|
||||
|
||||
/* install an "outbound" FWD policy in case there is a drop policy
|
||||
* matching outbound forwarded traffic, to allow another tunnel to use
|
||||
* the reversed subnets and do the same we don't set a reqid (this also
|
||||
* allows the kernel backend to distinguish between the two types of
|
||||
* FWD policies) */
|
||||
out_id.dir = POLICY_FWD;
|
||||
other_sa->reqid = 0;
|
||||
status |= charon->kernel->add_policy(charon->kernel, &out_id, &out_policy);
|
||||
/* reset the reqid for any other further policies */
|
||||
other_sa->reqid = this->reqid;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -853,20 +943,48 @@ static status_t install_policies_internal(private_child_sa_t *this,
|
||||
static void del_policies_internal(private_child_sa_t *this,
|
||||
host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
|
||||
traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
|
||||
ipsec_sa_cfg_t *other_sa, policy_type_t type, policy_priority_t priority)
|
||||
ipsec_sa_cfg_t *other_sa, policy_type_t type,
|
||||
policy_priority_t priority, uint32_t manual_prio)
|
||||
{
|
||||
kernel_ipsec_policy_id_t out_id = {
|
||||
.dir = POLICY_OUT,
|
||||
.src_ts = my_ts,
|
||||
.dst_ts = other_ts,
|
||||
.mark = this->mark_out,
|
||||
.interface = this->config->get_interface(this->config),
|
||||
}, in_id = {
|
||||
.dir = POLICY_IN,
|
||||
.src_ts = other_ts,
|
||||
.dst_ts = my_ts,
|
||||
.mark = this->mark_in,
|
||||
};
|
||||
kernel_ipsec_manage_policy_t out_policy = {
|
||||
.type = type,
|
||||
.prio = priority,
|
||||
.manual_prio = manual_prio,
|
||||
.src = my_addr,
|
||||
.dst = other_addr,
|
||||
.sa = other_sa,
|
||||
}, in_policy = {
|
||||
.type = type,
|
||||
.prio = priority,
|
||||
.manual_prio = manual_prio,
|
||||
.src = other_addr,
|
||||
.dst = my_addr,
|
||||
.sa = my_sa,
|
||||
};
|
||||
|
||||
charon->kernel->del_policy(charon->kernel,
|
||||
my_addr, other_addr, my_ts, other_ts, POLICY_OUT, type,
|
||||
other_sa, this->mark_out, priority);
|
||||
charon->kernel->del_policy(charon->kernel,
|
||||
other_addr, my_addr, other_ts, my_ts, POLICY_IN,
|
||||
type, my_sa, this->mark_in, priority);
|
||||
charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
|
||||
charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
|
||||
if (this->mode != MODE_TRANSPORT)
|
||||
{
|
||||
charon->kernel->del_policy(charon->kernel,
|
||||
other_addr, my_addr, other_ts, my_ts, POLICY_FWD,
|
||||
type, my_sa, this->mark_in, priority);
|
||||
in_id.dir = POLICY_FWD;
|
||||
charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
|
||||
|
||||
out_id.dir = POLICY_FWD;
|
||||
other_sa->reqid = 0;
|
||||
charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
|
||||
other_sa->reqid = this->reqid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -912,8 +1030,10 @@ METHOD(child_sa_t, add_policies, status_t,
|
||||
{
|
||||
policy_priority_t priority;
|
||||
ipsec_sa_cfg_t my_sa, other_sa;
|
||||
uint32_t manual_prio;
|
||||
|
||||
prepare_sa_cfg(this, &my_sa, &other_sa);
|
||||
manual_prio = this->config->get_manual_prio(this->config);
|
||||
|
||||
/* if we're not in state CHILD_INSTALLING (i.e. if there is no SAD
|
||||
* entry) we install a trap policy */
|
||||
@@ -927,18 +1047,20 @@ METHOD(child_sa_t, add_policies, status_t,
|
||||
{
|
||||
/* install outbound drop policy to avoid packets leaving unencrypted
|
||||
* when updating policies */
|
||||
if (priority == POLICY_PRIORITY_DEFAULT && require_policy_update())
|
||||
if (priority == POLICY_PRIORITY_DEFAULT && manual_prio == 0 &&
|
||||
require_policy_update())
|
||||
{
|
||||
status |= install_policies_internal(this, this->my_addr,
|
||||
this->other_addr, my_ts, other_ts,
|
||||
&my_sa, &other_sa, POLICY_DROP,
|
||||
POLICY_PRIORITY_FALLBACK);
|
||||
POLICY_PRIORITY_FALLBACK, 0);
|
||||
}
|
||||
|
||||
/* install policies */
|
||||
status |= install_policies_internal(this, this->my_addr,
|
||||
this->other_addr, my_ts, other_ts,
|
||||
&my_sa, &other_sa, POLICY_IPSEC, priority);
|
||||
&my_sa, &other_sa, POLICY_IPSEC,
|
||||
priority, manual_prio);
|
||||
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
@@ -994,11 +1116,22 @@ METHOD(child_sa_t, update, status_t,
|
||||
/* update our (initiator) SA */
|
||||
if (this->my_spi)
|
||||
{
|
||||
if (charon->kernel->update_sa(charon->kernel,
|
||||
this->my_spi, proto_ike2ip(this->protocol),
|
||||
this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
|
||||
this->other_addr, this->my_addr, other, me,
|
||||
this->encap, encap, this->mark_in) == NOT_SUPPORTED)
|
||||
kernel_ipsec_sa_id_t id = {
|
||||
.src = this->other_addr,
|
||||
.dst = this->my_addr,
|
||||
.spi = this->my_spi,
|
||||
.proto = proto_ike2ip(this->protocol),
|
||||
.mark = this->mark_in,
|
||||
};
|
||||
kernel_ipsec_update_sa_t sa = {
|
||||
.cpi = this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
|
||||
.new_src = other,
|
||||
.new_dst = me,
|
||||
.encap = this->encap,
|
||||
.new_encap = encap,
|
||||
};
|
||||
if (charon->kernel->update_sa(charon->kernel, &id,
|
||||
&sa) == NOT_SUPPORTED)
|
||||
{
|
||||
set_state(this, old);
|
||||
return NOT_SUPPORTED;
|
||||
@@ -1008,11 +1141,22 @@ METHOD(child_sa_t, update, status_t,
|
||||
/* update his (responder) SA */
|
||||
if (this->other_spi)
|
||||
{
|
||||
if (charon->kernel->update_sa(charon->kernel,
|
||||
this->other_spi, proto_ike2ip(this->protocol),
|
||||
this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
|
||||
this->my_addr, this->other_addr, me, other,
|
||||
this->encap, encap, this->mark_out) == NOT_SUPPORTED)
|
||||
kernel_ipsec_sa_id_t id = {
|
||||
.src = this->my_addr,
|
||||
.dst = this->other_addr,
|
||||
.spi = this->other_spi,
|
||||
.proto = proto_ike2ip(this->protocol),
|
||||
.mark = this->mark_out,
|
||||
};
|
||||
kernel_ipsec_update_sa_t sa = {
|
||||
.cpi = this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
|
||||
.new_src = me,
|
||||
.new_dst = other,
|
||||
.encap = this->encap,
|
||||
.new_encap = encap,
|
||||
};
|
||||
if (charon->kernel->update_sa(charon->kernel, &id,
|
||||
&sa) == NOT_SUPPORTED)
|
||||
{
|
||||
set_state(this, old);
|
||||
return NOT_SUPPORTED;
|
||||
@@ -1028,18 +1172,21 @@ METHOD(child_sa_t, update, status_t,
|
||||
ipsec_sa_cfg_t my_sa, other_sa;
|
||||
enumerator_t *enumerator;
|
||||
traffic_selector_t *my_ts, *other_ts;
|
||||
uint32_t manual_prio;
|
||||
|
||||
prepare_sa_cfg(this, &my_sa, &other_sa);
|
||||
manual_prio = this->config->get_manual_prio(this->config);
|
||||
|
||||
/* always use high priorities, as hosts getting updated are INSTALLED */
|
||||
enumerator = create_policy_enumerator(this);
|
||||
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
|
||||
{
|
||||
traffic_selector_t *old_my_ts = NULL, *old_other_ts = NULL;
|
||||
|
||||
/* remove old policies first */
|
||||
del_policies_internal(this, this->my_addr, this->other_addr,
|
||||
my_ts, other_ts, &my_sa, &other_sa,
|
||||
POLICY_IPSEC, POLICY_PRIORITY_DEFAULT);
|
||||
my_ts, other_ts, &my_sa, &other_sa, POLICY_IPSEC,
|
||||
POLICY_PRIORITY_DEFAULT, manual_prio);
|
||||
|
||||
/* check if we have to update a "dynamic" traffic selector */
|
||||
if (!me->ip_equals(me, this->my_addr) &&
|
||||
@@ -1062,17 +1209,20 @@ METHOD(child_sa_t, update, status_t,
|
||||
/* reinstall updated policies */
|
||||
install_policies_internal(this, me, other, my_ts, other_ts,
|
||||
&my_sa, &other_sa, POLICY_IPSEC,
|
||||
POLICY_PRIORITY_DEFAULT);
|
||||
POLICY_PRIORITY_DEFAULT, manual_prio);
|
||||
|
||||
/* update fallback policies after the new policy is in place */
|
||||
del_policies_internal(this, this->my_addr, this->other_addr,
|
||||
old_my_ts ?: my_ts,
|
||||
old_other_ts ?: other_ts,
|
||||
&my_sa, &other_sa, POLICY_DROP,
|
||||
POLICY_PRIORITY_FALLBACK);
|
||||
install_policies_internal(this, me, other, my_ts, other_ts,
|
||||
if (manual_prio == 0)
|
||||
{
|
||||
del_policies_internal(this, this->my_addr, this->other_addr,
|
||||
old_my_ts ?: my_ts,
|
||||
old_other_ts ?: other_ts,
|
||||
&my_sa, &other_sa, POLICY_DROP,
|
||||
POLICY_PRIORITY_FALLBACK);
|
||||
POLICY_PRIORITY_FALLBACK, 0);
|
||||
install_policies_internal(this, me, other, my_ts, other_ts,
|
||||
&my_sa, &other_sa, POLICY_DROP,
|
||||
POLICY_PRIORITY_FALLBACK, 0);
|
||||
}
|
||||
DESTROY_IF(old_my_ts);
|
||||
DESTROY_IF(old_other_ts);
|
||||
}
|
||||
@@ -1115,20 +1265,24 @@ METHOD(child_sa_t, destroy, void,
|
||||
if (this->config->install_policy(this->config))
|
||||
{
|
||||
ipsec_sa_cfg_t my_sa, other_sa;
|
||||
uint32_t manual_prio;
|
||||
|
||||
prepare_sa_cfg(this, &my_sa, &other_sa);
|
||||
manual_prio = this->config->get_manual_prio(this->config);
|
||||
|
||||
/* delete all policies in the kernel */
|
||||
enumerator = create_policy_enumerator(this);
|
||||
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
|
||||
{
|
||||
del_policies_internal(this, this->my_addr, this->other_addr,
|
||||
my_ts, other_ts, &my_sa, &other_sa, POLICY_IPSEC, priority);
|
||||
if (priority == POLICY_PRIORITY_DEFAULT && require_policy_update())
|
||||
my_ts, other_ts, &my_sa, &other_sa,
|
||||
POLICY_IPSEC, priority, manual_prio);
|
||||
if (priority == POLICY_PRIORITY_DEFAULT && manual_prio == 0 &&
|
||||
require_policy_update())
|
||||
{
|
||||
del_policies_internal(this, this->my_addr, this->other_addr,
|
||||
my_ts, other_ts, &my_sa, &other_sa, POLICY_DROP,
|
||||
POLICY_PRIORITY_FALLBACK);
|
||||
my_ts, other_ts, &my_sa, &other_sa,
|
||||
POLICY_DROP, POLICY_PRIORITY_FALLBACK, 0);
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
@@ -1137,17 +1291,31 @@ METHOD(child_sa_t, destroy, void,
|
||||
/* delete SAs in the kernel, if they are set up */
|
||||
if (this->my_spi)
|
||||
{
|
||||
charon->kernel->del_sa(charon->kernel,
|
||||
this->other_addr, this->my_addr, this->my_spi,
|
||||
proto_ike2ip(this->protocol), this->my_cpi,
|
||||
this->mark_in);
|
||||
kernel_ipsec_sa_id_t id = {
|
||||
.src = this->other_addr,
|
||||
.dst = this->my_addr,
|
||||
.spi = this->my_spi,
|
||||
.proto = proto_ike2ip(this->protocol),
|
||||
.mark = this->mark_in,
|
||||
};
|
||||
kernel_ipsec_del_sa_t sa = {
|
||||
.cpi = this->my_cpi,
|
||||
};
|
||||
charon->kernel->del_sa(charon->kernel, &id, &sa);
|
||||
}
|
||||
if (this->other_spi)
|
||||
{
|
||||
charon->kernel->del_sa(charon->kernel,
|
||||
this->my_addr, this->other_addr, this->other_spi,
|
||||
proto_ike2ip(this->protocol), this->other_cpi,
|
||||
this->mark_out);
|
||||
kernel_ipsec_sa_id_t id = {
|
||||
.src = this->my_addr,
|
||||
.dst = this->other_addr,
|
||||
.spi = this->other_spi,
|
||||
.proto = proto_ike2ip(this->protocol),
|
||||
.mark = this->mark_out,
|
||||
};
|
||||
kernel_ipsec_del_sa_t sa = {
|
||||
.cpi = this->other_cpi,
|
||||
};
|
||||
charon->kernel->del_sa(charon->kernel, &id, &sa);
|
||||
}
|
||||
|
||||
if (this->reqid_allocated)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Tobias Brunner
|
||||
* Copyright (C) 2011 Andreas Steffen
|
||||
* Copyright (C) 2015-2016 Tobias Brunner
|
||||
* Copyright (C) 2011-2016 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -68,6 +68,8 @@ static bool install_shunt_policy(child_cfg_t *child)
|
||||
policy_type_t policy_type;
|
||||
policy_priority_t policy_prio;
|
||||
status_t status = SUCCESS;
|
||||
uint32_t manual_prio;
|
||||
char *interface;
|
||||
ipsec_sa_cfg_t sa = { .mode = MODE_TRANSPORT };
|
||||
|
||||
switch (child->get_mode(child))
|
||||
@@ -92,6 +94,9 @@ static bool install_shunt_policy(child_cfg_t *child)
|
||||
other_ts_list = child->get_traffic_selectors(child, FALSE, NULL, hosts);
|
||||
hosts->destroy(hosts);
|
||||
|
||||
manual_prio = child->get_manual_prio(child);
|
||||
interface = child->get_interface(child);
|
||||
|
||||
/* enumerate pairs of traffic selectors */
|
||||
e_my_ts = my_ts_list->create_enumerator(my_ts_list);
|
||||
while (e_my_ts->enumerate(e_my_ts, &my_ts))
|
||||
@@ -110,25 +115,37 @@ static bool install_shunt_policy(child_cfg_t *child)
|
||||
continue;
|
||||
}
|
||||
/* install out policy */
|
||||
status |= charon->kernel->add_policy(charon->kernel,
|
||||
host_any, host_any,
|
||||
my_ts, other_ts, POLICY_OUT, policy_type,
|
||||
&sa, child->get_mark(child, FALSE),
|
||||
policy_prio);
|
||||
|
||||
kernel_ipsec_policy_id_t id = {
|
||||
.dir = POLICY_OUT,
|
||||
.src_ts = my_ts,
|
||||
.dst_ts = other_ts,
|
||||
.mark = child->get_mark(child, FALSE),
|
||||
.interface = interface,
|
||||
};
|
||||
kernel_ipsec_manage_policy_t policy = {
|
||||
.type = policy_type,
|
||||
.prio = policy_prio,
|
||||
.manual_prio = manual_prio,
|
||||
.src = host_any,
|
||||
.dst = host_any,
|
||||
.sa = &sa,
|
||||
};
|
||||
status |= charon->kernel->add_policy(charon->kernel, &id, &policy);
|
||||
/* install "outbound" forward policy */
|
||||
id.dir = POLICY_FWD;
|
||||
status |= charon->kernel->add_policy(charon->kernel, &id, &policy);
|
||||
/* install in policy */
|
||||
status |= charon->kernel->add_policy(charon->kernel,
|
||||
host_any, host_any,
|
||||
other_ts, my_ts, POLICY_IN, policy_type,
|
||||
&sa, child->get_mark(child, TRUE),
|
||||
policy_prio);
|
||||
|
||||
/* install forward policy */
|
||||
status |= charon->kernel->add_policy(charon->kernel,
|
||||
host_any, host_any,
|
||||
other_ts, my_ts, POLICY_FWD, policy_type,
|
||||
&sa, child->get_mark(child, TRUE),
|
||||
policy_prio);
|
||||
id = (kernel_ipsec_policy_id_t){
|
||||
.dir = POLICY_IN,
|
||||
.src_ts = other_ts,
|
||||
.dst_ts = my_ts,
|
||||
.mark = child->get_mark(child, TRUE),
|
||||
.interface = interface,
|
||||
};
|
||||
status |= charon->kernel->add_policy(charon->kernel, &id, &policy);
|
||||
/* install "inbound" forward policy */
|
||||
id.dir = POLICY_FWD;
|
||||
status |= charon->kernel->add_policy(charon->kernel, &id, &policy);
|
||||
}
|
||||
e_other_ts->destroy(e_other_ts);
|
||||
}
|
||||
@@ -205,6 +222,8 @@ static void uninstall_shunt_policy(child_cfg_t *child)
|
||||
policy_type_t policy_type;
|
||||
policy_priority_t policy_prio;
|
||||
status_t status = SUCCESS;
|
||||
uint32_t manual_prio;
|
||||
char *interface;
|
||||
ipsec_sa_cfg_t sa = { .mode = MODE_TRANSPORT };
|
||||
|
||||
switch (child->get_mode(child))
|
||||
@@ -229,6 +248,9 @@ static void uninstall_shunt_policy(child_cfg_t *child)
|
||||
other_ts_list = child->get_traffic_selectors(child, FALSE, NULL, hosts);
|
||||
hosts->destroy(hosts);
|
||||
|
||||
manual_prio = child->get_manual_prio(child);
|
||||
interface = child->get_interface(child);
|
||||
|
||||
/* enumerate pairs of traffic selectors */
|
||||
e_my_ts = my_ts_list->create_enumerator(my_ts_list);
|
||||
while (e_my_ts->enumerate(e_my_ts, &my_ts))
|
||||
@@ -247,25 +269,37 @@ static void uninstall_shunt_policy(child_cfg_t *child)
|
||||
continue;
|
||||
}
|
||||
/* uninstall out policy */
|
||||
status |= charon->kernel->del_policy(charon->kernel,
|
||||
host_any, host_any,
|
||||
my_ts, other_ts, POLICY_OUT, policy_type,
|
||||
&sa, child->get_mark(child, FALSE),
|
||||
policy_prio);
|
||||
|
||||
kernel_ipsec_policy_id_t id = {
|
||||
.dir = POLICY_OUT,
|
||||
.src_ts = my_ts,
|
||||
.dst_ts = other_ts,
|
||||
.mark = child->get_mark(child, FALSE),
|
||||
.interface = interface,
|
||||
};
|
||||
kernel_ipsec_manage_policy_t policy = {
|
||||
.type = policy_type,
|
||||
.prio = policy_prio,
|
||||
.manual_prio = manual_prio,
|
||||
.src = host_any,
|
||||
.dst = host_any,
|
||||
.sa = &sa,
|
||||
};
|
||||
status |= charon->kernel->del_policy(charon->kernel, &id, &policy);
|
||||
/* uninstall "outbound" forward policy */
|
||||
id.dir = POLICY_FWD;
|
||||
status |= charon->kernel->del_policy(charon->kernel, &id, &policy);
|
||||
/* uninstall in policy */
|
||||
status |= charon->kernel->del_policy(charon->kernel,
|
||||
host_any, host_any,
|
||||
other_ts, my_ts, POLICY_IN, policy_type,
|
||||
&sa, child->get_mark(child, TRUE),
|
||||
policy_prio);
|
||||
|
||||
/* uninstall forward policy */
|
||||
status |= charon->kernel->del_policy(charon->kernel,
|
||||
host_any, host_any,
|
||||
other_ts, my_ts, POLICY_FWD, policy_type,
|
||||
&sa, child->get_mark(child, TRUE),
|
||||
policy_prio);
|
||||
id = (kernel_ipsec_policy_id_t){
|
||||
.dir = POLICY_IN,
|
||||
.src_ts = other_ts,
|
||||
.dst_ts = my_ts,
|
||||
.mark = child->get_mark(child, TRUE),
|
||||
.interface = interface,
|
||||
};
|
||||
status |= charon->kernel->del_policy(charon->kernel, &id, &policy);
|
||||
/* uninstall "inbound" forward policy */
|
||||
id.dir = POLICY_FWD;
|
||||
status |= charon->kernel->del_policy(charon->kernel, &id, &policy);
|
||||
}
|
||||
e_other_ts->destroy(e_other_ts);
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ CALLBACK(children_sn, int,
|
||||
hashtable_t *ike, vici_res_t *res, char *name)
|
||||
{
|
||||
hashtable_t *child;
|
||||
char *interface, *priority;
|
||||
int ret;
|
||||
|
||||
child = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
|
||||
@@ -89,6 +90,18 @@ CALLBACK(children_sn, int,
|
||||
printf(" %s: %s\n", name, child->get(child, "mode"));
|
||||
printf(" local: %s\n", child->get(child, "local-ts"));
|
||||
printf(" remote: %s\n", child->get(child, "remote-ts"));
|
||||
|
||||
interface = child->get(child, "interface");
|
||||
if (interface)
|
||||
{
|
||||
printf(" interface: %s\n", interface);
|
||||
}
|
||||
|
||||
priority = child->get(child, "priority");
|
||||
if (priority)
|
||||
{
|
||||
printf(" priority: %s\n", priority);
|
||||
}
|
||||
}
|
||||
free_hashtable(child);
|
||||
return ret;
|
||||
|
||||
@@ -684,6 +684,16 @@ connections.<conn>.children.<child>.reqid = 0
|
||||
not more than once. The default of _0_ uses dynamic reqids, allocated
|
||||
incrementally.
|
||||
|
||||
connections.<conn>.children.<child>.priority = 0
|
||||
Optional fixed priority for IPsec policies.
|
||||
|
||||
Optional fixed priority for IPsec policies. This could be useful to install
|
||||
high-priority drop policies. The default of _0_ uses dynamically calculated
|
||||
priorities based on the size of the traffic selectors.
|
||||
|
||||
connections.<conn>.children.<child>.interface =
|
||||
Optional interface name to restrict IPsec policies.
|
||||
|
||||
connections.<conn>.children.<child>.mark_in = 0/0x00000000
|
||||
Netfilter mark and mask for input traffic.
|
||||
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each
|
||||
to gateway <b>moon</b>. The authentication is based on <b>X.509 certificates</b>.
|
||||
High priority passthrough rules cause ssh connections to be exempted from both
|
||||
ESP encryption and a general drop rule for <b>moon</b>'s external eth0 interface.
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 [email protected] remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
|
||||
dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 [email protected] remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
|
||||
moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 [email protected].*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
|
||||
moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 [email protected].*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]::YES
|
||||
carol::ping -c 1 10.1.0.1::64 bytes from 10.1.0.1: icmp_req=1::YES
|
||||
carol::ping -c 1 10.1.0.10::64 bytes from 10.1.0.10: icmp_req=1::YES
|
||||
dave:: ping -c 1 10.1.0.1::64 bytes from 10.1.0.1: icmp_req=1::YES
|
||||
dave:: ping -c 1 10.1.0.20::64 bytes from 10.1.0.20: icmp_req=1::YES
|
||||
moon:: ping -c 1 10.1.0.10::64 bytes from 10.1.0.10: icmp_req=1::YES
|
||||
moon:: ping -c 1 10.1.0.20::64 bytes from 10.1.0.20: icmp_req=1::YES
|
||||
alice::ping -c 1 -W 1 192.168.0.150::64 bytes from 192.168.0.150: icmp_req=1::NO
|
||||
moon:: ping -c 1 -W 1 192.168.0.150::64 bytes from 192.168.0.150: icmp_req=1::NO
|
||||
winnetou::ping -c 1 -W 1 192.168.0.1::64 bytes from 192.168.0.1: icmp_req=1::NO
|
||||
carol::ssh -o ConnectTimeout=5 192.168.0.1 hostname 2> /dev/null::moon::YES
|
||||
carol::ssh -o ConnectTimeout=5 10.1.0.1 hostname 2> /dev/null::moon::YES
|
||||
carol::ssh -o ConnectTimeout=5 10.1.0.10 hostname 2> /dev/null::alice::YES
|
||||
dave:: ssh -o ConnectTimeout=5 192.168.0.1 hostname 2> /dev/null::moon::YES
|
||||
dave ::ssh -o ConnectTimeout=5 10.1.0.1 hostname 2> /dev/null::moon::YES
|
||||
dave ::ssh -o ConnectTimeout=5 10.1.0.20 hostname 2> /dev/null::venus::YES
|
||||
moon ::ssh -o ConnectTimeout=5 192.168.0.150 hostname 2> /dev/null::winnetou::YES
|
||||
moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
|
||||
moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
|
||||
moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
|
||||
moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
|
||||
@@ -0,0 +1,14 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
swanctl {
|
||||
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||
}
|
||||
|
||||
charon {
|
||||
load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints pubkey gmp random nonce curl kernel-netlink socket-default updown vici
|
||||
|
||||
start-scripts {
|
||||
creds = /usr/local/sbin/swanctl --load-creds
|
||||
conns = /usr/local/sbin/swanctl --load-conns
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
connections {
|
||||
|
||||
home {
|
||||
local_addrs = 192.168.0.100
|
||||
remote_addrs = 192.168.0.1
|
||||
|
||||
local {
|
||||
auth = pubkey
|
||||
certs = carolCert.pem
|
||||
id = [email protected]
|
||||
}
|
||||
remote {
|
||||
auth = pubkey
|
||||
id = moon.strongswan.org
|
||||
}
|
||||
children {
|
||||
home {
|
||||
remote_ts = 10.1.0.0/16
|
||||
priority = 2
|
||||
|
||||
esp_proposals = aes128gcm128-modp3072
|
||||
}
|
||||
}
|
||||
version = 2
|
||||
proposals = aes128-sha256-modp3072
|
||||
}
|
||||
|
||||
shunts {
|
||||
|
||||
children {
|
||||
pass-ssh-in {
|
||||
local_ts = 0.0.0.0/0[tcp/ssh]
|
||||
remote_ts = 0.0.0.0/0[tcp]
|
||||
priority = 1
|
||||
|
||||
mode = pass
|
||||
start_action = trap
|
||||
}
|
||||
pass-ssh-out {
|
||||
local_ts = 0.0.0.0/0[tcp]
|
||||
remote_ts = 0.0.0.0/0[tcp/ssh]
|
||||
priority = 1
|
||||
|
||||
mode = pass
|
||||
start_action = trap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
swanctl {
|
||||
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||
}
|
||||
|
||||
charon {
|
||||
load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints pubkey gmp random nonce curl kernel-netlink socket-default updown vici
|
||||
|
||||
start-scripts {
|
||||
creds = /usr/local/sbin/swanctl --load-creds
|
||||
conns = /usr/local/sbin/swanctl --load-conns
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
connections {
|
||||
|
||||
home {
|
||||
local_addrs = 192.168.0.200
|
||||
remote_addrs = 192.168.0.1
|
||||
|
||||
local {
|
||||
auth = pubkey
|
||||
certs = daveCert.pem
|
||||
id = [email protected]
|
||||
}
|
||||
remote {
|
||||
auth = pubkey
|
||||
id = moon.strongswan.org
|
||||
}
|
||||
children {
|
||||
home {
|
||||
remote_ts = 10.1.0.0/16
|
||||
|
||||
updown = /usr/local/libexec/ipsec/_updown iptables
|
||||
esp_proposals = aes128gcm128-modp3072
|
||||
}
|
||||
}
|
||||
version = 2
|
||||
proposals = aes128-sha256-modp3072
|
||||
}
|
||||
|
||||
shunts {
|
||||
|
||||
children {
|
||||
pass-ssh-in {
|
||||
local_ts = 0.0.0.0/0[tcp/ssh]
|
||||
remote_ts = 0.0.0.0/0[tcp]
|
||||
priority = 1
|
||||
|
||||
mode = pass
|
||||
start_action = trap
|
||||
}
|
||||
pass-ssh-out {
|
||||
local_ts = 0.0.0.0/0[tcp]
|
||||
remote_ts = 0.0.0.0/0[tcp/ssh]
|
||||
priority = 1
|
||||
|
||||
mode = pass
|
||||
start_action = trap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
swanctl {
|
||||
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||
}
|
||||
|
||||
charon {
|
||||
load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints pubkey gmp random nonce curl kernel-netlink socket-default updown vici
|
||||
|
||||
start-scripts {
|
||||
creds = /usr/local/sbin/swanctl --load-creds
|
||||
conns = /usr/local/sbin/swanctl --load-conns
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
connections {
|
||||
|
||||
rw {
|
||||
local_addrs = 192.168.0.1
|
||||
|
||||
local {
|
||||
auth = pubkey
|
||||
certs = moonCert.pem
|
||||
id = moon.strongswan.org
|
||||
}
|
||||
remote {
|
||||
auth = pubkey
|
||||
}
|
||||
children {
|
||||
net {
|
||||
local_ts = 10.1.0.0/16
|
||||
priority = 2
|
||||
interface = eth0
|
||||
|
||||
esp_proposals = aes128gcm128-modp3072
|
||||
}
|
||||
}
|
||||
version = 2
|
||||
proposals = aes128-sha256-modp3072
|
||||
}
|
||||
|
||||
shunts {
|
||||
|
||||
children {
|
||||
drop-eth0-default {
|
||||
local_ts = 0.0.0.0/0
|
||||
remote_ts = 0.0.0.0/0
|
||||
interface = eth0
|
||||
priority = 4
|
||||
|
||||
mode = drop
|
||||
start_action = trap
|
||||
}
|
||||
pass-ssh-in {
|
||||
local_ts = 0.0.0.0/0[tcp/ssh]
|
||||
remote_ts = 0.0.0.0/0[tcp]
|
||||
priority = 1
|
||||
|
||||
mode = pass
|
||||
start_action = trap
|
||||
}
|
||||
pass-ssh-out {
|
||||
local_ts = 0.0.0.0/0[tcp]
|
||||
remote_ts = 0.0.0.0/0[tcp/ssh]
|
||||
priority = 1
|
||||
|
||||
mode = pass
|
||||
start_action = trap
|
||||
}
|
||||
pass-http-out {
|
||||
local_ts = 0.0.0.0/0[tcp]
|
||||
remote_ts = 192.168.0.150[tcp/http]
|
||||
priority = 1
|
||||
|
||||
mode = pass
|
||||
start_action = trap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
carol::swanctl --terminate --ike home
|
||||
dave::swanctl --terminate --ike home
|
||||
carol::service charon stop 2> /dev/null
|
||||
dave::service charon stop 2> /dev/null
|
||||
moon::service charon stop 2> /dev/null
|
||||
winnetou::ip route del 10.1.0.0/16 via 192.168.0.1
|
||||
carol::ip route del 10.1.0.0/16 via 192.168.0.1
|
||||
dave::ip route del 10.1.0.0/16 via 192.168.0.1
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
winnetou::ip route add 10.1.0.0/16 via 192.168.0.1
|
||||
carol::ip route add 10.1.0.0/16 via 192.168.0.1
|
||||
dave::ip route add 10.1.0.0/16 via 192.168.0.1
|
||||
moon::service charon start 2> /dev/null
|
||||
carol::service charon start 2> /dev/null
|
||||
dave::service charon start 2> /dev/null
|
||||
moon::expect-connection rw
|
||||
carol::expect-connection home
|
||||
carol::swanctl --initiate --child home 2> /dev/null
|
||||
dave::expect-connection home
|
||||
dave::swanctl --initiate --child home 2> /dev/null
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# This configuration file provides information on the
|
||||
# guest instances used for this test
|
||||
|
||||
# All guest instances that are required for this test
|
||||
#
|
||||
VIRTHOSTS="alice venus moon carol winnetou dave"
|
||||
|
||||
# Corresponding block diagram
|
||||
#
|
||||
DIAGRAM="a-v-m-c-w-d.png"
|
||||
|
||||
# Guest instances on which tcpdump is to be started
|
||||
#
|
||||
TCPDUMPHOSTS="moon"
|
||||
|
||||
# Guest instances on which IPsec is started
|
||||
# Used for IPsec logging purposes
|
||||
#
|
||||
IPSECHOSTS="moon carol dave"
|
||||
|
||||
# charon controlled by swanctl
|
||||
#
|
||||
SWANCTL=1
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
A connection between the subnets behind the gateways <b>moon</b> and <b>sun</b> is set up
|
||||
via the gateway <b>carol</b>.
|
||||
The authentication is based on <b>X.509 certificates</b>. Upon the successful
|
||||
establishment of the IPsec tunnels, the updown script automatically
|
||||
inserts iptables-based firewall rules that let pass the tunneled traffic.
|
||||
In order to test tunnels and firewall, client <b>alice</b> behind gateway <b>moon</b>
|
||||
pings client <b>bob</b> located behind gateway <b>sun</b>.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
moon::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=500 [email protected] initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.2.0.0/16]::YES
|
||||
sun:: swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=500 local-id=sun.strongswan.org remote-host=192.168.0.100 remote-port=500 [email protected].*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.2.0.0/16] remote-ts=\[10.1.0.0/16]::YES
|
||||
alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
|
||||
sun::tcpdump::IP carol.strongswan.org > sun.strongswan.org: ESP::YES
|
||||
sun::tcpdump::IP sun.strongswan.org > carol.strongswan.org: ESP::YES
|
||||
@@ -0,0 +1,14 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
swanctl {
|
||||
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||
}
|
||||
|
||||
charon {
|
||||
load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints pubkey gmp random nonce curl kernel-netlink socket-default updown vici
|
||||
|
||||
start-scripts {
|
||||
creds = /usr/local/sbin/swanctl --load-creds
|
||||
conns = /usr/local/sbin/swanctl --load-conns
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
connections {
|
||||
|
||||
gw-moon {
|
||||
local {
|
||||
auth = pubkey
|
||||
certs = carolCert.pem
|
||||
id = [email protected]
|
||||
}
|
||||
remote {
|
||||
auth = pubkey
|
||||
id = moon.strongswan.org
|
||||
}
|
||||
children {
|
||||
net-moon {
|
||||
local_ts = 10.2.0.0/16
|
||||
remote_ts = 10.1.0.0/16
|
||||
|
||||
updown = /usr/local/libexec/ipsec/_updown iptables
|
||||
esp_proposals = aes128gcm128-modp3072
|
||||
}
|
||||
}
|
||||
version = 2
|
||||
mobike = no
|
||||
proposals = aes128-sha256-modp3072
|
||||
}
|
||||
gw-sun {
|
||||
local {
|
||||
auth = pubkey
|
||||
certs = carolCert.pem
|
||||
id = [email protected]
|
||||
}
|
||||
remote {
|
||||
auth = pubkey
|
||||
id = sun.strongswan.org
|
||||
}
|
||||
children {
|
||||
net-sun {
|
||||
local_ts = 10.1.0.0/16
|
||||
remote_ts = 10.2.0.0/16
|
||||
|
||||
updown = /usr/local/libexec/ipsec/_updown iptables
|
||||
esp_proposals = aes128gcm128-modp3072
|
||||
}
|
||||
}
|
||||
version = 2
|
||||
mobike = no
|
||||
proposals = aes128-sha256-modp3072
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
swanctl {
|
||||
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||
}
|
||||
|
||||
charon {
|
||||
load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints pubkey gmp random nonce curl kernel-netlink socket-default updown vici
|
||||
|
||||
start-scripts {
|
||||
creds = /usr/local/sbin/swanctl --load-creds
|
||||
conns = /usr/local/sbin/swanctl --load-conns
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
connections {
|
||||
|
||||
gw-gw {
|
||||
remote_addrs = 192.168.0.100
|
||||
|
||||
local {
|
||||
auth = pubkey
|
||||
certs = moonCert.pem
|
||||
id = moon.strongswan.org
|
||||
}
|
||||
remote {
|
||||
auth = pubkey
|
||||
id = [email protected]
|
||||
}
|
||||
children {
|
||||
net-net {
|
||||
local_ts = 10.1.0.0/16
|
||||
remote_ts = 10.2.0.0/16
|
||||
|
||||
updown = /usr/local/libexec/ipsec/_updown iptables
|
||||
esp_proposals = aes128gcm128-modp3072
|
||||
}
|
||||
}
|
||||
version = 2
|
||||
mobike = no
|
||||
proposals = aes128-sha256-modp3072
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
swanctl {
|
||||
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||
}
|
||||
|
||||
charon {
|
||||
load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints pubkey gmp random nonce curl kernel-netlink socket-default updown vici
|
||||
|
||||
start-scripts {
|
||||
creds = /usr/local/sbin/swanctl --load-creds
|
||||
conns = /usr/local/sbin/swanctl --load-conns
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
connections {
|
||||
|
||||
gw-gw {
|
||||
remote_addrs = 192.168.0.100
|
||||
|
||||
local {
|
||||
auth = pubkey
|
||||
certs = sunCert.pem
|
||||
id = sun.strongswan.org
|
||||
}
|
||||
remote {
|
||||
auth = pubkey
|
||||
id = [email protected]
|
||||
}
|
||||
children {
|
||||
net-net {
|
||||
local_ts = 10.2.0.0/16
|
||||
remote_ts = 10.1.0.0/16
|
||||
|
||||
updown = /usr/local/libexec/ipsec/_updown iptables
|
||||
esp_proposals = aes128gcm128-modp3072
|
||||
}
|
||||
}
|
||||
version = 2
|
||||
mobike = no
|
||||
proposals = aes128-sha256-modp3072
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
moon::swanctl --terminate --ike gw-gw 2> /dev/null
|
||||
sun::swanctl --terminate --ike gw-gw 2> /dev/null
|
||||
moon::service charon stop 2> /dev/null
|
||||
sun::service charon stop 2> /dev/null
|
||||
carol::service charon stop 2> /dev/null
|
||||
moon::iptables-restore < /etc/iptables.flush
|
||||
sun::iptables-restore < /etc/iptables.flush
|
||||
carol::iptables-restore < /etc/iptables.flush
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
moon::iptables-restore < /etc/iptables.rules
|
||||
sun::iptables-restore < /etc/iptables.rules
|
||||
carol::iptables-restore < /etc/iptables.rules
|
||||
moon::service charon start 2> /dev/null
|
||||
sun::service charon start 2> /dev/null
|
||||
carol::service charon start 2> /dev/null
|
||||
carol::expect-connection gw-moon
|
||||
carol::expect-connection gw-sun
|
||||
moon::expect-connection gw-gw
|
||||
moon::swanctl --initiate --child net-net 2> /dev/null
|
||||
sun::expect-connection gw-gw
|
||||
sun::swanctl --initiate --child net-net 2> /dev/null
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# This configuration file provides information on the
|
||||
# guest instances used for this test
|
||||
|
||||
# All guest instances that are required for this test
|
||||
#
|
||||
VIRTHOSTS="alice moon carol winnetou sun bob"
|
||||
|
||||
# Corresponding block diagram
|
||||
#
|
||||
DIAGRAM="a-m-c-w-s-b-med.png"
|
||||
|
||||
# Guest instances on which tcpdump is to be started
|
||||
#
|
||||
TCPDUMPHOSTS="sun"
|
||||
|
||||
# Guest instances on which IPsec is started
|
||||
# Used for IPsec logging purposes
|
||||
#
|
||||
IPSECHOSTS="moon sun carol"
|
||||
|
||||
# charon controlled by swanctl
|
||||
#
|
||||
SWANCTL=1
|
||||
Reference in New Issue
Block a user