Merge branch 'kernel-policies'

This commit is contained in:
Andreas Steffen
2016-04-11 10:19:21 +02:00
56 changed files with 2562 additions and 1650 deletions
+21 -19
View File
@@ -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,
+40 -40
View File
@@ -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);
+39 -48
View File
@@ -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
View File
@@ -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,
+20 -17
View File
@@ -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"));
+52 -45
View File
@@ -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;
}
+62 -37
View File
@@ -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_ @}*/
+26 -37
View File
@@ -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;
}
+46 -35
View File
@@ -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_ @}*/
+25 -43
View File
@@ -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,
+39 -112
View File
@@ -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
View File
@@ -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);
};
/**
+17 -9
View File
@@ -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**)&current_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;
}
+19 -17
View File
@@ -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);
+45 -43
View File
@@ -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));
+12 -8
View File
@@ -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();
+39 -11
View File
@@ -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);
+65 -55
View File
@@ -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);
+20 -16
View File
@@ -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));
+4 -4
View File
@@ -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);
+139 -131
View File
@@ -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)
+14 -1
View File
@@ -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
View File
@@ -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)
+72 -38
View File
@@ -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);
}
+13
View File
@@ -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;
+10
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+25
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+12
View File
@@ -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
+25
View File
@@ -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